design-system-guidelines

star 2

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.

g4rcez By g4rcez schedule Updated 5/21/2026

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";
// Usage: <MyComponent as="a" href="/link"> renders an <a> tag

4. css() — Class Merging

Import css from ../../lib/dom (NOT clsx or cn directly):

import { css } from "../../lib/dom";
// css() = twMerge(clsx(...)) — handles conflicts + conditional classes
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 };
// Usage: <Tabs.Root><Tabs.List><Tabs.Item /></Tabs.List></Tabs.Root>

TypeScript Rules

No any

Use unknown, generics, or proper union types. Never any.

Polymorphic Props

import { PolymorphicProps } from "./polymorph";
import { CvaVariants, Override } from "../../types";

// Variant keys extracted from CVA variants object (NOT the cva() result):
type Variants = CvaVariants<typeof variants>;

// Full component props:
type MyComponentProps<T extends React.ElementType = "div"> = PropsWithChildren<
    PolymorphicProps<Variants & Partial<{ extraProp: string }>, T>
>;

// Override source props with new ones:
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
radius rounded-{component}-radius
border or *-border border-{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" />  // OK
<Card className="rounded-lg p-4" />       // WRONG

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" />                          // OK
<Modal className="rounded-xl p-8 z-[9999]" />   // WRONG

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.ts
Component tokens (sizing, radius, spacing, font sizes) packages/lib/src/styles/components.ts
Global spacing / Rounded / Z-Index packages/lib/src/styles/common.ts
Tailwind token registration packages/lib/preset.tailwind.ts
css() utility packages/lib/src/lib/dom.ts
Type utilities packages/lib/src/types.ts
Polymorph packages/lib/src/components/core/polymorph.tsx
Tailwind config packages/lib/tailwind.config.ts
Install via CLI
npx skills add https://github.com/g4rcez/components --skill design-system-guidelines
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator