import { colorTokens, defaultTheme, defaultMotionAccessibility, defaultMotionPack, motionTokens, motionAccessibilityDetails, motionPackDetails, radiusTokens, shadowTokens, themeDetails, themeNames, typographyTokens, type MotionAccessibilityName, type MotionPackName, type ThemeName } from "@ai-ui/tokens"; import type { Meta, StoryObj } from "@storybook/react"; type TokensOverviewProps = { motionAccessibility: MotionAccessibilityName; motionPack: MotionPackName; theme: ThemeName; }; function ResolvedTokenValue({ cssVar }: { cssVar: string }) { const value = typeof document === "undefined" ? "" : getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim(); return {value || cssVar}; } function TokenSwatch({ cssVar, name, role }: { cssVar: string; name: string; role: string; }) { return (
); } function ThemeCard({ themeName }: { themeName: ThemeName }) { const theme = themeDetails[themeName]; return (

{theme.label}

{theme.note}

{themeName}
); } function TokensOverview({ motionAccessibility, motionPack, theme }: TokensOverviewProps) { return (

AI UI / Phase 1

The first stable token layer defines color, type, surface depth, and motion rhythm.

Theme switching now happens at the token layer, not inside component implementations. Motion is also represented as named tokens and starter recipes rather than ad hoc transition values.

Active Theme

{themeDetails[theme].label}

Motion Pack

{motionPackDetails[motionPack].label}

Accessibility Override

{motionAccessibilityDetails[motionAccessibility].label}

Theme scaffolds

These cards render their own nested theme roots, so tokens can be validated side by side without touching component code.

{themeNames.map((themeName) => ( ))}

Color roles

Semantic color tokens replace hardcoded brand values. Components consume roles such as primary, muted, destructive, or surface.

{colorTokens.map((token) => ( ))}

Typography scale

The system now separates display voice, body readability, and metadata density into named text roles.

{typographyTokens.map((token) => (
{token.name} {token.fontVar} {token.familyVar}

{token.sample}

))}

Radius scale

{radiusTokens.map((token) => (

{token.name}

{token.cssVar}
))}

Shadow scale

{shadowTokens.map((token) => (

{token.name}

{token.cssVar}
))}

Motion tokens

Timing and motion scale now live in variables that components can consume directly. The toolbar now separates the active motion pack from the accessibility override.

Durations

{motionTokens.durations.map((token) => (
{token.name}
))}

Distances

{motionTokens.distances.map((token) => (
{token.name}
))}

Starter recipes

`motion.css` now includes a small recipe layer for transitions, press feedback, enters, and overlays.

{[ "motion-transition", "motion-pressable", "motion-enter-fade", "motion-enter-rise", "motion-overlay-enter", "motion-overlay-exit" ].map((recipe) => (
{recipe} recipe
))}
); } const meta = { title: "Foundation/Tokens", component: TokensOverview, parameters: { layout: "fullscreen" } } satisfies Meta; export default meta; type Story = StoryObj; export const Overview: Story = { args: { motionAccessibility: defaultMotionAccessibility, motionPack: defaultMotionPack, theme: defaultTheme }, render: (_args, context) => ( ) };