{"owner":"heroui-inc","repo":"heroui","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nInstructions for AI agents working with the HeroUI v3 repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with **Tailwind CSS v4**, organized as a **pnpm monorepo** managed by **Turborepo**. Components are built on top of [React Aria Components](https://react-spectrum.adobe.com/react-aria/) and follow a compound component pattern similar to Radix UI.\n\n### Tech Stack\n\n| Technology | Version | Purpose |\n|---|---|---|\n| Node.js | 22+ | Runtime |\n| pnpm | 10.26.2 | Package manager (via corepack) |\n| React | 19+ | UI framework |\n| Tailwind CSS | 4.x | Styling |\n| TypeScript | 5.x | Type safety |\n| Turborepo | 2.x | Build orchestration |\n| Storybook | Latest | Component development |\n| Vitest | 4.x | Testing |\n| React Aria Components | Latest | Accessibility primitives |\n| tailwind-variants | Latest | Variant-based styling (includes twMerge) |\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/              # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/             # Main UI library (@heroui/react)\n│   │   ├── src/components/  # All components\n│   │   ├── src/utils/       # Shared utilities\n│   │   └── scripts/         # Build & codegen scripts\n│   ├── styles/            # CSS styles & variants (@heroui/styles)\n│   │   └── src/components/  # Per-component .css files\n│   ├── standard/          # Shared ESLint, Prettier, TS configs\n│   ├── storybook/         # Storybook configuration\n│   └── testing/           # Shared test harness (@heroui/testing)\n├── turbo.json\n└── pnpm-workspace.yaml\n```\n\n## Commands\n\n| Action | Command |\n|---|---|\n| Install dependencies | `pnpm i --hoist` |\n| Build all packages | `pnpm build` |\n| Build specific package | `pnpm build --filter=@heroui/react` |\n| Dev (Storybook, port 6006) | `pnpm dev` |\n| Dev (Docs site, port 3000) | `pnpm dev:docs` |\n| Lint | `pnpm lint` |\n| Typecheck | `pnpm typecheck` |\n| Test all (jsdom + browser) | `pnpm test` |\n| Test one file (filter) | `pnpm --filter @heroui/react exec vitest run button` |\n| Test with coverage | `pnpm test:coverage` (jsdom floors only — not “done”) |\n| Test changed files (local) | `pnpm --filter @heroui/react test:changed` (jsdom only; not a gate) |\n| Format | `pnpm run format` |\n| Bump version | `pnpm version:bump` |\n| Scaffold a new component | `cd packages/react && pnpm add:component ComponentName` |\n\n## Behavioral tests (`@heroui/react`)\n\n- Suites live in `packages/react/tests/components/<name>/`:\n  - `*.test.tsx` — jsdom (~90% of contracts)\n  - `*.ssr.test.tsx` — Client SSR smoke via `ssrSmoke()` (not RSC)\n  - `*.browser.test.tsx` — Playwright (overlays + high-risk portals; not every component)\n  - optional `fixtures.tsx` — shared JSX across layers\n- Import harness from `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`). Browser suites: `render` from `@heroui/testing/browser` (wraps `vitest-browser-react`; owned by `@heroui/testing`). Prefer `@/` for sources. Pattern testers: `const user = new User(...); user.createTester(...)` — not a top-level export.\n- Query: `getByRole` / label / text first; `data-testid` when needed; avoid class-primary queries.\n- Assert: roles/names, HeroUI `data-*` hooks, callbacks, focus, light BEM + documented `data-slot` on compound parts — not colors, full class lists, or RAC internals.\n- Fake timers: per-suite only; wire `advanceTimers` into `setupUser` + `User`; use `runAllTimers()`.\n- Pattern testers for groups / overlays / collections; skip for Button / Checkbox / Switch / TextField.\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`.\n- Intentional skips (no dedicated suite required): internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, `menu-section`, `list-box-section`), Toast SSR (client portal only — covered by jsdom + browser). Public `input-group` has its own suite. SSR and browser are risk-based, not universal.\n- Browser setup (once locally): `pnpm --filter @heroui/testing exec playwright install chromium` before `pnpm test`. CI uses `playwright install --with-deps chromium`, then `test:browser` + `test:coverage` (not a single `pnpm test`).\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`.\n- Coverage (`pnpm test:coverage`): jsdom only; `src/components/**` minus barrels. Thresholds are **CI floors** (statements/lines can pass with thin smoke). Green coverage ≠ sufficient depth — still require role/callback/focus (and browser for high-risk portals).\n- `test:changed`: local jsdom-only shortcut (`vitest related --changed`). Does **not** run browser suites; never use it as the merge gate — use `pnpm test` / CI.\n\n## Git Commit Convention\n\nAll commits must follow [Conventional Commits](https://www.conventionalcommits.org/) and are validated by Husky + commitlint. Pre-commit also runs `lint-staged`.\n\n```\n<type>(<scope>): <message>\n```\n\n**Allowed types:** `feat`, `feature`, `fix`, `refactor`, `docs`, `build`, `test`, `ci`, `chore`\n\nExamples:\n\n```\nfeat(components): add select component\nfix(button): resolve disabled state not applying\ndocs: update installation guide\n```\n\n## Component Architecture\n\n### File Structure\n\nEach component lives in `packages/react/src/components/<component-name>/`:\n\n```\ncomponent-name/\n├── component-name.tsx          # Component implementation (uses React Aria)\n├── component-name.styles.ts    # Tailwind Variants styling\n├── component-name.stories.tsx  # Storybook stories\n└── index.ts                    # Barrel exports\n```\n\nCSS styles live in `packages/styles/src/components/<component-name>/`.\n\n### Creating a New Component\n\nAlways use the scaffold script:\n\n```bash\ncd packages/react\npnpm add:component ComponentName\n```\n\nThen build to update package.json exports:\n\n```bash\npnpm build\n```\n\n### Compound Component Pattern\n\nHeroUI uses a compound component pattern. Each component exports its sub-parts so users can compose and style them independently.\n\n```tsx\n// Context shares state/styles across parts\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root wraps children with context\nconst ComponentRoot = forwardRef(({children, className, ...props}, ref) => {\n  const slots = useMemo(() => componentVariants({...}), [...]);\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaPrimitive>\n    </ComponentContext>\n  );\n});\n\n// Child parts consume context\nconst ComponentItem = forwardRef(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n  return (\n    <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaPrimitive>\n  );\n});\n```\n\nCompound components are exported via `Object.assign` as the default export:\n\n```tsx\nconst CompoundComponent = Object.assign(ComponentRoot, {\n  Item: ComponentItem,\n  Trigger: ComponentTrigger,\n});\nexport default CompoundComponent;\n```\n\n### Export Strategy\n\n```tsx\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n### Styling Rules\n\n1. **Styles go in `.styles.ts` files**, never in `.tsx` files. Use `tv()` from `tailwind-variants`.\n2. **Import from `tailwind-variants`**, never from `@heroui/standard`.\n3. **Never use `twMerge` manually** — `tailwind-variants` already includes it.\n4. **Add `\"use client\"` directive** at the top of every component `.tsx` file.\n5. **Display names** follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`.\n\n### CSS / BEM Naming\n\nComponents use BEM-style CSS class names:\n\n- **Block**: `button`, `card`, `alert`\n- **Element**: `card__header`, `alert__icon`\n- **Modifier**: `button--primary`, `button--lg`, `button--icon-only`\n\n### Default Size Pattern (Critical)\n\nAll components must include default sizes in base classes so they work without explicit size props:\n\n```css\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default (equivalent to --md) */\n}\n\n.avatar--sm { @apply size-8; }\n.avatar--md { /* empty — this IS the default */ }\n.avatar--lg { @apply size-12; }\n```\n\n### Interactive State Pattern\n\nAll interactive components must support both pseudo-classes and data attributes:\n\n```css\n.component {\n  &:hover,\n  &[data-hovered=\"true\"] { @apply ...; }\n\n  &:active,\n  &[data-pressed=\"true\"] { @apply ...; }\n\n  &:focus-visible,\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n### React Aria className Patterns\n\nReact Aria components differ in how they accept `className`:\n\n- **Render-prop components** (Button, Checkbox, Switch, Popover, Tooltip, Tabs, Link, Menu, etc.) — use `composeTwRenderProps(className, slots.foo())`.\n- **String-only components** (Label, Text, Input, TextArea, Heading, Dialog) — pass `className` directly: `slots?.label({className})`.\n\n### Composition Over Duplication\n\nDo **not** create component-specific Label/Description/FieldError sub-components. Instead, compose with the existing shared primitives:\n\n```tsx\nimport {Label} from \"@/components/label\";\nimport {Description} from \"@/components/description\";\n\n<div className=\"flex items-center gap-3\">\n  <Checkbox id=\"terms\"><Checkbox.Indicator /></Checkbox>\n  <Label htmlFor=\"terms\">Accept terms</Label>\n</div>\n```\n\n### Tailwind Class Detection\n\nTailwind CSS scans files as plain text. **Never construct class names dynamically**:\n\n```tsx\n// BAD — Tailwind won't detect this\n<div className={`text-${color}-600`} />\n<span className={`button--${size}`} />\n\n// GOOD — use complete class name mappings\nconst colorClasses = {\n  blue: \"text-blue-600\",\n  red: \"text-red-600\",\n};\n```\n\n### Storybook\n\nAll stories must use the `\"Components\"` group in their title:\n\n```tsx\nexport default { title: \"Components/Button\" };\n```\n\nStorybook is the primary dev workflow — run with `pnpm dev` (port 6006).\n\n### Icon Library\n\nHeroUI uses **Iconify** with **gravity-ui** as the default icon set.\n\n## Current Components\n\n### Completed\n\naccordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n### In Progress\n\ncalendar-year-picker\n\n## Non-obvious Gotchas\n\n1. **`pnpm i` triggers builds** — The `postinstall` hook builds `@heroui/styles` and runs `typegen:docs` and `typegen:docs-cn`. If it fails, run `pnpm --filter @heroui/styles build` manually.\n\n2. **Build order matters** — `@heroui/styles` must build before `@heroui/react`. Running `pnpm build` from root handles this via Turbo's `^build` dependency.\n\n3. **Native addons allowlist** — `onlyBuiltDependencies` in root `pnpm-workspace.yaml` allows native compilation for `esbuild`, `@swc/core`, `@parcel/watcher`, etc. If this list is missing, you'll see \"Ignored build scripts\" warnings.\n\n4. **Behavioral tests** — see [Behavioral tests](#behavioral-tests-herouireact) above. Harness lives in `@heroui/testing`; suites in `packages/react/tests/`.\n\n5. **Commit hooks** — Husky runs `lint-staged` on pre-commit and `commitlint` on commit-msg. Non-conforming commits are rejected.\n\n6. **Run checks before committing** — `pnpm lint && pnpm typecheck && pnpm test`\n\n## Cursor Cloud Specific\n\n- **Node.js v22+** is installed via binary tarball to `/usr/local/`.\n- **pnpm** is activated via `corepack` — the `packageManager` field in root `package.json` declares `pnpm@10.26.2`.\n- Full command reference and component architecture details are also in `CLAUDE.md`.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with Tailwind CSS v4, using a pnpm monorepo structure managed by Turborepo.\n\n### Key Technical Stack\n\n- **Node.js**: v22+ required\n- **pnpm**: v10.26.2 (package manager)\n- **React**: v19+\n- **Tailwind CSS**: v4.1.18\n- **TypeScript**: v5.9.3\n- **Turborepo**: Build orchestration\n- **Storybook**: Component development\n- **Vitest**: Testing framework\n\n## Development Commands\n\n### Core Development Commands\n\n```bash\n# Install dependencies (use --hoist flag)\npnpm i --hoist\n\n# Start Storybook for component development\npnpm dev\n\n# Start documentation site\npnpm dev:docs\n\n# Build all packages\npnpm build\n\n# Build specific package\npnpm build --filter=@heroui/react\n\n# Run linting\npnpm lint\n\n# Run tests (turbo → packages with a test script; jsdom + browser)\npnpm test\n\n# Filter by file name (e.g. button.test.tsx)\npnpm --filter @heroui/react exec vitest run button\n\n# Coverage (jsdom floors only — not a depth bar)\npnpm test:coverage\n\n# Changed-set (local jsdom only; not a merge gate)\npnpm --filter @heroui/react test:changed\n\n# Run formatting\npnpm run format\n\n# Run type checking\npnpm typecheck\n```\n\n### Behavioral tests (`@heroui/react`)\n\n- Suites: `packages/react/tests/components/<name>/` — `*.test.tsx` (jsdom), `*.ssr.test.tsx` (Client SSR via `ssrSmoke()`, not RSC), `*.browser.test.tsx` (Playwright for high-risk portals/overlays; not universal), optional `fixtures.tsx`\n- Harness: `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`); browser `render` from `@heroui/testing/browser`. Sources via `@/`. Pattern testers: `user.createTester(...)` — do not import `createTester` directly\n- Query/assert: role/label/text first; HeroUI `data-*` + light BEM + documented `data-slot` on compound parts; no colors, full class lists, or RAC internals\n- Timers: fake timers per-suite only; wire `advanceTimers` into `setupUser` + `User`\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`\n- Intentional skips: internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, …), Toast SSR (client portal — jsdom + browser). Public `input-group` has its own suite. SSR/browser are risk-based\n- Browser setup (once locally): `playwright install chromium` before `pnpm test`. CI: `--with-deps`, then `test:browser` + `test:coverage`\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`\n- Coverage: jsdom-only floors — green ≠ depth. `test:changed`: local jsdom shortcut only, not a merge gate\n\n### Package-Specific Commands\n\n- Use `--filter` flag with package name: `pnpm build --filter=@heroui/react`\n- Main packages: `@heroui/react`, `@heroui/styles`, `@heroui/docs`, `@heroui/storybook`\n\n## Git Commit Convention\n\n**IMPORTANT**: This repository uses conventional commits with strict validation. All commits must follow this format:\n\n```\n<type>(<scope>): <message>\n```\n\n### Allowed Types:\n\n- `feat` / `feature`: New features\n- `fix`: Bug fixes\n- `refactor`: Code refactoring\n- `docs`: Documentation changes\n- `build`: Build system changes\n- `test`: Test changes\n- `ci`: CI configuration changes\n- `chore`: Other changes\n\n### Examples:\n\n```bash\ngit commit -m \"feat(components): add new prop to avatar component\"\ngit commit -m \"fix(button): resolve click handler issue\"\ngit commit -m \"docs: update installation guide\"\ngit commit -m \"ci: add Claude Code GitHub Action workflow\"\n```\n\n**Note**: Commits without proper format will be rejected by git hooks.\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/          # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/         # Main UI component library (@heroui/react)\n│   ├── styles/        # CSS styles & variants (@heroui/styles)\n│   ├── standard/      # Shared ESLint, Prettier, TypeScript configs\n│   ├── storybook/     # Storybook configuration\n│   └── testing/       # Shared test harness (@heroui/testing)\n├── turbo.json         # Turborepo configuration\n└── pnpm-workspace.yaml # Workspace definition\n```\n\n### Component Architecture Pattern\n\nEach component in `packages/react/src/components/` follows this structure:\n\n```\ncomponent-name/\n├── component-name.tsx      # Main component (uses React Aria)\n├── component-name.styles.ts # Tailwind Variants styling\n├── component-name.stories.tsx # Storybook stories (title: \"Components/ComponentName\")\n└── index.ts               # Barrel exports\n```\n\n**IMPORTANT**: All Storybook stories must use the \"Components\" group in their title. For example: `title: \"Components/Card\"`, `title: \"Components/Button\"`, etc.\n\n### CSS Class Naming Convention\n\n**IMPORTANT**: HeroUI v3 uses BEM (Block Element Modifier) style for CSS classes to ensure predictable and maintainable styling:\n\n- **Block**: The main component class (e.g., `button`, `card`, `alert`)\n- **Modifier**: Variations of the component using double dashes (e.g., `button--primary`, `button--lg`, `button--icon-only`)\n- **Element**: Child elements within a component (e.g., `card__header`, `alert__icon`)\n\n**Migration to CSS-based Styling**:\n\n- The `button` component has been migrated to use CSS styles from `@heroui/styles/src/components/button.css`\n- This approach allows for better customization through CSS utilities and `@utility` directives\n- Other components will gradually be migrated to follow this CSS-based pattern\n- Components use `tv()` from `tailwind-variants` to map variant props to BEM class names\n\n**Default Size Pattern**:\n\n**CRITICAL**: All components MUST include default sizes in their base classes to prevent broken appearances when no size modifier is specified. Following the following pattern:\n\n- **Base classes** include default dimensions (equivalent to the `--md` variant)\n- **Medium variants** (`--md`) are empty with explanatory comments\n- **Size modifiers** override the defaults when specified\n\nExample implementation:\n\n```css\n/* Base component with default size */\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default, equivalent to --md */\n}\n\n/* Size variants */\n.avatar--sm {\n  @apply size-8; /* Override default */\n}\n\n.avatar--md {\n  /* No styles as this is the default size */\n}\n\n.avatar--lg {\n  @apply size-12; /* Override default */\n}\n```\n\nThis ensures components work properly without explicit size classes:\n\n- `<div className=\"avatar\">` → Works perfectly (size-10)\n- `<div className=\"avatar avatar--lg\">` → Override to large (size-12)\n\n### Core Component Design Principles\n\n**IMPORTANT**: HeroUI v3 follows a compound component pattern similar to Radix UI, built on top of React Aria Components primitives. This enables maximum flexibility and customization for users.\n\n### React Aria Components Integration\n\n**CRITICAL**: Before implementing any component, you MUST:\n\n1. Visit React Aria Components docs: https://react-spectrum.adobe.com/react-aria/\n2. Study the specific component's API and examples\n3. Understand its accessibility features and ARIA patterns\n4. Plan the transformation from React Aria's prop-based API to Radix UI's composition-based API\n\nReact Aria provides the accessibility foundation, but we transform their API to match Radix UI's compound component pattern for better customization.\n\n#### 1. **Compound Component Pattern**:\n\n- Export all internal component pieces (Root, Item, Trigger, Content, etc.)\n- Each piece can be styled and composed independently\n- Users can customize render logic without accessing internal code\n- Examples: Accordion (Root, Item, Heading, Trigger, Panel, Indicator, Body), Alert (Root, Icon, Title, Description, Action, Close)\n\n#### 2. **Export Strategy**:\n\n```typescript\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n#### 3. **Component Structure for Compound Components**:\n\n```typescript\n// Context for sharing state/styles\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root component wraps with context\nconst ComponentRoot = React.forwardRef<...>(({children, className, ...props}, ref) => {\n  const slots = React.useMemo(() => componentVariants({...}), [...]);\n\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaComponent>\n    </ComponentContext>\n  );\n});\n\n// Child components consume context\nconst ComponentItem = React.forwardRef<...>(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n\n  return (\n    <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaComponent>\n  );\n});\n\n// Export pattern\nexport {ComponentRoot as Root, ComponentItem as Item, ...};\n```\n\n#### 4. **Key Implementation Details**:\n\n1. **Styling with Tailwind Variants**:\n   - Styles defined in `.styles.ts` files using `tv()` function from `tailwind-variants`\n   - **IMPORTANT**: Always import from `tailwind-variants`, never from `@heroui/standard` (which doesn't exist)\n   - **CRITICAL**: tailwind-variants already includes `twMerge` functionality, so NEVER manually use `twMerge`\n   - **RULE**: All component styles MUST be defined in separate `.styles.ts` files, NOT in the component implementation files\n   - Component implementation files (`.tsx`) should only contain logic and React Aria primitives\n   - Example imports:\n     ```typescript\n     import type {VariantProps} from \"tailwind-variants\";\n     import {tv} from \"tailwind-variants\";\n     ```\n   - Support for variants (primary, secondary, etc.)\n   - Compound variants for conditional styling\n   - Slot system for complex components\n\n2. **Component Features**:\n   - Built on React Aria Components for accessibility\n   - Use `forwardRef` for all components\n   - Display names follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`\n   - Support render props from React Aria when available\n\n3. **Type Exports**:\n\n   ```typescript\n   // Export props for each component part\n   export type ComponentRootProps = {...}\n   export type ComponentItemProps = {...}\n   export type ComponentVariants = VariantProps<typeof componentVariants>\n   ```\n\n4. **Utilities** (`packages/react/src/utils/`):\n   - `composeTwRenderProps`: Merge Tailwind classes with render props\n   - `focusRingClasses`: Consistent focus styling\n   - `disabledClasses`: Disabled state styling\n   - `mapPropsVariants`: Separate variant props from component props\n\n5. **React Aria Components className Patterns**:\n\n   **CRITICAL**: React Aria components have different className prop behaviors:\n\n   **Components that support render props** (use `composeTwRenderProps`):\n   - Button, TextField, FieldError, Checkbox, CheckboxGroup\n   - Switch, RadioGroup, Radio, Slider (and Track, Thumb, Output)\n   - Popover, Tooltip, Tabs (and Tab, TabList, TabPanel)\n   - Link, Menu, MenuItem, Accordion (DisclosureGroup)\n\n   **Components that ONLY accept string className** (pass className directly):\n   - Label, Text, Input, TextArea\n   - Heading, Dialog, OverlayArrow\n\n   **Usage examples**:\n\n   ```typescript\n   // For render prop components - use composeTwRenderProps\n   <ButtonPrimitive\n     className={composeTwRenderProps(className, slots?.button())}\n   />\n\n   // For string-only components - pass className directly\n   <LabelPrimitive\n     className={slots?.label({className})}\n   />\n   // OR\n   <LabelPrimitive\n     className={labelVariants({size, variant, className})}\n   />\n   ```\n\n   **How to check**: If unsure, check the React Aria docs or try both approaches - TypeScript will error if a component doesn't support render props\n\n6. **Composition Pattern with Existing Components**:\n\n   **CRITICAL**: HeroUI follows a composition-based approach. Components should reuse existing primitives rather than creating component-specific versions.\n\n   **Key Principles**:\n   - **DO NOT** create component-specific Label, Description, or FieldError components\n   - **DO** reuse the existing `Label`, `Description`, and `FieldError` components\n   - **DO** use standard HTML composition patterns with `htmlFor`/`id` attributes\n\n   **Example Pattern**:\n\n   ```typescript\n   // ❌ WRONG - Component-specific label\n   export const Checkbox = {\n     Root: CheckboxRoot,\n     Label: CheckboxLabel, // Don't create this!\n   };\n\n   // ✅ CORRECT - Compose with existing components\n   import { Label } from \"@/components/label\";\n   import { Description } from \"@/components/description\";\n\n   // Usage:\n   <div className=\"flex items-center gap-3\">\n     <Checkbox id=\"terms\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <Label htmlFor=\"terms\">Accept terms</Label>\n   </div>\n\n   // With description:\n   <div className=\"flex gap-3\">\n     <Checkbox className=\"mt-0.5\" id=\"notifications\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <div className=\"flex flex-col gap-1\">\n       <Label htmlFor=\"notifications\">Email notifications</Label>\n       <Description>Get notified when someone mentions you</Description>\n     </div>\n   </div>\n   ```\n\n   **Components that follow this pattern**:\n   - Checkbox - uses external Label/Description\n   - Radio - uses external Label/Description\n   - Switch - uses external Label/Description\n   - TextField - provides slots for Label/Description/FieldError\n\n### Current Components\n\n**Completed**: accordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n**In Progress**: calendar-year-picker\n\n> Source of truth: `packages/react/src/components/index.ts`.\n\n## Development Workflow\n\n### Standard Feature Development Process\n\n**IMPORTANT**: When working on any feature or improvement, Claude Code MUST follow this systematic workflow to ensure accuracy and code quality:\n\n1. **Research Phase**:\n   - Thoroughly research the feature/component requirements\n   - Study relevant documentation (React Aria, Tailwind CSS, etc.)\n   - Analyze existing similar implementations in the codebase\n   - Identify all dependencies and integration points\n\n2. **Planning Phase**:\n   - Create a detailed implementation plan with a comprehensive checklist\n   - Break down the task into specific, measurable steps\n   - Include testing and verification steps in the plan\n   - Present the plan for review before proceeding\n\n3. **Review & Correction Phase**:\n   - Review the plan for completeness and accuracy\n   - Make necessary corrections or adjustments\n   - Ensure all edge cases are considered\n   - Confirm the plan aligns with HeroUI patterns and conventions\n\n4. **Execution Phase**:\n   - Start executing the plan step by step\n   - Use the TodoWrite tool to track progress automatically\n   - Mark todos as in_progress when starting a task\n   - Mark todos as completed immediately after finishing each step\n   - Never batch completions - update status in real-time\n\n5. **Verification Phase**:\n   - Manually verify all changes work as expected\n   - Test API calls if backend changes were made\n   - Check frontend rendering and interactions\n   - Run lint and type checks: `pnpm lint && pnpm typecheck`\n   - Ensure all tests pass: `pnpm test`\n\n**Example Workflow**:\n\n```\nUser: \"Add a new Select component\"\n\nClaude:\n1. Research: Studies React Aria Select, existing patterns\n2. Plan: Creates detailed checklist with 15+ items\n3. Review: Presents plan for feedback\n4. Execute: Implements step-by-step with todo updates\n5. Verify: Tests component, runs checks, confirms functionality\n```\n\nThis workflow ensures thorough understanding, proper planning, and high-quality implementation with full transparency throughout the process.\n\n### Component Development Workflow\n\n1. **Creating New Components**:\n\n   **CRITICAL: Research & Design Phase**:\n   - **FIRST**: Check the Figma design for the component breakdown (e.g., Menu Container, Menu Item, etc.)\n   - **SECOND**: Research the React Aria Components documentation at https://react-spectrum.adobe.com/react-aria/\n   - Find the appropriate React Aria primitive (e.g., CheckboxGroup, Dialog, Select, etc.)\n   - Understand the React Aria API, props, and accessibility features\n   - Map Figma component pieces to React Aria components and plan the compound structure\n   - Plan how to adapt it to follow Radix UI's compound component pattern\n\n   **Component Creation - ALWAYS USE THE SCRIPT**:\n\n   ```bash\n   # Navigate to packages/react directory\n   cd packages/react\n\n   # Use the add:component script\n   pnpm add:component ComponentName\n\n   # Examples:\n   pnpm add:component Menu\n   pnpm add:component Select\n   pnpm add:component DatePicker\n   ```\n\n   This script will:\n   - Create all necessary files with proper structure\n   - Add the export to `src/components/index.ts`\n   - Generate boilerplate following HeroUI patterns\n   - Set up the component with TypeScript and proper exports\n\n   After creating the component:\n\n   ```bash\n   # Build to update package.json exports automatically\n   pnpm build\n   ```\n\n   **Implementation Steps**:\n   - Study existing HeroUI components (accordion, alert) to understand the compound pattern\n   - Use React Aria Components as the foundation for accessibility\n   - Transform React Aria's API to match Radix UI patterns:\n     - Single component → Multiple exported parts (Item, Trigger, Content, etc.)\n     - Props-based API → Composition-based API\n     - Internal state → Context-based state sharing\n   - Create Context for sharing styles across component parts\n   - Export ALL component parts for maximum customization\n   - Define styles in separate `.styles.ts` file with slot system\n   - Add \"use client\" directive at the top of component file\n   - Create comprehensive Storybook stories showing all variants and compositions\n   - Follow the export pattern: `export * as ComponentName from \"./component-name\"`\n\n   **Example Transformation**:\n\n   ```typescript\n   // React Aria: Single component with props\n   <CheckboxGroup label=\"Options\" value={selected} onChange={setSelected}>\n     <Checkbox value=\"1\">Option 1</Checkbox>\n   </CheckboxGroup>\n\n   // HeroUI: Compound pattern\n   <CheckboxGroup value={selected} onValueChange={setSelected}>\n     <CheckboxGroup.Label>Options</CheckboxGroup.Label>\n     <CheckboxGroup.Item value=\"1\">\n       <CheckboxGroup.Indicator />\n       <CheckboxGroup.Label>Option 1</CheckboxGroup.Label>\n     </CheckboxGroup.Item>\n   </CheckboxGroup>\n   ```\n\n   **Example of a compound component exports**\n\n   ```typescript\n   const CompoundAccordion = Object.assign(Accordion, {\n     Item: AccordionItem,\n     Heading: AccordionHeading,\n     Trigger: AccordionTrigger,\n     Panel: AccordionPanel,\n     Indicator: AccordionIndicator,\n     Body: AccordionBody,\n   });\n\n   export type {\n     AccordionProps,\n     AccordionItemProps,\n     AccordionTriggerProps,\n     AccordionPanelProps,\n     AccordionIndicatorProps,\n     AccordionBodyProps,\n   };\n\n   export default CompoundAccordion;\n   ```\n\n   **IMPORTANT**: The compound component should be exported as the default export.\n\n2. **Testing**:\n   - Follow Behavioral tests conventions above (semantics-first, `setupUser`, `data-*` state hooks)\n   - Run `pnpm test` for jsdom + browser; filter with `pnpm --filter @heroui/react exec vitest run <name>`\n   - Place tests under `packages/react/tests/components/<name>/` (`*.test.tsx` / `*.ssr.test.tsx` / `*.browser.test.tsx`, optional `fixtures.tsx`)\n   - Prefer arrow functions for harness helpers and test fixtures\n\n3. **Documentation**:\n   - Docs live in `apps/docs/content/`\n   - Uses MDX format\n   - HeroUI components are pre-imported\n\n4. **Version Management**:\n   - Uses [bumpp](https://github.com/antfu/bumpp) for version bumping\n   - Run `pnpm version:bump` to interactively bump the version, commit, and tag\n   - Pushing a `v*` tag triggers the release CI workflow\n   - Follow semantic versioning\n\n## Icon Library\n\n**IMPORTANT**: HeroUI uses Iconify with gravity-ui as the default icon set.\n\n## Important Notes\n\n- Always prefer editing existing files over creating new ones\n- **NEVER** create documentation files (_.md, _.mdx, README files) unless explicitly requested by the user\n- Follow the established component patterns and conventions\n- Ensure accessibility with React Aria Components\n- Maintain TypeScript type safety\n- Use the commit convention to avoid git hook failures\n- Run lint and type checks before committing: `pnpm lint && pnpm typecheck`\n\n## Tailwind CSS Class Detection Rules\n\n**CRITICAL**: Tailwind CSS scans files as plain text and requires complete class names to be statically detectable.\n\n### Key Rules:\n\n1. **Never construct class names dynamically**\n\n   ❌ **BAD** - Dynamic string concatenation:\n\n   ```jsx\n   // These patterns will NOT work:\n   <div className={`text-${color}-600`} />\n   <button className={`bg-${variant}-500`} />\n   <span className={`button--${size}`} />\n   ```\n\n   ✅ **GOOD** - Complete class names:\n\n   ```jsx\n   // Use complete strings or object mappings:\n   <div className={error ? \"text-red-600\" : \"text-green-600\"} />\n   ```\n\n2. **Use object mappings for dynamic classes**\n\n   ❌ **BAD** - Props in template literals:\n\n   ```jsx\n   function Button({color}) {\n     return <button className={`bg-${color}-600 hover:bg-${color}-500`} />;\n   }\n   ```\n\n   ✅ **GOOD** - Map props to complete classes:\n\n   ```jsx\n   function Button({color}) {\n     const colorVariants = {\n       blue: \"bg-blue-600 hover:bg-blue-500\",\n       red: \"bg-red-600 hover:bg-red-500\",\n     };\n     return <button className={colorVariants[color]} />;\n   }\n   ```\n\n3. **For BEM-style classes, use complete mappings**\n\n   ✅ **GOOD** - Complete class name mappings:\n\n   ```jsx\n   const sizeClasses = {\n     sm: \"button--sm\",\n     md: \"button--md\",\n     lg: \"button--lg\",\n   };\n\n   // Use the mapping:\n   className={sizeClasses[size]}\n   ```\n\n### Why This Matters:\n\n- Tailwind generates CSS only for classes it can detect in your source files\n- Dynamic concatenation prevents Tailwind from finding the complete class names\n- Missing classes = missing styles in production\n\n## Figma Integration & MCP Server Rules\n\n### Figma Dev Mode MCP Server\n\n**IMPORTANT**: When creating components with Figma designs:\n\n1. **Component Breakdown**: Figma designs are already broken down into component pieces (e.g., Menu Container, Menu Item, etc.). Use these as reference for:\n   - Component structure and naming (adapt to code conventions)\n   - Visual styling and spacing\n   - Component composition patterns\n\n2. **MCP Server Rules**:\n   - The Figma Dev Mode MCP Server provides an assets endpoint for images and SVG assets\n   - **CRITICAL**: If the Figma MCP Server returns a localhost source for an image or SVG, use that source directly\n   - **DO NOT** import or add new icon packages - all assets should come from the Figma payload\n   - **DO NOT** use or create placeholders if a localhost source is provided\n   - Always use the actual assets from Figma MCP Server\n\n3. **Workflow**:\n   - Check Figma for component visual design and breakdown\n   - Map Figma component names to appropriate React Aria primitives\n   - Use Figma assets (icons, images) directly from the MCP Server\n   - Implement styles based on Figma design tokens and specifications\n\n## Library Documentation with Context7 MCP\n\n**IMPORTANT**: We have the Context7 MCP server available (https://github.com/upstash/context7) for accessing up-to-date library documentation.\n\n### When to Use Context7\n\nUse Context7 MCP when working with external libraries, especially:\n\n- **Tailwind CSS v4**: When working with Tailwind CSS v4 features, use Context7 to get the latest documentation at https://context7.com/context7/tailwindcss\n- **Fumadocs**: When working on the documentation site in `apps/docs/`, use Context7 to get the latest Fumadocs framework documentation\n- **Next.js**: For Next.js specific features and APIs used in the docs app\n- Any other third-party libraries where up-to-date documentation is needed\n\n### How to Use Context7\n\n1. First, resolve the library ID using `mcp__context7__resolve-library-id`\n2. Then fetch documentation using `mcp__context7__get-library-docs` with the resolved ID\n3. This ensures you're always working with the latest documentation rather than outdated information\n\n### Example Usage Areas\n\n- Implementing new documentation features in `apps/docs/`\n- Configuring Fumadocs settings in `source.config.ts`\n- Working with MDX components and layouts\n- Setting up search functionality\n- Implementing documentation navigation and structure\n\n## GitHub Repository Search with Grep MCP\n\n**IMPORTANT**: We have the Grep MCP server available for searching over a million public GitHub repositories to find real-world code examples and patterns.\n\n### When to Use Grep MCP\n\nUse the Grep MCP (`mcp__grep__searchGitHub`) when tackling complex problems that require:\n\n- **Real-world implementation examples**: Finding how other developers solve similar problems\n- **Best practices and patterns**: Discovering production-ready code patterns\n- **Library usage examples**: Understanding how specific APIs or libraries are used in practice\n- **Complex integrations**: Seeing how different libraries work together\n- **Error handling patterns**: Learning from battle-tested error handling approaches\n\n### How to Use Grep MCP\n\nThe Grep MCP searches for **literal code patterns**, not keywords. Use actual code syntax:\n\n**Good examples**:\n\n- `'useState('` - Find React hooks usage\n- `'import { tv } from \"tailwind-variants\"'` - Find tailwind-variants imports\n- `'forwardRef<'` - Find forwardRef usage patterns\n- `'(?s)useEffect\\\\(\\\\(\\\\) => {.*return.*}'` - Find useEffect with cleanup (regex)\n\n**Bad examples**:\n\n- `'react best practices'` - This is a keyword, not code\n- `'how to use tailwind'` - Use actual import statements instead\n\n### Example Use Cases\n\n1. **Complex Component Patterns**:\n   - Search: `'compound.*component'` with language=['TypeScript', 'TSX']\n   - Find how others implement compound component patterns\n\n2. **Accessibility Implementations**:\n   - Search: `'AriaProps'` or `'useAriaLabel'`\n   - Discover accessibility patterns in React apps\n\n3. **Monorepo Configurations**:\n   - Search: `'pnpm-workspace.yaml'` with path='pnpm-workspace.yaml'\n   - Study monorepo setups similar to HeroUI\n\n4. **Tailwind CSS v4 Patterns**:\n   - Search: `'@import \"tailwindcss\"'` with language=['CSS']\n   - Find Tailwind CSS v4 usage patterns\n\n5. **React Aria Components Usage**:\n   - Search: `'from \"react-aria-components\"'`\n   - See how others integrate React Aria Components\n\n### Best Practices\n\n- Use language filters to narrow results (e.g., `language=['TypeScript', 'TSX']`)\n- Use regex patterns with `useRegexp=true` for flexible matching\n- Filter by well-known repositories for quality examples (e.g., `repo='vercel/'`)\n- Combine with file path filters for specific file types\n\n## Agent-Specific Guidelines\n\n### For style-migrator and tailwind-v4-css-expert Agents\n\nWhen working with HeroUI CSS components, follow these critical patterns:\n\n#### Default Size Implementation\n\n**REQUIRED**: All CSS components MUST follow the default size pattern:\n\n1. **Base classes** include default dimensions equivalent to `--md` variant\n2. **Medium variant** (`--md`) is an empty class with explanatory comment\n3. **Size variants** override the base defaults\n\n**Template for CSS components with size variants:**\n\n```css\n/* Base component styles */\n.component {\n  /* Base styling */\n  @apply [base-styles];\n\n  /* Default size - matches component--md variant */\n  @apply [default-size-classes];\n}\n\n/* Size variants */\n.component--sm {\n  @apply [small-size-overrides];\n}\n\n.component--md {\n  /* No styles as this is the default size */\n}\n\n.component--lg {\n  @apply [large-size-overrides];\n}\n```\n\n#### Pseudo-Class Fallback Pattern\n\n**REQUIRED**: All interactive components MUST include both pseudo-class and data-attribute support:\n\n```css\n/* Interactive states - both approaches */\n.component {\n  /* Hover states */\n  &:hover,\n  &[data-hovered=\"true\"] {\n    @apply [hover-styles];\n  }\n\n  /* Active/pressed states */\n  &:active,\n  &[data-pressed=\"true\"] {\n    @apply [active-styles];\n  }\n\n  /* Focus states */\n  &:focus-visible,\n  &:focus:not(:focus-visible),\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n#### Component Examples\n\n- **button.css**: Base has `h-10 md:h-9`, empty `.button--md` variant\n- **avatar.css**: Base has `size-10`, empty `.avatar--md` variant\n- **spinner.css**: Base has `size-6`, empty `.spinner--md` variant\n\nThese patterns ensure components never appear broken and maintain consistency across the design system.\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nInstructions for AI agents working with the HeroUI v3 repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with **Tailwind CSS v4**, organized as a **pnpm monorepo** managed by **Turborepo**. Components are built on top of [React Aria Components](https://react-spectrum.adobe.com/react-aria/) and follow a compound component pattern similar to Radix UI.\n\n### Tech Stack\n\n| Technology | Version | Purpose |\n|---|---|---|\n| Node.js | 22+ | Runtime |\n| pnpm | 10.26.2 | Package manager (via corepack) |\n| React | 19+ | UI framework |\n| Tailwind CSS | 4.x | Styling |\n| TypeScript | 5.x | Type safety |\n| Turborepo | 2.x | Build orchestration |\n| Storybook | Latest | Component development |\n| Vitest | 4.x | Testing |\n| React Aria Components | Latest | Accessibility primitives |\n| tailwind-variants | Latest | Variant-based styling (includes twMerge) |\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/              # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/             # Main UI library (@heroui/react)\n│   │   ├── src/components/  # All components\n│   │   ├── src/utils/       # Shared utilities\n│   │   └── scripts/         # Build & codegen scripts\n│   ├── styles/            # CSS styles & variants (@heroui/styles)\n│   │   └── src/components/  # Per-component .css files\n│   ├── standard/          # Shared ESLint, Prettier, TS configs\n│   ├── storybook/         # Storybook configuration\n│   └── testing/           # Shared test harness (@heroui/testing)\n├── turbo.json\n└── pnpm-workspace.yaml\n```\n\n## Commands\n\n| Action | Command |\n|---|---|\n| Install dependencies | `pnpm i --hoist` |\n| Build all packages | `pnpm build` |\n| Build specific package | `pnpm build --filter=@heroui/react` |\n| Dev (Storybook, port 6006) | `pnpm dev` |\n| Dev (Docs site, port 3000) | `pnpm dev:docs` |\n| Lint | `pnpm lint` |\n| Typecheck | `pnpm typecheck` |\n| Test all (jsdom + browser) | `pnpm test` |\n| Test one file (filter) | `pnpm --filter @heroui/react exec vitest run button` |\n| Test with coverage | `pnpm test:coverage` (jsdom floors only — not “done”) |\n| Test changed files (local) | `pnpm --filter @heroui/react test:changed` (jsdom only; not a gate) |\n| Format | `pnpm run format` |\n| Bump version | `pnpm version:bump` |\n| Scaffold a new component | `cd packages/react && pnpm add:component ComponentName` |\n\n## Behavioral tests (`@heroui/react`)\n\n- Suites live in `packages/react/tests/components/<name>/`:\n  - `*.test.tsx` — jsdom (~90% of contracts)\n  - `*.ssr.test.tsx` — Client SSR smoke via `ssrSmoke()` (not RSC)\n  - `*.browser.test.tsx` — Playwright (overlays + high-risk portals; not every component)\n  - optional `fixtures.tsx` — shared JSX across layers\n- Import harness from `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`). Browser suites: `render` from `@heroui/testing/browser` (wraps `vitest-browser-react`; owned by `@heroui/testing`). Prefer `@/` for sources. Pattern testers: `const user = new User(...); user.createTester(...)` — not a top-level export.\n- Query: `getByRole` / label / text first; `data-testid` when needed; avoid class-primary queries.\n- Assert: roles/names, HeroUI `data-*` hooks, callbacks, focus, light BEM + documented `data-slot` on compound parts — not colors, full class lists, or RAC internals.\n- Fake timers: per-suite only; wire `advanceTimers` into `setupUser` + `User`; use `runAllTimers()`.\n- Pattern testers for groups / overlays / collections; skip for Button / Checkbox / Switch / TextField.\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`.\n- Intentional skips (no dedicated suite required): internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, `menu-section`, `list-box-section`), Toast SSR (client portal only — covered by jsdom + browser). Public `input-group` has its own suite. SSR and browser are risk-based, not universal.\n- Browser setup (once locally): `pnpm --filter @heroui/testing exec playwright install chromium` before `pnpm test`. CI uses `playwright install --with-deps chromium`, then `test:browser` + `test:coverage` (not a single `pnpm test`).\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`.\n- Coverage (`pnpm test:coverage`): jsdom only; `src/components/**` minus barrels. Thresholds are **CI floors** (statements/lines can pass with thin smoke). Green coverage ≠ sufficient depth — still require role/callback/focus (and browser for high-risk portals).\n- `test:changed`: local jsdom-only shortcut (`vitest related --changed`). Does **not** run browser suites; never use it as the merge gate — use `pnpm test` / CI.\n\n## Git Commit Convention\n\nAll commits must follow [Conventional Commits](https://www.conventionalcommits.org/) and are validated by Husky + commitlint. Pre-commit also runs `lint-staged`.\n\n```\n<type>(<scope>): <message>\n```\n\n**Allowed types:** `feat`, `feature`, `fix`, `refactor`, `docs`, `build`, `test`, `ci`, `chore`\n\nExamples:\n\n```\nfeat(components): add select component\nfix(button): resolve disabled state not applying\ndocs: update installation guide\n```\n\n## Component Architecture\n\n### File Structure\n\nEach component lives in `packages/react/src/components/<component-name>/`:\n\n```\ncomponent-name/\n├── component-name.tsx          # Component implementation (uses React Aria)\n├── component-name.styles.ts    # Tailwind Variants styling\n├── component-name.stories.tsx  # Storybook stories\n└── index.ts                    # Barrel exports\n```\n\nCSS styles live in `packages/styles/src/components/<component-name>/`.\n\n### Creating a New Component\n\nAlways use the scaffold script:\n\n```bash\ncd packages/react\npnpm add:component ComponentName\n```\n\nThen build to update package.json exports:\n\n```bash\npnpm build\n```\n\n### Compound Component Pattern\n\nHeroUI uses a compound component pattern. Each component exports its sub-parts so users can compose and style them independently.\n\n```tsx\n// Context shares state/styles across parts\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root wraps children with context\nconst ComponentRoot = forwardRef(({children, className, ...props}, ref) => {\n  const slots = useMemo(() => componentVariants({...}), [...]);\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaPrimitive>\n    </ComponentContext>\n  );\n});\n\n// Child parts consume context\nconst ComponentItem = forwardRef(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n  return (\n    <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaPrimitive>\n  );\n});\n```\n\nCompound components are exported via `Object.assign` as the default export:\n\n```tsx\nconst CompoundComponent = Object.assign(ComponentRoot, {\n  Item: ComponentItem,\n  Trigger: ComponentTrigger,\n});\nexport default CompoundComponent;\n```\n\n### Export Strategy\n\n```tsx\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n### Styling Rules\n\n1. **Styles go in `.styles.ts` files**, never in `.tsx` files. Use `tv()` from `tailwind-variants`.\n2. **Import from `tailwind-variants`**, never from `@heroui/standard`.\n3. **Never use `twMerge` manually** — `tailwind-variants` already includes it.\n4. **Add `\"use client\"` directive** at the top of every component `.tsx` file.\n5. **Display names** follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`.\n\n### CSS / BEM Naming\n\nComponents use BEM-style CSS class names:\n\n- **Block**: `button`, `card`, `alert`\n- **Element**: `card__header`, `alert__icon`\n- **Modifier**: `button--primary`, `button--lg`, `button--icon-only`\n\n### Default Size Pattern (Critical)\n\nAll components must include default sizes in base classes so they work without explicit size props:\n\n```css\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default (equivalent to --md) */\n}\n\n.avatar--sm { @apply size-8; }\n.avatar--md { /* empty — this IS the default */ }\n.avatar--lg { @apply size-12; }\n```\n\n### Interactive State Pattern\n\nAll interactive components must support both pseudo-classes and data attributes:\n\n```css\n.component {\n  &:hover,\n  &[data-hovered=\"true\"] { @apply ...; }\n\n  &:active,\n  &[data-pressed=\"true\"] { @apply ...; }\n\n  &:focus-visible,\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n### React Aria className Patterns\n\nReact Aria components differ in how they accept `className`:\n\n- **Render-prop components** (Button, Checkbox, Switch, Popover, Tooltip, Tabs, Link, Menu, etc.) — use `composeTwRenderProps(className, slots.foo())`.\n- **String-only components** (Label, Text, Input, TextArea, Heading, Dialog) — pass `className` directly: `slots?.label({className})`.\n\n### Composition Over Duplication\n\nDo **not** create component-specific Label/Description/FieldError sub-components. Instead, compose with the existing shared primitives:\n\n```tsx\nimport {Label} from \"@/components/label\";\nimport {Description} from \"@/components/description\";\n\n<div className=\"flex items-center gap-3\">\n  <Checkbox id=\"terms\"><Checkbox.Indicator /></Checkbox>\n  <Label htmlFor=\"terms\">Accept terms</Label>\n</div>\n```\n\n### Tailwind Class Detection\n\nTailwind CSS scans files as plain text. **Never construct class names dynamically**:\n\n```tsx\n// BAD — Tailwind won't detect this\n<div className={`text-${color}-600`} />\n<span className={`button--${size}`} />\n\n// GOOD — use complete class name mappings\nconst colorClasses = {\n  blue: \"text-blue-600\",\n  red: \"text-red-600\",\n};\n```\n\n### Storybook\n\nAll stories must use the `\"Components\"` group in their title:\n\n```tsx\nexport default { title: \"Components/Button\" };\n```\n\nStorybook is the primary dev workflow — run with `pnpm dev` (port 6006).\n\n### Icon Library\n\nHeroUI uses **Iconify** with **gravity-ui** as the default icon set.\n\n## Current Components\n\n### Completed\n\naccordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n### In Progress\n\ncalendar-year-picker\n\n## Non-obvious Gotchas\n\n1. **`pnpm i` triggers builds** — The `postinstall` hook builds `@heroui/styles` and runs `typegen:docs` and `typegen:docs-cn`. If it fails, run `pnpm --filter @heroui/styles build` manually.\n\n2. **Build order matters** — `@heroui/styles` must build before `@heroui/react`. Running `pnpm build` from root handles this via Turbo's `^build` dependency.\n\n3. **Native addons allowlist** — `onlyBuiltDependencies` in root `pnpm-workspace.yaml` allows native compilation for `esbuild`, `@swc/core`, `@parcel/watcher`, etc. If this list is missing, you'll see \"Ignored build scripts\" warnings.\n\n4. **Behavioral tests** — see [Behavioral tests](#behavioral-tests-herouireact) above. Harness lives in `@heroui/testing`; suites in `packages/react/tests/`.\n\n5. **Commit hooks** — Husky runs `lint-staged` on pre-commit and `commitlint` on commit-msg. Non-conforming commits are rejected.\n\n6. **Run checks before committing** — `pnpm lint && pnpm typecheck && pnpm test`\n\n## Cursor Cloud Specific\n\n- **Node.js v22+** is installed via binary tarball to `/usr/local/`.\n- **pnpm** is activated via `corepack` — the `packageManager` field in root `package.json` declares `pnpm@10.26.2`.\n- Full command reference and component architecture details are also in `CLAUDE.md`.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with Tailwind CSS v4, using a pnpm monorepo structure managed by Turborepo.\n\n### Key Technical Stack\n\n- **Node.js**: v22+ required\n- **pnpm**: v10.26.2 (package manager)\n- **React**: v19+\n- **Tailwind CSS**: v4.1.18\n- **TypeScript**: v5.9.3\n- **Turborepo**: Build orchestration\n- **Storybook**: Component development\n- **Vitest**: Testing framework\n\n## Development Commands\n\n### Core Development Commands\n\n```bash\n# Install dependencies (use --hoist flag)\npnpm i --hoist\n\n# Start Storybook for component development\npnpm dev\n\n# Start documentation site\npnpm dev:docs\n\n# Build all packages\npnpm build\n\n# Build specific package\npnpm build --filter=@heroui/react\n\n# Run linting\npnpm lint\n\n# Run tests (turbo → packages with a test script; jsdom + browser)\npnpm test\n\n# Filter by file name (e.g. button.test.tsx)\npnpm --filter @heroui/react exec vitest run button\n\n# Coverage (jsdom floors only — not a depth bar)\npnpm test:coverage\n\n# Changed-set (local jsdom only; not a merge gate)\npnpm --filter @heroui/react test:changed\n\n# Run formatting\npnpm run format\n\n# Run type checking\npnpm typecheck\n```\n\n### Behavioral tests (`@heroui/react`)\n\n- Suites: `packages/react/tests/components/<name>/` — `*.test.tsx` (jsdom), `*.ssr.test.tsx` (Client SSR via `ssrSmoke()`, not RSC), `*.browser.test.tsx` (Playwright for high-risk portals/overlays; not universal), optional `fixtures.tsx`\n- Harness: `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`); browser `render` from `@heroui/testing/browser`. Sources via `@/`. Pattern testers: `user.createTester(...)` — do not import `createTester` directly\n- Query/assert: role/label/text first; HeroUI `data-*` + light BEM + documented `data-slot` on compound parts; no colors, full class lists, or RAC internals\n- Timers: fake timers per-suite only; wire `advanceTimers` into `setupUser` + `User`\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`\n- Intentional skips: internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, …), Toast SSR (client portal — jsdom + browser). Public `input-group` has its own suite. SSR/browser are risk-based\n- Browser setup (once locally): `playwright install chromium` before `pnpm test`. CI: `--with-deps`, then `test:browser` + `test:coverage`\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`\n- Coverage: jsdom-only floors — green ≠ depth. `test:changed`: local jsdom shortcut only, not a merge gate\n\n### Package-Specific Commands\n\n- Use `--filter` flag with package name: `pnpm build --filter=@heroui/react`\n- Main packages: `@heroui/react`, `@heroui/styles`, `@heroui/docs`, `@heroui/storybook`\n\n## Git Commit Convention\n\n**IMPORTANT**: This repository uses conventional commits with strict validation. All commits must follow this format:\n\n```\n<type>(<scope>): <message>\n```\n\n### Allowed Types:\n\n- `feat` / `feature`: New features\n- `fix`: Bug fixes\n- `refactor`: Code refactoring\n- `docs`: Documentation changes\n- `build`: Build system changes\n- `test`: Test changes\n- `ci`: CI configuration changes\n- `chore`: Other changes\n\n### Examples:\n\n```bash\ngit commit -m \"feat(components): add new prop to avatar component\"\ngit commit -m \"fix(button): resolve click handler issue\"\ngit commit -m \"docs: update installation guide\"\ngit commit -m \"ci: add Claude Code GitHub Action workflow\"\n```\n\n**Note**: Commits without proper format will be rejected by git hooks.\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/          # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/         # Main UI component library (@heroui/react)\n│   ├── styles/        # CSS styles & variants (@heroui/styles)\n│   ├── standard/      # Shared ESLint, Prettier, TypeScript configs\n│   ├── storybook/     # Storybook configuration\n│   └── testing/       # Shared test harness (@heroui/testing)\n├── turbo.json         # Turborepo configuration\n└── pnpm-workspace.yaml # Workspace definition\n```\n\n### Component Architecture Pattern\n\nEach component in `packages/react/src/components/` follows this structure:\n\n```\ncomponent-name/\n├── component-name.tsx      # Main component (uses React Aria)\n├── component-name.styles.ts # Tailwind Variants styling\n├── component-name.stories.tsx # Storybook stories (title: \"Components/ComponentName\")\n└── index.ts               # Barrel exports\n```\n\n**IMPORTANT**: All Storybook stories must use the \"Components\" group in their title. For example: `title: \"Components/Card\"`, `title: \"Components/Button\"`, etc.\n\n### CSS Class Naming Convention\n\n**IMPORTANT**: HeroUI v3 uses BEM (Block Element Modifier) style for CSS classes to ensure predictable and maintainable styling:\n\n- **Block**: The main component class (e.g., `button`, `card`, `alert`)\n- **Modifier**: Variations of the component using double dashes (e.g., `button--primary`, `button--lg`, `button--icon-only`)\n- **Element**: Child elements within a component (e.g., `card__header`, `alert__icon`)\n\n**Migration to CSS-based Styling**:\n\n- The `button` component has been migrated to use CSS styles from `@heroui/styles/src/components/button.css`\n- This approach allows for better customization through CSS utilities and `@utility` directives\n- Other components will gradually be migrated to follow this CSS-based pattern\n- Components use `tv()` from `tailwind-variants` to map variant props to BEM class names\n\n**Default Size Pattern**:\n\n**CRITICAL**: All components MUST include default sizes in their base classes to prevent broken appearances when no size modifier is specified. Following the following pattern:\n\n- **Base classes** include default dimensions (equivalent to the `--md` variant)\n- **Medium variants** (`--md`) are empty with explanatory comments\n- **Size modifiers** override the defaults when specified\n\nExample implementation:\n\n```css\n/* Base component with default size */\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default, equivalent to --md */\n}\n\n/* Size variants */\n.avatar--sm {\n  @apply size-8; /* Override default */\n}\n\n.avatar--md {\n  /* No styles as this is the default size */\n}\n\n.avatar--lg {\n  @apply size-12; /* Override default */\n}\n```\n\nThis ensures components work properly without explicit size classes:\n\n- `<div className=\"avatar\">` → Works perfectly (size-10)\n- `<div className=\"avatar avatar--lg\">` → Override to large (size-12)\n\n### Core Component Design Principles\n\n**IMPORTANT**: HeroUI v3 follows a compound component pattern similar to Radix UI, built on top of React Aria Components primitives. This enables maximum flexibility and customization for users.\n\n### React Aria Components Integration\n\n**CRITICAL**: Before implementing any component, you MUST:\n\n1. Visit React Aria Components docs: https://react-spectrum.adobe.com/react-aria/\n2. Study the specific component's API and examples\n3. Understand its accessibility features and ARIA patterns\n4. Plan the transformation from React Aria's prop-based API to Radix UI's composition-based API\n\nReact Aria provides the accessibility foundation, but we transform their API to match Radix UI's compound component pattern for better customization.\n\n#### 1. **Compound Component Pattern**:\n\n- Export all internal component pieces (Root, Item, Trigger, Content, etc.)\n- Each piece can be styled and composed independently\n- Users can customize render logic without accessing internal code\n- Examples: Accordion (Root, Item, Heading, Trigger, Panel, Indicator, Body), Alert (Root, Icon, Title, Description, Action, Close)\n\n#### 2. **Export Strategy**:\n\n```typescript\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n#### 3. **Component Structure for Compound Components**:\n\n```typescript\n// Context for sharing state/styles\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root component wraps with context\nconst ComponentRoot = React.forwardRef<...>(({children, className, ...props}, ref) => {\n  const slots = React.useMemo(() => componentVariants({...}), [...]);\n\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaComponent>\n    </ComponentContext>\n  );\n});\n\n// Child components consume context\nconst ComponentItem = React.forwardRef<...>(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n\n  return (\n    <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaComponent>\n  );\n});\n\n// Export pattern\nexport {ComponentRoot as Root, ComponentItem as Item, ...};\n```\n\n#### 4. **Key Implementation Details**:\n\n1. **Styling with Tailwind Variants**:\n   - Styles defined in `.styles.ts` files using `tv()` function from `tailwind-variants`\n   - **IMPORTANT**: Always import from `tailwind-variants`, never from `@heroui/standard` (which doesn't exist)\n   - **CRITICAL**: tailwind-variants already includes `twMerge` functionality, so NEVER manually use `twMerge`\n   - **RULE**: All component styles MUST be defined in separate `.styles.ts` files, NOT in the component implementation files\n   - Component implementation files (`.tsx`) should only contain logic and React Aria primitives\n   - Example imports:\n     ```typescript\n     import type {VariantProps} from \"tailwind-variants\";\n     import {tv} from \"tailwind-variants\";\n     ```\n   - Support for variants (primary, secondary, etc.)\n   - Compound variants for conditional styling\n   - Slot system for complex components\n\n2. **Component Features**:\n   - Built on React Aria Components for accessibility\n   - Use `forwardRef` for all components\n   - Display names follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`\n   - Support render props from React Aria when available\n\n3. **Type Exports**:\n\n   ```typescript\n   // Export props for each component part\n   export type ComponentRootProps = {...}\n   export type ComponentItemProps = {...}\n   export type ComponentVariants = VariantProps<typeof componentVariants>\n   ```\n\n4. **Utilities** (`packages/react/src/utils/`):\n   - `composeTwRenderProps`: Merge Tailwind classes with render props\n   - `focusRingClasses`: Consistent focus styling\n   - `disabledClasses`: Disabled state styling\n   - `mapPropsVariants`: Separate variant props from component props\n\n5. **React Aria Components className Patterns**:\n\n   **CRITICAL**: React Aria components have different className prop behaviors:\n\n   **Components that support render props** (use `composeTwRenderProps`):\n   - Button, TextField, FieldError, Checkbox, CheckboxGroup\n   - Switch, RadioGroup, Radio, Slider (and Track, Thumb, Output)\n   - Popover, Tooltip, Tabs (and Tab, TabList, TabPanel)\n   - Link, Menu, MenuItem, Accordion (DisclosureGroup)\n\n   **Components that ONLY accept string className** (pass className directly):\n   - Label, Text, Input, TextArea\n   - Heading, Dialog, OverlayArrow\n\n   **Usage examples**:\n\n   ```typescript\n   // For render prop components - use composeTwRenderProps\n   <ButtonPrimitive\n     className={composeTwRenderProps(className, slots?.button())}\n   />\n\n   // For string-only components - pass className directly\n   <LabelPrimitive\n     className={slots?.label({className})}\n   />\n   // OR\n   <LabelPrimitive\n     className={labelVariants({size, variant, className})}\n   />\n   ```\n\n   **How to check**: If unsure, check the React Aria docs or try both approaches - TypeScript will error if a component doesn't support render props\n\n6. **Composition Pattern with Existing Components**:\n\n   **CRITICAL**: HeroUI follows a composition-based approach. Components should reuse existing primitives rather than creating component-specific versions.\n\n   **Key Principles**:\n   - **DO NOT** create component-specific Label, Description, or FieldError components\n   - **DO** reuse the existing `Label`, `Description`, and `FieldError` components\n   - **DO** use standard HTML composition patterns with `htmlFor`/`id` attributes\n\n   **Example Pattern**:\n\n   ```typescript\n   // ❌ WRONG - Component-specific label\n   export const Checkbox = {\n     Root: CheckboxRoot,\n     Label: CheckboxLabel, // Don't create this!\n   };\n\n   // ✅ CORRECT - Compose with existing components\n   import { Label } from \"@/components/label\";\n   import { Description } from \"@/components/description\";\n\n   // Usage:\n   <div className=\"flex items-center gap-3\">\n     <Checkbox id=\"terms\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <Label htmlFor=\"terms\">Accept terms</Label>\n   </div>\n\n   // With description:\n   <div className=\"flex gap-3\">\n     <Checkbox className=\"mt-0.5\" id=\"notifications\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <div className=\"flex flex-col gap-1\">\n       <Label htmlFor=\"notifications\">Email notifications</Label>\n       <Description>Get notified when someone mentions you</Description>\n     </div>\n   </div>\n   ```\n\n   **Components that follow this pattern**:\n   - Checkbox - uses external Label/Description\n   - Radio - uses external Label/Description\n   - Switch - uses external Label/Description\n   - TextField - provides slots for Label/Description/FieldError\n\n### Current Components\n\n**Completed**: accordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n**In Progress**: calendar-year-picker\n\n> Source of truth: `packages/react/src/components/index.ts`.\n\n## Development Workflow\n\n### Standard Feature Development Process\n\n**IMPORTANT**: When working on any feature or improvement, Claude Code MUST follow this systematic workflow to ensure accuracy and code quality:\n\n1. **Research Phase**:\n   - Thoroughly research the feature/component requirements\n   - Study relevant documentation (React Aria, Tailwind CSS, etc.)\n   - Analyze existing similar implementations in the codebase\n   - Identify all dependencies and integration points\n\n2. **Planning Phase**:\n   - Create a detailed implementation plan with a comprehensive checklist\n   - Break down the task into specific, measurable steps\n   - Include testing and verification steps in the plan\n   - Present the plan for review before proceeding\n\n3. **Review & Correction Phase**:\n   - Review the plan for completeness and accuracy\n   - Make necessary corrections or adjustments\n   - Ensure all edge cases are considered\n   - Confirm the plan aligns with HeroUI patterns and conventions\n\n4. **Execution Phase**:\n   - Start executing the plan step by step\n   - Use the TodoWrite tool to track progress automatically\n   - Mark todos as in_progress when starting a task\n   - Mark todos as completed immediately after finishing each step\n   - Never batch completions - update status in real-time\n\n5. **Verification Phase**:\n   - Manually verify all changes work as expected\n   - Test API calls if backend changes were made\n   - Check frontend rendering and interactions\n   - Run lint and type checks: `pnpm lint && pnpm typecheck`\n   - Ensure all tests pass: `pnpm test`\n\n**Example Workflow**:\n\n```\nUser: \"Add a new Select component\"\n\nClaude:\n1. Research: Studies React Aria Select, existing patterns\n2. Plan: Creates detailed checklist with 15+ items\n3. Review: Presents plan for feedback\n4. Execute: Implements step-by-step with todo updates\n5. Verify: Tests component, runs checks, confirms functionality\n```\n\nThis workflow ensures thorough understanding, proper planning, and high-quality implementation with full transparency throughout the process.\n\n### Component Development Workflow\n\n1. **Creating New Components**:\n\n   **CRITICAL: Research & Design Phase**:\n   - **FIRST**: Check the Figma design for the component breakdown (e.g., Menu Container, Menu Item, etc.)\n   - **SECOND**: Research the React Aria Components documentation at https://react-spectrum.adobe.com/react-aria/\n   - Find the appropriate React Aria primitive (e.g., CheckboxGroup, Dialog, Select, etc.)\n   - Understand the React Aria API, props, and accessibility features\n   - Map Figma component pieces to React Aria components and plan the compound structure\n   - Plan how to adapt it to follow Radix UI's compound component pattern\n\n   **Component Creation - ALWAYS USE THE SCRIPT**:\n\n   ```bash\n   # Navigate to packages/react directory\n   cd packages/react\n\n   # Use the add:component script\n   pnpm add:component ComponentName\n\n   # Examples:\n   pnpm add:component Menu\n   pnpm add:component Select\n   pnpm add:component DatePicker\n   ```\n\n   This script will:\n   - Create all necessary files with proper structure\n   - Add the export to `src/components/index.ts`\n   - Generate boilerplate following HeroUI patterns\n   - Set up the component with TypeScript and proper exports\n\n   After creating the component:\n\n   ```bash\n   # Build to update package.json exports automatically\n   pnpm build\n   ```\n\n   **Implementation Steps**:\n   - Study existing HeroUI components (accordion, alert) to understand the compound pattern\n   - Use React Aria Components as the foundation for accessibility\n   - Transform React Aria's API to match Radix UI patterns:\n     - Single component → Multiple exported parts (Item, Trigger, Content, etc.)\n     - Props-based API → Composition-based API\n     - Internal state → Context-based state sharing\n   - Create Context for sharing styles across component parts\n   - Export ALL component parts for maximum customization\n   - Define styles in separate `.styles.ts` file with slot system\n   - Add \"use client\" directive at the top of component file\n   - Create comprehensive Storybook stories showing all variants and compositions\n   - Follow the export pattern: `export * as ComponentName from \"./component-name\"`\n\n   **Example Transformation**:\n\n   ```typescript\n   // React Aria: Single component with props\n   <CheckboxGroup label=\"Options\" value={selected} onChange={setSelected}>\n     <Checkbox value=\"1\">Option 1</Checkbox>\n   </CheckboxGroup>\n\n   // HeroUI: Compound pattern\n   <CheckboxGroup value={selected} onValueChange={setSelected}>\n     <CheckboxGroup.Label>Options</CheckboxGroup.Label>\n     <CheckboxGroup.Item value=\"1\">\n       <CheckboxGroup.Indicator />\n       <CheckboxGroup.Label>Option 1</CheckboxGroup.Label>\n     </CheckboxGroup.Item>\n   </CheckboxGroup>\n   ```\n\n   **Example of a compound component exports**\n\n   ```typescript\n   const CompoundAccordion = Object.assign(Accordion, {\n     Item: AccordionItem,\n     Heading: AccordionHeading,\n     Trigger: AccordionTrigger,\n     Panel: AccordionPanel,\n     Indicator: AccordionIndicator,\n     Body: AccordionBody,\n   });\n\n   export type {\n     AccordionProps,\n     AccordionItemProps,\n     AccordionTriggerProps,\n     AccordionPanelProps,\n     AccordionIndicatorProps,\n     AccordionBodyProps,\n   };\n\n   export default CompoundAccordion;\n   ```\n\n   **IMPORTANT**: The compound component should be exported as the default export.\n\n2. **Testing**:\n   - Follow Behavioral tests conventions above (semantics-first, `setupUser`, `data-*` state hooks)\n   - Run `pnpm test` for jsdom + browser; filter with `pnpm --filter @heroui/react exec vitest run <name>`\n   - Place tests under `packages/react/tests/components/<name>/` (`*.test.tsx` / `*.ssr.test.tsx` / `*.browser.test.tsx`, optional `fixtures.tsx`)\n   - Prefer arrow functions for harness helpers and test fixtures\n\n3. **Documentation**:\n   - Docs live in `apps/docs/content/`\n   - Uses MDX format\n   - HeroUI components are pre-imported\n\n4. **Version Management**:\n   - Uses [bumpp](https://github.com/antfu/bumpp) for version bumping\n   - Run `pnpm version:bump` to interactively bump the version, commit, and tag\n   - Pushing a `v*` tag triggers the release CI workflow\n   - Follow semantic versioning\n\n## Icon Library\n\n**IMPORTANT**: HeroUI uses Iconify with gravity-ui as the default icon set.\n\n## Important Notes\n\n- Always prefer editing existing files over creating new ones\n- **NEVER** create documentation files (_.md, _.mdx, README files) unless explicitly requested by the user\n- Follow the established component patterns and conventions\n- Ensure accessibility with React Aria Components\n- Maintain TypeScript type safety\n- Use the commit convention to avoid git hook failures\n- Run lint and type checks before committing: `pnpm lint && pnpm typecheck`\n\n## Tailwind CSS Class Detection Rules\n\n**CRITICAL**: Tailwind CSS scans files as plain text and requires complete class names to be statically detectable.\n\n### Key Rules:\n\n1. **Never construct class names dynamically**\n\n   ❌ **BAD** - Dynamic string concatenation:\n\n   ```jsx\n   // These patterns will NOT work:\n   <div className={`text-${color}-600`} />\n   <button className={`bg-${variant}-500`} />\n   <span className={`button--${size}`} />\n   ```\n\n   ✅ **GOOD** - Complete class names:\n\n   ```jsx\n   // Use complete strings or object mappings:\n   <div className={error ? \"text-red-600\" : \"text-green-600\"} />\n   ```\n\n2. **Use object mappings for dynamic classes**\n\n   ❌ **BAD** - Props in template literals:\n\n   ```jsx\n   function Button({color}) {\n     return <button className={`bg-${color}-600 hover:bg-${color}-500`} />;\n   }\n   ```\n\n   ✅ **GOOD** - Map props to complete classes:\n\n   ```jsx\n   function Button({color}) {\n     const colorVariants = {\n       blue: \"bg-blue-600 hover:bg-blue-500\",\n       red: \"bg-red-600 hover:bg-red-500\",\n     };\n     return <button className={colorVariants[color]} />;\n   }\n   ```\n\n3. **For BEM-style classes, use complete mappings**\n\n   ✅ **GOOD** - Complete class name mappings:\n\n   ```jsx\n   const sizeClasses = {\n     sm: \"button--sm\",\n     md: \"button--md\",\n     lg: \"button--lg\",\n   };\n\n   // Use the mapping:\n   className={sizeClasses[size]}\n   ```\n\n### Why This Matters:\n\n- Tailwind generates CSS only for classes it can detect in your source files\n- Dynamic concatenation prevents Tailwind from finding the complete class names\n- Missing classes = missing styles in production\n\n## Figma Integration & MCP Server Rules\n\n### Figma Dev Mode MCP Server\n\n**IMPORTANT**: When creating components with Figma designs:\n\n1. **Component Breakdown**: Figma designs are already broken down into component pieces (e.g., Menu Container, Menu Item, etc.). Use these as reference for:\n   - Component structure and naming (adapt to code conventions)\n   - Visual styling and spacing\n   - Component composition patterns\n\n2. **MCP Server Rules**:\n   - The Figma Dev Mode MCP Server provides an assets endpoint for images and SVG assets\n   - **CRITICAL**: If the Figma MCP Server returns a localhost source for an image or SVG, use that source directly\n   - **DO NOT** import or add new icon packages - all assets should come from the Figma payload\n   - **DO NOT** use or create placeholders if a localhost source is provided\n   - Always use the actual assets from Figma MCP Server\n\n3. **Workflow**:\n   - Check Figma for component visual design and breakdown\n   - Map Figma component names to appropriate React Aria primitives\n   - Use Figma assets (icons, images) directly from the MCP Server\n   - Implement styles based on Figma design tokens and specifications\n\n## Library Documentation with Context7 MCP\n\n**IMPORTANT**: We have the Context7 MCP server available (https://github.com/upstash/context7) for accessing up-to-date library documentation.\n\n### When to Use Context7\n\nUse Context7 MCP when working with external libraries, especially:\n\n- **Tailwind CSS v4**: When working with Tailwind CSS v4 features, use Context7 to get the latest documentation at https://context7.com/context7/tailwindcss\n- **Fumadocs**: When working on the documentation site in `apps/docs/`, use Context7 to get the latest Fumadocs framework documentation\n- **Next.js**: For Next.js specific features and APIs used in the docs app\n- Any other third-party libraries where up-to-date documentation is needed\n\n### How to Use Context7\n\n1. First, resolve the library ID using `mcp__context7__resolve-library-id`\n2. Then fetch documentation using `mcp__context7__get-library-docs` with the resolved ID\n3. This ensures you're always working with the latest documentation rather than outdated information\n\n### Example Usage Areas\n\n- Implementing new documentation features in `apps/docs/`\n- Configuring Fumadocs settings in `source.config.ts`\n- Working with MDX components and layouts\n- Setting up search functionality\n- Implementing documentation navigation and structure\n\n## GitHub Repository Search with Grep MCP\n\n**IMPORTANT**: We have the Grep MCP server available for searching over a million public GitHub repositories to find real-world code examples and patterns.\n\n### When to Use Grep MCP\n\nUse the Grep MCP (`mcp__grep__searchGitHub`) when tackling complex problems that require:\n\n- **Real-world implementation examples**: Finding how other developers solve similar problems\n- **Best practices and patterns**: Discovering production-ready code patterns\n- **Library usage examples**: Understanding how specific APIs or libraries are used in practice\n- **Complex integrations**: Seeing how different libraries work together\n- **Error handling patterns**: Learning from battle-tested error handling approaches\n\n### How to Use Grep MCP\n\nThe Grep MCP searches for **literal code patterns**, not keywords. Use actual code syntax:\n\n**Good examples**:\n\n- `'useState('` - Find React hooks usage\n- `'import { tv } from \"tailwind-variants\"'` - Find tailwind-variants imports\n- `'forwardRef<'` - Find forwardRef usage patterns\n- `'(?s)useEffect\\\\(\\\\(\\\\) => {.*return.*}'` - Find useEffect with cleanup (regex)\n\n**Bad examples**:\n\n- `'react best practices'` - This is a keyword, not code\n- `'how to use tailwind'` - Use actual import statements instead\n\n### Example Use Cases\n\n1. **Complex Component Patterns**:\n   - Search: `'compound.*component'` with language=['TypeScript', 'TSX']\n   - Find how others implement compound component patterns\n\n2. **Accessibility Implementations**:\n   - Search: `'AriaProps'` or `'useAriaLabel'`\n   - Discover accessibility patterns in React apps\n\n3. **Monorepo Configurations**:\n   - Search: `'pnpm-workspace.yaml'` with path='pnpm-workspace.yaml'\n   - Study monorepo setups similar to HeroUI\n\n4. **Tailwind CSS v4 Patterns**:\n   - Search: `'@import \"tailwindcss\"'` with language=['CSS']\n   - Find Tailwind CSS v4 usage patterns\n\n5. **React Aria Components Usage**:\n   - Search: `'from \"react-aria-components\"'`\n   - See how others integrate React Aria Components\n\n### Best Practices\n\n- Use language filters to narrow results (e.g., `language=['TypeScript', 'TSX']`)\n- Use regex patterns with `useRegexp=true` for flexible matching\n- Filter by well-known repositories for quality examples (e.g., `repo='vercel/'`)\n- Combine with file path filters for specific file types\n\n## Agent-Specific Guidelines\n\n### For style-migrator and tailwind-v4-css-expert Agents\n\nWhen working with HeroUI CSS components, follow these critical patterns:\n\n#### Default Size Implementation\n\n**REQUIRED**: All CSS components MUST follow the default size pattern:\n\n1. **Base classes** include default dimensions equivalent to `--md` variant\n2. **Medium variant** (`--md`) is an empty class with explanatory comment\n3. **Size variants** override the base defaults\n\n**Template for CSS components with size variants:**\n\n```css\n/* Base component styles */\n.component {\n  /* Base styling */\n  @apply [base-styles];\n\n  /* Default size - matches component--md variant */\n  @apply [default-size-classes];\n}\n\n/* Size variants */\n.component--sm {\n  @apply [small-size-overrides];\n}\n\n.component--md {\n  /* No styles as this is the default size */\n}\n\n.component--lg {\n  @apply [large-size-overrides];\n}\n```\n\n#### Pseudo-Class Fallback Pattern\n\n**REQUIRED**: All interactive components MUST include both pseudo-class and data-attribute support:\n\n```css\n/* Interactive states - both approaches */\n.component {\n  /* Hover states */\n  &:hover,\n  &[data-hovered=\"true\"] {\n    @apply [hover-styles];\n  }\n\n  /* Active/pressed states */\n  &:active,\n  &[data-pressed=\"true\"] {\n    @apply [active-styles];\n  }\n\n  /* Focus states */\n  &:focus-visible,\n  &:focus:not(:focus-visible),\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n#### Component Examples\n\n- **button.css**: Base has `h-10 md:h-9`, empty `.button--md` variant\n- **avatar.css**: Base has `size-10`, empty `.avatar--md` variant\n- **spinner.css**: Base has `size-6`, empty `.spinner--md` variant\n\nThese patterns ensure components never appear broken and maintain consistency across the design system.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nInstructions for AI agents working with the HeroUI v3 repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with **Tailwind CSS v4**, organized as a **pnpm monorepo** managed by **Turborepo**. Components are built on top of [React Aria Components](https://react-spectrum.adobe.com/react-aria/) and follow a compound component pattern similar to Radix UI.\n\n### Tech Stack\n\n| Technology | Version | Purpose |\n|---|---|---|\n| Node.js | 22+ | Runtime |\n| pnpm | 10.26.2 | Package manager (via corepack) |\n| React | 19+ | UI framework |\n| Tailwind CSS | 4.x | Styling |\n| TypeScript | 5.x | Type safety |\n| Turborepo | 2.x | Build orchestration |\n| Storybook | Latest | Component development |\n| Vitest | 4.x | Testing |\n| React Aria Components | Latest | Accessibility primitives |\n| tailwind-variants | Latest | Variant-based styling (includes twMerge) |\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/              # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/             # Main UI library (@heroui/react)\n│   │   ├── src/components/  # All components\n│   │   ├── src/utils/       # Shared utilities\n│   │   └── scripts/         # Build & codegen scripts\n│   ├── styles/            # CSS styles & variants (@heroui/styles)\n│   │   └── src/components/  # Per-component .css files\n│   ├── standard/          # Shared ESLint, Prettier, TS configs\n│   ├── storybook/         # Storybook configuration\n│   └── testing/           # Shared test harness (@heroui/testing)\n├── turbo.json\n└── pnpm-workspace.yaml\n```\n\n## Commands\n\n| Action | Command |\n|---|---|\n| Install dependencies | `pnpm i --hoist` |\n| Build all packages | `pnpm build` |\n| Build specific package | `pnpm build --filter=@heroui/react` |\n| Dev (Storybook, port 6006) | `pnpm dev` |\n| Dev (Docs site, port 3000) | `pnpm dev:docs` |\n| Lint | `pnpm lint` |\n| Typecheck | `pnpm typecheck` |\n| Test all (jsdom + browser) | `pnpm test` |\n| Test one file (filter) | `pnpm --filter @heroui/react exec vitest run button` |\n| Test with coverage | `pnpm test:coverage` (jsdom floors only — not “done”) |\n| Test changed files (local) | `pnpm --filter @heroui/react test:changed` (jsdom only; not a gate) |\n| Format | `pnpm run format` |\n| Bump version | `pnpm version:bump` |\n| Scaffold a new component | `cd packages/react && pnpm add:component ComponentName` |\n\n## Behavioral tests (`@heroui/react`)\n\n- Suites live in `packages/react/tests/components/<name>/`:\n  - `*.test.tsx` — jsdom (~90% of contracts)\n  - `*.ssr.test.tsx` — Client SSR smoke via `ssrSmoke()` (not RSC)\n  - `*.browser.test.tsx` — Playwright (overlays + high-risk portals; not every component)\n  - optional `fixtures.tsx` — shared JSX across layers\n- Import harness from `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`). Browser suites: `render` from `@heroui/testing/browser` (wraps `vitest-browser-react`; owned by `@heroui/testing`). Prefer `@/` for sources. Pattern testers: `const user = new User(...); user.createTester(...)` — not a top-level export.\n- Query: `getByRole` / label / text first; `data-testid` when needed; avoid class-primary queries.\n- Assert: roles/names, HeroUI `data-*` hooks, callbacks, focus, light BEM + documented `data-slot` on compound parts — not colors, full class lists, or RAC internals.\n- Fake timers: per-suite only; wire `advanceTimers` into `setupUser` + `User`; use `runAllTimers()`.\n- Pattern testers for groups / overlays / collections; skip for Button / Checkbox / Switch / TextField.\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`.\n- Intentional skips (no dedicated suite required): internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, `menu-section`, `list-box-section`), Toast SSR (client portal only — covered by jsdom + browser). Public `input-group` has its own suite. SSR and browser are risk-based, not universal.\n- Browser setup (once locally): `pnpm --filter @heroui/testing exec playwright install chromium` before `pnpm test`. CI uses `playwright install --with-deps chromium`, then `test:browser` + `test:coverage` (not a single `pnpm test`).\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`.\n- Coverage (`pnpm test:coverage`): jsdom only; `src/components/**` minus barrels. Thresholds are **CI floors** (statements/lines can pass with thin smoke). Green coverage ≠ sufficient depth — still require role/callback/focus (and browser for high-risk portals).\n- `test:changed`: local jsdom-only shortcut (`vitest related --changed`). Does **not** run browser suites; never use it as the merge gate — use `pnpm test` / CI.\n\n## Git Commit Convention\n\nAll commits must follow [Conventional Commits](https://www.conventionalcommits.org/) and are validated by Husky + commitlint. Pre-commit also runs `lint-staged`.\n\n```\n<type>(<scope>): <message>\n```\n\n**Allowed types:** `feat`, `feature`, `fix`, `refactor`, `docs`, `build`, `test`, `ci`, `chore`\n\nExamples:\n\n```\nfeat(components): add select component\nfix(button): resolve disabled state not applying\ndocs: update installation guide\n```\n\n## Component Architecture\n\n### File Structure\n\nEach component lives in `packages/react/src/components/<component-name>/`:\n\n```\ncomponent-name/\n├── component-name.tsx          # Component implementation (uses React Aria)\n├── component-name.styles.ts    # Tailwind Variants styling\n├── component-name.stories.tsx  # Storybook stories\n└── index.ts                    # Barrel exports\n```\n\nCSS styles live in `packages/styles/src/components/<component-name>/`.\n\n### Creating a New Component\n\nAlways use the scaffold script:\n\n```bash\ncd packages/react\npnpm add:component ComponentName\n```\n\nThen build to update package.json exports:\n\n```bash\npnpm build\n```\n\n### Compound Component Pattern\n\nHeroUI uses a compound component pattern. Each component exports its sub-parts so users can compose and style them independently.\n\n```tsx\n// Context shares state/styles across parts\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root wraps children with context\nconst ComponentRoot = forwardRef(({children, className, ...props}, ref) => {\n  const slots = useMemo(() => componentVariants({...}), [...]);\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaPrimitive>\n    </ComponentContext>\n  );\n});\n\n// Child parts consume context\nconst ComponentItem = forwardRef(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n  return (\n    <ReactAriaPrimitive ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaPrimitive>\n  );\n});\n```\n\nCompound components are exported via `Object.assign` as the default export:\n\n```tsx\nconst CompoundComponent = Object.assign(ComponentRoot, {\n  Item: ComponentItem,\n  Trigger: ComponentTrigger,\n});\nexport default CompoundComponent;\n```\n\n### Export Strategy\n\n```tsx\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n### Styling Rules\n\n1. **Styles go in `.styles.ts` files**, never in `.tsx` files. Use `tv()` from `tailwind-variants`.\n2. **Import from `tailwind-variants`**, never from `@heroui/standard`.\n3. **Never use `twMerge` manually** — `tailwind-variants` already includes it.\n4. **Add `\"use client\"` directive** at the top of every component `.tsx` file.\n5. **Display names** follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`.\n\n### CSS / BEM Naming\n\nComponents use BEM-style CSS class names:\n\n- **Block**: `button`, `card`, `alert`\n- **Element**: `card__header`, `alert__icon`\n- **Modifier**: `button--primary`, `button--lg`, `button--icon-only`\n\n### Default Size Pattern (Critical)\n\nAll components must include default sizes in base classes so they work without explicit size props:\n\n```css\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default (equivalent to --md) */\n}\n\n.avatar--sm { @apply size-8; }\n.avatar--md { /* empty — this IS the default */ }\n.avatar--lg { @apply size-12; }\n```\n\n### Interactive State Pattern\n\nAll interactive components must support both pseudo-classes and data attributes:\n\n```css\n.component {\n  &:hover,\n  &[data-hovered=\"true\"] { @apply ...; }\n\n  &:active,\n  &[data-pressed=\"true\"] { @apply ...; }\n\n  &:focus-visible,\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n### React Aria className Patterns\n\nReact Aria components differ in how they accept `className`:\n\n- **Render-prop components** (Button, Checkbox, Switch, Popover, Tooltip, Tabs, Link, Menu, etc.) — use `composeTwRenderProps(className, slots.foo())`.\n- **String-only components** (Label, Text, Input, TextArea, Heading, Dialog) — pass `className` directly: `slots?.label({className})`.\n\n### Composition Over Duplication\n\nDo **not** create component-specific Label/Description/FieldError sub-components. Instead, compose with the existing shared primitives:\n\n```tsx\nimport {Label} from \"@/components/label\";\nimport {Description} from \"@/components/description\";\n\n<div className=\"flex items-center gap-3\">\n  <Checkbox id=\"terms\"><Checkbox.Indicator /></Checkbox>\n  <Label htmlFor=\"terms\">Accept terms</Label>\n</div>\n```\n\n### Tailwind Class Detection\n\nTailwind CSS scans files as plain text. **Never construct class names dynamically**:\n\n```tsx\n// BAD — Tailwind won't detect this\n<div className={`text-${color}-600`} />\n<span className={`button--${size}`} />\n\n// GOOD — use complete class name mappings\nconst colorClasses = {\n  blue: \"text-blue-600\",\n  red: \"text-red-600\",\n};\n```\n\n### Storybook\n\nAll stories must use the `\"Components\"` group in their title:\n\n```tsx\nexport default { title: \"Components/Button\" };\n```\n\nStorybook is the primary dev workflow — run with `pnpm dev` (port 6006).\n\n### Icon Library\n\nHeroUI uses **Iconify** with **gravity-ui** as the default icon set.\n\n## Current Components\n\n### Completed\n\naccordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n### In Progress\n\ncalendar-year-picker\n\n## Non-obvious Gotchas\n\n1. **`pnpm i` triggers builds** — The `postinstall` hook builds `@heroui/styles` and runs `typegen:docs` and `typegen:docs-cn`. If it fails, run `pnpm --filter @heroui/styles build` manually.\n\n2. **Build order matters** — `@heroui/styles` must build before `@heroui/react`. Running `pnpm build` from root handles this via Turbo's `^build` dependency.\n\n3. **Native addons allowlist** — `onlyBuiltDependencies` in root `pnpm-workspace.yaml` allows native compilation for `esbuild`, `@swc/core`, `@parcel/watcher`, etc. If this list is missing, you'll see \"Ignored build scripts\" warnings.\n\n4. **Behavioral tests** — see [Behavioral tests](#behavioral-tests-herouireact) above. Harness lives in `@heroui/testing`; suites in `packages/react/tests/`.\n\n5. **Commit hooks** — Husky runs `lint-staged` on pre-commit and `commitlint` on commit-msg. Non-conforming commits are rejected.\n\n6. **Run checks before committing** — `pnpm lint && pnpm typecheck && pnpm test`\n\n## Cursor Cloud Specific\n\n- **Node.js v22+** is installed via binary tarball to `/usr/local/`.\n- **pnpm** is activated via `corepack` — the `packageManager` field in root `package.json` declares `pnpm@10.26.2`.\n- Full command reference and component architecture details are also in `CLAUDE.md`.\n","category":"root","tokens":3197},{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nHeroUI v3 is a modern React UI library built with Tailwind CSS v4, using a pnpm monorepo structure managed by Turborepo.\n\n### Key Technical Stack\n\n- **Node.js**: v22+ required\n- **pnpm**: v10.26.2 (package manager)\n- **React**: v19+\n- **Tailwind CSS**: v4.1.18\n- **TypeScript**: v5.9.3\n- **Turborepo**: Build orchestration\n- **Storybook**: Component development\n- **Vitest**: Testing framework\n\n## Development Commands\n\n### Core Development Commands\n\n```bash\n# Install dependencies (use --hoist flag)\npnpm i --hoist\n\n# Start Storybook for component development\npnpm dev\n\n# Start documentation site\npnpm dev:docs\n\n# Build all packages\npnpm build\n\n# Build specific package\npnpm build --filter=@heroui/react\n\n# Run linting\npnpm lint\n\n# Run tests (turbo → packages with a test script; jsdom + browser)\npnpm test\n\n# Filter by file name (e.g. button.test.tsx)\npnpm --filter @heroui/react exec vitest run button\n\n# Coverage (jsdom floors only — not a depth bar)\npnpm test:coverage\n\n# Changed-set (local jsdom only; not a merge gate)\npnpm --filter @heroui/react test:changed\n\n# Run formatting\npnpm run format\n\n# Run type checking\npnpm typecheck\n```\n\n### Behavioral tests (`@heroui/react`)\n\n- Suites: `packages/react/tests/components/<name>/` — `*.test.tsx` (jsdom), `*.ssr.test.tsx` (Client SSR via `ssrSmoke()`, not RSC), `*.browser.test.tsx` (Playwright for high-risk portals/overlays; not universal), optional `fixtures.tsx`\n- Harness: `@heroui/testing/helpers` (`render`, `setupUser`, `runAllTimers`, `ssrSmoke`, `User`); browser `render` from `@heroui/testing/browser`. Sources via `@/`. Pattern testers: `user.createTester(...)` — do not import `createTester` directly\n- Query/assert: role/label/text first; HeroUI `data-*` + light BEM + documented `data-slot` on compound parts; no colors, full class lists, or RAC internals\n- Timers: fake timers per-suite only; wire `advanceTimers` into `setupUser` + `User`\n- Naming: `describe(\"Component\")`; nested concern; `it` as `supports…` / `calls…` / `exposes…` / `renders…`. SSR: `\"Component SSR\"`; browser: `\"Component (browser)\"`\n- Intentional skips: internals (`rac`, `icons`), non-exported helpers (`color-input-group`, `date-input-group`), in-progress `calendar-year-picker`, parent-covered parts (`list-box-item`, `menu-item`, …), Toast SSR (client portal — jsdom + browser). Public `input-group` has its own suite. SSR/browser are risk-based\n- Browser setup (once locally): `playwright install chromium` before `pnpm test`. CI: `--with-deps`, then `test:browser` + `test:coverage`\n- Commands: `pnpm test` (jsdom + browser, needs Chromium); filter with `pnpm --filter @heroui/react exec vitest run <name>`\n- Coverage: jsdom-only floors — green ≠ depth. `test:changed`: local jsdom shortcut only, not a merge gate\n\n### Package-Specific Commands\n\n- Use `--filter` flag with package name: `pnpm build --filter=@heroui/react`\n- Main packages: `@heroui/react`, `@heroui/styles`, `@heroui/docs`, `@heroui/storybook`\n\n## Git Commit Convention\n\n**IMPORTANT**: This repository uses conventional commits with strict validation. All commits must follow this format:\n\n```\n<type>(<scope>): <message>\n```\n\n### Allowed Types:\n\n- `feat` / `feature`: New features\n- `fix`: Bug fixes\n- `refactor`: Code refactoring\n- `docs`: Documentation changes\n- `build`: Build system changes\n- `test`: Test changes\n- `ci`: CI configuration changes\n- `chore`: Other changes\n\n### Examples:\n\n```bash\ngit commit -m \"feat(components): add new prop to avatar component\"\ngit commit -m \"fix(button): resolve click handler issue\"\ngit commit -m \"docs: update installation guide\"\ngit commit -m \"ci: add Claude Code GitHub Action workflow\"\n```\n\n**Note**: Commits without proper format will be rejected by git hooks.\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```\n/\n├── apps/\n│   └── docs/          # Documentation site (Next.js + Fumadocs)\n├── packages/\n│   ├── react/         # Main UI component library (@heroui/react)\n│   ├── styles/        # CSS styles & variants (@heroui/styles)\n│   ├── standard/      # Shared ESLint, Prettier, TypeScript configs\n│   ├── storybook/     # Storybook configuration\n│   └── testing/       # Shared test harness (@heroui/testing)\n├── turbo.json         # Turborepo configuration\n└── pnpm-workspace.yaml # Workspace definition\n```\n\n### Component Architecture Pattern\n\nEach component in `packages/react/src/components/` follows this structure:\n\n```\ncomponent-name/\n├── component-name.tsx      # Main component (uses React Aria)\n├── component-name.styles.ts # Tailwind Variants styling\n├── component-name.stories.tsx # Storybook stories (title: \"Components/ComponentName\")\n└── index.ts               # Barrel exports\n```\n\n**IMPORTANT**: All Storybook stories must use the \"Components\" group in their title. For example: `title: \"Components/Card\"`, `title: \"Components/Button\"`, etc.\n\n### CSS Class Naming Convention\n\n**IMPORTANT**: HeroUI v3 uses BEM (Block Element Modifier) style for CSS classes to ensure predictable and maintainable styling:\n\n- **Block**: The main component class (e.g., `button`, `card`, `alert`)\n- **Modifier**: Variations of the component using double dashes (e.g., `button--primary`, `button--lg`, `button--icon-only`)\n- **Element**: Child elements within a component (e.g., `card__header`, `alert__icon`)\n\n**Migration to CSS-based Styling**:\n\n- The `button` component has been migrated to use CSS styles from `@heroui/styles/src/components/button.css`\n- This approach allows for better customization through CSS utilities and `@utility` directives\n- Other components will gradually be migrated to follow this CSS-based pattern\n- Components use `tv()` from `tailwind-variants` to map variant props to BEM class names\n\n**Default Size Pattern**:\n\n**CRITICAL**: All components MUST include default sizes in their base classes to prevent broken appearances when no size modifier is specified. Following the following pattern:\n\n- **Base classes** include default dimensions (equivalent to the `--md` variant)\n- **Medium variants** (`--md`) are empty with explanatory comments\n- **Size modifiers** override the defaults when specified\n\nExample implementation:\n\n```css\n/* Base component with default size */\n.avatar {\n  @apply relative flex size-10 shrink-0 overflow-hidden rounded-full;\n  /* size-10 is the default, equivalent to --md */\n}\n\n/* Size variants */\n.avatar--sm {\n  @apply size-8; /* Override default */\n}\n\n.avatar--md {\n  /* No styles as this is the default size */\n}\n\n.avatar--lg {\n  @apply size-12; /* Override default */\n}\n```\n\nThis ensures components work properly without explicit size classes:\n\n- `<div className=\"avatar\">` → Works perfectly (size-10)\n- `<div className=\"avatar avatar--lg\">` → Override to large (size-12)\n\n### Core Component Design Principles\n\n**IMPORTANT**: HeroUI v3 follows a compound component pattern similar to Radix UI, built on top of React Aria Components primitives. This enables maximum flexibility and customization for users.\n\n### React Aria Components Integration\n\n**CRITICAL**: Before implementing any component, you MUST:\n\n1. Visit React Aria Components docs: https://react-spectrum.adobe.com/react-aria/\n2. Study the specific component's API and examples\n3. Understand its accessibility features and ARIA patterns\n4. Plan the transformation from React Aria's prop-based API to Radix UI's composition-based API\n\nReact Aria provides the accessibility foundation, but we transform their API to match Radix UI's compound component pattern for better customization.\n\n#### 1. **Compound Component Pattern**:\n\n- Export all internal component pieces (Root, Item, Trigger, Content, etc.)\n- Each piece can be styled and composed independently\n- Users can customize render logic without accessing internal code\n- Examples: Accordion (Root, Item, Heading, Trigger, Panel, Indicator, Body), Alert (Root, Icon, Title, Description, Action, Close)\n\n#### 2. **Export Strategy**:\n\n```typescript\n// Named exports for compound components\nexport * as ComponentName from \"./component-name\";\n\n// Direct exports for simple components\nexport {Component, type ComponentProps} from \"./component\";\n\n// Always export variants\nexport {componentVariants, type ComponentVariants} from \"./component.styles\";\n```\n\n#### 3. **Component Structure for Compound Components**:\n\n```typescript\n// Context for sharing state/styles\nconst ComponentContext = createContext<{slots?: ReturnType<typeof componentVariants>}>({});\n\n// Root component wraps with context\nconst ComponentRoot = React.forwardRef<...>(({children, className, ...props}, ref) => {\n  const slots = React.useMemo(() => componentVariants({...}), [...]);\n\n  return (\n    <ComponentContext value={{slots}}>\n      <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots.base())}>\n        {children}\n      </ReactAriaComponent>\n    </ComponentContext>\n  );\n});\n\n// Child components consume context\nconst ComponentItem = React.forwardRef<...>(({className, ...props}, ref) => {\n  const {slots} = useContext(ComponentContext);\n\n  return (\n    <ReactAriaComponent ref={ref} className={composeTwRenderProps(className, slots?.item())}>\n      {props.children}\n    </ReactAriaComponent>\n  );\n});\n\n// Export pattern\nexport {ComponentRoot as Root, ComponentItem as Item, ...};\n```\n\n#### 4. **Key Implementation Details**:\n\n1. **Styling with Tailwind Variants**:\n   - Styles defined in `.styles.ts` files using `tv()` function from `tailwind-variants`\n   - **IMPORTANT**: Always import from `tailwind-variants`, never from `@heroui/standard` (which doesn't exist)\n   - **CRITICAL**: tailwind-variants already includes `twMerge` functionality, so NEVER manually use `twMerge`\n   - **RULE**: All component styles MUST be defined in separate `.styles.ts` files, NOT in the component implementation files\n   - Component implementation files (`.tsx`) should only contain logic and React Aria primitives\n   - Example imports:\n     ```typescript\n     import type {VariantProps} from \"tailwind-variants\";\n     import {tv} from \"tailwind-variants\";\n     ```\n   - Support for variants (primary, secondary, etc.)\n   - Compound variants for conditional styling\n   - Slot system for complex components\n\n2. **Component Features**:\n   - Built on React Aria Components for accessibility\n   - Use `forwardRef` for all components\n   - Display names follow: `HeroUI.ComponentName` or `HeroUI.Component.SubPart`\n   - Support render props from React Aria when available\n\n3. **Type Exports**:\n\n   ```typescript\n   // Export props for each component part\n   export type ComponentRootProps = {...}\n   export type ComponentItemProps = {...}\n   export type ComponentVariants = VariantProps<typeof componentVariants>\n   ```\n\n4. **Utilities** (`packages/react/src/utils/`):\n   - `composeTwRenderProps`: Merge Tailwind classes with render props\n   - `focusRingClasses`: Consistent focus styling\n   - `disabledClasses`: Disabled state styling\n   - `mapPropsVariants`: Separate variant props from component props\n\n5. **React Aria Components className Patterns**:\n\n   **CRITICAL**: React Aria components have different className prop behaviors:\n\n   **Components that support render props** (use `composeTwRenderProps`):\n   - Button, TextField, FieldError, Checkbox, CheckboxGroup\n   - Switch, RadioGroup, Radio, Slider (and Track, Thumb, Output)\n   - Popover, Tooltip, Tabs (and Tab, TabList, TabPanel)\n   - Link, Menu, MenuItem, Accordion (DisclosureGroup)\n\n   **Components that ONLY accept string className** (pass className directly):\n   - Label, Text, Input, TextArea\n   - Heading, Dialog, OverlayArrow\n\n   **Usage examples**:\n\n   ```typescript\n   // For render prop components - use composeTwRenderProps\n   <ButtonPrimitive\n     className={composeTwRenderProps(className, slots?.button())}\n   />\n\n   // For string-only components - pass className directly\n   <LabelPrimitive\n     className={slots?.label({className})}\n   />\n   // OR\n   <LabelPrimitive\n     className={labelVariants({size, variant, className})}\n   />\n   ```\n\n   **How to check**: If unsure, check the React Aria docs or try both approaches - TypeScript will error if a component doesn't support render props\n\n6. **Composition Pattern with Existing Components**:\n\n   **CRITICAL**: HeroUI follows a composition-based approach. Components should reuse existing primitives rather than creating component-specific versions.\n\n   **Key Principles**:\n   - **DO NOT** create component-specific Label, Description, or FieldError components\n   - **DO** reuse the existing `Label`, `Description`, and `FieldError` components\n   - **DO** use standard HTML composition patterns with `htmlFor`/`id` attributes\n\n   **Example Pattern**:\n\n   ```typescript\n   // ❌ WRONG - Component-specific label\n   export const Checkbox = {\n     Root: CheckboxRoot,\n     Label: CheckboxLabel, // Don't create this!\n   };\n\n   // ✅ CORRECT - Compose with existing components\n   import { Label } from \"@/components/label\";\n   import { Description } from \"@/components/description\";\n\n   // Usage:\n   <div className=\"flex items-center gap-3\">\n     <Checkbox id=\"terms\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <Label htmlFor=\"terms\">Accept terms</Label>\n   </div>\n\n   // With description:\n   <div className=\"flex gap-3\">\n     <Checkbox className=\"mt-0.5\" id=\"notifications\">\n       <Checkbox.Indicator />\n     </Checkbox>\n     <div className=\"flex flex-col gap-1\">\n       <Label htmlFor=\"notifications\">Email notifications</Label>\n       <Description>Get notified when someone mentions you</Description>\n     </div>\n   </div>\n   ```\n\n   **Components that follow this pattern**:\n   - Checkbox - uses external Label/Description\n   - Radio - uses external Label/Description\n   - Switch - uses external Label/Description\n   - TextField - provides slots for Label/Description/FieldError\n\n### Current Components\n\n**Completed**: accordion, alert, alert-dialog, autocomplete, avatar, badge, breadcrumbs, button, button-group, calendar, card, checkbox, checkbox-group, chip, close-button, color-area, color-field, color-picker, color-slider, color-swatch, color-swatch-picker, combo-box, date-field, date-picker, date-range-picker, description, disclosure, disclosure-group, drawer, dropdown, empty-state, error-message, field-error, fieldset, form, header, input, input-group, input-otp, kbd, label, link, list-box, list-box-item, list-box-section, menu, menu-item, menu-section, meter, modal, number-field, pagination, popover, progress-bar, progress-circle, radio, radio-group, range-calendar, scroll-shadow, search-field, select, separator, skeleton, slider, spinner, surface, switch, switch-group, table, tabs, tag, tag-group, textarea, textfield, time-field, toast, toggle-button, toggle-button-group, toolbar, tooltip, typography\n\n**In Progress**: calendar-year-picker\n\n> Source of truth: `packages/react/src/components/index.ts`.\n\n## Development Workflow\n\n### Standard Feature Development Process\n\n**IMPORTANT**: When working on any feature or improvement, Claude Code MUST follow this systematic workflow to ensure accuracy and code quality:\n\n1. **Research Phase**:\n   - Thoroughly research the feature/component requirements\n   - Study relevant documentation (React Aria, Tailwind CSS, etc.)\n   - Analyze existing similar implementations in the codebase\n   - Identify all dependencies and integration points\n\n2. **Planning Phase**:\n   - Create a detailed implementation plan with a comprehensive checklist\n   - Break down the task into specific, measurable steps\n   - Include testing and verification steps in the plan\n   - Present the plan for review before proceeding\n\n3. **Review & Correction Phase**:\n   - Review the plan for completeness and accuracy\n   - Make necessary corrections or adjustments\n   - Ensure all edge cases are considered\n   - Confirm the plan aligns with HeroUI patterns and conventions\n\n4. **Execution Phase**:\n   - Start executing the plan step by step\n   - Use the TodoWrite tool to track progress automatically\n   - Mark todos as in_progress when starting a task\n   - Mark todos as completed immediately after finishing each step\n   - Never batch completions - update status in real-time\n\n5. **Verification Phase**:\n   - Manually verify all changes work as expected\n   - Test API calls if backend changes were made\n   - Check frontend rendering and interactions\n   - Run lint and type checks: `pnpm lint && pnpm typecheck`\n   - Ensure all tests pass: `pnpm test`\n\n**Example Workflow**:\n\n```\nUser: \"Add a new Select component\"\n\nClaude:\n1. Research: Studies React Aria Select, existing patterns\n2. Plan: Creates detailed checklist with 15+ items\n3. Review: Presents plan for feedback\n4. Execute: Implements step-by-step with todo updates\n5. Verify: Tests component, runs checks, confirms functionality\n```\n\nThis workflow ensures thorough understanding, proper planning, and high-quality implementation with full transparency throughout the process.\n\n### Component Development Workflow\n\n1. **Creating New Components**:\n\n   **CRITICAL: Research & Design Phase**:\n   - **FIRST**: Check the Figma design for the component breakdown (e.g., Menu Container, Menu Item, etc.)\n   - **SECOND**: Research the React Aria Components documentation at https://react-spectrum.adobe.com/react-aria/\n   - Find the appropriate React Aria primitive (e.g., CheckboxGroup, Dialog, Select, etc.)\n   - Understand the React Aria API, props, and accessibility features\n   - Map Figma component pieces to React Aria components and plan the compound structure\n   - Plan how to adapt it to follow Radix UI's compound component pattern\n\n   **Component Creation - ALWAYS USE THE SCRIPT**:\n\n   ```bash\n   # Navigate to packages/react directory\n   cd packages/react\n\n   # Use the add:component script\n   pnpm add:component ComponentName\n\n   # Examples:\n   pnpm add:component Menu\n   pnpm add:component Select\n   pnpm add:component DatePicker\n   ```\n\n   This script will:\n   - Create all necessary files with proper structure\n   - Add the export to `src/components/index.ts`\n   - Generate boilerplate following HeroUI patterns\n   - Set up the component with TypeScript and proper exports\n\n   After creating the component:\n\n   ```bash\n   # Build to update package.json exports automatically\n   pnpm build\n   ```\n\n   **Implementation Steps**:\n   - Study existing HeroUI components (accordion, alert) to understand the compound pattern\n   - Use React Aria Components as the foundation for accessibility\n   - Transform React Aria's API to match Radix UI patterns:\n     - Single component → Multiple exported parts (Item, Trigger, Content, etc.)\n     - Props-based API → Composition-based API\n     - Internal state → Context-based state sharing\n   - Create Context for sharing styles across component parts\n   - Export ALL component parts for maximum customization\n   - Define styles in separate `.styles.ts` file with slot system\n   - Add \"use client\" directive at the top of component file\n   - Create comprehensive Storybook stories showing all variants and compositions\n   - Follow the export pattern: `export * as ComponentName from \"./component-name\"`\n\n   **Example Transformation**:\n\n   ```typescript\n   // React Aria: Single component with props\n   <CheckboxGroup label=\"Options\" value={selected} onChange={setSelected}>\n     <Checkbox value=\"1\">Option 1</Checkbox>\n   </CheckboxGroup>\n\n   // HeroUI: Compound pattern\n   <CheckboxGroup value={selected} onValueChange={setSelected}>\n     <CheckboxGroup.Label>Options</CheckboxGroup.Label>\n     <CheckboxGroup.Item value=\"1\">\n       <CheckboxGroup.Indicator />\n       <CheckboxGroup.Label>Option 1</CheckboxGroup.Label>\n     </CheckboxGroup.Item>\n   </CheckboxGroup>\n   ```\n\n   **Example of a compound component exports**\n\n   ```typescript\n   const CompoundAccordion = Object.assign(Accordion, {\n     Item: AccordionItem,\n     Heading: AccordionHeading,\n     Trigger: AccordionTrigger,\n     Panel: AccordionPanel,\n     Indicator: AccordionIndicator,\n     Body: AccordionBody,\n   });\n\n   export type {\n     AccordionProps,\n     AccordionItemProps,\n     AccordionTriggerProps,\n     AccordionPanelProps,\n     AccordionIndicatorProps,\n     AccordionBodyProps,\n   };\n\n   export default CompoundAccordion;\n   ```\n\n   **IMPORTANT**: The compound component should be exported as the default export.\n\n2. **Testing**:\n   - Follow Behavioral tests conventions above (semantics-first, `setupUser`, `data-*` state hooks)\n   - Run `pnpm test` for jsdom + browser; filter with `pnpm --filter @heroui/react exec vitest run <name>`\n   - Place tests under `packages/react/tests/components/<name>/` (`*.test.tsx` / `*.ssr.test.tsx` / `*.browser.test.tsx`, optional `fixtures.tsx`)\n   - Prefer arrow functions for harness helpers and test fixtures\n\n3. **Documentation**:\n   - Docs live in `apps/docs/content/`\n   - Uses MDX format\n   - HeroUI components are pre-imported\n\n4. **Version Management**:\n   - Uses [bumpp](https://github.com/antfu/bumpp) for version bumping\n   - Run `pnpm version:bump` to interactively bump the version, commit, and tag\n   - Pushing a `v*` tag triggers the release CI workflow\n   - Follow semantic versioning\n\n## Icon Library\n\n**IMPORTANT**: HeroUI uses Iconify with gravity-ui as the default icon set.\n\n## Important Notes\n\n- Always prefer editing existing files over creating new ones\n- **NEVER** create documentation files (_.md, _.mdx, README files) unless explicitly requested by the user\n- Follow the established component patterns and conventions\n- Ensure accessibility with React Aria Components\n- Maintain TypeScript type safety\n- Use the commit convention to avoid git hook failures\n- Run lint and type checks before committing: `pnpm lint && pnpm typecheck`\n\n## Tailwind CSS Class Detection Rules\n\n**CRITICAL**: Tailwind CSS scans files as plain text and requires complete class names to be statically detectable.\n\n### Key Rules:\n\n1. **Never construct class names dynamically**\n\n   ❌ **BAD** - Dynamic string concatenation:\n\n   ```jsx\n   // These patterns will NOT work:\n   <div className={`text-${color}-600`} />\n   <button className={`bg-${variant}-500`} />\n   <span className={`button--${size}`} />\n   ```\n\n   ✅ **GOOD** - Complete class names:\n\n   ```jsx\n   // Use complete strings or object mappings:\n   <div className={error ? \"text-red-600\" : \"text-green-600\"} />\n   ```\n\n2. **Use object mappings for dynamic classes**\n\n   ❌ **BAD** - Props in template literals:\n\n   ```jsx\n   function Button({color}) {\n     return <button className={`bg-${color}-600 hover:bg-${color}-500`} />;\n   }\n   ```\n\n   ✅ **GOOD** - Map props to complete classes:\n\n   ```jsx\n   function Button({color}) {\n     const colorVariants = {\n       blue: \"bg-blue-600 hover:bg-blue-500\",\n       red: \"bg-red-600 hover:bg-red-500\",\n     };\n     return <button className={colorVariants[color]} />;\n   }\n   ```\n\n3. **For BEM-style classes, use complete mappings**\n\n   ✅ **GOOD** - Complete class name mappings:\n\n   ```jsx\n   const sizeClasses = {\n     sm: \"button--sm\",\n     md: \"button--md\",\n     lg: \"button--lg\",\n   };\n\n   // Use the mapping:\n   className={sizeClasses[size]}\n   ```\n\n### Why This Matters:\n\n- Tailwind generates CSS only for classes it can detect in your source files\n- Dynamic concatenation prevents Tailwind from finding the complete class names\n- Missing classes = missing styles in production\n\n## Figma Integration & MCP Server Rules\n\n### Figma Dev Mode MCP Server\n\n**IMPORTANT**: When creating components with Figma designs:\n\n1. **Component Breakdown**: Figma designs are already broken down into component pieces (e.g., Menu Container, Menu Item, etc.). Use these as reference for:\n   - Component structure and naming (adapt to code conventions)\n   - Visual styling and spacing\n   - Component composition patterns\n\n2. **MCP Server Rules**:\n   - The Figma Dev Mode MCP Server provides an assets endpoint for images and SVG assets\n   - **CRITICAL**: If the Figma MCP Server returns a localhost source for an image or SVG, use that source directly\n   - **DO NOT** import or add new icon packages - all assets should come from the Figma payload\n   - **DO NOT** use or create placeholders if a localhost source is provided\n   - Always use the actual assets from Figma MCP Server\n\n3. **Workflow**:\n   - Check Figma for component visual design and breakdown\n   - Map Figma component names to appropriate React Aria primitives\n   - Use Figma assets (icons, images) directly from the MCP Server\n   - Implement styles based on Figma design tokens and specifications\n\n## Library Documentation with Context7 MCP\n\n**IMPORTANT**: We have the Context7 MCP server available (https://github.com/upstash/context7) for accessing up-to-date library documentation.\n\n### When to Use Context7\n\nUse Context7 MCP when working with external libraries, especially:\n\n- **Tailwind CSS v4**: When working with Tailwind CSS v4 features, use Context7 to get the latest documentation at https://context7.com/context7/tailwindcss\n- **Fumadocs**: When working on the documentation site in `apps/docs/`, use Context7 to get the latest Fumadocs framework documentation\n- **Next.js**: For Next.js specific features and APIs used in the docs app\n- Any other third-party libraries where up-to-date documentation is needed\n\n### How to Use Context7\n\n1. First, resolve the library ID using `mcp__context7__resolve-library-id`\n2. Then fetch documentation using `mcp__context7__get-library-docs` with the resolved ID\n3. This ensures you're always working with the latest documentation rather than outdated information\n\n### Example Usage Areas\n\n- Implementing new documentation features in `apps/docs/`\n- Configuring Fumadocs settings in `source.config.ts`\n- Working with MDX components and layouts\n- Setting up search functionality\n- Implementing documentation navigation and structure\n\n## GitHub Repository Search with Grep MCP\n\n**IMPORTANT**: We have the Grep MCP server available for searching over a million public GitHub repositories to find real-world code examples and patterns.\n\n### When to Use Grep MCP\n\nUse the Grep MCP (`mcp__grep__searchGitHub`) when tackling complex problems that require:\n\n- **Real-world implementation examples**: Finding how other developers solve similar problems\n- **Best practices and patterns**: Discovering production-ready code patterns\n- **Library usage examples**: Understanding how specific APIs or libraries are used in practice\n- **Complex integrations**: Seeing how different libraries work together\n- **Error handling patterns**: Learning from battle-tested error handling approaches\n\n### How to Use Grep MCP\n\nThe Grep MCP searches for **literal code patterns**, not keywords. Use actual code syntax:\n\n**Good examples**:\n\n- `'useState('` - Find React hooks usage\n- `'import { tv } from \"tailwind-variants\"'` - Find tailwind-variants imports\n- `'forwardRef<'` - Find forwardRef usage patterns\n- `'(?s)useEffect\\\\(\\\\(\\\\) => {.*return.*}'` - Find useEffect with cleanup (regex)\n\n**Bad examples**:\n\n- `'react best practices'` - This is a keyword, not code\n- `'how to use tailwind'` - Use actual import statements instead\n\n### Example Use Cases\n\n1. **Complex Component Patterns**:\n   - Search: `'compound.*component'` with language=['TypeScript', 'TSX']\n   - Find how others implement compound component patterns\n\n2. **Accessibility Implementations**:\n   - Search: `'AriaProps'` or `'useAriaLabel'`\n   - Discover accessibility patterns in React apps\n\n3. **Monorepo Configurations**:\n   - Search: `'pnpm-workspace.yaml'` with path='pnpm-workspace.yaml'\n   - Study monorepo setups similar to HeroUI\n\n4. **Tailwind CSS v4 Patterns**:\n   - Search: `'@import \"tailwindcss\"'` with language=['CSS']\n   - Find Tailwind CSS v4 usage patterns\n\n5. **React Aria Components Usage**:\n   - Search: `'from \"react-aria-components\"'`\n   - See how others integrate React Aria Components\n\n### Best Practices\n\n- Use language filters to narrow results (e.g., `language=['TypeScript', 'TSX']`)\n- Use regex patterns with `useRegexp=true` for flexible matching\n- Filter by well-known repositories for quality examples (e.g., `repo='vercel/'`)\n- Combine with file path filters for specific file types\n\n## Agent-Specific Guidelines\n\n### For style-migrator and tailwind-v4-css-expert Agents\n\nWhen working with HeroUI CSS components, follow these critical patterns:\n\n#### Default Size Implementation\n\n**REQUIRED**: All CSS components MUST follow the default size pattern:\n\n1. **Base classes** include default dimensions equivalent to `--md` variant\n2. **Medium variant** (`--md`) is an empty class with explanatory comment\n3. **Size variants** override the base defaults\n\n**Template for CSS components with size variants:**\n\n```css\n/* Base component styles */\n.component {\n  /* Base styling */\n  @apply [base-styles];\n\n  /* Default size - matches component--md variant */\n  @apply [default-size-classes];\n}\n\n/* Size variants */\n.component--sm {\n  @apply [small-size-overrides];\n}\n\n.component--md {\n  /* No styles as this is the default size */\n}\n\n.component--lg {\n  @apply [large-size-overrides];\n}\n```\n\n#### Pseudo-Class Fallback Pattern\n\n**REQUIRED**: All interactive components MUST include both pseudo-class and data-attribute support:\n\n```css\n/* Interactive states - both approaches */\n.component {\n  /* Hover states */\n  &:hover,\n  &[data-hovered=\"true\"] {\n    @apply [hover-styles];\n  }\n\n  /* Active/pressed states */\n  &:active,\n  &[data-pressed=\"true\"] {\n    @apply [active-styles];\n  }\n\n  /* Focus states */\n  &:focus-visible,\n  &:focus:not(:focus-visible),\n  &[data-focus-visible=\"true\"] {\n    outline: 2px solid var(--focus);\n    outline-offset: 2px;\n  }\n}\n```\n\n#### Component Examples\n\n- **button.css**: Base has `h-10 md:h-9`, empty `.button--md` variant\n- **avatar.css**: Base has `size-10`, empty `.avatar--md` variant\n- **spinner.css**: Base has `size-6`, empty `.spinner--md` variant\n\nThese patterns ensure components never appear broken and maintain consistency across the design system.\n","category":"root","tokens":7485}]}