always use this skill when creating new components, modifying existing components, adding styling, working with design tokens, migrating CSS, or doing anything related to this component library. Use this before writing any component code. Enforce the token-first design system: prioritize `packages/lib/src/styles/tokens.css`, follow the simplified CSS-variable usage pattern from `packages/lib/src/components/display/card/card.css`, derive component tokens from base tokens with `calc()`, avoid two-level variable alias/fallback chains, never use `color-mix()`, prefer broadly supported `hsla()` color tokens, and preserve the shadcn/ui mindset of semantic tokens that are easy to theme rather than hardcoded values.
Installation
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
always use this skill when creating new components, modifying existing components, adding styling, working with design tokens, migrating CSS, or doing anything related to this component library. Use this before writing any component code. Enforce the token-first design system: prioritize `packages/lib/src/styles/tokens.css`, follow the simplified CSS-variable usage pattern from `packages/lib/src/components/display/card/card.css`, derive component tokens from base tokens with `calc()`, avoid two-level variable alias/fallback chains, never use `color-mix()`, prefer broadly supported `hsla()` color tokens, and preserve the shadcn/ui mindset of semantic tokens that are easy to theme rather than hardcoded values.
Design System Guidelines
Enforce design system rules and best practices for the components library.
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
CSS Mental Model
The library styling contract has four layers. Keep them separate:
Component TSX emits stable semantic classes — use defineComponentStyles() from *.styles.ts for the base class and variants, and explicit slot classes such as __button__icon, __checkbox__control, or __input-field__error-text.
Component CSS owns visual implementation — styles live in *.css files and target stable selectors. Do not encode visual rules as long utility strings in TSX.
Design tokens are CSS variables — component CSS reads tokens with var(...); changing a token must update the component live without changing classes.
Manifests/docs describe the public contract — when selectors, variants, slots, or dependencies change, update the style sidecar/docs/manifest source so agents and tools can discover the contract.
Stable selector rules
Public class contract: __component, __component--variant-value, __component__slot.
Never add or preserve generated migration classes like __form-input-field__tw-17, __component__tw-extra-1, or __component__tw-state-1.
Rename generated classes to semantic slots based on purpose, not source order (__radiobox__control-state, not tw-state-1).
Shared selectors must target stable component roots/slots. Do not make new CSS depend on another component's generated tw-* hook.
TSX class names should be small and structural: base + variants + slots + user className. Put visual declarations in CSS.
Token customization model
Component defaults are defined in packages/lib/src/styles/components.ts and emitted as CSS custom properties.
New handwritten v6 CSS should prefer the --var-* token namespace when available (for example --var-button-height, --var-color-primary, --var-rounded-full). Some legacy chunks still read direct component variables such as --radiobox-size; preserve those until the component is migrated.
Component demos/token editors should override CSS variables on a wrapper or theme scope so changes apply in real time:
Consumer apps customize globally through theme objects + createTokenStyles()/createCssProperties(), and locally through scoped CSS variable overrides. Do not customize by reaching into generated classes or hardcoding Tailwind utilities.
Design Token Rules
Token source of truth
Treat packages/lib/src/styles/tokens.css as the base token source for new CSS. Component CSS should consume a single semantic --var-* token when the value is component-specific, or consume a global semantic/base token directly when the component does not need its own meaning. Derive component sizes from base tokens with calc() instead of inventing new literal values.
No two-level variable aliases. Do not define a component token whose value is only a fallback/alias to another token, then consume that alias in CSS. For example, avoid --var-card-border-color: var(--var-card-border, var(--var-color-border)) if the component can read --var-color-border directly. Avoid --var-input-padding: var(--var-input-spacing, var(--var-spacing)) if the component can read --var-spacing directly.
Component tokens must earn their name. Create --var-component-slot-property only when the value represents a real semantic part of the component/DOM, or when consumers should customize that part independently. Otherwise use the global semantic/base token directly.
Derived component tokens use base-token math. Prefer --var-card-title-padding-block-end: calc(var(--var-spacing-base) / 2) over literal deltas like 0.5rem.
CSS usage stays shallow. Component CSS should read one variable per declaration (padding-inline: var(--var-card-padding-inline);) instead of nested fallback chains.
Legacy fallbacks are temporary migration code. If an existing component still needs old --component-* support, keep that compatibility close to the old CSS while migrating, but do not introduce new alias/fallback chains in tokens.css.
Avoid modern color-computation functions. Never use color-mix() in tokens or component CSS. Prefer explicit semantic color tokens whose default values are broadly supported hsla(...) colors.
Literal values are allowed only when they represent browser primitives, structural resets, math constants, or token primitive defaults (0, 1, 100%, transparent, currentColor, inherit, none, linear, hsla(...), etc.).
Shadcn-style semantic token mindset
Follow the shadcn/ui token philosophy without copying names blindly: components should depend on semantic CSS variables (background, foreground, border, primary, muted, card, button) that can be remapped by themes. Do not bind component intent to raw color families, one-off spacing, or visual adjectives like “blue card” or “large 24px gap.” Prefer tokens that describe role and relationship, then derive variants from those tokens.
Variable names must describe the semantic DOM role, not implementation mechanics or visual coincidence. Prefer --var-card-title-padding-block-end, --var-card-stats-icon-size, and --var-input-field-padding-inline; avoid vague aliases like --var-card-border-color when the semantic value is just the global border, or generic names like --var-input-spacing when the DOM role is input field padding/gap.
Color tokens and legacy browser support
Define color primitives and semantic color tokens as explicit hsla(...) values in tokens.css or theme files. Component CSS should consume those tokens directly with color: var(--var-color-...), background-color: var(--var-...-background), or border-color: var(--var-...-border).
Do not use color-mix(), relative color syntax, oklch(), lab(), or other modern color math for defaults. They make theming harder to reason about and reduce legacy browser compatibility. If a lighter/darker/subtle state is needed, add an explicit semantic token such as --var-alert-danger-background: hsla(...) or reuse an existing token like --var-color-danger-subtle.
Core Rule: NEVER hardcode values
No text-[#fff], rounded-[8px], z-[9999], p-[12px], color: #2563eb, or height: 1rem inside component styling. Use design-token CSS variables or token utilities 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}):
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.
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).
Use card.css as a reference implementation for token migration and fallback order.
Prefer direct global tokens for shared meanings: --var-color-background, --var-color-border, --var-color-primary, --var-color-primary-foreground, --var-shadow-card.
Add --var-card-* tokens only for card-specific DOM semantics such as body gap, title padding, stats icon size, or stats value typography.
Do not create card aliases like --var-card-border-color: var(--var-card-border, var(--var-color-border)); use --var-color-border directly in card.css unless card border needs independent semantics.
Derive secondary card metrics with calc(var(--var-spacing-base) / 2) or similar base-token math.
DO NOT add custom rounded-*, p-*, shadow-*, border-* overrides.
Tailwind-era token utilities, when present in TSX examples, should map to card tokens: rounded-card-radius, shadow-shadow-card, border-card-border, bg-card-background.