name design-system-guidelines description ALWAYS use this skill when creating new components, modifying existing components, adding styling, working with design tokens, or doing anything related to this component library. Use this before writing any component code.
Design System Guidelines
Enforce design system rules and best practices for the components library.
React Patterns
All components MUST follow these patterns:
1. forwardRef — Always
Every component uses forwardRef:
export const MyComponent : <T extends React .ElementType = "div" >(_ : MyComponentProps <T> ) => React .ReactNode = forwardRef (function MyComponent (
{ className, theme, size, ...props }: MyComponentProps ,
ref : React .Ref <"div" >
) {
return (
<Polymorph
{...props }
ref ={ref}
data-component ="my-component"
as ={props.as ?? "div "}
className ={css(myVariants({ theme , size }), className )}
/>
);
}) as any ;
2. cva() — Variant Management
Use cva() from class-variance-authority for all variant-based styling:
import { cva } from "class-variance-authority" ;
const variants = {
theme : {
primary : "bg-button-primary-bg text-button-primary-text" ,
danger : "bg-button-danger-bg text-button-danger-text" ,
muted : "bg-button-muted-bg text-button-muted-text" ,
},
size : {
default : "h-button-height px-button-padding-x py-button-padding-y" ,
small : "h-button-height-small px-button-padding-x-small py-button-padding-y-small text-typography-sm" ,
},
};
const myVariants = cva ("base-classes-here" , {
variants,
defaultVariants : { theme : "primary" , size : "default" },
});
3. Polymorph — Polymorphic Rendering
When the element type can vary, use Polymorph:
import { Polymorph , PolymorphicProps } from "./polymorph" ;
4. css() — Class Merging
Import css from ../../lib/dom (NOT clsx or cn directly):
import { css } from "../../lib/dom" ;
className={css (myVariants ({ theme, size }), className)}
5. data-component — Debugging Attribute
Every component root element must have data-component="kebab-case-name":
<Polymorph data-component="my-component" ... />
6. Compound Components — Complex Components
Use compound component pattern (Tabs, Step, List, etc.):
export const Tabs = { Root : TabsRoot , List : TabsList , Item : TabsItem };
TypeScript Rules
No any
Use unknown, generics, or proper union types. Never any.
Polymorphic Props
import { PolymorphicProps } from "./polymorph" ;
import { CvaVariants , Override } from "../../types" ;
type Variants = CvaVariants <typeof variants>;
type MyComponentProps <T extends React .ElementType = "div" > = PropsWithChildren <
PolymorphicProps <Variants & Partial <{ extraProp : string }>, T>
>;
type CustomProps = Override <React .HTMLAttributes <HTMLDivElement >, { onClick : (id : string ) => void }>;
CvaVariants<T> — extracts variant keys from the variants object (the plain object, not the cva() call)
PolymorphicProps<Props, T> — merges custom props with the element's native props, adding as?: T
Override<Source, New> — Omit<Source, keyof New> & New
Design Token Rules
Core Rule: NEVER hardcode values
No text-[#fff], rounded-[8px], z-[9999], p-[12px]. Use tokens only.
Component Token System
All component-specific tokens are defined in packages/lib/src/styles/components.ts and auto-registered in Tailwind by preset.tailwind.ts. The mapping rule is:
Attribute in components.ts Tailwind class pattern radiusrounded-{component}-radiusborder or *-borderborder-{component}-{attr} (also usable as spacing)text, *-text, text-*text-{component}-{attr} (also usable as spacing)anything else spacing — h-, p-, px-, py-, gap-, w-, m-, etc.
Typography sizes are a special case: attrs from components.typography register as text-typography-{size} (not text-{size}):
text-typography-xs · text-typography-sm · text-typography-base
text-typography-lg · text-typography-xl · text-typography-2xl
text-typography-3xl · text-typography-4xl · text-typography-5xl
Common examples:
Button:
h-button-height, px-button-padding-x, py-button-padding-y
h-button-height-small, px-button-padding-x-small, py-button-padding-y-small
h-button-height-big, h-button-height-min, h-button-height-tiny
rounded-button-radius, gap-button-gap, p-button-padding-icon
Input:
h-input-height, px-input-padding-x, py-input-padding-y
rounded-input-radius, gap-input-gap
text-input-text, text-input-label-text, text-input-hint-text
Card:
rounded-card-radius, px-card-padding-x, py-card-padding-y, gap-card-gap
Modal:
rounded-modal-radius, px-modal-padding-x, py-modal-padding-y
Tag:
h-tag-height, px-tag-padding-x, py-tag-padding-y, gap-tag-gap
rounded-tag-radius, size-tag-indicator-size
For any component token not listed here, read packages/lib/src/styles/components.ts directly — every key maps to a Tailwind class following the rule above.
Colors — Semantic Tokens
Use as bg-{token}, text-{token}, border-{token}:
Global:
foreground, background, border, muted, muted-foreground, disabled
primary, primary-foreground, primary-subtle, primary-hover
secondary, secondary-foreground, secondary-subtle, secondary-hover, secondary-background
info, info-foreground, info-subtle, info-hover, info-notification
danger, danger-foreground, danger-subtle, danger-hover, danger-notification
warn, warn-foreground, warn-subtle, warn-hover, warn-notification
success, success-foreground, success-subtle, success-hover, success-notification
emphasis, emphasis-foreground, emphasis-subtle, emphasis-hover
Component-specific:
Card: bg-card-background, border-card-border, bg-card-muted
Button: bg-button-primary-bg, text-button-primary-text, bg-button-danger-bg, text-button-danger-text, bg-button-muted-bg, text-button-muted-text, bg-button-warn-bg, text-button-warn-text, bg-button-info-bg, text-button-info-text, bg-button-success-bg, text-button-success-text, bg-button-secondary-bg, text-button-secondary-text, bg-button-neutral-bg, text-button-neutral-text
Tag: bg-tag-primary-bg, text-tag-primary-text, bg-tag-danger-bg, text-tag-danger-text, bg-tag-warn-bg, text-tag-warn-text, bg-tag-success-bg, text-tag-success-text, bg-tag-muted-bg, text-tag-muted-text, bg-tag-neutral-bg, text-tag-neutral-text, bg-tag-secondary-bg, text-tag-secondary-text
Alert: bg-alert-{theme}-bg, text-alert-{theme}-text, border-alert-{theme}-border (themes: primary, danger, warn, info, success, muted, neutral, secondary)
Floating: bg-floating-background, text-floating-foreground, border-floating-border, bg-floating-hover, bg-floating-overlay
Tooltip: bg-tooltip-background, text-tooltip-foreground, border-tooltip-border
Table: bg-table-header, bg-table-background, border-table-border
Input: border-input-border, text-input-placeholder, bg-input-mask-error, bg-input-switch-bg, bg-input-switch, bg-input-slider
Global Spacing — from common.ts
gap-base, p-base, px-base, py-base (1rem)
gap-lg, p-lg (1.125rem)
gap-sm, p-sm (0.75rem)
gap-hairline, p-hairline (0.0625rem)
w-dialog (modal/dialog width: 20rem)
Rounded — Global Tokens
Only pill and full remain as global rounded tokens:
rounded-pill — pill-shaped elements (e.g. tags, indicators)
rounded-full — circles / avatars
All other component radii use the component token pattern: rounded-{component}-radius (e.g. rounded-button-radius, rounded-card-radius, rounded-modal-radius, rounded-input-radius).
Shadows
shadow-shadow-card — subtle card elevation
shadow-shadow-floating — modals, dropdowns
shadow-shadow-notification — toasts, notifications
shadow-shadow-table — table container
Z-Index
z-normal (1) — default stacking
z-calendar (2) — date pickers
z-tooltip (20) — tooltips
z-overlay (21) — modal overlays
z-navbar (22) — nav bar
z-floating (22) — floating panels, modals
z-wizard (50) — wizard/stepper overlays
Full Component Example
import { cva } from "class-variance-authority" ;
import React , { forwardRef, PropsWithChildren } from "react" ;
import { css } from "../../lib/dom" ;
import { CvaVariants } from "../../types" ;
import { Polymorph , PolymorphicProps } from "../core/polymorph" ;
const variants = {
theme : {
primary : "bg-button-primary-bg text-button-primary-text" ,
danger : "bg-button-danger-bg text-button-danger-text" ,
muted : "bg-button-muted-bg text-button-muted-text" ,
},
size : {
default : "h-button-height px-button-padding-x py-button-padding-y" ,
small : "h-button-height-small px-button-padding-x-small py-button-padding-y-small text-typography-sm" ,
},
};
const badgeVariants = cva ("inline-flex items-center font-medium rounded-button-radius" , {
variants,
defaultVariants : { theme : "primary" , size : "default" },
});
type Variants = CvaVariants <typeof variants>;
export type BadgeProps <T extends React .ElementType = "span" > = PropsWithChildren <
PolymorphicProps <Variants , T>
>;
export const Badge : <T extends React .ElementType = "span" >(_ : BadgeProps <T> ) => React .ReactNode = forwardRef (function Badge (
{ className, theme, size, ...props }: BadgeProps ,
ref : React .Ref <"span" >
) {
return (
<Polymorph
{...props }
ref ={ref}
data-component ="badge"
as ={props.as ?? "span "}
className ={css(badgeVariants({ theme , size }), className )}
/>
);
}) as any ;
Component-Specific Rules
Card (/packages/lib/src/components/display/card.tsx)
DO NOT add custom rounded-*, p-*, shadow-*, border-* overrides
Use tokens: rounded-card-radius, shadow-shadow-card, border-card-border, bg-card-background
<Card container="custom-layout-class" />
<Card className ="rounded-lg p-4" />
Modal (/packages/lib/src/components/floating/modal.tsx)
DO NOT add custom z-*, rounded-*, p-* overrides
Use tokens: z-floating, bg-floating-background, border-floating-border, rounded-modal-radius
<Modal type ="dialog" />
<Modal className ="rounded-xl p-8 z-[9999]" />
Validation Checklist
When creating or reviewing component code:
No hardcoded color values (#3B82F6, rgb(...), text-blue-500)
No hardcoded spacing (p-[12px], gap-[8px])
No arbitrary Tailwind values (rounded-[8px], z-[9999])
Primary color uses primary token, not "blue"
Card: no custom rounded-*, p-*, shadow-* — use rounded-card-radius
Modal: no custom z-*, rounded-*, p-* — use rounded-modal-radius
Button: uses rounded-button-radius not rounded-button or rounded-md
All z-index from token system (z-floating, z-tooltip, etc.)
Typography font sizes use text-typography-{size} not text-sm, text-xs, etc.
Component sizes/spacing use {component}-{attr} tokens not hardcoded values
Component uses forwardRef
Component uses cva() for variants
Variant types use CvaVariants<typeof variants> (variants object, not cva result)
Polymorphic components use Polymorph + PolymorphicProps
Class merging uses css() from ../../lib/dom
Root element has data-component="kebab-name"
No any types — use generics/unknown/unions
Quick Reference
Concern File Colors packages/lib/src/styles/light.ts / dark.tsComponent tokens (sizing, radius, spacing, font sizes) packages/lib/src/styles/components.tsGlobal spacing / Rounded / Z-Index packages/lib/src/styles/common.tsTailwind token registration packages/lib/preset.tailwind.tscss() utilitypackages/lib/src/lib/dom.tsType utilities packages/lib/src/types.tsPolymorph packages/lib/src/components/core/polymorph.tsxTailwind config packages/lib/tailwind.config.ts