[WEB-5602] feat: new design system (#8220)

* chore: init tailwind v4

* chore: update all configs

* chore: add source to parse monorepo packages

* chore: combine all css files

* feat: added extended colors

* chore: update typography

* chore: update extended color var names

* refactor: remove initial spacing variable and update dark mode selector

* chore: update css files

* chore: update animations

* chore: remove spacing tokens

* fix: external css files

* chore: update tailwind-merge version

* chore: update font family

* chore: added brief agents.md and story for new design system

* chore: enhance design system documentation with rare exceptions for visual separation

* chore: add fontsource package for typography

* chore: material symbols font added

* chore: update shadow default

* chore: add stroke and outline theme vars

* chore: update ring and fill colors

* chore: overwrite tailwind typography tokens

* chore: add high contrast mode tokens

* chore: update scrollbar colors

* chore: backward compatibility for buttons and placeholders

* chore: add priority colors

* chore: update urgent priority color

* chore: update plan colors

* chore: add missing utility class

* chore: update height and padding classes

* chore: update label colors

* chore: add missing utlity

* chore: add typography plugin to space app

* chore: replace existing classNames with new design system tokens #8244 (#8278)

* chore: update border colors

* chore: update all borders

* chore: update text colors

* chore: update css variables

* chore: update font sizes and weights

* chore: update bg colors

* chore: sync changes

* fix: uncomment spacing-1200 variable in variables.css

* chore: update primary colors

* refactor: updated border to border-subtle

* refactor: update various components and improve UI consistency across the application

* updated classnames

* updated classnames

* refactor: update color-related class names to use new design system variables for consistency

* chore: default automations

* chore: update text sizes

* chore: home and power k

* chore: home and power k

* chore: replace ui package button components

* chore: update text sizes

* chore: updated issue identifier (#8275)

* refactor: top navigation and sidebar design token (#8276)

* chore: update all button components (#8277)

* chore: new button component

* chore: update existing buttons

* chore: overwrite tailwind typography tokens

* fix: twMerge config + fixed cn instances

* refactor: toast design token updated (#8279)

* chore: update existing buttons

* chore: tooltip design token updatged (#8280)

* chore: moved cn utility to propel (#8281)

* chore: update space app UI (#8285)

* chore; update space app filters component

* fix: button whitespace wrap

* chore: space app votes

* chore: update dropdown components

* refactor: auth, onboarding, sidebar, and common component design token migration (#8291)

* chore: checkbox component design token updated

* chore: indicator and oauth component design token updated

* chore: sidebar design token updated

* chore: auth and onboarding design token updated

* chore: update divider color

* style: update background colors and hover effects across list components

* fix: tailwind merge

* refactor: toggle switch design token migration and header utility classname added (#8295)

* chore: toggle component design token updated

* chore: h-header utility class added

* chore: updated color tokens for work item detail page (#8296)

* chore: update react-day-picker UI

* refactor: update button sizes and styles in filters components

* refactor: breadcrumbs design token updated (#8297)

* chore: update priority icon colors

* refactor: updated layout variables

* chore: update plan card primary CTA

* Chore update editor design system (#8299)

* refactor: update styles for callout, color selector, logo selector, and image uploader

* refactor:fix image

* chore: update settings UI

* chore: updated notifications color and size tokens (#8302)

* chore: update sm button border radius

* fix: logo renderer

* chore: icon button component

* chore: remove deprecated classes

* chore: remove deprecated classes

* chore: update editor list spacing

* fix: icon button size

* chore: improvements (#8309)

* chore: update cycles and modules pages

* refactor: update background styles across various components to use new design system colors

* fix: button type errors

* chore: update modals design system (#8310)

* refactor: callout bg

* refactor: code  bg

* refactor: modal size and variant

---------

Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>

* chore: update next-themes

* design: update billing and plans component styles and remove unused utility functions (#8313)

* refactor: empty state design token migration and improvements (#8315)

* fix: profile page

* refactor: tabs design token updated (#8316)

* chore: updated buttons and tokens for work items (#8317)

* fix: adjust trial button spacing in checkout modal

* chore: update add button hover state

* fix: type error (#8318)

* fix: type error

* chore: code refactor

* refactor: update button sizes and background styles in rich filters components

* refactor: update editor bg

* refactor: enhance Gantt chart sidebar functionality and styling

- Removed unused  prop from .
- Updated  to include new props for better block management and scrolling behavior.
- Improved auto-scroll functionality for Gantt chart items.
- Adjusted styles in  component for consistent design.

* regression: gantt design

* chore: new badge component

* fix: favorite star

* chore: update backgroung, typography and button sizes across workspace settings general and members pages

* fix: header button sizes

* fix: emoji icon logo (#8323)

* more fixes

* chore: update settings sidebar

* refactor: avatar component

* chore: updated work item detail sidebar (#8327)

* refactor: update link preview

* fix: work item property dropdowns

* fix: dropdown buttons border radius

* chore: update power k translation

* chore: updated profile activity design (#8328)

* chore: update settings pages

* chore: update work item sidebar alignments (#8330)

* refactor: admin design system

* chore: update page header

---------

Co-authored-by: Jayash Tripathy <76092296+JayashTripathy@users.noreply.github.com>
Co-authored-by: VipinDevelops <vipinchaudhary1809@gmail.com>
Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: gakshita <akshitagoyal1516@gmail.com>
Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>

* fix: formatting

* reexport types

* fix: lint error

---------

Co-authored-by: Jayash Tripathy <76092296+JayashTripathy@users.noreply.github.com>
Co-authored-by: VipinDevelops <vipinchaudhary1809@gmail.com>
Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: gakshita <akshitagoyal1516@gmail.com>
Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>
This commit is contained in:
Aaryan Khandelwal 2025-12-12 20:50:14 +05:30 committed by GitHub
parent d86418aad8
commit 22339b9786
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1342 changed files with 14227 additions and 15119 deletions

View file

@ -73,7 +73,7 @@ export function AuthConfirmPasswordInput({
onBlur={handleBlur}
autoComplete="on"
/>
{confirmPassword && passwordsMatch && <p className="text-sm text-green-500">Passwords match</p>}
{confirmPassword && passwordsMatch && <p className="text-13 text-green-500">Passwords match</p>}
</div>
);
}

View file

@ -27,7 +27,7 @@ export function AuthForgotPassword({
onClick={handleClick}
disabled={disabled}
className={cn(
"text-sm text-custom-primary-100 hover:text-custom-primary-200 transition-colors duration-200",
"text-13 text-accent-primary hover:text-accent-secondary transition-colors duration-200",
{
"opacity-50 cursor-not-allowed": disabled,
"cursor-pointer": !disabled,

View file

@ -190,11 +190,11 @@ export function AuthForm({
{/* Alternate Mode Button */}
{onModeChange && (
<div className="text-center">
<span className="text-sm text-custom-text-300">{getAlternateModeText()}</span>
<span className="text-13 text-tertiary">{getAlternateModeText()}</span>
<button
type="button"
onClick={handleModeChange}
className="ml-1 text-sm text-custom-primary-100 hover:text-custom-primary-200 transition-colors duration-200"
className="ml-1 text-13 text-accent-primary hover:text-accent-secondary transition-colors duration-200"
disabled={disabled}
>
{getAlternateModeButtonText()}

View file

@ -31,18 +31,16 @@ export function AuthInput({
return (
<div className={cn(baseContainerClassName)}>
{label && (
<label htmlFor={id} className={cn("text-sm font-semibold text-custom-text-300")}>
<label htmlFor={id} className={cn("text-13 font-semibold text-tertiary")}>
{label}
</label>
)}
<div
className={cn("relative flex items-center rounded-md border border-custom-border-300 py-2 px-3 transition-all")}
>
<div className={cn("relative flex items-center rounded-md border border-strong py-2 px-3 transition-all")}>
<Input
{...props}
type={inputType}
className={cn(
"rounded-md disable-autofill-style h-6 w-full placeholder:text-base placeholder:text-custom-text-400 p-0 border-none",
"rounded-md disable-autofill-style h-6 w-full placeholder:text-14 placeholder:text-placeholder p-0 border-none",
{
"border-red-500": error,
},
@ -60,7 +58,7 @@ export function AuthInput({
)}
</div>
{error && <p className={cn("text-sm text-red-500", errorClassName)}>{error}</p>}
{error && <p className={cn("text-13 text-red-500", errorClassName)}>{error}</p>}
</div>
);
}

View file

@ -4,8 +4,8 @@ import { Tooltip } from "@plane/propel/tooltip";
// helpers
import { cn } from "../utils";
// types
import type { TAvatarSize } from "./avatar";
import { getSizeInfo, isAValidNumber } from "./avatar";
import type { TAvatarSize } from "./helper";
import { getSizeInfo, isAValidNumber } from "./helper";
type Props = {
/**
@ -60,7 +60,7 @@ export function AvatarGroup(props: Props) {
return (
<div className={cn("flex", sizeInfo.spacing)}>
{avatarsWithUpdatedProps.map((avatar, index) => (
<div key={index} className="rounded-full ring-1 ring-custom-background-100">
<div key={index} className="rounded-full border border-subtle-1">
{avatar}
</div>
))}
@ -68,7 +68,7 @@ export function AvatarGroup(props: Props) {
<Tooltip tooltipContent={`${totalAvatars} total`} disabled={!showTooltip}>
<div
className={cn(
"grid place-items-center rounded-full bg-custom-primary-10 text-[9px] text-custom-primary-100 ring-1 ring-custom-background-100",
"grid place-items-center rounded-full bg-accent-subtle text-9 text-accent-primary border border-subtle-1",
{
[sizeInfo.avatarSize]: !isAValidNumber(size),
}

View file

@ -1,10 +1,9 @@
import React from "react";
// ui
import { Tooltip } from "@plane/propel/tooltip";
// helpers
import { cn } from "../utils";
export type TAvatarSize = "sm" | "md" | "base" | "lg" | number;
import type { TAvatarSize } from "./helper";
import { getBorderRadius, getSizeInfo, isAValidNumber } from "./helper";
type Props = {
/**
@ -50,69 +49,6 @@ type Props = {
className?: string;
};
/**
* Get the size details based on the size prop
* @param size The size of the avatar
* @returns The size details
*/
export const getSizeInfo = (size: TAvatarSize) => {
switch (size) {
case "sm":
return {
avatarSize: "h-4 w-4",
fontSize: "text-xs",
spacing: "-space-x-1",
};
case "md":
return {
avatarSize: "h-5 w-5",
fontSize: "text-xs",
spacing: "-space-x-1",
};
case "base":
return {
avatarSize: "h-6 w-6",
fontSize: "text-sm",
spacing: "-space-x-1.5",
};
case "lg":
return {
avatarSize: "h-7 w-7",
fontSize: "text-sm",
spacing: "-space-x-1.5",
};
default:
return {
avatarSize: "h-5 w-5",
fontSize: "text-xs",
spacing: "-space-x-1",
};
}
};
/**
* Get the border radius based on the shape prop
* @param shape The shape of the avatar
* @returns The border radius
*/
export const getBorderRadius = (shape: "circle" | "square") => {
switch (shape) {
case "circle":
return "rounded-full";
case "square":
return "rounded";
default:
return "rounded-full";
}
};
/**
* Check if the value is a valid number
* @param value The value to check
* @returns Whether the value is a valid number or not
*/
export const isAValidNumber = (value: any) => typeof value === "number" && !isNaN(value);
export function Avatar(props: Props) {
const {
name,

View file

@ -0,0 +1,64 @@
export type TAvatarSize = "sm" | "md" | "base" | "lg" | number;
/**
* Get the size details based on the size prop
* @param size The size of the avatar
* @returns The size details
*/
export const getSizeInfo = (size: TAvatarSize) => {
switch (size) {
case "sm":
return {
avatarSize: "h-4 w-4",
fontSize: "text-11",
spacing: "-space-x-1",
};
case "md":
return {
avatarSize: "h-5 w-5",
fontSize: "text-11",
spacing: "-space-x-1",
};
case "base":
return {
avatarSize: "h-6 w-6",
fontSize: "text-13",
spacing: "-space-x-1.5",
};
case "lg":
return {
avatarSize: "h-7 w-7",
fontSize: "text-13",
spacing: "-space-x-1.5",
};
default:
return {
avatarSize: "h-5 w-5",
fontSize: "text-11",
spacing: "-space-x-1",
};
}
};
/**
* Get the border radius based on the shape prop
* @param shape The shape of the avatar
* @returns The border radius
*/
export const getBorderRadius = (shape: "circle" | "square") => {
switch (shape) {
case "circle":
return "rounded-full";
case "square":
return "rounded-sm";
default:
return "rounded-full";
}
};
/**
* Check if the value is a valid number
* @param value The value to check
* @returns Whether the value is a valid number or not
*/
export const isAValidNumber = (value: unknown) => typeof value === "number" && !isNaN(value);

View file

@ -27,10 +27,10 @@ export interface IBadgeStyling {
// TODO: convert them to objects instead of enums
enum badgeSizeStyling {
sm = `px-2.5 py-1 font-medium text-xs rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
md = `px-4 py-1.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
lg = `px-4 py-2 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
xl = `px-5 py-3 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
sm = `px-2.5 py-1 font-medium text-11 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
md = `px-4 py-1.5 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
lg = `px-4 py-2 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
xl = `px-5 py-3 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
}
// TODO: convert them to objects instead of enums
@ -44,39 +44,39 @@ enum badgeIconStyling {
export const badgeStyling: IBadgeStyling = {
primary: {
default: `text-white bg-custom-primary-100`,
hover: `hover:bg-custom-primary-200`,
default: `text-on-color bg-accent-primary`,
hover: `hover:bg-accent-primary/80`,
disabled: `cursor-not-allowed !bg-custom-primary-60 hover:bg-custom-primary-60`,
},
"accent-primary": {
default: `bg-custom-primary-10 text-custom-primary-100`,
hover: `hover:bg-custom-primary-20 hover:text-custom-primary-200`,
disabled: `cursor-not-allowed !text-custom-primary-60`,
default: `bg-accent-subtle text-accent-primary`,
hover: `hover:bg-custom-primary-20 hover:text-accent-secondary`,
disabled: `cursor-not-allowed !text-accent-primary/60`,
},
"outline-primary": {
default: `text-custom-primary-100 bg-custom-background-100 border border-custom-primary-100`,
hover: `hover:border-custom-primary-80 hover:bg-custom-primary-10`,
disabled: `cursor-not-allowed !text-custom-primary-60 !border-custom-primary-60 `,
default: `text-accent-primary bg-surface-1 border border-accent-strong`,
hover: `hover:border-accent-strong-80 hover:bg-accent-subtle`,
disabled: `cursor-not-allowed !text-accent-primary/60 !border-accent-strong-60 `,
},
neutral: {
default: `text-custom-background-100 bg-custom-text-100 border border-custom-border-200`,
hover: `hover:bg-custom-text-200`,
disabled: `cursor-not-allowed bg-custom-border-200 !text-custom-text-400`,
default: `text-custom-background-100 bg-layer-1 border border-subtle`,
hover: `hover:bg-layer-1`,
disabled: `cursor-not-allowed bg-subtle-1 !text-placeholder`,
},
"accent-neutral": {
default: `text-custom-text-200 bg-custom-background-80`,
hover: `hover:bg-custom-border-200 hover:text-custom-text-100`,
disabled: `cursor-not-allowed !text-custom-text-400`,
default: `text-secondary bg-layer-1`,
hover: `hover:bg-subtle-1 hover:text-primary`,
disabled: `cursor-not-allowed !text-placeholder`,
},
"outline-neutral": {
default: `text-custom-text-200 bg-custom-background-100 border border-custom-border-200`,
hover: `hover:text-custom-text-100 hover:bg-custom-border-200`,
disabled: `cursor-not-allowed !text-custom-text-400`,
default: `text-secondary bg-surface-1 border border-subtle`,
hover: `hover:text-primary hover:bg-subtle-1`,
disabled: `cursor-not-allowed !text-placeholder`,
},
success: {
default: `text-white bg-green-500`,
default: `text-on-color bg-green-500`,
hover: `hover:bg-green-600`,
disabled: `cursor-not-allowed !bg-green-300`,
},
@ -86,13 +86,13 @@ export const badgeStyling: IBadgeStyling = {
disabled: `cursor-not-allowed !text-green-300`,
},
"outline-success": {
default: `text-green-500 bg-custom-background-100 border border-green-500`,
default: `text-green-500 bg-surface-1 border border-green-500`,
hover: `hover:text-green-600 hover:bg-green-50`,
disabled: `cursor-not-allowed !text-green-300 border-green-300`,
},
warning: {
default: `text-white bg-amber-500`,
default: `text-on-color bg-amber-500`,
hover: `hover:bg-amber-600`,
disabled: `cursor-not-allowed !bg-amber-300`,
},
@ -102,13 +102,13 @@ export const badgeStyling: IBadgeStyling = {
disabled: `cursor-not-allowed !text-amber-300`,
},
"outline-warning": {
default: `text-amber-500 bg-custom-background-100 border border-amber-500`,
default: `text-amber-500 bg-surface-1 border border-amber-500`,
hover: `hover:text-amber-600 hover:bg-amber-50`,
disabled: `cursor-not-allowed !text-amber-300 border-amber-300`,
},
destructive: {
default: `text-white bg-red-500`,
default: `text-on-color bg-red-500`,
hover: `hover:bg-red-600`,
disabled: `cursor-not-allowed !bg-red-300`,
},
@ -118,7 +118,7 @@ export const badgeStyling: IBadgeStyling = {
disabled: `cursor-not-allowed !text-red-300`,
},
"outline-destructive": {
default: `text-red-500 bg-custom-background-100 border border-red-500`,
default: `text-red-500 bg-surface-1 border border-red-500`,
hover: `hover:text-red-600 hover:bg-red-50`,
disabled: `cursor-not-allowed !text-red-300 border-red-300`,
},

View file

@ -1 +0,0 @@
export * from "./subscription";

View file

@ -1,209 +0,0 @@
// plane imports
import { EProductSubscriptionEnum } from "@plane/types";
import { cn } from "@plane/utils";
export const getSubscriptionTextColor = (
planVariant: EProductSubscriptionEnum,
shade: "200" | "400" = "200"
): string => {
const subscriptionColors = {
[EProductSubscriptionEnum.ONE]: {
"200": "text-custom-subscription-one-200",
"400": "text-custom-subscription-one-400",
},
[EProductSubscriptionEnum.PRO]: {
"200": "text-custom-subscription-pro-200",
"400": "text-custom-subscription-pro-400",
},
[EProductSubscriptionEnum.BUSINESS]: {
"200": "text-custom-subscription-business-200",
"400": "text-custom-subscription-business-400",
},
[EProductSubscriptionEnum.ENTERPRISE]: {
"200": "text-custom-subscription-enterprise-200",
"400": "text-custom-subscription-enterprise-400",
},
[EProductSubscriptionEnum.FREE]: {
"200": "text-custom-subscription-free-200",
"400": "text-custom-subscription-free-400",
},
};
return subscriptionColors[planVariant]?.[shade] ?? subscriptionColors[EProductSubscriptionEnum.FREE][shade];
};
export const getSubscriptionBackgroundColor = (
planVariant: EProductSubscriptionEnum,
shade: "50" | "100" | "200" | "400" = "100"
): string => {
const subscriptionColors = {
[EProductSubscriptionEnum.ONE]: {
"50": "bg-custom-subscription-one-200/10",
"100": "bg-custom-subscription-one-200/20",
"200": "bg-custom-subscription-one-200",
"400": "bg-custom-subscription-one-400",
},
[EProductSubscriptionEnum.PRO]: {
"50": "bg-custom-subscription-pro-200/10",
"100": "bg-custom-subscription-pro-200/20",
"200": "bg-custom-subscription-pro-200",
"400": "bg-custom-subscription-pro-400",
},
[EProductSubscriptionEnum.BUSINESS]: {
"50": "bg-custom-subscription-business-200/10",
"100": "bg-custom-subscription-business-200/20",
"200": "bg-custom-subscription-business-200",
"400": "bg-custom-subscription-business-400",
},
[EProductSubscriptionEnum.ENTERPRISE]: {
"50": "bg-custom-subscription-enterprise-200/10",
"100": "bg-custom-subscription-enterprise-200/20",
"200": "bg-custom-subscription-enterprise-200",
"400": "bg-custom-subscription-enterprise-400",
},
[EProductSubscriptionEnum.FREE]: {
"50": "bg-custom-subscription-free-200/10",
"100": "bg-custom-subscription-free-200/20",
"200": "bg-custom-subscription-free-200",
"400": "bg-custom-subscription-free-400",
},
};
return subscriptionColors[planVariant]?.[shade] ?? subscriptionColors[EProductSubscriptionEnum.FREE][shade];
};
export const getSubscriptionBorderColor = (
planVariant: EProductSubscriptionEnum,
shade: "200" | "400" = "200"
): string => {
const subscriptionColors = {
[EProductSubscriptionEnum.ONE]: {
"200": "border-custom-subscription-one-200",
"400": "border-custom-subscription-one-400",
},
[EProductSubscriptionEnum.PRO]: {
"200": "border-custom-subscription-pro-200",
"400": "border-custom-subscription-pro-400",
},
[EProductSubscriptionEnum.BUSINESS]: {
"200": "border-custom-subscription-business-200",
"400": "border-custom-subscription-business-400",
},
[EProductSubscriptionEnum.ENTERPRISE]: {
"200": "border-custom-subscription-enterprise-200",
"400": "border-custom-subscription-enterprise-400",
},
[EProductSubscriptionEnum.FREE]: {
"200": "border-custom-subscription-free-200",
"400": "border-custom-subscription-free-400",
},
default: "border-custom-subscription-free-400",
};
return subscriptionColors[planVariant]?.[shade] ?? subscriptionColors.default;
};
export const getUpgradeButtonStyle = (
planVariant: EProductSubscriptionEnum,
isDisabled: boolean
): string | undefined => {
const baseClassNames = "border bg-custom-background-100";
const hoverClassNames = !isDisabled ? "hover:text-white hover:bg-gradient-to-br" : "";
const disabledClassNames = isDisabled ? "opacity-70 cursor-not-allowed" : "";
const COMMON_CLASSNAME = cn(baseClassNames, hoverClassNames, disabledClassNames);
switch (planVariant) {
case EProductSubscriptionEnum.ENTERPRISE:
return cn(
"text-custom-subscription-enterprise-200 from-custom-subscription-enterprise-200 to-custom-subscription-enterprise-400",
getSubscriptionBorderColor(planVariant, "200"),
COMMON_CLASSNAME
);
case EProductSubscriptionEnum.BUSINESS:
return cn(
"text-custom-subscription-business-200 from-custom-subscription-business-200 to-custom-subscription-business-400",
getSubscriptionBorderColor(planVariant, "200"),
COMMON_CLASSNAME
);
case EProductSubscriptionEnum.PRO:
return cn(
"text-custom-subscription-pro-200 from-custom-subscription-pro-200 to-custom-subscription-pro-400",
getSubscriptionBorderColor(planVariant, "200"),
COMMON_CLASSNAME
);
case EProductSubscriptionEnum.ONE:
return cn(
"text-custom-subscription-one-200 from-custom-subscription-one-200 to-custom-subscription-one-400",
getSubscriptionBorderColor(planVariant, "200"),
COMMON_CLASSNAME
);
case EProductSubscriptionEnum.FREE:
default:
return cn(
"text-custom-subscription-free-200 from-custom-subscription-free-200 to-custom-subscription-free-400",
getSubscriptionBorderColor(planVariant, "200"),
COMMON_CLASSNAME
);
}
};
export const getUpgradeCardVariantStyle = (planVariant: EProductSubscriptionEnum): string | undefined => {
const COMMON_CLASSNAME = cn("bg-gradient-to-b from-0% to-40% border border-custom-border-200 rounded-xl");
switch (planVariant) {
case EProductSubscriptionEnum.ENTERPRISE:
return cn("from-custom-subscription-enterprise-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.BUSINESS:
return cn("from-custom-subscription-business-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.PRO:
return cn("from-custom-subscription-pro-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.ONE:
return cn("from-custom-subscription-one-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.FREE:
default:
return cn("from-custom-subscription-free-200/[0.14] to-transparent", COMMON_CLASSNAME);
}
};
export const getSuccessModalVariantStyle = (planVariant: EProductSubscriptionEnum) => {
const COMMON_CLASSNAME = cn("bg-gradient-to-b from-0% to-30% rounded-2xl");
switch (planVariant) {
case EProductSubscriptionEnum.ENTERPRISE:
return cn("from-custom-subscription-enterprise-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.BUSINESS:
return cn("from-custom-subscription-business-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.PRO:
return cn("from-custom-subscription-pro-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.ONE:
return cn("from-custom-subscription-one-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.FREE:
default:
return cn("from-custom-subscription-free-200/[0.14] to-transparent", COMMON_CLASSNAME);
}
};
export const getBillingAndPlansCardVariantStyle = (planVariant: EProductSubscriptionEnum) => {
const COMMON_CLASSNAME = cn("bg-gradient-to-b from-0% to-50%");
switch (planVariant) {
case EProductSubscriptionEnum.ENTERPRISE:
return cn("from-custom-subscription-enterprise-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.BUSINESS:
return cn("from-custom-subscription-business-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.PRO:
return cn("from-custom-subscription-pro-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.ONE:
return cn("from-custom-subscription-one-200/[0.14] to-transparent", COMMON_CLASSNAME);
case EProductSubscriptionEnum.FREE:
default:
return cn("from-custom-subscription-free-200/[0.14] to-transparent", COMMON_CLASSNAME);
}
};
export const getSubscriptionTextAndBackgroundColor = (planVariant: EProductSubscriptionEnum) =>
cn(getSubscriptionTextColor(planVariant), getSubscriptionBackgroundColor(planVariant));
export const getDiscountPillStyle = (planVariant: EProductSubscriptionEnum): string =>
cn(getSubscriptionBackgroundColor(planVariant, "200"), "text-white");

View file

@ -25,7 +25,7 @@ function BreadcrumbBlock(props: TBreadcrumbBlockProps) {
return (
<>
<Breadcrumbs.ItemWrapper label={label} disableTooltip={disableTooltip}>
{icon && <div className="flex size-4 items-center justify-center overflow-hidden !text-[1rem]">{icon}</div>}
{icon && <div className="flex size-4 items-center justify-center overflow-hidden !text-16">{icon}</div>}
{label && <div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{label}</div>}
</Breadcrumbs.ItemWrapper>
</>

View file

@ -13,9 +13,9 @@ type BreadcrumbsProps = {
export function BreadcrumbItemLoader() {
return (
<div className="flex items-center gap-2 h-7 animate-pulse">
<div className="group h-full flex items-center gap-2 rounded px-2 py-1 text-sm font-medium">
<span className="h-full w-5 bg-custom-background-80 rounded" />
<span className="h-full w-16 bg-custom-background-80 rounded" />
<div className="group h-full flex items-center gap-2 rounded-sm px-2 py-1 text-13 font-medium">
<span className="h-full w-5 bg-layer-1 rounded-sm" />
<span className="h-full w-16 bg-layer-1 rounded-sm" />
</div>
</div>
);
@ -62,11 +62,11 @@ function Breadcrumbs({ className, children, onBack, isLoading = false }: Breadcr
<>
<div className="flex items-center gap-2.5 p-1">
{onBack && (
<span onClick={onBack} className="text-custom-text-200">
<span onClick={onBack} className="text-secondary">
...
</span>
)}
<ChevronRightIcon className="h-3.5 w-3.5 flex-shrink-0 text-custom-text-400" aria-hidden="true" />
<ChevronRightIcon className="h-3.5 w-3.5 flex-shrink-0 text-placeholder" aria-hidden="true" />
</div>
<div className="flex items-center gap-2.5 p-1">
{isLoading ? (
@ -141,10 +141,10 @@ function BreadcrumbSeparator(props: BreadcrumbSeparatorProps) {
const { className, containerClassName, iconClassName, showDivider = false } = props;
return (
<div className={cn("relative flex items-center justify-center h-full px-1.5 py-1", className)}>
{showDivider && <span className="absolute -left-0.5 top-0 h-full w-[1.8px] bg-custom-background-100" />}
{showDivider && <span className="absolute -left-0.5 top-0 h-full w-[1.8px] bg-surface-1" />}
<div
className={cn(
"flex items-center justify-center flex-shrink-0 rounded text-custom-text-400 transition-all",
"flex items-center justify-center flex-shrink-0 rounded-sm text-placeholder transition-all",
containerClassName
)}
>
@ -170,9 +170,9 @@ function BreadcrumbItemWrapper(props: BreadcrumbItemWrapperProps) {
<Tooltip tooltipContent={label} position="bottom" disabled={!label || label === "" || disableTooltip}>
<div
className={cn(
"group h-full flex items-center gap-2 rounded px-1.5 py-1 text-sm font-medium text-custom-text-300 cursor-default",
"group h-full flex items-center gap-2 rounded-sm px-1.5 py-1 text-13 font-medium text-tertiary cursor-default",
{
"hover:text-custom-text-100 hover:bg-custom-background-90 cursor-pointer": type === "link" && !isLast,
"hover:text-primary hover:bg-surface-2 cursor-pointer": type === "link" && !isLast,
},
className
)}

View file

@ -39,13 +39,13 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow
}
}}
className={cn(
"group h-full flex items-center gap-2 px-1.5 py-1 text-sm font-medium text-custom-text-300 cursor-pointer rounded rounded-r-none",
"group h-full flex items-center gap-2 px-1.5 py-1 text-13 font-medium text-tertiary cursor-pointer rounded-sm rounded-r-none",
{
"hover:bg-custom-background-80 hover:text-custom-text-100": !isLast,
"hover:bg-layer-1 hover:text-primary": !isLast,
}
)}
>
<div className="flex @4xl:hidden text-custom-text-300">...</div>
<div className="flex @4xl:hidden text-tertiary">...</div>
<div className="hidden @4xl:flex gap-2">
{selectedItemIcon && <Breadcrumbs.Icon>{selectedItemIcon}</Breadcrumbs.Icon>}
<Breadcrumbs.Label>{selectedItem?.title}</Breadcrumbs.Label>
@ -65,13 +65,13 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow
<>
<NavigationButton />
<Breadcrumbs.Separator
className={cn("rounded-r", {
"bg-custom-background-80": isOpen && !isLast,
"hover:bg-custom-background-80": !isLast,
className={cn("rounded-r-sm", {
"bg-layer-1": isOpen && !isLast,
"hover:bg-layer-1": !isLast,
})}
containerClassName="p-0"
iconClassName={cn("group-hover:rotate-90 hover:text-custom-text-100", {
"text-custom-text-100": isOpen,
iconClassName={cn("group-hover:rotate-90 hover:text-primary", {
"text-primary": isOpen,
"rotate-90": isOpen || isLast,
})}
showDivider={!isLast}
@ -79,11 +79,11 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow
</>
}
placement="bottom-start"
className="h-full rounded"
className="h-full rounded-sm"
customButtonClassName={cn(
"group flex items-center gap-0.5 rounded hover:bg-custom-background-90 outline-none cursor-pointer h-full rounded",
"group flex items-center gap-0.5 rounded-sm hover:bg-surface-2 outline-none cursor-pointer h-full rounded-sm",
{
"bg-custom-background-90": isOpen,
"bg-surface-2": isOpen,
}
)}
closeOnSelect
@ -108,7 +108,7 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow
className={cn(
"flex items-center gap-2",
{
"text-custom-text-400": item.disabled,
"text-placeholder": item.disabled,
},
item.className
)}
@ -119,8 +119,8 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow
<h5>{item.title}</h5>
{item.description && (
<p
className={cn("text-custom-text-300 whitespace-pre-line", {
"text-custom-text-400": item.disabled,
className={cn("text-tertiary whitespace-pre-line", {
"text-placeholder": item.disabled,
})}
>
{item.description}

View file

@ -61,13 +61,13 @@ export function BreadcrumbNavigationSearchDropdown(props: TBreadcrumbNavigationS
}
}}
className={cn(
"group h-full flex items-center gap-2 px-1.5 py-1 text-sm font-medium text-custom-text-300 cursor-pointer rounded rounded-r-none",
"group h-full flex items-center gap-2 px-1.5 py-1 text-13 font-medium text-tertiary cursor-pointer rounded-sm rounded-r-none",
{
"hover:bg-custom-background-80 hover:text-custom-text-100": !isLast,
"hover:bg-layer-1 hover:text-primary": !isLast,
}
)}
>
{shouldTruncate && <div className="flex @4xl:hidden text-custom-text-300">...</div>}
{shouldTruncate && <div className="flex @4xl:hidden text-tertiary">...</div>}
<div
className={cn("flex gap-2", {
"hidden @4xl:flex gap-2": shouldTruncate,
@ -79,13 +79,13 @@ export function BreadcrumbNavigationSearchDropdown(props: TBreadcrumbNavigationS
</button>
</Tooltip>
<Breadcrumbs.Separator
className={cn("rounded-r", {
"bg-custom-background-80": isDropdownOpen && !isLast,
"hover:bg-custom-background-80": !isLast,
className={cn("rounded-r-sm", {
"bg-layer-1": isDropdownOpen && !isLast,
"hover:bg-layer-1": !isLast,
})}
containerClassName="p-0"
iconClassName={cn("group-hover:rotate-90 hover:text-custom-text-100", {
"text-custom-text-100": isDropdownOpen,
iconClassName={cn("group-hover:rotate-90 hover:text-primary", {
"text-primary": isDropdownOpen,
"rotate-90": isDropdownOpen || isLast,
})}
showDivider={!isLast}
@ -93,11 +93,11 @@ export function BreadcrumbNavigationSearchDropdown(props: TBreadcrumbNavigationS
</>
}
disabled={navigationDisabled}
className="h-full rounded"
className="h-full rounded-sm"
customButtonClassName={cn(
"group flex items-center gap-0.5 rounded hover:bg-custom-background-90 outline-none cursor-pointer h-full rounded",
"group flex items-center gap-0.5 rounded-sm hover:bg-surface-2 outline-none cursor-pointer h-full rounded-sm",
{
"bg-custom-background-90": isDropdownOpen,
"bg-surface-2": isDropdownOpen,
}
)}
/>

View file

@ -23,10 +23,10 @@ export interface IButtonStyling {
}
enum buttonSizeStyling {
sm = `px-3 py-1.5 font-medium text-xs rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
md = `px-4 py-1.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
lg = `px-5 py-2 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
xl = `px-5 py-3.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
sm = `px-3 py-1.5 font-medium text-11 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
md = `px-4 py-1.5 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
lg = `px-5 py-2 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
xl = `px-5 py-3.5 font-medium text-13 rounded-sm flex items-center gap-1.5 whitespace-nowrap transition-all justify-center`,
}
enum buttonIconStyling {
@ -38,38 +38,38 @@ enum buttonIconStyling {
export const buttonStyling: IButtonStyling = {
primary: {
default: `text-white bg-custom-primary-100`,
hover: `hover:bg-custom-primary-200`,
pressed: `focus:text-custom-brand-40 focus:bg-custom-primary-200`,
default: `text-on-color bg-accent-primary`,
hover: `hover:bg-accent-primary/80`,
pressed: `focus:text-custom-brand-40 focus:bg-accent-primary/80`,
disabled: `cursor-not-allowed !bg-custom-primary-60 hover:bg-custom-primary-60`,
},
"accent-primary": {
default: `bg-custom-primary-100/20 text-custom-primary-100`,
hover: `hover:bg-custom-primary-100/10 hover:text-custom-primary-200`,
pressed: `focus:bg-custom-primary-100/10`,
disabled: `cursor-not-allowed !text-custom-primary-60`,
default: `bg-accent-primary/20 text-accent-primary`,
hover: `hover:bg-accent-primary/10 hover:text-accent-secondary`,
pressed: `focus:bg-accent-primary/10`,
disabled: `cursor-not-allowed !text-accent-primary/60`,
},
"outline-primary": {
default: `text-custom-primary-100 bg-transparent border border-custom-primary-100`,
hover: `hover:bg-custom-primary-100/20`,
pressed: `focus:text-custom-primary-100 focus:bg-custom-primary-100/30`,
disabled: `cursor-not-allowed !text-custom-primary-60 !border-custom-primary-60 `,
default: `text-accent-primary bg-transparent border border-accent-strong`,
hover: `hover:bg-accent-primary/20`,
pressed: `focus:text-accent-primary focus:bg-accent-primary/30`,
disabled: `cursor-not-allowed !text-accent-primary/60 !border-accent-strong-60 `,
},
"neutral-primary": {
default: `text-custom-text-200 bg-custom-background-100 border border-custom-border-200`,
hover: `hover:bg-custom-background-90`,
pressed: `focus:text-custom-text-300 focus:bg-custom-background-90`,
disabled: `cursor-not-allowed !text-custom-text-400`,
default: `text-secondary bg-surface-1 border border-subtle`,
hover: `hover:bg-surface-2`,
pressed: `focus:text-tertiary focus:bg-surface-2`,
disabled: `cursor-not-allowed !text-placeholder`,
},
"link-primary": {
default: `text-custom-primary-100 bg-custom-background-100`,
hover: `hover:text-custom-primary-200`,
pressed: `focus:text-custom-primary-80 `,
disabled: `cursor-not-allowed !text-custom-primary-60`,
default: `text-accent-primary bg-surface-1`,
hover: `hover:text-accent-secondary`,
pressed: `focus:text-accent-primary/80 `,
disabled: `cursor-not-allowed !text-accent-primary/60`,
},
danger: {
default: `text-white bg-red-500`,
default: `text-on-color bg-red-500`,
hover: ` hover:bg-red-600`,
pressed: `focus:text-red-200 focus:bg-red-600`,
disabled: `cursor-not-allowed !bg-red-300`,
@ -87,22 +87,22 @@ export const buttonStyling: IButtonStyling = {
disabled: `cursor-not-allowed !text-red-300 !border-red-300`,
},
"link-danger": {
default: `text-red-500 bg-custom-background-100`,
default: `text-red-500 bg-surface-1`,
hover: `hover:text-red-400`,
pressed: `focus:text-red-400`,
disabled: `cursor-not-allowed !text-red-300`,
},
"tertiary-danger": {
default: `text-red-500 bg-custom-background-100 border border-red-200`,
default: `text-red-500 bg-surface-1 border border-red-200`,
hover: `hover:bg-red-50 hover:border-red-300`,
pressed: `focus:text-red-400`,
disabled: `cursor-not-allowed !text-red-300`,
},
"link-neutral": {
default: `text-custom-text-300`,
hover: `hover:text-custom-text-200`,
pressed: `focus:text-custom-text-100`,
disabled: `cursor-not-allowed !text-custom-text-400`,
default: `text-tertiary`,
hover: `hover:text-secondary`,
pressed: `focus:text-primary`,
disabled: `cursor-not-allowed !text-placeholder`,
},
};

View file

@ -1,5 +1,4 @@
import { Switch } from "@headlessui/react";
import * as React from "react";
// helpers
import { cn } from "../utils";
@ -21,12 +20,14 @@ function ToggleSwitch(props: IToggleSwitchProps) {
disabled={disabled}
onChange={onChange}
className={cn(
"relative inline-flex flex-shrink-0 h-6 w-10 cursor-pointer rounded-full border border-custom-border-200 transition-colors duration-200 ease-in-out focus:outline-none bg-gray-700",
"relative inline-flex flex-shrink-0 h-6 w-10 cursor-pointer rounded-full border-0 transition-colors duration-200 ease-in-out focus:outline-none",
{
"h-4 w-6": size === "sm",
"h-5 w-8": size === "md",
"bg-custom-primary-100": value,
"cursor-not-allowed bg-custom-background-80": disabled,
"h-4 w-7": size === "sm",
"h-5 w-9": size === "md",
"bg-accent-primary": value && !disabled,
"bg-(--text-color-icon-placeholder)": !value && !disabled,
"cursor-not-allowed opacity-50 bg-accent-primary": value && disabled,
"cursor-not-allowed opacity-50 bg-(--text-color-icon-placeholder)": !value && disabled,
},
className
)}
@ -35,15 +36,14 @@ function ToggleSwitch(props: IToggleSwitchProps) {
<span
aria-hidden="true"
className={cn(
"inline-block self-center h-4 w-4 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
"inline-block self-center h-5 w-5 transform rounded-full bg-(--text-color-icon-on-color) ring-0 transition duration-200 ease-in-out",
{
"translate-x-5 bg-white": value,
"h-2 w-2": size === "sm",
"h-3 w-3": size === "md",
"translate-x-3": value && size === "sm",
"translate-x-4": value && size === "md",
"translate-x-0.5 bg-custom-background-90": !value,
"cursor-not-allowed bg-custom-background-90": disabled,
"h-3 w-3 translate-x-3.5": size === "sm" && value,
"h-3 w-3 translate-x-0.5": size === "sm" && !value,
"h-4 w-4 translate-x-4": size === "md" && value,
"h-4 w-4 translate-x-0.5": size === "md" && !value,
"translate-x-4": size === "lg" && value,
"translate-x-0.5": size === "lg" && !value,
}
)}
/>

View file

@ -18,8 +18,7 @@ export interface ICardProperties {
[key: string]: string;
}
const DEFAULT_STYLE =
"bg-custom-background-100 rounded-lg border-[0.5px] border-custom-border-200 w-full flex flex-col";
const DEFAULT_STYLE = "bg-surface-1 rounded-lg border-[0.5px] border-subtle w-full flex flex-col";
export const containerStyle: ICardProperties = {
[ECardVariant.WITHOUT_SHADOW]: "",
[ECardVariant.WITH_SHADOW]: "hover:shadow-custom-shadow-4xl duration-300",

View file

@ -27,22 +27,17 @@ export function CollapsibleButton(props: Props) {
ChevronIcon = DropdownIcon,
} = props;
return (
<div
className={cn(
"flex items-center justify-between gap-3 h-12 px-2.5 py-3 border-b border-custom-border-200",
className
)}
>
<div className={cn("flex items-center justify-between gap-3 h-12 px-2.5 py-3 border-b border-subtle", className)}>
<div className="flex items-center gap-3.5">
<div className="flex items-center gap-3">
{!hideChevron && (
<ChevronIcon
className={cn("size-2 text-custom-text-300 hover:text-custom-text-200 duration-300", {
className={cn("size-2 text-tertiary hover:text-secondary duration-300", {
"-rotate-90": !isOpen,
})}
/>
)}
<span className={cn("text-base text-custom-text-100 font-medium", titleClassName)}>{title}</span>
<span className={cn("text-14 text-primary font-medium", titleClassName)}>{title}</span>
</div>
{indicatorElement && indicatorElement}
</div>

View file

@ -21,10 +21,7 @@ export const DragHandle = forwardRef(function DragHandle(
return (
<button
type="button"
className={cn(
"p-0.5 flex flex-shrink-0 rounded bg-custom-background-90 text-custom-sidebar-text-200 cursor-grab",
className
)}
className={cn("p-0.5 flex flex-shrink-0 rounded-sm bg-surface-2 text-secondary cursor-grab", className)}
onContextMenu={(e) => {
e.preventDefault();
e.stopPropagation();

View file

@ -13,10 +13,10 @@ export function DropIndicator(props: Props) {
<div
className={cn(
`block relative h-[2px] w-full
before:left-0 before:relative before:block before:top-[-2px] before:h-[6px] before:w-[6px] before:rounded
after:left-[calc(100%-6px)] after:relative after:block after:top-[-8px] after:h-[6px] after:w-[6px] after:rounded`,
before:left-0 before:relative before:block before:top-[-2px] before:h-[6px] before:w-[6px] before:rounded-sm
after:left-[calc(100%-6px)] after:relative after:block after:top-[-8px] after:h-[6px] after:w-[6px] after:rounded-sm`,
{
"bg-custom-primary-100 before:bg-custom-primary-100 after:bg-custom-primary-100": isVisible,
"bg-accent-primary before:bg-accent-primary after:bg-accent-primary": isVisible,
},
classNames
)}

View file

@ -23,7 +23,7 @@ export function DropdownButton(props: IMultiSelectDropdownButton | ISingleSelect
className={cn(
"clickable block h-full max-w-full outline-none",
{
"cursor-not-allowed text-custom-text-200": disabled,
"cursor-not-allowed text-secondary": disabled,
"cursor-pointer": !disabled,
},
buttonContainerClassName

View file

@ -39,16 +39,16 @@ export function InputSearch(props: IInputSearch) {
return (
<div
className={cn(
"flex items-center gap-1.5 rounded border border-custom-border-100 bg-custom-background-90 px-2",
"flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2",
inputContainerClassName
)}
>
{inputIcon ? <>{inputIcon}</> : <Search className="h-4 w-4 text-custom-text-300" aria-hidden="true" />}
{inputIcon ? <>{inputIcon}</> : <Search className="h-4 w-4 text-tertiary" aria-hidden="true" />}
<Combobox.Input
as="input"
ref={inputRef}
className={cn(
"w-full bg-transparent py-1 text-xs text-custom-text-200 placeholder:text-custom-text-400 focus:outline-none",
"w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none",
inputClassName
)}
value={query}

View file

@ -5,7 +5,7 @@ export function DropdownOptionsLoader() {
return (
<div className="flex flex-col gap-1 animate-pulse">
{range(6).map((index) => (
<div key={index} className="flex h-[1.925rem] w-full rounded px-1 py-1.5 bg-custom-background-90" />
<div key={index} className="flex h-[1.925rem] w-full rounded-sm px-1 py-1.5 bg-surface-2" />
))}
</div>
);

View file

@ -51,11 +51,11 @@ export function DropdownOptions(props: IMultiSelectDropdownOptions | ISingleSele
disabled={option.disabled}
className={({ active, selected }) =>
cn(
"flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5",
"flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5",
{
"bg-custom-background-80": active,
"text-custom-text-100": selected,
"text-custom-text-200": !selected,
"bg-layer-1": active,
"text-primary": selected,
"text-secondary": !selected,
},
option.className && option.className({ active, selected })
)
@ -77,7 +77,7 @@ export function DropdownOptions(props: IMultiSelectDropdownOptions | ISingleSele
</Combobox.Option>
))
) : (
<p className="px-1.5 py-1 italic text-custom-text-400">No matching results</p>
<p className="px-1.5 py-1 italic text-placeholder">No matching results</p>
)
) : loader ? (
<> {loader} </>

View file

@ -138,7 +138,7 @@ export function MultiSelectDropdown(props: IMultiSelectDropdown) {
<Combobox.Options className="fixed z-10" static>
<div
className={cn(
"my-1 w-48 rounded border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2.5 text-xs shadow-custom-shadow-rg focus:outline-none",
"my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2.5 text-11 shadow-custom-shadow-rg focus:outline-none",
optionsContainerClassName
)}
ref={setPopperElement}

View file

@ -137,7 +137,7 @@ export function Dropdown(props: ISingleSelectDropdown) {
<Combobox.Options className="fixed z-10" static>
<div
className={cn(
"my-1 w-48 rounded border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2 text-xs shadow-custom-shadow-rg focus:outline-none",
"my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2 text-11 shadow-custom-shadow-rg focus:outline-none",
optionsContainerClassName
)}
ref={setPopperElement}

View file

@ -152,10 +152,10 @@ export function ContextMenuItem(props: ContextMenuItemProps) {
ref={setReferenceElement}
type="button"
className={cn(
"w-full flex items-center gap-2 px-1 py-1.5 text-left text-custom-text-200 rounded text-xs select-none",
"w-full flex items-center gap-2 px-1 py-1.5 text-left text-secondary rounded-sm text-11 select-none",
{
"bg-custom-background-90": isActive,
"text-custom-text-400": item.disabled,
"bg-layer-transparent-hover": isActive,
"text-placeholder": item.disabled,
},
item.className
)}
@ -170,8 +170,8 @@ export function ContextMenuItem(props: ContextMenuItemProps) {
<h5>{item.title}</h5>
{item.description && (
<p
className={cn("text-custom-text-300 whitespace-pre-line", {
"text-custom-text-400": item.disabled,
className={cn("text-tertiary whitespace-pre-line", {
"text-placeholder": item.disabled,
})}
>
{item.description}
@ -191,7 +191,7 @@ export function ContextMenuItem(props: ContextMenuItemProps) {
style={styles.popper}
{...attributes.popper}
className={cn(
"fixed z-[35] min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2.5 text-xs shadow-custom-shadow-lg",
"fixed z-[35] min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-subtle-1 bg-surface-1 px-2 py-2.5 text-11",
"ring-1 ring-black ring-opacity-5"
)}
data-context-submenu="true"
@ -202,10 +202,10 @@ export function ContextMenuItem(props: ContextMenuItemProps) {
key={nestedItem.key}
type="button"
className={cn(
"w-full flex items-center gap-2 px-1 py-1.5 text-left text-custom-text-200 rounded text-xs select-none",
"w-full flex items-center gap-2 px-1 py-1.5 text-left text-secondary rounded-sm text-11 select-none",
{
"bg-custom-background-90": index === activeNestedIndex,
"text-custom-text-400": nestedItem.disabled,
"bg-layer-transparent-hover": index === activeNestedIndex,
"text-placeholder": nestedItem.disabled,
},
nestedItem.className
)}
@ -225,8 +225,8 @@ export function ContextMenuItem(props: ContextMenuItemProps) {
<h5>{nestedItem.title}</h5>
{nestedItem.description && (
<p
className={cn("text-custom-text-300 whitespace-pre-line", {
"text-custom-text-400": nestedItem.disabled,
className={cn("text-tertiary whitespace-pre-line", {
"text-placeholder": nestedItem.disabled,
})}
>
{nestedItem.description}

View file

@ -206,7 +206,7 @@ function ContextMenuWithoutPortal(props: ContextMenuProps) {
>
<div
ref={contextMenuRef}
className="fixed border-[0.5px] border-custom-border-300 bg-custom-background-100 shadow-custom-shadow-rg rounded-md px-2 py-2.5 max-h-72 min-w-[12rem] overflow-y-scroll vertical-scrollbar scrollbar-sm"
className="fixed border-[0.5px] border-subtle-1 bg-surface-1 rounded-md px-2 py-2.5 max-h-72 min-w-[12rem] overflow-y-scroll vertical-scrollbar scrollbar-sm"
style={{
top: position.y,
left: position.x,

View file

@ -194,7 +194,7 @@ function CustomMenu(props: ICustomMenuDropdownProps) {
>
<div
className={cn(
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2.5 text-xs shadow-custom-shadow-rg focus:outline-none min-w-[12rem] whitespace-nowrap",
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-subtle-1 bg-surface-1 px-2 py-2.5 text-11 focus:outline-none min-w-[12rem] whitespace-nowrap",
{
"max-h-60": maxHeight === "lg",
"max-h-48": maxHeight === "md",
@ -257,8 +257,8 @@ function CustomMenu(props: ICustomMenuDropdownProps) {
type="button"
onClick={handleMenuButtonClick}
disabled={disabled}
className={`relative grid place-items-center rounded p-1 text-custom-text-200 outline-none hover:text-custom-text-100 ${
disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80"
className={`relative grid place-items-center rounded-sm p-1 text-secondary outline-none hover:text-primary ${
disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-layer-transparent-hover"
} ${buttonClassName}`}
tabIndex={customButtonTabIndex}
aria-label={ariaLabel}
@ -271,12 +271,10 @@ function CustomMenu(props: ICustomMenuDropdownProps) {
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 whitespace-nowrap rounded-md px-2.5 py-1 text-xs duration-300 ${
open ? "bg-custom-background-90 text-custom-text-100" : "text-custom-text-200"
} ${noBorder ? "" : "border border-custom-border-300 shadow-sm focus:outline-none"} ${
disabled
? "cursor-not-allowed text-custom-text-200"
: "cursor-pointer hover:bg-custom-background-80"
className={`flex items-center justify-between gap-1 whitespace-nowrap rounded-md px-2.5 py-1 text-11 duration-300 ${
open ? "text-primary" : "text-secondary"
} ${noBorder ? "" : "border border-strong shadow-sm focus:outline-none"} ${
disabled ? "cursor-not-allowed text-secondary" : "cursor-pointer hover:bg-layer-transparent-hover"
} ${buttonClassName}`}
onClick={handleMenuButtonClick}
tabIndex={customButtonTabIndex}
@ -396,10 +394,10 @@ function SubMenu(props: ICustomSubMenuProps) {
{({ active }) => (
<div
className={cn(
"w-full select-none rounded px-1 py-1.5 text-left text-custom-text-200 flex items-center justify-between cursor-pointer",
"w-full select-none rounded-sm px-1 py-1.5 text-left text-secondary flex items-center justify-between cursor-pointer",
{
"bg-custom-background-80": active && !disabled,
"text-custom-text-400": disabled,
"bg-layer-transparent-hover": active && !disabled,
"text-placeholder": disabled,
"cursor-not-allowed": disabled,
}
)}
@ -419,7 +417,7 @@ function SubMenu(props: ICustomSubMenuProps) {
style={styles.popper}
{...attributes.popper}
className={cn(
"fixed z-30 min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 p-1 text-xs shadow-custom-shadow-lg",
"fixed z-30 min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-subtle-1 bg-surface-1 p-1 text-11",
"ring-1 ring-black ring-opacity-5", // Additional styling to make it stand out
contentClassName
)}
@ -459,10 +457,10 @@ function MenuItem(props: ICustomMenuItemProps) {
<button
type="button"
className={cn(
"w-full select-none truncate rounded px-1 py-1.5 text-left text-custom-text-200",
"w-full select-none truncate rounded-sm px-1 py-1.5 text-left text-secondary",
{
"bg-custom-background-80": active && !disabled,
"text-custom-text-400": disabled,
"bg-layer-transparent-hover": active && !disabled,
"text-placeholder": disabled,
},
className
)}
@ -489,10 +487,10 @@ function SubMenuTrigger(props: ICustomSubMenuTriggerProps) {
{({ active }) => (
<div
className={cn(
"w-full select-none rounded px-1 py-1.5 text-left text-custom-text-200 flex items-center justify-between",
"w-full select-none rounded-sm px-1 py-1.5 text-left text-secondary flex items-center justify-between",
{
"bg-custom-background-80": active && !disabled,
"text-custom-text-400": disabled,
"bg-layer-transparent-hover": active && !disabled,
"text-placeholder": disabled,
"cursor-pointer": !disabled,
"cursor-not-allowed": disabled,
},
@ -513,7 +511,7 @@ function SubMenuContent(props: ICustomSubMenuContentProps) {
return (
<div
className={cn(
"z-[15] min-w-[12rem] overflow-hidden rounded-md border border-custom-border-300 bg-custom-background-100 p-1 text-xs shadow-custom-shadow-rg",
"z-[15] min-w-[12rem] overflow-hidden rounded-md border border-subtle-1 bg-surface-1 p-1 text-11",
className
)}
>

View file

@ -99,10 +99,10 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
ref={setReferenceElement}
type="button"
className={cn(
"flex w-full items-center justify-between gap-1 text-xs",
"flex w-full items-center justify-between gap-1 text-11",
{
"cursor-not-allowed text-custom-text-200": disabled,
"cursor-pointer hover:bg-custom-background-80": !disabled,
"cursor-not-allowed text-secondary": disabled,
"cursor-pointer hover:bg-layer-transparent-hover": !disabled,
},
customButtonClassName
)}
@ -117,12 +117,12 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
ref={setReferenceElement}
type="button"
className={cn(
"flex w-full items-center justify-between gap-1 rounded border-[0.5px] border-custom-border-300",
"flex w-full items-center justify-between gap-1 rounded-sm border-[0.5px] border-strong",
{
"px-3 py-2 text-sm": input,
"px-2 py-1 text-xs": !input,
"cursor-not-allowed text-custom-text-200": disabled,
"cursor-pointer hover:bg-custom-background-80": !disabled,
"px-3 py-2 text-13": input,
"px-2 py-1 text-11": !input,
"cursor-not-allowed text-secondary": disabled,
"cursor-pointer hover:bg-layer-transparent-hover": !disabled,
},
buttonClassName
)}
@ -140,17 +140,17 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
<Combobox.Options data-prevent-outside-click static>
<div
className={cn(
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 py-2.5 text-xs shadow-custom-shadow-rg focus:outline-none min-w-48 whitespace-nowrap z-30",
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-subtle-1 bg-surface-1 py-2.5 text-11 focus:outline-none min-w-48 whitespace-nowrap z-30",
optionsClassName
)}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className="flex items-center gap-1.5 rounded border border-custom-border-100 bg-custom-background-90 px-2 mx-2">
<Search className="h-3.5 w-3.5 text-custom-text-400" strokeWidth={1.5} />
<div className="flex items-center gap-1.5 rounded-sm border border-subtle px-2 mx-2">
<Search className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
<Combobox.Input
className="w-full bg-transparent py-1 text-xs text-custom-text-200 placeholder:text-custom-text-400 focus:outline-none"
className="w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search"
@ -175,10 +175,10 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
value={option.value}
className={({ active }) =>
cn(
"w-full truncate flex items-center justify-between gap-2 rounded px-1 py-1.5 cursor-pointer select-none",
"w-full truncate flex items-center justify-between gap-2 rounded-sm px-1 py-1.5 cursor-pointer select-none",
{
"bg-custom-background-80": active,
"text-custom-text-400 opacity-60 cursor-not-allowed": option.disabled,
"bg-layer-transparent-hover": active,
"text-placeholder opacity-60 cursor-not-allowed": option.disabled,
}
)
}
@ -195,7 +195,7 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
<>
{typeof option.tooltip === "string" ? (
<Tooltip tooltipContent={option.tooltip}>
<Info className="h-3.5 w-3.5 flex-shrink-0 cursor-pointer text-custom-text-200" />
<Info className="h-3.5 w-3.5 flex-shrink-0 cursor-pointer text-secondary" />
</Tooltip>
) : (
option.tooltip
@ -207,10 +207,10 @@ export function CustomSearchSelect(props: ICustomSearchSelectProps) {
</Combobox.Option>
))
) : (
<p className="text-custom-text-400 italic py-1 px-1.5">{noResultsMessage}</p>
<p className="text-placeholder italic py-1 px-1.5">{noResultsMessage}</p>
)
) : (
<p className="text-custom-text-400 italic py-1 px-1.5">Loading...</p>
<p className="text-placeholder italic py-1 px-1.5">Loading...</p>
)}
</div>
{footerOption}

View file

@ -80,8 +80,8 @@ function CustomSelect(props: ICustomSelectProps) {
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 text-xs rounded ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
className={`flex items-center justify-between gap-1 text-11 rounded ${
disabled ? "cursor-not-allowed text-secondary" : "cursor-pointer hover:bg-layer-transparent-hover"
} ${customButtonClassName}`}
onClick={toggleDropdown}
>
@ -94,12 +94,12 @@ function CustomSelect(props: ICustomSelectProps) {
ref={setReferenceElement}
type="button"
className={cn(
"flex w-full items-center justify-between gap-1 rounded border-[0.5px] border-custom-border-300",
"flex w-full items-center justify-between gap-1 rounded border-[0.5px] border-strong",
{
"px-3 py-2 text-sm": input,
"px-2 py-1 text-xs": !input,
"cursor-not-allowed text-custom-text-200": disabled,
"cursor-pointer hover:bg-custom-background-80": !disabled,
"px-3 py-2 text-13": input,
"px-2 py-1 text-11": !input,
"cursor-not-allowed text-secondary": disabled,
"cursor-pointer hover:bg-layer-transparent-hover": !disabled,
},
buttonClassName
)}
@ -116,7 +116,7 @@ function CustomSelect(props: ICustomSelectProps) {
<Combobox.Options data-prevent-outside-click>
<div
className={cn(
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2.5 text-xs shadow-custom-shadow-rg focus:outline-none min-w-48 whitespace-nowrap z-30",
"my-1 overflow-y-scroll rounded-md border-[0.5px] border-subtle-1 bg-surface-1 px-2 py-2.5 text-11 focus:outline-none min-w-48 whitespace-nowrap z-30",
optionsClassName
)}
ref={setPopperElement}
@ -160,9 +160,9 @@ function Option(props: ICustomSelectItemProps) {
value={value}
className={({ active }) =>
cn(
"cursor-pointer select-none truncate rounded px-1 py-1.5 text-custom-text-200 flex items-center justify-between gap-2",
"cursor-pointer select-none truncate rounded-sm px-1 py-1.5 text-secondary flex items-center justify-between gap-2",
{
"bg-custom-background-80": active,
"bg-layer-transparent-hover": active,
},
className
)

View file

@ -17,9 +17,9 @@ export function FavoriteStar(props: Props) {
<button type="button" className={cn("h-4 w-4 grid place-items-center", buttonClassName)} onClick={onClick}>
<Star
className={cn(
"h-4 w-4 text-custom-text-300 transition-all",
"h-4 w-4 text-tertiary transition-all",
{
"fill-yellow-500 stroke-yellow-500": selected,
"fill-(--color-label-yellow-icon) stroke-(--color-label-yellow-icon)": selected,
},
iconClassName
)}

View file

@ -32,10 +32,12 @@ const Checkbox = React.forwardRef(function Checkbox(props: CheckboxProps, ref: R
className={cn(
"appearance-none shrink-0 size-4 border rounded-[3px] focus:outline-1 focus:outline-offset-4 focus:outline-custom-primary-50 cursor-pointer",
{
"border-custom-border-200 bg-custom-background-80 cursor-not-allowed": disabled,
"border-custom-border-300 hover:border-custom-border-400 bg-transparent": !disabled,
"border-custom-primary-40 hover:border-custom-primary-40 bg-custom-primary-100 hover:bg-custom-primary-200":
"border-subtle bg-layer-1 cursor-not-allowed": disabled,
"border-strong hover:border-strong-1 bg-transparent": !disabled,
"border-accent-strong-40 hover:border-accent-strong-40 bg-accent-primary hover:bg-accent-primary/80":
!disabled && (checked || indeterminate),
"border-none": checked,
},
className
)}
@ -44,10 +46,10 @@ const Checkbox = React.forwardRef(function Checkbox(props: CheckboxProps, ref: R
/>
<svg
className={cn(
"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 size-4 p-0.5 pointer-events-none outline-none hidden stroke-white",
"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 size-4 p-0.5 pointer-events-none outline-none hidden text-on-color",
{
block: checked,
"stroke-custom-text-400 opacity-40": disabled,
"text-placeholder opacity-40": disabled,
},
iconClassName
)}

View file

@ -48,66 +48,57 @@ export function InputColorPicker(props: InputColorPickerProps) {
onChange={handleInputChange}
hasError={hasError}
placeholder={placeholder}
className={cn("border-[0.5px] border-custom-border-200", className)}
className={cn("border-[0.5px] border-subtle", className)}
style={style}
/>
<Popover as="div" className="absolute right-1 top-1/2 z-10 -translate-y-1/2">
{({ open }) => {
if (open) {
}
return (
<>
<Popover.Button as={React.Fragment}>
<Button
ref={setReferenceElement}
variant="neutral-primary"
size="sm"
className="border-none !bg-transparent"
{() => (
<>
<Popover.Button as={React.Fragment}>
<Button ref={setReferenceElement} variant="neutral-primary" className="border-none !bg-transparent">
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-palette"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-palette"
>
<circle cx="13.5" cy="6.5" r=".5" />
<circle cx="17.5" cy="10.5" r=".5" />
<circle cx="8.5" cy="7.5" r=".5" />
<circle cx="6.5" cy="12.5" r=".5" />
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" />
</svg>
</Button>
</Popover.Button>
<Transition
as={React.Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel>
<div
className="z-10 overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 shadow-custom-shadow-rg"
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<ColorPicker.SketchPicker color={value} onChange={handleColorChange} />
</div>
</Popover.Panel>
</Transition>
</>
);
}}
<circle cx="13.5" cy="6.5" r=".5" />
<circle cx="17.5" cy="10.5" r=".5" />
<circle cx="8.5" cy="7.5" r=".5" />
<circle cx="6.5" cy="12.5" r=".5" />
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" />
</svg>
</Button>
</Popover.Button>
<Transition
as={React.Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel>
<div
className="z-10 overflow-hidden rounded-sm border border-subtle bg-surface-1 shadow-custom-shadow-rg"
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<ColorPicker.SketchPicker color={value} onChange={handleColorChange} />
</div>
</Popover.Panel>
</Transition>
</>
)}
</Popover>
</div>
);

View file

@ -30,12 +30,12 @@ const Input = React.forwardRef(function Input(props: InputProps, ref: React.Forw
type={type}
name={name}
className={cn(
"block rounded-md bg-transparent text-sm placeholder-custom-text-400 focus:outline-none",
"block rounded-md bg-transparent text-13 placeholder-custom-text-400 focus:outline-none",
{
"rounded-md border-[0.5px] border-custom-border-200": mode === "primary",
"rounded border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-custom-primary":
"rounded-md border-[0.5px] border-subtle": mode === "primary",
"rounded-sm border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-custom-primary":
mode === "transparent",
"rounded border-none bg-transparent ring-0": mode === "true-transparent",
"rounded-sm border-none bg-transparent ring-0": mode === "true-transparent",
"border-red-500": hasError,
"px-1.5 py-1": inputSize === "xs",
"px-3 py-2": inputSize === "sm",

View file

@ -14,7 +14,7 @@ export const getStrengthInfo = (strength: E_PASSWORD_STRENGTH): StrengthInfo =>
case E_PASSWORD_STRENGTH.EMPTY:
return {
message: "Please enter your password",
textColor: "text-custom-text-100",
textColor: "text-primary",
activeFragments: 0,
};
case E_PASSWORD_STRENGTH.LENGTH_NOT_VALID:
@ -38,7 +38,7 @@ export const getStrengthInfo = (strength: E_PASSWORD_STRENGTH): StrengthInfo =>
default:
return {
message: "Please enter your password",
textColor: "text-custom-text-100",
textColor: "text-primary",
activeFragments: 0,
};
}
@ -49,7 +49,7 @@ export const getStrengthInfo = (strength: E_PASSWORD_STRENGTH): StrengthInfo =>
*/
export const getFragmentColor = (fragmentIndex: number, activeFragments: number): string => {
if (fragmentIndex >= activeFragments) {
return "bg-custom-background-80";
return "bg-layer-1";
}
switch (activeFragments) {
@ -60,6 +60,6 @@ export const getFragmentColor = (fragmentIndex: number, activeFragments: number)
case 3:
return "bg-green-500";
default:
return "bg-custom-background-80";
return "bg-layer-1";
}
};

View file

@ -34,7 +34,7 @@ export function PasswordStrengthIndicator({
<div
key={fragmentIndex}
className={cn(
"h-1 flex-1 rounded-sm transition-all duration-300 ease-in-out",
"h-1 flex-1 rounded-xs transition-all duration-300 ease-in-out",
getFragmentColor(fragmentIndex, strengthInfo.activeFragments)
)}
/>
@ -42,7 +42,7 @@ export function PasswordStrengthIndicator({
</div>
{/* Strength Message */}
{password && <p className={cn("text-sm font-medium", strengthInfo.textColor)}>{strengthInfo.message}</p>}
{password && <p className={cn("!text-13 font-medium", strengthInfo.textColor)}>{strengthInfo.message}</p>}
</div>
{/* Criteria list */}
@ -54,14 +54,14 @@ export function PasswordStrengthIndicator({
<CircleCheck
className={cn("h-3 w-3 flex-shrink-0", {
"text-green-500": criterion.isValid,
"text-custom-text-100": !criterion.isValid,
"text-primary": !criterion.isValid,
})}
/>
</div>
<span
className={cn("text-xs", {
className={cn("!text-11", {
"text-green-500": criterion.isValid,
"text-custom-text-100": !criterion.isValid,
"text-primary": !criterion.isValid,
})}
>
{criterion.label}

View file

@ -31,9 +31,9 @@ export function PasswordInput({
value={value}
onChange={(e) => onChange(e.target.value)}
className={cn(
"w-full px-3 py-2 pr-10 text-custom-text-200 border rounded-md bg-custom-background-100 focus:outline-none focus:ring-2 focus:ring-custom-primary-100 placeholder:text-custom-text-400 focus:border-transparent transition-all duration-200",
"w-full px-3 py-2 pr-10 text-secondary border rounded-md bg-surface-1 focus:outline-none focus:ring-2 focus:ring-custom-primary-100 placeholder:text-placeholder focus:border-transparent transition-all duration-200",
{
"border-custom-border-300": !error,
"border-strong": !error,
"border-red-500": error,
},
className
@ -45,7 +45,7 @@ export function PasswordInput({
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-custom-text-200 hover:text-custom-text-100 transition-colors duration-200"
className="absolute inset-y-0 right-0 pr-3 flex items-center text-secondary hover:text-primary transition-colors duration-200"
>
<div className="relative w-4 h-4">
<Eye

View file

@ -10,7 +10,7 @@ interface LabelProps {
export function Label({ htmlFor, children, className }: LabelProps) {
return (
<label htmlFor={htmlFor} className={cn("block text-sm font-medium text-custom-text-100", className)}>
<label htmlFor={htmlFor} className={cn("block text-13 font-medium text-primary", className)}>
{children}
</label>
);
@ -30,7 +30,7 @@ export function FormField({ label, htmlFor, children, className, optional = fals
<div className={cn("flex flex-col gap-1.5", className)}>
<Label htmlFor={htmlFor}>
{label}
{optional && <span className="text-custom-text-400 text-sm"> (optional)</span>}
{optional && <span className="text-placeholder text-13"> (optional)</span>}
</Label>
{children}
</div>
@ -48,7 +48,7 @@ export function ValidationMessage({ type, message, className }: ValidationMessag
return (
<p
className={cn(
"text-sm",
"text-13",
{
"text-red-500": type === "error",
"text-green-500": type === "success",

View file

@ -39,10 +39,10 @@ const TextArea = React.forwardRef(function TextArea(
className={cn(
"no-scrollbar w-full bg-transparent placeholder-custom-text-400 outline-none",
{
"rounded-md border-[0.5px] border-custom-border-200": mode === "primary",
"focus:ring-theme rounded border-none bg-transparent ring-0 transition-all focus:ring-1":
"rounded-md border-[0.5px] border-subtle": mode === "primary",
"focus:ring-theme rounded-sm border-none bg-transparent ring-0 transition-all focus:ring-1":
mode === "transparent",
"rounded border-none bg-transparent ring-0": mode === "true-transparent",
"rounded-sm border-none bg-transparent ring-0": mode === "true-transparent",
"px-1.5 py-1": textAreaSize === "xs",
"px-3 py-2": textAreaSize === "sm",
"p-3": textAreaSize === "md",

View file

@ -10,11 +10,9 @@ export interface IHeaderProperties {
}
export const headerStyle: IHeaderProperties = {
[EHeaderVariant.PRIMARY]:
"relative flex w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-custom-sidebar-background-100 bg-custom-sidebar-background-100 z-[18]",
[EHeaderVariant.SECONDARY]:
"!py-0 overflow-y-hidden border-b border-custom-border-200 justify-between bg-custom-background-100 z-[15]",
[EHeaderVariant.TERNARY]:
"flex flex-wrap justify-between py-2 border-b border-custom-border-200 gap-2 bg-custom-background-100 z-[12]",
"relative flex w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-surface-1 bg-surface-1 z-[18]",
[EHeaderVariant.SECONDARY]: "!py-0 overflow-y-hidden border-b border-subtle justify-between bg-surface-1 z-[15]",
[EHeaderVariant.TERNARY]: "flex flex-wrap justify-between py-2 border-b border-subtle gap-2 bg-surface-1 z-[12]",
};
export const minHeights: IHeaderProperties = {
[EHeaderVariant.PRIMARY]: "",

View file

@ -30,5 +30,4 @@ export * from "./tag";
export * from "./tooltip";
export * from "./typography";
export * from "./utils";
export * from "./billing";
export * from "./oauth";

View file

@ -22,14 +22,14 @@ export function LinkItemBlock(props: TLinkItemBlockProps) {
return (
<div
onClick={onClick}
className="cursor-pointer group flex items-center bg-custom-background-100 px-4 w-[230px] h-[56px] border-[0.5px] border-custom-border-200 rounded-md gap-4"
className="cursor-pointer group flex items-center bg-surface-1 px-4 w-[230px] h-[56px] border-[0.5px] border-subtle rounded-md gap-4"
>
<div className="flex-shrink-0 size-8 rounded p-2 bg-custom-background-90 grid place-items-center">
<Icon className="size-4 stroke-2 text-custom-text-350 group-hover:text-custom-text-100" />
<div className="flex-shrink-0 size-8 rounded-sm p-2 bg-surface-2 grid place-items-center">
<Icon className="size-4 stroke-2 text-tertiary group-hover:text-primary" />
</div>
<div className="flex-1 truncate">
<div className="text-sm font-medium truncate">{title}</div>
{createdAt && <div className="text-xs font-medium text-custom-text-400">{calculateTimeAgo(createdAt)}</div>}
<div className="text-13 font-medium truncate">{title}</div>
{createdAt && <div className="text-11 font-medium text-placeholder">{calculateTimeAgo(createdAt)}</div>}
</div>
{menuItems && (
<div className="hidden group-hover:block">
@ -43,7 +43,7 @@ export function LinkItemBlock(props: TLinkItemBlockProps) {
item.action();
}}
className={cn("flex items-center gap-2 w-full ", {
"text-custom-text-400": item.disabled,
"text-placeholder": item.disabled,
})}
disabled={item.disabled}
>
@ -52,8 +52,8 @@ export function LinkItemBlock(props: TLinkItemBlockProps) {
<h5>{item.title}</h5>
{item.description && (
<p
className={cn("text-custom-text-300 whitespace-pre-line", {
"text-custom-text-400": item.disabled,
className={cn("text-tertiary whitespace-pre-line", {
"text-placeholder": item.disabled,
})}
>
{item.description}

View file

@ -22,9 +22,7 @@ type ItemProps = {
};
function Item({ height = "auto", width = "auto", className = "" }: ItemProps) {
return (
<div className={cn("rounded-md bg-custom-background-80", className)} style={{ height: height, width: width }} />
);
return <div className={cn("rounded-md bg-layer-1", className)} style={{ height: height, width: width }} />;
}
Loader.Item = Item;

View file

@ -42,7 +42,7 @@ const BUTTON_VARIANTS: Record<TModalVariant, TButtonVariant> = {
const VARIANT_CLASSES: Record<TModalVariant, string> = {
danger: "bg-red-500/20 text-red-500",
primary: "bg-custom-primary-100/20 text-custom-primary-100",
primary: "bg-accent-primary/20 text-accent-primary",
};
export function AlertModalCore(props: Props) {
@ -80,15 +80,15 @@ export function AlertModalCore(props: Props) {
</span>
)}
<div className="text-center sm:text-left">
<h3 className="text-lg font-medium">{title}</h3>
<p className="mt-1 text-sm text-custom-text-200">{content}</p>
<h3 className="text-16 font-medium">{title}</h3>
<p className="mt-1 text-13 text-secondary">{content}</p>
</div>
</div>
<div className="px-5 py-4 flex flex-col-reverse sm:flex-row sm:justify-end gap-2 border-t-[0.5px] border-custom-border-200">
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
<div className="px-5 py-4 flex flex-col-reverse sm:flex-row sm:justify-end gap-2 border-t-[0.5px] border-subtle">
<Button variant="neutral-primary" onClick={handleClose}>
{secondaryButtonText}
</Button>
<Button variant={BUTTON_VARIANTS[variant]} size="sm" tabIndex={1} onClick={handleSubmit} loading={isSubmitting}>
<Button variant={BUTTON_VARIANTS[variant]} tabIndex={1} onClick={handleSubmit} loading={isSubmitting}>
{isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
</Button>
</div>

View file

@ -35,7 +35,7 @@ export function ModalCore(props: Props) {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
<div className="fixed inset-0 bg-backdrop transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-30 overflow-y-auto">
@ -51,7 +51,7 @@ export function ModalCore(props: Props) {
>
<Dialog.Panel
className={cn(
"relative transform rounded-lg bg-custom-background-100 text-left shadow-custom-shadow-md transition-all w-full",
"relative transform rounded-lg bg-surface-1 text-left shadow-custom-shadow-md transition-all w-full",
width,
className
)}

View file

@ -17,14 +17,16 @@ const OAuthButton = React.forwardRef(function OAuthButton(
<button
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-center gap-2 rounded-md border border-custom-border-300 px-4 py-2.5 text-sm font-medium text-custom-text-100 duration-300 bg-onboarding-background-200 hover:bg-onboarding-background-300",
"flex h-9 w-full items-center justify-center gap-2 rounded-md border border-strong px-4 py-2.5 text-13 font-medium text-primary duration-300 bg-onboarding-background-200 hover:bg-onboarding-background-300",
className
)}
{...rest}
>
<div className="flex flex-shrink-0 items-center justify-center">{icon}</div>
{!compact && (
<div className="flex flex-grow items-center justify-center transition-opacity duration-300">{text}</div>
<span className="flex flex-grow items-center justify-center transition-opacity duration-300 text-body-sm-regular">
{text}
</span>
)}
</button>
);

View file

@ -48,9 +48,9 @@ export function OAuthOptions(props: OAuthOptionsProps) {
</div>
<div className="mt-4 flex items-center transition-all duration-300">
<hr className="w-full border-custom-border-300 transition-colors duration-300" />
<p className="mx-3 flex-shrink-0 text-center text-sm text-custom-text-400 transition-colors duration-300">or</p>
<hr className="w-full border-custom-border-300 transition-colors duration-300" />
<hr className="w-full border-strong transition-colors duration-300" />
<p className="mx-3 flex-shrink-0 text-center text-13 text-placeholder transition-colors duration-300">or</p>
<hr className="w-full border-strong transition-colors duration-300" />
</div>
</div>
);

View file

@ -16,7 +16,7 @@ const meta: Meta<typeof PopoverMenu<TPopoverMenu>> = {
tags: ["autodocs"],
args: {
popperPosition: "bottom-start",
panelClassName: "rounded bg-gray-100 p-2",
panelClassName: "rounded-sm bg-gray-100 p-2",
data: [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Doe" },
@ -25,7 +25,7 @@ const meta: Meta<typeof PopoverMenu<TPopoverMenu>> = {
],
keyExtractor: (item, index: number) => `${item.id}-${index}`,
render: (item: TPopoverMenu) => (
<div className="text-sm text-gray-600 hover:text-gray-700 rounded-sm cursor-pointer hover:bg-gray-200 transition-all px-1.5 py-0.5 capitalize">
<div className="text-13 text-gray-600 hover:text-gray-700 rounded-xs cursor-pointer hover:bg-gray-200 transition-all px-1.5 py-0.5 capitalize">
{item.name}
</div>
),

View file

@ -29,7 +29,7 @@ export function PopoverMenu<T>(props: TPopoverMenu<T>) {
button={button}
disabled={disabled}
panelClassName={cn(
"my-1 w-48 rounded border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2 text-xs shadow-custom-shadow-rg focus:outline-none",
"my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2 text-11 shadow-custom-shadow-rg focus:outline-none",
panelClassName
)}
popoverClassName={popoverClassName}

View file

@ -17,12 +17,12 @@ type Story = StoryObj<typeof Popover>;
// components
const RenderCustomPopoverComponent = (
<div className="space-y-2">
<div className="text-sm font-medium text-gray-500">Your custom component</div>
<div className="text-13 font-medium text-gray-500">Your custom component</div>
<div>
{["option1", "option2", "option3"].map((option) => (
<div
key={option}
className="text-sm text-gray-600 hover:text-gray-700 rounded-sm cursor-pointer hover:bg-gray-200 transition-all px-1.5 py-0.5 capitalize"
className="text-13 text-gray-600 hover:text-gray-700 rounded-xs cursor-pointer hover:bg-gray-200 transition-all px-1.5 py-0.5 capitalize"
>
{option}
</div>
@ -35,7 +35,7 @@ const RenderCustomPopoverComponent = (
export const Default: Story = {
args: {
popperPosition: "bottom-start",
panelClassName: "rounded bg-gray-100 p-2",
panelClassName: "rounded-sm bg-gray-100 p-2",
children: RenderCustomPopoverComponent,
},
};
@ -44,11 +44,11 @@ export const CustomMenuButton: Story = {
args: {
popperPosition: "bottom-start",
button: (
<div className="p-2 text-sm font-medium rounded bg-gray-100 hover:bg-gray-200 transition-all">
<div className="p-2 text-13 font-medium rounded-sm bg-gray-100 hover:bg-gray-200 transition-all">
Custom Menu Button
</div>
),
panelClassName: "rounded bg-gray-100 p-2",
panelClassName: "rounded-sm bg-gray-100 p-2",
children: RenderCustomPopoverComponent,
},
};

View file

@ -45,7 +45,7 @@ export function Popover(props: TPopover) {
ref={popoverButtonRef as Ref<HTMLButtonElement>}
className={cn(
{
"flex justify-center items-center text-base h-6 w-6 rounded transition-all bg-custom-background-90 hover:bg-custom-background-80":
"flex justify-center items-center text-14 h-6 w-6 rounded-sm transition-all bg-surface-2 hover:bg-layer-1":
!button,
},
buttonClassName

View file

@ -9,7 +9,7 @@ interface ICircularProgressIndicator {
}
export function CircularProgressIndicator(props: ICircularProgressIndicator) {
const { size = 40, percentage = 25, strokeWidth = 6, strokeColor = "stroke-custom-primary-100", children } = props;
const { size = 40, percentage = 25, strokeWidth = 6, strokeColor = "stroke-accent-primary", children } = props;
const sqSize = size;
const radius = (size - strokeWidth) / 2;
@ -20,7 +20,7 @@ export function CircularProgressIndicator(props: ICircularProgressIndicator) {
<div className="relative">
<svg width={size} height={size} viewBox={viewBox} fill="none">
<circle
className="fill-none stroke-custom-background-80"
className="fill-none stroke-(--border-color-strong)"
cx={size / 2}
cy={size / 2}
r={radius}

View file

@ -35,23 +35,21 @@ export function LinearProgressIndicator({
else
return (
<Tooltip key={item.id} tooltipContent={`${item.name} ${Math.round(item.value)}${inPercentage ? "%" : ""}`}>
<div style={style} className={cn("first:rounded-l-sm last:rounded-r-sm", barClassName)} />
<div style={style} className={cn("first:rounded-l-xs last:rounded-r-xs", barClassName)} />
</Tooltip>
);
});
return (
<div
className={cn("flex w-full items-center justify-between gap-[1px] rounded-sm", {
className={cn("flex w-full items-center justify-between gap-[1px] rounded-xs", {
"h-2": size === "sm",
"h-3": size === "md",
"h-3.5": size === "lg",
"h-[14px]": size === "xl",
})}
>
<div className={cn("flex h-full w-full gap-[1.5px] p-[2px] bg-custom-background-90 rounded-sm", className)}>
{bars}
</div>
<div className={cn("flex h-full w-full gap-[1.5px] p-[2px] bg-surface-2 rounded-xs", className)}>{bars}</div>
</div>
);
}

View file

@ -15,7 +15,7 @@ export function Spinner({ height = "32px", width = "32px", className = "" }: ISp
aria-hidden="true"
height={height}
width={width}
className={cn("animate-spin fill-custom-primary-100 text-custom-text-200", className)}
className={cn("animate-spin fill-custom-primary-100 text-secondary", className)}
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"

View file

@ -52,7 +52,7 @@ export const Default: Story = {
keyExtractor: (rowData) => rowData.id,
tableClassName: "bg-gray-100",
tHeadClassName: "bg-gray-200",
tHeadTrClassName: "text-gray-600 text-left text-sm font-medium",
tHeadTrClassName: "text-gray-600 text-left text-13 font-medium",
thClassName: "font-medium",
tBodyClassName: "bg-gray-100",
tBodyTrClassName: "text-gray-600",

View file

@ -20,8 +20,8 @@ export function Table<T>(props: TTableData<T>) {
return (
<table className={cn("table-auto w-full overflow-hidden whitespace-nowrap", tableClassName)}>
<thead className={cn("divide-y divide-custom-border-200", tHeadClassName)}>
<tr className={cn("divide-x divide-custom-border-200 text-sm text-custom-text-100", tHeadTrClassName)}>
<thead className={cn("divide-y divide-subtle-1", tHeadClassName)}>
<tr className={cn("divide-x divide-subtle-1 text-13 text-primary", tHeadTrClassName)}>
{columns.map((column) => (
<th key={column.key} className={cn("px-2.5 py-2", thClassName)}>
{(column?.thRender && column?.thRender()) || column.content}
@ -29,11 +29,11 @@ export function Table<T>(props: TTableData<T>) {
))}
</tr>
</thead>
<tbody className={cn("divide-y divide-custom-border-200", tBodyClassName)}>
<tbody className={cn("divide-y divide-subtle-1", tBodyClassName)}>
{data.map((item) => (
<tr
key={keyExtractor(item)}
className={cn("divide-x divide-custom-border-200 text-sm text-custom-text-200", tBodyTrClassName)}
className={cn("divide-x divide-subtle-1 text-13 text-secondary", tBodyTrClassName)}
>
{columns.map((column) => (
<td key={`${column.key}-${keyExtractor(item)}`} className={cn("px-2.5 py-2", tdClassName)}>

View file

@ -34,7 +34,7 @@ export function TabList({
<Tab.List
as="div"
className={cn(
"flex w-full min-w-fit items-center justify-between gap-1.5 rounded-md text-sm p-0.5 bg-custom-background-80/60",
"flex w-full min-w-fit items-center justify-between gap-1.5 rounded-md text-13 p-0.5 bg-layer-1/60",
tabListClassName
)}
>
@ -42,16 +42,16 @@ export function TabList({
<Tab
className={({ selected }) =>
cn(
"flex items-center justify-center p-1 min-w-fit w-full font-medium text-custom-text-100 outline-none focus:outline-none cursor-pointer transition-all rounded",
"flex items-center justify-center p-1 min-w-fit w-full font-medium text-primary outline-none focus:outline-none cursor-pointer transition-all rounded-sm",
(selectedTab ? selectedTab === tab.key : selected)
? "bg-custom-background-100 text-custom-text-100 shadow-sm"
? "bg-layer-transparent-active text-primary shadow-sm"
: tab.disabled
? "text-custom-text-400 cursor-not-allowed"
: "text-custom-text-400 hover:text-custom-text-300 hover:bg-custom-background-80/60",
? "text-placeholder cursor-not-allowed"
: "text-placeholder hover:text-tertiary hover:bg-layer-transparent-hover",
{
"text-xs": size === "sm",
"text-sm": size === "md",
"text-base": size === "lg",
"text-11": size === "sm",
"text-13": size === "md",
"text-14": size === "lg",
},
tabClassName
)

View file

@ -14,7 +14,7 @@ export interface ITagProperties {
export const containerStyle: ITagProperties = {
[ETagVariant.OUTLINED]:
"flex items-center rounded-md border border-custom-border-200 text-xs text-custom-text-300 hover:text-custom-text-200 min-h-[36px] my-auto capitalize flex-wrap cursor-pointer gap-1.5",
"flex items-center rounded-md border border-subtle text-11 text-tertiary hover:text-secondary min-h-[36px] my-auto capitalize flex-wrap cursor-pointer gap-1.5",
};
export const sizes = {
[ETagSize.SM]: "p-1.5",

View file

@ -83,14 +83,14 @@ export function Tooltip({
content={
<div
className={cn(
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md",
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-surface-1 p-2 text-11 text-secondary shadow-md",
{
hidden: isMobile,
},
className
)}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipHeading && <h5 className="font-medium text-primary">{tooltipHeading}</h5>}
{tooltipContent}
</div>
}

View file

@ -9,7 +9,7 @@ type Props = {
function SubHeading({ children, className, noMargin }: Props) {
return (
<h3 className={cn("text-xl font-medium text-custom-text-200 block leading-7", !noMargin && "mb-2", className)}>
<h3 className={cn("text-18 font-medium text-secondary block leading-7", !noMargin && "mb-2", className)}>
{children}
</h3>
);

View file

@ -1,5 +1 @@
import { clsx } from "clsx";
import type { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));
export { cn } from "@plane/utils";