Repository: zwgnr/BaseLayer Branch: main Commit: 3e7e74ea8517 Files: 217 Total size: 411.3 KB Directory structure: gitextract_31woigsj/ ├── .cursorrules ├── .github/ │ └── workflows/ │ └── sync-components.yml ├── .gitignore ├── .prototools ├── LICENSE.md ├── README.md ├── biome.json ├── package.json ├── packages/ │ ├── components/ │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── registry.json │ │ ├── scripts/ │ │ │ └── gen-registry-json.ts │ │ ├── src/ │ │ │ ├── core/ │ │ │ │ ├── accordion/ │ │ │ │ │ ├── accordion.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── badge/ │ │ │ │ │ ├── badge.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── breadcrumbs/ │ │ │ │ │ ├── breadcrumbs.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── button/ │ │ │ │ │ ├── button.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── calendar/ │ │ │ │ │ ├── calendar.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── card/ │ │ │ │ │ ├── card.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── checkbox/ │ │ │ │ │ ├── checkbox.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── combobox/ │ │ │ │ │ ├── combobox.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── command/ │ │ │ │ │ ├── command.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── date-field/ │ │ │ │ │ ├── date-field.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── date-picker/ │ │ │ │ │ ├── date-picker.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── index.ts │ │ │ │ ├── input/ │ │ │ │ │ ├── input.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── menu/ │ │ │ │ │ ├── menu.tsx │ │ │ │ │ └── meta.json │ │ │ │ ├── meter/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── meter.tsx │ │ │ │ ├── modal/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── modal.tsx │ │ │ │ ├── popover/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── popover.tsx │ │ │ │ ├── radio-group/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── radio-group.tsx │ │ │ │ ├── select/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── select.tsx │ │ │ │ ├── slider/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── slider.tsx │ │ │ │ ├── switch/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── switch.tsx │ │ │ │ ├── table/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── table.tsx │ │ │ │ ├── tabs/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── tabs.tsx │ │ │ │ ├── tag-group/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── tag-group.tsx │ │ │ │ ├── time-field/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── time-field.tsx │ │ │ │ ├── toggle/ │ │ │ │ │ ├── meta.json │ │ │ │ │ └── toggle.tsx │ │ │ │ └── tooltip/ │ │ │ │ ├── meta.json │ │ │ │ └── tooltip.tsx │ │ │ ├── examples/ │ │ │ │ ├── accordion-base.tsx │ │ │ │ ├── accordion-group.tsx │ │ │ │ ├── badge-base.tsx │ │ │ │ ├── badge-variants.tsx │ │ │ │ ├── breadcrumbs-base.tsx │ │ │ │ ├── breadcrumbs-seperators.tsx │ │ │ │ ├── button-base.tsx │ │ │ │ ├── button-helper-icons.tsx │ │ │ │ ├── button-sizes.tsx │ │ │ │ ├── button-variants.tsx │ │ │ │ ├── calendar-base.tsx │ │ │ │ ├── card-base.tsx │ │ │ │ ├── card-variants.tsx │ │ │ │ ├── checkbox-base.tsx │ │ │ │ ├── checkbox-group.tsx │ │ │ │ ├── combobox-base.tsx │ │ │ │ ├── combobox-disabled-option.tsx │ │ │ │ ├── combobox-menu-trigger.tsx │ │ │ │ ├── command-base.tsx │ │ │ │ ├── command-custom-trigger.tsx │ │ │ │ ├── date-field-base.tsx │ │ │ │ ├── date-picker-base.tsx │ │ │ │ ├── date-range-picker-base.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── input-base.tsx │ │ │ │ ├── input-disabled.tsx │ │ │ │ ├── input-label.tsx │ │ │ │ ├── menu-base.tsx │ │ │ │ ├── meter-base.tsx │ │ │ │ ├── modal-base.tsx │ │ │ │ ├── modal-dismissable.tsx │ │ │ │ ├── popover-base.tsx │ │ │ │ ├── radio-group-base.tsx │ │ │ │ ├── range-calendar-base.tsx │ │ │ │ ├── select-base.tsx │ │ │ │ ├── select-popover-classname.tsx │ │ │ │ ├── select-searchable.tsx │ │ │ │ ├── slider-base.tsx │ │ │ │ ├── switch-base.tsx │ │ │ │ ├── table-base.tsx │ │ │ │ ├── tabs-base.tsx │ │ │ │ ├── tag-group-base.tsx │ │ │ │ ├── time-field-base.tsx │ │ │ │ ├── toggle-base.tsx │ │ │ │ ├── toggle-group-base.tsx │ │ │ │ └── tooltip-base.tsx │ │ │ ├── index.ts │ │ │ └── tailwind.css │ │ └── tsconfig.json │ └── registry/ │ ├── CHANGELOG.md │ ├── package.json │ ├── src/ │ │ ├── index.ts │ │ └── schema.ts │ └── tsconfig.json ├── pnpm-workspace.yaml ├── turbo.json └── web/ ├── .gitignore ├── CHANGELOG.md ├── README.md ├── app/ │ ├── api/ │ │ ├── examples/ │ │ │ └── [name]/ │ │ │ └── route.ts │ │ └── search/ │ │ └── route.ts │ ├── docs/ │ │ ├── [...slug]/ │ │ │ └── page.tsx │ │ ├── content/ │ │ │ ├── components/ │ │ │ │ ├── accordion.mdx │ │ │ │ ├── badge.mdx │ │ │ │ ├── breadcrumbs.mdx │ │ │ │ ├── button.mdx │ │ │ │ ├── calendar.mdx │ │ │ │ ├── card.mdx │ │ │ │ ├── checkbox.mdx │ │ │ │ ├── combobox.mdx │ │ │ │ ├── command.mdx │ │ │ │ ├── date-field.mdx │ │ │ │ ├── date-picker.mdx │ │ │ │ ├── input.mdx │ │ │ │ ├── menu.mdx │ │ │ │ ├── meter.mdx │ │ │ │ ├── modal.mdx │ │ │ │ ├── popover.mdx │ │ │ │ ├── radio-group.mdx │ │ │ │ ├── select.mdx │ │ │ │ ├── slider.mdx │ │ │ │ ├── switch.mdx │ │ │ │ ├── table.mdx │ │ │ │ ├── tabs.mdx │ │ │ │ ├── tag-group.mdx │ │ │ │ ├── time-field.mdx │ │ │ │ ├── toggle.mdx │ │ │ │ └── tooltip.mdx │ │ │ ├── intro.mdx │ │ │ ├── styles.mdx │ │ │ └── usage.mdx │ │ ├── layout.tsx │ │ └── page.tsx │ ├── globals.css │ ├── layout.tsx │ ├── llms.txt/ │ │ └── route.ts │ ├── page.tsx │ └── r/ │ └── [[...segments]]/ │ └── route.ts ├── components/ │ ├── code-block-client.tsx │ ├── code-block.tsx │ ├── component-metadata.tsx │ ├── docs-page.tsx │ ├── mdx-components.tsx │ ├── mobile-nav.tsx │ ├── open-in-ai-menu.tsx │ ├── preview.tsx │ ├── rac-link.tsx │ ├── search.tsx │ ├── sidebar-link.tsx │ ├── sidebar.tsx │ ├── table-of-contents.tsx │ └── theme-toggle.tsx ├── components.json ├── hooks/ │ └── use-active-heading.ts ├── lib/ │ ├── component-data.ts │ ├── cx.ts │ ├── examples-map.ts │ ├── metadata.ts │ ├── navigation.ts │ └── source.ts ├── next.config.ts ├── package.json ├── postcss.config.mjs ├── public/ │ └── r/ │ ├── accordion.json │ ├── badge.json │ ├── breadcrumbs.json │ ├── button.json │ ├── calendar.json │ ├── card.json │ ├── checkbox.json │ ├── combobox.json │ ├── command.json │ ├── date-field.json │ ├── date-picker.json │ ├── input.json │ ├── menu.json │ ├── meter.json │ ├── modal.json │ ├── popover.json │ ├── radio-group.json │ ├── registry.json │ ├── select.json │ ├── slider.json │ ├── switch.json │ ├── table.json │ ├── tabs.json │ ├── tag-group.json │ ├── time-field.json │ ├── toggle.json │ └── tooltip.json ├── source.config.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cursorrules ================================================ # Cursor Rules ## General - Always use pnpm ================================================ FILE: .github/workflows/sync-components.yml ================================================ name: Component Sync Check on: pull_request: paths: - 'packages/components/src/**' - 'packages/components/scripts/**' - 'packages/components/package.json' push: branches: - main jobs: pr-check: if: github.event_name == 'pull_request' runs-on: ubuntu-latest name: Check Registry Drift steps: - name: Checkout uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10.12.1 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - name: Install dependencies run: pnpm install - name: Build registry dependency first run: pnpm --filter @baselayer/registry build - name: Build components and generate registry run: pnpm --filter @baselayer/components build - name: Check for registry drift run: | # Check registry.json and generated shadcn registry files if git diff --quiet packages/components/registry.json web/public/r/; then echo "✅ Registry is in sync" else echo "❌ Registry out of sync! Generated files differ from committed files." echo "" echo "Please run the following locally and commit the changes:" echo " pnpm --filter @baselayer/components build" echo "" echo "Changed files:" git diff --name-only packages/components/registry.json web/public/r/ echo "" echo "Diff:" git diff packages/components/registry.json web/public/r/ exit 1 fi build-and-test: if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest name: Build and Test steps: - name: Checkout uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10.12.1 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - name: Install dependencies run: pnpm install - name: Build all packages run: pnpm build ================================================ FILE: .gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies node_modules/ /.pnp .pnp.js # testing /coverage # next.js /.next/ /out/ # production /build /dist # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* # local env files .env.local .env # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts # turbo .turbo # pnpm .pnpm-store/ .pnpm-debug.log* # build outputs **/dist/ **/build/ **/.next/ **/.turbo/ # IDE and editor files .vscode/ .idea/ *.swp *.swo *~ .project .classpath .settings/ # OS generated files .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* # Runtime data pids *.pid *.seed *.pid.lock # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional stylelint cache .stylelintcache *.vsix # Go workspace file go.work ================================================ FILE: .prototools ================================================ pnpm = "10.12.2" ================================================ FILE: LICENSE.md ================================================ MIT License Copyright (c) 2025 Zach Wagner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # BaseLayer ## Overview BaseLayer is a comprehensive React component library built for modern development workflows and AI-powered tooling. It combines the accessibility and power of React Aria Components with the styling flexibility of Tailwind CSS, creating a robust foundation for building incredible user interfaces. ## Docs [https://baselayer.dev](https://baselayer.dev) ## Contributing Coming soon, but in the meantime, feel free to open an issue or [reach out!](https://x.com/zwagnr) ================================================ FILE: biome.json ================================================ { "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", "formatter": { "enabled": true }, "linter": { "enabled": true, "domains": { "next": "recommended" }, "rules": { "recommended": true, "nursery": { "useSortedClasses": { "level": "warn", "fix": "safe", "options": { "attributes": ["className"], "functions": ["cx", "tv"] } } } } }, "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ ["react", "react/**"], ":BLANK_LINE:", "next/**", ":BLANK_LINE:", "react-aria-components", "tailwind-variants", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", "@/hooks/**", ":BLANK_LINE:", ["@/lib/**", "@/utils/**"], ":BLANK_LINE:", "@/components/**", ":BLANK_LINE:", "~/**", ":BLANK_LINE:", ":PATH:" ] } } } } } } ================================================ FILE: package.json ================================================ { "name": "baselayer", "private": true, "version": "2.1.1", "description": "Beautiful, accessible, and AI optimized React components for the web.", "scripts": { "build": "turbo build", "dev": "turbo dev", "lint": "turbo lint", "clean": "turbo clean", "type-check": "turbo type-check" }, "devDependencies": { "@biomejs/biome": "2.2.5", "shadcn": "3.4.0", "turbo": "^2.5.8" }, "packageManager": "pnpm@10.12.1", "engines": { "node": "22.17.0" } } ================================================ FILE: packages/components/CHANGELOG.md ================================================ # @baselayer/components ## 2.0.3 ### Patch Changes - f594c82: update RAC + tw ## 2.0.2 ### Patch Changes - 6f88f68: mobile optimizations ## 2.0.1 ### Patch Changes - 6f94762: fix secondary button border ## 2.0.0 ### Major Changes - 7204382: v2 ### Patch Changes - Updated dependencies [7204382] - @baselayer/registry@2.0.0 ================================================ FILE: packages/components/package.json ================================================ { "name": "@baselayer/components", "version": "2.1.1", "private": true, "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "files": [ "src" ], "scripts": { "build": "tsc && pnpm generate:registry && pnpm registry:build", "dev": "tsc --watch", "generate:registry": "tsx scripts/gen-registry-json.ts", "registry:build": "shadcn build --cwd . --output ../../web/public/r" }, "dependencies": { "@baselayer/registry": "workspace:*", "lucide-react": "^0.525.0", "react": "^19.2.3", "react-aria-components": "catalog:", "tailwind-variants": "catalog:", "zod": "^3.25.67" }, "devDependencies": { "@types/node": "catalog:", "@types/react": "^19.2.7", "fast-glob": "^3.3.2", "ts-morph": "^26.0.0", "tsx": "^4.20.3", "tw-animate-css": "^1.3.6", "typescript": "catalog:" }, "peerDependencies": { "react": ">=19.0.0", "tailwindcss": ">=4.0.0" } } ================================================ FILE: packages/components/registry.json ================================================ { "name": "@baselayer", "$schema": "https://ui.shadcn.com/schema/registry.json", "homepage": "https://baselayer.dev", "items": [ { "name": "accordion", "type": "registry:ui", "title": "accordion", "description": "An accordion allows users to toggle the display of sections of content. Each accordion consists of a header with a title and content area.", "author": "BaseLayer", "categories": [ "layout" ], "files": [ { "path": "src/core/accordion/accordion.tsx", "target": "components/ui/accordion.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "disclosure", "collapsible", "expandable", "content" ] } }, { "name": "badge", "type": "registry:ui", "title": "badge", "description": "A badge is a small label that can be used to display information or status.", "author": "BaseLayer", "categories": [ "display" ], "files": [ { "path": "src/core/badge/badge.tsx", "target": "components/ui/badge.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "status" ] } }, { "name": "breadcrumbs", "type": "registry:ui", "title": "breadcrumbs", "description": "Breadcrumbs display a heirarchy of links to the current page or resource in an application.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", "target": "components/ui/breadcrumbs.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation" ] } }, { "name": "button", "type": "registry:ui", "title": "button", "description": "A button allows a user to perform an action, with mouse, touch, and keyboard interactions.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/button/button.tsx", "target": "components/ui/button.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "calendar", "type": "registry:ui", "title": "calendar", "description": "A calendar displays one or more date grids and allows users to select either a single date or a contiguous range of dates.", "author": "BaseLayer", "categories": [ "data-entry" ], "files": [ { "path": "src/core/calendar/calendar.tsx", "target": "components/ui/calendar.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] } }, { "name": "card", "type": "registry:ui", "title": "card", "description": "Displays a card with header, content, and footer.", "author": "BaseLayer", "categories": [ "layout" ], "files": [ { "path": "src/core/card/card.tsx", "target": "components/ui/card.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "layout", "container", "display" ] } }, { "name": "checkbox", "type": "registry:ui", "title": "checkbox", "description": "A checkbox allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/checkbox/checkbox.tsx", "target": "components/ui/checkbox.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "combobox", "type": "registry:ui", "title": "combobox", "description": "A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/combobox/combobox.tsx", "target": "components/ui/combobox.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] } }, { "name": "command", "type": "registry:ui", "title": "command", "description": "A command palette that allows users to quickly search and execute commands using keyboard shortcuts.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/command/command.tsx", "target": "components/ui/command.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "beta", "tags": [ "search", "navigation", "keyboard", "palette" ] } }, { "name": "date-field", "type": "registry:ui", "title": "date-field", "description": "A date field allows users to enter and edit date and time values using a keyboard. Each part of a date value is displayed in an individually editable segment.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/date-field/date-field.tsx", "target": "components/ui/date-field.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date" ] } }, { "name": "date-picker", "type": "registry:ui", "title": "date-picker", "description": "A date picker combines one or more DateFields with a calendar popover, allowing users to enter or select a single date/time or a range.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/date-picker/date-picker.tsx", "target": "components/ui/date-picker.tsx", "type": "registry:component" } ], "registryDependencies": [ "calendar" ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] } }, { "name": "input", "type": "registry:ui", "title": "input", "description": "Allows a user to enter a plain text value with a keyboard.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/input/input.tsx", "target": "components/ui/input.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "menu", "type": "registry:ui", "title": "menu", "description": "A menu displays a list of actions or options that a user can choose.", "author": "BaseLayer", "categories": [ "pickers" ], "files": [ { "path": "src/core/menu/menu.tsx", "target": "components/ui/menu.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "interactive", "navigation" ] } }, { "name": "meter", "type": "registry:ui", "title": "meter", "description": "A meter represents a quantity within a known range, or a fractional value.", "author": "BaseLayer", "categories": [ "data-display" ], "files": [ { "path": "src/core/meter/meter.tsx", "target": "components/ui/meter.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "progress" ] } }, { "name": "modal", "type": "registry:ui", "title": "modal", "description": "A modal is an overlay element which blocks interaction with elements outside it.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/modal/modal.tsx", "target": "components/ui/modal.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay" ] } }, { "name": "popover", "type": "registry:ui", "title": "popover", "description": "A popover is an overlay element positioned relative to a trigger.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/popover/popover.tsx", "target": "components/ui/popover.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive" ] } }, { "name": "radio-group", "type": "registry:ui", "title": "radio-group", "description": "A radio group allows a user to select a single option from a list of mutually exclusive options.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/radio-group/radio-group.tsx", "target": "components/ui/radio-group.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection" ] } }, { "name": "select", "type": "registry:ui", "title": "select", "description": "A select displays a collapsible list of options and allows a user to select one of them.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/select/select.tsx", "target": "components/ui/select.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] } }, { "name": "slider", "type": "registry:ui", "title": "slider", "description": "A slider allows a user to select one or more values within a range.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/slider/slider.tsx", "target": "components/ui/slider.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "range" ] } }, { "name": "switch", "type": "registry:ui", "title": "switch", "description": "A switch allows a user to turn a setting on or off.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/switch/switch.tsx", "target": "components/ui/switch.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] } }, { "name": "table", "type": "registry:ui", "title": "table", "description": "A table displays data in rows and columns and enables a user to navigate its contents via directional navigation keys, and optionally supports row selection and sorting.", "author": "BaseLayer", "categories": [ "data-display" ], "files": [ { "path": "src/core/table/table.tsx", "target": "components/ui/table.tsx", "type": "registry:component" } ], "registryDependencies": [ "button", "checkbox" ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "interactive" ] } }, { "name": "tabs", "type": "registry:ui", "title": "tabs", "description": "Tabs organize content into multiple sections and allow users to navigate between them.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/tabs/tabs.tsx", "target": "components/ui/tabs.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation", "interactive", "layout" ] } }, { "name": "tag-group", "type": "registry:ui", "title": "tag-group", "description": "A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/tag-group/tag-group.tsx", "target": "components/ui/tag-group.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection", "filtering" ] } }, { "name": "time-field", "type": "registry:ui", "title": "time-field", "description": "A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/time-field/time-field.tsx", "target": "components/ui/time-field.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "time" ] } }, { "name": "toggle", "type": "registry:ui", "title": "toggle", "description": "A toggle button allows a user to toggle a selection on or off, for example switching between two states or modes.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/toggle/toggle.tsx", "target": "components/ui/toggle.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] } }, { "name": "tooltip", "type": "registry:ui", "title": "tooltip", "description": "A tooltip displays a description of an element on hover or focus.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/tooltip/tooltip.tsx", "target": "components/ui/tooltip.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive", "help" ] } } ] } ================================================ FILE: packages/components/scripts/gen-registry-json.ts ================================================ /** biome-ignore-all lint/suspicious/noAssignInExpressions: skip */ import type { Registry, RegistryItem } from "@baselayer/registry"; import glob from "fast-glob"; import { existsSync, readFileSync, writeFileSync } from "node:fs"; const COMPONENTS_DIR = "src/core"; const OUTPUT_FILE = "registry.json"; async function generateRegistryJson() { console.log("Discovering components..."); // Find all component directories with meta.json files const metaFiles = await glob(`${COMPONENTS_DIR}/*/meta.json`); console.log(`Found ${metaFiles.length} components`); const registryItems: RegistryItem[] = []; for (const metaFilePath of metaFiles) { try { const component = await processComponent(metaFilePath); if (component) { registryItems.push(component); console.log(`Processed ${component.name}`); } } catch (error) { console.error(`Failed to process ${metaFilePath}:`, error); } } // Sort components by name for consistent output registryItems.sort((a, b) => a.name.localeCompare(b.name)); const registry: Registry = { name: "@baselayer", $schema: "https://ui.shadcn.com/schema/registry.json", homepage: "https://baselayer.dev", items: registryItems, }; const jsonContent = JSON.stringify(registry, null, 2); writeFileSync(OUTPUT_FILE, jsonContent); console.log( `Generated registry.json with ${registryItems.length} components`, ); console.log(`\nNext step: Run 'pnpm registry:build' to generate final files`); } async function processComponent( metaFilePath: string, ): Promise { // Extract component id from path (e.g., src/core/button/meta.json -> button) const componentId = metaFilePath.split("/").slice(-2, -1)[0]; // Read component metadata const metaContent = readFileSync(metaFilePath, "utf8"); const meta = JSON.parse(metaContent); // Read component source file const sourceFile = `${COMPONENTS_DIR}/${componentId}/${componentId}.tsx`; if (!existsSync(sourceFile)) { console.warn(`Source file not found: ${sourceFile}`); return null; } const sourceContent = readFileSync(sourceFile, "utf8"); // Detect registry dependencies (imports from other components in registry) const registryDependencies: string[] = []; // Match both relative imports and alias imports const relativeImportRegex = /from\s+["']\.\.\/([^/"']+)\/\1["']/g; const aliasImportRegex = /from\s+["']@\/components\/ui\/([^/"']+)\/\1["']/g; let match: RegExpExecArray | null; // Check relative imports while ((match = relativeImportRegex.exec(sourceContent)) !== null) { const depComponentId = match[1]; if (depComponentId !== componentId) { registryDependencies.push(depComponentId); } } // Check alias imports while ((match = aliasImportRegex.exec(sourceContent)) !== null) { const depComponentId = match[1]; if (depComponentId !== componentId) { registryDependencies.push(depComponentId); } } return { name: componentId, type: "registry:ui", title: meta.name, description: meta.description, author: "BaseLayer", categories: [meta.category], files: [ { path: `src/core/${componentId}/${componentId}.tsx`, target: `components/ui/${componentId}.tsx`, type: "registry:component", }, ], // Add registry dependencies (other components this depends on in registry) ...(registryDependencies.length > 0 && { registryDependencies }), // Add dependencies dependencies: [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css", ], tailwind: { config: { content: ["./components/**/*.{ts,tsx}"], theme: { extend: {}, }, }, }, // CSS variables cssVars: { theme: { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)", }, light: { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff", }, dark: { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)", }, }, // CSS imports and custom CSS css: { "@import \"tw-animate-css\"": {}, }, meta: { status: meta.status, tags: meta.tags, }, }; } generateRegistryJson().catch(console.error); ================================================ FILE: packages/components/src/core/accordion/accordion.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { Button, Disclosure, DisclosureGroup, type DisclosureGroupProps, DisclosurePanel, type DisclosureProps, Heading, } from "react-aria-components"; import { tv, type VariantProps } from "tailwind-variants"; import { Minus, Plus } from "lucide-react"; const accordion = tv({ slots: { root: "group w-full", group: "flex flex-col gap-3", button: "flex w-full items-center justify-between gap-6 rounded-2xl border border-border bg-surface-2 p-4 data-[focus-visible]:outline-none data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 data-[focus-visible]:ring-offset-surface group-data-[expanded]:rounded-b-none group-data-[expanded]:border-b-0", icon: "size-4 shrink-0 fill-none transition-transform duration-200", panel: "rounded-b-2xl border-border bg-surface-2 px-4 text-muted-foreground text-sm group-data-[expanded]:border-x group-data-[expanded]:border-b group-data-[expanded]:pb-4", }, }); const styles = accordion(); type AccordionVariantProps = VariantProps; interface AccordionProps extends AccordionVariantProps, Omit { className?: string; title?: string; children?: ReactNode; } const Accordion = ({ className, title, children, ...props }: AccordionProps) => { return ( {({ isExpanded }) => ( <> {children} )} ); }; interface AccordionGroupProps extends DisclosureGroupProps { className?: string; children: ReactNode; } const AccordionGroup = ({ className, children, ...props }: AccordionGroupProps) => ( {children} ); export { Accordion, AccordionGroup }; export type { AccordionProps, AccordionGroupProps }; ================================================ FILE: packages/components/src/core/accordion/meta.json ================================================ { "name": "accordion", "category": "layout", "status": "stable", "description": "An accordion allows users to toggle the display of sections of content. Each accordion consists of a header with a title and content area.", "tags": [ "disclosure", "collapsible", "expandable", "content" ] } ================================================ FILE: packages/components/src/core/badge/badge.tsx ================================================ import type { HTMLAttributes } from "react"; import { tv, type VariantProps } from "tailwind-variants"; export const badge = tv({ base: "flex items-center justify-center rounded-4xl px-3 py-2 font-semibold text-xs", variants: { variant: { attention: "bg-gradient-to-r from-pink-500 to-purple-500 text-white", neutral: "bg-secondary text-secondary-fg", danger: "bg-danger text-danger-fg", }, }, defaultVariants: { variant: "attention", }, }); type BadgeProps = VariantProps & HTMLAttributes; const Badge = ({ className, variant, ...props }: BadgeProps) => ( ); export { Badge }; export type { BadgeProps }; ================================================ FILE: packages/components/src/core/badge/meta.json ================================================ { "name": "badge", "category": "display", "status": "stable", "description": "A badge is a small label that can be used to display information or status.", "tags": [ "status" ] } ================================================ FILE: packages/components/src/core/breadcrumbs/breadcrumbs.tsx ================================================ "use client"; import { Breadcrumbs as AriaBreadcrumbs, type BreadcrumbsProps as AriaBreadcrumbsProps, Breadcrumb, type BreadcrumbProps, Link, type LinkProps, } from "react-aria-components"; import { tv } from "tailwind-variants"; const breadcrumbs = tv({ slots: { root: "m-0 flex list-none items-center gap-2 p-0 font-md", link: "relative cursor-pointer rounded-md text-fg outline-none ring-focus data-[hovered]:underline data-[focus-visible]:ring-2 [&[aria-current]]:font-extrabold [&[aria-current]]:text-fg", item: "flex items-center gap-2", }, }); const styles = breadcrumbs(); const Breadcrumbs = ({ children, className, ...props }: AriaBreadcrumbsProps & { className?: string }) => ( {children} ); const BreadcrumbsLink = ({ children, className, ...props }: LinkProps & { className?: string }) => ( {children} ); const BreadcrumbsItem = ({ children, className, ...props }: BreadcrumbProps & { className?: string }) => ( {children} ); export { BreadcrumbsItem, BreadcrumbsLink, Breadcrumbs }; ================================================ FILE: packages/components/src/core/breadcrumbs/meta.json ================================================ { "name": "breadcrumbs", "category": "navigation", "status": "stable", "description": "Breadcrumbs display a heirarchy of links to the current page or resource in an application.", "tags": [ "navigation" ] } ================================================ FILE: packages/components/src/core/button/button.tsx ================================================ "use client"; import { Button as AriaButton, type ButtonProps as AriaButtonProps, } from "react-aria-components"; import { tv, type VariantProps } from "tailwind-variants"; const button = tv({ base: "inline-flex appearance-none items-center justify-center rounded-full font-semibold outline-none ring-focus ring-offset-3 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[focus-visible]:ring-2", variants: { variant: { primary: "bg-primary text-primary-fg data-[hovered]:bg-primary/80", secondary: "border border-border text-fg data-[hovered]:border-secondary data-[hovered]:bg-secondary", ghost: "bg-transparent text-fg data-[hovered]:bg-secondary data-[hovered]:text-secondary-fg", danger: "border border-transparent bg-danger text-danger-fg data-[hovered]:bg-danger/80", }, size: { sm: "px-2 py-1.5 text-sm", md: "px-4 py-2.5 text-base", lg: "px-6 py-3.5 font-bold text-lg", icon: "size-9", }, }, defaultVariants: { variant: "primary", size: "md", }, }); type ButtonVariantProps = VariantProps; interface ButtonProps extends Omit, ButtonVariantProps { className?: string; } const Button = ({ className, size, variant, children, ...props }: ButtonProps) => ( {children} ); Button.displayName = "Button"; export { Button }; export type { ButtonProps }; ================================================ FILE: packages/components/src/core/button/meta.json ================================================ { "name": "button", "category": "forms", "status": "stable", "description": "A button allows a user to perform an action, with mouse, touch, and keyboard interactions.", "tags": [ "form", "interactive" ] } ================================================ FILE: packages/components/src/core/calendar/calendar.tsx ================================================ "use client"; import { Calendar as AriaCalendar, type CalendarProps as AriaCalendarProps, RangeCalendar as AriaRangeCalendar, type RangeCalendarProps as AriaRangeCalendarProps, Button, CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, type DateValue, Heading, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { ChevronLeft, ChevronRight } from "lucide-react"; const baseStyles = tv({ slots: { root: "w-fit max-w-full rounded-2xl border border-border bg-surface p-4 text-fg", header: "flex w-full items-center gap-1 pb-4", heading: "flex-1 text-center font-bold", headerCell: "pb-2 text-fg-muted text-sm", monthButton: "flex appearance-none items-center justify-center rounded-full p-2 text-center outline-none ring-focus data-[hovered]:bg-secondary data-[focus-visible]:ring-2", }, }); const calendar = tv({ extend: baseStyles, slots: { cell: "flex size-9 cursor-default items-center justify-center rounded-full border-border text-center text-sm outline-focus outline-offset-2 data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:outline-2 data-[focus-visible]:outline-focus [&[data-outside-month]]:hidden", }, }); const rangeCalendar = tv({ extend: baseStyles, slots: { cell: "flex size-9 cursor-default items-center justify-center rounded-full text-center text-sm outline-none outline-offset-2 data-[selected]:rounded-none data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 [&[data-outside-month]]:hidden [&[data-selection-end]]:rounded-r-full [&[data-selection-start]]:rounded-l-full", }, }); const styles = calendar(); const rangeStyles = rangeCalendar(); interface CalendarProps extends Omit, "className"> { errorMessage?: string; className?: string; } const Calendar = ({ className, errorMessage, ...props }: CalendarProps) => (
{(day) => ( {day} )} {(date) => } {errorMessage && ( {errorMessage} )}
); interface RangeCalendarProps extends Omit, "className"> { errorMessage?: string; className?: string; } const RangeCalendar = ({ className, errorMessage, ...props }: RangeCalendarProps) => (
{(day) => ( {day} )} {(date) => } {errorMessage && ( {errorMessage} )}
); export { Calendar, RangeCalendar }; export type { CalendarProps, RangeCalendarProps }; ================================================ FILE: packages/components/src/core/calendar/meta.json ================================================ { "name": "calendar", "category": "data-entry", "status": "stable", "description": "A calendar displays one or more date grids and allows users to select either a single date or a contiguous range of dates.", "tags": [ "form", "interactive", "date-time" ] } ================================================ FILE: packages/components/src/core/card/card.tsx ================================================ "use client"; import type { HTMLAttributes } from "react"; import { tv, type VariantProps } from "tailwind-variants"; const card = tv({ slots: { root: "rounded-2xl border-2 bg-surface text-fg", header: "flex flex-col space-y-1.5 p-6", title: "font-semibold text-2xl leading-none tracking-tight", description: "text-fg-muted text-sm", content: "p-6 pt-0", footer: "flex items-center p-6 pt-0", }, variants: { variant: { outlined: { root: "border border-border/50", }, filled: { root: "border-surface-2 bg-surface-2", }, }, }, defaultVariants: { variant: "outlined", }, }); const styles = card(); type CardVariantProps = VariantProps; interface CardProps extends HTMLAttributes, CardVariantProps { className?: string; title?: string; description?: string; } interface CardHeaderProps extends HTMLAttributes { className?: string; } interface CardContentProps extends HTMLAttributes { className?: string; } interface CardFooterProps extends HTMLAttributes { className?: string; } const Card = ({ className, variant, title, description, children, ...props }: CardProps) => (
{(title || description) && (
{title &&

{title}

} {description &&

{description}

}
)} {children}
); const CardHeader = ({ className, ...props }: CardHeaderProps) => (
); const CardContent = ({ className, ...props }: CardContentProps) => (
); const CardFooter = ({ className, ...props }: CardFooterProps) => (
); export { Card, CardHeader, CardContent, CardFooter }; export type { CardProps, CardHeaderProps, CardContentProps, CardFooterProps }; ================================================ FILE: packages/components/src/core/card/meta.json ================================================ { "name": "card", "category": "layout", "status": "stable", "description": "Displays a card with header, content, and footer.", "tags": [ "layout", "container", "display" ] } ================================================ FILE: packages/components/src/core/checkbox/checkbox.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { type CheckboxProps as AriaCheckBoxProps, Checkbox as AriaCheckbox, CheckboxGroup as AriaCheckboxGroup, type CheckboxGroupProps as AriaCheckboxGroupProps, FieldError, Text, type ValidationResult, } from "react-aria-components"; import { tv, type VariantProps } from "tailwind-variants"; import { Check } from "lucide-react"; const checkbox = tv({ base: "group flex items-center justify-center gap-2 py-1 text-fg", }); const checkboxGroup = tv({ base: "flex flex-col gap-2", }); type CheckboxVariantProps = VariantProps; interface CheckboxProps extends CheckboxVariantProps, AriaCheckBoxProps { className?: string; children: ReactNode; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); } const Checkbox = ({ className, errorMessage, children, description, ...props }: CheckboxProps) => { return ( {({ isSelected }) => ( <>
{isSelected && }
{children} {description && ( {description} )} {errorMessage} )}
); }; interface CheckboxGroupProps extends AriaCheckboxGroupProps { className?: string; label?: string; children: ReactNode; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); } const CheckboxGroup = ({ className, label, description, errorMessage, children, ...props }: CheckboxGroupProps) => ( {label && ( {label} )} {children} {description && ( {description} )} {errorMessage} ); export { Checkbox, CheckboxGroup }; export type { CheckboxProps, CheckboxGroupProps }; ================================================ FILE: packages/components/src/core/checkbox/meta.json ================================================ { "name": "checkbox", "category": "forms", "status": "stable", "description": "A checkbox allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.", "tags": [ "form", "interactive" ] } ================================================ FILE: packages/components/src/core/combobox/combobox.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { ComboBox as AriaComboBox, type ComboBoxProps as AriaComboBoxProps, Button, FieldError, Input, Label, ListBox, ListBoxItem, type ListBoxItemProps, Popover, Text, type ValidationResult, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { CheckIcon, ChevronsUpDown } from "lucide-react"; const combobox = tv({ slots: { root: "group max-h-inherit w-full overflow-auto p-1 outline-none", input: "w-full rounded-lg border border-border bg-surface px-4 py-1.5 align-middle font-semibold text-fg outline-none ring-fg transition-all group-data-[focused]:border-transparent group-data-[focused]:bg-surface group-data-[focused]:ring-2", button: "absolute right-2 flex appearance-none items-center justify-center rounded-full border-0 outline-none ring-focus ring-offset-2 ring-offset-surface data-[focus-visible]:ring-2", popover: "w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none", item: "relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled", }, }); const styles = combobox(); interface ComboBoxProps extends Omit, "className"> { className?: string; label?: string; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); } const ComboBox = ({ label, className, description, errorMessage, children, ...props }: ComboBoxProps) => ( {label && }
{description && ( {description} )} {errorMessage} {children}
); interface ComboBoxItemProps extends Omit { children: ReactNode; className?: string; } const ComboBoxItem = ({ className, ...props }: ComboBoxItemProps) => ( {({ isSelected }) => (
{props.children} {isSelected && }
)}
); export { ComboBox, ComboBoxItem }; export type { ComboBoxProps, ListBoxItemProps as ComboBoxItemProps }; ================================================ FILE: packages/components/src/core/combobox/meta.json ================================================ { "name": "combobox", "category": "forms", "status": "stable", "description": "A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.", "tags": [ "form", "interactive", "picker" ] } ================================================ FILE: packages/components/src/core/command/command.tsx ================================================ "use client"; import type { ComponentType, ReactNode } from "react"; import { useEffect, useState } from "react"; import { Button as AriaButton, Dialog as AriaDialog, DialogTrigger as AriaDialogTrigger, Modal as AriaModal, Autocomplete, Input, Menu, MenuItem, type MenuItemProps, ModalOverlay, type ModalOverlayProps, TextField, useFilter, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { Search } from "lucide-react"; const command = tv({ slots: { trigger: "flex w-full items-center justify-between rounded-full bg-secondary px-4 py-2 font-semibold text-fg outline-none ring-primary ring-offset-2 ring-offset-surface transition-colors data-[hovered]:bg-secondary/75 data-[focus-visible]:ring-2", overlay: "data-[entering]:fade-in data-[exiting]:fade-out fixed inset-0 z-50 flex min-h-full items-start justify-center bg-zinc-500/25 p-4 text-center data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200 sm:items-center", modal: "data-[entering]:zoom-in-95 data-[exiting]:zoom-out-95 data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200", dialog: "flex min-h-96 min-w-80 max-w-full flex-col gap-1 rounded-2xl bg-surface p-2 shadow-lg outline-none md:w-lg", input: "rounded-lg border-b-2 border-none bg-transparent px-3 py-2 text-base text-fg leading-5 outline-none placeholder:text-fg-muted", menu: "mt-2 h-80 overflow-auto", item: "group flex min-h-12 w-full cursor-default items-center rounded-lg px-3 py-2 text-fg outline-none data-[focused]:bg-secondary data-[pressed]:bg-surface-3 data-[focused]:text-focus-fg", kbd: "ml-auto rounded border border-border bg-surface-2 px-2 py-1 font-semibold text-fg-muted text-xs", }, }); const styles = command(); interface CommandItem { id: string; label: string; shortcut?: string; icon?: ComponentType<{ className?: string }>; onSelect?: () => void; } interface CommandProps extends Omit { className?: string; trigger?: ReactNode; commands: CommandItem[]; placeholder?: string; triggerKey?: string; onCommandSelect?: (command: CommandItem) => void; onSearchChange?: (search: string) => void; } const Command = ({ className, trigger, commands, placeholder = "Search commands…", triggerKey = "k", onCommandSelect, onSearchChange, ...props }: CommandProps) => { const [isOpen, setOpen] = useState(false); const [isMac, setIsMac] = useState(true); const { contains } = useFilter({ sensitivity: "base" }); useEffect(() => { setIsMac(/Mac/.test(navigator?.platform || "")); }, []); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ( e.key.toLowerCase() === triggerKey.toLowerCase() && (isMac ? e.metaKey : e.ctrlKey) ) { e.preventDefault(); setOpen((prev) => !prev); } else if (e.key === "Escape") { e.preventDefault(); setOpen(false); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [isMac, triggerKey]); const handleCommandSelect = (command: CommandItem) => { command.onSelect?.(); onCommandSelect?.(command); setOpen(false); }; return ( {trigger || (
Search
{isMac ? "⌘" : "Ctrl"} {triggerKey.toUpperCase()}
)} true : contains}> {({ label, shortcut, icon: Icon, ...command }) => ( handleCommandSelect({ label, shortcut, icon: Icon, ...command, }) } >
{Icon && ( )} {label}
{shortcut && ( {shortcut} )}
)}
); }; interface CommandMenuItemProps extends Omit { className?: string; children: ReactNode; } const CommandMenuItem = ({ className, children, ...props }: CommandMenuItemProps) => ( {children} ); const CommandTrigger = AriaDialogTrigger; export { Command, CommandMenuItem, CommandTrigger }; export type { CommandProps, CommandMenuItemProps, CommandItem }; ================================================ FILE: packages/components/src/core/command/meta.json ================================================ { "name": "command", "category": "navigation", "status": "beta", "description": "A command palette that allows users to quickly search and execute commands using keyboard shortcuts.", "tags": [ "search", "navigation", "keyboard", "palette" ] } ================================================ FILE: packages/components/src/core/date-field/date-field.tsx ================================================ "use client"; import type { DateFieldProps as AriaDateFieldProps, DateValue, } from "react-aria-components"; import { DateField as AriaDateField, DateInput, DateSegment, FieldError, Label, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; const dateField = tv({ slots: { input: "flex min-h-11 min-w-48 appearance-none items-center rounded-lg border border-border bg-surface px-3 py-0.5 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:border-none data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm", segmentStyles: "rounded-md p-1 text-end outline-none focus:text-primary-fg data-[focused]:bg-primary data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg", }, }); const styles = dateField(); interface DateFieldProps extends AriaDateFieldProps { label?: string; description?: string; errorMessage?: string; } const DateField = ({ label, description, errorMessage, ...props }: DateFieldProps) => ( {label && } {(segment) => ( )} {description && {description}} {errorMessage} ); export { DateField }; export type { DateFieldProps }; ================================================ FILE: packages/components/src/core/date-field/meta.json ================================================ { "name": "date-field", "category": "forms", "status": "stable", "description": "A date field allows users to enter and edit date and time values using a keyboard. Each part of a date value is displayed in an individually editable segment.", "tags": [ "form", "interactive", "date" ] } ================================================ FILE: packages/components/src/core/date-picker/date-picker.tsx ================================================ "use client"; import type { DatePickerProps as AriaDatePickerProps, DateRangePickerProps as AriaDateRangePickerProps, } from "react-aria-components"; import { DatePicker as AriaDatePicker, DateRangePicker as AriaDateRangePicker, Button, DateInput, DateSegment, type DateValue, Dialog, FieldError, Group, Label, Popover, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { ChevronDown } from "lucide-react"; import { Calendar, RangeCalendar } from "@/components/ui/calendar/calendar"; const baseStyles = tv({ slots: { input: "appearance-none rounded-lg px-3 py-1.5 outline-none ring-primary transition-all", popover: "overflow-auto rounded-2xl data-[entering]:animate-fade data-[exiting]:animate-fadeOut", }, }); const datePicker = tv({ extend: baseStyles, slots: { group: "relative flex min-h-11 w-auto min-w-48 items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface", dateSegment: "min-w-16 rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg", }, }); const dateRangePicker = tv({ extend: baseStyles, slots: { group: "relative flex min-h-11 w-full flex-wrap items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface", dateSegment: "rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg", separator: "px-2 text-fg-muted", }, }); const styles = datePicker(); const rangeStyles = dateRangePicker(); interface DatePickerProps extends AriaDatePickerProps { label?: string; description?: string; errorMessage?: string; } const DatePicker = ({ className, label, description, errorMessage, children, ...props }: DatePickerProps) => ( {label && } {(segment) => ( )} {description && ( {description} )} {errorMessage} ); interface DateRangePickerProps extends AriaDateRangePickerProps { label?: string; description?: string; errorMessage?: string; className?: string; } const DateRangePicker = ({ className, label, description, errorMessage, children, ...props }: DateRangePickerProps) => ( {label && } {(segment) => ( )} {(segment) => ( )} {description && ( {description} )} {errorMessage} ); export { DatePicker, DateRangePicker }; export type { DatePickerProps, DateRangePickerProps }; ================================================ FILE: packages/components/src/core/date-picker/meta.json ================================================ { "name": "date-picker", "category": "forms", "status": "stable", "description": "A date picker combines one or more DateFields with a calendar popover, allowing users to enter or select a single date/time or a range.", "tags": [ "form", "interactive", "date-time" ] } ================================================ FILE: packages/components/src/core/index.ts ================================================ export * from "./accordion/accordion"; export * from "./badge/badge"; export * from "./breadcrumbs/breadcrumbs"; export * from "./button/button"; export * from "./calendar/calendar"; export * from "./card/card"; export * from "./checkbox/checkbox"; export * from "./combobox/combobox"; export * from "./command/command"; export * from "./date-field/date-field"; export * from "./date-picker/date-picker"; export * from "./input/input"; export * from "./menu/menu"; export * from "./meter/meter"; export * from "./modal/modal"; export * from "./popover/popover"; export * from "./radio-group/radio-group"; export * from "./select/select"; export * from "./slider/slider"; export * from "./switch/switch"; export * from "./table/table"; export * from "./tabs/tabs"; export * from "./tag-group/tag-group"; export * from "./time-field/time-field"; export * from "./toggle/toggle"; export * from "./tooltip/tooltip"; ================================================ FILE: packages/components/src/core/input/input.tsx ================================================ "use client"; import type { TextFieldProps as AriaTextFieldProps, ValidationResult, } from "react-aria-components"; import { Input as AriaInput, TextField as AriaTextField, FieldError, Label, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; const input = tv({ base: "min-h-11 appearance-none rounded-lg border border-border bg-surface px-3 py-1 text-fg outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focused]:border-transparent data-[disabled]:bg-primary/10 data-[disabled]:text-fg-disabled data-[focused]:ring-2 [&::placeholder]:text-fg-muted [&::placeholder]:text-sm", }); interface InputProps extends Omit { className?: string; label?: string; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); placeholder?: string; } const Input = ({ label, description, errorMessage, placeholder, className, ...props }: InputProps) => ( {label && } {description && ( {description} )} {errorMessage} ); export { Input }; export type { InputProps }; ================================================ FILE: packages/components/src/core/input/meta.json ================================================ { "name": "input", "category": "forms", "status": "stable", "description": "Allows a user to enter a plain text value with a keyboard.", "tags": [ "form", "interactive" ] } ================================================ FILE: packages/components/src/core/menu/menu.tsx ================================================ "use client"; import type { HTMLAttributes } from "react"; import { Header as AriaHeader, Menu as AriaMenu, MenuItem as AriaMenuItem, MenuSection as AriaMenuSection, MenuTrigger as AriaMenuTrigger, type MenuItemProps, type MenuProps, Popover, Separator, } from "react-aria-components"; import { tv } from "tailwind-variants"; export const menu = tv({ slots: { menuPopover: "data-[entering]:fade-in data-[exiting]:fade-out overflow-auto rounded-2xl border border-border/25 bg-surface shadow-xl data-[entering]:animate-in data-[exiting]:animate-out", header: "p-2 font-semibold", content: "flex h-fit min-w-56 flex-col gap-2 p-3 outline-none", item: "relative flex cursor-default justify-between rounded-lg p-3 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled", separator: "h-[1px] bg-border", }, }); const { menuPopover, content, header, item, separator } = menu(); const MenuTrigger = AriaMenuTrigger; const MenuSection = AriaMenuSection; const MenuContent = ({ children, className, ...props }: MenuProps & { className?: string }) => ( {children} ); const MenuItem = ({ children, className, ...props }: MenuItemProps & { className?: string }) => ( {children} ); const MenuHeader = ({ children, className, ...props }: HTMLAttributes & { className?: string }) => ( {children} ); const MenuSeperator = ({ className, ...props }: HTMLAttributes & { className?: string }) => ( ); export { MenuContent, MenuHeader, MenuItem, MenuSeperator, MenuTrigger, MenuSection, }; ================================================ FILE: packages/components/src/core/menu/meta.json ================================================ { "name": "menu", "category": "pickers", "status": "stable", "description": "A menu displays a list of actions or options that a user can choose.", "tags": [ "interactive", "navigation" ] } ================================================ FILE: packages/components/src/core/meter/meta.json ================================================ { "name": "meter", "category": "data-display", "status": "stable", "description": "A meter represents a quantity within a known range, or a fractional value.", "tags": [ "data-display", "progress" ] } ================================================ FILE: packages/components/src/core/meter/meter.tsx ================================================ "use client"; import { Meter as AriaMeter, type MeterProps as AriaMeterProps, Label, } from "react-aria-components"; import { tv } from "tailwind-variants"; const bar = tv({ base: "h-4 overflow-hidden rounded-2xl bg-surface-2", }); interface MeterProps extends Omit { label?: string; className?: string; } const Meter = ({ label, className, ...props }: MeterProps) => ( {({ percentage, valueText }) => ( <>
{label && } {valueText}
)} ); export { Meter }; export type { MeterProps }; ================================================ FILE: packages/components/src/core/modal/meta.json ================================================ { "name": "modal", "category": "overlays", "status": "stable", "description": "A modal is an overlay element which blocks interaction with elements outside it.", "tags": [ "overlay" ] } ================================================ FILE: packages/components/src/core/modal/modal.tsx ================================================ "use client"; import { Dialog as AriaDialog, DialogTrigger as AriaDialogTrigger, Modal as AriaModal, type DialogProps, ModalOverlay, type ModalOverlayProps, } from "react-aria-components"; import { tv } from "tailwind-variants"; export const modal = tv({ slots: { dialog: "flex w-full flex-col gap-6 outline-none", modalStyles: "fade-in w-full rounded-2xl bg-surface p-6 text-fg outline-none data-[entering]:animate-in md:w-md", }, }); const styles = modal(); interface ModalProps extends Omit { className?: string; } const Modal = ({ children, className, ...props }: ModalProps) => ( {children} ); const Dialog = ({ children, className, ...props }: DialogProps) => ( {children} ); const ModalTrigger = AriaDialogTrigger; export { Modal, Dialog, ModalTrigger }; export type { ModalProps, DialogProps }; ================================================ FILE: packages/components/src/core/popover/meta.json ================================================ { "name": "popover", "category": "overlays", "status": "stable", "description": "A popover is an overlay element positioned relative to a trigger.", "tags": [ "overlay", "interactive" ] } ================================================ FILE: packages/components/src/core/popover/popover.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { DialogTrigger as AriaDialogTrigger, Popover as AriaPopover, type PopoverProps as AriaPopoverProps, Dialog, } from "react-aria-components"; import { tv } from "tailwind-variants"; export const popover = tv({ base: "data-[entering]:fade-in data-[exiting]:fade-out m-1 max-w-lg rounded-2xl border border-border/25 bg-surface p-2 text-fg shadow-lg outline-none data-[entering]:animate-in data-[exiting]:animate-out", }); interface DialogProps extends Omit { children: ReactNode; className?: string; } const PopoverTrigger = AriaDialogTrigger; const Popover = ({ children, className, ...props }: DialogProps) => ( {children} ); export { Popover, PopoverTrigger }; ================================================ FILE: packages/components/src/core/radio-group/meta.json ================================================ { "name": "radio-group", "category": "forms", "status": "stable", "description": "A radio group allows a user to select a single option from a list of mutually exclusive options.", "tags": [ "form", "interactive", "selection" ] } ================================================ FILE: packages/components/src/core/radio-group/radio-group.tsx ================================================ "use client"; import type { ReactNode } from "react"; import type { RadioGroupProps as AriaRadioGroupProps, RadioProps, ValidationResult, } from "react-aria-components"; import { Radio as AriaRadio, RadioGroup as AriaRadioGroup, FieldError, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; const radioGroup = tv({ slots: { radio: "flex items-center gap-4 text-fg before:block before:h-5 before:w-5 before:rounded-full before:border before:border-border before:ring-focus before:ring-offset-2 before:ring-offset-surface before:transition-all data-[selected]:before:border-4 data-[selected]:before:border-primary data-[focus-visible]:before:ring-2", group: "flex flex-col gap-4 text-fg", }, }); const { group, radio } = radioGroup(); interface RadioGroupProps extends Omit { className?: string; children?: ReactNode; label?: string; description?: string; errorMessage?: string | ((validation: ValidationResult) => string) } const RadioGroup = ({ className, label, description, errorMessage, children, ...props }: RadioGroupProps) => ( {label} {children} {description && {description}} {errorMessage} ); const Radio = ({ children, className, ...props }: RadioProps & { className?: string; }) => ( {children} ); export { RadioGroup, Radio }; ================================================ FILE: packages/components/src/core/select/meta.json ================================================ { "name": "select", "category": "forms", "status": "stable", "description": "A select displays a collapsible list of options and allows a user to select one of them.", "tags": [ "form", "interactive", "picker" ] } ================================================ FILE: packages/components/src/core/select/select.tsx ================================================ "use client"; import type { ReactNode } from "react"; import type { SelectProps as AriaSelectProps, ListBoxItemProps, ValidationResult, } from "react-aria-components"; import { Select as AriaSelect, Autocomplete, Button, FieldError, Input, Label, ListBox, ListBoxItem, Popover, SearchField, SelectValue, Text, useFilter, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { CheckIcon, ChevronDown, Search } from "lucide-react"; const select = tv({ slots: { group: "group flex flex-col gap-1", button: "group flex w-fit items-center justify-between gap-4 rounded-full border border-border bg-surface px-4 py-2.75 align-middle font-semibold text-fg text-sm outline-none ring-fg transition-all data-[hovered]:bg-surface-2 group-data-[focus-visible]:border-transparent group-data-[open]:bg-surface-2 group-data-[focus-visible]:ring-2", item: "relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled", searchField: "group m-1 flex items-center rounded-full border border-border bg-surface px-2 py-1.5", searchInput: "flex-1 bg-transparent text-fg outline-none placeholder:text-fg-muted", searchIcon: "mr-2 size-4 text-fg-muted", clearButton: "ml-2 rounded p-0.5 text-fg-muted transition-colors hover:bg-surface-2 hover:text-fg group-empty:invisible", popover: "min-w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none", }, }); const styles = select(); interface SelectProps extends Omit, "className"> { className?: string; popoverClassName?: string; label?: string; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); } const Select = ({ label, className, description, errorMessage, popoverClassName, children, ...props }: SelectProps) => ( {label && } {description && ( {description} )} {errorMessage} {children} ); interface SelectItemProps extends Omit { children: ReactNode; className?: string; } const SelectItem = ({ className, ...props }: SelectItemProps) => ( {({ isSelected }) => (
{props.children} {isSelected && }
)}
); interface SearchableSelectProps extends SelectProps { searchPlaceholder?: string; } const SearchableSelect = ({ label, className, description, errorMessage, searchPlaceholder = "Search...", children, popoverClassName, ...props }: SearchableSelectProps) => { const { contains } = useFilter({ sensitivity: "base" }); return ( {label && } {description && ( {description} )} {errorMessage} {children} ); }; export { Select, SelectItem, SearchableSelect }; export type { SelectProps, SelectItemProps, SearchableSelectProps }; ================================================ FILE: packages/components/src/core/slider/meta.json ================================================ { "name": "slider", "category": "forms", "status": "stable", "description": "A slider allows a user to select one or more values within a range.", "tags": [ "form", "interactive", "range" ] } ================================================ FILE: packages/components/src/core/slider/slider.tsx ================================================ "use client"; import { Slider as AriaSlider, SliderThumb as AriaSliderThumb, SliderTrack as AriaSliderTrack, Label, type LabelProps, SliderOutput, type SliderProps, type SliderThumbProps, } from "react-aria-components"; import { tv } from "tailwind-variants"; const slider = tv({ slots: { root: "grid w-64 auto-cols-fr grid-cols-1 text-fg-muted", thumb: "h-5 w-5 rounded-full bg-primary ring-focus ring-offset-2 ring-offset-surface data-[dragging]:outline-2 data-[focus-visible]:ring-2", track: "before:-translate-y-1/2 relative col-span-2 col-start-1 w-full before:absolute before:top-1/2 before:h-0.5 before:w-full before:transform before:bg-secondary", }, }); const { root, thumb, track } = slider(); const SliderRoot = ({ children, className, ...props }: SliderProps & { className?: string }) => ( {children} ); const SliderThumb = ({ children, className, ...props }: SliderThumbProps & { className?: string }) => ( ); const SliderLabel = ({ children, className, ...props }: LabelProps & { className?: string }) => (
); export { SliderRoot, SliderThumb, SliderLabel }; ================================================ FILE: packages/components/src/core/switch/meta.json ================================================ { "name": "switch", "category": "forms", "status": "stable", "description": "A switch allows a user to turn a setting on or off.", "tags": [ "form", "interactive", "toggle" ] } ================================================ FILE: packages/components/src/core/switch/switch.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { Switch as AriaSwitch, type SwitchProps as AriaSwitchProps, Label, } from "react-aria-components"; import { tv } from "tailwind-variants"; const switchStyles = tv({ slots: { root: "group flex items-center gap-2 transition-none duration-200", indicator: "h-6 w-10 cursor-pointer rounded-xl bg-secondary duration-200 before:mx-[3px] before:mt-[3px] before:block before:size-4.5 before:rounded-2xl before:bg-surface before:transition-all data-[selected]:bg-primary group-data-[selected]:bg-primary group-data-[focus-visible]:ring-2 group-data-[focus-visible]:ring-focus group-data-[focus-visible]:ring-offset-2 group-data-[focus-visible]:ring-offset-surface group-data-[selected]:before:translate-x-4", label: "font-semibold text-fg text-sm", }, }); const styles = switchStyles(); interface SwitchProps extends AriaSwitchProps { children?: ReactNode; className?: string; } const Switch = ({ className, children, ...restProps }: SwitchProps) => (
); export { Switch }; export type { SwitchProps }; ================================================ FILE: packages/components/src/core/table/meta.json ================================================ { "name": "table", "category": "data-display", "status": "stable", "description": "A table displays data in rows and columns and enables a user to navigate its contents via directional navigation keys, and optionally supports row selection and sorting.", "tags": [ "data-display", "interactive" ] } ================================================ FILE: packages/components/src/core/table/table.tsx ================================================ "use client"; import { Column as AriaColumn, Table as AriaTable, TableBody as AriaTableBody, TableHeader as AriaTableheader, Cell, type CellProps, Collection, type ColumnProps, Row, type RowProps, type TableHeaderProps, type TableProps, useTableOptions, } from "react-aria-components"; import { tv } from "tailwind-variants"; import { Menu } from "lucide-react"; import { Button } from "@/components/ui/button/button"; import { Checkbox } from "@/components/ui/checkbox/checkbox"; const table = tv({ slots: { root: "table min-h-[100px] border-separate border-spacing-0 rounded-xl border border-border p-4 outline-none", column: "border-border border-b-2 px-4 py-1 text-left outline-none", header: "text-fg after:table-row after:h-[2px]", label: "text-fg-3", row: "relative cursor-default rounded-xl text-fg outline-none ring-focus data-[focus-visible]:ring-2", cell: "px-4 py-2 outline-none ring-focus data-[focus-visible]:ring-2", }, }); const styles = table(); const TableBody = AriaTableBody; const Table = ({ children, className, ...props }: TableProps & { className?: string }) => ( {children} ); const TableCell = ({ children, className, ...props }: CellProps & { className?: string }) => ( {children} ); const TableColumn = ({ children, className, ...props }: ColumnProps & { className?: string }) => ( {children} ); const TableHeader = ({ children, className, columns, ...props }: TableHeaderProps & { className?: string }) => { const { selectionBehavior, selectionMode, allowsDragging } = useTableOptions(); return ( {/* Add extra columns for drag and drop and selection. */} {allowsDragging && } {selectionBehavior === "toggle" && ( {selectionMode === "multiple" && ( )} )} {children} ); }; const TableRow = ({ children, className, columns, id, ...props }: RowProps & { className?: string }) => { const { selectionBehavior, allowsDragging } = useTableOptions(); return ( {allowsDragging && ( )} {selectionBehavior === "toggle" && ( )} {children} ); }; export { TableColumn, Table, TableBody, TableCell, TableHeader, TableRow }; ================================================ FILE: packages/components/src/core/tabs/meta.json ================================================ { "name": "tabs", "category": "navigation", "status": "stable", "description": "Tabs organize content into multiple sections and allow users to navigate between them.", "tags": [ "navigation", "interactive", "layout" ] } ================================================ FILE: packages/components/src/core/tabs/tabs.tsx ================================================ "use client"; import { Tab as AriaTab, TabList as AriaTabList, type TabListProps as AriaTabListProps, TabPanel as AriaTabPanel, type TabPanelProps as AriaTabPanelProps, type TabProps as AriaTabProps, type TabsProps as AriaTabsProps, Tabs as AriaTabsRoot, } from "react-aria-components"; import { tv } from "tailwind-variants"; const tabs = tv({ slots: { root: "flex w-full flex-col items-start", list: "relative inline-flex items-center justify-between gap-6 rounded-md p-1", tab: "relative flex w-fit cursor-pointer justify-center rounded-2xl border-primary pb-0.5 font-semibold text-fg-muted outline-none ring-focus ring-offset-2 ring-offset-surface transition-colors duration-200 aria-selected:cursor-default aria-selected:rounded-none aria-selected:border-b-2 aria-selected:pb-0 aria-selected:text-primary aria-selected:hover:bg-transparent data-[hovered]:text-primary data-[focus-visible]:ring-2", panel: "mt-4 w-96 rounded-xl p-4 outline-none ring-focus data-[focus-visible]:ring-2", }, }); const styles = tabs(); interface TabsProps extends Omit { className?: string; } const TabsRoot = ({ children, className, ...props }: TabsProps) => ( {children} ); interface TabListProps extends Omit, "className"> { className?: string; } const TabList = ({ children, className, ...props }: TabListProps) => ( {children} ); interface TabProps extends Omit { className?: string; } const Tab = ({ children, className, ...props }: TabProps) => ( {children} ); interface TabPanelProps extends Omit { className?: string; } const TabPanel = ({ children, className, ...props }: TabPanelProps) => ( {children} ); export { Tab, TabList, TabPanel, TabsRoot }; export type { TabsProps, TabListProps, TabProps, TabPanelProps }; ================================================ FILE: packages/components/src/core/tag-group/meta.json ================================================ { "name": "tag-group", "category": "forms", "status": "stable", "description": "A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", "tags": [ "form", "interactive", "selection", "filtering" ] } ================================================ FILE: packages/components/src/core/tag-group/tag-group.tsx ================================================ "use client"; import { Tag as AriaTag, TagGroup as AriaTagGroup, type TagGroupProps as AriaTagGroupProps, type TagProps as AriaTagProps, Label, TagList, type TagListProps, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; const tagGroup = tv({ slots: { root: "flex flex-col gap-2 text-sm", list: "flex flex-wrap gap-2", tag: "flex cursor-default items-center rounded-full border border-border px-2 py-1 outline-none ring-focus ring-offset-2 ring-offset-surface aria-selected:border-primary aria-selected:bg-primary aria-selected:text-primary-fg data-[focus-visible]:ring-2", }, }); const styles = tagGroup(); interface TagGroupProps extends Omit, Pick, "items" | "children" | "renderEmptyState"> { label?: string; description?: string; errorMessage?: string; } const TagGroup = ({ label, className, description, errorMessage, items, children, renderEmptyState, ...props }: TagGroupProps) => ( {label && } {children} {description && ( {description} )} {errorMessage && ( {errorMessage} )} ); const Tag = ({ children, className, ...props }: AriaTagProps & { className?: string }) => { const textValue = typeof children === "string" ? children : undefined; return ( {children} ); }; export { Tag, TagGroup }; ================================================ FILE: packages/components/src/core/time-field/meta.json ================================================ { "name": "time-field", "category": "forms", "status": "stable", "description": "A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.", "tags": [ "form", "interactive", "time" ] } ================================================ FILE: packages/components/src/core/time-field/time-field.tsx ================================================ "use client"; import type { TimeFieldProps as AriaTimeFieldProps, TimeValue, } from "react-aria-components"; import { TimeField as AriaTimeField, DateInput, DateSegment, FieldError, Label, Text, } from "react-aria-components"; import { tv } from "tailwind-variants"; const timeField = tv({ slots: { input: "appearance-none rounded-lg border border-border bg-surface px-3 py-1.75 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm [&::placeholder]:focus:text-primary-fg", segmentStyles: "rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted", }, }); const styles = timeField(); interface TimeFieldProps extends AriaTimeFieldProps { label?: string; description?: string; errorMessage?: string; } const TimeField = ({ label, description, errorMessage, ...props }: TimeFieldProps) => ( {label && } {(segment) => ( )} {description && ( {description} )} {errorMessage} ); export { TimeField }; export type { TimeFieldProps }; ================================================ FILE: packages/components/src/core/toggle/meta.json ================================================ { "name": "toggle", "category": "forms", "status": "stable", "description": "A toggle button allows a user to toggle a selection on or off, for example switching between two states or modes.", "tags": [ "form", "interactive", "toggle" ] } ================================================ FILE: packages/components/src/core/toggle/toggle.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { ToggleButton, ToggleButtonGroup, type ToggleButtonGroupProps, type ToggleButtonProps, } from "react-aria-components"; import { tv } from "tailwind-variants"; const toggle = tv({ base: "inline-flex appearance-none items-center justify-center rounded-full bg-surface-2 px-4 py-1 font-medium outline-none ring-focus ring-offset-2 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[selected]:bg-primary data-[selected]:text-primary-fg data-[focus-visible]:ring-2", }); const toggleGroup = tv({ base: "flex min-h-11 gap-1 rounded-full border border-border bg-surface-2 p-1", }); interface ToggleProps extends Omit { className?: string; } const Toggle = ({ className, children, ...props }: ToggleProps) => ( {children} ); interface ToggleGroupProps extends ToggleButtonGroupProps { className?: string; children: ReactNode; } const ToggleGroup = ({ className, children, ...props }: ToggleGroupProps) => ( {children} ); export { Toggle, ToggleGroup }; export type { ToggleProps, ToggleGroupProps }; ================================================ FILE: packages/components/src/core/tooltip/meta.json ================================================ { "name": "tooltip", "category": "overlays", "status": "stable", "description": "A tooltip displays a description of an element on hover or focus.", "tags": [ "overlay", "interactive", "help" ] } ================================================ FILE: packages/components/src/core/tooltip/tooltip.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { Tooltip as AriaTooltip, type TooltipProps as AriaTooltipProps, TooltipTrigger as AriaTooltipTrigger, } from "react-aria-components"; import { tv } from "tailwind-variants"; const tooltip = tv({ base: "[&[data-entering]]:fade-in [&[data-exiting]]:fade-out m-1 max-w-sm rounded-full border border-border bg-surface px-4 py-2 text-fg shadow-xl outline-none [&[data-entering]]:animate-fade-in [&[data-exiting]]:animate-fade-out", }); const TooltipTrigger = AriaTooltipTrigger; interface TooltipProps extends Omit { className?: string; children: ReactNode; } const Tooltip = ({ children, className, ...props }: TooltipProps) => ( {children} ); export { Tooltip, TooltipTrigger }; ================================================ FILE: packages/components/src/examples/accordion-base.tsx ================================================ import { Accordion } from "../core/accordion/accordion"; export const AccordionBase = () => { return ( You can cancel your subscription at any time by going to your account settings and clicking "Cancel Subscription". Your access will continue until the end of your current billing period, and you won't be charged again. All your data will be safely stored for 30 days in case you decide to reactivate. ); }; ================================================ FILE: packages/components/src/examples/accordion-group.tsx ================================================ import { Accordion, AccordionGroup } from "../core/accordion/accordion"; export const AccordionGroupExample = () => { return (

Quick Setup: Install our SDK with npm install @company/sdk

API Key: Generate your API key from the dashboard

First Request: Make your first API call in under 5 minutes

Our comprehensive documentation includes code examples in Python, JavaScript, and cURL. Start building in minutes with our interactive tutorials.

API Keys: Secure your requests with bearer token authentication

Rate Limits: 1,000 requests per minute on free tier, unlimited on pro

Webhooks: Real-time notifications with 256-bit SSL encryption

Enterprise-grade security with SOC 2 compliance, end-to-end encryption, and 99.9% uptime SLA.

Official SDKs: JavaScript, Python, Ruby, Go, PHP

Frameworks: React, Vue, Angular, Next.js components

Platforms: Slack, Discord, Teams, Notion integrations

Join 50,000+ developers using our APIs. Browse community-built packages and contribute to our open-source ecosystem.

); }; ================================================ FILE: packages/components/src/examples/badge-base.tsx ================================================ import { Badge } from "../core/badge/badge"; export const BadgeBase = () => { return ( New ); }; ================================================ FILE: packages/components/src/examples/badge-variants.tsx ================================================ import { Badge } from "../core/badge/badge"; export const BadgeVariants = () => { return (
Attention Neutral Danger
); }; ================================================ FILE: packages/components/src/examples/breadcrumbs-base.tsx ================================================ import { ChevronRightIcon } from "lucide-react"; import { Breadcrumbs, BreadcrumbsItem, BreadcrumbsLink } from "../core/breadcrumbs/breadcrumbs"; export const BreadcrumbsBase = () => { return (
Home Documents Recent
); }; ================================================ FILE: packages/components/src/examples/breadcrumbs-seperators.tsx ================================================ import { SlashIcon } from "lucide-react"; import { Breadcrumbs, BreadcrumbsItem, BreadcrumbsLink } from "../core/breadcrumbs/breadcrumbs"; export const BreadcrumbsSeperators = () => { return (
Home Documents Recent
); }; ================================================ FILE: packages/components/src/examples/button-base.tsx ================================================ import { Button } from "../core/button/button"; export const ButtonBase = () => { return ( ); }; ================================================ FILE: packages/components/src/examples/button-helper-icons.tsx ================================================ import { PlusIcon, TrashIcon } from "lucide-react"; import { Button } from "../core/button/button"; export const ButtonHelperIcons = () => { return (
); }; ================================================ FILE: packages/components/src/examples/button-sizes.tsx ================================================ import { PlusIcon } from "lucide-react"; import { Button } from "../core/button/button"; export const ButtonSizes = () => { return (
); }; ================================================ FILE: packages/components/src/examples/button-variants.tsx ================================================ import { Button } from "../core/button/button"; export const ButtonVariants = () => { return (
); }; ================================================ FILE: packages/components/src/examples/calendar-base.tsx ================================================ import { Calendar } from "../core/calendar/calendar"; export const CalendarExample = () => (
); ================================================ FILE: packages/components/src/examples/card-base.tsx ================================================ import { GithubIcon } from "lucide-react"; import { Button } from "../core/button/button"; import { Card, CardContent, CardFooter } from "../core/card/card"; import { Input } from "../core/input/input"; export const CardBase = () => { return (
); }; ================================================ FILE: packages/components/src/examples/card-variants.tsx ================================================ import { Card, CardContent } from "../core/card/card"; export const CardVariants = () => { return (

Content goes here with outlined border.

Content goes here with surface 2 background.

); }; ================================================ FILE: packages/components/src/examples/checkbox-base.tsx ================================================ import { Checkbox } from "../core/checkbox/checkbox"; export const CheckboxBase = () => { return ( Accept terms and conditions ); }; ================================================ FILE: packages/components/src/examples/checkbox-group.tsx ================================================ import { Checkbox, CheckboxGroup } from "../core/checkbox/checkbox"; export const CheckboxGroupExample = () => { return ( Option 1 Option 2 Option 3 ); }; ================================================ FILE: packages/components/src/examples/combobox-base.tsx ================================================ import { ComboBox, ComboBoxItem } from "../core/combobox/combobox"; const countries = [ "United States", "United Kingdom", "Canada", "Australia", "Germany", "France", "Japan", "Brazil", "India", "China", "Mexico", "Netherlands", "Sweden", "Norway", "Italy", ]; export const ComboboxBase = () => { return (
{countries.map((country) => ( {country} ))}
); }; ================================================ FILE: packages/components/src/examples/combobox-disabled-option.tsx ================================================ import { ComboBox, ComboBoxItem } from "../core/combobox/combobox"; export const ComboboxDisabledOption = () => { return (
ChatGPT Gemini Claude
); }; ================================================ FILE: packages/components/src/examples/combobox-menu-trigger.tsx ================================================ import { ComboBox, ComboBoxItem } from "../core/combobox/combobox"; export const ComboboxMenuTrigger = () => { return (
ChatGPT Gemini Claude
); }; ================================================ FILE: packages/components/src/examples/command-base.tsx ================================================ "use client"; import { Calendar, FileBarChart, Flag, FolderPlus, MessageSquare, Plus, RotateCcw, Target, UserPlus, Users, } from "lucide-react"; import { Command, type CommandItem } from "../core/command/command"; export const CommandBase = () => { const commands = [ { id: "create-task", label: "Create new task", icon: Plus }, { id: "create-project", label: "Create new project", icon: FolderPlus }, { id: "assign-task", label: "Assign task to team member", icon: UserPlus }, { id: "set-priority", label: "Set task priority", icon: Flag }, { id: "change-status", label: "Change task status", icon: RotateCcw }, { id: "add-comment", label: "Add comment to task", icon: MessageSquare }, { id: "set-deadline", label: "Set task deadline", icon: Calendar }, { id: "create-milestone", label: "Create project milestone", icon: Target }, { id: "generate-report", label: "Generate project report", icon: FileBarChart, }, { id: "invite-member", label: "Invite team member", icon: Users }, ] satisfies CommandItem[]; return (
{ console.log("Executed:", command.label); }} />
); }; ================================================ FILE: packages/components/src/examples/command-custom-trigger.tsx ================================================ "use client"; import { Calendar, FileBarChart, Flag, FolderPlus, MessageSquare, Plus, RotateCcw, Search, Target, UserPlus, Users, } from "lucide-react"; import { Button } from "../core/button/button"; import { Command, type CommandItem } from "../core/command/command"; export const CommandCustomTrigger = () => { const commands = [ { id: "create-task", label: "Create new task", icon: Plus }, { id: "create-project", label: "Create new project", icon: FolderPlus }, { id: "assign-task", label: "Assign task to team member", icon: UserPlus }, { id: "set-priority", label: "Set task priority", icon: Flag }, { id: "change-status", label: "Change task status", icon: RotateCcw }, { id: "add-comment", label: "Add comment to task", icon: MessageSquare }, { id: "set-deadline", label: "Set task deadline", icon: Calendar }, { id: "create-milestone", label: "Create project milestone", icon: Target }, { id: "generate-report", label: "Generate project report", icon: FileBarChart, }, { id: "invite-member", label: "Invite team member", icon: Users }, ] satisfies CommandItem[]; return (
Search commands } onCommandSelect={(command) => { console.log("Executed:", command.label); }} />
); }; ================================================ FILE: packages/components/src/examples/date-field-base.tsx ================================================ import { DateField } from "../core/date-field/date-field"; export const DateFieldBase = () => { return ; }; ================================================ FILE: packages/components/src/examples/date-picker-base.tsx ================================================ import { DatePicker } from "../core/date-picker/date-picker"; export const DatePickerBase = () => ; ================================================ FILE: packages/components/src/examples/date-range-picker-base.tsx ================================================ import { DateRangePicker } from "../core/date-picker/date-picker"; export const DateRangePickerBase = () => (
); ================================================ FILE: packages/components/src/examples/index.ts ================================================ export * from "./accordion-base"; export * from "./accordion-group"; export * from "./badge-base"; export * from "./badge-variants"; export * from "./breadcrumbs-base"; export * from "./breadcrumbs-seperators"; export * from "./button-base"; export * from "./button-helper-icons"; export * from "./button-sizes"; export * from "./button-variants"; export * from "./calendar-base"; export * from "./card-base"; export * from "./card-variants"; export * from "./checkbox-base"; export * from "./checkbox-group"; export * from "./combobox-base"; export * from "./combobox-disabled-option"; export * from "./combobox-menu-trigger"; export * from "./command-base"; export * from "./command-custom-trigger"; export * from "./date-field-base"; export * from "./date-picker-base"; export * from "./date-range-picker-base"; export * from "./input-base"; export * from "./input-disabled"; export * from "./input-label"; export * from "./menu-base"; export * from "./meter-base"; export * from "./modal-base"; export * from "./modal-dismissable"; export * from "./popover-base"; export * from "./radio-group-base"; export * from "./range-calendar-base"; export * from "./select-base"; export * from "./select-popover-classname"; export * from "./select-searchable"; export * from "./slider-base"; export * from "./switch-base"; export * from "./table-base"; export * from "./tabs-base"; export * from "./tag-group-base"; export * from "./time-field-base"; export * from "./toggle-base"; export * from "./toggle-group-base"; export * from "./tooltip-base"; ================================================ FILE: packages/components/src/examples/input-base.tsx ================================================ import { Input } from "../core/input/input"; export const InputBase = () => { return (
); }; ================================================ FILE: packages/components/src/examples/input-disabled.tsx ================================================ import { Input } from "../core/input/input"; export const InputDisabled = () => { return (
); }; ================================================ FILE: packages/components/src/examples/input-label.tsx ================================================ import { Input } from "../core/input/input"; export const InputLabel = () => { return (
); }; ================================================ FILE: packages/components/src/examples/menu-base.tsx ================================================ import { HelpCircle, LogOut, Plus, Settings, } from "lucide-react"; import { Button } from "../core/button/button"; import { MenuContent, MenuHeader, MenuItem, MenuSection, MenuSeperator, MenuTrigger, } from "../core/menu/menu"; export const Menu = () => { return ( me@hello.com Account Settings Add Account Support Logout ); }; ================================================ FILE: packages/components/src/examples/meter-base.tsx ================================================ import { Meter } from "../core/meter/meter"; export const MeterExample = () => ; ================================================ FILE: packages/components/src/examples/modal-base.tsx ================================================ "use client"; import { Heading } from "react-aria-components"; import { Button } from "../core/button/button"; import { Input } from "../core/input/input"; import { Dialog, Modal, ModalTrigger } from "../core/modal/modal"; export const ModalExample = () => { return ( Edit Name
); }; ================================================ FILE: packages/components/src/examples/modal-dismissable.tsx ================================================ "use client"; import { Heading } from "react-aria-components"; import { Button } from "../core/button/button"; import { Input } from "../core/input/input"; import { Dialog, Modal, ModalTrigger } from "../core/modal/modal"; export const ModalDismissable = () => { return ( Edit Name
); }; ================================================ FILE: packages/components/src/examples/popover-base.tsx ================================================ import { Calendar, MapPin, MessageCircle, Settings, Star, User } from "lucide-react"; import { Button } from "../core/button/button"; import { Popover, PopoverTrigger } from "../core/popover/popover"; export const PopoverExample = () => (

Alex Morgan

Senior Product Designer

San Francisco, CA
127
Projects
4.9
Rating
2.1k
Followers

Passionate about creating intuitive user experiences and building design systems that scale.

); ================================================ FILE: packages/components/src/examples/radio-group-base.tsx ================================================ import { Radio, RadioGroup } from "../core/radio-group/radio-group"; export const RadioExample = () => ( Email Phone Call Text Message ); ================================================ FILE: packages/components/src/examples/range-calendar-base.tsx ================================================ import { RangeCalendar } from "../core/calendar/calendar"; export const RangeCalendarBase = () => ; ================================================ FILE: packages/components/src/examples/select-base.tsx ================================================ import { Select, SelectItem } from "../core/select/select"; export const SelectExample = () => { return ( ); }; ================================================ FILE: packages/components/src/examples/select-popover-classname.tsx ================================================ import { Select, SelectItem } from "../core/select/select"; export const SelectPopoverClassname = () => { return ( ); }; ================================================ FILE: packages/components/src/examples/select-searchable.tsx ================================================ import { SearchableSelect, SelectItem } from "../core/select/select"; export const SearchableSelectExample = () => { return (
4o o3 Sonnet 4 Gemini 2.0
); }; ================================================ FILE: packages/components/src/examples/slider-base.tsx ================================================ import { SliderLabel, SliderRoot, SliderThumb } from "../core/slider/slider"; export const Slider = () => { return ( Temperature ); }; ================================================ FILE: packages/components/src/examples/switch-base.tsx ================================================ import { Switch } from "../core/switch/switch"; export const SwitchBase = () => { return On/Off; }; ================================================ FILE: packages/components/src/examples/table-base.tsx ================================================ "use client"; import { Table, TableBody, TableCell, TableColumn, TableHeader, TableRow, } from "../core/table/table"; interface User { id: number; name: string; email: string; role: string; status: "Active" | "Inactive" | "Pending"; } const users: User[] = [ { id: 1, name: "Alice Johnson", email: "alice@example.com", role: "Admin", status: "Active", }, { id: 2, name: "Bob Smith", email: "bob@example.com", role: "Developer", status: "Active", }, { id: 3, name: "Carol Davis", email: "carol@example.com", role: "Designer", status: "Pending", }, { id: 4, name: "David Wilson", email: "david@example.com", role: "Developer", status: "Inactive", }, { id: 5, name: "Eva Brown", email: "eva@example.com", role: "Manager", status: "Active", }, ]; export const TableExample = () => (
Name Email Role Status {(user) => ( {user.name} {user.email} {user.role} {user.status} )}
); ================================================ FILE: packages/components/src/examples/tabs-base.tsx ================================================ import { ArrowDown, Heart, Plus } from "lucide-react"; import { Tab, TabList, TabPanel, TabsRoot } from "../core/tabs/tabs"; export const TabsExample = () => { return ( For You Browse Library

Made for You

Electric Dreams

Synthwave Collective

3:42

Ocean Breeze

Coastal Sounds

4:15

Forest Whispers

Nature's Symphony

5:28

Golden Sunrise

Morning Acoustic

3:21

New Releases

Neon Dreams

Electric Pulse

Ocean Waves

Ambient Sound

Forest Walk

Nature Sounds

Golden Hour

Indie Folk

Cosmic Dance

Electronic

Midnight Jazz

Jazz Collection

Your Music

Liked Songs

47 songs

Downloaded

23 songs

Recently Added

12 songs

); }; ================================================ FILE: packages/components/src/examples/tag-group-base.tsx ================================================ import { Tag, TagGroup } from "../core/tag-group/tag-group"; export const TagGroupExample = () => (
React TypeScript Node.js CSS Design Systems GraphQL Frontend Backend Design DevOps
); ================================================ FILE: packages/components/src/examples/time-field-base.tsx ================================================ "use client"; import { TimeField } from "../core/time-field/time-field"; export const TimeFieldExample = () => (
); ================================================ FILE: packages/components/src/examples/toggle-base.tsx ================================================ import { Toggle } from "../core/toggle/toggle"; export const ToggleExample = () => Mode; ================================================ FILE: packages/components/src/examples/toggle-group-base.tsx ================================================ import { LayoutGrid, List, SquareStack } from "lucide-react"; import { Toggle, ToggleGroup } from "../core/toggle/toggle"; export const ToggleGroupExample = () => ( ); ================================================ FILE: packages/components/src/examples/tooltip-base.tsx ================================================ import { Settings, Share } from "lucide-react"; import { Button } from "../core/button/button"; import { Tooltip, TooltipTrigger } from "../core/tooltip/tooltip"; export const TooltipExample = () => (
This is a helpful tooltip message Settings Share this content with others
); ================================================ FILE: packages/components/src/index.ts ================================================ export * from "./core"; export * from "./examples"; ================================================ FILE: packages/components/src/tailwind.css ================================================ @variant dark ([data-theme="dark"] &); :root { /* SURFACES (neutrals & elevation) */ --surface: oklch(98.5% 0 0); /* app/page background */ --surface-2: oklch(97% 0 0); /* card / raised */ /* CONTENT (foreground) */ --fg: oklch(14.5% 0 0); /* primary reading text */ --fg-muted: oklch(55.6% 0 0); /* secondary text, captions */ --fg-inverse: oklch(98.5% 0 0); /* text on dark */ --fg-disabled: oklch(70.8% 0 0); /* explicit disabled state text */ /* OUTLINES & DIVIDERS */ --border: oklch(87% 0 0); /* generic 1px rules, inputs */ --focus: oklch(68.5% 0.169 237.323); /* focus ring / a11y outline */ /* INTERACTIVE ROLES (paired bg / fg ) */ --primary: oklch(14.5% 0 0); --primary-fg: oklch(98.5% 0 0); --secondary: oklch(92.2% 0 0); --secondary-fg: oklch(14.5% 0 0); /* STATUS / FUNCTIONAL */ --danger: oklch(63.7% 0.237 25.331); --danger-fg: #ffffff; } [data-theme='dark'] { /* SURFACES (neutrals & elevation) */ --surface: oklch(14.5% 0 0); /* app/page background */ --surface-2: oklch(20.5% 0 0); /* card / raised */ /* CONTENT (foreground) */ --fg: oklch(98.5% 0.001 106.423); /* primary reading text */ --fg-muted: oklch(55.6% 0 0); /* secondary text, captions */ --fg-inverse: oklch(98.5% 0 0); /* text on dark */ --fg-disabled: oklch(37.1% 0 0); /* explicit disabled state text */ /* OUTLINES & DIVIDERS */ --border: oklch(37.1% 0 0); /* generic 1px rules, inputs */ --focus: oklch(68.5% 0.169 237.323); /* focus ring / a11y outline */ /* INTERACTIVE ROLES (paired bg / fg ) */ --primary: oklch(98.5% 0 0); --primary-fg: oklch(14.5% 0 0); --secondary: oklch(26.9% 0 0); --secondary-fg: oklch(98.5% 0 0); /* STATUS / FUNCTIONAL */ --danger: oklch(63.7% 0.237 25.331); --danger-fg: oklch(98.5% 0 0); } @theme { --color-surface: var(--surface); --color-surface-2: var(--surface-2); --color-fg: var(--fg); --color-fg-muted: var(--fg-muted); --color-fg-disabled: var(--fg-disabled); --color-fg-inverse: var(--fg-inverse); --color-border: var(--border); --color-focus: var(--focus); --color-primary: var(--primary); --color-primary-fg: var(--primary-fg); --color-secondary: var(--secondary); --color-secondary-fg: var(--secondary-fg); --color-danger: var(--danger); --color-danger-fg: var(--danger-fg); } /* clears the ‘X’ from Internet Explorer */ input[type="search"]::-ms-clear { display: none; width: 0; height: 0; } input[type="search"]::-ms-reveal { display: none; width: 0; height: 0; } /* clears the ‘X’ from Chrome */ input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-results-button, input[type="search"]::-webkit-search-results-decoration { display: none; } ================================================ FILE: packages/components/tsconfig.json ================================================ { "compilerOptions": { "target": "ES2020", "lib": ["DOM", "DOM.Iterable", "ES6"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": false, "jsx": "react-jsx", "declaration": true, "outDir": "./dist", "rootDir": "./src", "baseUrl": ".", "paths": { "@/components/ui/*": ["src/core/*"] } }, "include": [ "src/**/*" ], "exclude": [ "node_modules", "dist", "**/*.test.*" ] } ================================================ FILE: packages/registry/CHANGELOG.md ================================================ # @baselayer/registry ## 2.0.0 ### Major Changes - 7204382: v2 ================================================ FILE: packages/registry/package.json ================================================ { "name": "@baselayer/registry", "version": "2.1.0", "private": true, "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ "dist", "src" ], "scripts": { "build": "tsc", "dev": "tsc --watch", "type-check": "tsc --noEmit" }, "dependencies": { "zod": "^3.25.67" }, "devDependencies": { "@types/node": "catalog:", "typescript": "catalog:" }, "keywords": [ "baselayer", "registry", "schema" ], "author": "zwgnr", "license": "MIT" } ================================================ FILE: packages/registry/src/index.ts ================================================ // Registry package entry point // Exports all schemas and types for component registry export * from './schema.js'; ================================================ FILE: packages/registry/src/schema.ts ================================================ // Registry Schema Definition // This defines the structure for machine-readable component metadata compatible with shadcn import { z } from "zod"; // Zod schemas for shadcn registry compatibility export const RegistryItemFileSchema = z.object({ path: z.string(), content: z.string().optional(), type: z.enum([ "registry:block", "registry:component", "registry:lib", "registry:hook", "registry:ui", "registry:page", "registry:file", "registry:style", "registry:theme", "registry:item", ]), target: z.string().optional(), }); export const RegistryItemSchema = z.object({ name: z.string(), type: z.enum([ "registry:block", // Complex components with multiple files "registry:component", // Simple components "registry:lib", // Lib and utils "registry:hook", // Hooks "registry:ui", // UI components and single-file primitives "registry:page", // Page or file-based routes "registry:file", // Miscellaneous files "registry:style", // Registry styles (e.g. new-york) "registry:theme", // Themes "registry:item", // Universal registry items ]), title: z.string().optional(), description: z.string().optional(), author: z.string().optional(), categories: z.array(z.string()).optional(), docs: z.string().optional(), registryDependencies: z.array(z.string()).optional(), dependencies: z.array(z.string()).optional(), devDependencies: z.array(z.string()).optional(), files: z.array(RegistryItemFileSchema), tailwind: z .object({ config: z.record(z.any()).optional(), }) .optional(), cssVars: z.record(z.any()).optional(), css: z.record(z.any()).optional(), meta: z.record(z.any()).optional(), }); export const RegistrySchema = z.object({ name: z.string(), $schema: z.string(), homepage: z.string().url().optional(), items: z.array(RegistryItemSchema), }); // Derived TypeScript types export type RegistryItem = z.infer; export type RegistryItemFile = z.infer; export type Registry = z.infer; ================================================ FILE: packages/registry/tsconfig.json ================================================ { "compilerOptions": { "target": "ES2020", "lib": ["ES6"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": false, "declaration": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ================================================ FILE: pnpm-workspace.yaml ================================================ packages: - 'web' - 'packages/*' # Define a catalog of version ranges. catalog: react-aria-components: 1.11.0 tailwind-variants: 2.1.0 typescript: ^5.8.3 "@types/node": ^24.0.3 ================================================ FILE: turbo.json ================================================ { "$schema": "https://turbo.build/schema.json", "ui": "tui", "tasks": { "build": { "dependsOn": ["^build"], "outputs": [".next/**", "!.next/cache/**", "dist/**"] }, "dev": { "cache": false, "persistent": true }, "lint": { "dependsOn": ["^build"] }, "type-check": { "dependsOn": ["^build"] }, "clean": { "cache": false } } } ================================================ FILE: web/.gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/versions # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts # fumadocs generated files .source/ ================================================ FILE: web/CHANGELOG.md ================================================ # @baselayer/web ## 2.0.3 ### Patch Changes - f594c82: update RAC + tw - Updated dependencies [f594c82] - @baselayer/components@2.0.3 ## 2.0.2 ### Patch Changes - 6f88f68: mobile optimizations - Updated dependencies [6f88f68] - @baselayer/components@2.0.2 ## 2.0.1 ### Patch Changes - Updated dependencies [6f94762] - @baselayer/components@2.0.1 ## 2.0.0 ### Major Changes - 7204382: v2 ### Patch Changes - Updated dependencies [7204382] - @baselayer/components@2.0.0 - @baselayer/registry@2.0.0 ================================================ FILE: web/README.md ================================================ # baselayer v2 ================================================ FILE: web/app/api/examples/[name]/route.ts ================================================ import { NextResponse } from "next/server"; import { getExampleSource } from "@/lib/component-data"; export async function GET( _request: Request, { params }: { params: Promise<{ name: string }> }, ) { try { const { name } = await params; const exampleSource = await getExampleSource(name); if (exampleSource && !exampleSource.includes("not found")) { return new NextResponse(exampleSource, { headers: { "Content-Type": "text/plain", "Cache-Control": "public, max-age=3600", }, }); } return new NextResponse("Not found", { status: 404 }); } catch (error) { console.error("Error in examples API route:", error); return new NextResponse("Internal Server Error", { status: 500 }); } } ================================================ FILE: web/app/api/search/route.ts ================================================ import { createFromSource } from 'fumadocs-core/search/server'; import { source } from '@/lib/source'; export const { GET } = createFromSource(source); ================================================ FILE: web/app/docs/[...slug]/page.tsx ================================================ import { notFound } from "next/navigation"; import type { Metadata } from "next"; import { getPageNavigation } from "@/lib/navigation"; import { source } from "@/lib/source"; import { ComponentMetadata } from "@/components/component-metadata"; import { DocsPage } from "@/components/docs-page"; import { mdxComponents } from "@/components/mdx-components"; import { OpenInAiMenu } from "@/components/open-in-ai-menu"; import { RACLink } from "@/components/rac-link"; // Ensure strict static-only build export const dynamic = "error"; interface PageProps { params: Promise<{ slug?: string[]; }>; } // Convert PascalCase title to kebab-case component ID function titleToComponentId(title: string): string { // special cases if (title === "ComboBox") { return "combobox"; } return ( title // Insert a hyphen before uppercase letters that follow lowercase letters .replace(/([a-z])([A-Z])/g, "$1-$2") .toLowerCase() ); } export default async function Page({ params }: PageProps) { const { slug } = await params; const page = source.getPage(slug); if (!page) { notFound(); } const toc = page.data.toc || []; const MDXContent = page.data.body; const navigation = getPageNavigation(page.url); const componentId = titleToComponentId(page.data.title); const isComponentPage = page.url.includes("/docs/components/"); return (

{page.data.title}

{/* Component metadata for component pages only */} {isComponentPage && } {/* Links section - always show for all docs pages */}
{page.data.isRAC && }
); } export async function generateStaticParams() { return source.generateParams(); } export async function generateMetadata({ params, }: PageProps): Promise { const { slug } = await params; const page = source.getPage(slug); if (!page) notFound(); return { title: `${page.data.title} - BaseLayer`, description: page.data.description, }; } ================================================ FILE: web/app/docs/content/components/accordion.mdx ================================================ --- title: Accordion isRAC: true --- ## Group ## Source ================================================ FILE: web/app/docs/content/components/badge.mdx ================================================ --- title: Badge description: A badge is a small, visual indicator that can be used to label, categorize, or organize content. --- ## Variants ## Source ================================================ FILE: web/app/docs/content/components/breadcrumbs.mdx ================================================ --- title: Breadcrumbs isRAC: true --- ## Separator Icons ## Source ================================================ FILE: web/app/docs/content/components/button.mdx ================================================ --- title: Button isRAC: true --- ## Variants ## Sizes ## Helper Icons ## Source ================================================ FILE: web/app/docs/content/components/calendar.mdx ================================================ --- title: Calendar isRAC: true --- ## Range Calendar ## Source ================================================ FILE: web/app/docs/content/components/card.mdx ================================================ --- title: Card --- ## Variants ## Source ================================================ FILE: web/app/docs/content/components/checkbox.mdx ================================================ --- title: Checkbox isRAC: true --- ## Group ## Source ================================================ FILE: web/app/docs/content/components/combobox.mdx ================================================ --- title: ComboBox isRAC: true --- If this component is not what exactly you're looking for UX wise, you may want to check out the [Searchable Select](/docs/components/select#searchable-select) component. ## Menu trigger behavior ## Disabled Options ## Source ================================================ FILE: web/app/docs/content/components/command.mdx ================================================ --- title: Command description: A command palette that allows users to quickly search and execute commands using keyboard shortcuts. --- ## Custom Trigger ## Source ================================================ FILE: web/app/docs/content/components/date-field.mdx ================================================ --- title: DateField isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/date-picker.mdx ================================================ --- title: DatePicker isRAC: true --- ## Date Range Picker ## Source ================================================ FILE: web/app/docs/content/components/input.mdx ================================================ --- title: Input description: Allows a user to enter a plain text value with a keyboard. --- import { RACLink } from "@/components/rac-link"; ## Label ## Disabled ## Source ================================================ FILE: web/app/docs/content/components/menu.mdx ================================================ --- title: Menu isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/meter.mdx ================================================ --- title: Meter isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/modal.mdx ================================================ --- title: Modal isRAC: true --- ## Dismissable ## Source ================================================ FILE: web/app/docs/content/components/popover.mdx ================================================ --- title: Popover isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/radio-group.mdx ================================================ --- title: RadioGroup isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/select.mdx ================================================ --- title: Select isRAC: true --- ## Searchable Select ## Popover Classname ## Source ================================================ FILE: web/app/docs/content/components/slider.mdx ================================================ --- title: Slider isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/switch.mdx ================================================ --- title: Switch isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/table.mdx ================================================ --- title: Table isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/tabs.mdx ================================================ --- title: Tabs isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/tag-group.mdx ================================================ --- title: TagGroup isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/time-field.mdx ================================================ --- title: TimeField isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/components/toggle.mdx ================================================ --- title: Toggle isRAC: true --- ## Group ## Source ================================================ FILE: web/app/docs/content/components/tooltip.mdx ================================================ --- title: Tooltip isRAC: true --- ## Source ================================================ FILE: web/app/docs/content/intro.mdx ================================================ --- title: Intro description: BaseLayer is a collection of beautiful, accessible React components built with React Aria Components and TailwindCSS. Powered by the shadcn registry. --- ## What is BaseLayer? BaseLayer is a component collection built for the [shadcn](https://ui.shadcn.com) ecosystem. Like shadcn/ui, components are **copied into your project** and become part of your codebase - not installed as dependencies. BaseLayer uses [React Aria Components](https://react-spectrum.adobe.com/react-aria/) and all components have beautiful default styles. ## Key Features - **Own your components** - Components live in your codebase, not as a dependency - **shadcn CLI compatible** - Use the familiar `npx shadcn add` workflow to add components - **AI Native** - Works seamlessly with AI coding assistants via the built-in shadcn MCP server - **Variant-based design** - Powered by TailwindCSS and tailwind-variants for effortless customization - **Accessible by default** - Built on battle-tested React Aria Components ## Stack BaseLayer is built on top of the following technologies: - [shadcn Registry](https://ui.shadcn.com/docs/registry) - Component delivery system - [React Aria Components](https://react-spectrum.adobe.com/react-aria/getting-started.html) - Accessible component primitives - [TailwindCSS](https://tailwindcss.com/) - Utility-first styling - [tailwind-variants](https://www.tailwind-variants.org/) - Type-safe variant management - [TypeScript](https://www.typescriptlang.org/) - Type safety ## Design Philosophy BaseLayer components are designed with intelligent grouping in mind. Many components like Accordion, RadioGroup, and CheckboxGroup include both individual and group functionality within the same component export. This approach provides: - **Code reuse** - Shared styling and behavior between individual and group variants - **Consistency** - Unified design language across single and grouped instances - **Simplicity** - One component to learn instead of separate individual/group components ================================================ FILE: web/app/docs/content/styles.mdx ================================================ --- title: Styles --- ## Tailwind CSS BaseLayer uses Tailwind CSS for styling. Tailwind CSS is a utility-first CSS framework that allows you to build custom designs without leaving your HTML. For help setting up Tailwind in your framework, see the [Tailwind docs](https://tailwindcss.com/docs/installation/framework-guides). **Please note: Only Tailwind 4 is supported** ## Tailwind Variants [Tailwind Variants](https://www.tailwind-variants.org/) >The power of Tailwind combined with a first-class variant API. By default, BaseLayer uses Tailwind Variants for styling. Tailwind Variants is a library that allows you to create variants for your Tailwind CSS classes. This library also allows us to provide className overrides for every component without needed to install a separate library. ## Base Theme Upon setup, global CSS variables are set for the theme. These variables are used to style the components. The CSS var set is intentionally kept minimal. You may need to break out of the default and add more, and that's fine! Feel free to customize the theme to your liking. When you install components via the shadcn CLI, the necessary Tailwind configuration will be automatically added to your project. ================================================ FILE: web/app/docs/content/usage.mdx ================================================ --- title: Usage description: How to setup and use BaseLayer components in your project --- ## Prerequisites - React with TypeScript - TailwindCSS >= 4 - Familiarity with [shadcn](https://ui.shadcn.com) (see their [docs](https://ui.shadcn.com/docs) if you're new to shadcn) ## Quick Start ### 1. Initialize (first time only) ```bash npx shadcn@latest init ``` Skip this if you already have a `components.json` file - the CLI will auto-configure on first use. ### 2. Add components ```bash npx shadcn@latest add https://baselayer.dev/r/button ``` The CLI handles installation, dependencies, and file placement automatically. ### 3. Use it ```tsx import { Button } from '@/components/ui/button' export default function Page() { return } ``` ## Optional: Shorter Commands Add to your `components.json` for shorter commands: ```json { "registries": { "@baselayer": "https://baselayer.dev/r/{name}.json" } } ``` Then use: ```bash npx shadcn@latest add @baselayer/button ``` ## AI-Powered Workflow ### Cursor (MCP) The shadcn MCP server is built into Cursor. Simply ask: > "Add BaseLayer button component" > "Create a sign up page with BaseLayer components" **Pro Tip:** Add to `.cursorrules`: ``` Use BaseLayer components (baselayer.dev) instead of shadcn/ui ``` ### ChatGPT, Claude, Other Chatbots Use the "Open in AI" button on component pages, or reference in prompts: > Use BaseLayer components. Docs: https://www.baselayer.dev/llms.txt ## Manual Copy-Paste Setup If you prefer not to use the CLI and want complete manual control: 1. **Install dependencies:** ```bash pnpm add react-aria-components tailwind-variants tw-css-animate ``` 2. **Add global styles** - see [styles](/docs/styles) for details 3. **Configure TypeScript paths:**
Next.js example ```json // tsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./*"] } } } ```
Vite example ```json // tsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` ```json // tsconfig.app.json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` ```ts // vite.config.ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import tailwindcss from '@tailwindcss/vite'; import path from 'path'; export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, }); ```
4. **Copy components** - Each component page has a source section showing the code to copy ## Additional Resources - [React Aria Components docs](https://react-spectrum.adobe.com/react-aria/getting-started.html) - Detailed documentation for all component props and behavior ================================================ FILE: web/app/docs/layout.tsx ================================================ import type { ReactNode } from "react"; import Image from "next/image"; import Link from "next/link"; import { GithubIcon } from "lucide-react"; import { source } from "@/lib/source"; import { MobileNav } from "@/components/mobile-nav"; import { Sidebar } from "@/components/sidebar"; import { ThemeToggle } from "@/components/theme-toggle"; interface LayoutProps { children: ReactNode; } export default function Layout({ children }: LayoutProps) { const pages = source.getPages(); const introDocs = pages .filter((page) => !page.url.startsWith("/docs/components")) .map((page) => ({ url: page.url, data: { title: page.data.title, }, })); const componentDocs = pages .filter((page) => page.url.startsWith("/docs/components")) .map((page) => ({ url: page.url, data: { title: page.data.title, }, })); return (
{/* Top Navigation Bar - Full Width */}
BaseLayer {/* Desktop title - hidden on mobile, visible on desktop */} BaseLayer
{/* below the top nav */}
{/* Left Sidebar - hidden on mobile, visible on desktop */}
{/* Main content area - center content + right TOC */}
{children}
); } ================================================ FILE: web/app/docs/page.tsx ================================================ import Link from "next/link"; export default function DocsPage() { return (

Documentation

Get Started
); } ================================================ FILE: web/app/globals.css ================================================ @import 'tailwindcss'; @import "tw-animate-css"; @import "../../packages/components/src/tailwind.css"; @source '../../packages/components/src/**/*.{ts,tsx}'; @plugin "@tailwindcss/typography"; @theme { --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); } @media (prefers-color-scheme: dark) { :root { --background: var(--surface); --foreground: var(--fg); } } html, body { overscroll-behavior: none; overscroll-behavior-y: none; overscroll-behavior-x: none; } html { scroll-behavior: auto; /* Prevent elastic scrolling on Safari */ -webkit-overflow-scrolling: auto; } body { background: var(--surface); color: var(--fg); font-family: Arial, Helvetica, sans-serif; /* Additional Safari fixes */ -webkit-overflow-scrolling: auto; } /* CSS variables for theme support */ :root { --scrollbar-thumb: #888; --scrollbar-thumb-hover: #555; } [data-theme="dark"] { --scrollbar-thumb: #666; --scrollbar-thumb-hover: #999; } /* Auto-hide scrollbar until hover */ * { scrollbar-width: thin; scrollbar-color: transparent transparent; } *:hover { scrollbar-color: var(--scrollbar-thumb) transparent; } /* Webkit browsers */ *::-webkit-scrollbar { width: 8px; height: 8px; } *::-webkit-scrollbar-track { background: transparent; } *::-webkit-scrollbar-thumb { background-color: transparent; border-radius: 4px; } *:hover::-webkit-scrollbar-thumb { background-color: var(--scrollbar-thumb); } *::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-thumb-hover); } ================================================ FILE: web/app/layout.tsx ================================================ import { GeistMono } from 'geist/font/mono'; import { GeistSans } from 'geist/font/sans'; import type { Metadata } from "next"; import "./globals.css"; import { Analytics } from '@vercel/analytics/next'; import { ThemeProvider } from "next-themes"; export const metadata: Metadata = { title: "BaseLayer", description: "BaseLayer is a component system for building web applications.", icons: { icon: "/bl.svg", }, }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ================================================ FILE: web/app/llms.txt/route.ts ================================================ import { readFileSync } from "node:fs"; import { join } from "node:path"; interface RegistryItem { name: string; title?: string; description?: string; categories?: string[]; } export async function GET() { // Read the shadcn registry const registryPath = join(process.cwd(), "public/r/registry.json"); const registry = JSON.parse(readFileSync(registryPath, "utf8")); const components = registry.items; const content = `# BaseLayer Components BaseLayer is a component collection built for the shadcn ecosystem. Like shadcn/ui, components are **copied into your project** and become part of your codebase - not installed as dependencies. The key difference: BaseLayer uses React Aria Components instead of Radix UI, providing the same accessible primitives that power Adobe's design systems. ## Key Features - **Own your components** - Components live in your codebase, not as a dependency - **shadcn CLI compatible** - Use the familiar \`npx shadcn add\` workflow to add components - **AI Native** - Works seamlessly with AI coding assistants via the built-in shadcn MCP server - **Variant-based design** - Powered by TailwindCSS and tailwind-variants for effortless customization - **Accessible by default** - Built on battle-tested React Aria Components ## Stack - shadcn Registry - Component delivery system - React Aria Components - Accessible component primitives - TailwindCSS - Utility-first styling - tailwind-variants - Type-safe variant management - TypeScript - Type safety ## Available Components ${components.map((comp: RegistryItem) => `- **${comp.title || comp.name}** (${comp.categories?.[0] || "component"}): ${comp.description}`).join("\n")} ## Categories ${[ ...new Set( components.map((c: RegistryItem) => c.categories?.[0] || "component"), ), ] .map( (cat) => `- **${cat}**: ${components .filter((c: RegistryItem) => (c.categories?.[0] || "component") === cat) .map((c: RegistryItem) => c.title || c.name) .join(", ")}`, ) .join("\n")} ## Quick Start ### 1. Initialize (first time only) \`\`\`bash npx shadcn@latest init \`\`\` Skip this if you already have a \`components.json\` file - the CLI will auto-configure on first use. ### 2. Add components \`\`\`bash npx shadcn@latest add https://baselayer.dev/r/button \`\`\` The CLI handles installation, dependencies, and file placement automatically. ### 3. Use it \`\`\`tsx import { Button } from '@/components/ui/button' export default function Page() { return } \`\`\` ## Optional: Shorter Commands Add to your \`components.json\` for shorter commands: \`\`\`json { "registries": { "@baselayer": "https://baselayer.dev/r/{name}.json" } } \`\`\` Then use: \`\`\`bash npx shadcn@latest add @baselayer/button \`\`\` ## AI-Powered Workflow ### For Cursor (MCP) The shadcn MCP server is built into Cursor. Simply ask: - "Add BaseLayer button component" - "Create a sign up page with BaseLayer components" **Pro Tip:** Add to \`.cursorrules\`: \`\`\` Use BaseLayer components (baselayer.dev) instead of shadcn/ui \`\`\` ### For Other AI Assistants (ChatGPT, Claude, etc.) Reference BaseLayer in your prompts: - "Use BaseLayer components. Docs: https://www.baselayer.dev/llms.txt" Or use the Registry API to fetch components: \`\`\`bash curl https://baselayer.dev/r/button.json \`\`\` This returns the complete component definition with source code in the \`files[].content\` field. Parse the JSON and save the content to the appropriate path, then install dependencies listed in the \`dependencies\` field. ## Prerequisites - React with TypeScript - TailwindCSS >= 4 - Familiarity with shadcn (see https://ui.shadcn.com/docs if you're new to shadcn) ## Registry Endpoints - \`GET /r/registry.json\` - List all components with metadata - \`GET /r/{component}.json\` - Get specific component with full source code ## Additional Resources - Component docs and examples: https://baselayer.dev/docs - React Aria Components reference: https://react-spectrum.adobe.com/react-aria/getting-started.html - shadcn docs: https://ui.shadcn.com/docs ## Design Philosophy BaseLayer components are designed with intelligent grouping in mind. Many components like Accordion, RadioGroup, and CheckboxGroup include both individual and group functionality within the same component export. This provides code reuse, consistency, and simplicity - one component to learn instead of separate individual/group components. Remember: You own the components once you copy them - they're not dependencies! `; return new Response(content, { headers: { "Content-Type": "text/plain", }, }); } ================================================ FILE: web/app/page.tsx ================================================ import Image from "next/image"; import Link from "next/link"; import { Accessibility, ArrowRight, CodeIcon, Github, MessageCircle, Palette, Server, Sparkles, } from "lucide-react"; import { ThemeToggle } from "@/components/theme-toggle"; export default function Home() { return (
{/* Navigation */} {/* Hero Section */}
{/* Animated Background Elements */}
{/* Floating Shapes */}
{/* Grid Pattern */}
{/* Badge */}
v2 is here
{/* Main Heading */}

Own Your UI Code.

{/* Subtitle */}

Components that ship to your{" "} codebase, not your{" "} node_modules.
AI-optimized, accessible, yours.

{/* Enhanced CTA Section */}
{/* Glowing background effect */}
Start Building
{/* AI-Ready Features Section */}

Built for the AI era

Seamlessly integrate with your favorite AI development tools and workflows

{/* Feature Cards */}
{/* You Own Your Code */}

You Own Your Code

shadcn CLI compatible

Use the familiar shadcn CLI workflow to add components directly to your codebase. No library dependencies—just code you own, modify, and customize without restrictions.

{/* MCP */}

shadcn MCP

Built-in Cursor support

Works seamlessly with AI assistants via the shadcn MCP server. Just ask Cursor or Claude to add BaseLayer components—no setup required.

{/* Chat Bots & AI Tools */}

Chat Bots & AI Tools

ChatGPT, Claude, and more

Designed for use with your favorite chat bots and AI tools. llms.txt and more keep your AI tools in sync with your components.

{/* Traditional Features Section */}

Beautiful Design

Carefully crafted components that look great out of the box with thoughtful attention to detail.

Accessible

Built on React Aria Components with full keyboard navigation and screen reader support.

Open Source

Completely open source and free to use. MIT Licensed.

{/* CTA Section */}

Ready to build something amazing?

Join developers who are building the next generation of applications with BaseLayer components.

Start Building
); } ================================================ FILE: web/app/r/[[...segments]]/route.ts ================================================ import { NextResponse } from "next/server"; import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; export async function GET( _request: Request, { params }: { params: Promise<{ segments?: string[] }> }, ) { try { const { segments } = await params; // If no segments, return the registry index if (!segments || segments.length === 0) { const registryPath = join(process.cwd(), "public/r/registry.json"); const registryContent = readFileSync(registryPath, "utf8"); return new NextResponse(registryContent, { headers: { "Content-Type": "application/json", "Cache-Control": "public, max-age=3600", }, }); } // Handle specific registry item requests // Support both /r/button and /r/button.json const itemName = segments[0].replace(/\.json$/, ""); const itemPath = join(process.cwd(), `public/r/${itemName}.json`); if (!existsSync(itemPath)) { return new NextResponse("Registry item not found", { status: 404 }); } const itemContent = readFileSync(itemPath, "utf8"); return new NextResponse(itemContent, { headers: { "Content-Type": "application/json", "Cache-Control": "public, max-age=3600", }, }); } catch (error) { console.error("Error in registry API route:", error); return new NextResponse("Internal Server Error", { status: 500 }); } } ================================================ FILE: web/components/code-block-client.tsx ================================================ "use client"; import { useState } from "react"; import { Check, Copy } from "lucide-react"; interface CodeBlockWithCopyProps { code: string; html: string; } const CopyButton = ({ code }: { code: string }) => { const [copied, setCopied] = useState(false); const handleCopy = async () => { try { await navigator.clipboard.writeText(code); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (err) { console.error("Failed to copy text: ", err); } }; return ( ); }; export const CodeBlockWithCopy = ({ code, html }: CodeBlockWithCopyProps) => { return (
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: fine */}
); }; ================================================ FILE: web/components/code-block.tsx ================================================ import { codeToHtml } from "shiki"; import { CodeBlockWithCopy } from "./code-block-client"; interface CodeBlockProps { code: string; lang?: string; } export const CodeBlock = async ({ code, lang = "tsx" }: CodeBlockProps) => { const html = await codeToHtml(code, { lang, themes: { light: "catppuccin-latte", dark: "catppuccin-frappe", }, defaultColor: "light-dark()", }); return ; }; ================================================ FILE: web/components/component-metadata.tsx ================================================ import { Badge } from "@baselayer/components"; import { readFileSync } from "node:fs"; import { join } from "node:path"; interface ComponentMetadataProps { componentId: string; showTitle?: boolean; showDescription?: boolean; showCategory?: boolean; showStatus?: boolean; showTags?: boolean; } interface RegistryItem { name: string; title?: string; description?: string; categories?: string[]; meta?: { status?: string; tags?: string[]; }; } export async function ComponentMetadata({ componentId, showTitle = false, showDescription = true, showCategory = false, showStatus = false, showTags = false, }: ComponentMetadataProps) { // Read from shadcn registry for metadata const shadcnRegistryPath = join(process.cwd(), "public/r/registry.json"); const shadcnRegistryContent = readFileSync(shadcnRegistryPath, "utf8"); const shadcnRegistry = JSON.parse(shadcnRegistryContent); const item = shadcnRegistry.items?.find( (i: RegistryItem) => i.name === componentId, ); if (!item) { return null; } const { title, description, categories, meta } = item; return (
{showTitle && title && (

{title}

)} {showDescription && description && (

{description}

)}
{showCategory && categories && categories.length > 0 && ( {categories[0]} )} {showStatus && meta?.status && ( {meta.status} )} {showTags && meta?.tags && meta.tags.length > 0 && meta.tags.map((tag: string) => ( {tag} ))}
); } ================================================ FILE: web/components/docs-page.tsx ================================================ "use client"; import type { ReactNode } from "react"; import Link from "next/link"; import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; import { useActiveHeading } from "../hooks/use-active-heading"; import type { PageNavigation } from "../lib/navigation"; import { TableOfContents } from "./table-of-contents"; interface TocItem { depth: number; url: string; title: ReactNode; } interface DocsPageProps { toc: TocItem[]; children: ReactNode; navigation?: PageNavigation; } export function DocsPage({ toc, children, navigation }: DocsPageProps) { const { containerRef, activeId } = useActiveHeading(); return (
{/* Main Content */}
{children} {/* Page Navigation */} {(navigation?.previous || navigation?.next) && (
{navigation.previous ? (
Previous
{navigation.previous.title}
) : (
)} {navigation.next ? (
Next
{navigation.next.title}
) : (
)}
)}
{/* Right Sidebar - Table of Contents */}
); } ================================================ FILE: web/components/mdx-components.tsx ================================================ import { getComponentSource, getExampleSource } from "../lib/component-data"; import { getExampleComponent } from "../lib/examples-map"; import { CodeBlock } from "./code-block"; import { ComponentMetadata } from "./component-metadata"; import { Preview } from "./preview"; export const ComponentPreview = async ({ children, name, example, }: { children?: React.ReactNode; name?: string; example?: string; }) => { let sourceCode: string | undefined; let exampleComponent: React.ReactNode | undefined; if (example) { try { sourceCode = await getExampleSource(example); const ExampleComponent = await getExampleComponent(example); if (ExampleComponent) { exampleComponent = ; } } catch (error) { console.error(`Failed to load example ${example}:`, error); } } else if (name) { try { sourceCode = await getComponentSource(name); } catch (error) { console.error(`Failed to load source for ${name}:`, error); sourceCode = undefined; } } return (
: undefined } > {exampleComponent || children}
); }; // Layout components export const CodeTabs = ({ children }: { children: React.ReactNode }) => (
{children}
); export const TabsList = ({ children }: { children: React.ReactNode }) => (
{children}
); export const TabsTrigger = ({ children }: { children: React.ReactNode }) => ( ); export const TabsContent = ({ children }: { children: React.ReactNode }) => (
{children}
); export const Steps = ({ children }: { children: React.ReactNode }) => (
{children}
); export const Step = ({ children }: { children: React.ReactNode }) => (
{children}
); export const Pre = ({ children }: { children: React.ReactNode }) => (
		{children}
	
); export const Code = ({ children }: { children: React.ReactNode }) => ( {children} ); export const Ul = ({ children }: { children: React.ReactNode }) => (
    {children}
); export const Li = ({ children }: { children: React.ReactNode }) => (
  • {children}
  • ); // MDX Components export export const mdxComponents = { ComponentPreview, ComponentMetadata, CodeTabs, TabsList, TabsTrigger, TabsContent, Steps, Step, pre: Pre, code: Code, ul: Ul, li: Li, }; ================================================ FILE: web/components/mobile-nav.tsx ================================================ "use client"; import { useState } from "react"; import Image from "next/image"; import { Button, Dialog, Modal, ModalOverlay } from "react-aria-components"; import { MenuIcon } from "lucide-react"; import { SidebarLink } from "./sidebar-link"; interface Page { url: string; data: { title: string; }; } interface MobileNavProps { introDocs: Page[]; componentDocs: Page[]; } export function MobileNav({ introDocs, componentDocs }: MobileNavProps) { const [isOpen, setIsOpen] = useState(false); return ( <>
    BaseLayer BaseLayer
    ); } ================================================ FILE: web/components/open-in-ai-menu.tsx ================================================ "use client"; import { Button, MenuContent, MenuItem, MenuTrigger, } from "@baselayer/components"; import { ArrowUpRight, Share } from "lucide-react"; interface OpenInAiMenuProps { pageTitle: string; pageUrl: string; } const AI_SERVICES = [ { name: "ChatGPT", baseUrl: "https://chatgpt.com/", urlPattern: "?hints=search&q=", messageTemplate: (url: string) => `Read this BaseLayer documentation: ${url}`, }, { name: "Claude", baseUrl: "https://claude.ai/new", urlPattern: "?q=", messageTemplate: (url: string) => `Read this BaseLayer documentation: ${url}`, }, { name: "T3 Chat", baseUrl: "https://t3.chat/new", urlPattern: "?q=", messageTemplate: (url: string) => `Read this BaseLayer documentation: ${url}`, }, ] as const; export function OpenInAiMenu({ pageTitle, pageUrl }: OpenInAiMenuProps) { const baseUrl = "https://baselayer.dev"; const fullUrl = `${baseUrl}${pageUrl}`; const openInAI = (service: (typeof AI_SERVICES)[number]) => { const message = service.messageTemplate(fullUrl); const finalUrl = `${service.baseUrl}${service.urlPattern}${encodeURIComponent(message)}`; window.open(finalUrl, "_blank"); }; return ( {AI_SERVICES.map((service) => ( openInAI(service)} className="flex items-center gap-2" > {service.name} ))} ); } ================================================ FILE: web/components/preview.tsx ================================================ "use client"; import { useState } from "react"; import { CodeIcon, ComponentIcon, type LucideIcon } from "lucide-react"; interface TabButtonProps { tab: "preview" | "source"; activeTab: "preview" | "source"; onClick: () => void; icon: LucideIcon; } const TabButton = ({ tab, activeTab, onClick, icon: Icon }: TabButtonProps) => { const isActive = activeTab === tab; return ( ); }; export const Preview = ({ children, sourceCodeElement, }: { children?: React.ReactNode; sourceCodeElement?: React.ReactElement; }) => { const [activeTab, setActiveTab] = useState<"preview" | "source">("preview"); // If no children and only sourceCodeElement, render just the source code if (!children && sourceCodeElement) { return (
    {sourceCodeElement}
    ); } return (
    {sourceCodeElement && (
    {/* Active indicator background */}
    setActiveTab("preview")} icon={ComponentIcon} /> setActiveTab("source")} icon={CodeIcon} />
    )}
    {activeTab === "preview" ? (
    {children}
    ) : (
    {sourceCodeElement || (
    								{"// Source code not available"}
    							
    )}
    )}
    ); }; ================================================ FILE: web/components/rac-link.tsx ================================================ import Link from "next/link"; import { ArrowUpRightIcon } from "lucide-react"; export const RACLink = ({ componentName }: { componentName: string }) => ( RAC Docs ); ================================================ FILE: web/components/search.tsx ================================================ "use client"; import { useEffect, useMemo, useState } from "react"; import { useRouter } from "next/navigation"; import { Command, type CommandItem } from "@baselayer/components"; import { useDocsSearch } from "fumadocs-core/search/client"; import { BookOpenIcon, FileTextIcon } from "lucide-react"; export function SearchDialog() { const router = useRouter(); const [searchTerm, setSearchTerm] = useState(""); const { setSearch, query } = useDocsSearch({ type: "fetch", }); // Update search when searchTerm changes useEffect(() => { setSearch(searchTerm); }, [searchTerm, setSearch]); const results = Array.isArray(query.data) ? query.data : []; // Convert search results to CommandItem format const commands: CommandItem[] = useMemo(() => { // Show default popular pages when no search term if (searchTerm.length === 0) { return [ { id: "intro", label: "Introduction", icon: BookOpenIcon, onSelect: () => router.push("/docs/intro"), }, ]; } return results.slice(0, 10).map((result, index) => ({ id: result.id || `result-${index}`, label: result.content || "Untitled", icon: FileTextIcon, onSelect: () => { router.push(result.url); }, })); }, [results, router, searchTerm]); return ( ); } ================================================ FILE: web/components/sidebar-link.tsx ================================================ "use client"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { cx } from "@/lib/cx"; interface SidebarLinkProps { href: string; children: React.ReactNode; onClick?: () => void; } export function SidebarLink({ href, children, onClick }: SidebarLinkProps) { const pathname = usePathname(); const isActive = pathname === href; return ( { onClick?.(); }} href={href} className={cx( "block rounded-lg px-3 py-2 font-semibold text-sm transition-colors hover:bg-secondary", isActive && "bg-secondary text-primary hover:bg-secondary", )} > {children} ); } ================================================ FILE: web/components/sidebar.tsx ================================================ import { source } from "@/lib/source"; import { SearchDialog } from "./search"; import { SidebarLink } from "./sidebar-link"; export function Sidebar() { const pages = source.getPages(); // Separate docs into categories const introDocs = pages .filter((page) => !page.url.startsWith("/docs/components")) .sort((a, b) => { const order = ["/docs/intro", "/docs/usage", "/docs/styles"]; const aIndex = order.indexOf(a.url); const bIndex = order.indexOf(b.url); if (aIndex !== -1 && bIndex !== -1) { return aIndex - bIndex; } if (aIndex !== -1) return -1; if (bIndex !== -1) return 1; return a.url.localeCompare(b.url); }); const componentDocs = pages.filter((page) => page.url.startsWith("/docs/components"), ); return (
    {/* Fixed Search Section */}
    {/* Scrollable Navigation Section */}
    ); } ================================================ FILE: web/components/table-of-contents.tsx ================================================ "use client"; import type { ReactNode } from "react"; import { cx } from "@/lib/cx"; interface TocItem { depth: number; url: string; title: ReactNode; } interface TableOfContentsProps { toc: TocItem[]; activeId: string; } export function TableOfContents({ toc, activeId }: TableOfContentsProps) { const handleTocClick = (url: string, e: React.MouseEvent) => { e.preventDefault(); const id = url.replace("#", ""); const element = document.getElementById(id); if (element) { const headerOffset = 120; // Account for top nav height const elementPosition = element.getBoundingClientRect().top; const offsetPosition = elementPosition + window.pageYOffset - headerOffset; window.scrollTo({ top: offsetPosition, behavior: "auto", }); } }; if (toc.length === 0) return null; return ( ); } ================================================ FILE: web/components/theme-toggle.tsx ================================================ "use client"; import { useEffect, useState } from "react"; import { Button } from "@baselayer/components"; import { Moon, Sun } from "lucide-react"; import { useTheme } from "next-themes"; export const ThemeToggle = () => { const { theme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); // Ensure component is mounted on client before rendering theme-dependent content useEffect(() => { setMounted(true); }, []); const toggleTheme = () => { setTheme(theme === "light" ? "dark" : "light"); }; const isDark = theme === "dark"; if (!mounted) { return ; } return ( ); }; export default ThemeToggle; ================================================ FILE: web/components.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry.json", "name": "@baselayer", "homepage": "https://baselayer.dev", "baseUrl": "https://baselayer.dev", "registryUrl": "https://baselayer.dev/r", "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui" }, "registries": { "@baselayer": "https://baselayer.dev/r/{name}.json" }, "rsc": { "singleComponent": false }, "tailwind": { "config": "tailwind.config.ts", "css": "app/globals.css", "baseColor": "slate", "cssVariables": true, "prefix": "" } } ================================================ FILE: web/hooks/use-active-heading.ts ================================================ "use client"; import { useEffect, useRef, useState } from "react"; export function useActiveHeading() { const containerRef = useRef(null); const [activeId, setActiveId] = useState(""); useEffect(() => { const observer = new IntersectionObserver( (entries) => { const intersectingEntries = entries.filter( (entry) => entry.isIntersecting, ); if (intersectingEntries.length > 0) { const sorted = intersectingEntries.sort((a, b) => { const aRect = a.boundingClientRect; const bRect = b.boundingClientRect; const viewportCenter = window.innerHeight / 2; const aDistance = Math.abs(aRect.top - viewportCenter); const bDistance = Math.abs(bRect.top - viewportCenter); return aDistance - bDistance; }); setActiveId(sorted[0].target.id); } }, { rootMargin: "-10% 0% -60% 0%", threshold: 0, }, ); const headings = containerRef.current?.querySelectorAll( "h1, h2, h3, h4, h5, h6", ); if (headings) { headings.forEach((heading) => { if (heading.id) { observer.observe(heading); } }); } return () => { observer.disconnect(); }; }, []); return { containerRef, activeId }; } ================================================ FILE: web/lib/component-data.ts ================================================ import { readFileSync } from "node:fs"; import { join } from "node:path"; const examplesDir = join(process.cwd(), "../packages/components/src/examples"); const componentsSourceDir = join(process.cwd(), "../packages/components/src/core"); export async function getComponentSource(name: string): Promise { try { const sourceFilePath = join(componentsSourceDir, name, `${name}.tsx`); return readFileSync(sourceFilePath, "utf8"); } catch (error) { console.error(`Error loading component ${name}:`, error); return `// Error loading component: ${ error instanceof Error ? error.message : "Unknown error" }`; } } export async function getExampleSource(name: string): Promise { try { // Read the example file directly from the filesystem const exampleFilePath = join(examplesDir, `${name}.tsx`); let content = readFileSync(exampleFilePath, "utf8"); // Transform the import path for display content = content.replace( /from ["']\.\.\/core\/([^/]+)\/\1["']/g, 'from "@/components/ui/$1"', ); return content; } catch (error) { console.error(`Error loading example ${name}:`, error); return `// Error loading example: ${ error instanceof Error ? error.message : "Unknown error" }`; } } ================================================ FILE: web/lib/cx.ts ================================================ import { twJoin, twMerge } from "tailwind-merge"; /** * re export tailwind-merge */ export const cx = twMerge; /** * re export tailwind-join */ export const cn = twJoin; ================================================ FILE: web/lib/examples-map.ts ================================================ // Filesystem-based examples map using dynamic discovery import type { ComponentType } from "react"; import { readFileSync } from "node:fs"; import { join } from "node:path"; const examplesDir = join(process.cwd(), "../packages/components/src/examples"); export async function getExampleComponent(exampleId: string) { try { // Read the example file to extract the export name const exampleFilePath = join(examplesDir, `${exampleId}.tsx`); const fileContent = readFileSync(exampleFilePath, "utf8"); // Extract the export name using regex // Matches: export const ComponentName = ... const exportMatch = fileContent.match(/export\s+const\s+(\w+)\s*=/); if (!exportMatch) { console.error(`Could not find export in ${exampleId}.tsx`); return null; } const componentName = exportMatch[1]; // Dynamically import the component from the built package const module = await import("@baselayer/components"); const Component = (module as unknown as Record)[ componentName ]; if (!Component) { console.error( `Component ${componentName} not found in @baselayer/components`, ); return null; } return Component as React.ComponentType; } catch (error) { console.error(`Failed to load example component ${exampleId}:`, error); return null; } } ================================================ FILE: web/lib/metadata.ts ================================================ export const metadataImage = { src: '/bl.svg', width: 1200, height: 630, alt: 'BaseLayer Documentation' }; export const siteConfig = { name: 'BaseLayer', description: 'Modern React components for building beautiful user interfaces', url: 'https://baselayer.dev', }; ================================================ FILE: web/lib/navigation.ts ================================================ import { source } from "./source"; export interface NavigationPage { title: string; url: string; } export interface PageNavigation { previous?: NavigationPage; next?: NavigationPage; } export function getPageNavigation(currentUrl: string): PageNavigation { const pages = source.getPages(); // Create ordered list following sidebar structure const introDocs = pages .filter((page) => !page.url.startsWith("/docs/components")) .sort((a, b) => { // Define specific order for intro docs const order = ["/docs/intro", "/docs/usage", "/docs/styles"]; const aIndex = order.indexOf(a.url); const bIndex = order.indexOf(b.url); if (aIndex !== -1 && bIndex !== -1) { return aIndex - bIndex; } if (aIndex !== -1) return -1; if (bIndex !== -1) return 1; return a.url.localeCompare(b.url); }); const componentDocs = pages .filter((page) => page.url.startsWith("/docs/components")) .sort((a, b) => a.data.title.localeCompare(b.data.title)); // Combine in order: intro docs first, then components const orderedPages = [...introDocs, ...componentDocs]; // Find current page index const currentIndex = orderedPages.findIndex( (page) => page.url === currentUrl, ); if (currentIndex === -1) { return {}; } const previous = currentIndex > 0 ? { title: orderedPages[currentIndex - 1].data.title, url: orderedPages[currentIndex - 1].url, } : undefined; const next = currentIndex < orderedPages.length - 1 ? { title: orderedPages[currentIndex + 1].data.title, url: orderedPages[currentIndex + 1].url, } : undefined; return { previous, next }; } ================================================ FILE: web/lib/source.ts ================================================ import { loader } from 'fumadocs-core/source'; import { docs } from '@/.source'; export const source = loader({ baseUrl: '/docs', source: docs.toFumadocsSource(), }); ================================================ FILE: web/next.config.ts ================================================ import { createMDX } from "fumadocs-mdx/next"; import type { NextConfig } from "next"; import path from "node:path"; const withMDX = createMDX(); /** @type {import('next').NextConfig} */ const nextConfig: NextConfig = { reactStrictMode: true, pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"], webpack: (config) => { config.resolve.alias = { ...config.resolve.alias, "@/components/ui": path.resolve( __dirname, "../packages/components/src/core", ), }; return config; }, }; export default withMDX(nextConfig); ================================================ FILE: web/package.json ================================================ { "name": "@baselayer/web", "version": "2.1.1", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", "start": "next start", "type-check": "tsc --noEmit", "clean": "rm -rf .next dist", "postinstall": "fumadocs-mdx" }, "dependencies": { "@baselayer/components": "workspace:*", "@baselayer/registry": "workspace:*", "@types/mdx": "^2.0.13", "@vercel/analytics": "^1.5.0", "fumadocs-core": "^15.5.5", "fumadocs-mdx": "^11.6.9", "geist": "^1.5.1", "lucide-react": "^0.525.0", "next": "15.5.9", "next-themes": "^0.4.6", "react": "^19.2.3", "react-aria-components": "catalog:", "react-dom": "^19.2.3", "react-element-to-jsx-string": "^17.0.1", "shiki": "3.7.0", "tailwind-variants": "catalog:", "zod": "^3.25.67" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.10", "@tailwindcss/typography": "^0.5.16", "@types/node": "catalog:", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.10", "tw-animate-css": "^1.3.6", "typescript": "catalog:" } } ================================================ FILE: web/postcss.config.mjs ================================================ const config = { plugins: ["@tailwindcss/postcss"], }; export default config; ================================================ FILE: web/public/r/accordion.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "accordion", "type": "registry:ui", "title": "accordion", "author": "BaseLayer", "description": "An accordion allows users to toggle the display of sections of content. Each accordion consists of a header with a title and content area.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/accordion/accordion.tsx", "type": "registry:component", "target": "components/ui/accordion.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "disclosure", "collapsible", "expandable", "content" ] }, "categories": [ "layout" ] } ================================================ FILE: web/public/r/badge.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "badge", "type": "registry:ui", "title": "badge", "author": "BaseLayer", "description": "A badge is a small label that can be used to display information or status.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/badge/badge.tsx", "type": "registry:component", "target": "components/ui/badge.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "status" ] }, "categories": [ "display" ] } ================================================ FILE: web/public/r/breadcrumbs.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "breadcrumbs", "type": "registry:ui", "title": "breadcrumbs", "author": "BaseLayer", "description": "Breadcrumbs display a heirarchy of links to the current page or resource in an application.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", "type": "registry:component", "target": "components/ui/breadcrumbs.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation" ] }, "categories": [ "navigation" ] } ================================================ FILE: web/public/r/button.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "button", "type": "registry:ui", "title": "button", "author": "BaseLayer", "description": "A button allows a user to perform an action, with mouse, touch, and keyboard interactions.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/button/button.tsx", "type": "registry:component", "target": "components/ui/button.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/calendar.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "calendar", "type": "registry:ui", "title": "calendar", "author": "BaseLayer", "description": "A calendar displays one or more date grids and allows users to select either a single date or a contiguous range of dates.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/calendar/calendar.tsx", "type": "registry:component", "target": "components/ui/calendar.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] }, "categories": [ "data-entry" ] } ================================================ FILE: web/public/r/card.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "card", "type": "registry:ui", "title": "card", "author": "BaseLayer", "description": "Displays a card with header, content, and footer.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/card/card.tsx", "type": "registry:component", "target": "components/ui/card.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "layout", "container", "display" ] }, "categories": [ "layout" ] } ================================================ FILE: web/public/r/checkbox.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "checkbox", "type": "registry:ui", "title": "checkbox", "author": "BaseLayer", "description": "A checkbox allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/checkbox/checkbox.tsx", "type": "registry:component", "target": "components/ui/checkbox.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/combobox.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "combobox", "type": "registry:ui", "title": "combobox", "author": "BaseLayer", "description": "A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/combobox/combobox.tsx", "type": "registry:component", "target": "components/ui/combobox.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/command.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "command", "type": "registry:ui", "title": "command", "author": "BaseLayer", "description": "A command palette that allows users to quickly search and execute commands using keyboard shortcuts.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/command/command.tsx", "type": "registry:component", "target": "components/ui/command.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "beta", "tags": [ "search", "navigation", "keyboard", "palette" ] }, "categories": [ "navigation" ] } ================================================ FILE: web/public/r/date-field.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-field", "type": "registry:ui", "title": "date-field", "author": "BaseLayer", "description": "A date field allows users to enter and edit date and time values using a keyboard. Each part of a date value is displayed in an individually editable segment.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/date-field/date-field.tsx", "type": "registry:component", "target": "components/ui/date-field.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/date-picker.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-picker", "type": "registry:ui", "title": "date-picker", "author": "BaseLayer", "description": "A date picker combines one or more DateFields with a calendar popover, allowing users to enter or select a single date/time or a range.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "registryDependencies": [ "calendar" ], "files": [ { "path": "src/core/date-picker/date-picker.tsx", "type": "registry:component", "target": "components/ui/date-picker.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/input.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "input", "type": "registry:ui", "title": "input", "author": "BaseLayer", "description": "Allows a user to enter a plain text value with a keyboard.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/input/input.tsx", "type": "registry:component", "target": "components/ui/input.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/menu.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "menu", "type": "registry:ui", "title": "menu", "author": "BaseLayer", "description": "A menu displays a list of actions or options that a user can choose.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/menu/menu.tsx", "type": "registry:component", "target": "components/ui/menu.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "interactive", "navigation" ] }, "categories": [ "pickers" ] } ================================================ FILE: web/public/r/meter.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "meter", "type": "registry:ui", "title": "meter", "author": "BaseLayer", "description": "A meter represents a quantity within a known range, or a fractional value.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/meter/meter.tsx", "type": "registry:component", "target": "components/ui/meter.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "progress" ] }, "categories": [ "data-display" ] } ================================================ FILE: web/public/r/modal.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "modal", "type": "registry:ui", "title": "modal", "author": "BaseLayer", "description": "A modal is an overlay element which blocks interaction with elements outside it.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/modal/modal.tsx", "type": "registry:component", "target": "components/ui/modal.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay" ] }, "categories": [ "overlays" ] } ================================================ FILE: web/public/r/popover.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "popover", "type": "registry:ui", "title": "popover", "author": "BaseLayer", "description": "A popover is an overlay element positioned relative to a trigger.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/popover/popover.tsx", "type": "registry:component", "target": "components/ui/popover.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive" ] }, "categories": [ "overlays" ] } ================================================ FILE: web/public/r/radio-group.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "radio-group", "type": "registry:ui", "title": "radio-group", "author": "BaseLayer", "description": "A radio group allows a user to select a single option from a list of mutually exclusive options.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/radio-group/radio-group.tsx", "type": "registry:component", "target": "components/ui/radio-group.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/registry.json ================================================ { "name": "@baselayer", "$schema": "https://ui.shadcn.com/schema/registry.json", "homepage": "https://baselayer.dev", "items": [ { "name": "accordion", "type": "registry:ui", "title": "accordion", "description": "An accordion allows users to toggle the display of sections of content. Each accordion consists of a header with a title and content area.", "author": "BaseLayer", "categories": [ "layout" ], "files": [ { "path": "src/core/accordion/accordion.tsx", "target": "components/ui/accordion.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "disclosure", "collapsible", "expandable", "content" ] } }, { "name": "badge", "type": "registry:ui", "title": "badge", "description": "A badge is a small label that can be used to display information or status.", "author": "BaseLayer", "categories": [ "display" ], "files": [ { "path": "src/core/badge/badge.tsx", "target": "components/ui/badge.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "status" ] } }, { "name": "breadcrumbs", "type": "registry:ui", "title": "breadcrumbs", "description": "Breadcrumbs display a heirarchy of links to the current page or resource in an application.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", "target": "components/ui/breadcrumbs.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation" ] } }, { "name": "button", "type": "registry:ui", "title": "button", "description": "A button allows a user to perform an action, with mouse, touch, and keyboard interactions.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/button/button.tsx", "target": "components/ui/button.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "calendar", "type": "registry:ui", "title": "calendar", "description": "A calendar displays one or more date grids and allows users to select either a single date or a contiguous range of dates.", "author": "BaseLayer", "categories": [ "data-entry" ], "files": [ { "path": "src/core/calendar/calendar.tsx", "target": "components/ui/calendar.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] } }, { "name": "card", "type": "registry:ui", "title": "card", "description": "Displays a card with header, content, and footer.", "author": "BaseLayer", "categories": [ "layout" ], "files": [ { "path": "src/core/card/card.tsx", "target": "components/ui/card.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "layout", "container", "display" ] } }, { "name": "checkbox", "type": "registry:ui", "title": "checkbox", "description": "A checkbox allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/checkbox/checkbox.tsx", "target": "components/ui/checkbox.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "combobox", "type": "registry:ui", "title": "combobox", "description": "A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/combobox/combobox.tsx", "target": "components/ui/combobox.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] } }, { "name": "command", "type": "registry:ui", "title": "command", "description": "A command palette that allows users to quickly search and execute commands using keyboard shortcuts.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/command/command.tsx", "target": "components/ui/command.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "beta", "tags": [ "search", "navigation", "keyboard", "palette" ] } }, { "name": "date-field", "type": "registry:ui", "title": "date-field", "description": "A date field allows users to enter and edit date and time values using a keyboard. Each part of a date value is displayed in an individually editable segment.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/date-field/date-field.tsx", "target": "components/ui/date-field.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date" ] } }, { "name": "date-picker", "type": "registry:ui", "title": "date-picker", "description": "A date picker combines one or more DateFields with a calendar popover, allowing users to enter or select a single date/time or a range.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/date-picker/date-picker.tsx", "target": "components/ui/date-picker.tsx", "type": "registry:component" } ], "registryDependencies": [ "calendar" ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "date-time" ] } }, { "name": "input", "type": "registry:ui", "title": "input", "description": "Allows a user to enter a plain text value with a keyboard.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/input/input.tsx", "target": "components/ui/input.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive" ] } }, { "name": "menu", "type": "registry:ui", "title": "menu", "description": "A menu displays a list of actions or options that a user can choose.", "author": "BaseLayer", "categories": [ "pickers" ], "files": [ { "path": "src/core/menu/menu.tsx", "target": "components/ui/menu.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "interactive", "navigation" ] } }, { "name": "meter", "type": "registry:ui", "title": "meter", "description": "A meter represents a quantity within a known range, or a fractional value.", "author": "BaseLayer", "categories": [ "data-display" ], "files": [ { "path": "src/core/meter/meter.tsx", "target": "components/ui/meter.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "progress" ] } }, { "name": "modal", "type": "registry:ui", "title": "modal", "description": "A modal is an overlay element which blocks interaction with elements outside it.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/modal/modal.tsx", "target": "components/ui/modal.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay" ] } }, { "name": "popover", "type": "registry:ui", "title": "popover", "description": "A popover is an overlay element positioned relative to a trigger.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/popover/popover.tsx", "target": "components/ui/popover.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive" ] } }, { "name": "radio-group", "type": "registry:ui", "title": "radio-group", "description": "A radio group allows a user to select a single option from a list of mutually exclusive options.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/radio-group/radio-group.tsx", "target": "components/ui/radio-group.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection" ] } }, { "name": "select", "type": "registry:ui", "title": "select", "description": "A select displays a collapsible list of options and allows a user to select one of them.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/select/select.tsx", "target": "components/ui/select.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] } }, { "name": "slider", "type": "registry:ui", "title": "slider", "description": "A slider allows a user to select one or more values within a range.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/slider/slider.tsx", "target": "components/ui/slider.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "range" ] } }, { "name": "switch", "type": "registry:ui", "title": "switch", "description": "A switch allows a user to turn a setting on or off.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/switch/switch.tsx", "target": "components/ui/switch.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] } }, { "name": "table", "type": "registry:ui", "title": "table", "description": "A table displays data in rows and columns and enables a user to navigate its contents via directional navigation keys, and optionally supports row selection and sorting.", "author": "BaseLayer", "categories": [ "data-display" ], "files": [ { "path": "src/core/table/table.tsx", "target": "components/ui/table.tsx", "type": "registry:component" } ], "registryDependencies": [ "button", "checkbox" ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "interactive" ] } }, { "name": "tabs", "type": "registry:ui", "title": "tabs", "description": "Tabs organize content into multiple sections and allow users to navigate between them.", "author": "BaseLayer", "categories": [ "navigation" ], "files": [ { "path": "src/core/tabs/tabs.tsx", "target": "components/ui/tabs.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation", "interactive", "layout" ] } }, { "name": "tag-group", "type": "registry:ui", "title": "tag-group", "description": "A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/tag-group/tag-group.tsx", "target": "components/ui/tag-group.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection", "filtering" ] } }, { "name": "time-field", "type": "registry:ui", "title": "time-field", "description": "A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/time-field/time-field.tsx", "target": "components/ui/time-field.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "time" ] } }, { "name": "toggle", "type": "registry:ui", "title": "toggle", "description": "A toggle button allows a user to toggle a selection on or off, for example switching between two states or modes.", "author": "BaseLayer", "categories": [ "forms" ], "files": [ { "path": "src/core/toggle/toggle.tsx", "target": "components/ui/toggle.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] } }, { "name": "tooltip", "type": "registry:ui", "title": "tooltip", "description": "A tooltip displays a description of an element on hover or focus.", "author": "BaseLayer", "categories": [ "overlays" ], "files": [ { "path": "src/core/tooltip/tooltip.tsx", "target": "components/ui/tooltip.tsx", "type": "registry:component" } ], "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive", "help" ] } } ] } ================================================ FILE: web/public/r/select.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "select", "type": "registry:ui", "title": "select", "author": "BaseLayer", "description": "A select displays a collapsible list of options and allows a user to select one of them.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/select/select.tsx", "type": "registry:component", "target": "components/ui/select.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "picker" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/slider.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "slider", "type": "registry:ui", "title": "slider", "author": "BaseLayer", "description": "A slider allows a user to select one or more values within a range.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/slider/slider.tsx", "type": "registry:component", "target": "components/ui/slider.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "range" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/switch.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "switch", "type": "registry:ui", "title": "switch", "author": "BaseLayer", "description": "A switch allows a user to turn a setting on or off.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/switch/switch.tsx", "type": "registry:component", "target": "components/ui/switch.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/table.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "table", "type": "registry:ui", "title": "table", "author": "BaseLayer", "description": "A table displays data in rows and columns and enables a user to navigate its contents via directional navigation keys, and optionally supports row selection and sorting.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "registryDependencies": [ "button", "checkbox" ], "files": [ { "path": "src/core/table/table.tsx", "type": "registry:component", "target": "components/ui/table.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "data-display", "interactive" ] }, "categories": [ "data-display" ] } ================================================ FILE: web/public/r/tabs.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "tabs", "type": "registry:ui", "title": "tabs", "author": "BaseLayer", "description": "Tabs organize content into multiple sections and allow users to navigate between them.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/tabs/tabs.tsx", "type": "registry:component", "target": "components/ui/tabs.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "navigation", "interactive", "layout" ] }, "categories": [ "navigation" ] } ================================================ FILE: web/public/r/tag-group.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "tag-group", "type": "registry:ui", "title": "tag-group", "author": "BaseLayer", "description": "A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/tag-group/tag-group.tsx", "type": "registry:component", "target": "components/ui/tag-group.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "selection", "filtering" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/time-field.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "time-field", "type": "registry:ui", "title": "time-field", "author": "BaseLayer", "description": "A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/time-field/time-field.tsx", "type": "registry:component", "target": "components/ui/time-field.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "time" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/toggle.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "toggle", "type": "registry:ui", "title": "toggle", "author": "BaseLayer", "description": "A toggle button allows a user to toggle a selection on or off, for example switching between two states or modes.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/toggle/toggle.tsx", "type": "registry:component", "target": "components/ui/toggle.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "form", "interactive", "toggle" ] }, "categories": [ "forms" ] } ================================================ FILE: web/public/r/tooltip.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "tooltip", "type": "registry:ui", "title": "tooltip", "author": "BaseLayer", "description": "A tooltip displays a description of an element on hover or focus.", "dependencies": [ "react-aria-components", "tailwind-variants", "lucide-react", "tw-animate-css" ], "files": [ { "path": "src/core/tooltip/tooltip.tsx", "type": "registry:component", "target": "components/ui/tooltip.tsx" } ], "tailwind": { "config": { "content": [ "./components/**/*.{ts,tsx}" ], "theme": { "extend": {} } } }, "cssVars": { "theme": { "--color-surface": "var(--surface)", "--color-surface-2": "var(--surface-2)", "--color-fg": "var(--fg)", "--color-fg-muted": "var(--fg-muted)", "--color-fg-disabled": "var(--fg-disabled)", "--color-fg-inverse": "var(--fg-inverse)", "--color-border": "var(--border)", "--color-focus": "var(--focus)", "--color-primary": "var(--primary)", "--color-primary-fg": "var(--primary-fg)", "--color-secondary": "var(--secondary)", "--color-secondary-fg": "var(--secondary-fg)", "--color-danger": "var(--danger)", "--color-danger-fg": "var(--danger-fg)" }, "light": { "--surface": "oklch(98.5% 0 0)", "--surface-2": "oklch(97% 0 0)", "--fg": "oklch(14.5% 0 0)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(70.8% 0 0)", "--border": "oklch(87% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(14.5% 0 0)", "--primary-fg": "oklch(98.5% 0 0)", "--secondary": "oklch(92.2% 0 0)", "--secondary-fg": "oklch(14.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "#ffffff" }, "dark": { "--surface": "oklch(14.5% 0 0)", "--surface-2": "oklch(20.5% 0 0)", "--fg": "oklch(98.5% 0.001 106.423)", "--fg-muted": "oklch(55.6% 0 0)", "--fg-inverse": "oklch(98.5% 0 0)", "--fg-disabled": "oklch(37.1% 0 0)", "--border": "oklch(37.1% 0 0)", "--focus": "oklch(68.5% 0.169 237.323)", "--primary": "oklch(98.5% 0 0)", "--primary-fg": "oklch(14.5% 0 0)", "--secondary": "oklch(26.9% 0 0)", "--secondary-fg": "oklch(98.5% 0 0)", "--danger": "oklch(63.7% 0.237 25.331)", "--danger-fg": "oklch(98.5% 0 0)" } }, "css": { "@import \"tw-animate-css\"": {} }, "meta": { "status": "stable", "tags": [ "overlay", "interactive", "help" ] }, "categories": [ "overlays" ] } ================================================ FILE: web/source.config.ts ================================================ import { defineDocs, frontmatterSchema } from "fumadocs-mdx/config"; import { z } from "zod"; export const docs = defineDocs({ dir: "app/docs/content", docs: { schema: frontmatterSchema.extend({ isRAC: z.boolean().optional().default(false), }), }, }); ================================================ FILE: web/tsconfig.json ================================================ { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./*"], "@/components/ui/*": ["../packages/components/src/core/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] }