{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "ballmac",
  "homepage": "https://ui.ballmac.com",
  "items": [
    {
      "name": "accordion",
      "type": "registry:ui",
      "title": "Accordion",
      "description": "Vertically stacked disclosure sections on Radix Accordion, single or multiple open, with hairline dividers, a rotating plus and height animation.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "devDependencies": [
        "tw-animate-css"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/accordion.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/accordion.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "accordion",
          "disclosure",
          "faq",
          "collapsible",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "Show and hide sections of content one at a time (type=\"single\" collapsible) or several at once (type=\"multiple\").",
          "whenToUse": [
            "FAQ sections",
            "Settings or docs with optional detail",
            "Long content where readers scan headings first"
          ],
          "whenNotToUse": [
            "A single show/hide toggle (use reasoning-disclosure or a Radix Collapsible)",
            "Navigation between views (use tabs)"
          ],
          "composesWith": [
            "badge"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Toggles the focused section"
            },
            {
              "keys": "↓ / ↑",
              "action": "Moves focus between section headers"
            },
            {
              "keys": "Home / End",
              "action": "Moves focus to the first or last header"
            }
          ],
          "customization": [
            "type: single | multiple",
            "collapsible (single): allow closing the open section",
            "defaultValue / value for open sections"
          ]
        },
        "source": {
          "name": "shadcn/ui Accordion",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "accordion-demo",
          "accordion-multiple"
        ],
        "url": "https://ui.ballmac.com/components/accordion"
      }
    },
    {
      "name": "accordion-demo",
      "type": "registry:example",
      "title": "Accordion: Default",
      "description": "Default example of Accordion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/accordion.json"
      ],
      "files": [
        {
          "path": "registry/examples/accordion-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/accordion-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "accordion",
        "tier": "free"
      }
    },
    {
      "name": "accordion-multiple",
      "type": "registry:example",
      "title": "Accordion: Multiple open",
      "description": "Multiple open example of Accordion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/accordion.json"
      ],
      "files": [
        {
          "path": "registry/examples/accordion-multiple.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/accordion-multiple.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "accordion",
        "tier": "free"
      }
    },
    {
      "name": "agent-roster",
      "type": "registry:ui",
      "title": "Agent Roster",
      "description": "Every agent on a team of agents as a card: name and role, a status in words (working, waiting, blocked, idle, offline), what it is doing, a load meter and when it was last active, with status counts that filter the grid.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/agent-roster.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/agent-roster.tsx"
        }
      ],
      "categories": [
        "ai"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "ai",
          "agents",
          "roster",
          "status",
          "team",
          "multi-agent",
          "monitor"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "agents is [{ id, name, role?, status: working | idle | waiting | blocked | offline, task?, load?: 0..100, lastActive? }]. selected / defaultSelected / onSelectedChange track the picked agent (a second click clears it). Status counts are filters; statuses with no agents are hidden.",
          "whenToUse": [
            "An overview of the agents in a multi-agent product and what each is doing",
            "Picking an agent to open its run, logs or settings"
          ],
          "whenNotToUse": [
            "One agent's steps; use trace",
            "A table of users; use data-table",
            "Who handed what to whom; use agent-lanes or handoff-card"
          ],
          "composesWith": [
            "agent-lanes",
            "handoff-card",
            "run-ledger",
            "trace"
          ],
          "a11y": [
            {
              "keys": "Tab, Enter / Space",
              "action": "Filters and cards are buttons; a card is a toggle (aria-pressed)"
            },
            {
              "keys": "Screen readers",
              "action": "Status is written as a word beside its icon; the load is a labelled meter; the shown count is a polite live region"
            },
            {
              "keys": "Blocked",
              "action": "Called out in words and an icon, with a red border only as reinforcement"
            }
          ],
          "customization": [
            "agents and their wording",
            "title",
            "Controlled or uncontrolled selection"
          ]
        },
        "statesNone": "A presentational overview: the agents are passed in, so it has nothing of its own to load or fail.",
        "examples": [
          "agent-roster-demo",
          "agent-roster-select"
        ],
        "url": "https://ui.ballmac.com/components/agent-roster"
      }
    },
    {
      "name": "agent-roster-demo",
      "type": "registry:example",
      "title": "Agent Roster: A team of six",
      "description": "A team of six example of Agent Roster.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/agent-roster.json"
      ],
      "files": [
        {
          "path": "registry/examples/agent-roster-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/agent-roster-demo.tsx"
        }
      ],
      "categories": [
        "ai"
      ],
      "meta": {
        "example": true,
        "of": "agent-roster",
        "tier": "free"
      }
    },
    {
      "name": "agent-roster-select",
      "type": "registry:example",
      "title": "Agent Roster: Select to open a run",
      "description": "Select to open a run example of Agent Roster.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/agent-roster.json"
      ],
      "files": [
        {
          "path": "registry/examples/agent-roster-select.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/agent-roster-select.tsx"
        }
      ],
      "categories": [
        "ai"
      ],
      "meta": {
        "example": true,
        "of": "agent-roster",
        "tier": "free"
      }
    },
    {
      "name": "alert-dialog",
      "type": "registry:ui",
      "title": "Alert Dialog",
      "description": "Focus-managed confirmation for consequential actions, with a clear cancel path, optional media, and a token-based destructive action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/alert-dialog.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/alert-dialog.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "confirmation",
          "modal",
          "destructive",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Ask for explicit confirmation before a consequential action; cancel remains the safe keyboard path.",
          "whenToUse": [
            "Delete or revoke something permanent",
            "Confirm an action with a material consequence"
          ],
          "whenNotToUse": [
            "Show information without requiring a choice; use dialog",
            "Confirm a low-risk routine action"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab / Shift+Tab",
              "action": "Moves within the modal choices"
            },
            {
              "keys": "Enter / Space",
              "action": "Activates the focused choice"
            },
            {
              "keys": "Escape",
              "action": "Cancels when the dialog permits dismissal"
            }
          ],
          "customization": [
            "size: default | sm",
            "destructive action state",
            "controlled open state"
          ]
        },
        "examples": [
          "alert-dialog-demo",
          "alert-dialog-states"
        ],
        "url": "https://ui.ballmac.com/components/alert-dialog"
      }
    },
    {
      "name": "alert-dialog-demo",
      "type": "registry:example",
      "title": "Alert Dialog: Remove a project",
      "description": "Remove a project example of Alert Dialog.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alert-dialog.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/alert-dialog-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alert-dialog-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "alert-dialog",
        "tier": "free"
      }
    },
    {
      "name": "alert-dialog-states",
      "type": "registry:example",
      "title": "Alert Dialog: Confirmation styles",
      "description": "Confirmation styles example of Alert Dialog.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alert-dialog.json"
      ],
      "files": [
        {
          "path": "registry/examples/alert-dialog-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alert-dialog-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "alert-dialog",
        "tier": "free"
      }
    },
    {
      "name": "alert",
      "type": "registry:ui",
      "title": "Alert",
      "description": "A semantic callout with five theme-aware tones, clear icon placement, an action row, and opt-in urgent announcements.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/alert.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/alert.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "alert",
          "callout",
          "status"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A semantic callout with five theme-aware tones, clear icon placement, an action row, and opt-in urgent announcements.",
          "whenToUse": [
            "Display a status or important message",
            "Pair a warning with a clear next action"
          ],
          "whenNotToUse": [
            "Use a toast for transient confirmation"
          ],
          "composesWith": [
            "badge",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "moves to links and actions"
            }
          ],
          "customization": [
            "variant: default | info | success | warning | destructive",
            "urgent: announce new urgent content"
          ]
        },
        "source": {
          "name": "shadcn/ui Alert",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "alert-demo",
          "alert-states"
        ],
        "url": "https://ui.ballmac.com/components/alert"
      }
    },
    {
      "name": "alert-demo",
      "type": "registry:example",
      "title": "Alert: Overview",
      "description": "Overview example of Alert.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alert.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/alert-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alert-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "alert",
        "tier": "free"
      }
    },
    {
      "name": "alert-states",
      "type": "registry:example",
      "title": "Alert: States and variants",
      "description": "States and variants example of Alert.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alert.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/alert-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alert-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "alert",
        "tier": "free"
      }
    },
    {
      "name": "android-frame",
      "type": "registry:ui",
      "title": "Android Frame",
      "description": "A modern Android phone drawn in CSS: satin frame in porcelain, obsidian or sage, centered punch-hole camera, Material-style status bar and gesture or three-button navigation. Children render at phone resolution, scaled to fit.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/android-frame.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/android-frame.tsx"
        }
      ],
      "categories": [
        "devices"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "mockup",
          "device",
          "phone",
          "android",
          "pixel",
          "mobile",
          "hero"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "Wrap a mobile screen in <AndroidFrame screenWidth={412}>: children render below a status bar at 412 CSS px wide and are scaled to the frame's width. Set the width with className (e.g. w-64).",
          "whenToUse": [
            "Showing an Android or responsive mobile app",
            "Side by side with phone-frame for cross-platform stories"
          ],
          "whenNotToUse": [
            "iPhone mockups (phone-frame)",
            "Real device screenshots with a bezel"
          ],
          "composesWith": [
            "phone-frame",
            "tablet-frame",
            "laptop-frame"
          ],
          "a11y": [
            {
              "keys": "Static",
              "action": "Purely visual: no focusable elements from the frame"
            },
            {
              "keys": "Reduced motion",
              "action": "Video on the screen is not autoplayed"
            }
          ],
          "customization": [
            "variant: auto | porcelain | obsidian | sage",
            "navigation: gesture | buttons | none",
            "screenWidth: virtual width in CSS px",
            "statusBar, time",
            "src/alt or videoSrc/poster instead of children"
          ]
        },
        "examples": [
          "android-frame-demo",
          "android-frame-buttons"
        ],
        "url": "https://ui.ballmac.com/components/android-frame"
      }
    },
    {
      "name": "android-frame-demo",
      "type": "registry:example",
      "title": "Android Frame: Home screen",
      "description": "Home screen example of Android Frame.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/android-frame.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/android-frame-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/android-frame-demo.tsx"
        }
      ],
      "categories": [
        "devices"
      ],
      "meta": {
        "example": true,
        "of": "android-frame",
        "tier": "free"
      }
    },
    {
      "name": "android-frame-buttons",
      "type": "registry:example",
      "title": "Android Frame: Three-button navigation",
      "description": "Three-button navigation example of Android Frame.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/android-frame.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/android-frame-buttons.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/android-frame-buttons.tsx"
        }
      ],
      "categories": [
        "devices"
      ],
      "meta": {
        "example": true,
        "of": "android-frame",
        "tier": "free"
      }
    },
    {
      "name": "animated-beam",
      "type": "registry:ui",
      "title": "Animated Beam",
      "description": "An SVG beam that connects two elements with a curved path and sends a glowing gradient pulse along it. Follows layout changes, pauses off-screen, static under reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/animated-beam.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/animated-beam.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "beam",
          "connection",
          "integration",
          "diagram",
          "svg",
          "hero",
          "motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "tests": true,
        "ai": {
          "summary": "Give a relative container a ref, give each endpoint element a ref, and render <AnimatedBeam containerRef fromRef toRef /> inside the container once per connection. Put endpoint nodes above the beams with relative z-10. The SVG is aria-hidden and pointer-events-none.",
          "whenToUse": [
            "Integration diagrams: tools or data sources flowing into an agent or product",
            "Showing a request path between services on a landing page",
            "Explaining a sync or pipeline visually in a feature section"
          ],
          "whenNotToUse": [
            "Real, data-driven graphs with many nodes (use a graph library)",
            "Conveying state on its own; label the nodes, the beam is decorative"
          ],
          "composesWith": [
            "orbiting-circles",
            "dot-pattern",
            "border-beam"
          ],
          "a11y": [],
          "customization": [
            "curvature in px (positive bows up), reverse to flip direction",
            "duration, delay and repeatDelay in seconds; stagger delays across beams",
            "pulseLength as a fraction of the path (default 0.35)",
            "startXOffset/startYOffset/endXOffset/endYOffset to attach to node edges",
            "pathColor, pathWidth, pathOpacity; gradientStartColor/gradientStopColor default to var(--chart-1) → var(--chart-4)"
          ]
        },
        "source": {
          "name": "Magic UI Animated Beam",
          "url": "https://github.com/magicuidesign/magicui",
          "license": "MIT",
          "copyright": "Copyright (c) Magic UI",
          "modified": true
        },
        "examples": [
          "animated-beam-demo",
          "animated-beam-bidirectional"
        ],
        "url": "https://ui.ballmac.com/components/animated-beam"
      }
    },
    {
      "name": "animated-beam-demo",
      "type": "registry:example",
      "title": "Animated Beam: Agent integrations",
      "description": "Agent integrations example of Animated Beam.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-beam.json",
        "utils"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/animated-beam-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-beam-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "animated-beam",
        "tier": "free"
      }
    },
    {
      "name": "animated-beam-bidirectional",
      "type": "registry:example",
      "title": "Animated Beam: Two-way sync",
      "description": "Two-way sync example of Animated Beam.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-beam.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/animated-beam-bidirectional.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-beam-bidirectional.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "animated-beam",
        "tier": "free"
      }
    },
    {
      "name": "animated-grid",
      "type": "registry:ui",
      "title": "Animated Grid",
      "description": "A decorative hairline grid background where a few random cells softly light up and fade, like instrument lights. SVG, hydration-safe, static under reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/animated-grid.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/animated-grid.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "background",
          "grid",
          "pattern",
          "hero",
          "decorative",
          "motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "Place <AnimatedGrid /> as the first child of a relative container (it is absolute inset-0, aria-hidden, pointer-events-none) and put content after it with relative positioning. Lit cells are picked on the client after mount, so SSR output is just the grid.",
          "whenToUse": [
            "Hero or section backgrounds on developer-tool and SaaS landing pages",
            "Empty states or sign-in screens that need quiet texture"
          ],
          "whenNotToUse": [
            "Behind dense text or data (it competes with content)",
            "More than one per screen"
          ],
          "composesWith": [
            "text-reveal",
            "shimmer-text",
            "magnetic-button"
          ],
          "a11y": [],
          "customization": [
            "cellSize in px (default 40); count of lit cells (default 8); interval in ms between changes (default 700)",
            "fade toggles the radial edge mask; pass your own mask via style",
            "Colors are CSS variables: className=\"[--grid-line:…] [--grid-light:…]\" (defaults: 8% foreground lines, 20% ring cells)"
          ]
        },
        "examples": [
          "animated-grid-demo"
        ],
        "url": "https://ui.ballmac.com/components/animated-grid"
      }
    },
    {
      "name": "animated-grid-demo",
      "type": "registry:example",
      "title": "Animated Grid: Hero background",
      "description": "Hero background example of Animated Grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-grid.json"
      ],
      "files": [
        {
          "path": "registry/examples/animated-grid-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-grid-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "animated-grid",
        "tier": "free"
      }
    },
    {
      "name": "animated-list",
      "type": "registry:ui",
      "title": "Animated List",
      "description": "A live feed where new items spring in at the top and the rest glide down, with leave animations, an item cap, an optional fading tail and a polite announcement for new entries.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/animated-list.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/animated-list.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "list",
          "feed",
          "notifications",
          "live",
          "spring"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "<AnimatedList max fadeEnd announce><AnimatedListItem key={id}>…</AnimatedListItem></AnimatedList>. Each item needs a stable key. Prepend new entries to your array; layout animation does the rest.",
          "whenToUse": [
            "Live activity, notification and event feeds",
            "Chat-like logs where entries arrive over time"
          ],
          "whenNotToUse": [
            "Static lists (stagger-list)",
            "Hundreds of rows (virtualize instead)"
          ],
          "composesWith": [
            "notification-stack",
            "activity-feed",
            "stagger-list"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "announce turns on a polite live region that reads additions only"
            },
            {
              "keys": "Reduced motion",
              "action": "Items fade in without moving or scaling"
            }
          ],
          "customization": [
            "max",
            "fadeEnd",
            "announce",
            "label",
            "item content is yours"
          ]
        },
        "examples": [
          "animated-list-demo",
          "animated-list-log"
        ],
        "url": "https://ui.ballmac.com/components/animated-list"
      }
    },
    {
      "name": "animated-list-demo",
      "type": "registry:example",
      "title": "Animated List: Live notification feed",
      "description": "Live notification feed example of Animated List.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-list.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/animated-list-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-list-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "animated-list",
        "tier": "free"
      }
    },
    {
      "name": "animated-list-log",
      "type": "registry:example",
      "title": "Animated List: Capped activity log",
      "description": "Capped activity log example of Animated List.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-list.json"
      ],
      "files": [
        {
          "path": "registry/examples/animated-list-log.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-list-log.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "animated-list",
        "tier": "free"
      }
    },
    {
      "name": "animated-tabs",
      "type": "registry:ui",
      "title": "Animated Tabs",
      "description": "Radix Tabs with a pill or underline indicator that slides between triggers on a spring, and panels that fade in. Keeps full keyboard support and ARIA; controlled or uncontrolled.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12",
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/animated-tabs.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/animated-tabs.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "tabs",
          "segmented",
          "navigation",
          "indicator",
          "layout animation",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "tests": true,
        "ai": {
          "summary": "Same API as Radix Tabs: <AnimatedTabs defaultValue variant=\"pill\" | \"underline\"> with AnimatedTabsList, AnimatedTabsTrigger value and AnimatedTabsContent value. The indicator is a Motion layoutId element inside the active trigger.",
          "whenToUse": [
            "Switching between views of the same object (overview, activity, settings)",
            "Settings pages with a few sections",
            "Pricing toggles such as monthly and yearly"
          ],
          "whenNotToUse": [
            "Page-level navigation between routes (use links)",
            "More than about six options (use a select)",
            "Package-manager command tabs (use install-tabs)"
          ],
          "composesWith": [
            "install-tabs",
            "code-block"
          ],
          "a11y": [
            {
              "keys": "Left / Right",
              "action": "Moves focus between tabs and selects them"
            },
            {
              "keys": "Home / End",
              "action": "Jumps to the first or last tab"
            },
            {
              "keys": "Tab",
              "action": "Moves from the tab list into the selected panel"
            }
          ],
          "customization": [
            "variant: pill (default) | underline",
            "value / onValueChange for controlled use, defaultValue otherwise",
            "Icon-only triggers need aria-label",
            "Style parts via [data-slot=animated-tabs-indicator], -list, -trigger, -content",
            "Reduced motion: the indicator jumps and panels appear without a fade"
          ]
        },
        "examples": [
          "animated-tabs-demo",
          "animated-tabs-underline"
        ],
        "url": "https://ui.ballmac.com/components/animated-tabs"
      }
    },
    {
      "name": "animated-tabs-demo",
      "type": "registry:example",
      "title": "Animated Tabs: Pill with icons",
      "description": "Pill with icons example of Animated Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-tabs.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/animated-tabs-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-tabs-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "animated-tabs",
        "tier": "free"
      }
    },
    {
      "name": "animated-tabs-underline",
      "type": "registry:example",
      "title": "Animated Tabs: Underline",
      "description": "Underline example of Animated Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/animated-tabs.json"
      ],
      "files": [
        {
          "path": "registry/examples/animated-tabs-underline.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/animated-tabs-underline.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "animated-tabs",
        "tier": "free"
      }
    },
    {
      "name": "api-key-field",
      "type": "registry:ui",
      "title": "API Key Field",
      "description": "Displays a secret such as an API key, masked by default (sk-live-••••••••a1b2), with a reveal toggle, a copy button that copies the full key, and an optional regenerate action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/api-key-field.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/api-key-field.tsx"
        }
      ],
      "categories": [
        "developer"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "api-key",
          "secret",
          "token",
          "copy",
          "mask",
          "settings",
          "developer"
        ],
        "version": "1.0.1",
        "updated": "2026-10-02",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-02",
            "note": "Labels (show, hide, copy, regenerate) come from the i18n messages, padding uses start/end so the field mirrors in right-to-left, and the key stays left-to-right. Adds the i18n helper.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Show an existing secret: <ApiKeyField value={key} label='Secret key' onRegenerate={confirmThenRotate} />. It is read-only; copy always copies the full value, even while masked.",
          "whenToUse": [
            "API keys, webhook signing secrets and access tokens on settings or developer pages",
            "Showing a newly created key once so the user can copy it"
          ],
          "whenNotToUse": [
            "Password entry (use an input with type=password)",
            "Secrets you should not send to the browser at all (show only the last four characters from the server)"
          ],
          "composesWith": [
            "button",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves between reveal, copy and regenerate buttons"
            },
            {
              "keys": "Enter / Space",
              "action": "Reveal is a toggle button (aria-pressed); copy announces 'Key copied to clipboard'"
            },
            {
              "keys": "—",
              "action": "While masked, screen readers hear the prefix and last characters, not bullet characters"
            }
          ],
          "customization": [
            "visiblePrefix (default 8) and visibleSuffix (default 4) characters stay visible; the mask length is fixed so it doesn't reveal the key length",
            "revealed/defaultRevealed/onRevealedChange",
            "onRegenerate shows a regenerate button; confirmation is the caller's job (e.g. a dialog); regenerating spins it",
            "onCopy runs after a successful copy; the component never logs the value"
          ]
        },
        "examples": [
          "api-key-field-demo"
        ],
        "url": "https://ui.ballmac.com/components/api-key-field"
      }
    },
    {
      "name": "api-key-field-demo",
      "type": "registry:example",
      "title": "API Key Field: Default",
      "description": "Default example of API Key Field.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-key-field.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-key-field-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-key-field-demo.tsx"
        }
      ],
      "categories": [
        "developer"
      ],
      "meta": {
        "example": true,
        "of": "api-key-field",
        "tier": "free"
      }
    },
    {
      "name": "app-shell",
      "type": "registry:ui",
      "title": "App Shell",
      "description": "The frame of an application page: skip link, sticky header, sidebar that becomes a sheet on small screens, main area, optional aside and footer.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/sheet.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/app-shell.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/app-shell.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "layout",
          "dashboard",
          "sidebar",
          "landmarks"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "AppShell > AppShellSkipLink, AppShellHeader (with AppShellSidebarTrigger), AppShellSidebar, AppShellMain, AppShellAside, AppShellFooter. Sizes are CSS variables set by props.",
          "whenToUse": [
            "Admin and dashboard pages",
            "Any page with a sidebar, a main column and optional details"
          ],
          "whenNotToUse": [
            "A collapsible icon-rail sidebar; use sidebar",
            "Marketing pages; use navbar"
          ],
          "composesWith": [
            "sidebar",
            "navbar",
            "sheet"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "The first stop is the skip link; it jumps to the main content"
            },
            {
              "keys": "Screen readers",
              "action": "Header, sidebar, main, aside and footer are landmarks"
            },
            {
              "keys": "Escape",
              "action": "Closes the mobile sidebar"
            }
          ],
          "customization": [
            "headerHeight, sidebarWidth, asideWidth",
            "sticky panels scroll on their own",
            "hide the aside by leaving it out"
          ]
        },
        "examples": [
          "app-shell-demo",
          "app-shell-states"
        ],
        "url": "https://ui.ballmac.com/components/app-shell"
      }
    },
    {
      "name": "app-shell-demo",
      "type": "registry:example",
      "title": "App Shell: Dashboard frame",
      "description": "Dashboard frame example of App Shell.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-shell.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/app-shell-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-shell-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "app-shell",
        "tier": "free"
      }
    },
    {
      "name": "app-shell-states",
      "type": "registry:example",
      "title": "App Shell: Compact shell",
      "description": "Compact shell example of App Shell.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-shell.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/app-shell-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-shell-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "app-shell",
        "tier": "free"
      }
    },
    {
      "name": "app-window",
      "type": "registry:ui",
      "title": "App Window",
      "description": "The window chrome of a real desktop app (Tauri or Electron): a title bar that drags the window, double-click to maximize, and the controls the platform draws: traffic lights, Windows caption buttons, or none.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/feel-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/app-window.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/app-window.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "window",
          "titlebar",
          "tauri",
          "electron",
          "desktop",
          "macos",
          "windows",
          "chrome",
          "drag region",
          "feel"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "macOS traffic lights are 12 px apart so every target meets the 24 px target-size rule (WCAG 2.5.8).",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-12",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Real window chrome for a Tauri or Electron app. <AppWindow onClose onMinimize onMaximize><AppWindowTitleBar title=\"…\">toolbar</AppWindowTitleBar><AppWindowContent/></AppWindow>. It draws the platform's controls (macOS traffic lights on the left, Windows caption buttons on the right, none on iOS or web) from the page's feel, drags the window, and maximizes on double-click. You wire the callbacks; there is no Tauri or Electron dependency.",
          "whenToUse": [
            "The window of a Tauri or Electron app with a hidden native title bar (decorations: false, or titleBarStyle hidden)",
            "A desktop-style web app that should match the platform's window chrome"
          ],
          "whenNotToUse": [
            "Landing-page mockups of a Mac app (use mac-window)",
            "Modal dialogs inside a web app (use dialog)"
          ],
          "composesWith": [
            "feel-auto",
            "sidebar",
            "toolbar",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Reaches the window controls when their handlers are set, then the toolbar"
            },
            {
              "keys": "Enter / Space",
              "action": "Presses the focused window control"
            },
            {
              "keys": "Double-click the bar",
              "action": "Maximizes or restores (calls onMaximize)"
            }
          ],
          "customization": [
            "feel: 'macos' | 'windows' | 'ios' | 'web' overrides the page's feel for this window",
            "active: defaults to following real window focus; maximized switches the Windows button to restore and squares the corners",
            "onFullscreen: the macOS green button; hold Option to call onMaximize instead",
            "Tauri v2: onClose={() => getCurrentWindow().close()}; Electron: send an IPC message from the handler",
            "AppWindowControls renders only the controls, for a custom title bar"
          ]
        },
        "source": {
          "name": "tauri-controls",
          "url": "https://github.com/agmmnn/tauri-controls",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 agmmnn",
          "modified": true
        },
        "examples": [
          "app-window-demo",
          "app-window-feels"
        ],
        "url": "https://ui.ballmac.com/components/app-window"
      }
    },
    {
      "name": "app-window-demo",
      "type": "registry:example",
      "title": "App Window: Notes app, in any feel",
      "description": "Notes app, in any feel example of App Window.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-window.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/switch.json",
        "https://ui.ballmac.com/r/feel-presets.json",
        "utils"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/app-window-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-window-demo.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "app-window",
        "tier": "free"
      }
    },
    {
      "name": "app-window-feels",
      "type": "registry:example",
      "title": "App Window: One window, three feels",
      "description": "One window, three feels example of App Window.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-window.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/feel-presets.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/app-window-feels.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-window-feels.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "app-window",
        "tier": "free"
      }
    },
    {
      "name": "aspect-ratio",
      "type": "registry:ui",
      "title": "Aspect Ratio",
      "description": "A CSS-native ratio frame that reserves space for media and safely handles invalid ratio values.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/aspect-ratio.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/aspect-ratio.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "media",
          "image",
          "layout"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A CSS-native ratio frame that reserves space for media and safely handles invalid ratio values.",
          "whenToUse": [
            "Reserve image or video space before it loads",
            "Keep cards aligned across a grid"
          ],
          "whenNotToUse": [
            "Use fixed height when cropping is intentional"
          ],
          "composesWith": [
            "card"
          ],
          "a11y": [],
          "customization": [
            "ratio: width divided by height; default 16/9"
          ]
        },
        "source": {
          "name": "shadcn/ui Aspect Ratio",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "aspect-ratio-demo",
          "aspect-ratio-states"
        ],
        "url": "https://ui.ballmac.com/components/aspect-ratio"
      }
    },
    {
      "name": "aspect-ratio-demo",
      "type": "registry:example",
      "title": "Aspect Ratio: Overview",
      "description": "Overview example of Aspect Ratio.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/aspect-ratio.json"
      ],
      "files": [
        {
          "path": "registry/examples/aspect-ratio-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/aspect-ratio-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "aspect-ratio",
        "tier": "free"
      }
    },
    {
      "name": "aspect-ratio-states",
      "type": "registry:example",
      "title": "Aspect Ratio: States and variants",
      "description": "States and variants example of Aspect Ratio.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/aspect-ratio.json"
      ],
      "files": [
        {
          "path": "registry/examples/aspect-ratio-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/aspect-ratio-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "aspect-ratio",
        "tier": "free"
      }
    },
    {
      "name": "avatar",
      "type": "registry:ui",
      "title": "Avatar",
      "description": "A Radix avatar with image and initials fallback, three sizes, an optional presence dot, and AvatarGroup for overlapping stacks with a +N overflow counter.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/avatar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/avatar.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "avatar",
          "user",
          "profile",
          "presence",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "User or team picture with initials fallback while the image loads or if it fails. Add status for presence, and wrap several in AvatarGroup with max to cap the visible count.",
          "whenToUse": [
            "Showing who owns, edited or is assigned to something",
            "Account menus and comment threads",
            "Stacks of collaborators or members with an overflow count"
          ],
          "whenNotToUse": [
            "Logos or product icons (use an img)",
            "Large profile headers that need a custom shape"
          ],
          "composesWith": [
            "badge",
            "tooltip",
            "dialog"
          ],
          "a11y": [],
          "customization": [
            "size: sm | default | lg (24 / 32 / 44 px)",
            "status: online | away | busy | offline, announced as screen reader text (statusLabel to override)",
            "AvatarGroup: size, max, total (when more members exist than you render)",
            "Always include an AvatarFallback with initials; the image alt names the person"
          ]
        },
        "source": {
          "name": "shadcn/ui Avatar",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "avatar-demo",
          "avatar-group"
        ],
        "url": "https://ui.ballmac.com/components/avatar"
      }
    },
    {
      "name": "avatar-demo",
      "type": "registry:example",
      "title": "Avatar: Default",
      "description": "Default example of Avatar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/avatar.json"
      ],
      "files": [
        {
          "path": "registry/examples/avatar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/avatar-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "avatar",
        "tier": "free"
      }
    },
    {
      "name": "avatar-group",
      "type": "registry:example",
      "title": "Avatar: Group",
      "description": "Group example of Avatar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/avatar.json"
      ],
      "files": [
        {
          "path": "registry/examples/avatar-group.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/avatar-group.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "avatar",
        "tier": "free"
      }
    },
    {
      "name": "back-to-top",
      "type": "registry:ui",
      "title": "Back To Top",
      "description": "A floating button that appears after scrolling, draws a progress ring, scrolls smoothly (instantly under reduced motion) and moves focus to the content.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react",
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/scroll.json",
        "https://ui.ballmac.com/r/motion-presets.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/back-to-top.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/back-to-top.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "button",
          "scroll",
          "floating",
          "progress"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Render <BackToTop /> once. threshold sets when it appears; container follows a scrollable element; focusTarget chooses where focus lands.",
          "whenToUse": [
            "Long pages, feeds and docs",
            "Panels with a lot of scrolling"
          ],
          "whenNotToUse": [
            "Short pages",
            "Infinite feeds where returning to the top loses work"
          ],
          "composesWith": [
            "scroll-progress",
            "button"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Scrolls to the top and moves focus to the main content so focus is not lost when the button disappears"
            },
            {
              "keys": "Reduced motion",
              "action": "Jumps instead of scrolling smoothly"
            }
          ],
          "customization": [
            "threshold",
            "showProgress",
            "showLabel",
            "container and focusTarget"
          ]
        },
        "examples": [
          "back-to-top-demo",
          "back-to-top-states"
        ],
        "url": "https://ui.ballmac.com/components/back-to-top"
      }
    },
    {
      "name": "back-to-top-demo",
      "type": "registry:example",
      "title": "Back To Top: Progress ring",
      "description": "Progress ring example of Back To Top.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/back-to-top.json"
      ],
      "files": [
        {
          "path": "registry/examples/back-to-top-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/back-to-top-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "back-to-top",
        "tier": "free"
      }
    },
    {
      "name": "back-to-top-states",
      "type": "registry:example",
      "title": "Back To Top: Labelled",
      "description": "Labelled example of Back To Top.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/back-to-top.json"
      ],
      "files": [
        {
          "path": "registry/examples/back-to-top-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/back-to-top-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "back-to-top",
        "tier": "free"
      }
    },
    {
      "name": "badge",
      "type": "registry:ui",
      "title": "Badge",
      "description": "A small pill label in four variants with an optional status dot and success, warning and error tones. Style links with badgeVariants().",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/badge.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/badge.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "badge",
          "status",
          "tag",
          "label",
          "pill"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "Short metadata or status label. Use variant for emphasis, status (neutral | success | warning | error) for state with a coloured dot, and badgeVariants() on an <a> for a link.",
          "whenToUse": [
            "Status of a deployment, invoice or job",
            "Counts, plan names and version tags",
            "Small labels on cards and table rows"
          ],
          "whenNotToUse": [
            "Clickable filters that toggle (use a toggle or button)",
            "Long text (it doesn't wrap)",
            "Notifications that need attention (use an alert or toast)"
          ],
          "composesWith": [
            "avatar",
            "button",
            "switch"
          ],
          "a11y": [],
          "customization": [
            "variant: default | secondary | outline | destructive",
            "status: neutral | success (chart-2) | warning (chart-3) | error (destructive); overrides variant colours with a soft tint",
            "dot: shows a leading dot; on by default when status is set",
            "badgeVariants({ variant }) gives the same styles to an <a> or button"
          ]
        },
        "source": {
          "name": "shadcn/ui Badge",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "badge-demo",
          "badge-status"
        ],
        "url": "https://ui.ballmac.com/components/badge"
      }
    },
    {
      "name": "badge-demo",
      "type": "registry:example",
      "title": "Badge: Default",
      "description": "Default example of Badge.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/badge.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/badge-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/badge-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "badge",
        "tier": "free"
      }
    },
    {
      "name": "badge-status",
      "type": "registry:example",
      "title": "Badge: Status",
      "description": "Status example of Badge.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/badge.json"
      ],
      "files": [
        {
          "path": "registry/examples/badge-status.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/badge-status.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "badge",
        "tier": "free"
      }
    },
    {
      "name": "banner",
      "type": "registry:ui",
      "title": "Banner",
      "description": "A page-wide announcement with semantic tones, optional action, and controlled or local dismissal.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/banner.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/banner.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "announcement",
          "status",
          "dismissible"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A page-wide announcement with semantic tones, optional action, and controlled or local dismissal.",
          "whenToUse": [
            "Announce a page-level update",
            "Keep a persistent notice above page content"
          ],
          "whenNotToUse": [
            "Use alert for content scoped to one panel"
          ],
          "composesWith": [
            "alert",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter",
              "action": "Focus and activate the action or dismiss control"
            }
          ],
          "customization": [
            "tone: info | success | warning",
            "Controlled or uncontrolled visibility"
          ]
        },
        "examples": [
          "banner-demo",
          "banner-states"
        ],
        "url": "https://ui.ballmac.com/components/banner"
      }
    },
    {
      "name": "banner-demo",
      "type": "registry:example",
      "title": "Banner: Overview",
      "description": "Overview example of Banner.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/banner.json"
      ],
      "files": [
        {
          "path": "registry/examples/banner-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/banner-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "banner",
        "tier": "free"
      }
    },
    {
      "name": "banner-states",
      "type": "registry:example",
      "title": "Banner: States and variants",
      "description": "States and variants example of Banner.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/banner.json"
      ],
      "files": [
        {
          "path": "registry/examples/banner-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/banner-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "banner",
        "tier": "free"
      }
    },
    {
      "name": "bar-list",
      "type": "registry:ui",
      "title": "Bar List",
      "description": "A ranked list of bars with the name and number on top of the bar, so both stay readable at any width. Rows can be links or buttons, a long list folds to its top few, and every value is real text.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/bar-list.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/bar-list.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chart",
          "ranking",
          "top list",
          "analytics",
          "bars",
          "dashboard",
          "leaderboard"
        ],
        "version": "1.0.0",
        "updated": "2026-10-25",
        "tests": true,
        "ai": {
          "summary": "items is [{ id, label, value, href?, icon?, hint? }]. Sorted by value unless sort is false. title, format(value), showShare (percent of total), limit (folds the rest behind a Show N more button). href makes a row a link; onSelect(id) with selected makes rows toggle buttons. The bar is decoration behind real text.",
          "whenToUse": [
            "Top pages, sources, countries, products or errors in an analytics view",
            "A leaderboard where the label matters more than the shape"
          ],
          "whenNotToUse": [
            "Comparing a few values precisely over time; use chart-bar",
            "Part-to-whole with many parts; use treemap or split-bar"
          ],
          "composesWith": [
            "split-bar",
            "funnel-chart",
            "stat-card",
            "kpi-row"
          ],
          "a11y": [
            {
              "keys": "List",
              "action": "An ordered list; each row also says 'Number n' for screen readers"
            },
            {
              "keys": "Rows",
              "action": "Links and buttons are native; buttons have pressed state"
            },
            {
              "keys": "Fold",
              "action": "A button with aria-expanded"
            },
            {
              "keys": "Values",
              "action": "Written as text, with the share as a percent if asked, so nothing depends on bar length"
            }
          ],
          "customization": [
            "items and title",
            "format, showShare",
            "limit",
            "onSelect and selected"
          ]
        },
        "statesNone": "A presentational list: the items are passed in, so it has nothing of its own to load.",
        "examples": [
          "bar-list-demo",
          "bar-list-select"
        ],
        "url": "https://ui.ballmac.com/components/bar-list"
      }
    },
    {
      "name": "bar-list-demo",
      "type": "registry:example",
      "title": "Bar List: Top pages with links and a fold",
      "description": "Top pages with links and a fold example of Bar List.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/bar-list.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/bar-list-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/bar-list-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "bar-list",
        "tier": "free"
      }
    },
    {
      "name": "bar-list-select",
      "type": "registry:example",
      "title": "Bar List: Rows as filter buttons",
      "description": "Rows as filter buttons example of Bar List.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/bar-list.json"
      ],
      "files": [
        {
          "path": "registry/examples/bar-list-select.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/bar-list-select.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "bar-list",
        "tier": "free"
      }
    },
    {
      "name": "bento-grid",
      "type": "registry:ui",
      "title": "Bento Grid",
      "description": "A responsive bento layout of feature cards that span columns and rows. Each BentoCard has a background visual slot, icon, title and description, and a link that slides up on hover or focus.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/media-image.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/bento-grid.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/bento-grid.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "bento",
          "grid",
          "features",
          "landing",
          "cards",
          "layout"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Fixes a crash when it is rendered from a server component: isMediaImage now comes from the new media-image helper, not from the client-only media file. Adds media-image as a dependency.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "<BentoGrid columns={3}> with <BentoCard colSpan rowSpan icon title description href background />. The grid responds to its own width (container queries): one column below 36rem. The background slot takes any decorative node, such as animated-grid, marquee or number-ticker visuals.",
          "whenToUse": [
            "Landing-page feature sections with 4–7 features of different weight",
            "Product overviews where each tile shows a small live visual",
            "Dashboard home pages with shortcuts"
          ],
          "whenNotToUse": [
            "Uniform lists of equal items (use a plain grid of cards)",
            "Long text content; cards hold one or two lines"
          ],
          "composesWith": [
            "animated-grid",
            "marquee",
            "number-ticker",
            "border-beam"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focuses the card's link; the whole card is its click target and shows a focus ring"
            }
          ],
          "customization": [
            "BentoGrid: columns 2 | 3 | 4 (default 3), rowHeight (default 13rem)",
            "BentoCard: colSpan 1–4, rowSpan 1–2, href + cta (default \"Learn more\")",
            "background is aria-hidden and masked to fade toward the text",
            "On touch screens the link is always visible"
          ]
        },
        "examples": [
          "bento-grid-demo",
          "bento-grid-features"
        ],
        "url": "https://ui.ballmac.com/components/bento-grid"
      }
    },
    {
      "name": "bento-grid-demo",
      "type": "registry:example",
      "title": "Bento Grid: Live feature grid",
      "description": "Live feature grid example of Bento Grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/bento-grid.json",
        "https://ui.ballmac.com/r/animated-grid.json",
        "https://ui.ballmac.com/r/border-beam.json",
        "https://ui.ballmac.com/r/marquee.json",
        "https://ui.ballmac.com/r/number-ticker.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/bento-grid-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/bento-grid-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "bento-grid",
        "tier": "free"
      }
    },
    {
      "name": "bento-grid-features",
      "type": "registry:example",
      "title": "Bento Grid: Two columns",
      "description": "Two columns example of Bento Grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/bento-grid.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/bento-grid-features.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/bento-grid-features.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "bento-grid",
        "tier": "free"
      }
    },
    {
      "name": "about-1",
      "type": "registry:block",
      "title": "About 1: company story",
      "description": "A company story page: a large two-tone statement and a wide picture, numbers that count up, the story beside a pull quote, value cards that light up under the pointer, a milestone timeline and a closing call to action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/blur-fade.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/cover-art.json",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/number-ticker.json",
        "https://ui.ballmac.com/r/spotlight-card.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/about-1/about-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/about-1/about-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "about"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "about",
          "company",
          "story",
          "mission",
          "values",
          "timeline",
          "stats",
          "culture",
          "brand",
          "editorial"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "An About page. <About1 eyebrow headline={['Line one.', 'Softer line two.']} intro media mediaAlt stats={[{ label, value, suffix, plain }]} story={['Larger first paragraph', '…']} quote={{ text, name, role }} values={[{ title, description, icon }]} milestones={[{ year, title, description }]} cta={{ title, description, primary: { label, href }, secondary }} />. Every part is optional: pass [] for stats, values or milestones, or null for quote or cta, and that section disappears. Without media it draws art from the headline.",
          "whenToUse": [
            "The About or Our story page of a company, studio or product",
            "A manifesto page with numbers, values and history"
          ],
          "whenNotToUse": [
            "A page of people (use team-1)",
            "A job list (use careers-1)",
            "A landing page (use the hero blocks)"
          ],
          "composesWith": [
            "header-2",
            "footer-2",
            "team-1",
            "careers-1",
            "gallery-1"
          ],
          "a11y": [
            {
              "keys": "Headings",
              "action": "One h1 for the statement and an h2 for each section; the pull quote is a real blockquote in a figure with a caption"
            },
            {
              "keys": "Motion",
              "action": "Entrances, the count-up and the card glow are skipped under reduced motion"
            },
            {
              "keys": "Timeline",
              "action": "An ordered list; the year is text next to each event, so order never depends on the line"
            }
          ],
          "customization": [
            "headline as one string or two lines",
            "stats[].plain for years; suffix for \"k+\"",
            "values[].icon takes any node, usually a lucide icon",
            "media takes a URL, an image with alt text or an element"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "about-1-demo",
          "about-1-short"
        ],
        "url": "https://ui.ballmac.com/components/about-1"
      }
    },
    {
      "name": "about-1-demo",
      "type": "registry:example",
      "title": "About 1: company story: Default",
      "description": "Default example of About 1: company story.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/about-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/about-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/about-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "about-1",
        "tier": "free"
      }
    },
    {
      "name": "about-1-short",
      "type": "registry:example",
      "title": "About 1: company story: Just the story",
      "description": "Just the story example of About 1: company story.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/about-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/about-1-short.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/about-1-short.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "about-1",
        "tier": "free"
      }
    },
    {
      "name": "access-1",
      "type": "registry:block",
      "title": "Access 1: access review",
      "description": "A periodic access review: each person's role and last use, Keep, Reduce or Remove with lower roles only, people idle for months flagged in words, a keep-everyone-active shortcut, progress, and a confirmation before anyone loses access.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/alert-dialog.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/return-focus.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/access-1/access-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/access-1/access-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "access"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "access review",
          "permissions",
          "roles",
          "security",
          "compliance",
          "admin",
          "least privilege"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "A quarterly access review. <Access1 people={[{ id, name, email, role, lastUsed: '3 days ago', idleDays: 3 }]} roles={['Owner','Admin','Member','Viewer']} flagAfterDays={90} due='Due 31 Oct' onSubmit={(decisions) => Promise} />. Each person gets Keep, Reduce (to a lower role) or Remove; undecided people stay as they are. Submit is off until everyone has a decision and asks first when anyone will be removed.",
          "whenToUse": [
            "A workspace admin's quarterly check of who has access",
            "A compliance task that needs a record of every keep, reduce and remove"
          ],
          "whenNotToUse": [
            "Inviting or changing one person's role; use settings or team blocks",
            "A log of past changes; use audit-1"
          ],
          "composesWith": [
            "audit-1",
            "settings-1",
            "invite-1",
            "app-shell-1"
          ],
          "a11y": [
            {
              "keys": "Decisions",
              "action": "Each person's Keep, Reduce and Remove are a native radio group in a fieldset named for them; the arrow keys move between them"
            },
            {
              "keys": "Progress",
              "action": "A meter reading '3 of 7 reviewed'; what is left is also written under the list"
            },
            {
              "keys": "Flagged people",
              "action": "Marked 'not used lately' in words with an icon, not colour alone"
            },
            {
              "keys": "Removing",
              "action": "An alert dialog names exactly who loses access and returns focus when closed"
            }
          ],
          "customization": [
            "roles and flagAfterDays",
            "due text",
            "onSubmit receives { [id]: { action, to? } }; reject it and the message says nothing was saved"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "access-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton cards under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "Nobody to review",
            "example": "access-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says nobody is to review; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "access-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying no decisions were lost, with Try again (onRetry)."
          }
        ],
        "examples": [
          "access-1-demo",
          "access-1-flagged",
          "access-1-loading",
          "access-1-empty",
          "access-1-error"
        ],
        "url": "https://ui.ballmac.com/components/access-1"
      }
    },
    {
      "name": "access-1-demo",
      "type": "registry:example",
      "title": "Access 1: access review: Default",
      "description": "Default example of Access 1: access review.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/access-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/access-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/access-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "access-1",
        "tier": "free"
      }
    },
    {
      "name": "access-1-flagged",
      "type": "registry:example",
      "title": "Access 1: access review: Reviewing the flagged first",
      "description": "Reviewing the flagged first example of Access 1: access review.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/access-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/access-1-flagged.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/access-1-flagged.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "access-1",
        "tier": "free"
      }
    },
    {
      "name": "access-1-loading",
      "type": "registry:example",
      "title": "Access 1: access review: Loading",
      "description": "Loading example of Access 1: access review.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/access-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/access-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/access-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "access-1",
        "tier": "free"
      }
    },
    {
      "name": "access-1-empty",
      "type": "registry:example",
      "title": "Access 1: access review: Nobody to review",
      "description": "Nobody to review example of Access 1: access review.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/access-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/access-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/access-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "access-1",
        "tier": "free"
      }
    },
    {
      "name": "access-1-error",
      "type": "registry:example",
      "title": "Access 1: access review: Could not load",
      "description": "Could not load example of Access 1: access review.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/access-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/access-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/access-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "access-1",
        "tier": "free"
      }
    },
    {
      "name": "alerts-1",
      "type": "registry:block",
      "title": "Alerts 1: alert rules",
      "description": "The alert rules of a monitoring setup: what each watches, severity, where it notifies, and firing, muted or fine in words, firing first, switch off, mute for an hour, four hours or a day, send a test, all undone with the reason if it fails.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/switch.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/alerts-1/alerts-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/alerts-1/alerts-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "alerts"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "alerts",
          "monitoring",
          "rules",
          "pager",
          "on-call",
          "notifications",
          "observability",
          "sre"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "Alert rules. <Alerts1 rules={[{ id, name, condition, severity: 'critical' | 'warning' | 'info', channel, status: 'firing' | 'ok' | 'muted', enabled, since?, until? }]} onToggle={(rule, enabled) => Promise} onMute={(rule, hours) => Promise /* hours 0 means unmute */} onTest={(rule) => Promise} />. Firing rules are listed first. Each action updates the screen at once and is undone if the handler rejects.",
          "whenToUse": [
            "The settings page of a monitoring or alerting tool",
            "An on-call overview of what is firing and what is muted"
          ],
          "whenNotToUse": [
            "Notification preferences for end users; use settings-1",
            "A feed of past alerts; use audit-1 or log-stream"
          ],
          "composesWith": [
            "oncall-1",
            "incident-1",
            "runbook-1",
            "slo-1"
          ],
          "a11y": [
            {
              "keys": "Status",
              "action": "Firing, Muted until… and Switched off are written as words with icons; severity is written too"
            },
            {
              "keys": "Switch",
              "action": "Named '<rule> is on'; a failure is an alert and the switch goes back"
            },
            {
              "keys": "Mute",
              "action": "A labelled select for how long and a button named for the rule"
            },
            {
              "keys": "Condition",
              "action": "Shown as code that stays left to right"
            },
            {
              "keys": "Summary",
              "action": "The count of firing rules is a polite live region"
            }
          ],
          "customization": [
            "rules and channels",
            "onToggle, onMute and onTest",
            "Mute durations are 1 hour, 4 hours and 1 day"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "alerts-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton rows under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No alert rules yet",
            "example": "alerts-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says no alert rules yet; emptyState sets the copy. A filter with no match says so."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "alerts-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed or muted, with Try again (onRetry). A change that fails goes back and says why."
          }
        ],
        "examples": [
          "alerts-1-demo",
          "alerts-1-quiet",
          "alerts-1-loading",
          "alerts-1-empty",
          "alerts-1-error"
        ],
        "url": "https://ui.ballmac.com/components/alerts-1"
      }
    },
    {
      "name": "alerts-1-demo",
      "type": "registry:example",
      "title": "Alerts 1: alert rules: Default",
      "description": "Default example of Alerts 1: alert rules.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alerts-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/alerts-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alerts-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "alerts-1",
        "tier": "free"
      }
    },
    {
      "name": "alerts-1-quiet",
      "type": "registry:example",
      "title": "Alerts 1: alert rules: Nothing firing",
      "description": "Nothing firing example of Alerts 1: alert rules.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alerts-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/alerts-1-quiet.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alerts-1-quiet.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "alerts-1",
        "tier": "free"
      }
    },
    {
      "name": "alerts-1-loading",
      "type": "registry:example",
      "title": "Alerts 1: alert rules: Loading",
      "description": "Loading example of Alerts 1: alert rules.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alerts-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/alerts-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alerts-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "alerts-1",
        "tier": "free"
      }
    },
    {
      "name": "alerts-1-empty",
      "type": "registry:example",
      "title": "Alerts 1: alert rules: No alert rules yet",
      "description": "No alert rules yet example of Alerts 1: alert rules.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alerts-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/alerts-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alerts-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "alerts-1",
        "tier": "free"
      }
    },
    {
      "name": "alerts-1-error",
      "type": "registry:example",
      "title": "Alerts 1: alert rules: Could not load",
      "description": "Could not load example of Alerts 1: alert rules.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/alerts-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/alerts-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/alerts-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "alerts-1",
        "tier": "free"
      }
    },
    {
      "name": "analytics-1",
      "type": "registry:block",
      "title": "Analytics 1: product analytics",
      "description": "A product analytics page that reads like a report: four metrics with their change and trend, the visit-to-purchase funnel with the biggest drop flagged, a tabbed ranking of pages, sources and countries, and a device split.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/sparkline.json",
        "https://ui.ballmac.com/r/bar-list.json",
        "https://ui.ballmac.com/r/funnel-chart.json",
        "https://ui.ballmac.com/r/split-bar.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/analytics-1/analytics-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/analytics-1/analytics-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "dashboard"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "dashboard",
          "analytics",
          "funnel",
          "metrics",
          "traffic",
          "growth",
          "charts",
          "report"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "Product analytics. <Analytics1 title description periods={[{ id, label, metrics, funnel, lists, devices }]} defaultPeriod onPeriodChange={(id) => void} />. Each period carries four metrics ({ label, value, change, series }), funnel steps, ranked lists for the tabs and device segments. Switching the period swaps every part. The period is a radio group; the ranking is a tablist with arrow keys.",
          "whenToUse": [
            "The overview page of an analytics or growth tool",
            "A report a founder reads every morning"
          ],
          "whenNotToUse": [
            "Operational health; use reliability-1",
            "Revenue and billing detail; use cost-1 or dashboard-1"
          ],
          "composesWith": [
            "reliability-1",
            "reviews-2",
            "app-shell-1",
            "dashboard-2"
          ],
          "a11y": [
            {
              "keys": "Period",
              "action": "A labelled radio group; arrow keys change it and the whole page follows"
            },
            {
              "keys": "Metrics",
              "action": "A description list; changes are written as 'Up 8.2%', never only an arrow or a color"
            },
            {
              "keys": "Ranking",
              "action": "A tablist with a tabpanel; Left and Right move between tabs"
            },
            {
              "keys": "Funnel",
              "action": "Drop-off and conversion are text; steps are toggle buttons"
            }
          ],
          "customization": [
            "title and description",
            "periods and defaultPeriod",
            "onPeriodChange"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "analytics-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton metrics and charts under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No data for this period",
            "example": "analytics-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says there is no data for the period; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "analytics-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed, with Try again (onRetry)."
          }
        ],
        "examples": [
          "analytics-1-demo",
          "analytics-1-week",
          "analytics-1-loading",
          "analytics-1-empty",
          "analytics-1-error"
        ],
        "url": "https://ui.ballmac.com/components/analytics-1"
      }
    },
    {
      "name": "analytics-1-demo",
      "type": "registry:example",
      "title": "Analytics 1: product analytics: Default",
      "description": "Default example of Analytics 1: product analytics.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/analytics-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/analytics-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/analytics-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "analytics-1",
        "tier": "free"
      }
    },
    {
      "name": "analytics-1-week",
      "type": "registry:example",
      "title": "Analytics 1: product analytics: Last 7 days",
      "description": "Last 7 days example of Analytics 1: product analytics.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/analytics-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/analytics-1-week.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/analytics-1-week.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "analytics-1",
        "tier": "free"
      }
    },
    {
      "name": "analytics-1-loading",
      "type": "registry:example",
      "title": "Analytics 1: product analytics: Loading",
      "description": "Loading example of Analytics 1: product analytics.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/analytics-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/analytics-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/analytics-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "analytics-1",
        "tier": "free"
      }
    },
    {
      "name": "analytics-1-empty",
      "type": "registry:example",
      "title": "Analytics 1: product analytics: No data for this period",
      "description": "No data for this period example of Analytics 1: product analytics.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/analytics-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/analytics-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/analytics-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "analytics-1",
        "tier": "free"
      }
    },
    {
      "name": "analytics-1-error",
      "type": "registry:example",
      "title": "Analytics 1: product analytics: Could not load",
      "description": "Could not load example of Analytics 1: product analytics.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/analytics-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/analytics-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/analytics-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "analytics-1",
        "tier": "free"
      }
    },
    {
      "name": "api-1",
      "type": "registry:block",
      "title": "API 1: request explorer",
      "description": "An API explorer: a method, an address, headers and a JSON body, then the answer with its status in words, time and size and the body as a tree; a broken body is caught before sending, with history and Copy as cURL.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/copy-button.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/json-viewer.json",
        "https://ui.ballmac.com/r/select.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/textarea.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/api-1/api-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/api-1/api-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "api"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "api",
          "request",
          "http",
          "rest",
          "postman",
          "playground",
          "curl",
          "developer",
          "docs",
          "explorer",
          "json"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "An API explorer. <Api1 title defaultRequest={{ method: 'POST', url, headers: [{ id, key, value }], body }} defaultResponse onSend={(request) => Promise<{ status, statusText, ms, headers, body }>} />. Send is disabled while the address is not a full https URL or a body is not valid JSON, and says why. Every send is added to a history of six. Copy as cURL builds the command from the current request. Without onSend a built-in demo API for /v1/users answers (401 without an Authorization header, 200, 201, 404, 422).",
          "whenToUse": [
            "API documentation with a try-it panel",
            "A developer dashboard where customers test their keys"
          ],
          "whenNotToUse": [
            "Showing one endpoint's reference (use api-endpoint)",
            "Watching live traffic (use log-stream)"
          ],
          "composesWith": [
            "dev-1",
            "webhooks-1",
            "app-shell-1"
          ],
          "a11y": [
            {
              "keys": "Tab, Enter",
              "action": "Method menu, address, then Send; pressing Enter in the address sends. Header rows are labelled by position and each has a Remove button"
            },
            {
              "keys": "Validation",
              "action": "A bad address or broken JSON is an alert that says what is wrong and why Send is off"
            },
            {
              "keys": "Response",
              "action": "The panel is a polite live region that reads the status in words, such as '404 Not Found', with time and size"
            }
          ],
          "customization": [
            "Addresses, headers and bodies are shown left to right in right-to-left layouts, like code",
            "History restores a past request into the form",
            "Methods without a body (GET, DELETE) hide the body field and say so"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "api-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton request bar and panel under the real heading, announced as loading. While a request is in flight the response panel shows a skeleton and the page is marked busy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "api-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert with Try again (onRetry). A request that gets no answer shows 'No response' with the reason in the response panel."
          }
        ],
        "examples": [
          "api-1-demo",
          "api-1-created",
          "api-1-notfound",
          "api-1-loading",
          "api-1-error"
        ],
        "url": "https://ui.ballmac.com/components/api-1"
      }
    },
    {
      "name": "api-1-demo",
      "type": "registry:example",
      "title": "API 1: request explorer: Ready to send",
      "description": "Ready to send example of API 1: request explorer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "api-1",
        "tier": "free"
      }
    },
    {
      "name": "api-1-created",
      "type": "registry:example",
      "title": "API 1: request explorer: A POST answered 201",
      "description": "A POST answered 201 example of API 1: request explorer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-1-created.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-1-created.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "api-1",
        "tier": "free"
      }
    },
    {
      "name": "api-1-notfound",
      "type": "registry:example",
      "title": "API 1: request explorer: An error answer",
      "description": "An error answer example of API 1: request explorer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-1-notfound.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-1-notfound.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "api-1",
        "tier": "free"
      }
    },
    {
      "name": "api-1-loading",
      "type": "registry:example",
      "title": "API 1: request explorer: Loading",
      "description": "Loading example of API 1: request explorer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "api-1",
        "tier": "free"
      }
    },
    {
      "name": "api-1-error",
      "type": "registry:example",
      "title": "API 1: request explorer: Could not load",
      "description": "Could not load example of API 1: request explorer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/api-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/api-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/api-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "api-1",
        "tier": "free"
      }
    },
    {
      "name": "app-shell-1",
      "type": "registry:block",
      "title": "App Shell 1: collapsible sidebar with command menu",
      "description": "A product frame: workspace switcher, grouped navigation with badges that collapses to an icon rail, top bar with search, notifications and a ⌘K command menu, and a scrolling page slot. A drawer on phones.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/command.json",
        "https://ui.ballmac.com/r/dropdown-menu.json",
        "https://ui.ballmac.com/r/kbd.json",
        "https://ui.ballmac.com/r/sheet.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/app-shell-1/app-shell-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/app-shell-1/app-shell-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "app-shell"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "app shell",
          "sidebar",
          "dashboard layout",
          "navigation",
          "command menu",
          "workspace"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "ai": {
          "summary": "The frame around an app. Pass nav=[{ label?, items: [{ id, label, icon?, badge? }] }], workspace, user and a children render function (page) => node; value / onValueChange control the open page.",
          "whenToUse": [
            "Dashboards, admin tools and any multi-page product",
            "A realistic frame for demos and screenshots"
          ],
          "whenNotToUse": [
            "Marketing sites (use header-2)",
            "Single-screen tools"
          ],
          "composesWith": [
            "dashboard-1",
            "dashboard-2",
            "settings-1",
            "billing-1",
            "mail-1",
            "kanban-1"
          ],
          "a11y": [
            {
              "keys": "Ctrl/⌘ + K",
              "action": "Opens the command menu to jump to any page"
            },
            {
              "keys": "Ctrl/⌘ + B",
              "action": "Collapses or expands the sidebar"
            },
            {
              "keys": "Tab",
              "action": "A skip link jumps past the sidebar; the open page is marked aria-current=page"
            }
          ],
          "customization": [
            "nav groups, workspace, workspaces, user",
            "children: (page) => node",
            "defaultCollapsed, height ('100svh' for a full-screen app)"
          ]
        },
        "statesNone": "A layout around your own pages; each page inside shows its own states.",
        "examples": [
          "app-shell-1-demo",
          "app-shell-1-collapsed"
        ],
        "url": "https://ui.ballmac.com/components/app-shell-1"
      }
    },
    {
      "name": "app-shell-1-demo",
      "type": "registry:example",
      "title": "App Shell 1: collapsible sidebar with command menu: Default",
      "description": "Default example of App Shell 1: collapsible sidebar with command menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-shell-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/app-shell-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-shell-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "app-shell-1",
        "tier": "free"
      }
    },
    {
      "name": "app-shell-1-collapsed",
      "type": "registry:example",
      "title": "App Shell 1: collapsible sidebar with command menu: Collapsed, custom pages",
      "description": "Collapsed, custom pages example of App Shell 1: collapsible sidebar with command menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/app-shell-1.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/app-shell-1-collapsed.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/app-shell-1-collapsed.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "app-shell-1",
        "tier": "free"
      }
    },
    {
      "name": "audit-1",
      "type": "registry:block",
      "title": "Audit 1: audit log",
      "description": "An audit log you can search: who did what to what, when and from where, filters with counts, failed attempts written out, rows that open to show exactly which values changed, show-more paging and an export of what the filter shows.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/match-highlight.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/audit-1/audit-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/audit-1/audit-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "audit"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "audit log",
          "security",
          "compliance",
          "activity",
          "admin",
          "export",
          "history"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "An audit log. <Audit1 events={[{ id, time, actor: { name, email? }, action, category: 'signin' | 'permissions' | 'data' | 'billing', target, ip?, place?, result?: 'failed', changes?: [{ field, from, to }] }]} onExport={(events) => Promise} />. Search and the kind filter narrow the list and the count; Export sends what is currently shown. Rows with changes open to show from and to.",
          "whenToUse": [
            "An admin area where owners review security and data activity",
            "A compliance screen that needs an exportable trail"
          ],
          "whenNotToUse": [
            "A user's own activity feed; use activity-feed",
            "The live output of a process; use log-stream",
            "Agent guardrail checks; use guardrail-feed"
          ],
          "composesWith": [
            "access-1",
            "settings-1",
            "webhooks-1",
            "app-shell-1"
          ],
          "a11y": [
            {
              "keys": "Table",
              "action": "A real table with a caption and column headings; times and addresses stay left to right in right-to-left layouts"
            },
            {
              "keys": "Enter / Space on an action",
              "action": "Opens the details of what changed (aria-expanded); rows with nothing to show are not buttons"
            },
            {
              "keys": "Failed attempts",
              "action": "Written as the word Failed with an icon, never colour alone"
            },
            {
              "keys": "Filters",
              "action": "Toggle buttons with counts; the event count and the export result are polite announcements"
            }
          ],
          "customization": [
            "Page size and the event you open at first",
            "onExport receives the filtered events; reject it and the message says the export failed",
            "Search matches person, action, target and address"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "audit-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton rows under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No activity yet",
            "example": "audit-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says what will appear and when; emptyState sets the copy. A search or filter with no match says so with Clear filters."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "audit-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed, with Try again (onRetry)."
          }
        ],
        "examples": [
          "audit-1-demo",
          "audit-1-failed",
          "audit-1-loading",
          "audit-1-empty",
          "audit-1-error"
        ],
        "url": "https://ui.ballmac.com/components/audit-1"
      }
    },
    {
      "name": "audit-1-demo",
      "type": "registry:example",
      "title": "Audit 1: audit log: Default",
      "description": "Default example of Audit 1: audit log.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/audit-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/audit-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/audit-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "audit-1",
        "tier": "free"
      }
    },
    {
      "name": "audit-1-failed",
      "type": "registry:example",
      "title": "Audit 1: audit log: Search with no match",
      "description": "Search with no match example of Audit 1: audit log.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/audit-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/audit-1-failed.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/audit-1-failed.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "audit-1",
        "tier": "free"
      }
    },
    {
      "name": "audit-1-loading",
      "type": "registry:example",
      "title": "Audit 1: audit log: Loading",
      "description": "Loading example of Audit 1: audit log.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/audit-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/audit-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/audit-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "audit-1",
        "tier": "free"
      }
    },
    {
      "name": "audit-1-empty",
      "type": "registry:example",
      "title": "Audit 1: audit log: No activity yet",
      "description": "No activity yet example of Audit 1: audit log.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/audit-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/audit-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/audit-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "audit-1",
        "tier": "free"
      }
    },
    {
      "name": "audit-1-error",
      "type": "registry:example",
      "title": "Audit 1: audit log: Could not load",
      "description": "Could not load example of Audit 1: audit log.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/audit-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/audit-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/audit-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "audit-1",
        "tier": "free"
      }
    },
    {
      "name": "billing-2",
      "type": "registry:block",
      "title": "Billing 2: change plan with proration",
      "description": "A change-plan flow: billing interval, plan cards as radios, a seat stepper that respects the current team, and a sticky summary that works out the prorated charge, the credit and what is due today.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/badge.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/billing-2/billing-2.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/billing-2/billing-2.tsx"
        }
      ],
      "categories": [
        "blocks",
        "billing"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "billing",
          "upgrade",
          "downgrade",
          "proration",
          "seats",
          "plans",
          "checkout"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton with the same shapes as the ready view, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Upgrade and downgrade flow. Pass plans=[{ id, name, monthly, yearly, description, features }], currentPlan, currentSeats, today and renewsOn (ISO dates, so server and browser agree) and onConfirm({ plan, seats, interval }) (throw to show an error).",
          "whenToUse": [
            "In-app plan changes",
            "Seat-based products with prorated billing"
          ],
          "whenNotToUse": [
            "Public pricing pages (use pricing-2 or pricing-3)"
          ],
          "composesWith": [
            "billing-1",
            "app-shell-1",
            "settings-3"
          ],
          "a11y": [
            {
              "keys": "Arrow keys on plans",
              "action": "Move between plan radios; the chosen plan is marked and named 'Current' when it is the active one"
            },
            {
              "keys": "Seat buttons",
              "action": "Named 'Add a seat' and 'Remove a seat'; the count is announced politely and can't go below the team size"
            },
            {
              "keys": "Summary",
              "action": "A labelled complementary region; every line is plain text"
            }
          ],
          "customization": [
            "plans, currentPlan, currentSeats, currentInterval, minSeats",
            "today and renewsOn drive the proration",
            "onConfirm(change) async",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "billing-2-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No plans",
            "example": "billing-2-no-plans",
            "trigger": "state=\"empty\"",
            "note": "A clear message that there is nothing yet. emptyState sets the copy and can add an action."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "billing-2-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "billing-2-demo",
          "billing-2-yearly",
          "billing-2-loading",
          "billing-2-error",
          "billing-2-no-plans"
        ],
        "url": "https://ui.ballmac.com/components/billing-2"
      }
    },
    {
      "name": "billing-2-demo",
      "type": "registry:example",
      "title": "Billing 2: change plan with proration: Default",
      "description": "Default example of Billing 2: change plan with proration.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/billing-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/billing-2-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/billing-2-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "billing-2",
        "tier": "free"
      }
    },
    {
      "name": "billing-2-yearly",
      "type": "registry:example",
      "title": "Billing 2: change plan with proration: Yearly account",
      "description": "Yearly account example of Billing 2: change plan with proration.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/billing-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/billing-2-yearly.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/billing-2-yearly.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "billing-2",
        "tier": "free"
      }
    },
    {
      "name": "billing-2-loading",
      "type": "registry:example",
      "title": "Billing 2: change plan with proration: Loading",
      "description": "Loading example of Billing 2: change plan with proration.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/billing-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/billing-2-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/billing-2-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "billing-2",
        "tier": "free"
      }
    },
    {
      "name": "billing-2-error",
      "type": "registry:example",
      "title": "Billing 2: change plan with proration: Could not load",
      "description": "Could not load example of Billing 2: change plan with proration.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/billing-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/billing-2-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/billing-2-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "billing-2",
        "tier": "free"
      }
    },
    {
      "name": "billing-2-no-plans",
      "type": "registry:example",
      "title": "Billing 2: change plan with proration: No plans",
      "description": "No plans example of Billing 2: change plan with proration.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/billing-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/billing-2-no-plans.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/billing-2-no-plans.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "billing-2",
        "tier": "free"
      }
    },
    {
      "name": "blog-1",
      "type": "registry:block",
      "title": "Blog 1: featured post with filterable grid",
      "description": "A blog index with a large featured post, topic filter chips and a three-column grid. Posts without a photo get a generated cover drawn from theme tokens, in five compositions.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/blog-1/blog-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/blog-1/blog-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "blog"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "blog",
          "posts",
          "articles",
          "index",
          "filter",
          "cards"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton with the same shapes as the ready view, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "The index page of a blog. Pass posts=[{ title, excerpt, category, date, readMinutes, author, role?, href, image?, cover? }]; the first post is featured. Also exports BlogCover for your own cards.",
          "whenToUse": [
            "Company and product blogs",
            "Resource and news pages"
          ],
          "whenNotToUse": [
            "A single article (use blog-post-1)",
            "Hundreds of posts that need pagination and search"
          ],
          "composesWith": [
            "blog-post-1",
            "newsletter-1",
            "header-2",
            "footer-2"
          ],
          "a11y": [
            {
              "keys": "Enter / Space on a topic chip",
              "action": "Filters the list (aria-pressed); the count is announced politely"
            },
            {
              "keys": "Tab",
              "action": "Each card has one link; the whole card is clickable"
            }
          ],
          "customization": [
            "posts: image for a photo, or cover (0 to 4) to choose a generated cover",
            "filterable: false hides the chips",
            "locale for dates (UTC, fixed by default)",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "blog-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No posts",
            "example": "blog-1-no-posts",
            "trigger": "state=\"empty\"",
            "note": "A clear message that there is nothing yet. emptyState sets the copy and can add an action."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "blog-1-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "blog-1-demo",
          "blog-1-compact",
          "blog-1-loading",
          "blog-1-error",
          "blog-1-no-posts"
        ],
        "url": "https://ui.ballmac.com/components/blog-1"
      }
    },
    {
      "name": "blog-1-demo",
      "type": "registry:example",
      "title": "Blog 1: featured post with filterable grid: Default",
      "description": "Default example of Blog 1: featured post with filterable grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/blog-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blog-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "blog-1",
        "tier": "free"
      }
    },
    {
      "name": "blog-1-compact",
      "type": "registry:example",
      "title": "Blog 1: featured post with filterable grid: Three posts",
      "description": "Three posts example of Blog 1: featured post with filterable grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/blog-1-compact.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blog-1-compact.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "blog-1",
        "tier": "free"
      }
    },
    {
      "name": "blog-1-loading",
      "type": "registry:example",
      "title": "Blog 1: featured post with filterable grid: Loading",
      "description": "Loading example of Blog 1: featured post with filterable grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/blog-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blog-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "blog-1",
        "tier": "free"
      }
    },
    {
      "name": "blog-1-error",
      "type": "registry:example",
      "title": "Blog 1: featured post with filterable grid: Could not load",
      "description": "Could not load example of Blog 1: featured post with filterable grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/blog-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blog-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "blog-1",
        "tier": "free"
      }
    },
    {
      "name": "blog-1-no-posts",
      "type": "registry:example",
      "title": "Blog 1: featured post with filterable grid: No posts",
      "description": "No posts example of Blog 1: featured post with filterable grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/blog-1-no-posts.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blog-1-no-posts.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "blog-1",
        "tier": "free"
      }
    },
    {
      "name": "booking-1",
      "type": "registry:block",
      "title": "Booking 1: class timetable",
      "description": "A weekly class timetable people book from: classes grouped by day, places left written out, one button that does the right thing (book, join the waiting list, cancel, leave), a kind filter, and changes undone with the reason if they fail.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/booking-1/booking-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/booking-1/booking-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "booking"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "booking",
          "classes",
          "timetable",
          "fitness",
          "studio",
          "waitlist",
          "schedule",
          "wellness"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "A class timetable. <Booking1 classes={[{ id, title, kind, instructor, day: 'Mon 27 Oct', time: '07:00', length: '45 min', capacity, taken, booked?, waitlisted? }]} onChange={(class, 'book' | 'waitlist' | 'cancel' | 'leave') => Promise} />. Places left = capacity minus taken (minus you if booked); 3 or fewer says 'Only 2 places left', zero says 'Full' and offers the waiting list. Changes show at once and are undone if onChange rejects.",
          "whenToUse": [
            "A studio, gym or workshop timetable with limited places",
            "Any scheduled session where people can book, queue or cancel"
          ],
          "whenNotToUse": [
            "A day schedule for staff and patients; use clinic-1",
            "A calendar of events with tickets; use event-1"
          ],
          "composesWith": [
            "clinic-1",
            "calendar-1",
            "event-1",
            "profile-1"
          ],
          "a11y": [
            {
              "keys": "Days",
              "action": "Each day is a labelled region with a heading; classes are list items in time order"
            },
            {
              "keys": "Places left",
              "action": "Written as words ('Only 1 place left', 'Full'), never colour alone"
            },
            {
              "keys": "Buttons",
              "action": "Named for the class, day and time ('Book Spin 45, Wed 29 Oct at 06:45'); the result is a polite announcement and a failure is an alert"
            },
            {
              "keys": "Filter",
              "action": "Toggle buttons with aria-pressed"
            }
          ],
          "customization": [
            "classes and the filter kinds come from the data",
            "onChange handles all four actions",
            "The week summary updates as you book"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "booking-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton day headings and cards under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No classes this week",
            "example": "booking-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says no classes this week; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "booking-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was booked or cancelled, with Try again (onRetry). A booking that fails is undone and says why."
          }
        ],
        "examples": [
          "booking-1-demo",
          "booking-1-loading",
          "booking-1-empty",
          "booking-1-error"
        ],
        "url": "https://ui.ballmac.com/components/booking-1"
      }
    },
    {
      "name": "booking-1-demo",
      "type": "registry:example",
      "title": "Booking 1: class timetable: Default",
      "description": "Default example of Booking 1: class timetable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/booking-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/booking-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/booking-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "booking-1",
        "tier": "free"
      }
    },
    {
      "name": "booking-1-loading",
      "type": "registry:example",
      "title": "Booking 1: class timetable: Loading",
      "description": "Loading example of Booking 1: class timetable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/booking-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/booking-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/booking-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "booking-1",
        "tier": "free"
      }
    },
    {
      "name": "booking-1-empty",
      "type": "registry:example",
      "title": "Booking 1: class timetable: No classes this week",
      "description": "No classes this week example of Booking 1: class timetable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/booking-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/booking-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/booking-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "booking-1",
        "tier": "free"
      }
    },
    {
      "name": "booking-1-error",
      "type": "registry:example",
      "title": "Booking 1: class timetable: Could not load",
      "description": "Could not load example of Booking 1: class timetable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/booking-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/booking-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/booking-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "booking-1",
        "tier": "free"
      }
    },
    {
      "name": "calendar-1",
      "type": "registry:block",
      "title": "Calendar 1: week view with mini month",
      "description": "A week calendar: a time grid with overlapping events placed side by side, an all-day row, a now line, a mini month and calendar toggles, event popovers and a new-event dialog. One day at a time on phones.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/calendar.json",
        "https://ui.ballmac.com/r/dialog.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/popover.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/calendar-1/calendar-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/calendar-1/calendar-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "calendar"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "calendar",
          "schedule",
          "week view",
          "events",
          "planner",
          "agenda"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton with the same shapes as the ready view, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "The mini calendar uses the block's own today, so the block prerenders with Cache Components (the Next.js 16.4 default). The highlighted day is unchanged.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A scheduling view. Pass defaultEvents=[{ id, title, start, end, calendar, location?, allDay? }] with local 'YYYY-MM-DDTHH:mm' times, calendars, today (YYYY-MM-DD) and now (HH:mm) so the page is identical on the server and in the browser.",
          "whenToUse": [
            "Scheduling, booking and planning screens",
            "A realistic product screenshot"
          ],
          "whenNotToUse": [
            "Picking a date in a form (use calendar or date-picker)",
            "An agenda list (use calendar-agenda)"
          ],
          "composesWith": [
            "app-shell-1",
            "kanban-1",
            "mail-1"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Events are buttons in time order; Enter opens a popover with the details"
            },
            {
              "keys": "Mini month arrow keys",
              "action": "Move between days; PageUp and PageDown change month"
            },
            {
              "keys": "Calendar checkboxes",
              "action": "Show or hide a calendar; each event's name, time and place are in its accessible name"
            }
          ],
          "customization": [
            "defaultEvents, calendars, today, now (null hides the line)",
            "startHour and endHour",
            "onAdd(event), height",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "calendar-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No events",
            "example": "calendar-1-no-events",
            "trigger": "state=\"empty\"",
            "note": "The real week with no events, so adding one still works."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "calendar-1-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "calendar-1-demo",
          "calendar-1-compact",
          "calendar-1-loading",
          "calendar-1-error",
          "calendar-1-no-events"
        ],
        "url": "https://ui.ballmac.com/components/calendar-1"
      }
    },
    {
      "name": "calendar-1-demo",
      "type": "registry:example",
      "title": "Calendar 1: week view with mini month: Default",
      "description": "Default example of Calendar 1: week view with mini month.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "calendar-1",
        "tier": "free"
      }
    },
    {
      "name": "calendar-1-compact",
      "type": "registry:example",
      "title": "Calendar 1: week view with mini month: Work hours, your calendars",
      "description": "Work hours, your calendars example of Calendar 1: week view with mini month.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-1-compact.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-1-compact.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "calendar-1",
        "tier": "free"
      }
    },
    {
      "name": "calendar-1-loading",
      "type": "registry:example",
      "title": "Calendar 1: week view with mini month: Loading",
      "description": "Loading example of Calendar 1: week view with mini month.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "calendar-1",
        "tier": "free"
      }
    },
    {
      "name": "calendar-1-error",
      "type": "registry:example",
      "title": "Calendar 1: week view with mini month: Could not load",
      "description": "Could not load example of Calendar 1: week view with mini month.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "calendar-1",
        "tier": "free"
      }
    },
    {
      "name": "calendar-1-no-events",
      "type": "registry:example",
      "title": "Calendar 1: week view with mini month: No events",
      "description": "No events example of Calendar 1: week view with mini month.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-1-no-events.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-1-no-events.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "calendar-1",
        "tier": "free"
      }
    },
    {
      "name": "careers-1",
      "type": "registry:block",
      "title": "Careers 1: open roles with filters and perks",
      "description": "Open roles grouped by team with team filter chips, live search and an empty state, then a hairline grid of perks. Every role row is one large link with location and type.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/search-field.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/careers-1/careers-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/careers-1/careers-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "careers"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "careers",
          "jobs",
          "hiring",
          "roles",
          "filter",
          "perks"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A jobs section. Pass jobs=[{ title, team, location, type?, href }] and optionally perks=[{ icon?, title, description }]; teams and filters are derived from the jobs.",
          "whenToUse": [
            "Company careers pages",
            "Open source projects looking for maintainers"
          ],
          "whenNotToUse": [
            "A full applicant tracking system"
          ],
          "composesWith": [
            "team-1",
            "contact-1",
            "header-2",
            "footer-2"
          ],
          "a11y": [
            {
              "keys": "Enter / Space on a team chip",
              "action": "Filters the roles (aria-pressed); the count is announced politely"
            },
            {
              "keys": "Tab",
              "action": "Each role is a single link with its location and type in the name"
            }
          ],
          "customization": [
            "jobs / perks arrays",
            "perks: [] hides the grid",
            "openApplication: null hides the link"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "careers-1-demo",
          "careers-1-small"
        ],
        "url": "https://ui.ballmac.com/components/careers-1"
      }
    },
    {
      "name": "careers-1-demo",
      "type": "registry:example",
      "title": "Careers 1: open roles with filters and perks: Default",
      "description": "Default example of Careers 1: open roles with filters and perks.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/careers-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/careers-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/careers-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "careers-1",
        "tier": "free"
      }
    },
    {
      "name": "careers-1-small",
      "type": "registry:example",
      "title": "Careers 1: open roles with filters and perks: A few roles",
      "description": "A few roles example of Careers 1: open roles with filters and perks.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/careers-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/careers-1-small.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/careers-1-small.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "careers-1",
        "tier": "free"
      }
    },
    {
      "name": "changelog-1",
      "type": "registry:block",
      "title": "Changelog 1: release notes timeline",
      "description": "A release-notes page: a sticky version and date beside each release card, optional banner art for headline releases, typed changes with filters and counts, and a show-older button.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/blog-1.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/changelog-1/changelog-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/changelog-1/changelog-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "changelog"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "changelog",
          "release notes",
          "updates",
          "versions",
          "timeline",
          "filter"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton with the same shapes as the ready view, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A public changelog page. Pass releases=[{ version, date, title, summary?, changes: { type: 'new' | 'improved' | 'fixed', text }[], cover? }] newest first.",
          "whenToUse": [
            "Product release notes",
            "Open-source project updates"
          ],
          "whenNotToUse": [
            "A compact in-app feed (use changelog-feed)"
          ],
          "composesWith": [
            "newsletter-1",
            "header-2",
            "footer-2",
            "hero-6"
          ],
          "a11y": [
            {
              "keys": "Enter / Space on a filter",
              "action": "Filters the changes (aria-pressed); the release count is announced politely"
            },
            {
              "keys": "Tab",
              "action": "Each change type is also spelled out in text, not only colour"
            }
          ],
          "customization": [
            "releases: cover (0 to 4) adds banner art to a headline release",
            "initialCount: releases shown before the button",
            "feed: null hides the RSS button",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "changelog-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No releases",
            "example": "changelog-1-no-releases",
            "trigger": "state=\"empty\"",
            "note": "A clear message that there is nothing yet. emptyState sets the copy and can add an action."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "changelog-1-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "changelog-1-demo",
          "changelog-1-minimal",
          "changelog-1-loading",
          "changelog-1-error",
          "changelog-1-no-releases"
        ],
        "url": "https://ui.ballmac.com/components/changelog-1"
      }
    },
    {
      "name": "changelog-1-demo",
      "type": "registry:example",
      "title": "Changelog 1: release notes timeline: Default",
      "description": "Default example of Changelog 1: release notes timeline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/changelog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/changelog-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/changelog-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "changelog-1",
        "tier": "free"
      }
    },
    {
      "name": "changelog-1-minimal",
      "type": "registry:example",
      "title": "Changelog 1: release notes timeline: Minimal",
      "description": "Minimal example of Changelog 1: release notes timeline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/changelog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/changelog-1-minimal.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/changelog-1-minimal.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "changelog-1",
        "tier": "free"
      }
    },
    {
      "name": "changelog-1-loading",
      "type": "registry:example",
      "title": "Changelog 1: release notes timeline: Loading",
      "description": "Loading example of Changelog 1: release notes timeline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/changelog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/changelog-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/changelog-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "changelog-1",
        "tier": "free"
      }
    },
    {
      "name": "changelog-1-error",
      "type": "registry:example",
      "title": "Changelog 1: release notes timeline: Could not load",
      "description": "Could not load example of Changelog 1: release notes timeline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/changelog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/changelog-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/changelog-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "changelog-1",
        "tier": "free"
      }
    },
    {
      "name": "changelog-1-no-releases",
      "type": "registry:example",
      "title": "Changelog 1: release notes timeline: No releases",
      "description": "No releases example of Changelog 1: release notes timeline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/changelog-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/changelog-1-no-releases.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/changelog-1-no-releases.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "changelog-1",
        "tier": "free"
      }
    },
    {
      "name": "chat-1",
      "type": "registry:block",
      "title": "Chat 1: team chat with threads",
      "description": "A team chat: channels and direct messages with unread counts and presence, messages grouped by person and day with a New divider, reactions, threads, @mentions that suggest people, and Retry when a message fails to send.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/chat-1/chat-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/chat-1/chat-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "chat"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chat",
          "team chat",
          "messaging",
          "channels",
          "threads",
          "reactions",
          "mentions",
          "slack",
          "realtime",
          "collaboration"
        ],
        "version": "1.0.0",
        "updated": "2026-10-17",
        "tests": true,
        "ai": {
          "summary": "A Slack-style team chat. <Chat1 people={[{ id, name, status }]} meId channels={[{ id, name, kind: 'channel' | 'dm', private, topic, unread, personId }]} messages={{ [channelId]: [{ id, authorId, text, day, time, reactions, replies }] }} firstUnread={{ [channelId]: messageId }} onSend={async ({ channelId, text, threadId }) => …} onReact onChannelChange />. Messages appear straight away while sending; throw from onSend to mark one Not sent with Retry.",
          "whenToUse": [
            "Team or community messaging inside a product",
            "Customer conversations with internal threads"
          ],
          "whenNotToUse": [
            "Talking to an AI assistant (use ai-chat-1 or ai-chat-2)",
            "Email-style threads (use mail-1)"
          ],
          "composesWith": [
            "app-shell-1",
            "settings-2",
            "agent-2"
          ],
          "a11y": [
            {
              "keys": "Enter / Shift+Enter in the composer",
              "action": "Sends / adds a line"
            },
            {
              "keys": "@ then Up / Down and Enter or Tab",
              "action": "Suggests people and inserts the mention (a combobox)"
            },
            {
              "keys": "Tab into a message",
              "action": "Shows Add a reaction and Reply in thread; reactions are toggle buttons with their count"
            },
            {
              "keys": "Messages",
              "action": "A log region named after the channel, with day and New separators"
            }
          ],
          "customization": [
            "Wire onSend to your realtime backend and pass new messages back through messages",
            "Below 768 px the sidebar becomes a channel select and threads open over the conversation"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "chat-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton messages while the channel loads; the sidebar and composer stay usable."
          },
          {
            "id": "empty",
            "title": "New channel",
            "example": "chat-1-empty",
            "trigger": "state=\"empty\" (or a channel with no messages)",
            "note": "\"This is the start of #channel\" with a prompt to say hello; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "chat-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert with Try again (onRetry). A single message that fails to send shows Not sent and Retry instead."
          }
        ],
        "examples": [
          "chat-1-demo",
          "chat-1-thread",
          "chat-1-loading",
          "chat-1-empty",
          "chat-1-error"
        ],
        "url": "https://ui.ballmac.com/components/chat-1"
      }
    },
    {
      "name": "chat-1-demo",
      "type": "registry:example",
      "title": "Chat 1: team chat with threads: Default",
      "description": "Default example of Chat 1: team chat with threads.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chat-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/chat-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chat-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "chat-1",
        "tier": "free"
      }
    },
    {
      "name": "chat-1-thread",
      "type": "registry:example",
      "title": "Chat 1: team chat with threads: Thread open",
      "description": "Thread open example of Chat 1: team chat with threads.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chat-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/chat-1-thread.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chat-1-thread.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "chat-1",
        "tier": "free"
      }
    },
    {
      "name": "chat-1-loading",
      "type": "registry:example",
      "title": "Chat 1: team chat with threads: Loading",
      "description": "Loading example of Chat 1: team chat with threads.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chat-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/chat-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chat-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "chat-1",
        "tier": "free"
      }
    },
    {
      "name": "chat-1-empty",
      "type": "registry:example",
      "title": "Chat 1: team chat with threads: New channel",
      "description": "New channel example of Chat 1: team chat with threads.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chat-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/chat-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chat-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "chat-1",
        "tier": "free"
      }
    },
    {
      "name": "chat-1-error",
      "type": "registry:example",
      "title": "Chat 1: team chat with threads: Could not load",
      "description": "Could not load example of Chat 1: team chat with threads.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chat-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/chat-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chat-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "chat-1",
        "tier": "free"
      }
    },
    {
      "name": "comments-1",
      "type": "registry:block",
      "title": "Comments 1: threaded discussion",
      "description": "A threaded discussion: a composer where @ offers people, replies, emoji reactions that count and toggle, editing and deleting your own, resolving a thread, and a comment that appears at once and stays with Retry if it cannot be saved.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/cover-art.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/textarea.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/comments-1/comments-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/comments-1/comments-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "comments"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "comments",
          "discussion",
          "thread",
          "replies",
          "mentions",
          "reactions",
          "collaboration",
          "feedback",
          "conversation"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "Threaded comments. <Comments1 comments={[{ id, author, body, at: ISO, reactions: { '👍': ['Priya Shah'] }, edited, resolvedBy, replies: [...] }]} people={[{ id, name }]} me='Sam Okafor' now='2026-10-18T10:00:00Z' onPost={({ body, replyTo }) => Promise} onEdit onDelete onReact={(id, emoji, on) => ...} onResolve={(id, resolved) => ...} />. Typing @ opens a people list (arrows, Enter or Tab pick, Escape closes); only @Name that matches a person is highlighted. Times are 'N min ago' from now; pass now yourself, the block never reads the clock. Only comments whose author equals me can be edited or deleted. Reject onPost to show Not posted with Retry.",
          "whenToUse": [
            "Comments on a document, task, design or post",
            "A team discussion with mentions and reactions"
          ],
          "whenNotToUse": [
            "Real-time chat (use chat-1)",
            "A support conversation with private notes (use tickets-1)"
          ],
          "composesWith": [
            "tickets-1",
            "tasks-1",
            "editor-1",
            "app-shell-1"
          ],
          "a11y": [
            {
              "keys": "@, Up / Down, Enter or Tab, Escape",
              "action": "The composer is a combobox; the people list is a listbox with the active option announced, and Escape closes it without losing the text"
            },
            {
              "keys": "Reactions",
              "action": "Each is a toggle button that says its emoji, count and who reacted ('👍 3: Priya Shah, Sam Okafor, Theo Nakamura')"
            },
            {
              "keys": "Actions",
              "action": "Edit and Delete say which comment they act on; posting, replying, deleting and resolving are announced politely"
            }
          ],
          "customization": [
            "Replies nest one level deep, drawn with a rule on the reading edge so it mirrors in right-to-left",
            "A resolved thread collapses to one line with Show, and Reopen brings it back",
            "Your own comments get Edit and Delete; reactions toggle for you"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "comments-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton composer and comments under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No comments yet",
            "example": "comments-1-empty",
            "trigger": "state=\"empty\" (or comments={[]})",
            "note": "Invites the first comment and mentions @; the composer stays usable. emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "comments-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed, with Try again (onRetry). A comment that fails to post stays with Not posted and Retry."
          }
        ],
        "examples": [
          "comments-1-demo",
          "comments-1-failed",
          "comments-1-loading",
          "comments-1-empty",
          "comments-1-error"
        ],
        "url": "https://ui.ballmac.com/components/comments-1"
      }
    },
    {
      "name": "comments-1-demo",
      "type": "registry:example",
      "title": "Comments 1: threaded discussion: A live thread",
      "description": "A live thread example of Comments 1: threaded discussion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comments-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comments-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comments-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comments-1",
        "tier": "free"
      }
    },
    {
      "name": "comments-1-failed",
      "type": "registry:example",
      "title": "Comments 1: threaded discussion: Posting fails",
      "description": "Posting fails example of Comments 1: threaded discussion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comments-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comments-1-failed.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comments-1-failed.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comments-1",
        "tier": "free"
      }
    },
    {
      "name": "comments-1-loading",
      "type": "registry:example",
      "title": "Comments 1: threaded discussion: Loading",
      "description": "Loading example of Comments 1: threaded discussion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comments-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comments-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comments-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comments-1",
        "tier": "free"
      }
    },
    {
      "name": "comments-1-empty",
      "type": "registry:example",
      "title": "Comments 1: threaded discussion: No comments yet",
      "description": "No comments yet example of Comments 1: threaded discussion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comments-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comments-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comments-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comments-1",
        "tier": "free"
      }
    },
    {
      "name": "comments-1-error",
      "type": "registry:example",
      "title": "Comments 1: threaded discussion: Could not load",
      "description": "Could not load example of Comments 1: threaded discussion.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comments-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comments-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comments-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comments-1",
        "tier": "free"
      }
    },
    {
      "name": "comparison-1",
      "type": "registry:block",
      "title": "Comparison 1: us versus the alternatives",
      "description": "A product-versus-alternatives table where your column is lifted into its own card, with yes, partly, no and text values and a row of headline results. Phones switch between alternatives.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/segmented-control.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/comparison-1/comparison-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/comparison-1/comparison-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "comparison"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "comparison",
          "versus",
          "alternatives",
          "table",
          "switch",
          "features"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "ai": {
          "summary": "A switch-from-X page section. Pass product, competitors=[{ key, name }] and rows=[{ label, hint?, values: { us, [key]: true | false | 'partial' | text } }].",
          "whenToUse": [
            "Landing pages aimed at people evaluating alternatives",
            "Migration and 'vs' pages"
          ],
          "whenNotToUse": [
            "Comparing your own plans (use pricing-3)"
          ],
          "composesWith": [
            "pricing-2",
            "testimonials-2",
            "cta-1",
            "faq-2"
          ],
          "a11y": [
            {
              "keys": "Arrow Left / Right (phones)",
              "action": "Switches the alternative shown"
            },
            {
              "keys": "Screen reader",
              "action": "Each cell reads as 'Name, capability: yes / partly / no'"
            }
          ],
          "customization": [
            "values use the key 'us' for your product",
            "reasons: [] hides the headline results"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "comparison-1-demo",
          "comparison-1-single"
        ],
        "url": "https://ui.ballmac.com/components/comparison-1"
      }
    },
    {
      "name": "comparison-1-demo",
      "type": "registry:example",
      "title": "Comparison 1: us versus the alternatives: Default",
      "description": "Default example of Comparison 1: us versus the alternatives.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comparison-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comparison-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comparison-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comparison-1",
        "tier": "free"
      }
    },
    {
      "name": "comparison-1-single",
      "type": "registry:example",
      "title": "Comparison 1: us versus the alternatives: One alternative",
      "description": "One alternative example of Comparison 1: us versus the alternatives.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/comparison-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/comparison-1-single.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/comparison-1-single.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "comparison-1",
        "tier": "free"
      }
    },
    {
      "name": "contact-1",
      "type": "registry:block",
      "title": "Contact 1: form with contact methods",
      "description": "A contact section with a validated form (name, email, topic, message with counter, consent), loading, error and thank-you states, beside tiles for email, chat, phone and office with a response-time pill.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/field.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/select.json",
        "https://ui.ballmac.com/r/status-dot.json",
        "https://ui.ballmac.com/r/textarea.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/contact-1/contact-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/contact-1/contact-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "contact"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "contact",
          "form",
          "support",
          "validation",
          "email",
          "sales"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (submitting, success, error) to drive the form from your own async code, and defaultValues or defaultEmail to prefill. Fields lock while a request is in flight. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Contact page section. Pass methods, topics and onSubmit(values) (throw to show an error). Validation, focus on the first error, loading and the thank-you screen are built in.",
          "whenToUse": [
            "Contact and support pages",
            "Sales enquiry sections"
          ],
          "whenNotToUse": [
            "Newsletter signup (use newsletter-1)",
            "Authenticated in-app feedback (use feedback-widget)"
          ],
          "composesWith": [
            "faq-2",
            "header-2",
            "footer-2",
            "careers-1"
          ],
          "a11y": [
            {
              "keys": "Submit with errors",
              "action": "Focus moves to the first invalid field; each error is announced as an alert and linked with aria-describedby"
            },
            {
              "keys": "Arrow keys / Enter in the topic menu",
              "action": "Choose a topic (Radix Select)"
            }
          ],
          "customization": [
            "methods: { icon?, label, value, href? }[]",
            "topics: [] hides the dropdown",
            "responseTime: null hides the pill",
            "onSubmit(values): async; throw to show the error state",
            "state: \"submitting\" | \"success\" | \"error\" (omit it and the form runs by itself); errorState.description sets the failure message. Pair with your own async handler: state={pending ? \"submitting\" : failed ? \"error\" : done ? \"success\" : undefined}"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Sending",
            "example": "contact-1-sending",
            "trigger": "state=\"submitting\"",
            "note": "Every field and button is disabled while the request is in flight, the button shows a spinner, and the form is marked busy."
          },
          {
            "id": "success",
            "title": "Message sent",
            "example": "contact-1-sent",
            "trigger": "state=\"success\"",
            "note": "The confirmation screen the flow ends on."
          },
          {
            "id": "error",
            "title": "Could not send",
            "example": "contact-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert above the form with the message (errorState.description to change it); the fields stay editable so it can be fixed."
          }
        ],
        "examples": [
          "contact-1-demo",
          "contact-1-support",
          "contact-1-sending",
          "contact-1-sent",
          "contact-1-error"
        ],
        "url": "https://ui.ballmac.com/components/contact-1"
      }
    },
    {
      "name": "contact-1-demo",
      "type": "registry:example",
      "title": "Contact 1: form with contact methods: Default",
      "description": "Default example of Contact 1: form with contact methods.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/contact-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/contact-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/contact-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "contact-1",
        "tier": "free"
      }
    },
    {
      "name": "contact-1-support",
      "type": "registry:example",
      "title": "Contact 1: form with contact methods: Support form",
      "description": "Support form example of Contact 1: form with contact methods.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/contact-1.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/contact-1-support.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/contact-1-support.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "contact-1",
        "tier": "free"
      }
    },
    {
      "name": "contact-1-sending",
      "type": "registry:example",
      "title": "Contact 1: form with contact methods: Sending",
      "description": "Sending example of Contact 1: form with contact methods.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/contact-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/contact-1-sending.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/contact-1-sending.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "contact-1",
        "tier": "free"
      }
    },
    {
      "name": "contact-1-sent",
      "type": "registry:example",
      "title": "Contact 1: form with contact methods: Message sent",
      "description": "Message sent example of Contact 1: form with contact methods.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/contact-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/contact-1-sent.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/contact-1-sent.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "contact-1",
        "tier": "free"
      }
    },
    {
      "name": "contact-1-error",
      "type": "registry:example",
      "title": "Contact 1: form with contact methods: Could not send",
      "description": "Could not send example of Contact 1: form with contact methods.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/contact-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/contact-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/contact-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "contact-1",
        "tier": "free"
      }
    },
    {
      "name": "crm-1",
      "type": "registry:block",
      "title": "CRM 1: contact and deal record",
      "description": "A contact record for a sales team: the pipeline stage you can move, deal value, last contact and an overdue follow-up worked out from the day you pass, and a timeline of notes, calls, emails and meetings with a form to log the next.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/cover-art.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/textarea.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/crm-1/crm-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/crm-1/crm-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "crm"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "crm",
          "contact",
          "deal",
          "pipeline",
          "sales",
          "leads",
          "activity",
          "follow-up",
          "customer record",
          "account"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "A CRM contact record. <Crm1 contact={{ id, name, title, company, email, phone, location, owner, stage: 2, value: 48000, tags, followUp: '2026-10-16', activities: [{ id, kind: 'note' | 'call' | 'email' | 'meeting', date: '2026-10-09', by, summary }] }} stages={['Lead', 'Qualified', 'Proposal', 'Negotiation', 'Won']} today='2026-10-18' currency locale onLog={({ kind, summary, date }) => Promise} onStageChange={(index) => ...} onFollowUp={(date) => ...} />. Last contact and the follow-up status (Due in N days, Due today, Overdue by N days) are worked out from today; pass it yourself, the block never reads the clock. A logged item appears at once; reject onLog and it stays with Not saved and Retry.",
          "whenToUse": [
            "A customer or lead record in a CRM or support tool",
            "An account page for sales and customer success"
          ],
          "whenNotToUse": [
            "A list or board of deals (use kanban-1)",
            "A support conversation (use tickets-1)"
          ],
          "composesWith": [
            "directory-1",
            "tickets-1",
            "invoice-1",
            "app-shell-1"
          ],
          "a11y": [
            {
              "keys": "Tab, Enter / Space",
              "action": "Each pipeline stage is a button that says done, current stage or nothing; the activity type is a radio group and the form fields have labels"
            },
            {
              "keys": "Follow-up",
              "action": "'Overdue by 2 days' is written in words with the date, and the card is tinted as well as worded"
            },
            {
              "keys": "Logging",
              "action": "A new activity shows Saving, and a failure is an alert with a Retry button"
            }
          ],
          "customization": [
            "stages is a plain list of names, so any pipeline works",
            "Value, dates and relative times follow currency, locale and today",
            "The timeline line and stages mirror in right-to-left"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "crm-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton header, timeline and side panel, announced as loading."
          },
          {
            "id": "empty",
            "title": "Contact not found",
            "example": "crm-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says they may have been merged or removed; emptyState sets the copy and can add a link back."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "crm-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed, with Try again (onRetry). A logged activity that fails to save stays in the timeline with Not saved and Retry."
          }
        ],
        "examples": [
          "crm-1-demo",
          "crm-1-won",
          "crm-1-loading",
          "crm-1-empty",
          "crm-1-error"
        ],
        "url": "https://ui.ballmac.com/components/crm-1"
      }
    },
    {
      "name": "crm-1-demo",
      "type": "registry:example",
      "title": "CRM 1: contact and deal record: A follow-up overdue",
      "description": "A follow-up overdue example of CRM 1: contact and deal record.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/crm-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/crm-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/crm-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "crm-1",
        "tier": "free"
      }
    },
    {
      "name": "crm-1-won",
      "type": "registry:example",
      "title": "CRM 1: contact and deal record: A won deal",
      "description": "A won deal example of CRM 1: contact and deal record.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/crm-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/crm-1-won.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/crm-1-won.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "crm-1",
        "tier": "free"
      }
    },
    {
      "name": "crm-1-loading",
      "type": "registry:example",
      "title": "CRM 1: contact and deal record: Loading",
      "description": "Loading example of CRM 1: contact and deal record.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/crm-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/crm-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/crm-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "crm-1",
        "tier": "free"
      }
    },
    {
      "name": "crm-1-empty",
      "type": "registry:example",
      "title": "CRM 1: contact and deal record: Contact not found",
      "description": "Contact not found example of CRM 1: contact and deal record.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/crm-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/crm-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/crm-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "crm-1",
        "tier": "free"
      }
    },
    {
      "name": "crm-1-error",
      "type": "registry:example",
      "title": "CRM 1: contact and deal record: Could not load",
      "description": "Could not load example of CRM 1: contact and deal record.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/crm-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/crm-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/crm-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "crm-1",
        "tier": "free"
      }
    },
    {
      "name": "cron-1",
      "type": "registry:block",
      "title": "Cron 1: scheduled jobs",
      "description": "The scheduled jobs of a product: each schedule in plain words beside its cron expression, an on and off switch, the last run written out, the next runs, and a Run now button that asks first.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/alert-dialog.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/switch.json",
        "https://ui.ballmac.com/r/return-focus.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/cron-1/cron-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/cron-1/cron-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "cron"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "cron",
          "scheduled jobs",
          "scheduler",
          "automation",
          "backups",
          "tasks",
          "devops",
          "timers"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "Scheduled jobs. <Cron1 jobs={[{ id, name, schedule: '0 9 * * 1-5', timezone?, enabled, owner?, last?: { status: 'success' | 'failed' | 'running', at, duration? }, next?: string[] }]} onToggle={(job, enabled) => Promise} onRunNow={(job) => Promise} />. Exports describeCron(expr), which turns common five-field expressions into a sentence (every N minutes or hours, daily, weekdays, weekends, one weekday, monthly) and says 'A custom schedule' for the rest instead of guessing.",
          "whenToUse": [
            "An admin page for cron jobs and background schedules",
            "Letting a team pause a job or run it once by hand"
          ],
          "whenNotToUse": [
            "The workers and their failed jobs; use queues-1",
            "Automations built by users with triggers and steps; use workflow-1"
          ],
          "composesWith": [
            "queues-1",
            "audit-1",
            "pipeline-1",
            "slo-1"
          ],
          "a11y": [
            {
              "keys": "Schedule",
              "action": "Written as a sentence and also shown as code, which stays left to right"
            },
            {
              "keys": "Switch",
              "action": "Named '<job> is on'; a failure is an alert and the switch goes back"
            },
            {
              "keys": "Run now",
              "action": "A button named for the job that opens an alert dialog, and is off while the job is already running"
            },
            {
              "keys": "Last run",
              "action": "Written in words with an icon (Last run failed), never colour alone"
            }
          ],
          "customization": [
            "jobs with last and next runs",
            "onToggle and onRunNow",
            "describeCron is exported for your own lists"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "cron-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton rows under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No scheduled jobs",
            "example": "cron-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says no scheduled jobs; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "cron-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed or started, with Try again (onRetry). A switch that fails goes back and says why."
          }
        ],
        "examples": [
          "cron-1-demo",
          "cron-1-loading",
          "cron-1-empty",
          "cron-1-error"
        ],
        "url": "https://ui.ballmac.com/components/cron-1"
      }
    },
    {
      "name": "cron-1-demo",
      "type": "registry:example",
      "title": "Cron 1: scheduled jobs: Default",
      "description": "Default example of Cron 1: scheduled jobs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cron-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/cron-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cron-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "cron-1",
        "tier": "free"
      }
    },
    {
      "name": "cron-1-loading",
      "type": "registry:example",
      "title": "Cron 1: scheduled jobs: Loading",
      "description": "Loading example of Cron 1: scheduled jobs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cron-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/cron-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cron-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "cron-1",
        "tier": "free"
      }
    },
    {
      "name": "cron-1-empty",
      "type": "registry:example",
      "title": "Cron 1: scheduled jobs: No scheduled jobs",
      "description": "No scheduled jobs example of Cron 1: scheduled jobs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cron-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/cron-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cron-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "cron-1",
        "tier": "free"
      }
    },
    {
      "name": "cron-1-error",
      "type": "registry:example",
      "title": "Cron 1: scheduled jobs: Could not load",
      "description": "Could not load example of Cron 1: scheduled jobs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cron-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/cron-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cron-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "cron-1",
        "tier": "free"
      }
    },
    {
      "name": "cta-1",
      "type": "registry:block",
      "title": "CTA 1: framed call to action",
      "description": "A closing call-to-action panel: large heading, one line of reassurance and two buttons, over a softly lit animated grid.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/animated-grid.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/cta-1/cta-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/cta-1/cta-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "cta"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "cta",
          "call to action",
          "signup",
          "landing"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "The last section before the footer: one decisive action. Edit title, description and the two actions.",
          "whenToUse": [
            "End of landing and pricing pages",
            "Between long content sections to prompt sign-up"
          ],
          "whenNotToUse": [
            "Top of the page (use a hero)"
          ],
          "composesWith": [
            "footer-1",
            "faq-1"
          ],
          "a11y": [],
          "customization": [
            "title, description, primaryAction, secondaryAction props"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "cta-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/cta-1"
      }
    },
    {
      "name": "cta-1-demo",
      "type": "registry:example",
      "title": "CTA 1: framed call to action: Default",
      "description": "Default example of CTA 1: framed call to action.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cta-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/cta-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cta-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "cta-1",
        "tier": "free"
      }
    },
    {
      "name": "dashboard-1",
      "type": "registry:block",
      "title": "Dashboard 1: sales overview",
      "description": "A sales dashboard page: a date-range switch that recomputes everything, four KPI cards with change and trend, a revenue area chart against the previous period, revenue by channel and a recent-orders table.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react",
        "recharts@^3"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/badge.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/chart.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/sparkline.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/dashboard-1/dashboard-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/dashboard-1/dashboard-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "dashboard"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "dashboard",
          "analytics",
          "kpi",
          "chart",
          "orders",
          "sales",
          "table"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton of the cards, chart and tables under the real heading, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "The first screen of a store or SaaS admin. Pass getSeries(range) returning { label, revenue, previous, orders }[], plus channels, orders and currency; the KPIs, deltas and chart are derived from the series.",
          "whenToUse": [
            "Admin home pages",
            "Sales, billing and usage overviews"
          ],
          "whenNotToUse": [
            "Traffic analytics (use dashboard-2)"
          ],
          "composesWith": [
            "app-shell-1",
            "dashboard-2",
            "billing-1",
            "settings-1"
          ],
          "a11y": [
            {
              "keys": "Arrow Left / Right",
              "action": "Changes the date range"
            },
            {
              "keys": "Chart",
              "action": "Labelled figure with a plain-language summary; the same numbers are in the KPI cards and the table"
            },
            {
              "keys": "Tab",
              "action": "The orders table scrolls sideways on phones and is focusable"
            }
          ],
          "customization": [
            "getSeries(range) for your own data",
            "channels, orders, currency, locale",
            "onRangeChange to fetch",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "dashboard-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No sales yet",
            "example": "dashboard-1-no-data",
            "trigger": "state=\"empty\"",
            "note": "A clear message that there is nothing yet. emptyState sets the copy and can add an action."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "dashboard-1-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "dashboard-1-demo",
          "dashboard-1-week",
          "dashboard-1-loading",
          "dashboard-1-error",
          "dashboard-1-no-data"
        ],
        "url": "https://ui.ballmac.com/components/dashboard-1"
      }
    },
    {
      "name": "dashboard-1-demo",
      "type": "registry:example",
      "title": "Dashboard 1: sales overview: Default",
      "description": "Default example of Dashboard 1: sales overview.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dashboard-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/dashboard-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dashboard-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "dashboard-1",
        "tier": "free"
      }
    },
    {
      "name": "dashboard-1-week",
      "type": "registry:example",
      "title": "Dashboard 1: sales overview: Seven days, your data",
      "description": "Seven days, your data example of Dashboard 1: sales overview.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dashboard-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/dashboard-1-week.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dashboard-1-week.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "dashboard-1",
        "tier": "free"
      }
    },
    {
      "name": "dashboard-1-loading",
      "type": "registry:example",
      "title": "Dashboard 1: sales overview: Loading",
      "description": "Loading example of Dashboard 1: sales overview.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dashboard-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/dashboard-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dashboard-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "dashboard-1",
        "tier": "free"
      }
    },
    {
      "name": "dashboard-1-error",
      "type": "registry:example",
      "title": "Dashboard 1: sales overview: Could not load",
      "description": "Could not load example of Dashboard 1: sales overview.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dashboard-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/dashboard-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dashboard-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "dashboard-1",
        "tier": "free"
      }
    },
    {
      "name": "dashboard-1-no-data",
      "type": "registry:example",
      "title": "Dashboard 1: sales overview: No sales yet",
      "description": "No sales yet example of Dashboard 1: sales overview.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dashboard-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/dashboard-1-no-data.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dashboard-1-no-data.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "dashboard-1",
        "tier": "free"
      }
    },
    {
      "name": "deploys-1",
      "type": "registry:block",
      "title": "Deploys 1: deploy history",
      "description": "The deploy history of a product: version, what changed, who shipped it and when, how it ended in words, one environment at a time, the live version marked, and a confirmed rollback to any earlier version that succeeded.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/alert-dialog.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/return-focus.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/deploys-1/deploys-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/deploys-1/deploys-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "deploys"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "deploys",
          "releases",
          "rollback",
          "history",
          "ci",
          "cd",
          "versions",
          "devops"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "Deploy history. <Deploys1 deploys={[{ id, version, message, author, time, environment, status: 'success' | 'failed' | 'rolled-back' | 'running', duration?, commit? }]} onRollback={(deploy) => Promise} />. The first environment shows at first; a control switches. The newest successful deploy per environment is Live; only earlier successful ones offer Roll back to this, behind a confirmation naming both versions.",
          "whenToUse": [
            "A release page where people check what is live and go back if needed",
            "An audit of what shipped to each environment"
          ],
          "whenNotToUse": [
            "The stages of one deploy; use pipeline-1",
            "Changes to settings; use audit-1"
          ],
          "composesWith": [
            "pipeline-1",
            "incident-1",
            "audit-1",
            "status-1"
          ],
          "a11y": [
            {
              "keys": "Timeline",
              "action": "An ordered list named 'Deploys to production, newest first'; each status is written ('Succeeded · 3 min 12 s', 'Failed', 'Rolled back') with an icon"
            },
            {
              "keys": "Live",
              "action": "Marked with the word Live"
            },
            {
              "keys": "Environment",
              "action": "Toggle buttons with aria-pressed"
            },
            {
              "keys": "Rollback",
              "action": "A button named 'Roll back production to v2.18.2' that opens an alert dialog and returns focus when closed; a failure is an alert"
            }
          ],
          "customization": [
            "deploys with environments",
            "onRollback; reject and nothing changes",
            "Commit ids and versions stay left to right"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "deploys-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton rows under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "Nothing deployed yet",
            "example": "deploys-1-empty",
            "trigger": "state=\"empty\"",
            "note": "Says nothing has been deployed yet; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "deploys-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was rolled back or changed, with Try again (onRetry). A rollback that does not start says why."
          }
        ],
        "examples": [
          "deploys-1-demo",
          "deploys-1-failing",
          "deploys-1-loading",
          "deploys-1-empty",
          "deploys-1-error"
        ],
        "url": "https://ui.ballmac.com/components/deploys-1"
      }
    },
    {
      "name": "deploys-1-demo",
      "type": "registry:example",
      "title": "Deploys 1: deploy history: Default",
      "description": "Default example of Deploys 1: deploy history.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/deploys-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/deploys-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/deploys-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "deploys-1",
        "tier": "free"
      }
    },
    {
      "name": "deploys-1-failing",
      "type": "registry:example",
      "title": "Deploys 1: deploy history: Rollback fails",
      "description": "Rollback fails example of Deploys 1: deploy history.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/deploys-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/deploys-1-failing.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/deploys-1-failing.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "deploys-1",
        "tier": "free"
      }
    },
    {
      "name": "deploys-1-loading",
      "type": "registry:example",
      "title": "Deploys 1: deploy history: Loading",
      "description": "Loading example of Deploys 1: deploy history.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/deploys-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/deploys-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/deploys-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "deploys-1",
        "tier": "free"
      }
    },
    {
      "name": "deploys-1-empty",
      "type": "registry:example",
      "title": "Deploys 1: deploy history: Nothing deployed yet",
      "description": "Nothing deployed yet example of Deploys 1: deploy history.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/deploys-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/deploys-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/deploys-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "deploys-1",
        "tier": "free"
      }
    },
    {
      "name": "deploys-1-error",
      "type": "registry:example",
      "title": "Deploys 1: deploy history: Could not load",
      "description": "Could not load example of Deploys 1: deploy history.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/deploys-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/deploys-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/deploys-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "deploys-1",
        "tier": "free"
      }
    },
    {
      "name": "directory-1",
      "type": "registry:block",
      "title": "Directory 1: people directory",
      "description": "A people directory: search across names, roles, teams and cities, department chips with live counts, a location filter, a grid and a compact list, each person with availability and their local time right now.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/cover-art.json",
        "https://ui.ballmac.com/r/match-highlight.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/select.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/directory-1/directory-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/directory-1/directory-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "directory"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "directory",
          "people",
          "team",
          "employees",
          "contacts",
          "company",
          "who is who",
          "time zones",
          "staff"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "A people directory. <Directory1 people={[{ id, name, title, department, location, utcOffset: 1, email, pronouns, status: 'available' | 'away' | 'out' }]} now='2026-10-18T10:42:00Z' locale defaultView='grid' | 'list' onSelect />. Local times are worked out from now plus each utcOffset; pass now yourself, the block never reads the clock. Department chips and the location menu come from the data.",
          "whenToUse": [
            "An internal company directory or a team page with filters",
            "Remote teams that need to see where people are and what time it is for them"
          ],
          "whenNotToUse": [
            "A reporting hierarchy (use orgchart-1)",
            "A marketing team section with photos (use team-1)"
          ],
          "composesWith": [
            "orgchart-1",
            "app-shell-1",
            "about-1"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Search, location, view, department buttons (pressed state announced), then one button per person; the email shortcut is its own link"
            },
            {
              "keys": "Count",
              "action": "'7 people match' is announced politely as filters change"
            },
            {
              "keys": "Availability",
              "action": "Written as a word (Available, Away, Out of office) beside the dot, never by color alone"
            }
          ],
          "customization": [
            "Local time uses each person's utcOffset, so half-hour zones work",
            "A person between 21:00 and 07:00 locally is marked probably offline",
            "Pictures are drawn from the name, so identical on server and client"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "directory-1-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton cards under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "Nobody listed",
            "example": "directory-1-empty",
            "trigger": "state=\"empty\" (or people={[]})",
            "note": "Says people appear once added; emptyState sets the copy. A search with no match says so with Clear filters."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "directory-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert with Try again (onRetry)."
          }
        ],
        "examples": [
          "directory-1-demo",
          "directory-1-list",
          "directory-1-loading",
          "directory-1-empty",
          "directory-1-error"
        ],
        "url": "https://ui.ballmac.com/components/directory-1"
      }
    },
    {
      "name": "directory-1-demo",
      "type": "registry:example",
      "title": "Directory 1: people directory: Grid",
      "description": "Grid example of Directory 1: people directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/directory-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/directory-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/directory-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "directory-1",
        "tier": "free"
      }
    },
    {
      "name": "directory-1-list",
      "type": "registry:example",
      "title": "Directory 1: people directory: List",
      "description": "List example of Directory 1: people directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/directory-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/directory-1-list.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/directory-1-list.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "directory-1",
        "tier": "free"
      }
    },
    {
      "name": "directory-1-loading",
      "type": "registry:example",
      "title": "Directory 1: people directory: Loading",
      "description": "Loading example of Directory 1: people directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/directory-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/directory-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/directory-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "directory-1",
        "tier": "free"
      }
    },
    {
      "name": "directory-1-empty",
      "type": "registry:example",
      "title": "Directory 1: people directory: Nobody listed",
      "description": "Nobody listed example of Directory 1: people directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/directory-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/directory-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/directory-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "directory-1",
        "tier": "free"
      }
    },
    {
      "name": "directory-1-error",
      "type": "registry:example",
      "title": "Directory 1: people directory: Could not load",
      "description": "Could not load example of Directory 1: people directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/directory-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/directory-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/directory-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "directory-1",
        "tier": "free"
      }
    },
    {
      "name": "download-1",
      "type": "registry:block",
      "title": "Download 1: Mac app download with release notes",
      "description": "A Mac app download section: app icon and version, an Apple silicon or Intel choice that swaps the file, copyable checksum and Homebrew command, install steps and release notes you can flip between.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/copy-button.json",
        "https://ui.ballmac.com/r/mac-icons.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/download-1/download-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/download-1/download-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "download"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "download",
          "mac",
          "app",
          "release notes",
          "homebrew",
          "checksum",
          "install"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "ai": {
          "summary": "The download page of a Mac app. Pass app, tagline, downloads={ arm64: { href, file, size, sha256? }, x64: {...} }, requirements, brew, steps and releases=[{ version, date, changes: [{ type, text }] }].",
          "whenToUse": [
            "Direct-download Mac apps",
            "Any desktop app with separate builds per chip"
          ],
          "whenNotToUse": [
            "App Store only apps (link to the store instead)",
            "Web apps"
          ],
          "composesWith": [
            "hero-5",
            "showcase-1",
            "features-7",
            "pricing-4"
          ],
          "a11y": [
            {
              "keys": "Arrow Left / Right",
              "action": "Switches between Apple silicon and Intel, and between release versions"
            },
            {
              "keys": "Download link",
              "action": "A real link; when activated a polite status confirms the file name"
            },
            {
              "keys": "Copy buttons",
              "action": "Named 'Copy SHA-256 checksum' and 'Copy Homebrew command'; success is announced"
            }
          ],
          "customization": [
            "downloads, requirements, brew (null hides), steps ([] hides), releases",
            "glyph: a letter or short text on the icon"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "download-1-demo",
          "download-1-simple"
        ],
        "url": "https://ui.ballmac.com/components/download-1"
      }
    },
    {
      "name": "download-1-demo",
      "type": "registry:example",
      "title": "Download 1: Mac app download with release notes: Default",
      "description": "Default example of Download 1: Mac app download with release notes.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/download-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/download-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/download-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "download-1",
        "tier": "free"
      }
    },
    {
      "name": "download-1-simple",
      "type": "registry:example",
      "title": "Download 1: Mac app download with release notes: One build, no notes",
      "description": "One build, no notes example of Download 1: Mac app download with release notes.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/download-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/download-1-simple.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/download-1-simple.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "download-1",
        "tier": "free"
      }
    },
    {
      "name": "error-1",
      "type": "registry:block",
      "title": "Error 1: friendly 404, 403 and 500 page",
      "description": "An error page with giant fading numerals whose zero is a ring with an orbiting moon, plain-language copy per status, home and back buttons, site search and helpful links.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react",
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/search-field.json",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/error-1/error-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/error-1/error-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "error"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "error",
          "404",
          "not found",
          "500",
          "403",
          "page"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "The drifting background pauses with the theme's ambient setting, and the link lift follows --bm-lift. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Drop into not-found.tsx or error.tsx. Set status ('404' | '403' | '500'); override title and description if you like; pass onSearch to wire the search box, links for next steps and reference for a request id.",
          "whenToUse": [
            "Next.js not-found.tsx and error.tsx",
            "Any missing, forbidden or failed page"
          ],
          "whenNotToUse": [
            "Inline errors inside a form or panel (use alert or empty-state)"
          ],
          "composesWith": [
            "header-2",
            "footer-2",
            "contact-1"
          ],
          "a11y": [
            {
              "keys": "Page title",
              "action": "The heading is prefixed with 'Error 404:' for screen readers; the giant numerals are decorative"
            },
            {
              "keys": "Enter in the search field",
              "action": "Calls onSearch with the query"
            }
          ],
          "customization": [
            "status picks the numerals and default copy",
            "links: [] hides the cards, search: false hides the field",
            "The orbiting moon stops for reduced motion"
          ]
        },
        "statesNone": "This block is the error page itself.",
        "examples": [
          "error-1-demo",
          "error-1-server"
        ],
        "url": "https://ui.ballmac.com/components/error-1"
      }
    },
    {
      "name": "error-1-demo",
      "type": "registry:example",
      "title": "Error 1: friendly 404, 403 and 500 page: 404",
      "description": "404 example of Error 1: friendly 404, 403 and 500 page.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/error-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/error-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/error-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "error-1",
        "tier": "free"
      }
    },
    {
      "name": "error-1-server",
      "type": "registry:example",
      "title": "Error 1: friendly 404, 403 and 500 page: 500 with reference",
      "description": "500 with reference example of Error 1: friendly 404, 403 and 500 page.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/error-1.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/error-1-server.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/error-1-server.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "error-1",
        "tier": "free"
      }
    },
    {
      "name": "event-1",
      "type": "registry:block",
      "title": "Event 1: agenda and my schedule",
      "description": "An event page with its agenda: dates, venue and a countdown, the schedule by day with a filter per track, a star on each session to build your own schedule, a warning for overlaps, and a calendar file download.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/cover-art.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/event-1/event-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/event-1/event-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "event"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "event",
          "conference",
          "agenda",
          "schedule",
          "sessions",
          "speakers",
          "tracks",
          "calendar",
          "ics",
          "summit",
          "meetup"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "An event agenda. <Event1 name tagline dates={['2026-11-12', '2026-11-13']} venue utcOffset={1} sessions={[{ id, day: '2026-11-12', start: '09:00', end: '09:45', title, track, room, speakers: [{ name, role }], description }]} now='2026-10-18T10:00:00Z' defaultSaved={['s1']} onSavedChange />. Days and tracks come from the sessions; overlaps among saved sessions are found for you; 'Add to my calendar' builds an .ics file in the browser using utcOffset. Pass now yourself; the block never reads the clock.",
          "whenToUse": [
            "A conference, meetup or webinar series page with a schedule",
            "An internal offsite agenda"
          ],
          "whenNotToUse": [
            "Ticket purchase (use a pricing block)",
            "A month calendar of many events (use calendar-1)"
          ],
          "composesWith": [
            "hero-1",
            "pricing-1",
            "faq-1",
            "footer-1"
          ],
          "a11y": [
            {
              "keys": "Left / Right on the day tabs",
              "action": "Move between days (a tablist); the schedule below is the tab panel"
            },
            {
              "keys": "Tab, Enter / Space",
              "action": "Track buttons say whether they are on; each Save button says which session, and its pressed state"
            },
            {
              "keys": "Overlap",
              "action": "Written as a warning with the clashing session's name and times, not only a color; changes to your schedule are announced politely"
            }
          ],
          "customization": [
            "Sessions at the same time sit side by side in the list, ordered by title",
            "utcOffset sets the time zone of the calendar file",
            "Dates use the locale you pass"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "event-1-demo",
          "event-1-saved"
        ],
        "url": "https://ui.ballmac.com/components/event-1"
      }
    },
    {
      "name": "event-1-demo",
      "type": "registry:example",
      "title": "Event 1: agenda and my schedule: Default",
      "description": "Default example of Event 1: agenda and my schedule.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/event-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/event-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/event-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "event-1",
        "tier": "free"
      }
    },
    {
      "name": "event-1-saved",
      "type": "registry:example",
      "title": "Event 1: agenda and my schedule: A schedule with an overlap",
      "description": "A schedule with an overlap example of Event 1: agenda and my schedule.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/event-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/event-1-saved.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/event-1-saved.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "event-1",
        "tier": "free"
      }
    },
    {
      "name": "faq-1",
      "type": "registry:block",
      "title": "FAQ 1: accordion with heading",
      "description": "Frequently asked questions in an accessible accordion, with the heading and a help line in a side column on desktop.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/accordion.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/faq-1/faq-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/faq-1/faq-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "faq"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "faq",
          "accordion",
          "questions",
          "support"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "An FAQ section. Pass items=[{ question, answer }]; the first answer starts open.",
          "whenToUse": [
            "Pricing pages and landing pages",
            "Support and onboarding pages"
          ],
          "whenNotToUse": [
            "Long documentation (use a docs page)"
          ],
          "composesWith": [
            "pricing-1",
            "cta-1"
          ],
          "a11y": [],
          "customization": [
            "items: { question, answer }[]",
            "title and description props"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "faq-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/faq-1"
      }
    },
    {
      "name": "faq-1-demo",
      "type": "registry:example",
      "title": "FAQ 1: accordion with heading: Default",
      "description": "Default example of FAQ 1: accordion with heading.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/faq-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/faq-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/faq-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "faq-1",
        "tier": "free"
      }
    },
    {
      "name": "features-1",
      "type": "registry:block",
      "title": "Features 1: bento grid",
      "description": "Bento feature grid of spotlight cards in two sizes, with an animated stat and keyboard-shortcut hints mixed in for texture.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/kbd.json",
        "https://ui.ballmac.com/r/number-ticker.json",
        "https://ui.ballmac.com/r/spotlight-card.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/features-1/features-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/features-1/features-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "features"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "features",
          "bento",
          "grid",
          "landing"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "A four-cell bento grid for a product's main features. Edit the cells directly; each is a SpotlightCard with an icon, title, body and optional extra content.",
          "whenToUse": [
            "Showing 3–6 headline features with visual variety",
            "SaaS and developer product landing pages"
          ],
          "whenNotToUse": [
            "Long lists of features (use features-2)"
          ],
          "composesWith": [
            "hero-1",
            "pricing-1"
          ],
          "a11y": [],
          "customization": [
            "eyebrow, title, description props",
            "Change cells, spans (md:col-span-2) and icons in the source"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "features-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/features-1"
      }
    },
    {
      "name": "features-1-demo",
      "type": "registry:example",
      "title": "Features 1: bento grid: Default",
      "description": "Default example of Features 1: bento grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/features-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/features-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/features-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "features-1",
        "tier": "free"
      }
    },
    {
      "name": "footer-1",
      "type": "registry:block",
      "title": "Footer 1: columns with newsletter",
      "description": "Site footer with brand and tagline, an optional newsletter form, up to four link columns and a legal bar.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/footer-1/footer-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/footer-1/footer-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "footer"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "footer",
          "newsletter",
          "navigation",
          "links"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "The bottom of every marketing page. Pass groups of links; pass onSubscribe to show the newsletter form (you handle the email).",
          "whenToUse": [
            "Marketing sites and landing pages"
          ],
          "whenNotToUse": [
            "App screens behind login (keep chrome minimal)"
          ],
          "composesWith": [
            "header-1",
            "cta-1"
          ],
          "a11y": [],
          "customization": [
            "groups: { title, links: { label, href }[] }[]",
            "brand, tagline, legal props",
            "onSubscribe(email) shows the newsletter form"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "footer-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/footer-1"
      }
    },
    {
      "name": "footer-1-demo",
      "type": "registry:example",
      "title": "Footer 1: columns with newsletter: Default",
      "description": "Default example of Footer 1: columns with newsletter.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/footer-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/footer-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/footer-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "footer-1",
        "tier": "free"
      }
    },
    {
      "name": "forgot-password-1",
      "type": "registry:block",
      "title": "Forgot Password 1: request, resend and reset",
      "description": "The whole password-recovery flow in one card: request a link, check-your-email with a resend countdown, choose a new password with confirmation and strength, and a success screen. Focus moves to each new heading.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/field.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/password-input.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/forgot-password-1/forgot-password-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/forgot-password-1/forgot-password-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "auth"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "forgot password",
          "reset password",
          "auth",
          "recovery",
          "email",
          "countdown"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (submitting, success, error) to drive the form from your own async code, and defaultValues or defaultEmail to prefill. Fields lock while a request is in flight. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Use it on /forgot-password (initialView 'request') and on the page the emailed link opens (initialView 'reset'). Pass onRequest(email) and onReset(password); throw to show an error.",
          "whenToUse": [
            "Any app with passwords",
            "The page an emailed reset link opens"
          ],
          "whenNotToUse": [
            "Passwordless-only products"
          ],
          "composesWith": [
            "login-2",
            "login-1",
            "verify-1"
          ],
          "a11y": [
            {
              "keys": "Screen changes",
              "action": "Focus moves to the new heading so the change is announced"
            },
            {
              "keys": "Resend",
              "action": "The countdown is announced politely; the button is disabled until it ends"
            }
          ],
          "customization": [
            "initialView: 'request' | 'sent' | 'reset' | 'done'",
            "onRequest / onReset async handlers",
            "resendAfter: cooldown in seconds",
            "state: \"submitting\" | \"success\" | \"error\" (omit it and the form runs by itself); errorState.description sets the failure message. Pair with your own async handler: state={pending ? \"submitting\" : failed ? \"error\" : done ? \"success\" : undefined}"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Sending the link",
            "example": "forgot-password-1-submitting",
            "trigger": "state=\"submitting\"",
            "note": "Every field and button is disabled while the request is in flight, the button shows a spinner, and the form is marked busy."
          },
          {
            "id": "success",
            "title": "Check your email",
            "example": "forgot-password-1-success",
            "trigger": "state=\"success\"",
            "note": "The confirmation screen the flow ends on."
          },
          {
            "id": "error",
            "title": "Could not send",
            "example": "forgot-password-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert above the form with the message (errorState.description to change it); the fields stay editable so it can be fixed."
          }
        ],
        "examples": [
          "forgot-password-1-demo",
          "forgot-password-1-reset",
          "forgot-password-1-submitting",
          "forgot-password-1-success",
          "forgot-password-1-error"
        ],
        "url": "https://ui.ballmac.com/components/forgot-password-1"
      }
    },
    {
      "name": "forgot-password-1-demo",
      "type": "registry:example",
      "title": "Forgot Password 1: request, resend and reset: Request a link",
      "description": "Request a link example of Forgot Password 1: request, resend and reset.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/forgot-password-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/forgot-password-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/forgot-password-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "forgot-password-1",
        "tier": "free"
      }
    },
    {
      "name": "forgot-password-1-reset",
      "type": "registry:example",
      "title": "Forgot Password 1: request, resend and reset: Choose a new password",
      "description": "Choose a new password example of Forgot Password 1: request, resend and reset.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/forgot-password-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/forgot-password-1-reset.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/forgot-password-1-reset.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "forgot-password-1",
        "tier": "free"
      }
    },
    {
      "name": "forgot-password-1-submitting",
      "type": "registry:example",
      "title": "Forgot Password 1: request, resend and reset: Sending the link",
      "description": "Sending the link example of Forgot Password 1: request, resend and reset.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/forgot-password-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/forgot-password-1-submitting.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/forgot-password-1-submitting.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "forgot-password-1",
        "tier": "free"
      }
    },
    {
      "name": "forgot-password-1-success",
      "type": "registry:example",
      "title": "Forgot Password 1: request, resend and reset: Check your email",
      "description": "Check your email example of Forgot Password 1: request, resend and reset.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/forgot-password-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/forgot-password-1-success.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/forgot-password-1-success.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "forgot-password-1",
        "tier": "free"
      }
    },
    {
      "name": "forgot-password-1-error",
      "type": "registry:example",
      "title": "Forgot Password 1: request, resend and reset: Could not send",
      "description": "Could not send example of Forgot Password 1: request, resend and reset.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/forgot-password-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/forgot-password-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/forgot-password-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "forgot-password-1",
        "tier": "free"
      }
    },
    {
      "name": "header-1",
      "type": "registry:block",
      "title": "Header 1: sticky with mobile menu",
      "description": "Sticky site header with brand, main links, sign-in and primary action, and an accessible mobile menu that closes on Escape or link tap.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/header-1/header-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/header-1/header-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "header"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "header",
          "navbar",
          "navigation",
          "mobile menu"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "The top navigation bar for a marketing site. Pass links and the two actions; it handles the mobile menu.",
          "whenToUse": [
            "Marketing sites and landing pages",
            "Docs sites with a few top-level sections"
          ],
          "whenNotToUse": [
            "Apps with deep navigation (use a sidebar)"
          ],
          "composesWith": [
            "hero-1",
            "hero-2",
            "footer-1"
          ],
          "a11y": [
            {
              "keys": "Enter / Space on the menu button",
              "action": "Opens or closes the mobile menu"
            },
            {
              "keys": "Escape",
              "action": "Closes the mobile menu"
            }
          ],
          "customization": [
            "brand, brandHref, links, secondaryAction, primaryAction props",
            "sticky: false for a static header"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "header-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/header-1"
      }
    },
    {
      "name": "header-1-demo",
      "type": "registry:example",
      "title": "Header 1: sticky with mobile menu: Default",
      "description": "Default example of Header 1: sticky with mobile menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/header-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/header-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/header-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "header-1",
        "tier": "free"
      }
    },
    {
      "name": "hero-4",
      "type": "registry:block",
      "title": "Hero 4: split with interactive globe",
      "description": "Split hero with a live pill, headline, two actions and headline stats beside a large draggable WebGL globe marking your regions.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/globe.json",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/hero-4/hero-4.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/hero-4/hero-4.tsx"
        }
      ],
      "categories": [
        "blocks",
        "hero"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "hero",
          "globe",
          "infrastructure",
          "landing",
          "3d"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "Top-of-page hero for global or infrastructure products. Edit announcement, title, description, actions, stats and globe markers ([lat, long]).",
          "whenToUse": [
            "Infrastructure, hosting, edge or global-reach products",
            "Companies with offices or users worldwide"
          ],
          "whenNotToUse": [
            "Products where geography doesn't matter (use hero-1 or hero-2)"
          ],
          "composesWith": [
            "header-1",
            "logo-cloud-1",
            "features-3"
          ],
          "a11y": [],
          "customization": [
            "markers: [{ location: [lat, long], size }]",
            "stats: up to three { value, label }"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "hero-4-demo"
        ],
        "url": "https://ui.ballmac.com/components/hero-4"
      }
    },
    {
      "name": "hero-4-demo",
      "type": "registry:example",
      "title": "Hero 4: split with interactive globe: Default",
      "description": "Default example of Hero 4: split with interactive globe.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/hero-4.json"
      ],
      "files": [
        {
          "path": "registry/examples/hero-4-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/hero-4-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "hero-4",
        "tier": "free"
      }
    },
    {
      "name": "invoice-1",
      "type": "registry:block",
      "title": "Invoice 1: invoice you can pay",
      "description": "An invoice you can read, print and pay: parties, dates and line items, totals worked out from the lines, a status from the dates (paid, due in N days, overdue by N days) and a Pay now that handles waiting and failure.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/invoice-1/invoice-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/invoice-1/invoice-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "invoice"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "invoice",
          "billing",
          "payment",
          "receipt",
          "bill",
          "line items",
          "tax",
          "pay now",
          "print",
          "accounting"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "An invoice. <Invoice1 invoice={{ number, issued, due, paidOn, from: { name, lines }, to: { name, lines }, lines: [{ id, description, detail, quantity, unitPrice }], discountPercent, taxPercent, note, paymentDetails: [{ label, value }] }} today='2026-10-18' currency='USD' locale onPay={() => Promise} onDownload />. Subtotal, discount, tax and total are worked out from the lines; status is paid (paidOn set or payment succeeded), overdue by N days, or due in N days, from due and today. Pass today yourself; the block never reads the clock. Reject onPay to show its message.",
          "whenToUse": [
            "A customer-facing invoice page or a payment link",
            "An invoice detail in a billing area"
          ],
          "whenNotToUse": [
            "A list of invoices (use a data table)",
            "Changing plans with proration (use billing-2)"
          ],
          "composesWith": [
            "billing-1",
            "billing-2",
            "app-shell-1",
            "settings-5"
          ],
          "a11y": [
            {
              "keys": "Status",
              "action": "A live region that says Paid on a date, Due in N days, or Overdue by N days, with an icon, not only color"
            },
            {
              "keys": "Table",
              "action": "The items are a real table with a caption and column headers; totals are a description list"
            },
            {
              "keys": "Pay now",
              "action": "The button says the amount and shows Paying while busy; a failure is an alert that says no charge was made"
            }
          ],
          "customization": [
            "currency and locale format every amount and date",
            "Print hides the buttons and the card border",
            "Bank details are shown left to right in right-to-left layouts, like any number"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "invoice-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton sheet announced as loading."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "invoice-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert with Try again (onRetry). A failed payment says you were not charged, in place beside Pay now."
          }
        ],
        "examples": [
          "invoice-1-demo",
          "invoice-1-due",
          "invoice-1-paid",
          "invoice-1-loading",
          "invoice-1-error"
        ],
        "url": "https://ui.ballmac.com/components/invoice-1"
      }
    },
    {
      "name": "invoice-1-demo",
      "type": "registry:example",
      "title": "Invoice 1: invoice you can pay: Overdue",
      "description": "Overdue example of Invoice 1: invoice you can pay.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/invoice-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/invoice-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/invoice-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "invoice-1",
        "tier": "free"
      }
    },
    {
      "name": "invoice-1-due",
      "type": "registry:example",
      "title": "Invoice 1: invoice you can pay: Due soon, with tax",
      "description": "Due soon, with tax example of Invoice 1: invoice you can pay.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/invoice-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/invoice-1-due.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/invoice-1-due.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "invoice-1",
        "tier": "free"
      }
    },
    {
      "name": "invoice-1-paid",
      "type": "registry:example",
      "title": "Invoice 1: invoice you can pay: Paid",
      "description": "Paid example of Invoice 1: invoice you can pay.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/invoice-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/invoice-1-paid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/invoice-1-paid.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "invoice-1",
        "tier": "free"
      }
    },
    {
      "name": "invoice-1-loading",
      "type": "registry:example",
      "title": "Invoice 1: invoice you can pay: Loading",
      "description": "Loading example of Invoice 1: invoice you can pay.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/invoice-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/invoice-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/invoice-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "invoice-1",
        "tier": "free"
      }
    },
    {
      "name": "invoice-1-error",
      "type": "registry:example",
      "title": "Invoice 1: invoice you can pay: Could not load",
      "description": "Could not load example of Invoice 1: invoice you can pay.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/invoice-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/invoice-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/invoice-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "invoice-1",
        "tier": "free"
      }
    },
    {
      "name": "kanban-1",
      "type": "registry:block",
      "title": "Kanban 1: project board with drag and keyboard moves",
      "description": "A project board: columns with counts, rich task cards (tags, priority, due date, comments, assignee), drag and drop with a drop indicator, keyboard pick-up and move with announcements, a Move-to menu, quick add and a person filter.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/badge.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/dropdown-menu.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/kanban-1/kanban-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/kanban-1/kanban-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "kanban"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "kanban",
          "board",
          "tasks",
          "drag and drop",
          "project",
          "keyboard"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton with the same shapes as the ready view, an error with retry, and an empty message. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A task board. Pass defaultColumns=[{ id, title, tasks: [{ id, title, tags?, priority?, assignee?, due?, comments? }] }] and onChange(columns).",
          "whenToUse": [
            "Project and sprint boards",
            "Pipelines, hiring and support queues"
          ],
          "whenNotToUse": [
            "A simple list of tasks (use a table)"
          ],
          "composesWith": [
            "app-shell-1",
            "calendar-1",
            "mail-1"
          ],
          "a11y": [
            {
              "keys": "Space or Enter on a card",
              "action": "Picks it up; Arrow keys move it between columns and positions; Space or Enter drops it; Escape puts it back"
            },
            {
              "keys": "Move to menu",
              "action": "Every card has a menu that moves it to any column, for people who don't drag"
            },
            {
              "keys": "Announcements",
              "action": "Each pick-up, move, drop and removal is announced politely"
            }
          ],
          "customization": [
            "defaultColumns and onChange(columns)",
            "height of the board area",
            "priority: low, medium or high",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={r.state} onRetry={r.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "kanban-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton with the same shapes as the ready view, announced as loading; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No cards",
            "example": "kanban-1-no-cards",
            "trigger": "state=\"empty\"",
            "note": "A clear message that there is nothing yet. emptyState sets the copy and can add an action."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "kanban-1-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "kanban-1-demo",
          "kanban-1-simple",
          "kanban-1-loading",
          "kanban-1-error",
          "kanban-1-no-cards"
        ],
        "url": "https://ui.ballmac.com/components/kanban-1"
      }
    },
    {
      "name": "kanban-1-demo",
      "type": "registry:example",
      "title": "Kanban 1: project board with drag and keyboard moves: Default",
      "description": "Default example of Kanban 1: project board with drag and keyboard moves.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kanban-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/kanban-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kanban-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "kanban-1",
        "tier": "free"
      }
    },
    {
      "name": "kanban-1-simple",
      "type": "registry:example",
      "title": "Kanban 1: project board with drag and keyboard moves: Three columns",
      "description": "Three columns example of Kanban 1: project board with drag and keyboard moves.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kanban-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/kanban-1-simple.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kanban-1-simple.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "kanban-1",
        "tier": "free"
      }
    },
    {
      "name": "kanban-1-loading",
      "type": "registry:example",
      "title": "Kanban 1: project board with drag and keyboard moves: Loading",
      "description": "Loading example of Kanban 1: project board with drag and keyboard moves.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kanban-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/kanban-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kanban-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "kanban-1",
        "tier": "free"
      }
    },
    {
      "name": "kanban-1-error",
      "type": "registry:example",
      "title": "Kanban 1: project board with drag and keyboard moves: Could not load",
      "description": "Could not load example of Kanban 1: project board with drag and keyboard moves.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kanban-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/kanban-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kanban-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "kanban-1",
        "tier": "free"
      }
    },
    {
      "name": "kanban-1-no-cards",
      "type": "registry:example",
      "title": "Kanban 1: project board with drag and keyboard moves: No cards",
      "description": "No cards example of Kanban 1: project board with drag and keyboard moves.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kanban-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/kanban-1-no-cards.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kanban-1-no-cards.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "kanban-1",
        "tier": "free"
      }
    },
    {
      "name": "login-1",
      "type": "registry:block",
      "title": "Login 1: card with SSO and magic link",
      "description": "Centered sign-in card: SSO and email-link buttons, an email and password form with remember me, a loading submit and an inline error.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/label.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/login-1/login-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/login-1/login-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "auth"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "login",
          "sign in",
          "auth",
          "form",
          "sso"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (submitting, success, error) to drive the form from your own async code, and defaultValues or defaultEmail to prefill. Fields lock while a request is in flight. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A sign-in screen. Wire onSubmit to your auth (it can be async; the button shows a spinner), pass error to show failures, and onSso/onMagicLink for passwordless options.",
          "whenToUse": [
            "App sign-in pages",
            "Admin or dashboard login"
          ],
          "whenNotToUse": [
            "Sign-up with many fields (build a form from input, label and checkbox)"
          ],
          "composesWith": [
            "footer-1"
          ],
          "a11y": [],
          "customization": [
            "onSubmit({ email, password, remember })",
            "error, onSso, onMagicLink, forgotHref, signupHref props",
            "Pass onSso={null} or onMagicLink={null} to hide that button",
            "state: \"submitting\" | \"success\" | \"error\" (omit it and the form runs by itself); errorState.description sets the failure message. Pair with your own async handler: state={pending ? \"submitting\" : failed ? \"error\" : done ? \"success\" : undefined}"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Signing in",
            "example": "login-1-submitting",
            "trigger": "state=\"submitting\"",
            "note": "Every field and button is disabled while the request is in flight, the button shows a spinner, and the form is marked busy."
          },
          {
            "id": "error",
            "title": "Wrong password",
            "example": "login-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert above the form with the message (errorState.description to change it); the fields stay editable so it can be fixed."
          }
        ],
        "examples": [
          "login-1-demo",
          "login-1-submitting",
          "login-1-error"
        ],
        "url": "https://ui.ballmac.com/components/login-1"
      }
    },
    {
      "name": "login-1-demo",
      "type": "registry:example",
      "title": "Login 1: card with SSO and magic link: Default",
      "description": "Default example of Login 1: card with SSO and magic link.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/login-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/login-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/login-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "login-1",
        "tier": "free"
      }
    },
    {
      "name": "login-1-submitting",
      "type": "registry:example",
      "title": "Login 1: card with SSO and magic link: Signing in",
      "description": "Signing in example of Login 1: card with SSO and magic link.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/login-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/login-1-submitting.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/login-1-submitting.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "login-1",
        "tier": "free"
      }
    },
    {
      "name": "login-1-error",
      "type": "registry:example",
      "title": "Login 1: card with SSO and magic link: Wrong password",
      "description": "Wrong password example of Login 1: card with SSO and magic link.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/login-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/login-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/login-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "login-1",
        "tier": "free"
      }
    },
    {
      "name": "logo-cloud-1",
      "type": "registry:block",
      "title": "Logo Cloud 1: marquee or grid",
      "description": "Customer logos as an endlessly scrolling row with faded edges, or a static grid with hairline dividers. Wordmarks brighten on hover.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/marquee.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/logo-cloud-1/logo-cloud-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/logo-cloud-1/logo-cloud-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "logo-cloud"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "logos",
          "social proof",
          "customers",
          "marquee"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "Social proof strip under a hero. Pass `logos` ({ name, icon? | logo? }[]) with your customers' SVG logos via `logo`; choose variant \"marquee\" or \"grid\".",
          "whenToUse": [
            "Directly under a hero",
            "Near pricing to reassure buyers"
          ],
          "whenNotToUse": [
            "Fewer than four logos (use a single line of text)"
          ],
          "composesWith": [
            "hero-1",
            "hero-2",
            "testimonials-1"
          ],
          "a11y": [],
          "customization": [
            "title, logos, variant props",
            "Marquee speed and gap in the source"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "logo-cloud-1-demo",
          "logo-cloud-1-grid"
        ],
        "url": "https://ui.ballmac.com/components/logo-cloud-1"
      }
    },
    {
      "name": "logo-cloud-1-demo",
      "type": "registry:example",
      "title": "Logo Cloud 1: marquee or grid: Marquee",
      "description": "Marquee example of Logo Cloud 1: marquee or grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/logo-cloud-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/logo-cloud-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/logo-cloud-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "logo-cloud-1",
        "tier": "free"
      }
    },
    {
      "name": "logo-cloud-1-grid",
      "type": "registry:example",
      "title": "Logo Cloud 1: marquee or grid: Grid",
      "description": "Grid example of Logo Cloud 1: marquee or grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/logo-cloud-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/logo-cloud-1-grid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/logo-cloud-1-grid.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "logo-cloud-1",
        "tier": "free"
      }
    },
    {
      "name": "mail-1",
      "type": "registry:block",
      "title": "Mail 1: three-pane inbox",
      "description": "A working inbox: folders with an unread count, a searchable message list with stars and keyboard navigation, a reading pane with archive, delete, mark unread and reply, and a compose dialog. One pane at a time on phones.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/dialog.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/search-field.json",
        "https://ui.ballmac.com/r/select.json",
        "https://ui.ballmac.com/r/textarea.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/mail-1/mail-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/mail-1/mail-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "mail"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "mail",
          "inbox",
          "email",
          "three pane",
          "messages",
          "compose",
          "reply"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (loading, empty, error) with onRetry, emptyState and errorState: a skeleton of the three panes, an error with retry, and an empty mailbox where Compose still works. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "An email client UI. Pass messages=[{ id, folder, from, subject, body[], time, unread?, starred?, attachments? }], me and onSend(to, subject, body); archive, delete, star, read state, search and reply are handled in state.",
          "whenToUse": [
            "Webmail, support inboxes and notification centres",
            "A realistic product screenshot"
          ],
          "whenNotToUse": [
            "Chat (use ai-chat-2 or the chat components)"
          ],
          "composesWith": [
            "app-shell-1",
            "kanban-1",
            "calendar-1"
          ],
          "a11y": [
            {
              "keys": "Arrow Up / Down or J / K",
              "action": "Moves focus between messages; Enter or Space opens one"
            },
            {
              "keys": "Unread",
              "action": "Unread messages say 'Unread' to screen readers as well as being bold with a dot"
            },
            {
              "keys": "Actions",
              "action": "Archive, delete and mark-unread results are announced politely"
            }
          ],
          "customization": [
            "messages, me, height",
            "onSend(to, subject, body)",
            "folders are inbox, sent and archive plus Starred",
            "state: \"ready\" | \"loading\" | \"empty\" | \"error\"; onRetry, emptyState and errorState set the retry action and the copy. Pair with useResource: state={mail.state} messages={mail.data} onRetry={mail.retry}"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "mail-1-loading",
            "trigger": "state=\"loading\"",
            "note": "A skeleton of the three panes, announced as \"Loading messages\"; nothing is clickable."
          },
          {
            "id": "empty",
            "title": "No messages",
            "example": "mail-1-no-messages",
            "trigger": "state=\"empty\"",
            "note": "The real interface over an empty mailbox, so Compose still works. emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "mail-1-error",
            "trigger": "state=\"error\"",
            "note": "An error in the same frame with a Try again button (onRetry), announced as an alert."
          }
        ],
        "examples": [
          "mail-1-demo",
          "mail-1-empty",
          "mail-1-loading",
          "mail-1-error",
          "mail-1-no-messages"
        ],
        "url": "https://ui.ballmac.com/components/mail-1"
      }
    },
    {
      "name": "mail-1-demo",
      "type": "registry:example",
      "title": "Mail 1: three-pane inbox: Default",
      "description": "Default example of Mail 1: three-pane inbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mail-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/mail-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mail-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "mail-1",
        "tier": "free"
      }
    },
    {
      "name": "mail-1-empty",
      "type": "registry:example",
      "title": "Mail 1: three-pane inbox: Empty inbox",
      "description": "Empty inbox example of Mail 1: three-pane inbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mail-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/mail-1-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mail-1-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "mail-1",
        "tier": "free"
      }
    },
    {
      "name": "mail-1-loading",
      "type": "registry:example",
      "title": "Mail 1: three-pane inbox: Loading",
      "description": "Loading example of Mail 1: three-pane inbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mail-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/mail-1-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mail-1-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "mail-1",
        "tier": "free"
      }
    },
    {
      "name": "mail-1-error",
      "type": "registry:example",
      "title": "Mail 1: three-pane inbox: Could not load",
      "description": "Could not load example of Mail 1: three-pane inbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mail-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/mail-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mail-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "mail-1",
        "tier": "free"
      }
    },
    {
      "name": "mail-1-no-messages",
      "type": "registry:example",
      "title": "Mail 1: three-pane inbox: No messages",
      "description": "No messages example of Mail 1: three-pane inbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mail-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/mail-1-no-messages.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mail-1-no-messages.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "mail-1",
        "tier": "free"
      }
    },
    {
      "name": "newsletter-1",
      "type": "registry:block",
      "title": "Newsletter 1: signup with topics and sample issue",
      "description": "An editorial newsletter signup: topic chips, an email field with validation, loading, error and success states, avatar social proof, and a tilted sample issue card beside it.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/newsletter-1/newsletter-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/newsletter-1/newsletter-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "newsletter"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "newsletter",
          "signup",
          "email",
          "subscribe",
          "topics",
          "form"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (submitting, success, error) to drive the form from your own async code, and defaultValues or defaultEmail to prefill. Fields lock while a request is in flight. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A newsletter signup section. Pass topics (or [] for none), proof, issue headlines for the preview card, and onSubmit(email, topics); throw to show an error.",
          "whenToUse": [
            "Blogs, changelogs and docs sites",
            "Anywhere readers choose what to receive"
          ],
          "whenNotToUse": [
            "A waitlist over a dramatic background (use cta-2)"
          ],
          "composesWith": [
            "blog-1",
            "changelog-1",
            "footer-2",
            "faq-2"
          ],
          "a11y": [
            {
              "keys": "Enter / Space on a topic",
              "action": "Toggles it (aria-pressed)"
            },
            {
              "keys": "Submit with a bad address",
              "action": "The error is announced as an alert and linked with aria-describedby"
            }
          ],
          "customization": [
            "topics: [] hides the chips",
            "defaultTopics",
            "issue: { name, number, headlines } for the preview card",
            "onSubmit(email, topics)",
            "state: \"submitting\" | \"success\" | \"error\" (omit it and the form runs by itself); errorState.description sets the failure message. Pair with your own async handler: state={pending ? \"submitting\" : failed ? \"error\" : done ? \"success\" : undefined}"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Subscribing",
            "example": "newsletter-1-subscribing",
            "trigger": "state=\"submitting\"",
            "note": "Every field and button is disabled while the request is in flight, the button shows a spinner, and the form is marked busy."
          },
          {
            "id": "success",
            "title": "Subscribed",
            "example": "newsletter-1-subscribed",
            "trigger": "state=\"success\"",
            "note": "The confirmation screen the flow ends on."
          },
          {
            "id": "error",
            "title": "Could not subscribe",
            "example": "newsletter-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert above the form with the message (errorState.description to change it); the fields stay editable so it can be fixed."
          }
        ],
        "examples": [
          "newsletter-1-demo",
          "newsletter-1-simple",
          "newsletter-1-subscribing",
          "newsletter-1-subscribed",
          "newsletter-1-error"
        ],
        "url": "https://ui.ballmac.com/components/newsletter-1"
      }
    },
    {
      "name": "newsletter-1-demo",
      "type": "registry:example",
      "title": "Newsletter 1: signup with topics and sample issue: Default",
      "description": "Default example of Newsletter 1: signup with topics and sample issue.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/newsletter-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/newsletter-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/newsletter-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "newsletter-1",
        "tier": "free"
      }
    },
    {
      "name": "newsletter-1-simple",
      "type": "registry:example",
      "title": "Newsletter 1: signup with topics and sample issue: Email only",
      "description": "Email only example of Newsletter 1: signup with topics and sample issue.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/newsletter-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/newsletter-1-simple.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/newsletter-1-simple.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "newsletter-1",
        "tier": "free"
      }
    },
    {
      "name": "newsletter-1-subscribing",
      "type": "registry:example",
      "title": "Newsletter 1: signup with topics and sample issue: Subscribing",
      "description": "Subscribing example of Newsletter 1: signup with topics and sample issue.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/newsletter-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/newsletter-1-subscribing.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/newsletter-1-subscribing.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "newsletter-1",
        "tier": "free"
      }
    },
    {
      "name": "newsletter-1-subscribed",
      "type": "registry:example",
      "title": "Newsletter 1: signup with topics and sample issue: Subscribed",
      "description": "Subscribed example of Newsletter 1: signup with topics and sample issue.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/newsletter-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/newsletter-1-subscribed.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/newsletter-1-subscribed.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "newsletter-1",
        "tier": "free"
      }
    },
    {
      "name": "newsletter-1-error",
      "type": "registry:example",
      "title": "Newsletter 1: signup with topics and sample issue: Could not subscribe",
      "description": "Could not subscribe example of Newsletter 1: signup with topics and sample issue.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/newsletter-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/newsletter-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/newsletter-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "newsletter-1",
        "tier": "free"
      }
    },
    {
      "name": "onboarding-1",
      "type": "registry:block",
      "title": "Onboarding 1: workspace setup wizard",
      "description": "A four-step setup wizard with a progress rail: name and address a workspace (auto-filled), pick goals as cards, invite teammates as removable chips, review, then a finish screen. Slides between steps.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react",
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/field.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/onboarding-1/onboarding-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/onboarding-1/onboarding-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "onboarding"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "onboarding",
          "wizard",
          "setup",
          "workspace",
          "steps",
          "invite"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds state (submitting, success, error) to drive the form from your own async code, and defaultValues or defaultEmail to prefill. Fields lock while a request is in flight. Unchanged without state.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "First-run setup after signup. Pass product, domain, goals=[{ id, title, description }] and onComplete(values) with { name, slug, color, goals, invites } (throw to show an error).",
          "whenToUse": [
            "The first screen after signup or verification",
            "Products where a workspace or team has to be created"
          ],
          "whenNotToUse": [
            "A checklist that lives inside the app (use onboarding-checklist)"
          ],
          "composesWith": [
            "signup-1",
            "verify-1",
            "invite-1",
            "app-shell"
          ],
          "a11y": [
            {
              "keys": "Continue / Back",
              "action": "Focus moves to the new step's heading so the change is announced"
            },
            {
              "keys": "Arrow keys on colors",
              "action": "Move between color radios; goals are checkboxes toggled with Space"
            },
            {
              "keys": "Enter in the email field",
              "action": "Adds the address as a removable chip"
            }
          ],
          "customization": [
            "goals: { id, title, description }[]",
            "product, domain, continueHref",
            "onComplete(values) async",
            "state: \"submitting\" | \"success\" | \"error\" (omit it and the form runs by itself); errorState.description sets the failure message. Pair with your own async handler: state={pending ? \"submitting\" : failed ? \"error\" : done ? \"success\" : undefined}"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Creating the workspace",
            "example": "onboarding-1-creating",
            "trigger": "state=\"submitting\"",
            "note": "The review step with its button spinning and the steps locked."
          },
          {
            "id": "success",
            "title": "Workspace ready",
            "example": "onboarding-1-ready",
            "trigger": "state=\"success\"",
            "note": "The confirmation screen the flow ends on."
          },
          {
            "id": "error",
            "title": "Could not create",
            "example": "onboarding-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert above the form with the message (errorState.description to change it); the fields stay editable so it can be fixed."
          }
        ],
        "examples": [
          "onboarding-1-demo",
          "onboarding-1-custom",
          "onboarding-1-creating",
          "onboarding-1-ready",
          "onboarding-1-error"
        ],
        "url": "https://ui.ballmac.com/components/onboarding-1"
      }
    },
    {
      "name": "onboarding-1-demo",
      "type": "registry:example",
      "title": "Onboarding 1: workspace setup wizard: Default",
      "description": "Default example of Onboarding 1: workspace setup wizard.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/onboarding-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/onboarding-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/onboarding-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "onboarding-1",
        "tier": "free"
      }
    },
    {
      "name": "onboarding-1-custom",
      "type": "registry:example",
      "title": "Onboarding 1: workspace setup wizard: Custom goals",
      "description": "Custom goals example of Onboarding 1: workspace setup wizard.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/onboarding-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/onboarding-1-custom.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/onboarding-1-custom.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "onboarding-1",
        "tier": "free"
      }
    },
    {
      "name": "onboarding-1-creating",
      "type": "registry:example",
      "title": "Onboarding 1: workspace setup wizard: Creating the workspace",
      "description": "Creating the workspace example of Onboarding 1: workspace setup wizard.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/onboarding-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/onboarding-1-creating.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/onboarding-1-creating.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "onboarding-1",
        "tier": "free"
      }
    },
    {
      "name": "onboarding-1-ready",
      "type": "registry:example",
      "title": "Onboarding 1: workspace setup wizard: Workspace ready",
      "description": "Workspace ready example of Onboarding 1: workspace setup wizard.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/onboarding-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/onboarding-1-ready.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/onboarding-1-ready.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "onboarding-1",
        "tier": "free"
      }
    },
    {
      "name": "onboarding-1-error",
      "type": "registry:example",
      "title": "Onboarding 1: workspace setup wizard: Could not create",
      "description": "Could not create example of Onboarding 1: workspace setup wizard.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/onboarding-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/onboarding-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/onboarding-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "onboarding-1",
        "tier": "free"
      }
    },
    {
      "name": "pricing-1",
      "type": "registry:block",
      "title": "Pricing 1: two tiers",
      "description": "Two pricing cards side by side with included and excluded features, a highlighted plan with a border beam and badge, and small print.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/badge.json",
        "https://ui.ballmac.com/r/border-beam.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/pricing-1/pricing-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/pricing-1/pricing-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "pricing"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "pricing",
          "plans",
          "saas",
          "tiers"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "Pricing for a free-plus-paid or two-plan product. Pass plans=[{ name, price, period, description, features, cta, featured }].",
          "whenToUse": [
            "Freemium products",
            "Two-plan pricing pages"
          ],
          "whenNotToUse": [
            "Three or more plans side by side"
          ],
          "composesWith": [
            "faq-1",
            "cta-1"
          ],
          "a11y": [],
          "customization": [
            "plans: { name, price, period?, description, features: { label, included }[], cta, featured? }[]",
            "title, description, note props"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "pricing-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/pricing-1"
      }
    },
    {
      "name": "pricing-1-demo",
      "type": "registry:example",
      "title": "Pricing 1: two tiers: Default",
      "description": "Default example of Pricing 1: two tiers.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/pricing-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/pricing-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/pricing-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "pricing-1",
        "tier": "free"
      }
    },
    {
      "name": "reviews-2",
      "type": "registry:block",
      "title": "Reviews 2: ratings with insights",
      "description": "Reviews with the whole picture: the average and the shape of the ratings (which filter the list), what people keep mentioning, and whether the mood is positive. The list follows the star size you choose.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/rating-distribution.json",
        "https://ui.ballmac.com/r/bar-list.json",
        "https://ui.ballmac.com/r/split-bar.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/reviews-2/reviews-2.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/reviews-2/reviews-2.tsx"
        }
      ],
      "categories": [
        "blocks",
        "reviews"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "reviews",
          "ratings",
          "social proof",
          "insights",
          "sentiment",
          "filter",
          "ecommerce",
          "feedback"
        ],
        "version": "1.0.0",
        "updated": "2026-10-24",
        "tests": true,
        "ai": {
          "summary": "Reviews with insights. <Reviews2 title description reviews={[{ id, author, rating, date, title, body, verified?, helpful? }]} counts themes={BarListItem[]} sentiment={SplitSegment[]} />. Counts default to the reviews given. Choosing a star size filters the list and the count is announced politely.",
          "whenToUse": [
            "A product or app page where reviews drive the decision",
            "A review dashboard for the team"
          ],
          "whenNotToUse": [
            "A scrolling quote wall for a landing page; use testimonials-1",
            "Collecting a review; use a form"
          ],
          "composesWith": [
            "analytics-1",
            "testimonials-1",
            "hero-1",
            "pricing-2"
          ],
          "a11y": [
            {
              "keys": "Filter",
              "action": "Each star row is a toggle button named for its count; the list's size is announced"
            },
            {
              "keys": "Reviews",
              "action": "Each is a list item; the star rating is spoken as 'n out of 5 stars'"
            },
            {
              "keys": "Charts",
              "action": "The bars and the mood split repeat numbers shown as text"
            }
          ],
          "customization": [
            "title and description",
            "reviews and counts",
            "themes and sentiment"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "reviews-2-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton summary, list and side panels under the real heading, announced as loading."
          },
          {
            "id": "empty",
            "title": "No reviews yet",
            "example": "reviews-2-empty",
            "trigger": "state=\"empty\"",
            "note": "Says there are no reviews yet; emptyState sets the copy."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "reviews-2-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying nothing was changed, with Try again (onRetry)."
          }
        ],
        "examples": [
          "reviews-2-demo",
          "reviews-2-few",
          "reviews-2-loading",
          "reviews-2-empty",
          "reviews-2-error"
        ],
        "url": "https://ui.ballmac.com/components/reviews-2"
      }
    },
    {
      "name": "reviews-2-demo",
      "type": "registry:example",
      "title": "Reviews 2: ratings with insights: Default",
      "description": "Default example of Reviews 2: ratings with insights.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/reviews-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/reviews-2-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/reviews-2-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "reviews-2",
        "tier": "free"
      }
    },
    {
      "name": "reviews-2-few",
      "type": "registry:example",
      "title": "Reviews 2: ratings with insights: Two reviews",
      "description": "Two reviews example of Reviews 2: ratings with insights.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/reviews-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/reviews-2-few.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/reviews-2-few.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "reviews-2",
        "tier": "free"
      }
    },
    {
      "name": "reviews-2-loading",
      "type": "registry:example",
      "title": "Reviews 2: ratings with insights: Loading",
      "description": "Loading example of Reviews 2: ratings with insights.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/reviews-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/reviews-2-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/reviews-2-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "reviews-2",
        "tier": "free"
      }
    },
    {
      "name": "reviews-2-empty",
      "type": "registry:example",
      "title": "Reviews 2: ratings with insights: No reviews yet",
      "description": "No reviews yet example of Reviews 2: ratings with insights.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/reviews-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/reviews-2-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/reviews-2-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "reviews-2",
        "tier": "free"
      }
    },
    {
      "name": "reviews-2-error",
      "type": "registry:example",
      "title": "Reviews 2: ratings with insights: Could not load",
      "description": "Could not load example of Reviews 2: ratings with insights.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/reviews-2.json"
      ],
      "files": [
        {
          "path": "registry/examples/reviews-2-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/reviews-2-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "reviews-2",
        "tier": "free"
      }
    },
    {
      "name": "settings-4",
      "type": "registry:block",
      "title": "Settings 4: integrations directory",
      "description": "An integrations page: search, category filters, connected ones first, Connect with progress and the reason when it fails, Manage, Disconnect after a confirmation, coming-soon entries and a request link.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/alert-dialog.json",
        "https://ui.ballmac.com/r/badge.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/return-focus.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/settings-4/settings-4.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/settings-4/settings-4.tsx"
        }
      ],
      "categories": [
        "blocks",
        "settings"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "settings",
          "integrations",
          "apps",
          "connect",
          "marketplace",
          "directory",
          "oauth"
        ],
        "version": "1.0.0",
        "updated": "2026-10-17",
        "tests": true,
        "ai": {
          "summary": "An integrations directory. <Settings4 integrations={[{ id, name, description, category, icon, connected, account, comingSoon }]} onConnect={async (id) => accountName} onDisconnect onManage onRequest />. Throw from onConnect to show the reason on the card; categories come from the data.",
          "whenToUse": [
            "The Integrations or Apps page of a SaaS product",
            "Connecting OAuth apps from settings"
          ],
          "whenNotToUse": [
            "A marketing page that shows logos of integrations (use features-3 or logo-cloud-1)",
            "API keys and webhooks for developers (use api-key-field and webhook-card)"
          ],
          "composesWith": [
            "app-shell-1",
            "settings-1",
            "settings-3"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Category filters are toggle buttons; each card's buttons name their integration"
            },
            {
              "keys": "Disconnect",
              "action": "An alert dialog confirms first; focus returns to the page"
            },
            {
              "keys": "Connect",
              "action": "\"Connected\" or the failure reason is announced"
            }
          ],
          "customization": [
            "title, description",
            "Integration icons are any node: your brand marks or lucide icons",
            "Connect usually opens an OAuth popup: resolve when it closes successfully"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "settings-4-loading",
            "trigger": "state=\"loading\"",
            "note": "Skeleton cards; search and the category filter are disabled."
          },
          {
            "id": "empty",
            "title": "No integrations",
            "example": "settings-4-empty",
            "trigger": "state=\"empty\" (or integrations={[]})",
            "note": "A clear message; emptyState can add an action. A search with no matches says so in place."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "settings-4-error",
            "trigger": "state=\"error\"",
            "note": "An alert with Try again (onRetry). A failed Connect shows its reason on that card instead."
          }
        ],
        "examples": [
          "settings-4-demo",
          "settings-4-loading",
          "settings-4-empty",
          "settings-4-error"
        ],
        "url": "https://ui.ballmac.com/components/settings-4"
      }
    },
    {
      "name": "settings-4-demo",
      "type": "registry:example",
      "title": "Settings 4: integrations directory: Default",
      "description": "Default example of Settings 4: integrations directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/settings-4.json"
      ],
      "files": [
        {
          "path": "registry/examples/settings-4-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/settings-4-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "settings-4",
        "tier": "free"
      }
    },
    {
      "name": "settings-4-loading",
      "type": "registry:example",
      "title": "Settings 4: integrations directory: Loading",
      "description": "Loading example of Settings 4: integrations directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/settings-4.json"
      ],
      "files": [
        {
          "path": "registry/examples/settings-4-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/settings-4-loading.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "settings-4",
        "tier": "free"
      }
    },
    {
      "name": "settings-4-empty",
      "type": "registry:example",
      "title": "Settings 4: integrations directory: No integrations",
      "description": "No integrations example of Settings 4: integrations directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/settings-4.json"
      ],
      "files": [
        {
          "path": "registry/examples/settings-4-empty.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/settings-4-empty.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "settings-4",
        "tier": "free"
      }
    },
    {
      "name": "settings-4-error",
      "type": "registry:example",
      "title": "Settings 4: integrations directory: Could not load",
      "description": "Could not load example of Settings 4: integrations directory.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/settings-4.json"
      ],
      "files": [
        {
          "path": "registry/examples/settings-4-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/settings-4-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "settings-4",
        "tier": "free"
      }
    },
    {
      "name": "stats-1",
      "type": "registry:block",
      "title": "Stats 1: headline metrics with trends",
      "description": "Four large numbers in a hairline grid that count up on scroll, each with a change badge, a small trend line and one line of context. Heading and copy sit above.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/number-ticker.json",
        "https://ui.ballmac.com/r/sparkline.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/stats-1/stats-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/stats-1/stats-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "stats"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "stats",
          "metrics",
          "numbers",
          "social proof",
          "sparkline"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Social proof as numbers. Pass stats=[{ label, value, prefix?, suffix?, decimals?, delta?, trend?, trendLabel?, note? }].",
          "whenToUse": [
            "Under a hero or logo cloud as proof",
            "Company and about pages"
          ],
          "whenNotToUse": [
            "Live product dashboards (use stat-card or kpi-row)",
            "Numbers you cannot back up"
          ],
          "composesWith": [
            "hero-7",
            "logo-cloud-1",
            "testimonials-2",
            "cta-1"
          ],
          "a11y": [],
          "customization": [
            "stats: omit trend and delta for a plain numbers layout",
            "decimals controls the digits after the point; suffix can be %, k, M+ and so on"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "stats-1-demo",
          "stats-1-simple"
        ],
        "url": "https://ui.ballmac.com/components/stats-1"
      }
    },
    {
      "name": "stats-1-demo",
      "type": "registry:example",
      "title": "Stats 1: headline metrics with trends: Default",
      "description": "Default example of Stats 1: headline metrics with trends.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/stats-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/stats-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/stats-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "stats-1",
        "tier": "free"
      }
    },
    {
      "name": "stats-1-simple",
      "type": "registry:example",
      "title": "Stats 1: headline metrics with trends: Numbers only",
      "description": "Numbers only example of Stats 1: headline metrics with trends.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/stats-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/stats-1-simple.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/stats-1-simple.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "stats-1",
        "tier": "free"
      }
    },
    {
      "name": "team-1",
      "type": "registry:block",
      "title": "Team 1: portrait grid with hover bios",
      "description": "A grid of team portraits with name, role, location and links. On hover or keyboard focus a bio slides up over the photo; phones show it inline. Initial tiles when there is no photo.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/team-1/team-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/team-1/team-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "team"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "team",
          "people",
          "about",
          "company",
          "portraits"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "ai": {
          "summary": "An About-page team section. Pass members=[{ name, role, bio?, location?, image?, links? }].",
          "whenToUse": [
            "About and careers pages",
            "Showing the humans behind a product"
          ],
          "whenNotToUse": [
            "Long staff directories (use a table)"
          ],
          "composesWith": [
            "stats-1",
            "testimonials-2",
            "cta-1",
            "footer-1"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focusing a member's link reveals their bio, like hover"
            }
          ],
          "customization": [
            "members: { name, role, bio?, location?, image?, links?: { label, href, icon? }[] }[]",
            "action: link beside the heading (null to hide)"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "team-1-demo",
          "team-1-small"
        ],
        "url": "https://ui.ballmac.com/components/team-1"
      }
    },
    {
      "name": "team-1-demo",
      "type": "registry:example",
      "title": "Team 1: portrait grid with hover bios: Default",
      "description": "Default example of Team 1: portrait grid with hover bios.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/team-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/team-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/team-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "team-1",
        "tier": "free"
      }
    },
    {
      "name": "team-1-small",
      "type": "registry:example",
      "title": "Team 1: portrait grid with hover bios: Four people",
      "description": "Four people example of Team 1: portrait grid with hover bios.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/team-1.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/team-1-small.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/team-1-small.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "team-1",
        "tier": "free"
      }
    },
    {
      "name": "testimonials-1",
      "type": "registry:block",
      "title": "Testimonials 1: scrolling wall of quotes",
      "description": "A wall of testimonial cards in three columns that scroll at different speeds in opposite directions, pausing on hover, with a plain list on phones.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/marquee.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/testimonials-1/testimonials-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/testimonials-1/testimonials-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "testimonials"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "testimonials",
          "social proof",
          "quotes",
          "marquee"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "Social proof section: pass `testimonials` ({ quote, name, role }[]); they are spread across three vertical marquees. Replace the placeholder quotes with real ones.",
          "whenToUse": [
            "Landing pages after features or pricing",
            "Showing many short quotes without a carousel"
          ],
          "whenNotToUse": [
            "One or two quotes (use a single large quote in a section)"
          ],
          "composesWith": [
            "features-1",
            "pricing-1",
            "cta-1"
          ],
          "a11y": [],
          "customization": [
            "eyebrow, title, description, testimonials props",
            "Column speed and direction are set per column in the source"
          ]
        },
        "statesNone": "Static content: nothing to load, submit or fail.",
        "examples": [
          "testimonials-1-demo"
        ],
        "url": "https://ui.ballmac.com/components/testimonials-1"
      }
    },
    {
      "name": "testimonials-1-demo",
      "type": "registry:example",
      "title": "Testimonials 1: scrolling wall of quotes: Default",
      "description": "Default example of Testimonials 1: scrolling wall of quotes.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/testimonials-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/testimonials-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/testimonials-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "testimonials-1",
        "tier": "free"
      }
    },
    {
      "name": "waitlist-1",
      "type": "registry:block",
      "title": "Waitlist 1: referral waitlist",
      "description": "A launch waitlist that grows by referral: an email form with a count of who is waiting, then the person's place in line, their own share link to copy, and a ladder of rewards that fills as friends join.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/copy-button.json",
        "https://ui.ballmac.com/r/cover-art.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/number-ticker.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blocks/waitlist-1/waitlist-1.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/blocks/waitlist-1/waitlist-1.tsx"
        }
      ],
      "categories": [
        "blocks",
        "waitlist"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "waitlist",
          "launch",
          "referral",
          "early access",
          "signup",
          "invite",
          "viral",
          "coming soon",
          "pre-launch"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "A referral waitlist. <Waitlist1 product='Acme' waiting={2431} rewards={[{ at: 3, title, description }]} onJoin={(email) => Promise<{ position, link, referrals }>} defaultJoined state />. After joining it shows #position, the share link with a copy button, and rewards that unlock as referrals reaches each at. Reject onJoin to show its message with the email kept.",
          "whenToUse": [
            "A pre-launch landing page that collects emails",
            "Rolling out access in waves with referral rewards"
          ],
          "whenNotToUse": [
            "A newsletter signup (use newsletter-1)",
            "A full sign-up form (use auth blocks)"
          ],
          "composesWith": [
            "hero-1",
            "faq-1",
            "footer-1",
            "logo-cloud-1"
          ],
          "a11y": [
            {
              "keys": "Submit",
              "action": "An invalid email is announced as an alert and linked to the field; a failed join keeps the email"
            },
            {
              "keys": "After joining",
              "action": "Focus moves to the place in line, which is read as 'Number 1,284' with the message to follow"
            },
            {
              "keys": "Rewards",
              "action": "Each step says in words whether it is unlocked or how many more friends it needs"
            }
          ],
          "customization": [
            "rewards: any number of steps by friends needed",
            "The share link and text are built for email and X; swap in your own channels",
            "The link is shown left to right even in right-to-left layouts, like any address"
          ]
        },
        "states": [
          {
            "id": "submitting",
            "title": "Joining",
            "example": "waitlist-1-sending",
            "trigger": "state=\"submitting\"",
            "note": "The field and button are disabled, the button says Joining with a spinner and the section is marked busy."
          },
          {
            "id": "success",
            "title": "On the list",
            "example": "waitlist-1-joined",
            "trigger": "state=\"success\"",
            "note": "The second screen: place in line, share link and the reward ladder."
          },
          {
            "id": "error",
            "title": "Could not join",
            "example": "waitlist-1-error",
            "trigger": "state=\"error\"",
            "note": "An alert saying the email is still there; the person can press Join again."
          }
        ],
        "examples": [
          "waitlist-1-demo",
          "waitlist-1-joined",
          "waitlist-1-sending",
          "waitlist-1-error"
        ],
        "url": "https://ui.ballmac.com/components/waitlist-1"
      }
    },
    {
      "name": "waitlist-1-demo",
      "type": "registry:example",
      "title": "Waitlist 1: referral waitlist: Join form",
      "description": "Join form example of Waitlist 1: referral waitlist.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/waitlist-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/waitlist-1-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/waitlist-1-demo.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "waitlist-1",
        "tier": "free"
      }
    },
    {
      "name": "waitlist-1-joined",
      "type": "registry:example",
      "title": "Waitlist 1: referral waitlist: On the list",
      "description": "On the list example of Waitlist 1: referral waitlist.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/waitlist-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/waitlist-1-joined.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/waitlist-1-joined.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "waitlist-1",
        "tier": "free"
      }
    },
    {
      "name": "waitlist-1-sending",
      "type": "registry:example",
      "title": "Waitlist 1: referral waitlist: Joining",
      "description": "Joining example of Waitlist 1: referral waitlist.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/waitlist-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/waitlist-1-sending.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/waitlist-1-sending.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "waitlist-1",
        "tier": "free"
      }
    },
    {
      "name": "waitlist-1-error",
      "type": "registry:example",
      "title": "Waitlist 1: referral waitlist: Could not join",
      "description": "Could not join example of Waitlist 1: referral waitlist.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/waitlist-1.json"
      ],
      "files": [
        {
          "path": "registry/examples/waitlist-1-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/waitlist-1-error.tsx"
        }
      ],
      "categories": [
        "blocks"
      ],
      "meta": {
        "example": true,
        "of": "waitlist-1",
        "tier": "free"
      }
    },
    {
      "name": "blur-fade",
      "type": "registry:ui",
      "title": "Blur Fade",
      "description": "A wrapper that fades content in while it unblurs and slides a few pixels, once it scrolls into view, with a group that staggers its children.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/blur-fade.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/blur-fade.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "fade",
          "blur",
          "reveal",
          "scroll",
          "stagger"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "Wrap anything in <BlurFade delay direction offset blur inView once>. <BlurFadeGroup stagger> wraps each child and staggers them. Shows content instantly under reduced motion.",
          "whenToUse": [
            "Hero and section intros",
            "Lists and cards that should arrive in sequence"
          ],
          "whenNotToUse": [
            "Text that should animate letter by letter (text-animate)",
            "Content that must be visible without JavaScript before hydration"
          ],
          "composesWith": [
            "text-animate",
            "bento-grid",
            "card"
          ],
          "a11y": [
            {
              "keys": "Reduced motion",
              "action": "Content appears at once with no blur or travel"
            },
            {
              "keys": "Screen readers",
              "action": "Content is in the DOM from the start; only opacity, blur and position change"
            }
          ],
          "customization": [
            "direction: up | down | left | right | none",
            "offset and blur amounts",
            "inView, once, delay, duration",
            "BlurFadeGroup stagger and item settings"
          ]
        },
        "examples": [
          "blur-fade-demo",
          "blur-fade-directions"
        ],
        "url": "https://ui.ballmac.com/components/blur-fade"
      }
    },
    {
      "name": "blur-fade-demo",
      "type": "registry:example",
      "title": "Blur Fade: Staggered page intro",
      "description": "Staggered page intro example of Blur Fade.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blur-fade.json"
      ],
      "files": [
        {
          "path": "registry/examples/blur-fade-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blur-fade-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "blur-fade",
        "tier": "free"
      }
    },
    {
      "name": "blur-fade-directions",
      "type": "registry:example",
      "title": "Blur Fade: Directions and blur",
      "description": "Directions and blur example of Blur Fade.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/blur-fade.json"
      ],
      "files": [
        {
          "path": "registry/examples/blur-fade-directions.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/blur-fade-directions.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "blur-fade",
        "tier": "free"
      }
    },
    {
      "name": "border-beam",
      "type": "registry:ui",
      "title": "Border Beam",
      "description": "A short beam of light that travels around the inside edge of its parent's border at a constant speed. Decorative, token-colored, hidden under reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/border-beam.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/border-beam.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "border",
          "glow",
          "highlight",
          "decorative",
          "motion"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Decorative loops hold still when the theme turns ambient motion off (and under reduced motion), via useLoopsPaused. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Drop <BorderBeam /> as the last child of any element with position: relative and a border radius; it inherits the radius and draws only in a borderWidth-thick ring (aria-hidden, pointer-events-none). Renders a span, so it is valid inside buttons.",
          "whenToUse": [
            "Drawing attention to one highlighted card, such as the recommended pricing plan",
            "Marking a live or running state on a panel (an agent working, a deploy in progress)",
            "A featured call-to-action button"
          ],
          "whenNotToUse": [
            "Several elements on the same screen; one beam per view",
            "Communicating status on its own (pair it with text; it is hidden under reduced motion)"
          ],
          "composesWith": [
            "spotlight-card",
            "button",
            "magnetic-button"
          ],
          "a11y": [],
          "customization": [
            "duration (s per lap, default 8), delay, reverse",
            "size: beam length in px (default 80); borderWidth: ring thickness in px (default 1)",
            "colorFrom / colorTo: any CSS color, default var(--ring) fading out; try var(--chart-2)",
            "Two beams with delay={duration / 2} give an opposed pair; className=\"-inset-px\" moves the ring onto a 1px parent border",
            "Needs CSS offset-path rect() (Chrome 116, Firefox 122, Safari 17.2); older browsers simply don't show the beam"
          ]
        },
        "source": {
          "name": "Magic UI Border Beam",
          "url": "https://github.com/magicuidesign/magicui",
          "license": "MIT",
          "copyright": "Copyright (c) Magic UI",
          "modified": true
        },
        "examples": [
          "border-beam-demo",
          "border-beam-button"
        ],
        "url": "https://ui.ballmac.com/components/border-beam"
      }
    },
    {
      "name": "border-beam-demo",
      "type": "registry:example",
      "title": "Border Beam: Card",
      "description": "Card example of Border Beam.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/border-beam.json"
      ],
      "files": [
        {
          "path": "registry/examples/border-beam-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/border-beam-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "border-beam",
        "tier": "free"
      }
    },
    {
      "name": "border-beam-button",
      "type": "registry:example",
      "title": "Border Beam: Button",
      "description": "Button example of Border Beam.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/border-beam.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/border-beam-button.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/border-beam-button.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "border-beam",
        "tier": "free"
      }
    },
    {
      "name": "breadcrumb",
      "type": "registry:ui",
      "title": "Breadcrumb",
      "description": "A compact navigation trail with truncation, semantic current page, and visible keyboard focus.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/breadcrumb.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/breadcrumb.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "navigation",
          "hierarchy",
          "links"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A compact navigation trail with truncation, semantic current page, and visible keyboard focus.",
          "whenToUse": [
            "Show a location inside a deep hierarchy",
            "Provide a way back to parent sections"
          ],
          "whenNotToUse": [
            "Use tabs for switching peer views"
          ],
          "composesWith": [
            "pagination"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "moves among breadcrumb links"
            }
          ],
          "customization": [
            "aria-label: name the navigation landmark"
          ]
        },
        "source": {
          "name": "shadcn/ui Breadcrumb",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "breadcrumb-demo",
          "breadcrumb-states"
        ],
        "url": "https://ui.ballmac.com/components/breadcrumb"
      }
    },
    {
      "name": "breadcrumb-demo",
      "type": "registry:example",
      "title": "Breadcrumb: Overview",
      "description": "Overview example of Breadcrumb.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/breadcrumb.json"
      ],
      "files": [
        {
          "path": "registry/examples/breadcrumb-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/breadcrumb-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "breadcrumb",
        "tier": "free"
      }
    },
    {
      "name": "breadcrumb-states",
      "type": "registry:example",
      "title": "Breadcrumb: States and variants",
      "description": "States and variants example of Breadcrumb.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/breadcrumb.json"
      ],
      "files": [
        {
          "path": "registry/examples/breadcrumb-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/breadcrumb-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "breadcrumb",
        "tier": "free"
      }
    },
    {
      "name": "button-group",
      "type": "registry:ui",
      "title": "Button Group",
      "description": "Join adjacent actions into one compact control surface while retaining each button's visible keyboard focus and accessible name.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/button-group.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/button-group.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "buttons",
          "actions",
          "toolbar"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Groups closely related actions without turning them into a selection widget.",
          "whenToUse": [
            "Adjacent document or editor actions",
            "Compact controls with one shared boundary"
          ],
          "whenNotToUse": [
            "Mutually exclusive options; use toggle-group",
            "Unrelated actions"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves between each button in document order"
            },
            {
              "keys": "Enter / Space",
              "action": "Activates the focused button"
            }
          ],
          "customization": [
            "orientation: horizontal | vertical",
            "button and text parts"
          ]
        },
        "examples": [
          "button-group-demo",
          "button-group-states"
        ],
        "url": "https://ui.ballmac.com/components/button-group"
      }
    },
    {
      "name": "button-group-demo",
      "type": "registry:example",
      "title": "Button Group: Document actions",
      "description": "Document actions example of Button Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/button-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/button-group-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/button-group-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "button-group",
        "tier": "free"
      }
    },
    {
      "name": "button-group-states",
      "type": "registry:example",
      "title": "Button Group: Orientations",
      "description": "Orientations example of Button Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/button-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/button-group-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/button-group-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "button-group",
        "tier": "free"
      }
    },
    {
      "name": "button",
      "type": "registry:ui",
      "title": "Button",
      "description": "A button with six variants, three sizes, a pill shape and a built-in loading state. buttonVariants() styles links the same way.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/button.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/button.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "button",
          "cta",
          "loading",
          "radix"
        ],
        "version": "1.0.4",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.0.4",
            "date": "2026-10-12",
            "note": "Every size honours the platform feel's smallest touch target (--bm-target-min): 44 px under the iOS feel, no change otherwise.",
            "breaking": false
          },
          {
            "version": "1.0.3",
            "date": "2026-10-12",
            "note": "A loading button keeps its label in the accessibility tree (opacity instead of visibility), so a busy button still has a name.",
            "breaking": false
          },
          {
            "version": "1.0.2",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "The base action control. Use variant for emphasis, size for density, and loading while an async action runs.",
          "whenToUse": [
            "Primary and secondary actions",
            "Form submit buttons",
            "Links that should look like buttons (className={buttonVariants()} on an <a>)"
          ],
          "whenNotToUse": [
            "Navigation inside running text (use a link)",
            "Toggling state (use a switch or toggle)"
          ],
          "composesWith": [
            "kbd",
            "tooltip"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Activates the button"
            },
            {
              "keys": "Tab",
              "action": "Moves focus to the button"
            }
          ],
          "customization": [
            "variant: default | secondary | outline | ghost | link | destructive",
            "size: sm | default | lg | icon | icon-sm",
            "shape: default | pill"
          ]
        },
        "source": {
          "name": "shadcn/ui Button",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "button-demo",
          "button-variants",
          "button-loading"
        ],
        "url": "https://ui.ballmac.com/components/button"
      }
    },
    {
      "name": "button-demo",
      "type": "registry:example",
      "title": "Button: Default",
      "description": "Default example of Button.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/button-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/button-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "button",
        "tier": "free"
      }
    },
    {
      "name": "button-variants",
      "type": "registry:example",
      "title": "Button: Variants",
      "description": "Variants example of Button.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/button-variants.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/button-variants.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "button",
        "tier": "free"
      }
    },
    {
      "name": "button-loading",
      "type": "registry:example",
      "title": "Button: Loading",
      "description": "Loading example of Button.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/button-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/button-loading.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "button",
        "tier": "free"
      }
    },
    {
      "name": "calendar",
      "type": "registry:ui",
      "title": "Calendar",
      "description": "A date grid for one day, several days or a range, with month and year selects, week numbers, disabled rules and range-end styling, on React DayPicker.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "react-day-picker@^9",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/calendar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/calendar.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "date",
          "calendar",
          "range",
          "day-picker"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "React DayPicker reads the current time for today. That now happens inside Suspense, with a same-size placeholder in the prerendered page, so it builds with Cache Components (the Next.js 16.4 default). Pass today to skip the boundary.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Use mode single, multiple or range with selected and onSelect. All DayPicker props work: disabled, numberOfMonths, captionLayout dropdown, locale.",
          "whenToUse": [
            "Choosing a date or range inside a card or popover",
            "Booking and scheduling",
            "Showing availability with disabled days"
          ],
          "whenNotToUse": [
            "A date field in a form; use date-picker",
            "Typing a range with inputs; use date-range-picker"
          ],
          "composesWith": [
            "popover",
            "date-picker",
            "button"
          ],
          "a11y": [
            {
              "keys": "Arrow keys",
              "action": "Move between days"
            },
            {
              "keys": "PageUp / PageDown",
              "action": "Previous or next month; with Shift, previous or next year"
            },
            {
              "keys": "Home / End",
              "action": "First or last day of the week"
            },
            {
              "keys": "Enter / Space",
              "action": "Selects the focused day"
            }
          ],
          "customization": [
            "mode: single | multiple | range",
            "captionLayout dropdown with startMonth and endMonth",
            "disabled rules and max selection",
            "bordered surface",
            "footer text"
          ]
        },
        "source": {
          "name": "shadcn/ui Calendar",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "calendar-demo",
          "calendar-states"
        ],
        "url": "https://ui.ballmac.com/components/calendar"
      }
    },
    {
      "name": "calendar-demo",
      "type": "registry:example",
      "title": "Calendar: Date range",
      "description": "Date range example of Calendar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar.json"
      ],
      "dependencies": [
        "react-day-picker@^9"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "calendar",
        "tier": "free"
      }
    },
    {
      "name": "calendar-states",
      "type": "registry:example",
      "title": "Calendar: Dropdowns and multiple",
      "description": "Dropdowns and multiple example of Calendar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/calendar.json"
      ],
      "files": [
        {
          "path": "registry/examples/calendar-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/calendar-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "calendar",
        "tier": "free"
      }
    },
    {
      "name": "callout",
      "type": "registry:ui",
      "title": "Callout",
      "description": "An editorial guidance panel with a clear kind label, icon, title, and optional action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/callout.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/callout.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "guidance",
          "tip",
          "note"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "An editorial guidance panel with a clear kind label, icon, title, and optional action.",
          "whenToUse": [
            "Add contextual guidance to docs or settings",
            "Explain a recommended next step"
          ],
          "whenNotToUse": [
            "Use alert for urgent system feedback"
          ],
          "composesWith": [
            "alert",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focus an optional action"
            }
          ],
          "customization": [
            "kind: tip | note | caution",
            "Action slot and content"
          ]
        },
        "examples": [
          "callout-demo",
          "callout-states"
        ],
        "url": "https://ui.ballmac.com/components/callout"
      }
    },
    {
      "name": "callout-demo",
      "type": "registry:example",
      "title": "Callout: Overview",
      "description": "Overview example of Callout.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/callout.json"
      ],
      "files": [
        {
          "path": "registry/examples/callout-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/callout-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "callout",
        "tier": "free"
      }
    },
    {
      "name": "callout-states",
      "type": "registry:example",
      "title": "Callout: States and variants",
      "description": "States and variants example of Callout.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/callout.json"
      ],
      "files": [
        {
          "path": "registry/examples/callout-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/callout-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "callout",
        "tier": "free"
      }
    },
    {
      "name": "card",
      "type": "registry:ui",
      "title": "Card",
      "description": "A composable content surface with compact spacing, an action slot, and optional interactive feedback.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/card.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/card.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "surface",
          "panel",
          "dashboard"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-29",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A composable content surface with compact spacing, an action slot, and optional interactive feedback.",
          "whenToUse": [
            "Group a related set of content and actions",
            "Present a dashboard metric or settings panel"
          ],
          "whenNotToUse": [
            "Use an alert for status messages"
          ],
          "composesWith": [
            "button",
            "badge"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "reaches controls and links inside the card"
            }
          ],
          "customization": [
            "size: default | sm",
            "interactive: emphasize cards with controls"
          ]
        },
        "source": {
          "name": "shadcn/ui Card",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "card-demo",
          "card-states"
        ],
        "url": "https://ui.ballmac.com/components/card"
      }
    },
    {
      "name": "card-demo",
      "type": "registry:example",
      "title": "Card: Overview",
      "description": "Overview example of Card.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/card.json",
        "https://ui.ballmac.com/r/badge.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/card-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/card-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "card",
        "tier": "free"
      }
    },
    {
      "name": "card-states",
      "type": "registry:example",
      "title": "Card: States and variants",
      "description": "States and variants example of Card.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/card.json"
      ],
      "files": [
        {
          "path": "registry/examples/card-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/card-states.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "card",
        "tier": "free"
      }
    },
    {
      "name": "chart",
      "type": "registry:ui",
      "title": "Chart",
      "description": "Theme-aware chart wrapper for Recharts with token colors, a styled tooltip and legend, a named figure with a screen-reader summary, and keyboard navigation.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "recharts@^3"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/chart.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/chart.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chart",
          "recharts",
          "graph",
          "data"
        ],
        "version": "1.1.0",
        "updated": "2026-10-18",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-18",
            "note": "Adds ChartCenterLabel and a `format` prop on ChartContainer, groups tooltip numbers by the locale (useLocale) and looks a series up by what `nameKey` points at first, which fixes pie legends. No prop was removed.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Wrap any Recharts chart in ChartContainer with a config of label and color per series. Use ChartTooltipContent and ChartLegendContent. Always pass label and summary.",
          "whenToUse": [
            "Dashboards and reports",
            "Trends, comparisons and proportions"
          ],
          "whenNotToUse": [
            "A tiny inline trend; use sparkline",
            "A single ring value; use progress-ring"
          ],
          "composesWith": [
            "card",
            "stat-card"
          ],
          "a11y": [
            {
              "keys": "Arrow keys",
              "action": "Move between data points (accessibilityLayer)"
            },
            {
              "keys": "Screen readers",
              "action": "Read the figure name and summary"
            }
          ],
          "customization": [
            "config colors via chart tokens",
            "tooltip indicator: dot | line | dashed",
            "legend content",
            "summary text for assistive tech"
          ]
        },
        "source": {
          "name": "shadcn/ui Chart",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "chart-demo",
          "chart-bars",
          "chart-donut"
        ],
        "url": "https://ui.ballmac.com/components/chart"
      }
    },
    {
      "name": "chart-demo",
      "type": "registry:example",
      "title": "Chart: Revenue area chart",
      "description": "Revenue area chart example of Chart.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chart.json"
      ],
      "dependencies": [
        "recharts@^3"
      ],
      "files": [
        {
          "path": "registry/examples/chart-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chart-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "chart",
        "tier": "free"
      }
    },
    {
      "name": "chart-bars",
      "type": "registry:example",
      "title": "Chart: Grouped bars",
      "description": "Grouped bars example of Chart.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chart.json"
      ],
      "dependencies": [
        "recharts@^3"
      ],
      "files": [
        {
          "path": "registry/examples/chart-bars.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chart-bars.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "chart",
        "tier": "free"
      }
    },
    {
      "name": "chart-donut",
      "type": "registry:example",
      "title": "Chart: Donut",
      "description": "Donut example of Chart.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/chart.json"
      ],
      "dependencies": [
        "recharts@^3"
      ],
      "files": [
        {
          "path": "registry/examples/chart-donut.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/chart-donut.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "chart",
        "tier": "free"
      }
    },
    {
      "name": "checkbox",
      "type": "registry:ui",
      "title": "Checkbox",
      "description": "A Radix checkbox with checked and indeterminate (mixed) states, a check or minus icon, focus ring and invalid styling, for forms and select-all lists.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/checkbox.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/checkbox.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "checkbox",
          "form",
          "indeterminate",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Switch track, thumb travel, and checkbox and radio size follow the platform feel tokens (--bm-switch-*, --bm-check-size); select and command surfaces take the feel's frosting. Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Binary or tri-state choice. Pass checked=\"indeterminate\" for a parent row whose children are partly selected; aria-checked becomes \"mixed\". Pair with Label via id/htmlFor.",
          "whenToUse": [
            "Agreeing to terms or opting into emails",
            "Multi-select lists and table row selection",
            "A select-all control that reflects partial selection"
          ],
          "whenNotToUse": [
            "Settings that apply immediately (use switch)",
            "Choosing exactly one option from several (use a radio group or select)"
          ],
          "composesWith": [
            "label",
            "button"
          ],
          "a11y": [
            {
              "keys": "Space",
              "action": "Toggles the checkbox"
            },
            {
              "keys": "Tab",
              "action": "Moves focus to the checkbox"
            }
          ],
          "customization": [
            "checked: boolean | \"indeterminate\"; onCheckedChange receives the new state",
            "aria-invalid=\"true\" for errors",
            "Inherits the peer class so a following Label dims when disabled"
          ]
        },
        "source": {
          "name": "shadcn/ui Checkbox",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "checkbox-demo",
          "checkbox-indeterminate"
        ],
        "url": "https://ui.ballmac.com/components/checkbox"
      }
    },
    {
      "name": "checkbox-demo",
      "type": "registry:example",
      "title": "Checkbox: Default",
      "description": "Default example of Checkbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/checkbox-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/checkbox-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "checkbox",
        "tier": "free"
      }
    },
    {
      "name": "checkbox-indeterminate",
      "type": "registry:example",
      "title": "Checkbox: Select all",
      "description": "Select all example of Checkbox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/checkbox-indeterminate.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/checkbox-indeterminate.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "checkbox",
        "tier": "free"
      }
    },
    {
      "name": "collapsible",
      "type": "registry:ui",
      "title": "Collapsible",
      "description": "A single disclosure panel with a generous trigger, visible open state, and reduced-motion-aware content transition.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/collapsible.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/collapsible.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "disclosure",
          "details",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Reveals one optional section of information with a keyboard-accessible disclosure trigger.",
          "whenToUse": [
            "Advanced settings",
            "Supporting detail in a dense card"
          ],
          "whenNotToUse": [
            "Several related disclosures; use accordion",
            "Primary content that should always be visible"
          ],
          "composesWith": [
            "card"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Opens or closes the disclosure"
            },
            {
              "keys": "Tab",
              "action": "Moves into visible content"
            }
          ],
          "customization": [
            "controlled or uncontrolled open state",
            "optional trigger chevron"
          ]
        },
        "examples": [
          "collapsible-demo",
          "collapsible-states"
        ],
        "url": "https://ui.ballmac.com/components/collapsible"
      }
    },
    {
      "name": "collapsible-demo",
      "type": "registry:example",
      "title": "Collapsible: Release details",
      "description": "Release details example of Collapsible.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/collapsible.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/collapsible-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/collapsible-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "collapsible",
        "tier": "free"
      }
    },
    {
      "name": "collapsible-states",
      "type": "registry:example",
      "title": "Collapsible: Controlled disclosure",
      "description": "Controlled disclosure example of Collapsible.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/collapsible.json"
      ],
      "files": [
        {
          "path": "registry/examples/collapsible-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/collapsible-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "collapsible",
        "tier": "free"
      }
    },
    {
      "name": "color-picker",
      "type": "registry:ui",
      "title": "Color Picker",
      "description": "A native color chooser paired with an editable hex field and a live swatch.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/color-picker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/color-picker.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "color",
          "picker",
          "hex"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A native color chooser paired with an editable hex field and a live swatch.",
          "whenToUse": [
            "Choose a custom brand or annotation color",
            "Edit a color precisely by hexadecimal value"
          ],
          "whenNotToUse": [
            "Use theme tokens for application chrome"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves between color and text inputs"
            },
            {
              "keys": "Enter",
              "action": "Accepts a native color selection"
            }
          ],
          "customization": [
            "value / defaultValue and onValueChange",
            "name: form field name"
          ]
        },
        "examples": [
          "color-picker-demo",
          "color-picker-states"
        ],
        "url": "https://ui.ballmac.com/components/color-picker"
      }
    },
    {
      "name": "color-picker-demo",
      "type": "registry:example",
      "title": "Color Picker: Overview",
      "description": "Overview example of Color Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/color-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/color-picker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/color-picker-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "color-picker",
        "tier": "free"
      }
    },
    {
      "name": "color-picker-states",
      "type": "registry:example",
      "title": "Color Picker: States and variants",
      "description": "States and variants example of Color Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/color-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/color-picker-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/color-picker-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "color-picker",
        "tier": "free"
      }
    },
    {
      "name": "combobox",
      "type": "registry:ui",
      "title": "Combobox",
      "description": "A searchable single-choice select with groups, descriptions, keywords, clearable value, invalid state and hidden-input form submission.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/command.json",
        "https://ui.ballmac.com/r/popover.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/combobox.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/combobox.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "select",
          "search",
          "autocomplete",
          "form"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Pass options with value and label. It opens a filterable list; the trigger is a combobox button that submits through name.",
          "whenToUse": [
            "Choosing from more than about seven options",
            "Time zones, countries, users and frameworks"
          ],
          "whenNotToUse": [
            "Short lists; use select or radio-group",
            "Choosing several values; use multi-select"
          ],
          "composesWith": [
            "field",
            "command",
            "popover"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the list from the trigger"
            },
            {
              "keys": "Type",
              "action": "Filters options; matches value, label and keywords"
            },
            {
              "keys": "ArrowUp / ArrowDown / Enter",
              "action": "Moves and selects"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            }
          ],
          "customization": [
            "options with group, icon, description and keywords",
            "clearable",
            "invalid",
            "name for native form submission"
          ]
        },
        "examples": [
          "combobox-demo",
          "combobox-states"
        ],
        "url": "https://ui.ballmac.com/components/combobox"
      }
    },
    {
      "name": "combobox-demo",
      "type": "registry:example",
      "title": "Combobox: Framework picker",
      "description": "Framework picker example of Combobox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/combobox.json",
        "https://ui.ballmac.com/r/field.json"
      ],
      "files": [
        {
          "path": "registry/examples/combobox-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/combobox-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "combobox",
        "tier": "free"
      }
    },
    {
      "name": "combobox-states",
      "type": "registry:example",
      "title": "Combobox: Groups and states",
      "description": "Groups and states example of Combobox.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/combobox.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/combobox-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/combobox-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "combobox",
        "tier": "free"
      }
    },
    {
      "name": "command-bar",
      "type": "registry:ui",
      "title": "Command Bar",
      "description": "A command palette with pages: a search-field style trigger, grouped commands, drill-in pages with a breadcrumb, Backspace to go back and a footer of key hints.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/command.json",
        "https://ui.ballmac.com/r/kbd.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/command-bar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/command-bar.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "command palette",
          "search",
          "pages",
          "keyboard"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "groups: {heading, items:[{id,label,icon,shortcut,keywords,onSelect,pages}]}. An item with pages opens a second page. hotkey toggles with Cmd/Ctrl; trigger={false} hides the button.",
          "whenToUse": [
            "Global quick actions and navigation",
            "Apps with many commands and sub-choices"
          ],
          "whenNotToUse": [
            "A macOS-style launcher; use spotlight-search",
            "Choosing one value in a form; use combobox"
          ],
          "composesWith": [
            "command",
            "kbd",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Cmd/Ctrl+K",
              "action": "Toggles the bar"
            },
            {
              "keys": "Type",
              "action": "Filters commands"
            },
            {
              "keys": "ArrowUp / ArrowDown / Enter",
              "action": "Moves and runs"
            },
            {
              "keys": "Backspace on an empty field",
              "action": "Goes back one page"
            },
            {
              "keys": "Escape",
              "action": "Closes"
            }
          ],
          "customization": [
            "hotkey",
            "trigger text or false",
            "pages for nested choices",
            "controlled open"
          ]
        },
        "examples": [
          "command-bar-demo",
          "command-bar-states"
        ],
        "url": "https://ui.ballmac.com/components/command-bar"
      }
    },
    {
      "name": "command-bar-demo",
      "type": "registry:example",
      "title": "Command Bar: Global commands",
      "description": "Global commands example of Command Bar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/command-bar.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/command-bar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/command-bar-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "command-bar",
        "tier": "free"
      }
    },
    {
      "name": "command-bar-states",
      "type": "registry:example",
      "title": "Command Bar: Own trigger",
      "description": "Own trigger example of Command Bar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/command-bar.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/command-bar-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/command-bar-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "command-bar",
        "tier": "free"
      }
    },
    {
      "name": "command",
      "type": "registry:ui",
      "title": "Command",
      "description": "A filterable command list on cmdk, inline or in a Cmd/Ctrl+K dialog, with groups, shortcuts, descriptions, loading state and page-safe scrolling.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "cmdk@^1",
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/command.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/command.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "command palette",
          "search",
          "cmdk",
          "keyboard"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Switch track, thumb travel, and checkbox and radio size follow the platform feel tokens (--bm-switch-*, --bm-check-size); select and command surfaces take the feel's frosting. Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Compose Command, CommandInput, CommandList, CommandGroup and CommandItem. CommandDialog adds the modal and the ⌘K hotkey.",
          "whenToUse": [
            "Command palettes and quick switchers",
            "Searchable action lists",
            "The list inside a combobox"
          ],
          "whenNotToUse": [
            "macOS-style launcher visuals; use spotlight-search",
            "A simple select; use select"
          ],
          "composesWith": [
            "popover",
            "dialog",
            "kbd"
          ],
          "a11y": [
            {
              "keys": "Type",
              "action": "Filters the list"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves the highlighted item"
            },
            {
              "keys": "Enter",
              "action": "Runs the highlighted item"
            },
            {
              "keys": "Cmd/Ctrl+K",
              "action": "Toggles CommandDialog"
            },
            {
              "keys": "Escape",
              "action": "Closes the dialog"
            }
          ],
          "customization": [
            "hotkey key or false",
            "filter and shouldFilter from cmdk",
            "item description and selected check",
            "CommandLoading for async results"
          ]
        },
        "source": {
          "name": "shadcn/ui Command",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "command-demo",
          "command-dialog"
        ],
        "url": "https://ui.ballmac.com/components/command"
      }
    },
    {
      "name": "command-demo",
      "type": "registry:example",
      "title": "Command: Inline menu",
      "description": "Inline menu example of Command.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/command.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/command-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/command-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "command",
        "tier": "free"
      }
    },
    {
      "name": "command-dialog",
      "type": "registry:example",
      "title": "Command: Cmd+K dialog",
      "description": "Cmd+K dialog example of Command.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/command.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/kbd.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/command-dialog.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/command-dialog.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "command",
        "tier": "free"
      }
    },
    {
      "name": "container-scroll",
      "type": "registry:ui",
      "title": "Container Scroll",
      "description": "A showcase frame that starts tilted back in 3D and flattens to face the reader as it scrolls into view, with a title that lifts alongside.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/container-scroll.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/container-scroll.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "3d",
          "scroll",
          "hero",
          "showcase"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "<ContainerScroll title={...}>{screenshot or live demo}</ContainerScroll>. tilt sets the starting angle; container tracks a scrollable element.",
          "whenToUse": [
            "Product hero sections",
            "Showing a dashboard or app screenshot"
          ],
          "whenNotToUse": [
            "Content that must stay flat and readable at all times",
            "Pages that scroll inside nested containers without passing container"
          ],
          "composesWith": [
            "browser-frame",
            "sticky-scroll",
            "bento-grid"
          ],
          "a11y": [
            {
              "keys": "Reduced motion",
              "action": "The frame is flat from the start, with no transform"
            },
            {
              "keys": "Content",
              "action": "Children stay real, selectable, focusable content"
            }
          ],
          "customization": [
            "tilt",
            "title slot",
            "frameClassName",
            "container"
          ]
        },
        "examples": [
          "container-scroll-demo",
          "container-scroll-states"
        ],
        "url": "https://ui.ballmac.com/components/container-scroll"
      }
    },
    {
      "name": "container-scroll-demo",
      "type": "registry:example",
      "title": "Container Scroll: Product showcase",
      "description": "Product showcase example of Container Scroll.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/container-scroll.json"
      ],
      "files": [
        {
          "path": "registry/examples/container-scroll-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/container-scroll-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "container-scroll",
        "tier": "free"
      }
    },
    {
      "name": "container-scroll-states",
      "type": "registry:example",
      "title": "Container Scroll: Steeper tilt",
      "description": "Steeper tilt example of Container Scroll.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/container-scroll.json"
      ],
      "files": [
        {
          "path": "registry/examples/container-scroll-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/container-scroll-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "container-scroll",
        "tier": "free"
      }
    },
    {
      "name": "context-menu",
      "type": "registry:ui",
      "title": "Context Menu",
      "description": "A right-click, long-press and Shift+F10 menu with submenus, checkbox and radio items, shortcut hints and a destructive style, built on Radix.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/context-menu.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/context-menu.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "menu",
          "right-click",
          "overlay",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Shows actions at the pointer on right-click or long-press. Keyboard users open it with Shift+F10 or the Menu key on a focusable trigger.",
          "whenToUse": [
            "File, card and canvas actions",
            "Secondary actions that also exist elsewhere",
            "Desktop-style apps"
          ],
          "whenNotToUse": [
            "The only way to reach an action; menus must be discoverable, so also offer a dropdown-menu button",
            "Touch-first layouts without a visible trigger"
          ],
          "composesWith": [
            "dropdown-menu",
            "card"
          ],
          "a11y": [
            {
              "keys": "Right-click / long-press",
              "action": "Opens the menu at the pointer"
            },
            {
              "keys": "Shift+F10 / Menu key",
              "action": "Opens it from a focused trigger"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves between items"
            },
            {
              "keys": "ArrowRight / ArrowLeft",
              "action": "Opens and closes a submenu"
            },
            {
              "keys": "Escape",
              "action": "Closes the menu"
            }
          ],
          "customization": [
            "destructive item style",
            "give the trigger tabIndex 0 and a label so it is keyboard reachable",
            "checkbox and radio items"
          ]
        },
        "source": {
          "name": "shadcn/ui Context Menu",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "context-menu-demo",
          "context-menu-states"
        ],
        "url": "https://ui.ballmac.com/components/context-menu"
      }
    },
    {
      "name": "context-menu-demo",
      "type": "registry:example",
      "title": "Context Menu: File actions",
      "description": "File actions example of Context Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/context-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/context-menu-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/context-menu-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "context-menu",
        "tier": "free"
      }
    },
    {
      "name": "context-menu-states",
      "type": "registry:example",
      "title": "Context Menu: View options",
      "description": "View options example of Context Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/context-menu.json"
      ],
      "files": [
        {
          "path": "registry/examples/context-menu-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/context-menu-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "context-menu",
        "tier": "free"
      }
    },
    {
      "name": "copy-button",
      "type": "registry:ui",
      "title": "Copy Button",
      "description": "A copy-to-clipboard button with a morphing check icon, an optional label, a fallback for blocked clipboards, an error state and a polite announcement.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12",
        "lucide-react",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/copy-button.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/copy-button.tsx"
        }
      ],
      "categories": [
        "developer"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "copy",
          "clipboard",
          "button",
          "developer"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "Pass value (or getValue for content read at click time). label adds visible text, variant is ghost | outline | solid, size sm | default | lg. Falls back to execCommand when navigator.clipboard is blocked and shows 'Copy failed' if both fail.",
          "whenToUse": [
            "Any value a developer will paste: keys, URLs, commands, IDs",
            "Toolbars on code, logs and config"
          ],
          "whenNotToUse": [
            "Copying a whole code block with a header (code-block has its own button)"
          ],
          "composesWith": [
            "code-block",
            "api-key-field",
            "terminal"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Copies and confirms"
            },
            {
              "keys": "Screen readers",
              "action": "Name changes to 'Copied' and a polite status announces it; failures say 'Copy failed'"
            },
            {
              "keys": "Reduced motion",
              "action": "The icon swaps with a fade only"
            }
          ],
          "customization": [
            "variant",
            "size",
            "label and copiedLabel",
            "getValue for async or dynamic text",
            "resetAfter",
            "onCopied / onError"
          ]
        },
        "examples": [
          "copy-button-demo",
          "copy-button-inline"
        ],
        "url": "https://ui.ballmac.com/components/copy-button"
      }
    },
    {
      "name": "copy-button-demo",
      "type": "registry:example",
      "title": "Copy Button: Icon, label and variants",
      "description": "Icon, label and variants example of Copy Button.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/copy-button.json"
      ],
      "files": [
        {
          "path": "registry/examples/copy-button-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/copy-button-demo.tsx"
        }
      ],
      "categories": [
        "developer"
      ],
      "meta": {
        "example": true,
        "of": "copy-button",
        "tier": "free"
      }
    },
    {
      "name": "copy-button-inline",
      "type": "registry:example",
      "title": "Copy Button: Inline with a value",
      "description": "Inline with a value example of Copy Button.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/copy-button.json"
      ],
      "files": [
        {
          "path": "registry/examples/copy-button-inline.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/copy-button-inline.tsx"
        }
      ],
      "categories": [
        "developer"
      ],
      "meta": {
        "example": true,
        "of": "copy-button",
        "tier": "free"
      }
    },
    {
      "name": "countdown",
      "type": "registry:ui",
      "title": "Countdown",
      "description": "An SSR-safe timer with controlled or local seconds, pause support, and a completion announcement.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/countdown.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/countdown.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "timer",
          "countdown",
          "time"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "An SSR-safe timer with controlled or local seconds, pause support, and a completion announcement.",
          "whenToUse": [
            "Show time until a short event",
            "Display a temporary offer or session limit"
          ],
          "whenNotToUse": [
            "Use progress for work completion"
          ],
          "composesWith": [
            "progress-ring"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Timer is labelled; completion is announced"
            }
          ],
          "customization": [
            "Controlled or uncontrolled seconds",
            "Pause and completion callback"
          ]
        },
        "examples": [
          "countdown-demo",
          "countdown-states"
        ],
        "url": "https://ui.ballmac.com/components/countdown"
      }
    },
    {
      "name": "countdown-demo",
      "type": "registry:example",
      "title": "Countdown: Overview",
      "description": "Overview example of Countdown.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/countdown.json"
      ],
      "files": [
        {
          "path": "registry/examples/countdown-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/countdown-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "countdown",
        "tier": "free"
      }
    },
    {
      "name": "countdown-states",
      "type": "registry:example",
      "title": "Countdown: States and variants",
      "description": "States and variants example of Countdown.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/countdown.json"
      ],
      "files": [
        {
          "path": "registry/examples/countdown-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/countdown-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "countdown",
        "tier": "free"
      }
    },
    {
      "name": "cover-art",
      "type": "registry:ui",
      "title": "Cover Art",
      "description": "Cover pictures drawn from a seed in your theme's chart colors: color fields, rings, bars, dots or waves. The same seed always draws the same picture, so an item without an image still looks finished.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/cover-art.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/cover-art.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "cover",
          "artwork",
          "generative",
          "placeholder",
          "avatar",
          "thumbnail",
          "gradient",
          "seed"
        ],
        "version": "1.0.0",
        "updated": "2026-10-17",
        "tests": true,
        "ai": {
          "summary": "<CoverArt seed={project.id} /> fills its parent with a picture chosen and drawn from the seed; variant: 'mesh' | 'rings' | 'bars' | 'dots' | 'waves' | 'auto'; grid adds a faint grid. Put it in a sized container (an aspect-video div, a size-10 rounded avatar). It is decorative and hidden from screen readers, so keep the item's name as text next to it.",
          "whenToUse": [
            "The fallback for a card, channel, project or agent that has no image",
            "A profile cover or a thumbnail while images load"
          ],
          "whenNotToUse": [
            "A real photograph or logo (use media)",
            "An animated hero background (use aurora-background or beams-background)"
          ],
          "composesWith": [
            "media",
            "card",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Decorative: aria-hidden, no focus. Never the only way to tell items apart."
            }
          ],
          "customization": [
            "seed picks the picture and the chart colors it uses, so a theme change recolors every picture",
            "className sets size and corners: <CoverArt seed={id} className=\"aspect-video rounded-xl\" />",
            "Use it as the fallback of Media: <Media media={cover} fallback={<CoverArt seed={id} />} fill />"
          ]
        },
        "examples": [
          "cover-art-demo",
          "cover-art-seeds"
        ],
        "url": "https://ui.ballmac.com/components/cover-art"
      }
    },
    {
      "name": "cover-art-demo",
      "type": "registry:example",
      "title": "Cover Art: Five pictures",
      "description": "Five pictures example of Cover Art.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cover-art.json"
      ],
      "files": [
        {
          "path": "registry/examples/cover-art-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cover-art-demo.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "cover-art",
        "tier": "free"
      }
    },
    {
      "name": "cover-art-seeds",
      "type": "registry:example",
      "title": "Cover Art: One per name",
      "description": "One per name example of Cover Art.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/cover-art.json"
      ],
      "files": [
        {
          "path": "registry/examples/cover-art-seeds.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/cover-art-seeds.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "cover-art",
        "tier": "free"
      }
    },
    {
      "name": "currency-input",
      "type": "registry:ui",
      "title": "Currency Input",
      "description": "A locale-aware money field that formats on blur while keeping editing and caret behavior simple.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/currency-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/currency-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "currency",
          "money",
          "input"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A locale-aware money field that formats on blur while keeping editing and caret behavior simple.",
          "whenToUse": [
            "Collect prices, budgets, or payment amounts"
          ],
          "whenNotToUse": [
            "Use Number Input for unitless quantities"
          ],
          "composesWith": [
            "number-input"
          ],
          "a11y": [
            {
              "keys": "Tab / typing",
              "action": "Enters a numeric amount and formats it on blur"
            }
          ],
          "customization": [
            "Controlled and uncontrolled value",
            "Tokens and state styling"
          ]
        },
        "examples": [
          "currency-input-demo",
          "currency-input-states"
        ],
        "url": "https://ui.ballmac.com/components/currency-input"
      }
    },
    {
      "name": "currency-input-demo",
      "type": "registry:example",
      "title": "Currency Input: Overview",
      "description": "Overview example of Currency Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/currency-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/currency-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/currency-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "currency-input",
        "tier": "free"
      }
    },
    {
      "name": "currency-input-states",
      "type": "registry:example",
      "title": "Currency Input: States and variants",
      "description": "States and variants example of Currency Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/currency-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/currency-input-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/currency-input-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "currency-input",
        "tier": "free"
      }
    },
    {
      "name": "date-picker",
      "type": "registry:ui",
      "title": "Date Picker",
      "description": "A button that opens a calendar popover to choose one date, with presets, month and year selects, min and max dates, clearing, invalid state and form submission.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/calendar.json",
        "https://ui.ballmac.com/r/popover.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/date-picker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/date-picker.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "date",
          "input",
          "popover",
          "form"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "The dates for the year dropdown are worked out only when the popover opens, so a page with a date picker prerenders with Cache Components (the Next.js 16.4 default). Nothing else changes.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Give it a defaultValue or value and onValueChange. presets add quick picks, dropdowns adds month and year selects, name submits YYYY-MM-DD.",
          "whenToUse": [
            "A single date in a form",
            "Deadlines, birthdays and delivery dates",
            "When quick picks like Tomorrow help"
          ],
          "whenNotToUse": [
            "A date range; use date-range-picker",
            "An always-visible calendar; use calendar"
          ],
          "composesWith": [
            "field",
            "calendar",
            "popover"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the calendar from the trigger"
            },
            {
              "keys": "Arrow keys",
              "action": "Move between days"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            }
          ],
          "customization": [
            "presets",
            "dropdowns for distant dates",
            "minDate and maxDate",
            "format (Intl options) and locale",
            "clearable and invalid"
          ]
        },
        "examples": [
          "date-picker-demo",
          "date-picker-states"
        ],
        "url": "https://ui.ballmac.com/components/date-picker"
      }
    },
    {
      "name": "date-picker-demo",
      "type": "registry:example",
      "title": "Date Picker: Delivery date with presets",
      "description": "Delivery date with presets example of Date Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/date-picker.json",
        "https://ui.ballmac.com/r/field.json"
      ],
      "files": [
        {
          "path": "registry/examples/date-picker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/date-picker-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "date-picker",
        "tier": "free"
      }
    },
    {
      "name": "date-picker-states",
      "type": "registry:example",
      "title": "Date Picker: Birthday, invalid, disabled",
      "description": "Birthday, invalid, disabled example of Date Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/date-picker.json",
        "https://ui.ballmac.com/r/field.json"
      ],
      "files": [
        {
          "path": "registry/examples/date-picker-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/date-picker-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "date-picker",
        "tier": "free"
      }
    },
    {
      "name": "date-range-picker",
      "type": "registry:ui",
      "title": "Date Range Picker",
      "description": "Two native date controls with inclusive range correction and quick-select presets.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/date-range-picker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/date-range-picker.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "date",
          "range",
          "calendar"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Two native date controls with inclusive range correction and quick-select presets.",
          "whenToUse": [
            "Pick report or booking date windows"
          ],
          "whenNotToUse": [
            "Use Date Picker for one date"
          ],
          "composesWith": [
            "time-picker"
          ],
          "a11y": [
            {
              "keys": "Tab / Arrow keys",
              "action": "Edits native date fields and activates presets"
            }
          ],
          "customization": [
            "Controlled and uncontrolled value",
            "Tokens and state styling"
          ]
        },
        "examples": [
          "date-range-picker-demo",
          "date-range-picker-states"
        ],
        "url": "https://ui.ballmac.com/components/date-range-picker"
      }
    },
    {
      "name": "date-range-picker-demo",
      "type": "registry:example",
      "title": "Date Range Picker: Overview",
      "description": "Overview example of Date Range Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/date-range-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/date-range-picker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/date-range-picker-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "date-range-picker",
        "tier": "free"
      }
    },
    {
      "name": "date-range-picker-states",
      "type": "registry:example",
      "title": "Date Range Picker: States and variants",
      "description": "States and variants example of Date Range Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/date-range-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/date-range-picker-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/date-range-picker-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "date-range-picker",
        "tier": "free"
      }
    },
    {
      "name": "dialog",
      "type": "registry:ui",
      "title": "Dialog",
      "description": "A Radix modal dialog with a blurred overlay, centered card surface that fits 360 px screens, header and footer parts, optional close button and animations.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "devDependencies": [
        "tw-animate-css"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/dialog.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/dialog.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "dialog",
          "modal",
          "overlay",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "Modal window that traps focus. Compose Dialog > DialogTrigger (style it with buttonVariants) + DialogContent with DialogHeader (DialogTitle, DialogDescription) and DialogFooter; use DialogClose with buttonVariants for cancel buttons. Avoid asChild so the files also work in Base UI projects.",
          "whenToUse": [
            "Short forms that shouldn't leave the page (edit profile, rename)",
            "Confirming destructive actions",
            "Focused detail views"
          ],
          "whenNotToUse": [
            "Non-blocking messages (use a toast)",
            "Long multi-step flows (use a page)",
            "Content tied to a control that should stay visible (use a popover)"
          ],
          "composesWith": [
            "button",
            "input",
            "label",
            "textarea",
            "select"
          ],
          "a11y": [
            {
              "keys": "Escape",
              "action": "Closes the dialog"
            },
            {
              "keys": "Tab / Shift+Tab",
              "action": "Cycles focus inside the dialog"
            },
            {
              "keys": "Enter / Space on trigger",
              "action": "Opens the dialog"
            }
          ],
          "customization": [
            "showCloseButton (default true) and closeLabel for the X button",
            "DialogContent max-w-lg by default; override with className",
            "Always include a DialogTitle (use a sr-only class to hide it visually)",
            "Needs the tw-animate-css classes for the open and close animation"
          ]
        },
        "source": {
          "name": "shadcn/ui Dialog",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "dialog-demo",
          "dialog-confirm"
        ],
        "url": "https://ui.ballmac.com/components/dialog"
      }
    },
    {
      "name": "dialog-demo",
      "type": "registry:example",
      "title": "Dialog: Edit profile",
      "description": "Edit profile example of Dialog.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dialog.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/dialog-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dialog-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "dialog",
        "tier": "free"
      }
    },
    {
      "name": "dialog-confirm",
      "type": "registry:example",
      "title": "Dialog: Confirm",
      "description": "Confirm example of Dialog.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dialog.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/dialog-confirm.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dialog-confirm.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "dialog",
        "tier": "free"
      }
    },
    {
      "name": "drawer",
      "type": "registry:ui",
      "title": "Drawer",
      "description": "A swipe-to-dismiss panel from any edge on Vaul, with grab handle, header, scrollable body and footer, drag-safe inner content and reduced-motion handling.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "vaul@^1"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/drawer.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/drawer.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "overlay",
          "mobile",
          "bottom sheet",
          "vaul"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Bottom drawers suit mobile actions; use direction left or right for side panels. Compose DrawerHeader, DrawerBody and DrawerFooter.",
          "whenToUse": [
            "Mobile-first confirmations and pickers",
            "Panels users may want to flick away"
          ],
          "whenNotToUse": [
            "Desktop settings panels; use sheet",
            "Critical confirmations; use alert-dialog"
          ],
          "composesWith": [
            "button",
            "sheet"
          ],
          "a11y": [
            {
              "keys": "Tab / Shift+Tab",
              "action": "Cycles focus inside the drawer"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            },
            {
              "keys": "Drag / swipe",
              "action": "Dismisses by gesture"
            }
          ],
          "customization": [
            "direction",
            "snapPoints",
            "dismissible",
            "handle visibility"
          ]
        },
        "source": {
          "name": "shadcn/ui Drawer",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "drawer-demo",
          "drawer-states"
        ],
        "url": "https://ui.ballmac.com/components/drawer"
      }
    },
    {
      "name": "drawer-demo",
      "type": "registry:example",
      "title": "Drawer: Order review",
      "description": "Order review example of Drawer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/drawer.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/drawer-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/drawer-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "drawer",
        "tier": "free"
      }
    },
    {
      "name": "drawer-states",
      "type": "registry:example",
      "title": "Drawer: Four directions",
      "description": "Four directions example of Drawer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/drawer.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/drawer-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/drawer-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "drawer",
        "tier": "free"
      }
    },
    {
      "name": "dropdown-menu",
      "type": "registry:ui",
      "title": "Dropdown Menu",
      "description": "An action menu on a trigger with checkbox and radio items, submenus, shortcut hints and destructive rows, built on Radix for full keyboard and typeahead support.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/dropdown-menu.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/dropdown-menu.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "menu",
          "overlay",
          "actions",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Opens a menu of actions from a button. Supports groups, labels, checkbox and radio items, nested submenus, shortcuts and a destructive style.",
          "whenToUse": [
            "Account, row and overflow (…) actions",
            "Sort and view preferences with radio items",
            "Menus with a submenu or checked options"
          ],
          "whenNotToUse": [
            "Choosing a form value; use select or combobox",
            "Right-click menus; use context-menu",
            "A persistent app menu bar; use menubar"
          ],
          "composesWith": [
            "button",
            "kbd"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the menu from the trigger"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves between items; Home and End jump"
            },
            {
              "keys": "Type a letter",
              "action": "Jumps to the next item starting with it"
            },
            {
              "keys": "ArrowRight / ArrowLeft",
              "action": "Opens and closes a submenu"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            }
          ],
          "customization": [
            "destructive item style",
            "inset alignment for mixed icon rows",
            "alignment and side offset on the content",
            "controlled open state"
          ]
        },
        "source": {
          "name": "shadcn/ui Dropdown Menu",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "dropdown-menu-demo",
          "dropdown-menu-states"
        ],
        "url": "https://ui.ballmac.com/components/dropdown-menu"
      }
    },
    {
      "name": "dropdown-menu-demo",
      "type": "registry:example",
      "title": "Dropdown Menu: Account menu",
      "description": "Account menu example of Dropdown Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dropdown-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/dropdown-menu-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dropdown-menu-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "dropdown-menu",
        "tier": "free"
      }
    },
    {
      "name": "dropdown-menu-states",
      "type": "registry:example",
      "title": "Dropdown Menu: Radio choices",
      "description": "Radio choices example of Dropdown Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/dropdown-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/dropdown-menu-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/dropdown-menu-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "dropdown-menu",
        "tier": "free"
      }
    },
    {
      "name": "emoji-picker",
      "type": "registry:ui",
      "title": "Emoji Picker",
      "description": "An emoji picker that loads its data on first use: search by name or word, jump between groups, pick a skin tone, recent emoji, a real ARIA grid with arrow keys, and any language from Emojibase.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "emojibase-data@^18",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/emoji-picker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/emoji-picker.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "emoji",
          "picker",
          "reactions",
          "chat",
          "search",
          "skin tone",
          "grid"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "<EmojiPicker onSelect={(e) => insert(e.emoji)} />. It loads English emoji on first use. For another language pass loadEmojis that returns fromEmojibase(compact, groups) for that language. Wrap it in a popover for a button.",
          "whenToUse": [
            "Chat, comments and reactions where people add emoji",
            "A reaction bar's \"more\" menu",
            "Any text field that needs an emoji button"
          ],
          "whenNotToUse": [
            "A fixed handful of reactions; show buttons instead",
            "Inserting images or stickers",
            "Custom emoji sets; map them into the same EmojiData and pass loadEmojis"
          ],
          "composesWith": [
            "popover",
            "textarea",
            "mention-input",
            "rich-text-editor"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Search, group buttons, the grid (one tab stop) and the skin tones are separate stops"
            },
            {
              "keys": "Arrow keys",
              "action": "Move across the grid and into the next group; left and right swap in right-to-left"
            },
            {
              "keys": "Home / End / Ctrl+Home / Ctrl+End",
              "action": "Start and end of the row, and of the whole grid"
            },
            {
              "keys": "Enter / Space",
              "action": "Choose the emoji"
            },
            {
              "keys": "Arrow Down in search",
              "action": "Moves to the first result"
            },
            {
              "keys": "Screen readers",
              "action": "Each emoji is a button named in the picker's language; results found and the chosen emoji are announced"
            }
          ],
          "customization": [
            "columns, height, autoFocus",
            "skinTone and onSkinToneChange to hold the tone yourself",
            "recent and storageKey, or recent={false}",
            "loadEmojis for another language or your own emoji"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "emoji-picker-loading",
            "trigger": "while the emoji data loads",
            "note": "A grid of skeletons under a disabled search box, announced as loading. The data is fetched the first time the picker is shown."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "emoji-picker-error",
            "trigger": "loadEmojis rejects",
            "note": "An error with a Try again button that loads the emoji again, announced as an alert."
          }
        ],
        "source": {
          "name": "Emojibase",
          "url": "https://github.com/milesj/emojibase",
          "license": "MIT",
          "copyright": "Copyright (c) 2017-2019 Miles Johnson",
          "modified": true
        },
        "examples": [
          "emoji-picker-demo",
          "emoji-picker-popover",
          "emoji-picker-german",
          "emoji-picker-loading",
          "emoji-picker-error"
        ],
        "url": "https://ui.ballmac.com/components/emoji-picker"
      }
    },
    {
      "name": "emoji-picker-demo",
      "type": "registry:example",
      "title": "Emoji Picker: Picker",
      "description": "Picker example of Emoji Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/emoji-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/emoji-picker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/emoji-picker-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "emoji-picker",
        "tier": "free"
      }
    },
    {
      "name": "emoji-picker-popover",
      "type": "registry:example",
      "title": "Emoji Picker: In a popover, inserting into text",
      "description": "In a popover, inserting into text example of Emoji Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/emoji-picker.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/popover.json",
        "https://ui.ballmac.com/r/textarea.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/emoji-picker-popover.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/emoji-picker-popover.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "emoji-picker",
        "tier": "free"
      }
    },
    {
      "name": "emoji-picker-german",
      "type": "registry:example",
      "title": "Emoji Picker: German",
      "description": "German example of Emoji Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/emoji-picker.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/examples/emoji-picker-german.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/emoji-picker-german.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "emoji-picker",
        "tier": "free"
      }
    },
    {
      "name": "emoji-picker-loading",
      "type": "registry:example",
      "title": "Emoji Picker: Loading",
      "description": "Loading example of Emoji Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/emoji-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/emoji-picker-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/emoji-picker-loading.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "emoji-picker",
        "tier": "free"
      }
    },
    {
      "name": "emoji-picker-error",
      "type": "registry:example",
      "title": "Emoji Picker: Could not load",
      "description": "Could not load example of Emoji Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/emoji-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/emoji-picker-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/emoji-picker-error.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "emoji-picker",
        "tier": "free"
      }
    },
    {
      "name": "empty-state",
      "type": "registry:ui",
      "title": "Empty State",
      "description": "A ready-to-use empty screen with guidance and primary and secondary action slots.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "https://ui.ballmac.com/r/empty.json",
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/empty-state.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/empty-state.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "empty",
          "placeholder",
          "action"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A ready-to-use empty screen with guidance and primary and secondary action slots.",
          "whenToUse": [
            "Explain an empty collection",
            "Offer a clear first action"
          ],
          "whenNotToUse": [
            "Use empty for a custom composition"
          ],
          "composesWith": [
            "empty",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter",
              "action": "Focus and activate supplied actions"
            }
          ],
          "customization": [
            "Compact layout",
            "Icon and actions"
          ]
        },
        "examples": [
          "empty-state-demo",
          "empty-state-states"
        ],
        "url": "https://ui.ballmac.com/components/empty-state"
      }
    },
    {
      "name": "empty-state-demo",
      "type": "registry:example",
      "title": "Empty State: Overview",
      "description": "Overview example of Empty State.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/empty-state.json"
      ],
      "files": [
        {
          "path": "registry/examples/empty-state-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/empty-state-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "empty-state",
        "tier": "free"
      }
    },
    {
      "name": "empty-state-states",
      "type": "registry:example",
      "title": "Empty State: States and variants",
      "description": "States and variants example of Empty State.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/empty-state.json"
      ],
      "files": [
        {
          "path": "registry/examples/empty-state-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/empty-state-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "empty-state",
        "tier": "free"
      }
    },
    {
      "name": "empty",
      "type": "registry:ui",
      "title": "Empty",
      "description": "A responsive empty-state surface with media, concise guidance, and a dedicated action area.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/empty.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/empty.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "empty",
          "placeholder",
          "state"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A responsive empty-state surface with media, concise guidance, and a dedicated action area.",
          "whenToUse": [
            "Explain why a list has no content",
            "Give the next step after a search yields no results"
          ],
          "whenNotToUse": [
            "Use a skeleton while loading"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "reaches actions in the empty state"
            }
          ],
          "customization": [
            "compact: reduce vertical padding"
          ]
        },
        "source": {
          "name": "shadcn/ui Empty",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "empty-demo",
          "empty-states"
        ],
        "url": "https://ui.ballmac.com/components/empty"
      }
    },
    {
      "name": "empty-demo",
      "type": "registry:example",
      "title": "Empty: Overview",
      "description": "Overview example of Empty.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/empty.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/empty-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/empty-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "empty",
        "tier": "free"
      }
    },
    {
      "name": "empty-states",
      "type": "registry:example",
      "title": "Empty: States and variants",
      "description": "States and variants example of Empty.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/empty.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/empty-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/empty-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "empty",
        "tier": "free"
      }
    },
    {
      "name": "feel-auto",
      "type": "registry:ui",
      "title": "Feel Auto",
      "description": "Picks the platform feel for you: macOS, iOS, Windows or web, from the device, before the first paint. All four feels are included and a user's override is remembered.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/feel-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/feel-script.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/feel-script.tsx"
        }
      ],
      "cssVars": {
        "theme": {
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        }
      },
      "css": {
        "[data-feel=\"web\"]": {
          "--radius": "0.625rem",
          "--bm-speed": "1",
          "--bm-bounce": "0.25",
          "--bm-travel": "1",
          "--bm-hover": "1",
          "--bm-stagger": "1",
          "--bm-ambient": "1",
          "--bm-ambient-state": "running",
          "--bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "--bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "--bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "--bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "--bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "--bm-duration-base": "calc(220ms / var(--bm-speed))",
          "--bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "--bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "--bm-distance": "10px",
          "--bm-lift": "-2px",
          "--bm-press": "0.97",
          "--bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "--bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "--bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "--bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "--bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "--bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "--bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "--bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "--bm-text-xs": "0.75rem",
          "--bm-text-xs-lh": "calc(1 / 0.75)",
          "--bm-text-sm": "0.875rem",
          "--bm-text-sm-lh": "calc(1.25 / 0.875)",
          "--bm-text-base": "1rem",
          "--bm-text-base-lh": "calc(1.5 / 1)",
          "--bm-focus-width": "3px",
          "--bm-focus-alpha": "50%",
          "--bm-focus-color": "var(--ring)",
          "--bm-control-h": "calc(var(--spacing) * 9)",
          "--bm-control-h-sm": "calc(var(--spacing) * 8)",
          "--bm-control-h-lg": "calc(var(--spacing) * 11)",
          "--bm-target-min": "0px",
          "--bm-check-size": "calc(var(--spacing) * 4)",
          "--bm-switch-w": "calc(var(--spacing) * 9)",
          "--bm-switch-h": "calc(var(--spacing) * 5)",
          "--bm-press-dim": "1",
          "--bm-material-blur": "0px",
          "--bm-material-alpha": "100%",
          "--bm-sidebar-item-h": "2rem",
          "--bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "--bm-sidebar-indicator": "0px",
          "--bm-menu-item-h": "2rem",
          "--bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "--bm-menu-pad": "0.25rem",
          "--bm-scrollbar-width": "auto",
          "--bm-titlebar-h": "2.5rem",
          "--bm-toolbar-h": "52px",
          "--spacing": "0.25rem"
        },
        "[data-feel=\"macos\"]": {
          "--radius": "0.375rem",
          "--bm-speed": "1",
          "--bm-bounce": "0.25",
          "--bm-travel": "1",
          "--bm-hover": "1",
          "--bm-stagger": "1",
          "--bm-ambient": "1",
          "--bm-ambient-state": "running",
          "--bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "--bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "--bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "--bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "--bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "--bm-duration-base": "calc(220ms / var(--bm-speed))",
          "--bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "--bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "--bm-distance": "10px",
          "--bm-lift": "-2px",
          "--bm-press": "0.97",
          "--bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "--bm-shadow-xs": "0 0.5px 1px rgb(0 0 0 / 0.08), 0 0 0 0.5px rgb(0 0 0 / 0.04)",
          "--bm-shadow-sm": "0 1px 3px rgb(0 0 0 / 0.12), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "--bm-shadow-md": "0 4px 12px -2px rgb(0 0 0 / 0.14), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "--bm-shadow-lg": "0 12px 32px -6px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "--bm-shadow-xl": "0 20px 48px -8px rgb(0 0 0 / 0.26), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "--bm-shadow-2xl": "0 28px 64px -12px rgb(0 0 0 / 0.32), 0 0 0 0.5px rgb(0 0 0 / 0.1)",
          "--bm-shadow-popover": "0 8px 30px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.12)",
          "--bm-text-xs": "0.6875rem",
          "--bm-text-xs-lh": "0.875rem",
          "--bm-text-sm": "0.8125rem",
          "--bm-text-sm-lh": "1.125rem",
          "--bm-text-base": "0.9375rem",
          "--bm-text-base-lh": "1.375rem",
          "--bm-focus-width": "3px",
          "--bm-focus-alpha": "50%",
          "--bm-focus-color": "var(--ring)",
          "--bm-control-h": "1.75rem",
          "--bm-control-h-sm": "1.5rem",
          "--bm-control-h-lg": "2rem",
          "--bm-target-min": "0px",
          "--bm-check-size": "0.875rem",
          "--bm-switch-w": "2.375rem",
          "--bm-switch-h": "1.375rem",
          "--bm-press-dim": "1",
          "--bm-material-blur": "24px",
          "--bm-material-alpha": "78%",
          "--bm-sidebar-item-h": "1.75rem",
          "--bm-sidebar-item-radius": "0.375rem",
          "--bm-sidebar-indicator": "0px",
          "--bm-menu-item-h": "1.5rem",
          "--bm-menu-item-radius": "0.3125rem",
          "--bm-menu-pad": "0.3125rem",
          "--bm-scrollbar-width": "thin",
          "--bm-titlebar-h": "2.75rem",
          "--bm-toolbar-h": "52px",
          "--spacing": "0.225rem"
        },
        "[data-feel=\"ios\"]": {
          "--radius": "0.75rem",
          "--bm-speed": "1.1",
          "--bm-bounce": "0.55",
          "--bm-travel": "1.1",
          "--bm-hover": "0",
          "--bm-stagger": "1.1",
          "--bm-ambient": "1",
          "--bm-ambient-state": "running",
          "--bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "--bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "--bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "--bm-ease-spring": "linear(0, 0.026, 0.0947, 0.1927, 0.3084, 0.4319, 0.5553, 0.6724, 0.7789, 0.8718, 0.9497, 1.0122, 1.0596, 1.0932, 1.1143, 1.1249, 1.1268, 1.1219, 1.1121, 1.0989, 1.0839, 1.0681, 1.0526, 1.038, 1.0249, 1.0136, 1.0042, 0.9967, 0.9912, 0.9873, 0.985, 0.984, 0.984, 0.9848, 0.9862, 0.9879, 0.9899, 0.9919, 0.9938, 0.9956, 1)",
          "--bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "--bm-duration-base": "calc(220ms / var(--bm-speed))",
          "--bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "--bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "--bm-distance": "11px",
          "--bm-lift": "0px",
          "--bm-press": "1",
          "--bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "--bm-shadow-xs": "0 0 0 0 rgb(0 0 0 / 0)",
          "--bm-shadow-sm": "0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "--bm-shadow-md": "0 2px 10px rgb(0 0 0 / 0.08)",
          "--bm-shadow-lg": "0 10px 40px rgb(0 0 0 / 0.18)",
          "--bm-shadow-xl": "0 16px 56px rgb(0 0 0 / 0.22)",
          "--bm-shadow-2xl": "0 24px 72px rgb(0 0 0 / 0.28)",
          "--bm-shadow-popover": "0 10px 40px rgb(0 0 0 / 0.18)",
          "--bm-text-xs": "0.8125rem",
          "--bm-text-xs-lh": "1.125rem",
          "--bm-text-sm": "0.9375rem",
          "--bm-text-sm-lh": "1.375rem",
          "--bm-text-base": "1.0625rem",
          "--bm-text-base-lh": "1.5rem",
          "--bm-focus-width": "3px",
          "--bm-focus-alpha": "40%",
          "--bm-focus-color": "var(--ring)",
          "--bm-control-h": "2.75rem",
          "--bm-control-h-sm": "2.25rem",
          "--bm-control-h-lg": "3rem",
          "--bm-target-min": "2.75rem",
          "--bm-check-size": "1.375rem",
          "--bm-switch-w": "3.1875rem",
          "--bm-switch-h": "1.9375rem",
          "--bm-press-dim": "0.6",
          "--bm-material-blur": "30px",
          "--bm-material-alpha": "80%",
          "--bm-sidebar-item-h": "2.75rem",
          "--bm-sidebar-item-radius": "0.625rem",
          "--bm-sidebar-indicator": "0px",
          "--bm-menu-item-h": "2.75rem",
          "--bm-menu-item-radius": "0px",
          "--bm-menu-pad": "0px",
          "--bm-scrollbar-width": "none",
          "--bm-titlebar-h": "2.75rem",
          "--bm-toolbar-h": "44px",
          "--spacing": "0.275rem"
        },
        "[data-feel=\"windows\"]": {
          "--radius": "0.25rem",
          "--bm-speed": "1.3",
          "--bm-bounce": "0",
          "--bm-travel": "0.6",
          "--bm-hover": "0.5",
          "--bm-stagger": "0.5",
          "--bm-ambient": "1",
          "--bm-ambient-state": "running",
          "--bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "--bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "--bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "--bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "--bm-duration-base": "calc(220ms / var(--bm-speed))",
          "--bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "--bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "--bm-distance": "6px",
          "--bm-lift": "-1px",
          "--bm-press": "0.985",
          "--bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "--bm-shadow-xs": "0 0 2px rgb(0 0 0 / 0.12), 0 1px 2px rgb(0 0 0 / 0.14)",
          "--bm-shadow-sm": "0 0 2px rgb(0 0 0 / 0.12), 0 2px 4px rgb(0 0 0 / 0.14)",
          "--bm-shadow-md": "0 0 2px rgb(0 0 0 / 0.12), 0 4px 8px rgb(0 0 0 / 0.14)",
          "--bm-shadow-lg": "0 0 2px rgb(0 0 0 / 0.12), 0 8px 16px rgb(0 0 0 / 0.14)",
          "--bm-shadow-xl": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "--bm-shadow-2xl": "0 0 8px rgb(0 0 0 / 0.12), 0 32px 64px rgb(0 0 0 / 0.14)",
          "--bm-shadow-popover": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "--bm-text-xs": "0.75rem",
          "--bm-text-xs-lh": "1rem",
          "--bm-text-sm": "0.875rem",
          "--bm-text-sm-lh": "1.25rem",
          "--bm-text-base": "1rem",
          "--bm-text-base-lh": "1.375rem",
          "--bm-focus-width": "2px",
          "--bm-focus-alpha": "100%",
          "--bm-focus-color": "var(--foreground)",
          "--bm-control-h": "2rem",
          "--bm-control-h-sm": "1.5rem",
          "--bm-control-h-lg": "2.5rem",
          "--bm-target-min": "0px",
          "--bm-check-size": "1.25rem",
          "--bm-switch-w": "2.5rem",
          "--bm-switch-h": "1.25rem",
          "--bm-press-dim": "1",
          "--bm-material-blur": "30px",
          "--bm-material-alpha": "85%",
          "--bm-sidebar-item-h": "2.5rem",
          "--bm-sidebar-item-radius": "0.25rem",
          "--bm-sidebar-indicator": "3px",
          "--bm-menu-item-h": "2rem",
          "--bm-menu-item-radius": "0.25rem",
          "--bm-menu-pad": "0.25rem",
          "--bm-scrollbar-width": "thin",
          "--bm-titlebar-h": "2rem",
          "--bm-toolbar-h": "48px",
          "--spacing": "0.25rem"
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "Render <FeelScript /> once in <head> in your root layout and add suppressHydrationWarning to <html>. Use setFeel('macos' | 'ios' | 'windows' | 'web' | 'auto') from @/lib/ballmac/feel to let people choose.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "auto",
          "platform",
          "macos",
          "windows",
          "ios",
          "tauri",
          "electron",
          "detect"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "Install once, render <FeelScript /> in <head>, and the whole app handles like the platform it runs on. A Tauri or Electron app on a Mac becomes macOS and the same app on Windows becomes Windows, with no code branches.",
          "whenToUse": [
            "Desktop apps (Tauri, Electron) that ship to more than one OS",
            "Web apps that should feel native on phones and desktops"
          ],
          "whenNotToUse": [
            "Apps that always want one feel: install feel-macos, feel-ios or feel-windows instead",
            "Server components that must not read the platform: the feel is applied on the client before paint"
          ],
          "composesWith": [
            "app-window",
            "feel-presets"
          ],
          "a11y": [],
          "customization": [
            "setFeel('auto') returns to the device's own feel",
            "The font is inherited from data-feel on <html>; apps that set their own font on <body> keep it"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-auto"
      }
    },
    {
      "name": "field",
      "type": "registry:ui",
      "title": "Field",
      "description": "Form field layout with label, description and error that wire their ids to the control automatically, plus fieldset, legend, orientation and invalid/disabled state.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/field.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/field.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "form",
          "label",
          "validation",
          "layout"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Wrap a control in Field, spread useFieldControl() on it, and label, description, error, aria-invalid and disabled are connected for you.",
          "whenToUse": [
            "Any labelled form control",
            "Forms with validation messages",
            "Settings rows with a switch or checkbox"
          ],
          "whenNotToUse": [
            "A single unlabeled search box; use search-field",
            "Complete form state management; combine with your form library"
          ],
          "composesWith": [
            "input",
            "textarea",
            "select",
            "checkbox",
            "switch",
            "combobox"
          ],
          "a11y": [
            {
              "keys": "Click label",
              "action": "Focuses the control"
            },
            {
              "keys": "Screen readers",
              "action": "Read the description, and the error when invalid; the error is announced with role alert"
            }
          ],
          "customization": [
            "orientation: vertical | horizontal | responsive",
            "invalid and disabled",
            "FieldError errors array (deduplicated)",
            "required marker on FieldLabel"
          ]
        },
        "source": {
          "name": "shadcn/ui Field",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "field-demo",
          "field-states"
        ],
        "url": "https://ui.ballmac.com/components/field"
      }
    },
    {
      "name": "field-demo",
      "type": "registry:example",
      "title": "Field: Invite form",
      "description": "Invite form example of Field.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/field.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json"
      ],
      "files": [
        {
          "path": "registry/examples/field-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/field-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "field",
        "tier": "free"
      }
    },
    {
      "name": "field-states",
      "type": "registry:example",
      "title": "Field: Switch rows",
      "description": "Switch rows example of Field.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/field.json",
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/switch.json"
      ],
      "files": [
        {
          "path": "registry/examples/field-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/field-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "field",
        "tier": "free"
      }
    },
    {
      "name": "file-dropzone",
      "type": "registry:ui",
      "title": "File Dropzone",
      "description": "Drop files or browse with native file selection, type and size validation, removable file rows, and live errors.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/file-dropzone.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/file-dropzone.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "upload",
          "files",
          "dropzone"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Drop files or browse with native file selection, type and size validation, removable file rows, and live errors.",
          "whenToUse": [
            "Upload a document or group of assets",
            "Review selected files before submitting"
          ],
          "whenNotToUse": [
            "Use input for a minimal single-file field"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter",
              "action": "Opens the native file chooser"
            },
            {
              "keys": "Drop",
              "action": "Adds valid files"
            },
            {
              "keys": "Tab / Enter",
              "action": "Removes a selected file"
            }
          ],
          "customization": [
            "accept, maxFiles, maxSize, multiple",
            "files / defaultFiles and onFilesChange"
          ]
        },
        "examples": [
          "file-dropzone-demo",
          "file-dropzone-states"
        ],
        "url": "https://ui.ballmac.com/components/file-dropzone"
      }
    },
    {
      "name": "file-dropzone-demo",
      "type": "registry:example",
      "title": "File Dropzone: Overview",
      "description": "Overview example of File Dropzone.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/file-dropzone.json"
      ],
      "files": [
        {
          "path": "registry/examples/file-dropzone-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/file-dropzone-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "file-dropzone",
        "tier": "free"
      }
    },
    {
      "name": "file-dropzone-states",
      "type": "registry:example",
      "title": "File Dropzone: States and variants",
      "description": "States and variants example of File Dropzone.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/file-dropzone.json"
      ],
      "files": [
        {
          "path": "registry/examples/file-dropzone-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/file-dropzone-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "file-dropzone",
        "tier": "free"
      }
    },
    {
      "name": "floating-nav",
      "type": "registry:ui",
      "title": "Floating Nav",
      "description": "A pill-shaped navigation that floats over the page, with an indicator that glides between items on a spring and optional hide-on-scroll.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/scroll.json",
        "https://ui.ballmac.com/r/motion-presets.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/floating-nav.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/floating-nav.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "navigation",
          "pill",
          "floating",
          "mobile"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "items: {value,label,href,icon}. position top or bottom; autoHide slides it away on scroll; value/defaultValue/onValueChange pick the active item.",
          "whenToUse": [
            "Landing pages and portfolios",
            "App-style bottom navigation on small screens"
          ],
          "whenNotToUse": [
            "Sites that need nested menus; use navbar with mega-menu",
            "Long lists of links"
          ],
          "composesWith": [
            "navbar",
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves through the links"
            },
            {
              "keys": "Screen readers",
              "action": "Active item has aria-current; icon-only items keep their label"
            },
            {
              "keys": "Reduced motion",
              "action": "The indicator jumps instead of gliding; hiding uses no transition"
            }
          ],
          "customization": [
            "position: top | bottom",
            "autoHide",
            "icons (labels collapse on small screens)",
            "scrollContainer"
          ]
        },
        "examples": [
          "floating-nav-demo",
          "floating-nav-states"
        ],
        "url": "https://ui.ballmac.com/components/floating-nav"
      }
    },
    {
      "name": "floating-nav-demo",
      "type": "registry:example",
      "title": "Floating Nav: Top bar that hides",
      "description": "Top bar that hides example of Floating Nav.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/floating-nav.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/floating-nav-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/floating-nav-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "floating-nav",
        "tier": "free"
      }
    },
    {
      "name": "floating-nav-states",
      "type": "registry:example",
      "title": "Floating Nav: Bottom bar",
      "description": "Bottom bar example of Floating Nav.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/floating-nav.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/floating-nav-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/floating-nav-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "floating-nav",
        "tier": "free"
      }
    },
    {
      "name": "form",
      "type": "registry:ui",
      "title": "Form",
      "description": "React Hook Form wired to Ballmac Field: one FormField renders label, control, description and error with ids, aria-invalid and aria-describedby linked, plus a pending submit button.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "react-hook-form@^7"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/field.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/form.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/form.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "form",
          "validation",
          "react-hook-form",
          "field"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "const form = useForm(); <Form form onSubmit><FormField name label render={(props) => <Input {...props}/>}/><FormSubmit/></Form>. Use rules or a resolver for validation.",
          "whenToUse": [
            "Any form with client validation",
            "Forms that need per-field errors announced"
          ],
          "whenNotToUse": [
            "A single uncontrolled input; use field",
            "Server actions without client state"
          ],
          "composesWith": [
            "field",
            "input",
            "checkbox",
            "select"
          ],
          "a11y": [
            {
              "keys": "Enter",
              "action": "Submits; focus moves to the first invalid control"
            },
            {
              "keys": "Screen readers",
              "action": "Labels, hints and errors are linked; errors use role alert"
            }
          ],
          "customization": [
            "rules or resolver",
            "orientation horizontal for checkboxes",
            "pendingText on FormSubmit",
            "description and required"
          ]
        },
        "source": {
          "name": "shadcn/ui Form",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "form-demo",
          "form-states"
        ],
        "url": "https://ui.ballmac.com/components/form"
      }
    },
    {
      "name": "form-demo",
      "type": "registry:example",
      "title": "Form: Sign up",
      "description": "Sign up example of Form.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/form.json",
        "https://ui.ballmac.com/r/checkbox.json",
        "https://ui.ballmac.com/r/input.json"
      ],
      "dependencies": [
        "react-hook-form@^7",
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/form-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/form-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "form",
        "tier": "free"
      }
    },
    {
      "name": "form-states",
      "type": "registry:example",
      "title": "Form: Pending submit",
      "description": "Pending submit example of Form.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/form.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/textarea.json"
      ],
      "dependencies": [
        "react-hook-form@^7"
      ],
      "files": [
        {
          "path": "registry/examples/form-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/form-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "form",
        "tier": "free"
      }
    },
    {
      "name": "funnel-chart",
      "type": "registry:ui",
      "title": "Funnel Chart",
      "description": "A funnel as bars that narrow step by step. Between steps it says how many carried on and how many dropped out, flags the biggest drop, and ends with the overall result as a sentence.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/funnel-chart.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/funnel-chart.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chart",
          "funnel",
          "conversion",
          "analytics",
          "steps",
          "drop-off",
          "dashboard"
        ],
        "version": "1.0.0",
        "updated": "2026-10-25",
        "tests": true,
        "ai": {
          "summary": "steps is [{ id, label, value, hint? }] from first to last. title, format(value). Between steps: '40% carried on, 600 dropped out', and the biggest drop is tagged in words. onSelect(id | null) with selected makes steps toggle buttons. Ends with 'X% of everyone who started reached the end'.",
          "whenToUse": [
            "Checkout, signup or onboarding conversion",
            "Any process where people drop out between steps"
          ],
          "whenNotToUse": [
            "Steps that can happen in any order; use bar-list",
            "Flow with branches; use flow-sankey"
          ],
          "composesWith": [
            "bar-list",
            "stat-card",
            "kpi-row",
            "flow-sankey"
          ],
          "a11y": [
            {
              "keys": "Steps",
              "action": "An ordered list; drop-off and conversion are text, never only bar length"
            },
            {
              "keys": "Selection",
              "action": "Optional buttons with pressed state"
            },
            {
              "keys": "Biggest drop",
              "action": "Tagged with the words 'Biggest drop'"
            }
          ],
          "customization": [
            "steps and title",
            "format",
            "onSelect and selected"
          ]
        },
        "statesNone": "A presentational chart: the steps are passed in, so it has nothing of its own to load.",
        "examples": [
          "funnel-chart-demo",
          "funnel-chart-static"
        ],
        "url": "https://ui.ballmac.com/components/funnel-chart"
      }
    },
    {
      "name": "funnel-chart-demo",
      "type": "registry:example",
      "title": "Funnel Chart: Visit to purchase, with selection",
      "description": "Visit to purchase, with selection example of Funnel Chart.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/funnel-chart.json"
      ],
      "files": [
        {
          "path": "registry/examples/funnel-chart-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/funnel-chart-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "funnel-chart",
        "tier": "free"
      }
    },
    {
      "name": "funnel-chart-static",
      "type": "registry:example",
      "title": "Funnel Chart: Three steps",
      "description": "Three steps example of Funnel Chart.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/funnel-chart.json"
      ],
      "files": [
        {
          "path": "registry/examples/funnel-chart-static.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/funnel-chart-static.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "funnel-chart",
        "tier": "free"
      }
    },
    {
      "name": "globe",
      "type": "registry:ui",
      "title": "Globe",
      "description": "An interactive WebGL dot globe (cobe) with markers, drag-to-spin momentum and arrow-key control. Colors come from theme tokens and repaint on theme change; starts lazily and pauses off-screen.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "cobe@^0.6"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/color.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/globe.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/globe.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "globe",
          "webgl",
          "map",
          "regions",
          "3d",
          "hero",
          "interactive"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "tests": true,
        "ai": {
          "summary": "Render <Globe markers={[{ location: [lat, lng], size: 0.06 }]} /> in a sized container (it is a square, w-full, max 600px). The canvas has role=img and an aria-label; pass label to describe what it shows. It starts WebGL only when scrolled near the viewport.",
          "whenToUse": [
            "Showing global reach: regions, edge locations, offices, customers by country",
            "A hero or feature-card visual for infrastructure, networking or travel products"
          ],
          "whenNotToUse": [
            "Precise geographic data or choropleths (use a real map library)",
            "Several globes on one page; each is a WebGL context"
          ],
          "composesWith": [
            "number-ticker",
            "spotlight-card",
            "badge"
          ],
          "a11y": [
            {
              "keys": "Arrow Left / Arrow Right",
              "action": "Spins the globe"
            },
            {
              "keys": "Arrow Up / Arrow Down",
              "action": "Tilts the globe; it settles back"
            }
          ],
          "customization": [
            "markers: [{ location: [lat, lng], size }]",
            "markerColor (default --chart-1), baseColor and glowColor: CSS variable names or any CSS color; defaults adapt to light and dark",
            "speed (radians per frame, 0 to stop), phi, theta, mapBrightness, mapSamples",
            "interactive={false} for a purely decorative globe"
          ]
        },
        "examples": [
          "globe-demo",
          "globe-hero"
        ],
        "url": "https://ui.ballmac.com/components/globe"
      }
    },
    {
      "name": "globe-demo",
      "type": "registry:example",
      "title": "Globe: Regions card",
      "description": "Regions card example of Globe.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/globe.json"
      ],
      "files": [
        {
          "path": "registry/examples/globe-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/globe-demo.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "globe",
        "tier": "free"
      }
    },
    {
      "name": "globe-hero",
      "type": "registry:example",
      "title": "Globe: Hero horizon",
      "description": "Hero horizon example of Globe.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/globe.json"
      ],
      "files": [
        {
          "path": "registry/examples/globe-hero.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/globe-hero.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "globe",
        "tier": "free"
      }
    },
    {
      "name": "glow-border",
      "type": "registry:ui",
      "title": "Glow Border",
      "description": "Wraps any content in a border drawn by a rotating conic gradient in theme colors, with a soft outer glow. Speed, width, radius and arc length are props; it stops at a still angle under reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/glow-border.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/glow-border.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "border",
          "gradient",
          "glow",
          "conic",
          "highlight",
          "pricing",
          "button",
          "motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "Put content inside <GlowBorder>; it renders a padded wrapper whose padding shows a rotating conic gradient and a content surface (bg-card, radius minus width). Use arc={1} for a full rainbow ring, a smaller arc for a comet.",
          "whenToUse": [
            "The recommended plan in a pricing table",
            "One primary call-to-action or an AI entry point",
            "Marking a card as new, live or selected"
          ],
          "whenNotToUse": [
            "Several elements at once on the same screen (use it for one focal point)",
            "A thin light that travels along an existing border (use border-beam)"
          ],
          "composesWith": [
            "button",
            "border-beam",
            "tilt-card"
          ],
          "a11y": [],
          "customization": [
            "duration: seconds per rotation (default 4); width: ring px (default 1.5); radius: px (default 14, 999 for pills)",
            "colors: CSS colors or var(--chart-n) values; arc: 0–1 share of the ring lit (default 0.55)",
            "glow: 0–1 outer glow strength (0 turns it off)",
            "contentClassName styles the inner surface (bg-background, bg-primary…)",
            "Animates a registered CSS property (--glow-border-angle); pauses off-screen"
          ]
        },
        "examples": [
          "glow-border-demo",
          "glow-border-button"
        ],
        "url": "https://ui.ballmac.com/components/glow-border"
      }
    },
    {
      "name": "glow-border-demo",
      "type": "registry:example",
      "title": "Glow Border: Pricing highlight",
      "description": "Pricing highlight example of Glow Border.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/glow-border.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/glow-border-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/glow-border-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "glow-border",
        "tier": "free"
      }
    },
    {
      "name": "glow-border-button",
      "type": "registry:example",
      "title": "Glow Border: Buttons",
      "description": "Buttons example of Glow Border.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/glow-border.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/glow-border-button.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/glow-border-button.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "glow-border",
        "tier": "free"
      }
    },
    {
      "name": "grid-pattern",
      "type": "registry:ui",
      "title": "Grid Pattern",
      "description": "A crisp square-grid background in the border color with optional dashed lines, filled cells, softly lighting random cells and an edge fade, drawn as one SVG pattern.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/grid-pattern.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/grid-pattern.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "grid",
          "pattern",
          "svg",
          "background",
          "lines"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "<GridPattern cell strokeDasharray squares={[[col,row]]} flicker={n} fade='radial|top|bottom|none' /> in a relative parent. Random cells are picked after mount so server and browser agree.",
          "whenToUse": [
            "Section and hero backgrounds that need structure",
            "Behind cards and empty states"
          ],
          "whenNotToUse": [
            "Dots (dot-pattern)",
            "A pointer-reactive grid (interactive-grid)"
          ],
          "composesWith": [
            "dot-pattern",
            "interactive-grid",
            "animated-grid"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "Decorative: aria-hidden"
            },
            {
              "keys": "Reduced motion",
              "action": "No random cells light up"
            }
          ],
          "customization": [
            "cell",
            "x and y offset",
            "strokeDasharray",
            "squares",
            "flicker",
            "fade"
          ]
        },
        "examples": [
          "grid-pattern-demo",
          "grid-pattern-variants"
        ],
        "url": "https://ui.ballmac.com/components/grid-pattern"
      }
    },
    {
      "name": "grid-pattern-demo",
      "type": "registry:example",
      "title": "Grid Pattern: Faded grid with highlighted cells",
      "description": "Faded grid with highlighted cells example of Grid Pattern.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/grid-pattern.json"
      ],
      "files": [
        {
          "path": "registry/examples/grid-pattern-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/grid-pattern-demo.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "grid-pattern",
        "tier": "free"
      }
    },
    {
      "name": "grid-pattern-variants",
      "type": "registry:example",
      "title": "Grid Pattern: Dashed and flickering",
      "description": "Dashed and flickering example of Grid Pattern.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/grid-pattern.json"
      ],
      "files": [
        {
          "path": "registry/examples/grid-pattern-variants.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/grid-pattern-variants.tsx"
        }
      ],
      "categories": [
        "backgrounds"
      ],
      "meta": {
        "example": true,
        "of": "grid-pattern",
        "tier": "free"
      }
    },
    {
      "name": "hud",
      "type": "registry:ui",
      "title": "HUD",
      "description": "The macOS volume and brightness HUD: a dark frosted square with a big icon and a 16-segment bar, or a slim capsule with a smooth bar. Pops in, restarts its timer when the value changes, fades out and announces the new level.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/hud.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/hud.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "hud",
          "volume",
          "brightness",
          "macos",
          "overlay",
          "feedback"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "<Hud kind=\"volume\" value={60} visible={visible} onVisibleChange={setVisible} /> inside a relative container. useTransientHud() gives { visible, show, hide, onVisibleChange }.",
          "whenToUse": [
            "Keyboard-driven level changes in desktop UI demos",
            "Transient feedback for hardware-style controls"
          ],
          "whenNotToUse": [
            "Toasts and messages (toast)",
            "Persistent controls (slider)"
          ],
          "composesWith": [
            "control-center",
            "menu-bar",
            "keyboard-shortcuts"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "A polite status message says the new level; the visual HUD is hidden from them"
            },
            {
              "keys": "Reduced motion",
              "action": "Fades without scaling"
            }
          ],
          "customization": [
            "kind: volume | brightness | keyboard",
            "variant: mac | pill",
            "muted, duration, value 0 to 100"
          ]
        },
        "examples": [
          "hud-demo",
          "hud-pill"
        ],
        "url": "https://ui.ballmac.com/components/hud"
      }
    },
    {
      "name": "hud-demo",
      "type": "registry:example",
      "title": "HUD: Volume keys",
      "description": "Volume keys example of HUD.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/hud.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/hud-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/hud-demo.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "hud",
        "tier": "free"
      }
    },
    {
      "name": "hud-pill",
      "type": "registry:example",
      "title": "HUD: Capsule variant",
      "description": "Capsule variant example of HUD.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/hud.json"
      ],
      "files": [
        {
          "path": "registry/examples/hud-pill.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/hud-pill.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "hud",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper",
      "type": "registry:ui",
      "title": "Image Cropper",
      "description": "Crop a picture under a fixed frame: drag to move, wheel, pinch or slider to zoom, straighten and turn by quarters, any aspect ratio or a round avatar, full keyboard control and a canvas export to a file.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/image-cropper.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/image-cropper.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "image",
          "crop",
          "avatar",
          "upload",
          "zoom",
          "rotate",
          "canvas"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "<ImageCropper src aspect={1} cropperRef={ref} />. Get the file with await ref.current.toBlob({ width, type }); onCropComplete gives the area in original pixels to crop on a server. shape=\"round\" for avatars.",
          "whenToUse": [
            "Profile pictures, cover images and product photos cropped before upload",
            "Any upload that needs a fixed aspect ratio",
            "Straightening a slightly tilted photo"
          ],
          "whenNotToUse": [
            "Free-form selection boxes with resizable handles",
            "Photo editing with filters, text or drawing",
            "Pictures from another site without CORS headers, which cannot be exported"
          ],
          "composesWith": [
            "file-dropzone",
            "avatar",
            "dialog",
            "button"
          ],
          "a11y": [
            {
              "keys": "Arrow keys",
              "action": "Move the picture under the frame; Shift moves it further"
            },
            {
              "keys": "+ / -",
              "action": "Zoom in and out; the zoom is announced"
            },
            {
              "keys": "[ / ]",
              "action": "Turn a quarter left or right"
            },
            {
              "keys": "0",
              "action": "Reset"
            },
            {
              "keys": "Sliders and buttons",
              "action": "Zoom and straighten are native range inputs with spoken values; turn and reset are buttons"
            }
          ],
          "customization": [
            "aspect, shape, height, maxZoom, grid, zoomOnWheel",
            "value and onCropChange to hold the crop; onCropComplete for the area in original pixels",
            "toBlob options: width, maxWidth, type, quality, round, background",
            "controls={false} to build your own controls on the same ref"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "image-cropper-loading",
            "trigger": "no src yet, or while the picture loads",
            "note": "A skeleton in the picture's place, announced as loading; the controls are off."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "image-cropper-error",
            "trigger": "the picture fails to load",
            "note": "A message with a Try again button, announced as an alert; onError gets the error."
          }
        ],
        "examples": [
          "image-cropper-demo",
          "image-cropper-aspect",
          "image-cropper-avatar",
          "image-cropper-controlled",
          "image-cropper-loading",
          "image-cropper-error"
        ],
        "url": "https://ui.ballmac.com/components/image-cropper"
      }
    },
    {
      "name": "image-cropper-demo",
      "type": "registry:example",
      "title": "Image Cropper: Square crop with a result",
      "description": "Square crop with a result example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper-aspect",
      "type": "registry:example",
      "title": "Image Cropper: Choose the shape",
      "description": "Choose the shape example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-aspect.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-aspect.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper-avatar",
      "type": "registry:example",
      "title": "Image Cropper: Round avatar from a file",
      "description": "Round avatar from a file example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-avatar.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-avatar.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper-controlled",
      "type": "registry:example",
      "title": "Image Cropper: Controlled, with the area",
      "description": "Controlled, with the area example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-controlled.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-controlled.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper-loading",
      "type": "registry:example",
      "title": "Image Cropper: Loading",
      "description": "Loading example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-loading.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "image-cropper-error",
      "type": "registry:example",
      "title": "Image Cropper: Could not load",
      "description": "Could not load example of Image Cropper.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/image-cropper.json"
      ],
      "files": [
        {
          "path": "registry/examples/image-cropper-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/image-cropper-error.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "image-cropper",
        "tier": "free"
      }
    },
    {
      "name": "inline-alert",
      "type": "registry:ui",
      "title": "Inline Alert",
      "description": "A short in-context message with semantic live priority and an optional corrective action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/inline-alert.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/inline-alert.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "validation",
          "message",
          "status"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A short in-context message with semantic live priority and an optional corrective action.",
          "whenToUse": [
            "Explain a field or form outcome",
            "Show a small inline confirmation"
          ],
          "whenNotToUse": [
            "Use alert for a larger callout"
          ],
          "composesWith": [
            "alert",
            "input"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter",
              "action": "Focus and activate an optional action"
            }
          ],
          "customization": [
            "tone: info | success | error",
            "Action slot"
          ]
        },
        "examples": [
          "inline-alert-demo",
          "inline-alert-states"
        ],
        "url": "https://ui.ballmac.com/components/inline-alert"
      }
    },
    {
      "name": "inline-alert-demo",
      "type": "registry:example",
      "title": "Inline Alert: Overview",
      "description": "Overview example of Inline Alert.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/inline-alert.json"
      ],
      "files": [
        {
          "path": "registry/examples/inline-alert-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/inline-alert-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "inline-alert",
        "tier": "free"
      }
    },
    {
      "name": "inline-alert-states",
      "type": "registry:example",
      "title": "Inline Alert: States and variants",
      "description": "States and variants example of Inline Alert.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/inline-alert.json"
      ],
      "files": [
        {
          "path": "registry/examples/inline-alert-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/inline-alert-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "inline-alert",
        "tier": "free"
      }
    },
    {
      "name": "input-group",
      "type": "registry:ui",
      "title": "Input Group",
      "description": "One bordered field that wraps an input or textarea with icon, text, button and keyboard-hint addons at either end or above and below.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/input-group.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/input-group.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "input",
          "addon",
          "form",
          "textarea"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Put InputGroupInput or InputGroupTextarea plus InputGroupAddon parts inside InputGroup. The group draws the border, focus ring and invalid state.",
          "whenToUse": [
            "URL and currency prefixes and suffixes",
            "Search fields with a button",
            "Chat composers with a send button"
          ],
          "whenNotToUse": [
            "A plain field; use input",
            "Attached separate buttons; use button-group"
          ],
          "composesWith": [
            "field",
            "button",
            "kbd"
          ],
          "a11y": [
            {
              "keys": "Click addon text",
              "action": "Focuses the control"
            },
            {
              "keys": "Tab",
              "action": "Moves between the control and addon buttons"
            }
          ],
          "customization": [
            "addon align: inline-start | inline-end | block-start | block-end",
            "button size: xs | sm | icon-xs | icon-sm",
            "aria-invalid on the control"
          ]
        },
        "source": {
          "name": "shadcn/ui Input Group",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "input-group-demo",
          "input-group-states"
        ],
        "url": "https://ui.ballmac.com/components/input-group"
      }
    },
    {
      "name": "input-group-demo",
      "type": "registry:example",
      "title": "Input Group: Addons",
      "description": "Addons example of Input Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/input-group-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-group-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "input-group",
        "tier": "free"
      }
    },
    {
      "name": "input-group-states",
      "type": "registry:example",
      "title": "Input Group: Invalid and disabled",
      "description": "Invalid and disabled example of Input Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/input-group-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-group-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "input-group",
        "tier": "free"
      }
    },
    {
      "name": "input-otp",
      "type": "registry:ui",
      "title": "Input OTP",
      "description": "A one-time-code field with grouped slots, separator, caret, paste and autofill support, invalid state and reduced-motion-safe animation, on a single real input.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "input-otp@^1",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/input-otp.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/input-otp.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "otp",
          "code",
          "verification",
          "input"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "<InputOTP maxLength={6}> with InputOTPGroup, InputOTPSlot index and InputOTPSeparator. onComplete fires when every slot is filled.",
          "whenToUse": [
            "Two-step sign-in and email verification",
            "PIN entry"
          ],
          "whenNotToUse": [
            "Free-form text codes; use input",
            "Long passwords; use password-input"
          ],
          "composesWith": [
            "field",
            "label"
          ],
          "a11y": [
            {
              "keys": "Type / paste",
              "action": "Fills slots; autofill works with one-time-code"
            },
            {
              "keys": "Backspace / arrows",
              "action": "Edit like a normal text field"
            },
            {
              "keys": "Screen readers",
              "action": "One text input is announced, not six boxes"
            }
          ],
          "customization": [
            "maxLength and pattern",
            "groups and separators",
            "aria-invalid",
            "onComplete"
          ]
        },
        "source": {
          "name": "shadcn/ui Input OTP",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "input-otp-demo",
          "input-otp-states"
        ],
        "url": "https://ui.ballmac.com/components/input-otp"
      }
    },
    {
      "name": "input-otp-demo",
      "type": "registry:example",
      "title": "Input OTP: Verification code",
      "description": "Verification code example of Input OTP.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input-otp.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/input-otp-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-otp-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "input-otp",
        "tier": "free"
      }
    },
    {
      "name": "input-otp-states",
      "type": "registry:example",
      "title": "Input OTP: PIN, invalid, disabled",
      "description": "PIN, invalid, disabled example of Input OTP.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input-otp.json"
      ],
      "files": [
        {
          "path": "registry/examples/input-otp-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-otp-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "input-otp",
        "tier": "free"
      }
    },
    {
      "name": "input",
      "type": "registry:ui",
      "title": "Input",
      "description": "A text input in three heights that match Button, plus InputGroup and InputGroupAddon for leading or trailing icons, units and domains.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/input.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "input",
          "text-field",
          "form",
          "search"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Single-line text field. Use size to match neighbouring buttons, wrap in InputGroup with InputGroupAddon (align start or end) for icons or text like \".com\", and set aria-invalid for error styling.",
          "whenToUse": [
            "Any single-line form field (email, name, URL, search)",
            "Search boxes with a leading icon",
            "Fields with a fixed unit or domain suffix"
          ],
          "whenNotToUse": [
            "Multi-line text (use textarea)",
            "Choosing from a fixed list (use select)",
            "On/off settings (use switch or checkbox)"
          ],
          "composesWith": [
            "label",
            "button",
            "kbd",
            "tooltip",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves focus to the input"
            },
            {
              "keys": "Click on an addon",
              "action": "Focuses the input"
            }
          ],
          "customization": [
            "size: sm | default | lg (h-8 / h-9 / h-11)",
            "InputGroup size: sm | default | lg; InputGroupAddon align: start | end",
            "aria-invalid=\"true\" switches to destructive border and ring",
            "htmlSize maps to the native size attribute"
          ]
        },
        "source": {
          "name": "shadcn/ui Input",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "input-demo",
          "input-with-icon",
          "input-invalid"
        ],
        "url": "https://ui.ballmac.com/components/input"
      }
    },
    {
      "name": "input-demo",
      "type": "registry:example",
      "title": "Input: Default",
      "description": "Default example of Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input.json"
      ],
      "files": [
        {
          "path": "registry/examples/input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "input",
        "tier": "free"
      }
    },
    {
      "name": "input-with-icon",
      "type": "registry:example",
      "title": "Input: With icon and suffix",
      "description": "With icon and suffix example of Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/kbd.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/input-with-icon.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-with-icon.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "input",
        "tier": "free"
      }
    },
    {
      "name": "input-invalid",
      "type": "registry:example",
      "title": "Input: Invalid",
      "description": "Invalid example of Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/input-invalid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/input-invalid.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "input",
        "tier": "free"
      }
    },
    {
      "name": "json-viewer",
      "type": "registry:ui",
      "title": "JSON Viewer",
      "description": "A collapsible JSON inspector with compact type styling and keyboard-operable branches.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/json-viewer.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/json-viewer.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "json",
          "data",
          "developer"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A collapsible JSON inspector with compact type styling and keyboard-operable branches.",
          "whenToUse": [
            "Inspect nested API responses or configuration"
          ],
          "whenNotToUse": [
            "Use Code Block for unstructured text"
          ],
          "composesWith": [
            "code-block"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter / Space",
              "action": "Focuses and toggles JSON branches"
            }
          ],
          "customization": [
            "Controlled and uncontrolled state",
            "Content and token-based className styling"
          ]
        },
        "examples": [
          "json-viewer-demo",
          "json-viewer-states"
        ],
        "url": "https://ui.ballmac.com/components/json-viewer"
      }
    },
    {
      "name": "json-viewer-demo",
      "type": "registry:example",
      "title": "JSON Viewer: Overview",
      "description": "Overview example of JSON Viewer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/json-viewer.json"
      ],
      "files": [
        {
          "path": "registry/examples/json-viewer-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/json-viewer-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "json-viewer",
        "tier": "free"
      }
    },
    {
      "name": "json-viewer-states",
      "type": "registry:example",
      "title": "JSON Viewer: States and variants",
      "description": "States and variants example of JSON Viewer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/json-viewer.json"
      ],
      "files": [
        {
          "path": "registry/examples/json-viewer-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/json-viewer-states.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "json-viewer",
        "tier": "free"
      }
    },
    {
      "name": "kbd",
      "type": "registry:ui",
      "title": "Kbd",
      "description": "Keyboard key and shortcut display built on the semantic <kbd> element, in three sizes, with KbdGroup for combinations like ⌘ ⇧ K. Adapts inside tooltips.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/kbd.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/kbd.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "kbd",
          "keyboard",
          "shortcut",
          "hotkey"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "Displays a key or shortcut. Use Kbd for each key and KbdGroup for keys pressed together; it restyles itself for the dark tooltip surface automatically.",
          "whenToUse": [
            "Shortcut hints in menus, tooltips and command palettes",
            "Documentation of keyboard controls",
            "Search inputs that show a ⌘ K hint"
          ],
          "whenNotToUse": [
            "Inline code or commands (use code)",
            "Buttons that trigger the shortcut (use button)"
          ],
          "composesWith": [
            "tooltip",
            "button",
            "input"
          ],
          "a11y": [],
          "customization": [
            "size: sm | default | lg",
            "Use symbols (⌘ ⇧ ⌥ ⌃ ↵) or words (Ctrl, Enter); add aria-label on KbdGroup if symbols need spelling out"
          ]
        },
        "examples": [
          "kbd-demo"
        ],
        "url": "https://ui.ballmac.com/components/kbd"
      }
    },
    {
      "name": "kbd-demo",
      "type": "registry:example",
      "title": "Kbd: Default",
      "description": "Default example of Kbd.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kbd.json"
      ],
      "files": [
        {
          "path": "registry/examples/kbd-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kbd-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "kbd",
        "tier": "free"
      }
    },
    {
      "name": "kpi-row",
      "type": "registry:ui",
      "title": "KPI Row",
      "description": "A compact, semantic row of key metrics that adapts from one to four columns.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/kpi-row.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/kpi-row.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "metric",
          "dashboard",
          "summary"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A compact, semantic row of key metrics that adapts from one to four columns.",
          "whenToUse": [
            "Show several related metrics together"
          ],
          "whenNotToUse": [
            "Use Stat Card when each metric needs more context"
          ],
          "composesWith": [
            "stat-card"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Static content is announced with semantic structure"
            }
          ],
          "customization": [
            "Content, layout, and token-based className styling"
          ]
        },
        "examples": [
          "kpi-row-demo",
          "kpi-row-states"
        ],
        "url": "https://ui.ballmac.com/components/kpi-row"
      }
    },
    {
      "name": "kpi-row-demo",
      "type": "registry:example",
      "title": "KPI Row: Overview",
      "description": "Overview example of KPI Row.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kpi-row.json"
      ],
      "files": [
        {
          "path": "registry/examples/kpi-row-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kpi-row-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "kpi-row",
        "tier": "free"
      }
    },
    {
      "name": "kpi-row-states",
      "type": "registry:example",
      "title": "KPI Row: States and variants",
      "description": "States and variants example of KPI Row.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/kpi-row.json"
      ],
      "files": [
        {
          "path": "registry/examples/kpi-row-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/kpi-row-states.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "kpi-row",
        "tier": "free"
      }
    },
    {
      "name": "label",
      "type": "registry:ui",
      "title": "Label",
      "description": "An accessible form label built on Radix Label that dims itself when the paired peer control is disabled and never selects text on double-click.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/label.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/label.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "label",
          "form",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "Text label for a form control. Pair with htmlFor/id; put the control before it with className=\"peer\" (Checkbox and Switch already are) to get disabled styling.",
          "whenToUse": [
            "Naming inputs, textareas, selects, checkboxes and switches",
            "Clickable text next to a checkbox or switch"
          ],
          "whenNotToUse": [
            "Headings or section titles (use a heading element)",
            "Helper or error text under a field (use a p with text-muted-foreground or text-destructive)"
          ],
          "composesWith": [
            "input",
            "textarea",
            "checkbox",
            "switch",
            "select"
          ],
          "a11y": [
            {
              "keys": "Click",
              "action": "Focuses or toggles the associated control"
            }
          ],
          "customization": [
            "Disabled styling via peer-disabled (control before label) or a parent with group and data-disabled=\"true\"",
            "Lays out children in a row with gap-2, so icons or badges can sit beside the text"
          ]
        },
        "source": {
          "name": "shadcn/ui Label",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "label-demo"
        ],
        "url": "https://ui.ballmac.com/components/label"
      }
    },
    {
      "name": "label-demo",
      "type": "registry:example",
      "title": "Label: Default",
      "description": "Default example of Label.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/label.json",
        "https://ui.ballmac.com/r/input.json"
      ],
      "files": [
        {
          "path": "registry/examples/label-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/label-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "label",
        "tier": "free"
      }
    },
    {
      "name": "loading-dots",
      "type": "registry:ui",
      "title": "Loading Dots",
      "description": "A compact loading status with staggered token-colored dots that stop for reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/loading-dots.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/loading-dots.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "loading",
          "status",
          "animation"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A compact loading status with staggered token-colored dots that stop for reduced motion.",
          "whenToUse": [
            "Indicate short pending work",
            "Pair a compact loader with a button label"
          ],
          "whenNotToUse": [
            "Use skeleton for a full content placeholder"
          ],
          "composesWith": [
            "spinner",
            "button"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Accessible status label"
            }
          ],
          "customization": [
            "size: sm | default | lg",
            "Status label"
          ]
        },
        "examples": [
          "loading-dots-demo",
          "loading-dots-states"
        ],
        "url": "https://ui.ballmac.com/components/loading-dots"
      }
    },
    {
      "name": "loading-dots-demo",
      "type": "registry:example",
      "title": "Loading Dots: Overview",
      "description": "Overview example of Loading Dots.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/loading-dots.json"
      ],
      "files": [
        {
          "path": "registry/examples/loading-dots-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/loading-dots-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "loading-dots",
        "tier": "free"
      }
    },
    {
      "name": "loading-dots-states",
      "type": "registry:example",
      "title": "Loading Dots: States and variants",
      "description": "States and variants example of Loading Dots.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/loading-dots.json"
      ],
      "files": [
        {
          "path": "registry/examples/loading-dots-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/loading-dots-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "loading-dots",
        "tier": "free"
      }
    },
    {
      "name": "mac-icons",
      "type": "registry:ui",
      "title": "Mac Icons",
      "description": "Resolution-independent macOS-style icons drawn in SVG and CSS: folders, documents with extension badges, drives and gradient app icons in eight theme-aware colors.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/mac-icons.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/mac-icons.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "icons",
          "folder",
          "file",
          "app icon",
          "macos"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "<FolderIcon size tone />, <FileIcon label='PDF' tone />, <DriveIcon />, <AppIcon tone size>{glyph}</AppIcon>. tone is blue | teal | green | amber | orange | red | purple | graphite. All are decorative (aria-hidden): put the name in text next to them.",
          "whenToUse": [
            "Desktop, Finder and Launchpad recreations",
            "File lists that want recognisable macOS icons"
          ],
          "whenNotToUse": [
            "Small UI glyphs (use lucide-react icons)"
          ],
          "composesWith": [
            "finder-window",
            "desktop-icons",
            "launchpad",
            "dock"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "Icons are aria-hidden; always label the item with text"
            }
          ],
          "customization": [
            "size",
            "tone",
            "FileIcon label",
            "AppIcon glyph"
          ]
        },
        "examples": [
          "mac-icons-demo",
          "mac-icons-tones"
        ],
        "url": "https://ui.ballmac.com/components/mac-icons"
      }
    },
    {
      "name": "mac-icons-demo",
      "type": "registry:example",
      "title": "Mac Icons: The four icon kinds",
      "description": "The four icon kinds example of Mac Icons.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mac-icons.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/mac-icons-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mac-icons-demo.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "mac-icons",
        "tier": "free"
      }
    },
    {
      "name": "mac-icons-tones",
      "type": "registry:example",
      "title": "Mac Icons: Colors and sizes",
      "description": "Colors and sizes example of Mac Icons.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mac-icons.json"
      ],
      "files": [
        {
          "path": "registry/examples/mac-icons-tones.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mac-icons-tones.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "mac-icons",
        "tier": "free"
      }
    },
    {
      "name": "marquee",
      "type": "registry:ui",
      "title": "Marquee",
      "description": "An endless horizontal or vertical scroller for logo rows and testimonials. Speed is in pixels per second, it pauses on hover and focus, and it fills any width.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/marquee.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/marquee.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "animation",
          "scroller",
          "logos",
          "testimonials",
          "ticker",
          "motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "Put the items directly inside <Marquee>; it measures one copy, clones as many as the viewport needs (clones are aria-hidden and inert) and loops them with a GPU transform. Under reduced motion it renders a single copy in a scrollable row.",
          "whenToUse": [
            "A row of customer or partner logos under a hero",
            "A wall of short testimonials (vertical, several columns side by side)",
            "A ticker of changelog items, integrations or stats"
          ],
          "whenNotToUse": [
            "Content people must read or act on in full (use a grid or carousel with controls)",
            "Critical navigation or calls to action"
          ],
          "composesWith": [
            "spotlight-card",
            "badge",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves focus into the first copy of the content and pauses the scroll"
            }
          ],
          "customization": [
            "speed in px/s (default 40); reverse; vertical (set a height with className, e.g. h-80)",
            "gap as px number or CSS length (default 16)",
            "fade toggles the edge mask; pauseOnHover (default true)",
            "Style parts with [data-slot=marquee-track] and [data-slot=marquee-content]"
          ]
        },
        "examples": [
          "marquee-demo",
          "marquee-vertical"
        ],
        "url": "https://ui.ballmac.com/components/marquee"
      }
    },
    {
      "name": "marquee-demo",
      "type": "registry:example",
      "title": "Marquee: Logo row",
      "description": "Logo row example of Marquee.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/marquee.json"
      ],
      "files": [
        {
          "path": "registry/examples/marquee-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/marquee-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "marquee",
        "tier": "free"
      }
    },
    {
      "name": "marquee-vertical",
      "type": "registry:example",
      "title": "Marquee: Vertical testimonials",
      "description": "Vertical testimonials example of Marquee.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/marquee.json"
      ],
      "files": [
        {
          "path": "registry/examples/marquee-vertical.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/marquee-vertical.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "marquee",
        "tier": "free"
      }
    },
    {
      "name": "masonry-grid",
      "type": "registry:ui",
      "title": "Masonry Grid",
      "description": "A gap-free multi-column layout for tiles of different heights, built on CSS columns so it never shifts on load, with responsive column counts and optional reveal.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/masonry-grid.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/masonry-grid.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "masonry",
          "grid",
          "gallery",
          "columns"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "<MasonryGrid columns={{base:2, lg:4}} gap reveal><MasonryItem/>…</MasonryGrid>. DOM order is reading order: down the first column, then the next.",
          "whenToUse": [
            "Galleries, portfolios and boards",
            "Testimonials or notes of uneven length"
          ],
          "whenNotToUse": [
            "Rows that must line up across columns; use CSS grid",
            "Sortable boards; use kanban-board"
          ],
          "composesWith": [
            "card",
            "bento-grid"
          ],
          "a11y": [
            {
              "keys": "Tab order",
              "action": "Follows DOM order, which matches the visual column flow"
            },
            {
              "keys": "Reduced motion",
              "action": "Reveal animation is skipped"
            }
          ],
          "customization": [
            "columns number or per breakpoint",
            "gap: sm | md | lg",
            "reveal"
          ]
        },
        "examples": [
          "masonry-grid-demo",
          "masonry-grid-states"
        ],
        "url": "https://ui.ballmac.com/components/masonry-grid"
      }
    },
    {
      "name": "masonry-grid-demo",
      "type": "registry:example",
      "title": "Masonry Grid: Gallery",
      "description": "Gallery example of Masonry Grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/masonry-grid.json"
      ],
      "files": [
        {
          "path": "registry/examples/masonry-grid-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/masonry-grid-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "masonry-grid",
        "tier": "free"
      }
    },
    {
      "name": "masonry-grid-states",
      "type": "registry:example",
      "title": "Masonry Grid: Notes",
      "description": "Notes example of Masonry Grid.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/masonry-grid.json"
      ],
      "files": [
        {
          "path": "registry/examples/masonry-grid-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/masonry-grid-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "masonry-grid",
        "tier": "free"
      }
    },
    {
      "name": "match-highlight",
      "type": "registry:ui",
      "title": "Match Highlight",
      "description": "Text with the words of a search marked, as search results show them: real mark elements in a theme tint that stays readable in light and dark, plus helpers that split a query and test whether text matches it.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/match-highlight.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/match-highlight.tsx"
        }
      ],
      "categories": [
        "text"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "search",
          "highlight",
          "mark",
          "results",
          "query",
          "autocomplete",
          "snippet"
        ],
        "version": "1.0.0",
        "updated": "2026-10-17",
        "tests": true,
        "ai": {
          "summary": "<MatchHighlight text={result.title} query={query} /> marks every occurrence of every word of the query, ignoring case. queryTokens(query) gives the words, matchesAll(text, query) tests that all of them occur, countMatches(text, query) counts occurrences for ranking. No \"use client\": it works in server components.",
          "whenToUse": [
            "Search results, suggestions and autocomplete rows",
            "Showing why an item matched a filter"
          ],
          "whenNotToUse": [
            "Syntax highlighting of code (use code-block)",
            "A hand-drawn emphasis mark on a phrase (use highlighter)"
          ],
          "composesWith": [
            "search-field",
            "command",
            "help-1",
            "search-1"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Uses <mark>, which assistive technology can announce; the tint is chosen so the text keeps its contrast."
            }
          ],
          "customization": [
            "className sets the look of the wrapper; to change the tint, copy the file and edit the mark's classes",
            "query can be a string or a list of words, so you can pass your own tokens"
          ]
        },
        "statesNone": "A display of text: nothing to load, submit or fail.",
        "examples": [
          "match-highlight-demo",
          "match-highlight-live"
        ],
        "url": "https://ui.ballmac.com/components/match-highlight"
      }
    },
    {
      "name": "match-highlight-demo",
      "type": "registry:example",
      "title": "Match Highlight: Marked matches",
      "description": "Marked matches example of Match Highlight.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/match-highlight.json"
      ],
      "files": [
        {
          "path": "registry/examples/match-highlight-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/match-highlight-demo.tsx"
        }
      ],
      "categories": [
        "text"
      ],
      "meta": {
        "example": true,
        "of": "match-highlight",
        "tier": "free"
      }
    },
    {
      "name": "match-highlight-live",
      "type": "registry:example",
      "title": "Match Highlight: Type to search",
      "description": "Type to search example of Match Highlight.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/match-highlight.json"
      ],
      "files": [
        {
          "path": "registry/examples/match-highlight-live.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/match-highlight-live.tsx"
        }
      ],
      "categories": [
        "text"
      ],
      "meta": {
        "example": true,
        "of": "match-highlight",
        "tier": "free"
      }
    },
    {
      "name": "media",
      "type": "registry:ui",
      "title": "Media",
      "description": "A picture slot: reserves the space, lazy-loads, takes a URL, an image with required alt text and a dark-mode file, or your own element, and falls back to artwork if there is no image or it fails.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/media-image.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/media.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/media.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "image",
          "picture",
          "slot",
          "screenshot",
          "photo",
          "alt text",
          "aspect ratio",
          "dark mode"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "isMediaImage and the MediaImage type moved to the new media-image helper so server components can call it; both are still exported from here. Adds media-image as a dependency.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Pass media as a URL (with alt), an object { src, alt, srcDark? }, or any element such as a next/image. aspect reserves the box (video, photo, square, wide, portrait or '3/2'); fit is cover | contain | fill; priority loads an above-the-fold image eagerly. fallback shows when there is no media or the file fails.",
          "whenToUse": [
            "Any place a product screenshot, photo, cover or avatar goes",
            "Blocks and templates that ship with generated artwork but should accept the buyer's own image"
          ],
          "whenNotToUse": [
            "Icons (use an icon component)",
            "Animated or interactive content that is not an image: pass it as an element"
          ],
          "composesWith": [
            "hero-1",
            "features-5",
            "blog-1"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "Informative images need alt text; alt=\"\" marks decoration. A URL without alt logs a warning in development"
            },
            {
              "keys": "Layout",
              "action": "A fixed aspect ratio reserves the space, so nothing jumps when the file arrives"
            }
          ],
          "customization": [
            "aspect, fit and priority",
            "srcDark for a dark-mode file",
            "position for object-position",
            "fallback for the artwork shown with no image",
            "onImageError"
          ]
        },
        "examples": [
          "media-demo",
          "media-dark"
        ],
        "url": "https://ui.ballmac.com/components/media"
      }
    },
    {
      "name": "media-demo",
      "type": "registry:example",
      "title": "Media: Image, element and fallback",
      "description": "Image, element and fallback example of Media.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/examples/media-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/media-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "media",
        "tier": "free"
      }
    },
    {
      "name": "media-dark",
      "type": "registry:example",
      "title": "Media: A different file in dark mode",
      "description": "A different file in dark mode example of Media.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/examples/media-dark.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/media-dark.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "media",
        "tier": "free"
      }
    },
    {
      "name": "mega-menu",
      "type": "registry:ui",
      "title": "Mega Menu",
      "description": "A data-driven header menu with wide panels of grouped, described links, an optional featured card, and an accordion list for small screens.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/navigation-menu.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/mega-menu.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/mega-menu.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "navigation",
          "dropdown",
          "header",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Pass items: a plain link ({label, href}) or a panel ({label, columns, featured}). MegaMenuMobileList renders the same data for the mobile menu.",
          "whenToUse": [
            "Sites with many products or solutions",
            "Headers that need descriptions beside links"
          ],
          "whenNotToUse": [
            "A handful of plain links; use navbar",
            "Application commands; use menubar"
          ],
          "composesWith": [
            "navbar",
            "navigation-menu"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the focused panel"
            },
            {
              "keys": "ArrowLeft / ArrowRight",
              "action": "Moves between top-level items"
            },
            {
              "keys": "Tab",
              "action": "Enters the panel links"
            },
            {
              "keys": "Escape",
              "action": "Closes the panel"
            }
          ],
          "customization": [
            "columns with titles",
            "featured card with media and cta",
            "badge on links",
            "viewportAlign start | center"
          ]
        },
        "examples": [
          "mega-menu-demo",
          "mega-menu-states"
        ],
        "url": "https://ui.ballmac.com/components/mega-menu"
      }
    },
    {
      "name": "mega-menu-demo",
      "type": "registry:example",
      "title": "Mega Menu: Product menu",
      "description": "Product menu example of Mega Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mega-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/mega-menu-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mega-menu-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "mega-menu",
        "tier": "free"
      }
    },
    {
      "name": "mega-menu-states",
      "type": "registry:example",
      "title": "Mega Menu: Mobile list",
      "description": "Mobile list example of Mega Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mega-menu.json"
      ],
      "files": [
        {
          "path": "registry/examples/mega-menu-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mega-menu-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "mega-menu",
        "tier": "free"
      }
    },
    {
      "name": "mention-input",
      "type": "registry:ui",
      "title": "Mention Input",
      "description": "A text field where typing @ or # opens a list of people, channels or tags: highlighted mentions that know their id, async search, arrow-key choosing, whole-mention backspace and a combobox pattern for screen readers.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/mention-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/mention-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "mention",
          "at-mention",
          "autocomplete",
          "tags",
          "textarea",
          "comments",
          "combobox"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "Hold { text, mentions } in state: <MentionInput value onValueChange sources={[{ trigger: \"@\", options }]} />. options is an array or a function (query, signal) returning options or a promise. mentionsToMarkup and parseMentionMarkup convert to a string.",
          "whenToUse": [
            "Comments, chat and ticket replies where people are mentioned",
            "Tag or channel pickers inside a sentence",
            "Anywhere you need to know which entity a name in the text referred to"
          ],
          "whenNotToUse": [
            "Formatting text as well as mentions; use rich-text-editor",
            "Choosing one value from a list; use combobox",
            "Plain multi-line text; use textarea"
          ],
          "composesWith": [
            "textarea",
            "avatar",
            "rich-text-editor"
          ],
          "a11y": [
            {
              "keys": "Type @ or #",
              "action": "Opens the list under the caret; the field is a combobox with aria-activedescendant"
            },
            {
              "keys": "Arrow Up / Arrow Down",
              "action": "Choose a suggestion; disabled ones are skipped"
            },
            {
              "keys": "Enter / Tab",
              "action": "Insert the highlighted suggestion"
            },
            {
              "keys": "Escape",
              "action": "Close the list without inserting"
            },
            {
              "keys": "Backspace after a mention",
              "action": "Removes the whole mention"
            },
            {
              "keys": "Screen readers",
              "action": "The count of suggestions and the highlighted one are announced; Searching and No matches are announced too"
            }
          ],
          "customization": [
            "sources: trigger, options, label, className for each kind of mention",
            "minRows and maxRows, or singleLine",
            "invalid, disabled and the usual textarea props",
            "onSubmit for Enter in a single line or Ctrl/Cmd+Enter"
          ]
        },
        "statesNone": "Nothing loads on its own: an async source shows a Searching row in the list while it answers, and a No matches row when it finds nothing.",
        "examples": [
          "mention-input-demo",
          "mention-input-async",
          "mention-input-single",
          "mention-input-invalid"
        ],
        "url": "https://ui.ballmac.com/components/mention-input"
      }
    },
    {
      "name": "mention-input-demo",
      "type": "registry:example",
      "title": "Mention Input: People and channels",
      "description": "People and channels example of Mention Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mention-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/mention-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mention-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "mention-input",
        "tier": "free"
      }
    },
    {
      "name": "mention-input-async",
      "type": "registry:example",
      "title": "Mention Input: Search as you type",
      "description": "Search as you type example of Mention Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mention-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/mention-input-async.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mention-input-async.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "mention-input",
        "tier": "free"
      }
    },
    {
      "name": "mention-input-single",
      "type": "registry:example",
      "title": "Mention Input: Single line with tags",
      "description": "Single line with tags example of Mention Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mention-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/mention-input-single.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mention-input-single.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "mention-input",
        "tier": "free"
      }
    },
    {
      "name": "mention-input-invalid",
      "type": "registry:example",
      "title": "Mention Input: Invalid and disabled choices",
      "description": "Invalid and disabled choices example of Mention Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/mention-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/mention-input-invalid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/mention-input-invalid.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "mention-input",
        "tier": "free"
      }
    },
    {
      "name": "menubar",
      "type": "registry:ui",
      "title": "Menubar",
      "description": "A horizontal application menu bar with roving focus across menus, submenus, shortcuts, checkbox and radio items, built on Radix.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/menubar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/menubar.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "menu",
          "application",
          "desktop",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "A File / Edit / View style bar. Left and Right move between menus, Down opens one, and hovering across open menus switches them.",
          "whenToUse": [
            "Editors, dashboards and tools with many commands",
            "Desktop-style web apps"
          ],
          "whenNotToUse": [
            "Website navigation with links; use navigation-menu",
            "The macOS system menu bar mockup; use menu-bar"
          ],
          "composesWith": [
            "kbd",
            "dropdown-menu"
          ],
          "a11y": [
            {
              "keys": "ArrowLeft / ArrowRight",
              "action": "Moves focus between menu triggers"
            },
            {
              "keys": "ArrowDown / Enter / Space",
              "action": "Opens the focused menu"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves within a menu"
            },
            {
              "keys": "Escape",
              "action": "Closes the menu and returns to the bar"
            }
          ],
          "customization": [
            "value on each menu for a default open menu",
            "shortcut hints",
            "checkbox and radio items"
          ]
        },
        "source": {
          "name": "shadcn/ui Menubar",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "menubar-demo",
          "menubar-states"
        ],
        "url": "https://ui.ballmac.com/components/menubar"
      }
    },
    {
      "name": "menubar-demo",
      "type": "registry:example",
      "title": "Menubar: Editor menu",
      "description": "Editor menu example of Menubar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/menubar.json"
      ],
      "files": [
        {
          "path": "registry/examples/menubar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/menubar-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "menubar",
        "tier": "free"
      }
    },
    {
      "name": "menubar-states",
      "type": "registry:example",
      "title": "Menubar: Preferences",
      "description": "Preferences example of Menubar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/menubar.json"
      ],
      "files": [
        {
          "path": "registry/examples/menubar-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/menubar-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "menubar",
        "tier": "free"
      }
    },
    {
      "name": "multi-select",
      "type": "registry:ui",
      "title": "Multi Select",
      "description": "Search and select several options in a Radix popover with native checkboxes and a selection cap.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/multi-select.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/multi-select.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "multi-select",
          "filter",
          "checkbox"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Search and select several options in a Radix popover with native checkboxes and a selection cap.",
          "whenToUse": [
            "Choose multiple teammates or categories",
            "Filter a list by several states"
          ],
          "whenNotToUse": [
            "Use select when only one option is allowed"
          ],
          "composesWith": [
            "select"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Opens the option popover"
            },
            {
              "keys": "Tab / Space",
              "action": "Moves to and toggles native checkboxes"
            },
            {
              "keys": "Escape",
              "action": "Closes the popover"
            }
          ],
          "customization": [
            "options, maxSelected",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "multi-select-demo",
          "multi-select-states"
        ],
        "url": "https://ui.ballmac.com/components/multi-select"
      }
    },
    {
      "name": "multi-select-demo",
      "type": "registry:example",
      "title": "Multi Select: Overview",
      "description": "Overview example of Multi Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/multi-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/multi-select-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/multi-select-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "multi-select",
        "tier": "free"
      }
    },
    {
      "name": "multi-select-states",
      "type": "registry:example",
      "title": "Multi Select: States and variants",
      "description": "States and variants example of Multi Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/multi-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/multi-select-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/multi-select-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "multi-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select",
      "type": "registry:ui",
      "title": "Native Select",
      "description": "The browser's own select, styled to match the input: three sizes, a placeholder, groups, a leading icon, invalid and disabled states and a loading spinner, so phones keep their picker and forms keep working.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/native-select.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/native-select.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "select",
          "native",
          "dropdown",
          "form",
          "mobile",
          "picker",
          "optgroup"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "<NativeSelect name placeholder> with <NativeSelectOption value> children and <NativeSelectGroup label> for groups. It is a real select: use value and onValueChange, or leave it uncontrolled in a form.",
          "whenToUse": [
            "Forms where a short list of choices should use the device's own picker (phones, tablets)",
            "Long lists such as countries or time zones where type-to-jump matters",
            "Anywhere accessibility and autofill should be exactly the browser's"
          ],
          "whenNotToUse": [
            "Options with icons, descriptions or search; use select or combobox",
            "Choosing many items with chips; use multi-select",
            "A handful of choices that deserve to be seen at once; use radio-group or segmented-control"
          ],
          "composesWith": [
            "label",
            "input",
            "field"
          ],
          "a11y": [
            {
              "keys": "Tab / Shift+Tab",
              "action": "Moves to and from the field"
            },
            {
              "keys": "Space / Alt+Down / Enter",
              "action": "Opens the browser's list; arrow keys and typing choose"
            },
            {
              "keys": "Screen readers",
              "action": "It is a real select, so name, value, options and groups are read by the browser; give it a label"
            },
            {
              "keys": "aria-invalid and aria-describedby",
              "action": "Set them with an error message, as on an input"
            }
          ],
          "customization": [
            "size: sm | default | lg, to match input heights",
            "placeholder for a first empty choice (required keeps it from being chosen again)",
            "startIcon, loading, rows for a multiple select",
            "onValueChange as well as onChange"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading options",
            "example": "native-select-loading",
            "trigger": "loading",
            "note": "A spinner takes the arrow's place and the field is marked busy; it can still be opened, and the options appear when they arrive."
          },
          {
            "id": "disabled",
            "title": "Disabled",
            "example": "native-select-disabled",
            "trigger": "disabled",
            "note": "Dimmed and unavailable to the pointer and keyboard, and left out of the form's data, as a native select is."
          }
        ],
        "source": {
          "name": "shadcn/ui Input",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "native-select-demo",
          "native-select-groups",
          "native-select-sizes",
          "native-select-form",
          "native-select-loading",
          "native-select-disabled"
        ],
        "url": "https://ui.ballmac.com/components/native-select"
      }
    },
    {
      "name": "native-select-demo",
      "type": "registry:example",
      "title": "Native Select: With a placeholder",
      "description": "With a placeholder example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select-groups",
      "type": "registry:example",
      "title": "Native Select: Groups and an icon",
      "description": "Groups and an icon example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-groups.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-groups.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select-sizes",
      "type": "registry:example",
      "title": "Native Select: Sizes",
      "description": "Sizes example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-sizes.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-sizes.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select-form",
      "type": "registry:example",
      "title": "Native Select: In a form, with an error",
      "description": "In a form, with an error example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-form.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-form.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select-loading",
      "type": "registry:example",
      "title": "Native Select: Options still loading",
      "description": "Options still loading example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-loading.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "native-select-disabled",
      "type": "registry:example",
      "title": "Native Select: Disabled, invalid and multiple",
      "description": "Disabled, invalid and multiple example of Native Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/native-select.json"
      ],
      "files": [
        {
          "path": "registry/examples/native-select-disabled.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/native-select-disabled.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "native-select",
        "tier": "free"
      }
    },
    {
      "name": "navbar",
      "type": "registry:ui",
      "title": "Navbar",
      "description": "A responsive site header that gains a border and shadow on scroll, can hide while scrolling down, and turns its links into a sheet menu on small screens.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/sheet.json",
        "https://ui.ballmac.com/r/scroll.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/navbar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/navbar.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "header",
          "navigation",
          "sticky",
          "responsive"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Compose Navbar with NavbarBrand, NavbarLinks/NavbarLink (active sets aria-current), NavbarActions and NavbarMobileMenu with NavbarMobileLink.",
          "whenToUse": [
            "Marketing and docs site headers",
            "Headers that should get out of the way on long pages"
          ],
          "whenNotToUse": [
            "Application chrome with a sidebar; use app-shell",
            "Wide dropdown panels; add mega-menu"
          ],
          "composesWith": [
            "mega-menu",
            "button",
            "sheet"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves through brand, links, actions and the menu button"
            },
            {
              "keys": "Enter / Space",
              "action": "Opens the mobile menu; Escape closes it and returns focus"
            },
            {
              "keys": "Screen readers",
              "action": "Links are in a labelled navigation landmark; the current page has aria-current"
            }
          ],
          "customization": [
            "sticky and hideOnScroll",
            "border: scrolled | always | never",
            "scrollContainer for headers inside panels",
            "mobile menu label"
          ]
        },
        "examples": [
          "navbar-demo",
          "navbar-states"
        ],
        "url": "https://ui.ballmac.com/components/navbar"
      }
    },
    {
      "name": "navbar-demo",
      "type": "registry:example",
      "title": "Navbar: Marketing header",
      "description": "Marketing header example of Navbar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/navbar.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/navbar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/navbar-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "navbar",
        "tier": "free"
      }
    },
    {
      "name": "navbar-states",
      "type": "registry:example",
      "title": "Navbar: Hide on scroll",
      "description": "Hide on scroll example of Navbar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/navbar.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/navbar-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/navbar-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "navbar",
        "tier": "free"
      }
    },
    {
      "name": "navigation-menu",
      "type": "registry:ui",
      "title": "Navigation Menu",
      "description": "A site navigation bar with flyout panels sharing one animated viewport that resizes to its content, with keyboard and pointer intent handling, built on Radix.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/navigation-menu.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/navigation-menu.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "navigation",
          "header",
          "mega menu",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Top-level triggers open content panels of links. Use navigationMenuTriggerStyle for plain top-level links.",
          "whenToUse": [
            "Marketing site headers",
            "Docs navigation with grouped links"
          ],
          "whenNotToUse": [
            "An application command menu; use menubar",
            "A small overflow list; use dropdown-menu"
          ],
          "composesWith": [
            "button",
            "separator"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the focused panel"
            },
            {
              "keys": "Tab",
              "action": "Moves into the panel links"
            },
            {
              "keys": "ArrowLeft / ArrowRight",
              "action": "Moves between top-level items"
            },
            {
              "keys": "Escape",
              "action": "Closes the panel"
            }
          ],
          "customization": [
            "viewport: shared or per-item",
            "indicator arrow",
            "content width per panel"
          ]
        },
        "source": {
          "name": "shadcn/ui Navigation Menu",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "navigation-menu-demo",
          "navigation-menu-states"
        ],
        "url": "https://ui.ballmac.com/components/navigation-menu"
      }
    },
    {
      "name": "navigation-menu-demo",
      "type": "registry:example",
      "title": "Navigation Menu: Product menu",
      "description": "Product menu example of Navigation Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/navigation-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/navigation-menu-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/navigation-menu-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "navigation-menu",
        "tier": "free"
      }
    },
    {
      "name": "navigation-menu-states",
      "type": "registry:example",
      "title": "Navigation Menu: Without viewport",
      "description": "Without viewport example of Navigation Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/navigation-menu.json"
      ],
      "files": [
        {
          "path": "registry/examples/navigation-menu-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/navigation-menu-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "navigation-menu",
        "tier": "free"
      }
    },
    {
      "name": "number-input",
      "type": "registry:ui",
      "title": "Number Input",
      "description": "A bounded numeric field with native spinbutton semantics, step buttons, and controlled or uncontrolled state.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/number-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/number-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "number",
          "stepper",
          "spinbutton"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A bounded numeric field with native spinbutton semantics, step buttons, and controlled or uncontrolled state.",
          "whenToUse": [
            "Choose a quantity or bounded count",
            "Adjust a value precisely using keys or buttons"
          ],
          "whenNotToUse": [
            "Use a slider when approximate adjustment is sufficient"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Arrow Up / Down",
              "action": "Changes the native numeric value"
            },
            {
              "keys": "Tab / Enter",
              "action": "Operates the step buttons"
            }
          ],
          "customization": [
            "min, max, step",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "number-input-demo",
          "number-input-states"
        ],
        "url": "https://ui.ballmac.com/components/number-input"
      }
    },
    {
      "name": "number-input-demo",
      "type": "registry:example",
      "title": "Number Input: Overview",
      "description": "Overview example of Number Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/number-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/number-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/number-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "number-input",
        "tier": "free"
      }
    },
    {
      "name": "number-input-states",
      "type": "registry:example",
      "title": "Number Input: States and variants",
      "description": "States and variants example of Number Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/number-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/number-input-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/number-input-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "number-input",
        "tier": "free"
      }
    },
    {
      "name": "number-ticker",
      "type": "registry:ui",
      "title": "Number Ticker",
      "description": "Counts up to a number when it scrolls into view, with locale-aware formatting for currency, percentages and decimals.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/number-ticker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/number-ticker.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "animation",
          "counter",
          "stats",
          "motion"
        ],
        "version": "1.0.1",
        "updated": "2026-10-02",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-02",
            "note": "The locale prop now defaults to the I18nProvider locale (still en-US without a provider) instead of a fixed en-US. Adds the i18n helper as a dependency.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Animated number for stats and KPIs. Respects reduced motion by showing the final value immediately.",
          "whenToUse": [
            "Stat sections on landing pages",
            "Dashboard KPIs that load in"
          ],
          "whenNotToUse": [
            "Numbers that update every second (animate a live value instead)",
            "Prices users need to read instantly"
          ],
          "composesWith": [
            "text-reveal",
            "badge"
          ],
          "a11y": [],
          "customization": [
            "format accepts any Intl.NumberFormat options",
            "locale defaults to en-US so server and browser render identical text; pass your locale explicitly",
            "duration and delay in seconds"
          ]
        },
        "examples": [
          "number-ticker-demo",
          "number-ticker-currency"
        ],
        "url": "https://ui.ballmac.com/components/number-ticker"
      }
    },
    {
      "name": "number-ticker-demo",
      "type": "registry:example",
      "title": "Number Ticker: Default",
      "description": "Default example of Number Ticker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/number-ticker.json"
      ],
      "files": [
        {
          "path": "registry/examples/number-ticker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/number-ticker-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "number-ticker",
        "tier": "free"
      }
    },
    {
      "name": "number-ticker-currency",
      "type": "registry:example",
      "title": "Number Ticker: Currency",
      "description": "Currency example of Number Ticker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/number-ticker.json"
      ],
      "files": [
        {
          "path": "registry/examples/number-ticker-currency.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/number-ticker-currency.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "number-ticker",
        "tier": "free"
      }
    },
    {
      "name": "pagination",
      "type": "registry:ui",
      "title": "Pagination",
      "description": "A semantic page navigation set with current-page feedback, generous targets, and small-screen labels.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/pagination.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/pagination.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "pages",
          "navigation",
          "links"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "tests": true,
        "ai": {
          "summary": "A semantic page navigation set with current-page feedback, generous targets, and small-screen labels.",
          "whenToUse": [
            "Navigate a large result set by page",
            "Show a current page and neighboring destinations"
          ],
          "whenNotToUse": [
            "Use infinite scroll when discrete pages are unnecessary"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "moves between page links"
            },
            {
              "keys": "Enter",
              "action": "opens the focused page"
            }
          ],
          "customization": [
            "isActive: marks the current page"
          ]
        },
        "source": {
          "name": "shadcn/ui Pagination",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "pagination-demo",
          "pagination-states"
        ],
        "url": "https://ui.ballmac.com/components/pagination"
      }
    },
    {
      "name": "pagination-demo",
      "type": "registry:example",
      "title": "Pagination: Overview",
      "description": "Overview example of Pagination.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/pagination.json"
      ],
      "files": [
        {
          "path": "registry/examples/pagination-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/pagination-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "pagination",
        "tier": "free"
      }
    },
    {
      "name": "pagination-states",
      "type": "registry:example",
      "title": "Pagination: States and variants",
      "description": "States and variants example of Pagination.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/pagination.json"
      ],
      "files": [
        {
          "path": "registry/examples/pagination-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/pagination-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "pagination",
        "tier": "free"
      }
    },
    {
      "name": "password-input",
      "type": "registry:ui",
      "title": "Password Input",
      "description": "A password field with a visibility toggle and a four-step strength guide that explains how to improve the entry.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/password-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/password-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "password",
          "security",
          "strength"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A password field with a visibility toggle and a four-step strength guide that explains how to improve the entry.",
          "whenToUse": [
            "Create or change a password",
            "Give immediate guidance while typing"
          ],
          "whenNotToUse": [
            "Use input for a standard text field"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Tab / Space",
              "action": "Toggles password visibility"
            }
          ],
          "customization": [
            "showStrength",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "password-input-demo",
          "password-input-states"
        ],
        "url": "https://ui.ballmac.com/components/password-input"
      }
    },
    {
      "name": "password-input-demo",
      "type": "registry:example",
      "title": "Password Input: Overview",
      "description": "Overview example of Password Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/password-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/password-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/password-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "password-input",
        "tier": "free"
      }
    },
    {
      "name": "password-input-states",
      "type": "registry:example",
      "title": "Password Input: States and variants",
      "description": "States and variants example of Password Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/password-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/password-input-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/password-input-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "password-input",
        "tier": "free"
      }
    },
    {
      "name": "phone-input",
      "type": "registry:ui",
      "title": "Phone Input",
      "description": "A native dialing-code selector paired with a telephone field that preserves the user’s formatting.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/phone-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/phone-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "phone",
          "telephone",
          "country"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A native dialing-code selector paired with a telephone field that preserves the user’s formatting.",
          "whenToUse": [
            "Collect a contact number with a dialing prefix",
            "Edit a national number without forced formatting"
          ],
          "whenNotToUse": [
            "Use input type tel when a country selector is unnecessary"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Arrow Up / Down",
              "action": "Changes the native dialing-code selection"
            },
            {
              "keys": "Tab",
              "action": "Moves to the telephone field"
            }
          ],
          "customization": [
            "countries, countryCodeName",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "phone-input-demo",
          "phone-input-states"
        ],
        "url": "https://ui.ballmac.com/components/phone-input"
      }
    },
    {
      "name": "phone-input-demo",
      "type": "registry:example",
      "title": "Phone Input: Overview",
      "description": "Overview example of Phone Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/phone-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/phone-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/phone-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "phone-input",
        "tier": "free"
      }
    },
    {
      "name": "phone-input-states",
      "type": "registry:example",
      "title": "Phone Input: States and variants",
      "description": "States and variants example of Phone Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/phone-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/phone-input-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/phone-input-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "phone-input",
        "tier": "free"
      }
    },
    {
      "name": "popover",
      "type": "registry:ui",
      "title": "Popover",
      "description": "A focus-managed compact surface for controls or details, with collision handling, mobile-safe width, and optional close action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/popover.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/popover.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "overlay",
          "panel",
          "editor",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Displays a small interactive panel anchored to a control, with managed focus and Escape dismissal.",
          "whenToUse": [
            "Inline editors and compact preferences",
            "Actions needing more room than a menu"
          ],
          "whenNotToUse": [
            "Long or critical forms; use dialog",
            "Noninteractive link previews; use hover-card"
          ],
          "composesWith": [
            "button",
            "input"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Opens the panel from its trigger"
            },
            {
              "keys": "Tab / Shift+Tab",
              "action": "Moves among panel controls"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            }
          ],
          "customization": [
            "alignment and side offset",
            "optional close button",
            "controlled open state"
          ]
        },
        "examples": [
          "popover-demo",
          "popover-states"
        ],
        "url": "https://ui.ballmac.com/components/popover"
      }
    },
    {
      "name": "popover-demo",
      "type": "registry:example",
      "title": "Popover: Share settings",
      "description": "Share settings example of Popover.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/popover.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/popover-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/popover-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "popover",
        "tier": "free"
      }
    },
    {
      "name": "popover-states",
      "type": "registry:example",
      "title": "Popover: Profile details",
      "description": "Profile details example of Popover.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/popover.json"
      ],
      "files": [
        {
          "path": "registry/examples/popover-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/popover-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "popover",
        "tier": "free"
      }
    },
    {
      "name": "product-art",
      "type": "registry:ui",
      "title": "Product Art",
      "description": "Soft square placeholders with a simple object drawn in a chart color, for product grids, carts and detail pages before real photos exist, or as the fallback when a photo fails to load. Theme tokens only.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/product-art.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/product-art.tsx"
        }
      ],
      "categories": [
        "marketing"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "ecommerce",
          "product",
          "placeholder",
          "illustration",
          "image",
          "shop",
          "fallback"
        ],
        "version": "1.0.0",
        "updated": "2026-10-25",
        "tests": true,
        "ai": {
          "summary": "kind is 'speaker' | 'mug' | 'bag' | 'lamp' | 'bottle' | 'headphones'; tone is 1 to 5 (the chart color that tints the background and the object). It fills the width it is given as a square. Pass label to describe it as an image; without a label it is hidden from screen readers.",
          "whenToUse": [
            "Product cards and galleries in demos, templates and loading states",
            "A fallback when a product photo is missing"
          ],
          "whenNotToUse": [
            "Real product photography; use an image",
            "Icons; use lucide-react"
          ],
          "composesWith": [
            "ecommerce-1",
            "ecommerce-2",
            "ecommerce-3",
            "ecommerce-4"
          ],
          "a11y": [
            {
              "keys": "Image",
              "action": "Decorative by default (aria-hidden); with label it is role=img with that name"
            }
          ],
          "customization": [
            "kind and tone",
            "label",
            "className for the shape"
          ]
        },
        "statesNone": "A static illustration: nothing to load or fail.",
        "examples": [
          "product-art-demo",
          "product-art-tones"
        ],
        "url": "https://ui.ballmac.com/components/product-art"
      }
    },
    {
      "name": "product-art-demo",
      "type": "registry:example",
      "title": "Product Art: Six objects",
      "description": "Six objects example of Product Art.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/product-art.json"
      ],
      "files": [
        {
          "path": "registry/examples/product-art-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/product-art-demo.tsx"
        }
      ],
      "categories": [
        "marketing"
      ],
      "meta": {
        "example": true,
        "of": "product-art",
        "tier": "free"
      }
    },
    {
      "name": "product-art-tones",
      "type": "registry:example",
      "title": "Product Art: Five tones",
      "description": "Five tones example of Product Art.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/product-art.json"
      ],
      "files": [
        {
          "path": "registry/examples/product-art-tones.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/product-art-tones.tsx"
        }
      ],
      "categories": [
        "marketing"
      ],
      "meta": {
        "example": true,
        "of": "product-art",
        "tier": "free"
      }
    },
    {
      "name": "progress-steps",
      "type": "registry:ui",
      "title": "Progress Steps",
      "description": "An ordered progress sequence with current-step semantics and optional navigation to completed steps.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/progress-steps.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/progress-steps.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "steps",
          "wizard",
          "progress"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "An ordered progress sequence with current-step semantics and optional navigation to completed steps.",
          "whenToUse": [
            "Show a multi-step flow",
            "Let users revisit completed steps"
          ],
          "whenNotToUse": [
            "Use progress for an unlabelled percentage"
          ],
          "composesWith": [
            "stepper-form",
            "progress"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter",
              "action": "Return to a completed step when navigable"
            }
          ],
          "customization": [
            "Controlled or uncontrolled active index",
            "Optional descriptions"
          ]
        },
        "examples": [
          "progress-steps-demo",
          "progress-steps-states"
        ],
        "url": "https://ui.ballmac.com/components/progress-steps"
      }
    },
    {
      "name": "progress-steps-demo",
      "type": "registry:example",
      "title": "Progress Steps: Overview",
      "description": "Overview example of Progress Steps.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/progress-steps.json"
      ],
      "files": [
        {
          "path": "registry/examples/progress-steps-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/progress-steps-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "progress-steps",
        "tier": "free"
      }
    },
    {
      "name": "progress-steps-states",
      "type": "registry:example",
      "title": "Progress Steps: States and variants",
      "description": "States and variants example of Progress Steps.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/progress-steps.json"
      ],
      "files": [
        {
          "path": "registry/examples/progress-steps-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/progress-steps-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "progress-steps",
        "tier": "free"
      }
    },
    {
      "name": "progress",
      "type": "registry:ui",
      "title": "Progress",
      "description": "A Radix progress bar with clamped values, optional percentage text, and a reduced-motion-safe pending state.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/progress.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/progress.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "loading",
          "progress",
          "status"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A Radix progress bar with clamped values, optional percentage text, and a reduced-motion-safe pending state.",
          "whenToUse": [
            "Show completion of a bounded task",
            "Show work in progress when completion is unknown"
          ],
          "whenNotToUse": [
            "Use a spinner for very short waits"
          ],
          "composesWith": [
            "spinner"
          ],
          "a11y": [],
          "customization": [
            "value: current value or null for indeterminate",
            "showValue: display percentage"
          ]
        },
        "source": {
          "name": "shadcn/ui Progress",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "progress-demo",
          "progress-states"
        ],
        "url": "https://ui.ballmac.com/components/progress"
      }
    },
    {
      "name": "progress-demo",
      "type": "registry:example",
      "title": "Progress: Overview",
      "description": "Overview example of Progress.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/progress.json"
      ],
      "files": [
        {
          "path": "registry/examples/progress-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/progress-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "progress",
        "tier": "free"
      }
    },
    {
      "name": "progress-states",
      "type": "registry:example",
      "title": "Progress: States and variants",
      "description": "States and variants example of Progress.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/progress.json"
      ],
      "files": [
        {
          "path": "registry/examples/progress-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/progress-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "progress",
        "tier": "free"
      }
    },
    {
      "name": "radio-group",
      "type": "registry:ui",
      "title": "Radio Group",
      "description": "Single-choice radios with optional full-card labels, descriptions, and large pointer targets around Radix keyboard navigation.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/radio-group.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/radio-group.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "choice",
          "form",
          "radio",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Switch track, thumb travel, and checkbox and radio size follow the platform feel tokens (--bm-switch-*, --bm-check-size); select and command surfaces take the feel's frosting. Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Choose exactly one option in a form; use descriptive card labels when choices need context.",
          "whenToUse": [
            "A few mutually exclusive preferences",
            "Pricing or delivery options with explanations"
          ],
          "whenNotToUse": [
            "Many options; use select",
            "Multiple selections; use checkbox or toggle-group"
          ],
          "composesWith": [
            "label"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Enters the radio group"
            },
            {
              "keys": "Arrow keys",
              "action": "Moves and selects among enabled choices"
            },
            {
              "keys": "Space",
              "action": "Selects the focused choice"
            }
          ],
          "customization": [
            "controlled or uncontrolled value",
            "card or compact radio labels",
            "disabled options"
          ]
        },
        "examples": [
          "radio-group-demo",
          "radio-group-states"
        ],
        "url": "https://ui.ballmac.com/components/radio-group"
      }
    },
    {
      "name": "radio-group-demo",
      "type": "registry:example",
      "title": "Radio Group: Delivery frequency",
      "description": "Delivery frequency example of Radio Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/radio-group.json"
      ],
      "files": [
        {
          "path": "registry/examples/radio-group-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/radio-group-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "radio-group",
        "tier": "free"
      }
    },
    {
      "name": "radio-group-states",
      "type": "registry:example",
      "title": "Radio Group: Compact choices",
      "description": "Compact choices example of Radio Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/radio-group.json"
      ],
      "files": [
        {
          "path": "registry/examples/radio-group-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/radio-group-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "radio-group",
        "tier": "free"
      }
    },
    {
      "name": "rating-distribution",
      "type": "registry:ui",
      "title": "Rating Distribution",
      "description": "The shape of a set of ratings: the average with partly filled stars, the count, and a bar per star size that can filter the reviews beside it.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/rating-distribution.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/rating-distribution.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "reviews",
          "rating",
          "stars",
          "distribution",
          "histogram",
          "feedback",
          "ecommerce"
        ],
        "version": "1.0.0",
        "updated": "2026-10-25",
        "tests": true,
        "ai": {
          "summary": "counts is { 1, 2, 3, 4, 5 } (how many of each). The average and total are computed and written as text. onSelect(rating | null) with selected makes each row a toggle button for filtering a review list.",
          "whenToUse": [
            "Above a list of product, app or course reviews",
            "A feedback summary"
          ],
          "whenNotToUse": [
            "Collecting a rating; use rating",
            "Satisfaction over time; use chart-line"
          ],
          "composesWith": [
            "rating",
            "bar-list",
            "split-bar",
            "stat-card"
          ],
          "a11y": [
            {
              "keys": "Summary",
              "action": "The average and total are text; the stars are decoration"
            },
            {
              "keys": "Rows",
              "action": "Buttons named '4 stars: 2 ratings. Show only these' with pressed state"
            },
            {
              "keys": "Counts",
              "action": "Shown as numbers and percents beside each bar"
            }
          ],
          "customization": [
            "counts",
            "onSelect and selected"
          ]
        },
        "statesNone": "A presentational summary: the counts are passed in, so it has nothing of its own to load.",
        "examples": [
          "rating-distribution-demo",
          "rating-distribution-static"
        ],
        "url": "https://ui.ballmac.com/components/rating-distribution"
      }
    },
    {
      "name": "rating-distribution-demo",
      "type": "registry:example",
      "title": "Rating Distribution: Filtering by star size",
      "description": "Filtering by star size example of Rating Distribution.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rating-distribution.json"
      ],
      "files": [
        {
          "path": "registry/examples/rating-distribution-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rating-distribution-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "rating-distribution",
        "tier": "free"
      }
    },
    {
      "name": "rating-distribution-static",
      "type": "registry:example",
      "title": "Rating Distribution: Few ratings",
      "description": "Few ratings example of Rating Distribution.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rating-distribution.json"
      ],
      "files": [
        {
          "path": "registry/examples/rating-distribution-static.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rating-distribution-static.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "rating-distribution",
        "tier": "free"
      }
    },
    {
      "name": "rating",
      "type": "registry:ui",
      "title": "Rating",
      "description": "A native radio-group star rating with keyboard arrows, value text, and a clear action.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/rating.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/rating.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "rating",
          "stars",
          "feedback"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A native radio-group star rating with keyboard arrows, value text, and a clear action.",
          "whenToUse": [
            "Collect a quick score or satisfaction rating",
            "Display a read-only score beside content"
          ],
          "whenNotToUse": [
            "Use a text field for detailed feedback"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [
            {
              "keys": "Arrow Left / Right",
              "action": "Changes the selected native radio"
            },
            {
              "keys": "Tab / Space",
              "action": "Focuses and activates Clear"
            }
          ],
          "customization": [
            "max, showValue, readOnly",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "rating-demo",
          "rating-states"
        ],
        "url": "https://ui.ballmac.com/components/rating"
      }
    },
    {
      "name": "rating-demo",
      "type": "registry:example",
      "title": "Rating: Overview",
      "description": "Overview example of Rating.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rating.json"
      ],
      "files": [
        {
          "path": "registry/examples/rating-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rating-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rating",
        "tier": "free"
      }
    },
    {
      "name": "rating-states",
      "type": "registry:example",
      "title": "Rating: States and variants",
      "description": "States and variants example of Rating.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rating.json"
      ],
      "files": [
        {
          "path": "registry/examples/rating-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rating-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rating",
        "tier": "free"
      }
    },
    {
      "name": "resizable",
      "type": "registry:ui",
      "title": "Resizable",
      "description": "Draggable split panels with keyboard resizing, nested horizontal and vertical groups, collapsible panels, and a grip that appears on hover and focus.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "react-resizable-panels@^3",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/resizable.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/resizable.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "panels",
          "split",
          "layout",
          "resize"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "ResizablePanelGroup with ResizablePanel children separated by ResizableHandle. Sizes are percentages. Give each handle a label.",
          "whenToUse": [
            "IDE, email and file-manager layouts",
            "User-adjustable sidebars and consoles"
          ],
          "whenNotToUse": [
            "Fixed layouts; use plain CSS grid",
            "App navigation; use sidebar"
          ],
          "composesWith": [
            "scroll-area",
            "separator"
          ],
          "a11y": [
            {
              "keys": "ArrowLeft / ArrowRight (ArrowUp / ArrowDown)",
              "action": "Resize by 10% steps from the focused handle"
            },
            {
              "keys": "Home / End",
              "action": "Move to minimum or maximum"
            },
            {
              "keys": "Enter",
              "action": "Collapse or expand a collapsible neighbor"
            }
          ],
          "customization": [
            "direction",
            "defaultSize, minSize, maxSize",
            "collapsible panels",
            "autoSaveId to remember sizes",
            "withHandle grip"
          ]
        },
        "source": {
          "name": "shadcn/ui Resizable",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "resizable-demo",
          "resizable-states"
        ],
        "url": "https://ui.ballmac.com/components/resizable"
      }
    },
    {
      "name": "resizable-demo",
      "type": "registry:example",
      "title": "Resizable: Editor layout",
      "description": "Editor layout example of Resizable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/resizable.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/resizable-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/resizable-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "resizable",
        "tier": "free"
      }
    },
    {
      "name": "resizable-states",
      "type": "registry:example",
      "title": "Resizable: Collapsible panel",
      "description": "Collapsible panel example of Resizable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/resizable.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "react-resizable-panels@^3"
      ],
      "files": [
        {
          "path": "registry/examples/resizable-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/resizable-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "resizable",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor",
      "type": "registry:ui",
      "title": "Rich Text Editor",
      "description": "A rich text editor on Tiptap: headings, bold, lists, checklists, quotes, code and links, with a toolbar you drive by keyboard, a slash menu for blocks, a link popover, a character limit and HTML output.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "@tiptap/core@^3",
        "@tiptap/react@^3",
        "@tiptap/pm@^3",
        "@tiptap/starter-kit@^3",
        "@tiptap/extensions@^3",
        "@tiptap/extension-list@^3",
        "@tiptap/extension-text-align@^3",
        "@tiptap/suggestion@^3",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/popover.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/rich-text-editor.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/rich-text-editor.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "editor",
          "wysiwyg",
          "rich text",
          "tiptap",
          "markdown",
          "slash menu",
          "comments"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "Hold the HTML in state: <RichTextEditor label value={html} onChange={setHtml} />. Pick tools with features, add characterLimit and showCount, and mark invalid with description. Sanitize the HTML before you store or show it.",
          "whenToUse": [
            "Comments, descriptions, notes and release notes people format",
            "Content that is stored as HTML and shown elsewhere",
            "Forms that need a labelled, validated, accessible editor"
          ],
          "whenNotToUse": [
            "Plain multi-line text; use textarea",
            "Code editing with syntax highlighting; use a code editor",
            "Real-time collaboration, comments in the margin or tables out of the box; build on the Tiptap editor from editorRef"
          ],
          "composesWith": [
            "button",
            "popover",
            "label",
            "field"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "The toolbar is one tab stop, and the editor is the next; Escape then Tab leaves the editor"
            },
            {
              "keys": "Arrow keys / Home / End (toolbar)",
              "action": "Move between tools; they swap in right-to-left"
            },
            {
              "keys": "Ctrl or Cmd + B, I, U, K",
              "action": "Bold, italic, underline and the link popover; markdown shortcuts like ## and - work as you type"
            },
            {
              "keys": "/",
              "action": "Opens the block menu; Up and Down choose, Enter inserts, Escape closes, and the highlighted block is announced"
            },
            {
              "keys": "Screen readers",
              "action": "The editor is a labelled multiline textbox; tools are toggle buttons with aria-pressed; invalid and disabled are set on the textbox"
            }
          ],
          "customization": [
            "features: heading, bold, italic, underline, strike, code, link, bulletList, orderedList, taskList, blockquote, codeBlock, horizontalRule, align, undo, slash",
            "characterLimit, showCount, minHeight, maxHeight",
            "invalid with description for the hint and the error",
            "editorRef for the Tiptap editor, to add extensions or commands"
          ]
        },
        "states": [
          {
            "id": "loading",
            "title": "Loading",
            "example": "rich-text-editor-loading",
            "trigger": "state=\"loading\"",
            "note": "A toolbar and lines drawn as skeletons, announced as loading, for content that is still being fetched."
          },
          {
            "id": "error",
            "title": "Could not load",
            "example": "rich-text-editor-error",
            "trigger": "state=\"error\"",
            "note": "An error with a Try again button (onRetry), announced as an alert."
          },
          {
            "id": "disabled",
            "title": "Disabled",
            "example": "rich-text-editor-disabled",
            "trigger": "disabled",
            "note": "The content stays readable and selectable; the toolbar and typing are off and the editor says it is disabled."
          }
        ],
        "source": {
          "name": "Tiptap",
          "url": "https://github.com/ueberdosis/tiptap",
          "license": "MIT",
          "copyright": "Copyright (c) 2025, Tiptap GmbH",
          "modified": true
        },
        "examples": [
          "rich-text-editor-demo",
          "rich-text-editor-minimal",
          "rich-text-editor-form",
          "rich-text-editor-checklist",
          "rich-text-editor-disabled",
          "rich-text-editor-loading",
          "rich-text-editor-error"
        ],
        "url": "https://ui.ballmac.com/components/rich-text-editor"
      }
    },
    {
      "name": "rich-text-editor-demo",
      "type": "registry:example",
      "title": "Rich Text Editor: Release notes",
      "description": "Release notes example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-minimal",
      "type": "registry:example",
      "title": "Rich Text Editor: Comment box with a limit",
      "description": "Comment box with a limit example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-minimal.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-minimal.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-form",
      "type": "registry:example",
      "title": "Rich Text Editor: In a form",
      "description": "In a form example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-form.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-form.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-checklist",
      "type": "registry:example",
      "title": "Rich Text Editor: Checklist",
      "description": "Checklist example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-checklist.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-checklist.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-disabled",
      "type": "registry:example",
      "title": "Rich Text Editor: Disabled",
      "description": "Disabled example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-disabled.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-disabled.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-loading",
      "type": "registry:example",
      "title": "Rich Text Editor: Loading",
      "description": "Loading example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-loading.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-loading.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "rich-text-editor-error",
      "type": "registry:example",
      "title": "Rich Text Editor: Could not load",
      "description": "Could not load example of Rich Text Editor.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/rich-text-editor.json"
      ],
      "files": [
        {
          "path": "registry/examples/rich-text-editor-error.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/rich-text-editor-error.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "rich-text-editor",
        "tier": "free"
      }
    },
    {
      "name": "scroll-area",
      "type": "registry:ui",
      "title": "Scroll Area",
      "description": "A focusable, named scroll region with theme-aware custom thumb and native scrolling behavior for long lists and documents.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/scroll-area.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/scroll-area.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "scroll",
          "overflow",
          "region",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Constrains long content in an accessible keyboard-scrollable region without changing native scroll behavior.",
          "whenToUse": [
            "Activity feeds and long lists",
            "Constrained side panels"
          ],
          "whenNotToUse": [
            "Short content that can fit naturally",
            "The main page scroll"
          ],
          "composesWith": [
            "activity-feed"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focuses the named scroll region"
            },
            {
              "keys": "Arrow keys / Page Up / Page Down",
              "action": "Scrolls the focused region"
            }
          ],
          "customization": [
            "vertical and horizontal scrollbar",
            "accessible label",
            "viewport height"
          ]
        },
        "examples": [
          "scroll-area-demo",
          "scroll-area-states"
        ],
        "url": "https://ui.ballmac.com/components/scroll-area"
      }
    },
    {
      "name": "scroll-area-demo",
      "type": "registry:example",
      "title": "Scroll Area: Recent activity",
      "description": "Recent activity example of Scroll Area.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/scroll-area.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/scroll-area-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/scroll-area-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "scroll-area",
        "tier": "free"
      }
    },
    {
      "name": "scroll-area-states",
      "type": "registry:example",
      "title": "Scroll Area: Horizontal gallery",
      "description": "Horizontal gallery example of Scroll Area.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/scroll-area.json"
      ],
      "files": [
        {
          "path": "registry/examples/scroll-area-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/scroll-area-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "scroll-area",
        "tier": "free"
      }
    },
    {
      "name": "scroll-progress",
      "type": "registry:ui",
      "title": "Scroll Progress",
      "description": "A thin reading-progress bar fixed to the top or bottom of the page, or to a scrollable panel, that fills on a soft spring (or exactly under reduced motion).",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/scroll-progress.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/scroll-progress.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "progress",
          "reading",
          "scroll",
          "indicator"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Render <ScrollProgress /> once. Pass container (a ref) to follow a scrollable element and add className='absolute' inside its wrapper.",
          "whenToUse": [
            "Long articles and docs",
            "Multi-section landing pages"
          ],
          "whenNotToUse": [
            "Task or upload progress; use progress",
            "Step indicators; use progress-steps"
          ],
          "composesWith": [
            "table-of-contents",
            "back-to-top"
          ],
          "a11y": [
            {
              "keys": "Screen readers",
              "action": "Decorative (aria-hidden); the page's own scroll position is already exposed"
            },
            {
              "keys": "Reduced motion",
              "action": "No spring smoothing"
            }
          ],
          "customization": [
            "position: top | bottom",
            "thickness",
            "container"
          ]
        },
        "examples": [
          "scroll-progress-demo",
          "scroll-progress-states"
        ],
        "url": "https://ui.ballmac.com/components/scroll-progress"
      }
    },
    {
      "name": "scroll-progress-demo",
      "type": "registry:example",
      "title": "Scroll Progress: Article progress",
      "description": "Article progress example of Scroll Progress.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/scroll-progress.json"
      ],
      "files": [
        {
          "path": "registry/examples/scroll-progress-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/scroll-progress-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "scroll-progress",
        "tier": "free"
      }
    },
    {
      "name": "scroll-progress-states",
      "type": "registry:example",
      "title": "Scroll Progress: Bottom, thicker",
      "description": "Bottom, thicker example of Scroll Progress.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/scroll-progress.json"
      ],
      "files": [
        {
          "path": "registry/examples/scroll-progress-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/scroll-progress-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "scroll-progress",
        "tier": "free"
      }
    },
    {
      "name": "search-field",
      "type": "registry:ui",
      "title": "Search Field",
      "description": "A compact search control with a clear action, Enter callback, and preserved keyboard focus.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/search-field.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/search-field.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "search",
          "filter",
          "input"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A compact search control with a clear action, Enter callback, and preserved keyboard focus.",
          "whenToUse": [
            "Filter a list or catalog",
            "Submit a query from a toolbar"
          ],
          "whenNotToUse": [
            "Use spotlight-search for site-wide command search"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Enter",
              "action": "Submits the current query"
            },
            {
              "keys": "Tab / Space",
              "action": "Clears the query and returns focus"
            }
          ],
          "customization": [
            "onSearch",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "search-field-demo",
          "search-field-states"
        ],
        "url": "https://ui.ballmac.com/components/search-field"
      }
    },
    {
      "name": "search-field-demo",
      "type": "registry:example",
      "title": "Search Field: Overview",
      "description": "Overview example of Search Field.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/search-field.json"
      ],
      "files": [
        {
          "path": "registry/examples/search-field-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/search-field-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "search-field",
        "tier": "free"
      }
    },
    {
      "name": "search-field-states",
      "type": "registry:example",
      "title": "Search Field: States and variants",
      "description": "States and variants example of Search Field.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/search-field.json"
      ],
      "files": [
        {
          "path": "registry/examples/search-field-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/search-field-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "search-field",
        "tier": "free"
      }
    },
    {
      "name": "section-tabs",
      "type": "registry:ui",
      "title": "Section Tabs",
      "description": "Sticky in-page tabs that follow the reader's section, slide an indicator to it, keep the active tab in view on narrow screens and scroll to a section on click.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/scroll.json",
        "https://ui.ballmac.com/r/motion-presets.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/section-tabs.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/section-tabs.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "tabs",
          "scrollspy",
          "sticky",
          "anchor links"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "sections: {id,label} matching element ids in the page. offset is the space to leave for this bar and any header. variant underline or pill.",
          "whenToUse": [
            "Long product, pricing and docs pages",
            "Anchored sections of a settings page"
          ],
          "whenNotToUse": [
            "Switching views without scrolling; use tabs",
            "Vertical page outlines; use table-of-contents"
          ],
          "composesWith": [
            "table-of-contents",
            "navbar",
            "tabs"
          ],
          "a11y": [
            {
              "keys": "Enter",
              "action": "Scrolls to the section and updates the URL hash"
            },
            {
              "keys": "Tab",
              "action": "Real links; middle-click and copy link work"
            },
            {
              "keys": "Screen readers",
              "action": "Current section has aria-current=location"
            }
          ],
          "customization": [
            "variant",
            "sticky and stickyTop",
            "offset",
            "container"
          ]
        },
        "examples": [
          "section-tabs-demo",
          "section-tabs-states"
        ],
        "url": "https://ui.ballmac.com/components/section-tabs"
      }
    },
    {
      "name": "section-tabs-demo",
      "type": "registry:example",
      "title": "Section Tabs: Product page",
      "description": "Product page example of Section Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/section-tabs.json"
      ],
      "files": [
        {
          "path": "registry/examples/section-tabs-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/section-tabs-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "section-tabs",
        "tier": "free"
      }
    },
    {
      "name": "section-tabs-states",
      "type": "registry:example",
      "title": "Section Tabs: Pill, narrow",
      "description": "Pill, narrow example of Section Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/section-tabs.json"
      ],
      "files": [
        {
          "path": "registry/examples/section-tabs-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/section-tabs-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "section-tabs",
        "tier": "free"
      }
    },
    {
      "name": "segmented-control",
      "type": "registry:ui",
      "title": "Segmented Control",
      "description": "A macOS segmented control: mutually exclusive options with a selected pill that springs between segments and hairline dividers between unselected ones. A Radix radio group underneath.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12",
        "radix-ui",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/segmented-control.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/segmented-control.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "segmented control",
          "toggle group",
          "radio group",
          "tabs",
          "macos",
          "switcher",
          "form"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "tests": true,
        "ai": {
          "summary": "<SegmentedControl aria-label value|defaultValue onValueChange size><SegmentedControlItem value>Label</SegmentedControlItem>…</SegmentedControl>. Exactly one segment is always selected. Icon-only items need aria-label; fullWidth stretches segments equally.",
          "whenToUse": [
            "Switching a view mode or range (Day / Week / Month, List / Grid)",
            "A short, always-visible choice in settings (Light / Dark / Auto)",
            "Filtering one list by a few exclusive categories"
          ],
          "whenNotToUse": [
            "Switching between panels of content with their own semantics (use tabs)",
            "More than about five options or long labels (use select)",
            "Options that can be combined (use checkboxes or a toggle group)"
          ],
          "composesWith": [
            "mac-window"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focuses the selected segment (one tab stop)"
            },
            {
              "keys": "ArrowLeft / ArrowRight",
              "action": "Moves to and selects the previous or next segment, wrapping"
            },
            {
              "keys": "Space",
              "action": "Selects the focused segment"
            }
          ],
          "customization": [
            "size: sm | default | lg",
            "fullWidth: stretch to the container with equal segments",
            "value / defaultValue / onValueChange: controlled or uncontrolled",
            "Parts: [data-slot=segmented-control-indicator] (the sliding pill), [data-slot=segmented-control-divider]",
            "Under reduced motion the pill jumps instead of sliding"
          ]
        },
        "examples": [
          "segmented-control-demo"
        ],
        "url": "https://ui.ballmac.com/components/segmented-control"
      }
    },
    {
      "name": "segmented-control-demo",
      "type": "registry:example",
      "title": "Segmented Control: Settings panel",
      "description": "Settings panel example of Segmented Control.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/segmented-control.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/segmented-control-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/segmented-control-demo.tsx"
        }
      ],
      "categories": [
        "macos"
      ],
      "meta": {
        "example": true,
        "of": "segmented-control",
        "tier": "free"
      }
    },
    {
      "name": "select",
      "type": "registry:ui",
      "title": "Select",
      "description": "A Radix select with a sized trigger, popper-positioned menu, scroll buttons, groups, labels, separators and a check indicator on the chosen item.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react"
      ],
      "devDependencies": [
        "tw-animate-css"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/select.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/select.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "select",
          "dropdown",
          "form",
          "radix",
          "listbox"
        ],
        "version": "1.0.2",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.2",
            "date": "2026-10-11",
            "note": "Switch track, thumb travel, and checkbox and radio size follow the platform feel tokens (--bm-switch-*, --bm-check-size); select and command surfaces take the feel's frosting. Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Pick one value from a list. Compose Select > SelectTrigger > SelectValue and SelectContent > SelectItem (group with SelectGroup + SelectLabel). The menu is portalled and keyboard navigable with typeahead.",
          "whenToUse": [
            "Choosing one option from 4 to 20 fixed values (timezone, role, region)",
            "Compact filters in toolbars (size sm)",
            "Grouped options such as regions by continent"
          ],
          "whenNotToUse": [
            "Two or three options that should stay visible (use a radio group or segmented control)",
            "Long searchable lists (use a combobox)",
            "Actions rather than values (use a dropdown menu)"
          ],
          "composesWith": [
            "label",
            "button",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Space / Enter / ArrowDown",
              "action": "Opens the menu"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves between items"
            },
            {
              "keys": "Enter",
              "action": "Selects the focused item"
            },
            {
              "keys": "Type a letter",
              "action": "Jumps to the matching item"
            },
            {
              "keys": "Escape",
              "action": "Closes the menu"
            }
          ],
          "customization": [
            "SelectTrigger size: sm | default",
            "SelectContent position: popper (default, below the trigger) | item-aligned",
            "Items accept icons before the text",
            "Needs the tw-animate-css classes for the open and close animation"
          ]
        },
        "source": {
          "name": "shadcn/ui Select",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "select-demo",
          "select-grouped"
        ],
        "url": "https://ui.ballmac.com/components/select"
      }
    },
    {
      "name": "select-demo",
      "type": "registry:example",
      "title": "Select: Default",
      "description": "Default example of Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/select.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/select-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/select-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "select",
        "tier": "free"
      }
    },
    {
      "name": "select-grouped",
      "type": "registry:example",
      "title": "Select: Grouped",
      "description": "Grouped example of Select.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/select.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/select-grouped.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/select-grouped.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "select",
        "tier": "free"
      }
    },
    {
      "name": "separator",
      "type": "registry:ui",
      "title": "Separator",
      "description": "A semantic or decorative divider with horizontal, vertical, and centered-label layouts.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/separator.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/separator.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "divider",
          "layout",
          "section"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A semantic or decorative divider with horizontal, vertical, and centered-label layouts.",
          "whenToUse": [
            "Separate groups of related content",
            "Divide a form with a short label"
          ],
          "whenNotToUse": [
            "Use spacing alone when separation is already clear"
          ],
          "composesWith": [
            "card"
          ],
          "a11y": [],
          "customization": [
            "orientation: horizontal | vertical",
            "label: centered text"
          ]
        },
        "source": {
          "name": "shadcn/ui Separator",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "separator-demo",
          "separator-states"
        ],
        "url": "https://ui.ballmac.com/components/separator"
      }
    },
    {
      "name": "separator-demo",
      "type": "registry:example",
      "title": "Separator: Overview",
      "description": "Overview example of Separator.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/separator.json"
      ],
      "files": [
        {
          "path": "registry/examples/separator-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/separator-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "separator",
        "tier": "free"
      }
    },
    {
      "name": "separator-states",
      "type": "registry:example",
      "title": "Separator: States and variants",
      "description": "States and variants example of Separator.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/separator.json"
      ],
      "files": [
        {
          "path": "registry/examples/separator-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/separator-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "separator",
        "tier": "free"
      }
    },
    {
      "name": "sheet",
      "type": "registry:ui",
      "title": "Sheet",
      "description": "A modal panel that slides from any edge, with header, scrollable body and footer parts, a grab handle on bottom sheets, and safe-area padding.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "lucide-react",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/sheet.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/sheet.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "overlay",
          "panel",
          "drawer",
          "dialog",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A dialog attached to a screen edge. Use side right for settings panels, bottom for mobile actions, left for navigation.",
          "whenToUse": [
            "Edit forms that keep page context visible",
            "Filters and settings panels",
            "Mobile navigation drawers"
          ],
          "whenNotToUse": [
            "Short confirmations; use alert-dialog",
            "Small anchored panels; use popover"
          ],
          "composesWith": [
            "button",
            "input",
            "label"
          ],
          "a11y": [
            {
              "keys": "Enter / Space",
              "action": "Opens from the trigger"
            },
            {
              "keys": "Tab / Shift+Tab",
              "action": "Cycles focus inside the sheet"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus to the trigger"
            }
          ],
          "customization": [
            "side: right | left | top | bottom",
            "showCloseButton",
            "SheetBody scrolls long content"
          ]
        },
        "source": {
          "name": "shadcn/ui Sheet",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "sheet-demo",
          "sheet-states"
        ],
        "url": "https://ui.ballmac.com/components/sheet"
      }
    },
    {
      "name": "sheet-demo",
      "type": "registry:example",
      "title": "Sheet: Edit project",
      "description": "Edit project example of Sheet.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sheet.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/input.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/sheet-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sheet-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sheet",
        "tier": "free"
      }
    },
    {
      "name": "sheet-states",
      "type": "registry:example",
      "title": "Sheet: Four edges",
      "description": "Four edges example of Sheet.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sheet.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/sheet-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sheet-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sheet",
        "tier": "free"
      }
    },
    {
      "name": "shortcut-hint",
      "type": "registry:ui",
      "title": "Shortcut Hint",
      "description": "A compact accessible keycap sequence paired with the action it performs.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/shortcut-hint.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/shortcut-hint.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "keyboard",
          "shortcut",
          "kbd"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A compact accessible keycap sequence paired with the action it performs.",
          "whenToUse": [
            "Label a command in a menu",
            "Teach an optional keyboard shortcut"
          ],
          "whenNotToUse": [
            "Use kbd for an isolated key"
          ],
          "composesWith": [
            "kbd",
            "spotlight-search"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Full shortcut meaning is in the accessible name"
            }
          ],
          "customization": [
            "Compact keycaps",
            "Action label and key sequence"
          ]
        },
        "examples": [
          "shortcut-hint-demo",
          "shortcut-hint-states"
        ],
        "url": "https://ui.ballmac.com/components/shortcut-hint"
      }
    },
    {
      "name": "shortcut-hint-demo",
      "type": "registry:example",
      "title": "Shortcut Hint: Overview",
      "description": "Overview example of Shortcut Hint.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/shortcut-hint.json"
      ],
      "files": [
        {
          "path": "registry/examples/shortcut-hint-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/shortcut-hint-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "shortcut-hint",
        "tier": "free"
      }
    },
    {
      "name": "shortcut-hint-states",
      "type": "registry:example",
      "title": "Shortcut Hint: States and variants",
      "description": "States and variants example of Shortcut Hint.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/shortcut-hint.json"
      ],
      "files": [
        {
          "path": "registry/examples/shortcut-hint-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/shortcut-hint-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "shortcut-hint",
        "tier": "free"
      }
    },
    {
      "name": "sidebar",
      "type": "registry:ui",
      "title": "Sidebar",
      "description": "An app sidebar with icon-rail collapse, floating and inset variants, grouped menus with badges and sub-items, a mobile sheet, tooltips when collapsed and a Cmd/Ctrl+B shortcut.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "class-variance-authority",
        "radix-ui",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/sheet.json",
        "https://ui.ballmac.com/r/tooltip.json",
        "https://ui.ballmac.com/r/direction.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/sidebar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/sidebar.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "navigation",
          "layout",
          "app shell",
          "collapsible"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "SidebarProvider wraps Sidebar and SidebarInset. Menu entries use SidebarMenuButton with href and isActive. SidebarTrigger toggles it.",
          "whenToUse": [
            "Application navigation with many sections",
            "Dashboards and admin tools"
          ],
          "whenNotToUse": [
            "Marketing site headers; use navigation-menu",
            "Two or three links; use tabs"
          ],
          "composesWith": [
            "sheet",
            "tooltip",
            "button",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "Cmd/Ctrl+B",
              "action": "Toggles the sidebar"
            },
            {
              "keys": "Tab",
              "action": "Moves through links; the current page has aria-current"
            },
            {
              "keys": "Mobile",
              "action": "Opens as a named dialog sheet; Escape closes"
            }
          ],
          "customization": [
            "side, variant, collapsible",
            "defaultOpen or controlled open",
            "SidebarMenuBadge and sub-menus",
            "width via --sidebar-width"
          ]
        },
        "source": {
          "name": "shadcn/ui Sidebar",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "sidebar-demo",
          "sidebar-states"
        ],
        "url": "https://ui.ballmac.com/components/sidebar"
      }
    },
    {
      "name": "sidebar-demo",
      "type": "registry:example",
      "title": "Sidebar: Workspace navigation",
      "description": "Workspace navigation example of Sidebar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sidebar.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/sidebar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sidebar-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "sidebar",
        "tier": "free"
      }
    },
    {
      "name": "sidebar-states",
      "type": "registry:example",
      "title": "Sidebar: Icon rail",
      "description": "Icon rail example of Sidebar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sidebar.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/sidebar-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sidebar-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "sidebar",
        "tier": "free"
      }
    },
    {
      "name": "signature-pad",
      "type": "registry:ui",
      "title": "Signature Pad",
      "description": "A responsive pointer signature surface with a full keyboard-accessible typed alternative and undo.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/signature-pad.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/signature-pad.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "signature",
          "drawing",
          "form"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A responsive pointer signature surface with a full keyboard-accessible typed alternative and undo.",
          "whenToUse": [
            "Capture a signer name or freehand mark"
          ],
          "whenNotToUse": [
            "Use a text input when a signature is not required"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter / Space / typing",
              "action": "Switches methods, types a name, and clears or undoes the signature"
            }
          ],
          "customization": [
            "Controlled and uncontrolled value",
            "Tokens and state styling"
          ]
        },
        "examples": [
          "signature-pad-demo",
          "signature-pad-states"
        ],
        "url": "https://ui.ballmac.com/components/signature-pad"
      }
    },
    {
      "name": "signature-pad-demo",
      "type": "registry:example",
      "title": "Signature Pad: Overview",
      "description": "Overview example of Signature Pad.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/signature-pad.json"
      ],
      "files": [
        {
          "path": "registry/examples/signature-pad-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/signature-pad-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "signature-pad",
        "tier": "free"
      }
    },
    {
      "name": "signature-pad-states",
      "type": "registry:example",
      "title": "Signature Pad: States and variants",
      "description": "States and variants example of Signature Pad.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/signature-pad.json"
      ],
      "files": [
        {
          "path": "registry/examples/signature-pad-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/signature-pad-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "signature-pad",
        "tier": "free"
      }
    },
    {
      "name": "skeleton",
      "type": "registry:ui",
      "title": "Skeleton",
      "description": "A theme-aware loading placeholder with an animation that stops when reduced motion is requested.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/skeleton.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/skeleton.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "loading",
          "placeholder",
          "pulse"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "The pulse holds still when the theme turns decorative loops off (--bm-ambient-state). Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-29",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "A theme-aware loading placeholder with an animation that stops when reduced motion is requested.",
          "whenToUse": [
            "Reserve content space while data loads",
            "Preview the shape of a card or list"
          ],
          "whenNotToUse": [
            "Use a spinner for a single short operation"
          ],
          "composesWith": [
            "card"
          ],
          "a11y": [],
          "customization": [
            "animated: enable pulse motion"
          ]
        },
        "source": {
          "name": "shadcn/ui Skeleton",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "skeleton-demo",
          "skeleton-states"
        ],
        "url": "https://ui.ballmac.com/components/skeleton"
      }
    },
    {
      "name": "skeleton-demo",
      "type": "registry:example",
      "title": "Skeleton: Overview",
      "description": "Overview example of Skeleton.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/examples/skeleton-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/skeleton-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "skeleton",
        "tier": "free"
      }
    },
    {
      "name": "skeleton-states",
      "type": "registry:example",
      "title": "Skeleton: States and variants",
      "description": "States and variants example of Skeleton.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/skeleton.json"
      ],
      "files": [
        {
          "path": "registry/examples/skeleton-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/skeleton-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "skeleton",
        "tier": "free"
      }
    },
    {
      "name": "slider-range",
      "type": "registry:ui",
      "title": "Slider Range",
      "description": "A two-thumb Radix slider with a labeled value span, keyboard operation, and minimum thumb spacing.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/slider-range.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/slider-range.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "slider",
          "range",
          "filter"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A two-thumb Radix slider with a labeled value span, keyboard operation, and minimum thumb spacing.",
          "whenToUse": [
            "Filter a bounded numeric interval"
          ],
          "whenNotToUse": [
            "Use Number Input for exact values"
          ],
          "composesWith": [
            "number-input"
          ],
          "a11y": [
            {
              "keys": "Arrow keys / Home / End / Page Up / Page Down",
              "action": "Adjusts the focused minimum or maximum thumb"
            }
          ],
          "customization": [
            "Controlled and uncontrolled value",
            "Tokens and state styling"
          ]
        },
        "examples": [
          "slider-range-demo",
          "slider-range-states"
        ],
        "url": "https://ui.ballmac.com/components/slider-range"
      }
    },
    {
      "name": "slider-range-demo",
      "type": "registry:example",
      "title": "Slider Range: Overview",
      "description": "Overview example of Slider Range.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/slider-range.json"
      ],
      "files": [
        {
          "path": "registry/examples/slider-range-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/slider-range-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "slider-range",
        "tier": "free"
      }
    },
    {
      "name": "slider-range-states",
      "type": "registry:example",
      "title": "Slider Range: States and variants",
      "description": "States and variants example of Slider Range.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/slider-range.json"
      ],
      "files": [
        {
          "path": "registry/examples/slider-range-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/slider-range-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "slider-range",
        "tier": "free"
      }
    },
    {
      "name": "slider",
      "type": "registry:ui",
      "title": "Slider",
      "description": "A single or range slider with a name per thumb, a live value bubble, vertical orientation and full keyboard control, built on Radix.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/slider.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/slider.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "input",
          "range",
          "form",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Drag or use the keyboard to pick a number or a range. Give every thumb a name with thumbLabels; showValue adds a bubble on hover, focus and drag.",
          "whenToUse": [
            "Volume, brightness and zoom",
            "Price and date ranges with two thumbs",
            "Any bounded numeric choice where precision is not critical"
          ],
          "whenNotToUse": [
            "Exact numeric entry; use number-input",
            "A styled range with marks or steps shown; use slider-range"
          ],
          "composesWith": [
            "label",
            "field"
          ],
          "a11y": [
            {
              "keys": "ArrowLeft / ArrowRight / ArrowUp / ArrowDown",
              "action": "Changes the value by one step"
            },
            {
              "keys": "PageUp / PageDown",
              "action": "Changes by a larger step"
            },
            {
              "keys": "Home / End",
              "action": "Jumps to min or max"
            },
            {
              "keys": "Tab",
              "action": "Moves between thumbs"
            }
          ],
          "customization": [
            "min, max, step",
            "thumbLabels for range sliders",
            "showValue and formatValue",
            "orientation: horizontal | vertical"
          ]
        },
        "source": {
          "name": "shadcn/ui Slider",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "slider-demo",
          "slider-states"
        ],
        "url": "https://ui.ballmac.com/components/slider"
      }
    },
    {
      "name": "slider-demo",
      "type": "registry:example",
      "title": "Slider: Volume and price",
      "description": "Volume and price example of Slider.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/slider.json"
      ],
      "files": [
        {
          "path": "registry/examples/slider-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/slider-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "slider",
        "tier": "free"
      }
    },
    {
      "name": "slider-states",
      "type": "registry:example",
      "title": "Slider: Vertical and disabled",
      "description": "Vertical and disabled example of Slider.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/slider.json"
      ],
      "files": [
        {
          "path": "registry/examples/slider-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/slider-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "slider",
        "tier": "free"
      }
    },
    {
      "name": "sortable",
      "type": "registry:ui",
      "title": "Sortable",
      "description": "Reorder lists, grids and multi-column boards by pointer, touch or keyboard, with spoken announcements, move buttons for people who cannot drag, a floating lifted item and reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "@dnd-kit/core@^6",
        "@dnd-kit/sortable@^10",
        "@dnd-kit/utilities@^3",
        "motion@^12",
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/sortable.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/sortable.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "drag",
          "drop",
          "reorder",
          "sortable",
          "dnd",
          "kanban",
          "keyboard"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "Hold the order in state: <Sortable label value={ids} onValueChange={setIds}> with a <SortableItem id> per id, each holding a <SortableHandle>. SortableGroups and SortableGroup move items between lists.",
          "whenToUse": [
            "Playlists, checklists, filters and settings people put in their own order",
            "Dashboard tiles in a grid and chips in a row",
            "Boards where cards move between columns"
          ],
          "whenNotToUse": [
            "A full kanban product with cards, tags and assignees; use kanban-board",
            "Sorting by a column's value; use data-table or data-grid",
            "Reordering rows of a huge virtualized list"
          ],
          "composesWith": [
            "button",
            "badge",
            "kanban-board"
          ],
          "a11y": [
            {
              "keys": "Space / Enter on the handle",
              "action": "Picks up the item; the same keys drop it"
            },
            {
              "keys": "Arrow keys",
              "action": "Move the lifted item; the new position is announced"
            },
            {
              "keys": "Escape",
              "action": "Cancels and puts the item back"
            },
            {
              "keys": "SortableMove buttons",
              "action": "Move an item one place with a click, for people who cannot drag (WCAG 2.5.7)"
            },
            {
              "keys": "Screen readers",
              "action": "Instructions, picked-up, over, dropped and cancelled messages are read out, in the page's language"
            }
          ],
          "customization": [
            "orientation: vertical | horizontal | grid",
            "dragEverywhere on an item to drag by its whole body instead of a handle",
            "overlay={false} to keep the lifted item in place",
            "getLabel and getGroupLabel for spoken names",
            "className on the list, the group and each item"
          ]
        },
        "statesNone": "Nothing loads or fails: it reorders the items it is given; an empty list or group simply draws no items.",
        "source": {
          "name": "dnd-kit",
          "url": "https://github.com/clauderic/dnd-kit",
          "license": "MIT",
          "copyright": "Copyright (c) 2021, Claudéric Demers",
          "modified": true
        },
        "examples": [
          "sortable-demo",
          "sortable-grid",
          "sortable-horizontal",
          "sortable-board",
          "sortable-buttons"
        ],
        "url": "https://ui.ballmac.com/components/sortable"
      }
    },
    {
      "name": "sortable-demo",
      "type": "registry:example",
      "title": "Sortable: Playlist",
      "description": "Playlist example of Sortable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sortable.json"
      ],
      "files": [
        {
          "path": "registry/examples/sortable-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sortable-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sortable",
        "tier": "free"
      }
    },
    {
      "name": "sortable-grid",
      "type": "registry:example",
      "title": "Sortable: Dashboard grid",
      "description": "Dashboard grid example of Sortable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sortable.json"
      ],
      "files": [
        {
          "path": "registry/examples/sortable-grid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sortable-grid.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sortable",
        "tier": "free"
      }
    },
    {
      "name": "sortable-horizontal",
      "type": "registry:example",
      "title": "Sortable: Horizontal chips",
      "description": "Horizontal chips example of Sortable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sortable.json"
      ],
      "files": [
        {
          "path": "registry/examples/sortable-horizontal.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sortable-horizontal.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sortable",
        "tier": "free"
      }
    },
    {
      "name": "sortable-board",
      "type": "registry:example",
      "title": "Sortable: Board with columns",
      "description": "Board with columns example of Sortable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sortable.json"
      ],
      "files": [
        {
          "path": "registry/examples/sortable-board.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sortable-board.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sortable",
        "tier": "free"
      }
    },
    {
      "name": "sortable-buttons",
      "type": "registry:example",
      "title": "Sortable: With move buttons",
      "description": "With move buttons example of Sortable.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sortable.json"
      ],
      "files": [
        {
          "path": "registry/examples/sortable-buttons.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sortable-buttons.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "sortable",
        "tier": "free"
      }
    },
    {
      "name": "sparkline",
      "type": "registry:ui",
      "title": "Sparkline",
      "description": "A lightweight accessible SVG trend line with a marked latest value and no chart dependency.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/sparkline.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/sparkline.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chart",
          "trend",
          "data"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A lightweight accessible SVG trend line with a marked latest value and no chart dependency.",
          "whenToUse": [
            "Show a small trend beside a metric"
          ],
          "whenNotToUse": [
            "Use a full chart for axes and detailed inspection"
          ],
          "composesWith": [
            "stat-card"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Trend description is announced as an image"
            }
          ],
          "customization": [
            "Content, layout, and token-based className styling"
          ]
        },
        "examples": [
          "sparkline-demo",
          "sparkline-states"
        ],
        "url": "https://ui.ballmac.com/components/sparkline"
      }
    },
    {
      "name": "sparkline-demo",
      "type": "registry:example",
      "title": "Sparkline: Overview",
      "description": "Overview example of Sparkline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sparkline.json"
      ],
      "files": [
        {
          "path": "registry/examples/sparkline-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sparkline-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "sparkline",
        "tier": "free"
      }
    },
    {
      "name": "sparkline-states",
      "type": "registry:example",
      "title": "Sparkline: States and variants",
      "description": "States and variants example of Sparkline.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sparkline.json"
      ],
      "files": [
        {
          "path": "registry/examples/sparkline-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sparkline-states.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "sparkline",
        "tier": "free"
      }
    },
    {
      "name": "spinner",
      "type": "registry:ui",
      "title": "Spinner",
      "description": "A compact loading indicator with three sizes, an accessible label, and reduced-motion behavior.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/spinner.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/spinner.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "loading",
          "busy",
          "indicator"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "A compact loading indicator with three sizes, an accessible label, and reduced-motion behavior.",
          "whenToUse": [
            "Show a short in-progress action",
            "Place inside a disabled submit button"
          ],
          "whenNotToUse": [
            "Use progress for a measurable operation"
          ],
          "composesWith": [
            "button"
          ],
          "a11y": [],
          "customization": [
            "size: sm | default | lg",
            "label: screen reader announcement"
          ]
        },
        "source": {
          "name": "shadcn/ui Spinner",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "spinner-demo",
          "spinner-states"
        ],
        "url": "https://ui.ballmac.com/components/spinner"
      }
    },
    {
      "name": "spinner-demo",
      "type": "registry:example",
      "title": "Spinner: Overview",
      "description": "Overview example of Spinner.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spinner.json"
      ],
      "files": [
        {
          "path": "registry/examples/spinner-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spinner-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "spinner",
        "tier": "free"
      }
    },
    {
      "name": "spinner-states",
      "type": "registry:example",
      "title": "Spinner: States and variants",
      "description": "States and variants example of Spinner.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spinner.json"
      ],
      "files": [
        {
          "path": "registry/examples/spinner-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spinner-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "spinner",
        "tier": "free"
      }
    },
    {
      "name": "split-bar",
      "type": "registry:ui",
      "title": "Split Bar",
      "description": "One bar cut into shares with a legend that says the same in numbers. Pointing at a legend row lights its slice and dims the rest, and choosing it keeps it lit.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/split-bar.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/split-bar.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "chart",
          "share",
          "stacked",
          "composition",
          "budget",
          "breakdown",
          "legend"
        ],
        "version": "1.0.0",
        "updated": "2026-10-25",
        "tests": true,
        "ai": {
          "summary": "segments is [{ id, label, value, hint? }]; title, total (text above the bar), format(value). The legend lists every segment with its value and percent; hover or focus lights a slice, and a click keeps it lit (aria-pressed).",
          "whenToUse": [
            "Breaking a total into a handful of parts",
            "Spend, storage, traffic or time splits"
          ],
          "whenNotToUse": [
            "Many parts or nested parts; use treemap",
            "Ranking; use bar-list"
          ],
          "composesWith": [
            "bar-list",
            "treemap",
            "stat-card",
            "waterfall-chart"
          ],
          "a11y": [
            {
              "keys": "Legend",
              "action": "The accessible version: buttons with label, value and percent; pressed state"
            },
            {
              "keys": "Bar",
              "action": "Decoration only"
            },
            {
              "keys": "Color",
              "action": "Never the only way to tell parts apart"
            }
          ],
          "customization": [
            "segments and title",
            "total and format"
          ]
        },
        "statesNone": "A presentational chart: the segments are passed in, so it has nothing of its own to load.",
        "examples": [
          "split-bar-demo",
          "split-bar-two"
        ],
        "url": "https://ui.ballmac.com/components/split-bar"
      }
    },
    {
      "name": "split-bar-demo",
      "type": "registry:example",
      "title": "Split Bar: Where the spend goes",
      "description": "Where the spend goes example of Split Bar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/split-bar.json"
      ],
      "files": [
        {
          "path": "registry/examples/split-bar-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/split-bar-demo.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "split-bar",
        "tier": "free"
      }
    },
    {
      "name": "split-bar-two",
      "type": "registry:example",
      "title": "Split Bar: Two shares",
      "description": "Two shares example of Split Bar.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/split-bar.json"
      ],
      "files": [
        {
          "path": "registry/examples/split-bar-two.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/split-bar-two.tsx"
        }
      ],
      "categories": [
        "data-display"
      ],
      "meta": {
        "example": true,
        "of": "split-bar",
        "tier": "free"
      }
    },
    {
      "name": "split-view",
      "type": "registry:ui",
      "title": "Split View",
      "description": "A master and detail layout with a keyboard-resizable divider. Panes sit side by side in wide containers and stack with a Back button in narrow ones.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/split-view.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/split-view.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "master detail",
          "split",
          "list",
          "responsive"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "SplitView > SplitViewList, SplitViewDetail and SplitViewBack. Use useSplitView().setDetailOpen(true) when an item is chosen. Responds to its own width, not the screen's.",
          "whenToUse": [
            "Mail, files and settings screens",
            "Any list that opens a detail"
          ],
          "whenNotToUse": [
            "User-arranged dock panels; use resizable",
            "Overlay details; use sheet or drawer"
          ],
          "composesWith": [
            "resizable",
            "scroll-area",
            "sidebar"
          ],
          "a11y": [
            {
              "keys": "ArrowLeft / ArrowRight",
              "action": "Resize the list from the divider; Shift for larger steps; Home and End for the limits"
            },
            {
              "keys": "Tab",
              "action": "Back button appears only when panes stack"
            },
            {
              "keys": "Screen readers",
              "action": "Panes are labelled regions; the divider is a separator with value bounds"
            }
          ],
          "customization": [
            "listWidth, minListWidth, maxListWidth",
            "controlled detailOpen",
            "container-query breakpoint"
          ]
        },
        "examples": [
          "split-view-demo",
          "split-view-states"
        ],
        "url": "https://ui.ballmac.com/components/split-view"
      }
    },
    {
      "name": "split-view-demo",
      "type": "registry:example",
      "title": "Split View: Mail layout",
      "description": "Mail layout example of Split View.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/split-view.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/split-view-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/split-view-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "split-view",
        "tier": "free"
      }
    },
    {
      "name": "split-view-states",
      "type": "registry:example",
      "title": "Split View: Stacked on narrow",
      "description": "Stacked on narrow example of Split View.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/split-view.json"
      ],
      "files": [
        {
          "path": "registry/examples/split-view-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/split-view-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "split-view",
        "tier": "free"
      }
    },
    {
      "name": "spotlight-card",
      "type": "registry:ui",
      "title": "Spotlight Card",
      "description": "A card whose surface and border pick up a soft glow that follows the pointer, driven by CSS variables with no re-render per move. Keyboard focus shows a steady glow.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/spotlight-card.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/spotlight-card.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "card",
          "hover",
          "glow",
          "pointer",
          "feature",
          "motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "ai": {
          "summary": "A drop-in card surface (rounded-xl, border, bg-card, p-6) with a pointer-following glow in the --ring color. Put any content inside; if the card contains a link or button, focusing it lights the card.",
          "whenToUse": [
            "Feature grids on landing pages",
            "Pricing or plan cards that should respond to hover",
            "Clickable tiles in a dashboard or settings index"
          ],
          "whenNotToUse": [
            "Dense data tables or long lists of cards (the effect loses meaning when everything glows)",
            "Plain content containers with no interaction (use card)"
          ],
          "composesWith": [
            "badge",
            "button",
            "border-beam"
          ],
          "a11y": [],
          "customization": [
            "size: glow radius in px (default 320)",
            "Glow color follows --ring; override per card with className like [--ring:var(--chart-2)]",
            "Surface styles are ordinary classes: replace p-6, rounded-xl or bg-card through className",
            "Parts: [data-slot=spotlight-card-surface] and [data-slot=spotlight-card-border]"
          ]
        },
        "examples": [
          "spotlight-card-demo",
          "spotlight-card-grid"
        ],
        "url": "https://ui.ballmac.com/components/spotlight-card"
      }
    },
    {
      "name": "spotlight-card-demo",
      "type": "registry:example",
      "title": "Spotlight Card: Feature card",
      "description": "Feature card example of Spotlight Card.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spotlight-card.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/spotlight-card-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spotlight-card-demo.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "spotlight-card",
        "tier": "free"
      }
    },
    {
      "name": "spotlight-card-grid",
      "type": "registry:example",
      "title": "Spotlight Card: Feature grid",
      "description": "Feature grid example of Spotlight Card.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spotlight-card.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/spotlight-card-grid.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spotlight-card-grid.tsx"
        }
      ],
      "categories": [
        "motion"
      ],
      "meta": {
        "example": true,
        "of": "spotlight-card",
        "tier": "free"
      }
    },
    {
      "name": "spring-drawer",
      "type": "registry:ui",
      "title": "Spring Drawer",
      "description": "A drawer with spring physics: drag the handle to snap between heights or flick it closed, or slide in from the left or right, on Radix Dialog for focus trapping and scroll lock.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12",
        "lucide-react",
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/spring-drawer.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/spring-drawer.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "drawer",
          "sheet",
          "snap",
          "drag",
          "dialog"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "<SpringDrawer side snapPoints defaultSnap><SpringDrawerTrigger/><SpringDrawerContent><SpringDrawerHeader><SpringDrawerTitle/></SpringDrawerHeader><SpringDrawerBody/></SpringDrawerContent></SpringDrawer>. snapPoints are fractions of the screen height. The handle is a keyboard slider.",
          "whenToUse": [
            "Mobile-style sheets that can sit half open",
            "Details panels that can be pulled larger"
          ],
          "whenNotToUse": [
            "Simple modals (dialog)",
            "Vaul-style nested drawers (drawer)"
          ],
          "composesWith": [
            "drawer",
            "sheet",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Escape",
              "action": "Closes the drawer"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "On the handle, moves between snap points"
            },
            {
              "keys": "Focus",
              "action": "Trapped in the drawer and returned to the trigger on close"
            },
            {
              "keys": "Reduced motion",
              "action": "The drawer moves without springs"
            }
          ],
          "customization": [
            "side",
            "snapPoints and defaultSnap",
            "onSnapChange",
            "maxWidth",
            "showCloseButton"
          ]
        },
        "examples": [
          "spring-drawer-demo",
          "spring-drawer-side"
        ],
        "url": "https://ui.ballmac.com/components/spring-drawer"
      }
    },
    {
      "name": "spring-drawer-demo",
      "type": "registry:example",
      "title": "Spring Drawer: Bottom drawer with snap points",
      "description": "Bottom drawer with snap points example of Spring Drawer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spring-drawer.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/spring-drawer-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spring-drawer-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "spring-drawer",
        "tier": "free"
      }
    },
    {
      "name": "spring-drawer-side",
      "type": "registry:example",
      "title": "Spring Drawer: Side drawers",
      "description": "Side drawers example of Spring Drawer.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/spring-drawer.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/spring-drawer-side.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/spring-drawer-side.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "spring-drawer",
        "tier": "free"
      }
    },
    {
      "name": "state-view",
      "type": "registry:ui",
      "title": "State View",
      "description": "Shows the right thing for what the data is doing: a skeleton while loading, a helpful empty state, an error with retry, or your content. Announced to screen readers, never steals focus, fades with the theme's motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/empty.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/use-resource.json",
        "https://ui.ballmac.com/r/frame-props.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/state-view.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/state-view.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "state",
          "loading",
          "empty",
          "error",
          "skeleton",
          "retry",
          "boundary",
          "async"
        ],
        "version": "1.0.1",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-12",
            "note": "Moves frameProps into its own frame-props module so server components can use it; state-view still exports it.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-12",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Wrap any data view: <StateView state={state} loading={<MySkeleton/>} empty={{ title, description, action }} error={{ title, description, details }} onRetry={retry}>{ready content}</StateView>. Pair with useResource, which returns the state. Loading is announced and the region is aria-busy; errors use role=alert; focus is never moved.",
          "whenToUse": [
            "Any list, table, feed or panel that loads data",
            "Giving a block its loading, empty and error views without writing them each time"
          ],
          "whenNotToUse": [
            "Forms: they track submitting and success themselves (blocks with a state prop handle it)",
            "A single value that is just a number: use a skeleton line"
          ],
          "composesWith": [
            "use-resource",
            "empty",
            "skeleton",
            "button"
          ],
          "a11y": [
            {
              "keys": "Screen reader",
              "action": "Loading is announced as a status; an error is announced as an alert; the region is aria-busy while loading"
            },
            {
              "keys": "Tab",
              "action": "Reaches the retry button and the details disclosure; focus is never moved for you"
            }
          ],
          "customization": [
            "loading: pass a skeleton shaped like your content so nothing jumps",
            "empty and error: a config object ({ title, description, icon, action } and { title, description, details, retryLabel, action }) or your own node",
            "onRetry: draws the retry button"
          ]
        },
        "examples": [
          "state-view-demo",
          "state-view-resource"
        ],
        "url": "https://ui.ballmac.com/components/state-view"
      }
    },
    {
      "name": "state-view-demo",
      "type": "registry:example",
      "title": "State View: Every state",
      "description": "Every state example of State View.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/state-view-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/state-view-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "state-view",
        "tier": "free"
      }
    },
    {
      "name": "state-view-resource",
      "type": "registry:example",
      "title": "State View: With a real fetch",
      "description": "With a real fetch example of State View.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/state-view.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/segmented-control.json",
        "https://ui.ballmac.com/r/skeleton.json",
        "https://ui.ballmac.com/r/use-resource.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/state-view-resource.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/state-view-resource.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "state-view",
        "tier": "free"
      }
    },
    {
      "name": "status-dot",
      "type": "registry:ui",
      "title": "Status Dot",
      "description": "A compact status indicator that always pairs its color with a visible label.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/status-dot.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/status-dot.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "status",
          "presence",
          "online"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "ai": {
          "summary": "A compact status indicator that always pairs its color with a visible label.",
          "whenToUse": [
            "Show presence or service state",
            "Label a live operational status"
          ],
          "whenNotToUse": [
            "Use badge for category labels"
          ],
          "composesWith": [
            "badge",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "None",
              "action": "Status is expressed in visible text"
            }
          ],
          "customization": [
            "status: online | busy | away | offline",
            "Optional reduced-motion pulse"
          ]
        },
        "examples": [
          "status-dot-demo",
          "status-dot-states"
        ],
        "url": "https://ui.ballmac.com/components/status-dot"
      }
    },
    {
      "name": "status-dot-demo",
      "type": "registry:example",
      "title": "Status Dot: Overview",
      "description": "Overview example of Status Dot.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/status-dot.json"
      ],
      "files": [
        {
          "path": "registry/examples/status-dot-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/status-dot-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "status-dot",
        "tier": "free"
      }
    },
    {
      "name": "status-dot-states",
      "type": "registry:example",
      "title": "Status Dot: States and variants",
      "description": "States and variants example of Status Dot.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/status-dot.json"
      ],
      "files": [
        {
          "path": "registry/examples/status-dot-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/status-dot-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "status-dot",
        "tier": "free"
      }
    },
    {
      "name": "stepper-form",
      "type": "registry:ui",
      "title": "Stepper Form",
      "description": "A guided multistep form shell with gated progression, review states, and keyboard-accessible navigation.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/stepper-form.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/stepper-form.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "wizard",
          "form",
          "steps"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A guided multistep form shell with gated progression, review states, and keyboard-accessible navigation.",
          "whenToUse": [
            "Guide a long onboarding or setup process"
          ],
          "whenNotToUse": [
            "Use a single form for short tasks"
          ],
          "composesWith": [
            "progress"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter / Space",
              "action": "Navigates steps and completes the flow"
            }
          ],
          "customization": [
            "Controlled and uncontrolled value",
            "Tokens and state styling"
          ]
        },
        "examples": [
          "stepper-form-demo",
          "stepper-form-states"
        ],
        "url": "https://ui.ballmac.com/components/stepper-form"
      }
    },
    {
      "name": "stepper-form-demo",
      "type": "registry:example",
      "title": "Stepper Form: Overview",
      "description": "Overview example of Stepper Form.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/stepper-form.json"
      ],
      "files": [
        {
          "path": "registry/examples/stepper-form-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/stepper-form-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "stepper-form",
        "tier": "free"
      }
    },
    {
      "name": "stepper-form-states",
      "type": "registry:example",
      "title": "Stepper Form: States and variants",
      "description": "States and variants example of Stepper Form.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/stepper-form.json"
      ],
      "files": [
        {
          "path": "registry/examples/stepper-form-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/stepper-form-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "stepper-form",
        "tier": "free"
      }
    },
    {
      "name": "sticky-scroll",
      "type": "registry:ui",
      "title": "Sticky Scroll",
      "description": "Scroll-driven storytelling: text steps scroll past while one visual stays pinned and crossfades to match, with each visual inline on small screens.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/motion-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/sticky-scroll.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/sticky-scroll.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "scrollytelling",
          "sticky",
          "feature",
          "marketing"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "items: {id,title,description,visual}. The step nearest the middle of the viewport is active (aria-current=step) and its visual shows in the pinned panel.",
          "whenToUse": [
            "Feature tours on landing pages",
            "Step-by-step explanations with a matching picture"
          ],
          "whenNotToUse": [
            "Short lists of benefits; use a plain grid",
            "Content that must all be visible at once"
          ],
          "composesWith": [
            "container-scroll",
            "bento-grid"
          ],
          "a11y": [
            {
              "keys": "Reading order",
              "action": "Steps are an ordered list; the pinned visual is decorative and hidden from assistive technology"
            },
            {
              "keys": "Reduced motion",
              "action": "No crossfade or scale"
            }
          ],
          "customization": [
            "visualSide: left | right",
            "stickyOffset and stepMinHeight",
            "container for panel scrolling",
            "onActiveChange"
          ]
        },
        "examples": [
          "sticky-scroll-demo",
          "sticky-scroll-states"
        ],
        "url": "https://ui.ballmac.com/components/sticky-scroll"
      }
    },
    {
      "name": "sticky-scroll-demo",
      "type": "registry:example",
      "title": "Sticky Scroll: Feature story",
      "description": "Feature story example of Sticky Scroll.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sticky-scroll.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/sticky-scroll-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sticky-scroll-demo.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "sticky-scroll",
        "tier": "free"
      }
    },
    {
      "name": "sticky-scroll-states",
      "type": "registry:example",
      "title": "Sticky Scroll: Visual on the left",
      "description": "Visual on the left example of Sticky Scroll.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/sticky-scroll.json"
      ],
      "files": [
        {
          "path": "registry/examples/sticky-scroll-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/sticky-scroll-states.tsx"
        }
      ],
      "categories": [
        "layout"
      ],
      "meta": {
        "example": true,
        "of": "sticky-scroll",
        "tier": "free"
      }
    },
    {
      "name": "switch",
      "type": "registry:ui",
      "title": "Switch",
      "description": "A Radix toggle switch in two sizes with a CSS-animated thumb, for settings that take effect immediately. Stops animating under reduced motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui",
        "class-variance-authority"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/switch.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/switch.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "switch",
          "toggle",
          "settings",
          "form",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Switch track, thumb travel, and checkbox and radio size follow the platform feel tokens (--bm-switch-*, --bm-check-size); select and command surfaces take the feel's frosting. Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "On/off control for settings that apply immediately. Pair with a Label via id/htmlFor; use size=\"sm\" in dense lists.",
          "whenToUse": [
            "Enabling or disabling a feature or notification",
            "Settings pages with labelled rows",
            "Toggles inside dense menus or tables (size sm)"
          ],
          "whenNotToUse": [
            "Choices submitted later with a form, or agreeing to terms (use checkbox)",
            "More than two options (use select)"
          ],
          "composesWith": [
            "label",
            "badge"
          ],
          "a11y": [
            {
              "keys": "Space",
              "action": "Toggles the switch"
            },
            {
              "keys": "Enter",
              "action": "Toggles the switch"
            },
            {
              "keys": "Tab",
              "action": "Moves focus to the switch"
            }
          ],
          "customization": [
            "size: sm | default",
            "checked / defaultChecked with onCheckedChange",
            "aria-invalid=\"true\" for errors"
          ]
        },
        "source": {
          "name": "shadcn/ui Switch",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "switch-demo",
          "switch-settings"
        ],
        "url": "https://ui.ballmac.com/components/switch"
      }
    },
    {
      "name": "switch-demo",
      "type": "registry:example",
      "title": "Switch: Default",
      "description": "Default example of Switch.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/switch.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/switch-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/switch-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "switch",
        "tier": "free"
      }
    },
    {
      "name": "switch-settings",
      "type": "registry:example",
      "title": "Switch: Settings rows",
      "description": "Settings rows example of Switch.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/switch.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/switch-settings.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/switch-settings.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "switch",
        "tier": "free"
      }
    },
    {
      "name": "table-of-contents",
      "type": "registry:ui",
      "title": "Table Of Contents",
      "description": "An 'On this page' list with a scroll spy and a sliding current-section marker. It collects headings itself or takes a list, and scrolls below sticky headers.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/scroll.json",
        "https://ui.ballmac.com/r/motion-presets.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/table-of-contents.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/table-of-contents.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "toc",
          "scrollspy",
          "docs",
          "anchor links"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Leave items out to collect h2 and h3 headings (they need text; missing ids are created). Current section gets aria-current=location.",
          "whenToUse": [
            "Documentation and long articles",
            "Settings pages with many sections"
          ],
          "whenNotToUse": [
            "Horizontal in-page tabs; use section-tabs",
            "App navigation; use sidebar"
          ],
          "composesWith": [
            "scroll-progress",
            "section-tabs"
          ],
          "a11y": [
            {
              "keys": "Enter",
              "action": "Scrolls to the section and updates the URL hash"
            },
            {
              "keys": "Screen readers",
              "action": "A labelled navigation; the current section has aria-current=location"
            },
            {
              "keys": "Reduced motion",
              "action": "Jumps instead of smooth scrolling; the marker does not glide"
            }
          ],
          "customization": [
            "items or headingsFrom",
            "levels",
            "title",
            "offset and container"
          ]
        },
        "examples": [
          "table-of-contents-demo",
          "table-of-contents-states"
        ],
        "url": "https://ui.ballmac.com/components/table-of-contents"
      }
    },
    {
      "name": "table-of-contents-demo",
      "type": "registry:example",
      "title": "Table Of Contents: Auto-collected",
      "description": "Auto-collected example of Table Of Contents.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/table-of-contents.json"
      ],
      "files": [
        {
          "path": "registry/examples/table-of-contents-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/table-of-contents-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "table-of-contents",
        "tier": "free"
      }
    },
    {
      "name": "table-of-contents-states",
      "type": "registry:example",
      "title": "Table Of Contents: Explicit items",
      "description": "Explicit items example of Table Of Contents.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/table-of-contents.json"
      ],
      "files": [
        {
          "path": "registry/examples/table-of-contents-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/table-of-contents-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "table-of-contents",
        "tier": "free"
      }
    },
    {
      "name": "tabs",
      "type": "registry:ui",
      "title": "Tabs",
      "description": "Keyboard-navigable content tabs with quiet pill or underline styling and a clear selected state in both themes.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/tabs.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/tabs.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "tabs",
          "views",
          "navigation",
          "radix"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Control heights, menu and sidebar row sizes, press dimming and frosted surfaces follow the platform feel tokens (--bm-control-h, --bm-menu-*, --bm-sidebar-*, --bm-material-*). Unchanged without a feel.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-30",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "Switches between a small number of peer views while retaining Radix tablist semantics and roving focus.",
          "whenToUse": [
            "Related panels within one page",
            "Compact dashboards and detail views"
          ],
          "whenNotToUse": [
            "Steps in a workflow; use progress-steps",
            "Site navigation to separate pages"
          ],
          "composesWith": [
            "card",
            "badge"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focuses the active tab"
            },
            {
              "keys": "Arrow keys / Home / End",
              "action": "Moves among tabs"
            },
            {
              "keys": "Tab again",
              "action": "Moves into the active panel"
            }
          ],
          "customization": [
            "variant: pills | underline",
            "controlled or uncontrolled value",
            "orientation"
          ]
        },
        "examples": [
          "tabs-demo",
          "tabs-states"
        ],
        "url": "https://ui.ballmac.com/components/tabs"
      }
    },
    {
      "name": "tabs-demo",
      "type": "registry:example",
      "title": "Tabs: Workspace dashboard",
      "description": "Workspace dashboard example of Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/tabs.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/tabs-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/tabs-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "tabs",
        "tier": "free"
      }
    },
    {
      "name": "tabs-states",
      "type": "registry:example",
      "title": "Tabs: Underline tabs",
      "description": "Underline tabs example of Tabs.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/tabs.json"
      ],
      "files": [
        {
          "path": "registry/examples/tabs-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/tabs-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "tabs",
        "tier": "free"
      }
    },
    {
      "name": "tag-input",
      "type": "registry:ui",
      "title": "Tag Input",
      "description": "Enter, paste, and remove text tags with duplicate prevention, limits, and keyboard shortcuts.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/tag-input.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/tag-input.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "tags",
          "chips",
          "text-input"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Enter, paste, and remove text tags with duplicate prevention, limits, and keyboard shortcuts.",
          "whenToUse": [
            "Enter free-form labels or skills",
            "Edit a small set of keywords"
          ],
          "whenNotToUse": [
            "Use multi-select for a fixed set of options"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Enter / comma",
              "action": "Adds the typed tag"
            },
            {
              "keys": "Backspace",
              "action": "Removes the last tag when empty"
            },
            {
              "keys": "Tab / Enter",
              "action": "Focuses and activates remove buttons"
            }
          ],
          "customization": [
            "maxTags, maxLength",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "tag-input-demo",
          "tag-input-states"
        ],
        "url": "https://ui.ballmac.com/components/tag-input"
      }
    },
    {
      "name": "tag-input-demo",
      "type": "registry:example",
      "title": "Tag Input: Overview",
      "description": "Overview example of Tag Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/tag-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/tag-input-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/tag-input-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "tag-input",
        "tier": "free"
      }
    },
    {
      "name": "tag-input-states",
      "type": "registry:example",
      "title": "Tag Input: States and variants",
      "description": "States and variants example of Tag Input.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/tag-input.json"
      ],
      "files": [
        {
          "path": "registry/examples/tag-input-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/tag-input-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "tag-input",
        "tier": "free"
      }
    },
    {
      "name": "team-switcher",
      "type": "registry:ui",
      "title": "Team Switcher",
      "description": "A workspace picker: the current team on a button, the others in a radio menu with logos and descriptions, an add-team row, and a compact icon mode.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/dropdown-menu.json",
        "https://ui.ballmac.com/r/i18n.json",
        "https://ui.ballmac.com/r/media.json",
        "https://ui.ballmac.com/r/media-image.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/team-switcher.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/team-switcher.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "workspace",
          "switcher",
          "menu",
          "dropdown"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Fixes a crash when it is rendered from a server component: isMediaImage now comes from the new media-image helper, not from the client-only media file. Adds media-image as a dependency.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "teams: {id,name,description,logo}. value/defaultValue/onValueChange choose the active team; onAddTeam adds the last row; compact shows only the logo.",
          "whenToUse": [
            "Multi-workspace apps in a sidebar or header",
            "Switching organizations or projects"
          ],
          "whenNotToUse": [
            "Choosing a value in a form; use select or combobox",
            "Long searchable lists; use combobox"
          ],
          "composesWith": [
            "sidebar",
            "app-shell",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the menu"
            },
            {
              "keys": "ArrowUp / ArrowDown",
              "action": "Moves between teams"
            },
            {
              "keys": "Enter",
              "action": "Chooses the team"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus"
            }
          ],
          "customization": [
            "compact",
            "logo per team",
            "onAddTeam and addLabel",
            "side and align"
          ]
        },
        "examples": [
          "team-switcher-demo",
          "team-switcher-states"
        ],
        "url": "https://ui.ballmac.com/components/team-switcher"
      }
    },
    {
      "name": "team-switcher-demo",
      "type": "registry:example",
      "title": "Team Switcher: Workspace menu",
      "description": "Workspace menu example of Team Switcher.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/team-switcher.json"
      ],
      "files": [
        {
          "path": "registry/examples/team-switcher-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/team-switcher-demo.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "team-switcher",
        "tier": "free"
      }
    },
    {
      "name": "team-switcher-states",
      "type": "registry:example",
      "title": "Team Switcher: Compact",
      "description": "Compact example of Team Switcher.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/team-switcher.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/team-switcher-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/team-switcher-states.tsx"
        }
      ],
      "categories": [
        "navigation"
      ],
      "meta": {
        "example": true,
        "of": "team-switcher",
        "tier": "free"
      }
    },
    {
      "name": "template-publication",
      "type": "registry:block",
      "title": "Marginalia: magazine",
      "description": "An editorial five-page magazine: a masthead between double rules, a lead story, an article with reading progress, drop cap and margin notes, section pages with sort and load more, author pages and an issues shelf with subscriptions.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/copy-button.json",
        "https://ui.ballmac.com/r/scroll-progress.json",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/templates/publication/publication-fonts.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-fonts.ts"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-data.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-data.ts"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-theme.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-theme.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-home.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-home.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-article.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-article.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-section.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-section.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-author.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-author.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/publication/publication-issues.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/publication/publication-issues.tsx"
        },
        {
          "path": "registry/ballmac/app/publication/page.tsx",
          "type": "registry:page",
          "target": "app/publication/page.tsx"
        },
        {
          "path": "registry/ballmac/app/publication/essays/[slug]/page.tsx",
          "type": "registry:page",
          "target": "app/publication/essays/[slug]/page.tsx"
        },
        {
          "path": "registry/ballmac/app/publication/essays/page.tsx",
          "type": "registry:page",
          "target": "app/publication/essays/page.tsx"
        },
        {
          "path": "registry/ballmac/app/publication/authors/[id]/page.tsx",
          "type": "registry:page",
          "target": "app/publication/authors/[id]/page.tsx"
        },
        {
          "path": "registry/ballmac/app/publication/issues/page.tsx",
          "type": "registry:page",
          "target": "app/publication/issues/page.tsx"
        }
      ],
      "docs": "Pages are at /publication, /publication/essays/[slug], /publication/essays, /publication/authors/[id] and /publication/issues. Edit stories, authors and issues in publication-data.ts; the palette is the publicationCss string in publication-theme.tsx.",
      "categories": [
        "templates"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "template",
          "magazine",
          "blog",
          "editorial",
          "publication",
          "article",
          "newsletter",
          "serif"
        ],
        "version": "1.0.2",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.2",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "The page that reads params now does so inside Suspense, which Cache Components (the default in new Next.js 16.4 apps) requires. Nothing else changes.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Installs a five-page magazine. Change stories and authors in publication-data.ts, the palette in publicationCss, and the duotone MagArt illustrations (or swap them for photographs).",
          "whenToUse": [
            "Magazines, long-form blogs and newsletters with an archive",
            "Reading-first sites with margin notes and a strong masthead"
          ],
          "whenNotToUse": [
            "A product blog inside a SaaS marketing site (use blog-1 and blog-post-1)"
          ],
          "composesWith": [
            "blog-1",
            "blog-post-1",
            "newsletter-1"
          ],
          "a11y": [
            {
              "keys": "Tab to a note number",
              "action": "Moves to the note; on wide screens it sits in the margin beside the paragraph"
            },
            {
              "keys": "Enter / Space on a section",
              "action": "Switches the list and announces how many stories are shown"
            }
          ],
          "customization": [
            "Replace MagArt with photographs",
            "Edit publicationCss for the light and dark palettes",
            "Change the masthead name in publication-theme.tsx"
          ]
        },
        "examples": [
          "template-publication-demo",
          "template-publication-article",
          "template-publication-section",
          "template-publication-author",
          "template-publication-issues"
        ],
        "url": "https://ui.ballmac.com/components/template-publication"
      }
    },
    {
      "name": "template-publication-demo",
      "type": "registry:example",
      "title": "Marginalia: magazine: Home",
      "description": "Home example of Marginalia: magazine.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-publication.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-publication-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-publication-demo.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-publication",
        "tier": "free"
      }
    },
    {
      "name": "template-publication-article",
      "type": "registry:example",
      "title": "Marginalia: magazine: Article",
      "description": "Article example of Marginalia: magazine.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-publication.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-publication-article.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-publication-article.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-publication",
        "tier": "free"
      }
    },
    {
      "name": "template-publication-section",
      "type": "registry:example",
      "title": "Marginalia: magazine: Section",
      "description": "Section example of Marginalia: magazine.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-publication.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-publication-section.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-publication-section.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-publication",
        "tier": "free"
      }
    },
    {
      "name": "template-publication-author",
      "type": "registry:example",
      "title": "Marginalia: magazine: Author",
      "description": "Author example of Marginalia: magazine.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-publication.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-publication-author.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-publication-author.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-publication",
        "tier": "free"
      }
    },
    {
      "name": "template-publication-issues",
      "type": "registry:example",
      "title": "Marginalia: magazine: Issues",
      "description": "Issues example of Marginalia: magazine.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-publication.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-publication-issues.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-publication-issues.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-publication",
        "tier": "free"
      }
    },
    {
      "name": "template-studio",
      "type": "registry:block",
      "title": "Studio: creative agency",
      "description": "A loud, typographic five-page agency site: giant wide headlines, a work reel whose poster follows the pointer, numbered services that open, a work index with grid or table, project pages and a brief form.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react",
        "motion@^12"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/copy-button.json",
        "https://ui.ballmac.com/r/marquee.json",
        "https://ui.ballmac.com/r/media.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/templates/studio/studio-fonts.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-fonts.ts"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-data.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-data.ts"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-theme.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-theme.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-home.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-home.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-work.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-work.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-project.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-project.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-services.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-services.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/studio/studio-contact.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/studio/studio-contact.tsx"
        },
        {
          "path": "registry/ballmac/app/studio/page.tsx",
          "type": "registry:page",
          "target": "app/studio/page.tsx"
        },
        {
          "path": "registry/ballmac/app/studio/work/page.tsx",
          "type": "registry:page",
          "target": "app/studio/work/page.tsx"
        },
        {
          "path": "registry/ballmac/app/studio/work/[slug]/page.tsx",
          "type": "registry:page",
          "target": "app/studio/work/[slug]/page.tsx"
        },
        {
          "path": "registry/ballmac/app/studio/services/page.tsx",
          "type": "registry:page",
          "target": "app/studio/services/page.tsx"
        },
        {
          "path": "registry/ballmac/app/studio/contact/page.tsx",
          "type": "registry:page",
          "target": "app/studio/contact/page.tsx"
        }
      ],
      "docs": "Pages are at /studio, /studio/work, /studio/work/[slug], /studio/services and /studio/contact. Edit projects and services in studio-data.ts; the palette is the studioCss string in studio-theme.tsx.",
      "categories": [
        "templates"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "template",
          "agency",
          "studio",
          "branding",
          "portfolio",
          "typography",
          "creative",
          "contact"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and press depth follow the theme's --bm-lift and --bm-hover tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Installs a five-page agency site. Change the content in studio-data.ts, the palette in studioCss, and the painted posters in StudioArt (or swap them for real imagery).",
          "whenToUse": [
            "Agencies, studios and collectives that want a loud, typographic site",
            "Any site where the work should carry the page"
          ],
          "whenNotToUse": [
            "A personal portfolio with long case studies (use template-portfolio)"
          ],
          "composesWith": [
            "marquee",
            "copy-button",
            "faq-2"
          ],
          "a11y": [
            {
              "keys": "Tab through the work reel",
              "action": "Shows the poster beside the focused row, the same as hovering it"
            },
            {
              "keys": "Enter / Space on a service",
              "action": "Opens or closes it"
            }
          ],
          "customization": [
            "Replace StudioArt with real images",
            "Edit studioCss for the light and dark palettes",
            "Tune the headline width in the studioDisplay class"
          ]
        },
        "examples": [
          "template-studio-demo",
          "template-studio-work",
          "template-studio-project",
          "template-studio-services",
          "template-studio-contact"
        ],
        "url": "https://ui.ballmac.com/components/template-studio"
      }
    },
    {
      "name": "template-studio-demo",
      "type": "registry:example",
      "title": "Studio: creative agency: Home",
      "description": "Home example of Studio: creative agency.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-studio.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-studio-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-studio-demo.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-studio",
        "tier": "free"
      }
    },
    {
      "name": "template-studio-work",
      "type": "registry:example",
      "title": "Studio: creative agency: Work",
      "description": "Work example of Studio: creative agency.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-studio.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-studio-work.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-studio-work.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-studio",
        "tier": "free"
      }
    },
    {
      "name": "template-studio-project",
      "type": "registry:example",
      "title": "Studio: creative agency: Project",
      "description": "Project example of Studio: creative agency.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-studio.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-studio-project.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-studio-project.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-studio",
        "tier": "free"
      }
    },
    {
      "name": "template-studio-services",
      "type": "registry:example",
      "title": "Studio: creative agency: Services",
      "description": "Services example of Studio: creative agency.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-studio.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-studio-services.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-studio-services.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-studio",
        "tier": "free"
      }
    },
    {
      "name": "template-studio-contact",
      "type": "registry:example",
      "title": "Studio: creative agency: Contact",
      "description": "Contact example of Studio: creative agency.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-studio.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-studio-contact.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-studio-contact.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-studio",
        "tier": "free"
      }
    },
    {
      "name": "template-summit",
      "type": "registry:block",
      "title": "Northlight Summit: conference",
      "description": "A five-page conference site under a sunrise ridgeline: a hero with a live countdown, a schedule you can star into an agenda with clash warnings, speakers with bios, tickets with a live total and promo code, and a venue guide.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/dialog.json",
        "https://ui.ballmac.com/r/accordion.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/templates/summit/summit-fonts.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-fonts.ts"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-data.ts",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-data.ts"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-theme.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-theme.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-home.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-home.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-schedule.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-schedule.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-speakers.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-speakers.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-tickets.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-tickets.tsx"
        },
        {
          "path": "registry/ballmac/components/templates/summit/summit-venue.tsx",
          "type": "registry:component",
          "target": "@components/ballmac/templates/summit/summit-venue.tsx"
        },
        {
          "path": "registry/ballmac/app/summit/page.tsx",
          "type": "registry:page",
          "target": "app/summit/page.tsx"
        },
        {
          "path": "registry/ballmac/app/summit/schedule/page.tsx",
          "type": "registry:page",
          "target": "app/summit/schedule/page.tsx"
        },
        {
          "path": "registry/ballmac/app/summit/speakers/page.tsx",
          "type": "registry:page",
          "target": "app/summit/speakers/page.tsx"
        },
        {
          "path": "registry/ballmac/app/summit/tickets/page.tsx",
          "type": "registry:page",
          "target": "app/summit/tickets/page.tsx"
        },
        {
          "path": "registry/ballmac/app/summit/venue/page.tsx",
          "type": "registry:page",
          "target": "app/summit/venue/page.tsx"
        }
      ],
      "docs": "Pages are at /summit, /summit/schedule, /summit/speakers, /summit/tickets and /summit/venue. Speakers, sessions, tiers and FAQ live in summit-data.ts; set EVENT_DATE for the countdown. The promo code in the demo is NORTH10. Replace Portrait with photos when you have them.",
      "categories": [
        "templates"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "template",
          "event",
          "conference",
          "summit",
          "schedule",
          "speakers",
          "tickets",
          "countdown"
        ],
        "version": "1.0.1",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.0.1",
            "date": "2026-10-11",
            "note": "Hover lift and the decorative loop follow the theme's --bm-lift, --bm-hover and ambient tokens. Unchanged by default.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-01",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Installs a five-page conference site with a countdown, a starrable schedule that warns about clashes, speaker dialogs, a ticket calculator with group and promo discounts, and a venue guide. Edit summit-data.ts and summitCss.",
          "whenToUse": [
            "Conferences, meetups and festivals",
            "Any event site with a schedule, speakers and ticket tiers"
          ],
          "whenNotToUse": [
            "Ticketing with real payments (wire the form to your processor first)"
          ],
          "composesWith": [
            "dialog",
            "accordion",
            "countdown"
          ],
          "a11y": [
            {
              "keys": "Star button on a session",
              "action": "Adds or removes it from your agenda; the summary updates in a live region"
            },
            {
              "keys": "Enter on a speaker",
              "action": "Opens their bio in a dialog; Escape closes it"
            },
            {
              "keys": "Arrow buttons beside the ticket count",
              "action": "Change the quantity; the total is announced"
            }
          ],
          "customization": [
            "Edit summit-data.ts for the event, speakers, sessions and tiers",
            "Change summitCss for the sky and ridge colours",
            "Swap Portrait for real photos",
            "Connect the checkout form to your payment provider"
          ]
        },
        "examples": [
          "template-summit-demo",
          "template-summit-schedule",
          "template-summit-speakers",
          "template-summit-tickets",
          "template-summit-venue"
        ],
        "url": "https://ui.ballmac.com/components/template-summit"
      }
    },
    {
      "name": "template-summit-demo",
      "type": "registry:example",
      "title": "Northlight Summit: conference: Home",
      "description": "Home example of Northlight Summit: conference.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-summit.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-summit-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-summit-demo.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-summit",
        "tier": "free"
      }
    },
    {
      "name": "template-summit-schedule",
      "type": "registry:example",
      "title": "Northlight Summit: conference: Schedule",
      "description": "Schedule example of Northlight Summit: conference.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-summit.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-summit-schedule.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-summit-schedule.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-summit",
        "tier": "free"
      }
    },
    {
      "name": "template-summit-speakers",
      "type": "registry:example",
      "title": "Northlight Summit: conference: Speakers",
      "description": "Speakers example of Northlight Summit: conference.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-summit.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-summit-speakers.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-summit-speakers.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-summit",
        "tier": "free"
      }
    },
    {
      "name": "template-summit-tickets",
      "type": "registry:example",
      "title": "Northlight Summit: conference: Tickets",
      "description": "Tickets example of Northlight Summit: conference.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-summit.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-summit-tickets.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-summit-tickets.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-summit",
        "tier": "free"
      }
    },
    {
      "name": "template-summit-venue",
      "type": "registry:example",
      "title": "Northlight Summit: conference: Venue",
      "description": "Venue example of Northlight Summit: conference.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/template-summit.json"
      ],
      "files": [
        {
          "path": "registry/examples/template-summit-venue.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/template-summit-venue.tsx"
        }
      ],
      "categories": [
        "templates"
      ],
      "meta": {
        "example": true,
        "of": "template-summit",
        "tier": "free"
      }
    },
    {
      "name": "textarea",
      "type": "registry:ui",
      "title": "Textarea",
      "description": "A multi-line text field that can grow with its content between minRows and maxRows, then scroll. Plain resizable mode when autoResize is off.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/textarea.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/textarea.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "textarea",
          "form",
          "autosize",
          "multiline"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "Multi-line text input. Set autoResize with minRows and maxRows for chat composers and comment boxes; leave it off for a user-resizable box with a fixed rows count.",
          "whenToUse": [
            "Comments, feedback and descriptions",
            "Chat or prompt composers that grow as the user types (autoResize)",
            "Notes fields in settings forms"
          ],
          "whenNotToUse": [
            "Single-line values (use input)",
            "Rich text or markdown editing with formatting controls"
          ],
          "composesWith": [
            "label",
            "button",
            "dialog"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Moves focus to the textarea"
            },
            {
              "keys": "Enter",
              "action": "Inserts a new line"
            }
          ],
          "customization": [
            "autoResize: grows with content; minRows (default rows or 3) and maxRows cap the height",
            "aria-invalid=\"true\" switches to destructive styling",
            "Works controlled (value/onChange) or uncontrolled"
          ]
        },
        "source": {
          "name": "shadcn/ui Textarea",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "textarea-demo",
          "textarea-autosize"
        ],
        "url": "https://ui.ballmac.com/components/textarea"
      }
    },
    {
      "name": "textarea-demo",
      "type": "registry:example",
      "title": "Textarea: Default",
      "description": "Default example of Textarea.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/textarea.json",
        "https://ui.ballmac.com/r/label.json"
      ],
      "files": [
        {
          "path": "registry/examples/textarea-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/textarea-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "textarea",
        "tier": "free"
      }
    },
    {
      "name": "textarea-autosize",
      "type": "registry:example",
      "title": "Textarea: Auto-resize",
      "description": "Auto-resize example of Textarea.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/textarea.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/textarea-autosize.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/textarea-autosize.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "textarea",
        "tier": "free"
      }
    },
    {
      "name": "time-picker",
      "type": "registry:ui",
      "title": "Time Picker",
      "description": "A native time field with optional quick-pick presets and controlled or uncontrolled state.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/time-picker.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/time-picker.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "time",
          "schedule",
          "input"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A native time field with optional quick-pick presets and controlled or uncontrolled state.",
          "whenToUse": [
            "Schedule an appointment or reminder",
            "Offer common meeting times as shortcuts"
          ],
          "whenNotToUse": [
            "Use date-range-picker for a period across days"
          ],
          "composesWith": [
            "input"
          ],
          "a11y": [
            {
              "keys": "Arrow keys",
              "action": "Edits the native time field"
            },
            {
              "keys": "Tab / Enter",
              "action": "Activates a time preset"
            }
          ],
          "customization": [
            "presets",
            "value / defaultValue and onValueChange"
          ]
        },
        "examples": [
          "time-picker-demo",
          "time-picker-states"
        ],
        "url": "https://ui.ballmac.com/components/time-picker"
      }
    },
    {
      "name": "time-picker-demo",
      "type": "registry:example",
      "title": "Time Picker: Overview",
      "description": "Overview example of Time Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/time-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/time-picker-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/time-picker-demo.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "time-picker",
        "tier": "free"
      }
    },
    {
      "name": "time-picker-states",
      "type": "registry:example",
      "title": "Time Picker: States and variants",
      "description": "States and variants example of Time Picker.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/time-picker.json"
      ],
      "files": [
        {
          "path": "registry/examples/time-picker-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/time-picker-states.tsx"
        }
      ],
      "categories": [
        "forms"
      ],
      "meta": {
        "example": true,
        "of": "time-picker",
        "tier": "free"
      }
    },
    {
      "name": "toast-stack",
      "type": "registry:ui",
      "title": "Toast Stack",
      "description": "A token-based notification stack with dismissal, optional actions, and pause-on-interaction timing.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/toast-stack.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/toast-stack.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "toast",
          "notification",
          "feedback"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "A token-based notification stack with dismissal, optional actions, and pause-on-interaction timing.",
          "whenToUse": [
            "Confirm an asynchronous action",
            "Offer undo or retry after a task"
          ],
          "whenNotToUse": [
            "Use banner for persistent page-wide messages"
          ],
          "composesWith": [
            "button",
            "notification-stack"
          ],
          "a11y": [
            {
              "keys": "Tab / Enter / Escape",
              "action": "Activate actions or dismiss a focused toast"
            }
          ],
          "customization": [
            "Controlled or uncontrolled list",
            "Auto-dismiss duration and pause"
          ]
        },
        "examples": [
          "toast-stack-demo",
          "toast-stack-states"
        ],
        "url": "https://ui.ballmac.com/components/toast-stack"
      }
    },
    {
      "name": "toast-stack-demo",
      "type": "registry:example",
      "title": "Toast Stack: Overview",
      "description": "Overview example of Toast Stack.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toast-stack.json"
      ],
      "files": [
        {
          "path": "registry/examples/toast-stack-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toast-stack-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "toast-stack",
        "tier": "free"
      }
    },
    {
      "name": "toast-stack-states",
      "type": "registry:example",
      "title": "Toast Stack: States and variants",
      "description": "States and variants example of Toast Stack.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toast-stack.json"
      ],
      "files": [
        {
          "path": "registry/examples/toast-stack-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toast-stack-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "toast-stack",
        "tier": "free"
      }
    },
    {
      "name": "toast",
      "type": "registry:ui",
      "title": "Toast",
      "description": "Stacked toasts on Sonner styled with theme tokens: status icons, actions, promises, swipe to dismiss, pause on hover and focus, and screen-reader announcements.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "sonner@^2",
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/toast.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/toast.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "toast",
          "notification",
          "sonner",
          "feedback"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Render <Toaster /> once, then call toast(), toast.success(), toast.error() or toast.promise() from anywhere.",
          "whenToUse": [
            "Confirming an action (saved, copied, archived)",
            "Undo prompts",
            "Background task results"
          ],
          "whenNotToUse": [
            "Errors the user must fix in a form; use field errors",
            "Permanent page messages; use alert or banner",
            "A macOS-style stack; use toast-stack"
          ],
          "composesWith": [
            "button",
            "toast-stack"
          ],
          "a11y": [
            {
              "keys": "Alt+T",
              "action": "Focuses the notification region"
            },
            {
              "keys": "Tab",
              "action": "Reaches toast actions and close buttons"
            },
            {
              "keys": "Screen readers",
              "action": "Toasts are announced politely"
            }
          ],
          "customization": [
            "position",
            "duration",
            "action and cancel buttons",
            "toasterId for multiple regions"
          ]
        },
        "source": {
          "name": "shadcn/ui Sonner",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "toast-demo",
          "toast-states"
        ],
        "url": "https://ui.ballmac.com/components/toast"
      }
    },
    {
      "name": "toast-demo",
      "type": "registry:example",
      "title": "Toast: Toast types",
      "description": "Toast types example of Toast.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toast.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/toast-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toast-demo.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "toast",
        "tier": "free"
      }
    },
    {
      "name": "toast-states",
      "type": "registry:example",
      "title": "Toast: Action and warning",
      "description": "Action and warning example of Toast.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toast.json",
        "https://ui.ballmac.com/r/button.json"
      ],
      "files": [
        {
          "path": "registry/examples/toast-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toast-states.tsx"
        }
      ],
      "categories": [
        "feedback"
      ],
      "meta": {
        "example": true,
        "of": "toast",
        "tier": "free"
      }
    },
    {
      "name": "toggle-group",
      "type": "registry:ui",
      "title": "Toggle Group",
      "description": "A compact roving-focus selection group for one or several pressed options, with clear states and mobile-friendly sizing.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/direction.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/toggle-group.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/toggle-group.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "toggle",
          "selection",
          "toolbar",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Lets users choose one or multiple options from a short row while Radix handles roving focus.",
          "whenToUse": [
            "View mode or density selector",
            "Formatting options that can coexist"
          ],
          "whenNotToUse": [
            "Unrelated actions; use button-group",
            "A long list of options; use select"
          ],
          "composesWith": [
            "button-group"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Enters or exits the group"
            },
            {
              "keys": "Arrow keys",
              "action": "Moves focus between items"
            },
            {
              "keys": "Enter / Space",
              "action": "Selects the focused item"
            }
          ],
          "customization": [
            "type: single | multiple",
            "variant: default | outline",
            "size: sm | default | lg"
          ]
        },
        "examples": [
          "toggle-group-demo",
          "toggle-group-states"
        ],
        "url": "https://ui.ballmac.com/components/toggle-group"
      }
    },
    {
      "name": "toggle-group-demo",
      "type": "registry:example",
      "title": "Toggle Group: View density",
      "description": "View density example of Toggle Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toggle-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/toggle-group-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toggle-group-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "toggle-group",
        "tier": "free"
      }
    },
    {
      "name": "toggle-group-states",
      "type": "registry:example",
      "title": "Toggle Group: Multiple filters",
      "description": "Multiple filters example of Toggle Group.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toggle-group.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/toggle-group-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toggle-group-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "toggle-group",
        "tier": "free"
      }
    },
    {
      "name": "toggle",
      "type": "registry:ui",
      "title": "Toggle",
      "description": "A compact two-state action with distinct pressed styling, visible keyboard focus, and outline or filled variants.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/toggle.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/toggle.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "toggle",
          "pressed",
          "toolbar",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "An on/off action such as pinning or formatting that communicates its pressed state to assistive technology.",
          "whenToUse": [
            "A toolbar action with persistent pressed state",
            "Favorite or pin control"
          ],
          "whenNotToUse": [
            "Boolean form field; use switch",
            "Multiple related choices; use toggle-group"
          ],
          "composesWith": [
            "button-group"
          ],
          "a11y": [
            {
              "keys": "Tab",
              "action": "Focuses the toggle"
            },
            {
              "keys": "Enter / Space",
              "action": "Changes pressed state"
            }
          ],
          "customization": [
            "variant: default | outline",
            "size: sm | default | lg",
            "controlled or uncontrolled pressed state"
          ]
        },
        "examples": [
          "toggle-demo",
          "toggle-states"
        ],
        "url": "https://ui.ballmac.com/components/toggle"
      }
    },
    {
      "name": "toggle-demo",
      "type": "registry:example",
      "title": "Toggle: Pin a workspace",
      "description": "Pin a workspace example of Toggle.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toggle.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/toggle-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toggle-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "toggle",
        "tier": "free"
      }
    },
    {
      "name": "toggle-states",
      "type": "registry:example",
      "title": "Toggle: Sizes and states",
      "description": "Sizes and states example of Toggle.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/toggle.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/toggle-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/toggle-states.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "toggle",
        "tier": "free"
      }
    },
    {
      "name": "tooltip",
      "type": "registry:ui",
      "title": "Tooltip",
      "description": "A Radix tooltip with an arrow, side offset and fade and zoom transitions that opens on hover and keyboard focus. Works standalone or under a shared provider.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui"
      ],
      "devDependencies": [
        "tw-animate-css"
      ],
      "registryDependencies": [
        "utils"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/tooltip.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/tooltip.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "tooltip",
          "hint",
          "popover",
          "radix"
        ],
        "version": "1.0.0",
        "updated": "2026-09-28",
        "tests": true,
        "ai": {
          "summary": "Short text hint for a control, shown on hover and focus. Compose Tooltip > TooltipTrigger (style it with buttonVariants and give icon triggers an aria-label) + TooltipContent. Put Kbd inside the content for shortcut hints.",
          "whenToUse": [
            "Naming icon-only buttons (still give the button an aria-label)",
            "Shortcut hints next to a label",
            "Clarifying truncated text"
          ],
          "whenNotToUse": [
            "Essential information or anything interactive (use a popover)",
            "Touch-first UIs where hover doesn't exist",
            "Error messages (show them inline)"
          ],
          "composesWith": [
            "button",
            "kbd",
            "avatar"
          ],
          "a11y": [
            {
              "keys": "Tab (focus trigger)",
              "action": "Opens the tooltip"
            },
            {
              "keys": "Escape",
              "action": "Closes the tooltip"
            }
          ],
          "customization": [
            "TooltipProvider delayDuration (default 200 ms) and skipDelayDuration",
            "TooltipContent side, align, sideOffset (default 6) and arrow (default true)",
            "Needs the tw-animate-css classes for the open and close animation"
          ]
        },
        "source": {
          "name": "shadcn/ui Tooltip",
          "url": "https://github.com/shadcn-ui/ui",
          "license": "MIT",
          "copyright": "Copyright (c) 2023 shadcn",
          "modified": true
        },
        "examples": [
          "tooltip-demo"
        ],
        "url": "https://ui.ballmac.com/components/tooltip"
      }
    },
    {
      "name": "tooltip-demo",
      "type": "registry:example",
      "title": "Tooltip: Default",
      "description": "Default example of Tooltip.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/tooltip.json",
        "https://ui.ballmac.com/r/button.json",
        "https://ui.ballmac.com/r/kbd.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/tooltip-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/tooltip-demo.tsx"
        }
      ],
      "categories": [
        "primitives"
      ],
      "meta": {
        "example": true,
        "of": "tooltip",
        "tier": "free"
      }
    },
    {
      "name": "user-menu",
      "type": "registry:ui",
      "title": "User Menu",
      "description": "An account menu on the dropdown: avatar or avatar-with-name trigger, a header card with plan, link groups with shortcuts and badges, a theme submenu and sign out.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "utils",
        "https://ui.ballmac.com/r/avatar.json",
        "https://ui.ballmac.com/r/dropdown-menu.json",
        "https://ui.ballmac.com/r/i18n.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/components/user-menu.tsx",
          "type": "registry:ui",
          "target": "@components/ballmac/user-menu.tsx"
        }
      ],
      "categories": [
        "saas"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "account",
          "avatar",
          "menu",
          "theme"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "user {name,email,image,plan,status}, groups: UserMenuItem[][], theme/onThemeChange, onSignOut, variant avatar | full.",
          "whenToUse": [
            "Headers and sidebar footers",
            "Account access with theme and sign out"
          ],
          "whenNotToUse": [
            "Switching workspaces; use team-switcher",
            "Generic action menus; use dropdown-menu"
          ],
          "composesWith": [
            "avatar",
            "dropdown-menu",
            "team-switcher"
          ],
          "a11y": [
            {
              "keys": "Enter / Space / ArrowDown",
              "action": "Opens the menu"
            },
            {
              "keys": "Arrow keys and typeahead",
              "action": "Move between items"
            },
            {
              "keys": "Escape",
              "action": "Closes and returns focus"
            },
            {
              "keys": "Screen readers",
              "action": "The avatar button names the person; links are real links"
            }
          ],
          "customization": [
            "variant",
            "groups with icons, shortcuts and badges",
            "theme submenu",
            "open state props"
          ]
        },
        "examples": [
          "user-menu-demo",
          "user-menu-states"
        ],
        "url": "https://ui.ballmac.com/components/user-menu"
      }
    },
    {
      "name": "user-menu-demo",
      "type": "registry:example",
      "title": "User Menu: Sidebar account",
      "description": "Sidebar account example of User Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/user-menu.json"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "registry/examples/user-menu-demo.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/user-menu-demo.tsx"
        }
      ],
      "categories": [
        "saas"
      ],
      "meta": {
        "example": true,
        "of": "user-menu",
        "tier": "free"
      }
    },
    {
      "name": "user-menu-states",
      "type": "registry:example",
      "title": "User Menu: Avatar only",
      "description": "Avatar only example of User Menu.",
      "registryDependencies": [
        "https://ui.ballmac.com/r/user-menu.json"
      ],
      "files": [
        {
          "path": "registry/examples/user-menu-states.tsx",
          "type": "registry:example",
          "target": "@components/ballmac/examples/user-menu-states.tsx"
        }
      ],
      "categories": [
        "saas"
      ],
      "meta": {
        "example": true,
        "of": "user-menu",
        "tier": "free"
      }
    },
    {
      "name": "calendar-dates",
      "type": "registry:lib",
      "title": "Calendar Dates",
      "description": "Date helpers for calendars with no dependencies: weeks that start where the locale says, month grids, daylight-saving-safe day math, and layout for overlapping events.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/calendar-dates.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/calendar-dates.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "date",
          "calendar",
          "week",
          "month",
          "layout",
          "locale"
        ],
        "version": "1.0.0",
        "updated": "2026-10-19",
        "tests": true,
        "ai": {
          "summary": "Import from @/lib/ballmac/calendar-dates: toDate, addDays, addMonths, startOfWeek, monthGrid, weekStartFor(locale), spanOf, layoutDay and layoutWeek.",
          "whenToUse": [
            "Building a calendar, scheduler or timeline",
            "Reading dates like 2026-10-20 as local days, not UTC",
            "Placing overlapping events side by side"
          ],
          "whenNotToUse": [
            "Formatting or time zone conversion for a whole app; use Intl or a date library",
            "A date picker; use calendar"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "weekStartsOn is 0 (Sunday) to 6",
            "spanOf treats an all-day event's end as its last day, inclusive"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/calendar-dates"
      }
    },
    {
      "name": "color",
      "type": "registry:lib",
      "title": "Color",
      "description": "Resolves theme tokens for canvas and WebGL effects: CSS variables to color strings or RGBA numbers, plus a theme-change observer so effects repaint in dark mode.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/color.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/color.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "color",
          "canvas",
          "webgl",
          "theme"
        ],
        "version": "1.0.0",
        "updated": "2026-09-29",
        "ai": {
          "summary": "Use resolveCssColor(el, '--primary') for canvas fillStyle and cssColorToRgba for WebGL, and observeTheme to repaint when the theme changes.",
          "whenToUse": [
            "Canvas or WebGL components that must follow the theme tokens"
          ],
          "whenNotToUse": [
            "DOM elements (use Tailwind token classes)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Pass any CSS variable name, var() expression or CSS color"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/color"
      }
    },
    {
      "name": "direction",
      "type": "registry:lib",
      "title": "Direction Utilities",
      "description": "Right-to-left support helpers: useDirection reads the reading direction, DirectionProvider tells Radix-based components, and Dir scopes a region to ltr or rtl.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "radix-ui@^1"
      ],
      "files": [
        {
          "path": "registry/ballmac/lib/direction.tsx",
          "type": "registry:lib",
          "target": "@lib/ballmac/direction.tsx"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "rtl",
          "ltr",
          "direction",
          "i18n",
          "arabic",
          "hebrew",
          "persian"
        ],
        "version": "1.0.0",
        "updated": "2026-10-02",
        "ai": {
          "summary": "Import useDirection, DirectionProvider and Dir from @/lib/ballmac/direction. Set <html dir> and wrap the app in DirectionProvider so keyboard arrows, sliders, menus and tabs follow the reading direction.",
          "whenToUse": [
            "Shipping the app in Arabic, Hebrew, Persian or Urdu",
            "A region of mixed-direction content",
            "Code that must know which way is forward"
          ],
          "whenNotToUse": [
            "Layout alone: logical properties (ms-, me-, start-, end-) already follow dir with no JavaScript"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "dir: pass it to useDirection to force a direction",
            "Dir renders a div with display: contents"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/direction"
      }
    },
    {
      "name": "feel-presets",
      "type": "registry:lib",
      "title": "Feel Presets",
      "description": "Read and set the platform feel (web, macOS, iOS or Windows), detect the device's own, and remember an override. useFeel for components that need to know.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/feel.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/feel.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "platform",
          "macos",
          "windows",
          "ios",
          "detect",
          "tauri",
          "electron"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "useFeel() returns the current feel and setFeel(). detectFeel() reads the platform from the user agent (browser, Tauri, Electron). setFeel('auto') returns to the device's own feel. The feel is the data-feel attribute on <html>.",
          "whenToUse": [
            "A component needs to behave differently per platform, such as which side the window controls sit on",
            "Letting users override the detected feel in settings"
          ],
          "whenNotToUse": [
            "Styling that tokens already handle: use the --bm-* variables and Tailwind classes, which follow the feel by themselves"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "setFeel('macos') | 'ios' | 'windows' | 'web' | 'auto'",
            "Put data-feel on a container to scope a feel to part of the page"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-presets"
      }
    },
    {
      "name": "frame-props",
      "type": "registry:lib",
      "title": "Frame Props",
      "description": "Picks the plain HTML attributes from a block's props, so a block that shows a loading or error frame never spreads its own data props onto a DOM element. Safe in server components.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/frame-props.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/frame-props.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "state",
          "props",
          "server",
          "helper"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "frameProps(props) returns only id, style, lang, dir, role, hidden, title, tabIndex and aria-* and data-* attributes. Spread it onto the frame a block draws while it is loading or has failed.",
          "whenToUse": [
            "Writing a block with a state prop: the frame it draws instead of its content",
            "A server component that needs the same helper state-view exports"
          ],
          "whenNotToUse": [
            "Passing every prop through to the ready block: spread them as normal"
          ],
          "composesWith": [
            "state-view"
          ],
          "a11y": [],
          "customization": [
            "Add attributes by wrapping it: { ...frameProps(props), onClick }"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/frame-props"
      }
    },
    {
      "name": "highlight",
      "type": "registry:lib",
      "title": "Highlight",
      "description": "A small dependency-free tokenizer for the snippets developer UIs show: JSON, shell and curl, JavaScript and TypeScript, Python, Go, HTTP and .env, with theme-aware token colors.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/highlight.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/highlight.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "syntax highlighting",
          "tokenizer",
          "code",
          "snippet"
        ],
        "version": "1.0.0",
        "updated": "2026-10-01",
        "tests": true,
        "ai": {
          "summary": "Import highlightLines(code, language) from @/lib/ballmac/highlight to get tokens grouped by line, and map each token to tokenClass[token.type]. languageFromName('app.ts') picks a language from a file name or label. Not a full grammar: use Shiki for exact highlighting of large files.",
          "whenToUse": [
            "Showing short request examples, logs and config without shipping a highlighter",
            "Server or client rendering with no async loading"
          ],
          "whenNotToUse": [
            "Editors or long source files that need exact grammar (use Shiki)",
            "Languages outside the list"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "tokenClass: change the Tailwind classes per token type",
            "language: json | bash | javascript | typescript | python | go | http | env | text"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/highlight"
      }
    },
    {
      "name": "i18n",
      "type": "registry:lib",
      "title": "i18n Utilities",
      "description": "Translate every built-in string and set the locale in one place: I18nProvider takes a messages object, useMessages looks text up, useLocale feeds Intl formatting.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/i18n.tsx",
          "type": "registry:lib",
          "target": "@lib/ballmac/i18n.tsx"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "i18n",
          "translation",
          "locale",
          "internationalization",
          "arabic",
          "labels",
          "plural"
        ],
        "version": "1.0.0",
        "updated": "2026-10-02",
        "ai": {
          "summary": "Wrap the app in <I18nProvider locale messages>. Every Ballmac component looks its built-in text up by key with the English text as the default, so nothing breaks when a key is missing. The key list is at /i18n/en.json.",
          "whenToUse": [
            "Localising an app that uses Ballmac components",
            "Setting one locale for dates, numbers and sorting"
          ],
          "whenNotToUse": [
            "Your own app copy: use your i18n library (next-intl, i18next, Lingui) and pass its output in through props or messages"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "messages: a flat key to text object, with {name} placeholders and _one/_few/_many/_other plural suffixes",
            "locale: a BCP 47 tag such as ar, he, fa-IR, de-DE"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/i18n"
      }
    },
    {
      "name": "media-image",
      "type": "registry:lib",
      "title": "Media image check",
      "description": "The MediaImage type and isMediaImage(), which tells a picture (a URL or { src, alt }) from an element. A plain module, so server components can call it.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/media-image.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/media-image.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "image",
          "media",
          "server components"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "tests": true,
        "ai": {
          "summary": "isMediaImage(value) is true for an image URL or { src, alt }. Import it from here, not from media.tsx, when a server component needs it.",
          "whenToUse": [
            "A server component that accepts either a picture or your own element in a slot and renders pictures through Media"
          ],
          "whenNotToUse": [
            "Rendering a picture: use the Media component"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": []
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/media-image"
      }
    },
    {
      "name": "motion-presets",
      "type": "registry:lib",
      "title": "Motion Presets",
      "description": "Shared easings, durations, springs and enter variants for Motion that follow the theme's motion tokens (speed, bounce, travel, hover, stagger), plus a useMotion hook.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "dependencies": [
        "motion@^12"
      ],
      "files": [
        {
          "path": "registry/ballmac/lib/motion.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/motion.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "animation",
          "easing",
          "spring"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Durations, springs, variants and stagger follow the theme's --bm-* motion variables (defaults are unchanged). Adds useMotion, MotionProvider, getMotion and refreshMotion.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Import ease, duration, spring, variants and stagger from @/lib/ballmac/motion instead of hard-coding animation values. They read the theme's --bm-* motion variables, so a motion theme changes them with no code changes. useMotion() gives the same numbers reactively.",
          "whenToUse": [
            "Writing a new animated component that should match Ballmac UI",
            "Page or section entrance animations"
          ],
          "whenNotToUse": [
            "CSS-only transitions (use the --bm-ease-* and --bm-duration-* variables)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "spring.snappy for controls, spring.gentle for panels, spring.bouncy for accents",
            "variants.fadeUp with stagger() for lists",
            "useMotion() for live durations, springs, distance, lift, press and loop; MotionProvider scopes a setting to a preview"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-presets"
      }
    },
    {
      "name": "return-focus",
      "type": "registry:lib",
      "title": "Return focus",
      "description": "A hook that puts keyboard focus back on the element that opened a dialog, for dialogs opened from state, which have no trigger for Radix to return focus to.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/return-focus.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/return-focus.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "dialog",
          "focus",
          "keyboard",
          "accessibility",
          "modal",
          "alert dialog"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "tests": true,
        "ai": {
          "summary": "const returnFocus = useReturnFocus(open); <DialogContent {...returnFocus}>. Use it when a dialog is controlled with open and opened by your own code (a Delete button that asks to confirm). Dialogs with a DialogTrigger do not need it.",
          "whenToUse": [
            "Any Dialog or AlertDialog that is opened from state rather than from a DialogTrigger",
            "A lightbox or confirmation opened from a list item"
          ],
          "whenNotToUse": [
            "A dialog that already uses DialogTrigger, which returns focus by itself"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": []
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/return-focus"
      }
    },
    {
      "name": "scroll",
      "type": "registry:lib",
      "title": "Scroll Utilities",
      "description": "Small hooks and helpers for scroll-aware UI: scrolled state, scroll direction, a scroll spy for in-page sections, and reduced-motion-aware scrolling to an element below a sticky header.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/scroll.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/scroll.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "scroll",
          "scrollspy",
          "sticky header",
          "reduced motion"
        ],
        "version": "1.0.0",
        "updated": "2026-09-30",
        "tests": true,
        "ai": {
          "summary": "Import useScrolled, useScrollDirection, useScrollSpy, scrollToId, scrollToElement and prefersReducedMotion from @/lib/ballmac/scroll. Pass a container ref to watch an element instead of the page.",
          "whenToUse": [
            "Sticky headers that change on scroll",
            "Highlighting the current section in a table of contents or tab bar",
            "Smooth in-page links that respect reduced motion"
          ],
          "whenNotToUse": [
            "Scroll-linked animation values (use Motion's useScroll)",
            "Virtual lists"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "offset: pixels reserved for a sticky header",
            "container: a ref to a scrollable element"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/scroll"
      }
    },
    {
      "name": "shortcut",
      "type": "registry:lib",
      "title": "Shortcut",
      "description": "Keyboard shortcuts as plain strings (\"Mod+Shift+K\"): written as ⇧⌘K on a Mac and Ctrl+Shift+K elsewhere, recorded from key presses, and normalized so conflicts can be found.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/feel-presets.json"
      ],
      "files": [
        {
          "path": "registry/ballmac/lib/shortcut.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/shortcut.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "keyboard",
          "shortcut",
          "hotkey",
          "macos",
          "windows",
          "feel"
        ],
        "version": "1.0.0",
        "updated": "2026-10-17",
        "tests": true,
        "ai": {
          "summary": "formatShortcut('Mod+Shift+K', feel) → '⇧⌘K' or 'Ctrl+Shift+K'. shortcutFromEvent(event, isMac) records a key press (null while only modifiers are down). normalizeShortcut(s, feel) gives one spelling per combination for comparing.",
          "whenToUse": [
            "Showing shortcuts in menus, tooltips and settings in each platform's notation",
            "Recording or comparing user-chosen shortcuts"
          ],
          "whenNotToUse": [
            "Listening for shortcuts at runtime: use your framework's hotkey hook or Tauri's global-shortcut plugin, and pass them these strings"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": []
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/shortcut"
      }
    },
    {
      "name": "use-resource",
      "type": "registry:lib",
      "title": "Use Resource",
      "description": "A small fetch state machine that gives every block the state to show: loading, ready, empty or error, with retry, abort and stale-answer protection. Includes an adapter for TanStack Query and SWR.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "files": [
        {
          "path": "registry/ballmac/lib/use-resource.ts",
          "type": "registry:lib",
          "target": "@lib/ballmac/use-resource.ts"
        }
      ],
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "state",
          "loading",
          "empty",
          "error",
          "fetch",
          "hook",
          "swr",
          "tanstack"
        ],
        "version": "1.1.0",
        "updated": "2026-10-11",
        "changelog": [
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds FormStateProps and formPhase, the shared state contract for form blocks (submitting, success, error).",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-12",
            "note": "First release.",
            "breaking": false
          }
        ],
        "tests": true,
        "ai": {
          "summary": "useResource(fetcher) returns { state, data, error, retry, setData }. Pass state, data and onRetry to any Ballmac block that has a state prop. stateOf(query) maps TanStack Query or SWR results onto the same states. BlockState is the shared type.",
          "whenToUse": [
            "Wiring a block's loading, empty and error states to a fetch",
            "Mapping TanStack Query or SWR results onto a block's state prop"
          ],
          "whenNotToUse": [
            "Server components that fetch before render: pass the data and let the block render ready or empty",
            "Mutations: forms track submitting and success themselves"
          ],
          "composesWith": [
            "state-view"
          ],
          "a11y": [],
          "customization": [
            "isEmpty: decide what counts as no data",
            "enabled: wait until you can fetch",
            "deps: fetch again when they change",
            "setData: update the data after an optimistic edit"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/use-resource"
      }
    },
    {
      "name": "feel-ios",
      "type": "registry:theme",
      "title": "iOS feel",
      "description": "44 px touch targets, 17 px text, large corners, flat grouped surfaces and a springier motion. Controls dim when pressed and nothing reacts to hover. For mobile web apps and webviews.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "spacing": "0.275rem",
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.75rem",
          "bm-speed": "1.1",
          "bm-bounce": "0.55",
          "bm-travel": "1.1",
          "bm-hover": "0",
          "bm-stagger": "1.1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.026, 0.0947, 0.1927, 0.3084, 0.4319, 0.5553, 0.6724, 0.7789, 0.8718, 0.9497, 1.0122, 1.0596, 1.0932, 1.1143, 1.1249, 1.1268, 1.1219, 1.1121, 1.0989, 1.0839, 1.0681, 1.0526, 1.038, 1.0249, 1.0136, 1.0042, 0.9967, 0.9912, 0.9873, 0.985, 0.984, 0.984, 0.9848, 0.9862, 0.9879, 0.9899, 0.9919, 0.9938, 0.9956, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "11px",
          "bm-lift": "0px",
          "bm-press": "1",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0 0 0 rgb(0 0 0 / 0)",
          "bm-shadow-sm": "0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-md": "0 2px 10px rgb(0 0 0 / 0.08)",
          "bm-shadow-lg": "0 10px 40px rgb(0 0 0 / 0.18)",
          "bm-shadow-xl": "0 16px 56px rgb(0 0 0 / 0.22)",
          "bm-shadow-2xl": "0 24px 72px rgb(0 0 0 / 0.28)",
          "bm-shadow-popover": "0 10px 40px rgb(0 0 0 / 0.18)",
          "bm-text-xs": "0.8125rem",
          "bm-text-xs-lh": "1.125rem",
          "bm-text-sm": "0.9375rem",
          "bm-text-sm-lh": "1.375rem",
          "bm-text-base": "1.0625rem",
          "bm-text-base-lh": "1.5rem",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "40%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "2.75rem",
          "bm-control-h-sm": "2.25rem",
          "bm-control-h-lg": "3rem",
          "bm-target-min": "2.75rem",
          "bm-check-size": "1.375rem",
          "bm-switch-w": "3.1875rem",
          "bm-switch-h": "1.9375rem",
          "bm-press-dim": "0.6",
          "bm-material-blur": "30px",
          "bm-material-alpha": "80%",
          "bm-sidebar-item-h": "2.75rem",
          "bm-sidebar-item-radius": "0.625rem",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2.75rem",
          "bm-menu-item-radius": "0px",
          "bm-menu-pad": "0px",
          "bm-scrollbar-width": "none",
          "bm-titlebar-h": "2.75rem",
          "bm-toolbar-h": "44px"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "Changes how everything handles (shape, size, focus, shadows, motion) and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?fe=ios",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "theme",
          "tokens",
          "platform",
          "ios",
          "desktop"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "Big targets, rounded, dims on press. Sets radius, density, text scale, control and menu sizes, focus ring, shadows and motion as CSS variables that Tailwind's shadow and text scales and every Ballmac component follow, without touching colours.",
          "whenToUse": [
            "Mobile web apps, PWAs and webviews",
            "Anything used with a thumb"
          ],
          "whenNotToUse": [
            "The project needs its own sizing system or does not use Tailwind",
            "A native app UI is required; these are web components that feel like the platform, not native controls"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --radius, --spacing and the --bm-* variables by hand, or tune them at https://ui.ballmac.com/themes",
            "Set data-feel on a container to scope a feel to part of the page"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-ios"
      }
    },
    {
      "name": "feel-macos",
      "type": "registry:theme",
      "title": "macOS feel",
      "description": "Compact 28 px controls, 13 px text, a soft focus halo, hairline-edged shadows and frosted popovers and sidebars. For desktop apps built with Tauri or Electron that should sit comfortably next to native Mac apps.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "spacing": "0.225rem",
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.375rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0.5px 1px rgb(0 0 0 / 0.08), 0 0 0 0.5px rgb(0 0 0 / 0.04)",
          "bm-shadow-sm": "0 1px 3px rgb(0 0 0 / 0.12), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-md": "0 4px 12px -2px rgb(0 0 0 / 0.14), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-lg": "0 12px 32px -6px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "bm-shadow-xl": "0 20px 48px -8px rgb(0 0 0 / 0.26), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "bm-shadow-2xl": "0 28px 64px -12px rgb(0 0 0 / 0.32), 0 0 0 0.5px rgb(0 0 0 / 0.1)",
          "bm-shadow-popover": "0 8px 30px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.12)",
          "bm-text-xs": "0.6875rem",
          "bm-text-xs-lh": "0.875rem",
          "bm-text-sm": "0.8125rem",
          "bm-text-sm-lh": "1.125rem",
          "bm-text-base": "0.9375rem",
          "bm-text-base-lh": "1.375rem",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "1.75rem",
          "bm-control-h-sm": "1.5rem",
          "bm-control-h-lg": "2rem",
          "bm-target-min": "0px",
          "bm-check-size": "0.875rem",
          "bm-switch-w": "2.375rem",
          "bm-switch-h": "1.375rem",
          "bm-press-dim": "1",
          "bm-material-blur": "24px",
          "bm-material-alpha": "78%",
          "bm-sidebar-item-h": "1.75rem",
          "bm-sidebar-item-radius": "0.375rem",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "1.5rem",
          "bm-menu-item-radius": "0.3125rem",
          "bm-menu-pad": "0.3125rem",
          "bm-scrollbar-width": "thin",
          "bm-titlebar-h": "2.75rem",
          "bm-toolbar-h": "52px"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "Changes how everything handles (shape, size, focus, shadows, motion) and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?fe=macos",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "theme",
          "tokens",
          "platform",
          "macos",
          "desktop"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "Compact, soft shadows, frosted menus. Sets radius, density, text scale, control and menu sizes, focus ring, shadows and motion as CSS variables that Tailwind's shadow and text scales and every Ballmac component follow, without touching colours.",
          "whenToUse": [
            "Tauri or Electron apps for Mac",
            "Productivity and developer tools that should sit next to native Mac apps"
          ],
          "whenNotToUse": [
            "The project needs its own sizing system or does not use Tailwind",
            "A native app UI is required; these are web components that feel like the platform, not native controls"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --radius, --spacing and the --bm-* variables by hand, or tune them at https://ui.ballmac.com/themes",
            "Set data-feel on a container to scope a feel to part of the page"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-macos"
      }
    },
    {
      "name": "feel-web",
      "type": "registry:theme",
      "title": "Web feel",
      "description": "Ballmac UI's own feel and the default: shadcn proportions, a soft focus halo and Tailwind's shadows. Nothing changes until you pick another feel.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.625rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Changes how everything handles (shape, size, focus, shadows, motion) and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?fe=web",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "theme",
          "tokens",
          "platform",
          "web",
          "desktop"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "Neutral, as it is today. Sets radius, density, text scale, control and menu sizes, focus ring, shadows and motion as CSS variables that Tailwind's shadow and text scales and every Ballmac component follow, without touching colours.",
          "whenToUse": [
            "Going back to Ballmac UI's own default feel",
            "Resetting after trying another feel"
          ],
          "whenNotToUse": [
            "The project needs its own sizing system or does not use Tailwind",
            "A native app UI is required; these are web components that feel like the platform, not native controls"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --radius, --spacing and the --bm-* variables by hand, or tune them at https://ui.ballmac.com/themes",
            "Set data-feel on a container to scope a feel to part of the page"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-web"
      }
    },
    {
      "name": "feel-windows",
      "type": "registry:theme",
      "title": "Windows feel",
      "description": "4 px corners, 32 px controls, Fluent-style layered shadows, a 2 px solid focus outline and a fast, no-bounce motion. For desktop apps that should sit comfortably next to native Windows apps.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.25rem",
          "bm-speed": "1.3",
          "bm-bounce": "0",
          "bm-travel": "0.6",
          "bm-hover": "0.5",
          "bm-stagger": "0.5",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "6px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0 2px rgb(0 0 0 / 0.12), 0 1px 2px rgb(0 0 0 / 0.14)",
          "bm-shadow-sm": "0 0 2px rgb(0 0 0 / 0.12), 0 2px 4px rgb(0 0 0 / 0.14)",
          "bm-shadow-md": "0 0 2px rgb(0 0 0 / 0.12), 0 4px 8px rgb(0 0 0 / 0.14)",
          "bm-shadow-lg": "0 0 2px rgb(0 0 0 / 0.12), 0 8px 16px rgb(0 0 0 / 0.14)",
          "bm-shadow-xl": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "bm-shadow-2xl": "0 0 8px rgb(0 0 0 / 0.12), 0 32px 64px rgb(0 0 0 / 0.14)",
          "bm-shadow-popover": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "1rem",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "1.25rem",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "1.375rem",
          "bm-focus-width": "2px",
          "bm-focus-alpha": "100%",
          "bm-focus-color": "var(--foreground)",
          "bm-control-h": "2rem",
          "bm-control-h-sm": "1.5rem",
          "bm-control-h-lg": "2.5rem",
          "bm-target-min": "0px",
          "bm-check-size": "1.25rem",
          "bm-switch-w": "2.5rem",
          "bm-switch-h": "1.25rem",
          "bm-press-dim": "1",
          "bm-material-blur": "30px",
          "bm-material-alpha": "85%",
          "bm-sidebar-item-h": "2.5rem",
          "bm-sidebar-item-radius": "0.25rem",
          "bm-sidebar-indicator": "3px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "0.25rem",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "thin",
          "bm-titlebar-h": "2rem",
          "bm-toolbar-h": "48px"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "Changes how everything handles (shape, size, focus, shadows, motion) and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?fe=windows",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "feel",
          "theme",
          "tokens",
          "platform",
          "windows",
          "desktop"
        ],
        "version": "1.0.0",
        "updated": "2026-10-12",
        "ai": {
          "summary": "Square-ish, bordered, crisp 2 px focus. Sets radius, density, text scale, control and menu sizes, focus ring, shadows and motion as CSS variables that Tailwind's shadow and text scales and every Ballmac component follow, without touching colours.",
          "whenToUse": [
            "Tauri or Electron apps for Windows",
            "Business and developer tools that should sit next to native Windows apps"
          ],
          "whenNotToUse": [
            "The project needs its own sizing system or does not use Tailwind",
            "A native app UI is required; these are web components that feel like the platform, not native controls"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --radius, --spacing and the --bm-* variables by hand, or tune them at https://ui.ballmac.com/themes",
            "Set data-feel on a container to scope a feel to part of the page"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/feel-windows"
      }
    },
    {
      "name": "font-bricolage",
      "type": "registry:font",
      "title": "Bricolage Grotesque",
      "description": "Bricolage Grotesque: Characterful and bold. Marketing, portfolios. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Bricolage Grotesque Variable', sans-serif",
        "provider": "google",
        "import": "Bricolage Grotesque",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/bricolage-grotesque"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "bricolage",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Bricolage Grotesque as the interface font. Characterful and bold. Marketing, portfolios.",
          "whenToUse": [
            "Characterful and bold. Marketing, portfolios.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-bricolage"
      }
    },
    {
      "name": "font-dm-sans",
      "type": "registry:font",
      "title": "DM Sans",
      "description": "DM Sans: Low contrast, geometric, friendly. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'DM Sans Variable', sans-serif",
        "provider": "google",
        "import": "DM Sans",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/dm-sans"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "dm-sans",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "DM Sans as the interface font. Low contrast, geometric, friendly.",
          "whenToUse": [
            "Low contrast, geometric, friendly.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-dm-sans"
      }
    },
    {
      "name": "font-figtree",
      "type": "registry:font",
      "title": "Figtree",
      "description": "Figtree: Friendly and open. Health, education, community. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Figtree Variable', sans-serif",
        "provider": "google",
        "import": "Figtree",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/figtree"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "figtree",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Figtree as the interface font. Friendly and open. Health, education, community.",
          "whenToUse": [
            "Friendly and open. Health, education, community.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-figtree"
      }
    },
    {
      "name": "font-fraunces",
      "type": "registry:font",
      "title": "Fraunces",
      "description": "Fraunces: A soft, expressive serif. Editorial, food, lifestyle. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Fraunces Variable', serif",
        "provider": "google",
        "import": "Fraunces",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/fraunces"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "fraunces",
          "serif"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Fraunces as the interface font. A soft, expressive serif. Editorial, food, lifestyle.",
          "whenToUse": [
            "A soft, expressive serif. Editorial, food, lifestyle.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-fraunces"
      }
    },
    {
      "name": "font-geist-mono",
      "type": "registry:font",
      "title": "Geist Mono",
      "description": "Geist Mono: Clean monospace to pair with Geist. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Geist Mono Variable', monospace",
        "provider": "google",
        "import": "Geist Mono",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/geist-mono"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "geist-mono",
          "mono"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Geist Mono as the interface font. Clean monospace to pair with Geist.",
          "whenToUse": [
            "Clean monospace to pair with Geist.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-geist-mono"
      }
    },
    {
      "name": "font-geist",
      "type": "registry:font",
      "title": "Geist",
      "description": "Geist: Crisp and technical. Developer tools, dashboards. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Geist Variable', sans-serif",
        "provider": "google",
        "import": "Geist",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/geist"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "geist",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Geist as the interface font. Crisp and technical. Developer tools, dashboards.",
          "whenToUse": [
            "Crisp and technical. Developer tools, dashboards.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-geist"
      }
    },
    {
      "name": "font-instrument-sans",
      "type": "registry:font",
      "title": "Instrument Sans",
      "description": "Instrument Sans: Slightly condensed, editorial. Studios and brands. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Instrument Sans Variable', sans-serif",
        "provider": "google",
        "import": "Instrument Sans",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/instrument-sans"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "instrument-sans",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Instrument Sans as the interface font. Slightly condensed, editorial. Studios and brands.",
          "whenToUse": [
            "Slightly condensed, editorial. Studios and brands.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-instrument-sans"
      }
    },
    {
      "name": "font-inter",
      "type": "registry:font",
      "title": "Inter",
      "description": "Inter: Neutral, built for screens. The safe default. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Inter Variable', sans-serif",
        "provider": "google",
        "import": "Inter",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/inter"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "inter",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Inter as the interface font. Neutral, built for screens. The safe default.",
          "whenToUse": [
            "Neutral, built for screens. The safe default.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-inter"
      }
    },
    {
      "name": "font-jakarta",
      "type": "registry:font",
      "title": "Plus Jakarta Sans",
      "description": "Plus Jakarta Sans: Warm geometric forms. Consumer apps. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Plus Jakarta Sans Variable', sans-serif",
        "provider": "google",
        "import": "Plus Jakarta Sans",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/plus-jakarta-sans"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "jakarta",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Plus Jakarta Sans as the interface font. Warm geometric forms. Consumer apps.",
          "whenToUse": [
            "Warm geometric forms. Consumer apps.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-jakarta"
      }
    },
    {
      "name": "font-jetbrains-mono",
      "type": "registry:font",
      "title": "JetBrains Mono",
      "description": "JetBrains Mono: Made for code. Terminals, developer products. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'JetBrains Mono Variable', monospace",
        "provider": "google",
        "import": "JetBrains Mono",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/jetbrains-mono"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "jetbrains-mono",
          "mono"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "JetBrains Mono as the interface font. Made for code. Terminals, developer products.",
          "whenToUse": [
            "Made for code. Terminals, developer products.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-jetbrains-mono"
      }
    },
    {
      "name": "font-manrope",
      "type": "registry:font",
      "title": "Manrope",
      "description": "Manrope: Modern and a little wide. Fintech, SaaS. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Manrope Variable', sans-serif",
        "provider": "google",
        "import": "Manrope",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/manrope"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "manrope",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Manrope as the interface font. Modern and a little wide. Fintech, SaaS.",
          "whenToUse": [
            "Modern and a little wide. Fintech, SaaS.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-manrope"
      }
    },
    {
      "name": "font-newsreader",
      "type": "registry:font",
      "title": "Newsreader",
      "description": "Newsreader: A reading serif. Publications, docs, long text. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Newsreader Variable', serif",
        "provider": "google",
        "import": "Newsreader",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/newsreader"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "newsreader",
          "serif"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Newsreader as the interface font. A reading serif. Publications, docs, long text.",
          "whenToUse": [
            "A reading serif. Publications, docs, long text.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-newsreader"
      }
    },
    {
      "name": "font-source-serif",
      "type": "registry:font",
      "title": "Source Serif 4",
      "description": "Source Serif 4: Sturdy and neutral. Finance, legal, research. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Source Serif 4 Variable', serif",
        "provider": "google",
        "import": "Source Serif 4",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/source-serif-4"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "source-serif",
          "serif"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Source Serif 4 as the interface font. Sturdy and neutral. Finance, legal, research.",
          "whenToUse": [
            "Sturdy and neutral. Finance, legal, research.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-source-serif"
      }
    },
    {
      "name": "font-space-grotesk",
      "type": "registry:font",
      "title": "Space Grotesk",
      "description": "Space Grotesk: Quirky, technical. Crypto, hardware, creative tools. Installed from Fontsource, so the font files are served from your own app.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "font": {
        "family": "'Space Grotesk Variable', sans-serif",
        "provider": "google",
        "import": "Space Grotesk",
        "variable": "--font-sans",
        "subsets": [
          "latin"
        ],
        "dependency": "@fontsource-variable/space-grotesk"
      },
      "docs": "Sets --font-sans. Open https://ui.ballmac.com/themes to preview it on real components, or pick it inside a preset.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "font",
          "typography",
          "space-grotesk",
          "sans"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Space Grotesk as the interface font. Quirky, technical. Crypto, hardware, creative tools.",
          "whenToUse": [
            "Quirky, technical. Crypto, hardware, creative tools.",
            "A preset or theme that names this font"
          ],
          "whenNotToUse": [
            "The project already has a brand typeface you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --font-sans in your global CSS to use another family"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/font-space-grotesk"
      }
    },
    {
      "name": "motion-calm",
      "type": "registry:theme",
      "title": "Calm motion",
      "description": "Longer, softer transitions with no bounce and short travel. Suits products people use for a long time, like editors, health and finance.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))"
        },
        "light": {
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Changes how everything moves and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?mo=calm#motion",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "theme",
          "tokens",
          "animation",
          "calm"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "ai": {
          "summary": "Slower, no overshoot, small moves. Sets speed, bounce, travel, hover lift and stagger as CSS variables that Tailwind's duration and easing scales and every Ballmac component follow, with a reduced-motion fallback.",
          "whenToUse": [
            "Editors, health, finance and reading apps",
            "Products people use for hours"
          ],
          "whenNotToUse": [
            "The project needs its own timing system and does not use Tailwind's duration and ease utilities"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger by hand, or tune them at https://ui.ballmac.com/themes#motion"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-calm"
      }
    },
    {
      "name": "motion-native",
      "type": "registry:theme",
      "title": "Native motion",
      "description": "The Ballmac default: short fades, a soft settle on spatial moves and a light lift on hover. Reads as the platform, not as an effect.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))"
        },
        "light": {
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Changes how everything moves and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?mo=native#motion",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "theme",
          "tokens",
          "animation",
          "native"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "ai": {
          "summary": "Quick, quiet, a hint of spring. Sets speed, bounce, travel, hover lift and stagger as CSS variables that Tailwind's duration and easing scales and every Ballmac component follow, with a reduced-motion fallback.",
          "whenToUse": [
            "The default feel for most products",
            "Pairing with any colour theme without changing how it moves"
          ],
          "whenNotToUse": [
            "The project needs its own timing system and does not use Tailwind's duration and ease utilities"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger by hand, or tune them at https://ui.ballmac.com/themes#motion"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-native"
      }
    },
    {
      "name": "motion-playful",
      "type": "registry:theme",
      "title": "Playful motion",
      "description": "Clear overshoot, longer travel and a pronounced hover lift. Suits consumer apps, creative tools and marketing pages.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))"
        },
        "light": {
          "bm-speed": "1.1",
          "bm-bounce": "0.8",
          "bm-travel": "1.4",
          "bm-hover": "1.5",
          "bm-stagger": "1.2",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0819, 0.2862, 0.5499, 0.8166, 1.044, 1.2065, 1.2953, 1.3154, 1.2812, 1.2117, 1.127, 1.044, 0.9753, 0.928, 0.9039, 0.9011, 0.9143, 0.9376, 0.9647, 0.9904, 1.011, 1.0247, 1.031, 1.0309, 1.026, 1.0182, 1.0096, 1.0017, 0.9956, 0.9917, 0.9901, 0.9904, 0.9922, 0.9947, 0.9974, 0.9998, 1.0017, 1.0028, 1.0032, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "14px",
          "bm-lift": "-3px",
          "bm-press": "0.955",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Changes how everything moves and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?mo=playful#motion",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "theme",
          "tokens",
          "animation",
          "playful"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "ai": {
          "summary": "Bouncy, bigger moves, eager hover. Sets speed, bounce, travel, hover lift and stagger as CSS variables that Tailwind's duration and easing scales and every Ballmac component follow, with a reduced-motion fallback.",
          "whenToUse": [
            "Consumer apps, creative tools and marketing pages",
            "Brands that want personality in every interaction"
          ],
          "whenNotToUse": [
            "The project needs its own timing system and does not use Tailwind's duration and ease utilities"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger by hand, or tune them at https://ui.ballmac.com/themes#motion"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-playful"
      }
    },
    {
      "name": "motion-snappy",
      "type": "registry:theme",
      "title": "Snappy motion",
      "description": "Short durations, tight stagger and very little bounce. Suits dense tools and dashboards where speed is the feature.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))"
        },
        "light": {
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Changes how everything moves and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?mo=snappy#motion",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "theme",
          "tokens",
          "animation",
          "snappy"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "ai": {
          "summary": "Fast, tight, almost instant. Sets speed, bounce, travel, hover lift and stagger as CSS variables that Tailwind's duration and easing scales and every Ballmac component follow, with a reduced-motion fallback.",
          "whenToUse": [
            "Dashboards, admin tools and developer products",
            "Anywhere speed is the feature"
          ],
          "whenNotToUse": [
            "The project needs its own timing system and does not use Tailwind's duration and ease utilities"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger by hand, or tune them at https://ui.ballmac.com/themes#motion"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-snappy"
      }
    },
    {
      "name": "motion-still",
      "type": "registry:theme",
      "title": "Still motion",
      "description": "Ships the reduced-motion values to every visitor: no travel, no lift, no loops, no bounce. Opacity changes stay so state remains visible.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))"
        },
        "light": {
          "bm-speed": "2",
          "bm-bounce": "0",
          "bm-travel": "0",
          "bm-hover": "0",
          "bm-stagger": "0.4",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "0px",
          "bm-lift": "0px",
          "bm-press": "1",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))"
        }
      },
      "docs": "Changes how everything moves and leaves your colours alone. Tune it, preview it on real components and copy the CSS at https://ui.ballmac.com/themes?mo=still#motion",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "motion",
          "theme",
          "tokens",
          "animation",
          "still"
        ],
        "version": "1.0.0",
        "updated": "2026-10-11",
        "ai": {
          "summary": "Fades only, for everyone. Sets speed, bounce, travel, hover lift and stagger as CSS variables that Tailwind's duration and easing scales and every Ballmac component follow, with a reduced-motion fallback.",
          "whenToUse": [
            "Products that must hold perfectly still for everyone",
            "Kiosks, trading screens and high-focus tools"
          ],
          "whenNotToUse": [
            "The project needs its own timing system and does not use Tailwind's duration and ease utilities"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger by hand, or tune them at https://ui.ballmac.com/themes#motion"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/motion-still"
      }
    },
    {
      "name": "preset-atelier",
      "type": "registry:theme",
      "title": "Atelier preset",
      "description": "Warm paper tones with ink buttons, golden accents and Bricolage Grotesque for headlines that have character.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-bricolage.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Bricolage Grotesque Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(0.978 0.012 80)",
          "foreground": "oklch(0.17 0.016 80)",
          "card": "oklch(0.994 0.006 80)",
          "card-foreground": "oklch(0.17 0.016 80)",
          "popover": "oklch(0.994 0.006 80)",
          "popover-foreground": "oklch(0.17 0.016 80)",
          "primary": "oklch(0.2 0.024 80)",
          "primary-foreground": "oklch(0.985 0.004 80)",
          "secondary": "oklch(0.965 0.008 80)",
          "secondary-foreground": "oklch(0.2 0.024 80)",
          "muted": "oklch(0.965 0.008 80)",
          "muted-foreground": "oklch(0.5 0.016 80)",
          "accent": "oklch(0.955 0.011 80)",
          "accent-foreground": "oklch(0.2 0.024 80)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 80)",
          "input": "oklch(0.915 0.008 80)",
          "ring": "oklch(0.62 0.129 80)",
          "chart-1": "oklch(0.6 0.125 80)",
          "chart-2": "oklch(0.644 0.129 230)",
          "chart-3": "oklch(0.636 0.136 155)",
          "chart-4": "oklch(0.58 0.136 10)",
          "chart-5": "oklch(0.64 0.136 295)",
          "radius": "0.375rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 80)",
          "foreground": "oklch(0.97 0.006 80)",
          "card": "oklch(0.2 0.033 80)",
          "card-foreground": "oklch(0.97 0.006 80)",
          "popover": "oklch(0.2 0.033 80)",
          "popover-foreground": "oklch(0.97 0.006 80)",
          "primary": "oklch(0.97 0.006 80)",
          "primary-foreground": "oklch(0.2 0.033 80)",
          "secondary": "oklch(0.25 0.037 80)",
          "secondary-foreground": "oklch(0.97 0.006 80)",
          "muted": "oklch(0.25 0.037 80)",
          "muted-foreground": "oklch(0.72 0.026 80)",
          "accent": "oklch(0.28 0.043 80)",
          "accent-foreground": "oklch(0.97 0.006 80)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.137 80)",
          "chart-1": "oklch(0.7 0.128 80)",
          "chart-2": "oklch(0.76 0.128 230)",
          "chart-3": "oklch(0.8 0.128 155)",
          "chart-4": "oklch(0.68 0.128 10)",
          "chart-5": "oklch(0.74 0.128 295)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 0qb8-mcj9-sv3r-9byw; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "atelier"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Paper, gold and bold type. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Studios, portfolios and publications",
            "Brands that want warmth without a coloured button"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-atelier"
      }
    },
    {
      "name": "preset-bloom",
      "type": "registry:theme",
      "title": "Bloom preset",
      "description": "Saturated violet, pill-like corners and Plus Jakarta Sans, with springy motion that makes controls feel alive.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-jakarta.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Plus Jakarta Sans Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.02 305)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.02 305)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.02 305)",
          "primary": "oklch(0.56 0.22 305)",
          "primary-foreground": "oklch(0.985 0.005 305)",
          "secondary": "oklch(0.965 0.01 305)",
          "secondary-foreground": "oklch(0.2 0.03 305)",
          "muted": "oklch(0.965 0.01 305)",
          "muted-foreground": "oklch(0.5 0.02 305)",
          "accent": "oklch(0.955 0.015 305)",
          "accent-foreground": "oklch(0.2 0.03 305)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.01 305)",
          "input": "oklch(0.915 0.01 305)",
          "ring": "oklch(0.62 0.22 305)",
          "chart-1": "oklch(0.6 0.187 305)",
          "chart-2": "oklch(0.66 0.136 95)",
          "chart-3": "oklch(0.692 0.187 20)",
          "chart-4": "oklch(0.58 0.123 235)",
          "chart-5": "oklch(0.64 0.145 160)",
          "radius": "1rem",
          "bm-speed": "1.1",
          "bm-bounce": "0.8",
          "bm-travel": "1.4",
          "bm-hover": "1.5",
          "bm-stagger": "1.2",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0819, 0.2862, 0.5499, 0.8166, 1.044, 1.2065, 1.2953, 1.3154, 1.2812, 1.2117, 1.127, 1.044, 0.9753, 0.928, 0.9039, 0.9011, 0.9143, 0.9376, 0.9647, 0.9904, 1.011, 1.0247, 1.031, 1.0309, 1.026, 1.0182, 1.0096, 1.0017, 0.9956, 0.9917, 0.9901, 0.9904, 0.9922, 0.9947, 0.9974, 0.9998, 1.0017, 1.0028, 1.0032, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "14px",
          "bm-lift": "-3px",
          "bm-press": "0.955",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.033 305)",
          "foreground": "oklch(0.97 0.007 305)",
          "card": "oklch(0.2 0.041 305)",
          "card-foreground": "oklch(0.97 0.007 305)",
          "popover": "oklch(0.2 0.041 305)",
          "popover-foreground": "oklch(0.97 0.007 305)",
          "primary": "oklch(0.74 0.169 305)",
          "primary-foreground": "oklch(0.16 0.03 305)",
          "secondary": "oklch(0.25 0.046 305)",
          "secondary-foreground": "oklch(0.97 0.007 305)",
          "muted": "oklch(0.25 0.046 305)",
          "muted-foreground": "oklch(0.72 0.033 305)",
          "accent": "oklch(0.28 0.059 305)",
          "accent-foreground": "oklch(0.97 0.007 305)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.22 305)",
          "chart-1": "oklch(0.7 0.176 305)",
          "chart-2": "oklch(0.76 0.156 95)",
          "chart-3": "oklch(0.8 0.115 20)",
          "chart-4": "oklch(0.68 0.145 235)",
          "chart-5": "oklch(0.74 0.168 160)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2rka-apvx-r7ep-sa7v; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "bloom"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Rich purple, very round, playful. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Creative tools and communities",
            "Consumer apps"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-bloom"
      }
    },
    {
      "name": "preset-canopy",
      "type": "registry:theme",
      "title": "Canopy preset",
      "description": "A deep forest green with Figtree's open shapes and slow, steady motion.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-figtree.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Figtree Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 152)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 152)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 152)",
          "primary": "oklch(0.54 0.14 152)",
          "primary-foreground": "oklch(0.985 0.004 152)",
          "secondary": "oklch(0.965 0.008 152)",
          "secondary-foreground": "oklch(0.2 0.024 152)",
          "muted": "oklch(0.965 0.008 152)",
          "muted-foreground": "oklch(0.5 0.016 152)",
          "accent": "oklch(0.955 0.01 152)",
          "accent-foreground": "oklch(0.2 0.024 152)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 152)",
          "input": "oklch(0.915 0.008 152)",
          "ring": "oklch(0.62 0.14 152)",
          "chart-1": "oklch(0.6 0.119 152)",
          "chart-2": "oklch(0.66 0.119 302)",
          "chart-3": "oklch(0.66 0.119 227)",
          "chart-4": "oklch(0.58 0.119 82)",
          "chart-5": "oklch(0.64 0.119 7)",
          "radius": "0.5rem",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 152)",
          "foreground": "oklch(0.97 0.006 152)",
          "card": "oklch(0.2 0.033 152)",
          "card-foreground": "oklch(0.97 0.006 152)",
          "popover": "oklch(0.2 0.033 152)",
          "popover-foreground": "oklch(0.97 0.006 152)",
          "primary": "oklch(0.74 0.14 152)",
          "primary-foreground": "oklch(0.16 0.03 152)",
          "secondary": "oklch(0.25 0.037 152)",
          "secondary-foreground": "oklch(0.97 0.006 152)",
          "muted": "oklch(0.25 0.037 152)",
          "muted-foreground": "oklch(0.72 0.026 152)",
          "accent": "oklch(0.28 0.038 152)",
          "accent-foreground": "oklch(0.97 0.006 152)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.14 152)",
          "chart-1": "oklch(0.7 0.112 152)",
          "chart-2": "oklch(0.76 0.112 302)",
          "chart-3": "oklch(0.8 0.112 227)",
          "chart-4": "oklch(0.68 0.112 82)",
          "chart-5": "oklch(0.74 0.112 7)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 1c62-dbvb-hffx-tvnt; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "canopy"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Deep green, friendly and grounded. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Sustainability, finance and wellness",
            "Products meant to feel calm and established"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-canopy"
      }
    },
    {
      "name": "preset-forge",
      "type": "registry:theme",
      "title": "Forge preset",
      "description": "Crisp orange on warm greys, Space Grotesk's quirky edges and a lively pace. Energetic but still readable.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-space-grotesk.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Space Grotesk Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 60)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 60)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 60)",
          "primary": "oklch(0.56 0.161 45)",
          "primary-foreground": "oklch(0.985 0.004 60)",
          "secondary": "oklch(0.965 0.008 60)",
          "secondary-foreground": "oklch(0.2 0.024 60)",
          "muted": "oklch(0.965 0.008 60)",
          "muted-foreground": "oklch(0.5 0.016 60)",
          "accent": "oklch(0.955 0.012 45)",
          "accent-foreground": "oklch(0.2 0.024 60)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 60)",
          "input": "oklch(0.915 0.008 60)",
          "ring": "oklch(0.62 0.17 45)",
          "chart-1": "oklch(0.6 0.145 45)",
          "chart-2": "oklch(0.656 0.112 195)",
          "chart-3": "oklch(0.66 0.145 120)",
          "chart-4": "oklch(0.58 0.145 335)",
          "chart-5": "oklch(0.64 0.145 260)",
          "radius": "0.5rem",
          "bm-speed": "1.1",
          "bm-bounce": "0.8",
          "bm-travel": "1.4",
          "bm-hover": "1.5",
          "bm-stagger": "1.2",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0819, 0.2862, 0.5499, 0.8166, 1.044, 1.2065, 1.2953, 1.3154, 1.2812, 1.2117, 1.127, 1.044, 0.9753, 0.928, 0.9039, 0.9011, 0.9143, 0.9376, 0.9647, 0.9904, 1.011, 1.0247, 1.031, 1.0309, 1.026, 1.0182, 1.0096, 1.0017, 0.9956, 0.9917, 0.9901, 0.9904, 0.9922, 0.9947, 0.9974, 0.9998, 1.0017, 1.0028, 1.0032, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "14px",
          "bm-lift": "-3px",
          "bm-press": "0.955",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 60)",
          "foreground": "oklch(0.97 0.006 60)",
          "card": "oklch(0.2 0.033 60)",
          "card-foreground": "oklch(0.97 0.006 60)",
          "popover": "oklch(0.2 0.033 60)",
          "popover-foreground": "oklch(0.97 0.006 60)",
          "primary": "oklch(0.74 0.168 45)",
          "primary-foreground": "oklch(0.16 0.03 45)",
          "secondary": "oklch(0.25 0.037 60)",
          "secondary-foreground": "oklch(0.97 0.006 60)",
          "muted": "oklch(0.25 0.037 60)",
          "muted-foreground": "oklch(0.72 0.026 60)",
          "accent": "oklch(0.28 0.046 45)",
          "accent-foreground": "oklch(0.97 0.006 60)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.17 45)",
          "chart-1": "oklch(0.7 0.136 45)",
          "chart-2": "oklch(0.76 0.13 195)",
          "chart-3": "oklch(0.8 0.136 120)",
          "chart-4": "oklch(0.68 0.136 335)",
          "chart-5": "oklch(0.74 0.134 260)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 0d74-mrwe-5p3p-8wh9; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "forge"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Burnt orange, technical letters. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Developer platforms and media",
            "Calls to action that must stand out"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-forge"
      }
    },
    {
      "name": "preset-harbor",
      "type": "registry:theme",
      "title": "Harbor preset",
      "description": "A confident ocean blue with Manrope's wide, modern letters and soft corners. Looks established without looking stiff.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-manrope.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Manrope Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 248)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 248)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 248)",
          "primary": "oklch(0.556 0.15 248)",
          "primary-foreground": "oklch(0.985 0.004 248)",
          "secondary": "oklch(0.965 0.008 248)",
          "secondary-foreground": "oklch(0.2 0.024 248)",
          "muted": "oklch(0.965 0.008 248)",
          "muted-foreground": "oklch(0.5 0.016 248)",
          "accent": "oklch(0.955 0.012 248)",
          "accent-foreground": "oklch(0.2 0.024 248)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 248)",
          "input": "oklch(0.915 0.008 248)",
          "ring": "oklch(0.62 0.167 248)",
          "chart-1": "oklch(0.6 0.145 248)",
          "chart-2": "oklch(0.66 0.145 38)",
          "chart-3": "oklch(0.684 0.145 323)",
          "chart-4": "oklch(0.58 0.107 178)",
          "chart-5": "oklch(0.64 0.135 103)",
          "radius": "0.625rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 248)",
          "foreground": "oklch(0.97 0.006 248)",
          "card": "oklch(0.2 0.033 248)",
          "card-foreground": "oklch(0.97 0.006 248)",
          "popover": "oklch(0.2 0.033 248)",
          "popover-foreground": "oklch(0.97 0.006 248)",
          "primary": "oklch(0.74 0.141 248)",
          "primary-foreground": "oklch(0.16 0.03 248)",
          "secondary": "oklch(0.25 0.037 248)",
          "secondary-foreground": "oklch(0.97 0.006 248)",
          "muted": "oklch(0.25 0.037 248)",
          "muted-foreground": "oklch(0.72 0.026 248)",
          "accent": "oklch(0.28 0.046 248)",
          "accent-foreground": "oklch(0.97 0.006 248)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.17 248)",
          "chart-1": "oklch(0.7 0.136 248)",
          "chart-2": "oklch(0.76 0.136 38)",
          "chart-3": "oklch(0.8 0.136 323)",
          "chart-4": "oklch(0.68 0.125 178)",
          "chart-5": "oklch(0.74 0.136 103)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2814-78n7-rge5-7z4b; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "harbor"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Trustworthy blue, open type. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Fintech and SaaS",
            "Anything that has to feel trustworthy"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-harbor"
      }
    },
    {
      "name": "preset-ink",
      "type": "registry:theme",
      "title": "Ink preset",
      "description": "Graphite greys with near-black buttons, Geist for text and a quick, precise way of moving. Content leads and the interface stays out of the way.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-geist.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Geist Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.008 255)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.008 255)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.008 255)",
          "primary": "oklch(0.2 0.012 255)",
          "primary-foreground": "oklch(0.985 0.002 255)",
          "secondary": "oklch(0.965 0.004 255)",
          "secondary-foreground": "oklch(0.2 0.012 255)",
          "muted": "oklch(0.965 0.004 255)",
          "muted-foreground": "oklch(0.5 0.008 255)",
          "accent": "oklch(0.955 0.008 255)",
          "accent-foreground": "oklch(0.2 0.012 255)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.004 255)",
          "input": "oklch(0.915 0.004 255)",
          "ring": "oklch(0.62 0.12 255)",
          "chart-1": "oklch(0.6 0.102 255)",
          "chart-2": "oklch(0.66 0.102 45)",
          "chart-3": "oklch(0.68 0.102 330)",
          "chart-4": "oklch(0.58 0.102 185)",
          "chart-5": "oklch(0.64 0.102 110)",
          "radius": "0.5rem",
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.013 255)",
          "foreground": "oklch(0.97 0.003 255)",
          "card": "oklch(0.2 0.017 255)",
          "card-foreground": "oklch(0.97 0.003 255)",
          "popover": "oklch(0.2 0.017 255)",
          "popover-foreground": "oklch(0.97 0.003 255)",
          "primary": "oklch(0.97 0.003 255)",
          "primary-foreground": "oklch(0.2 0.017 255)",
          "secondary": "oklch(0.25 0.018 255)",
          "secondary-foreground": "oklch(0.97 0.003 255)",
          "muted": "oklch(0.25 0.018 255)",
          "muted-foreground": "oklch(0.72 0.013 255)",
          "accent": "oklch(0.28 0.032 255)",
          "accent-foreground": "oklch(0.97 0.003 255)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.12 255)",
          "chart-1": "oklch(0.7 0.096 255)",
          "chart-2": "oklch(0.76 0.096 45)",
          "chart-3": "oklch(0.8 0.096 330)",
          "chart-4": "oklch(0.68 0.096 185)",
          "chart-5": "oklch(0.74 0.096 110)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2a08-xyd3-dr43-nwcz; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "ink"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Quiet greys, sharp type. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Dashboards and admin tools",
            "Products that should look neutral and fast"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-ink"
      }
    },
    {
      "name": "preset-lagoon",
      "type": "registry:theme",
      "title": "Lagoon preset",
      "description": "Blue-green with DM Sans and rounded corners. Friendly enough for health apps, clear enough for data.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-dm-sans.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'DM Sans Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 200)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 200)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 200)",
          "primary": "oklch(0.544 0.094 192)",
          "primary-foreground": "oklch(0.985 0.004 200)",
          "secondary": "oklch(0.965 0.008 200)",
          "secondary-foreground": "oklch(0.2 0.024 200)",
          "muted": "oklch(0.965 0.008 200)",
          "muted-foreground": "oklch(0.5 0.016 200)",
          "accent": "oklch(0.955 0.008 192)",
          "accent-foreground": "oklch(0.2 0.024 200)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 200)",
          "input": "oklch(0.915 0.008 200)",
          "ring": "oklch(0.62 0.107 192)",
          "chart-1": "oklch(0.6 0.102 192)",
          "chart-2": "oklch(0.66 0.102 342)",
          "chart-3": "oklch(0.672 0.102 267)",
          "chart-4": "oklch(0.58 0.102 122)",
          "chart-5": "oklch(0.64 0.102 47)",
          "radius": "0.875rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 200)",
          "foreground": "oklch(0.97 0.006 200)",
          "card": "oklch(0.2 0.033 200)",
          "card-foreground": "oklch(0.97 0.006 200)",
          "popover": "oklch(0.2 0.033 200)",
          "popover-foreground": "oklch(0.97 0.006 200)",
          "primary": "oklch(0.74 0.12 192)",
          "primary-foreground": "oklch(0.16 0.03 192)",
          "secondary": "oklch(0.25 0.037 200)",
          "secondary-foreground": "oklch(0.97 0.006 200)",
          "muted": "oklch(0.25 0.037 200)",
          "muted-foreground": "oklch(0.72 0.026 200)",
          "accent": "oklch(0.28 0.032 192)",
          "accent-foreground": "oklch(0.97 0.006 200)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.114 192)",
          "chart-1": "oklch(0.7 0.096 192)",
          "chart-2": "oklch(0.76 0.096 342)",
          "chart-3": "oklch(0.8 0.096 267)",
          "chart-4": "oklch(0.68 0.096 122)",
          "chart-5": "oklch(0.74 0.096 47)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 1qr6-x84c-jyxh-vjbq; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "lagoon"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Fresh teal, round and clear. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Health, data and productivity apps",
            "Dashboards with a friendly tone"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-lagoon"
      }
    },
    {
      "name": "preset-lumen",
      "type": "registry:theme",
      "title": "Lumen preset",
      "description": "Indigo accents with Instrument Sans, generous corners and an easy pace. Modern and a little distinct.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-instrument-sans.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Instrument Sans Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 277)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 277)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 277)",
          "primary": "oklch(0.56 0.2 277)",
          "primary-foreground": "oklch(0.985 0.004 277)",
          "secondary": "oklch(0.965 0.008 277)",
          "secondary-foreground": "oklch(0.2 0.024 277)",
          "muted": "oklch(0.965 0.008 277)",
          "muted-foreground": "oklch(0.5 0.016 277)",
          "accent": "oklch(0.955 0.014 277)",
          "accent-foreground": "oklch(0.2 0.024 277)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 277)",
          "input": "oklch(0.915 0.008 277)",
          "ring": "oklch(0.62 0.2 277)",
          "chart-1": "oklch(0.6 0.17 277)",
          "chart-2": "oklch(0.66 0.146 67)",
          "chart-3": "oklch(0.688 0.17 352)",
          "chart-4": "oklch(0.58 0.1 207)",
          "chart-5": "oklch(0.64 0.17 132)",
          "radius": "0.75rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 277)",
          "foreground": "oklch(0.97 0.006 277)",
          "card": "oklch(0.2 0.033 277)",
          "card-foreground": "oklch(0.97 0.006 277)",
          "popover": "oklch(0.2 0.033 277)",
          "popover-foreground": "oklch(0.97 0.006 277)",
          "primary": "oklch(0.74 0.135 277)",
          "primary-foreground": "oklch(0.16 0.03 277)",
          "secondary": "oklch(0.25 0.037 277)",
          "secondary-foreground": "oklch(0.97 0.006 277)",
          "muted": "oklch(0.25 0.037 277)",
          "muted-foreground": "oklch(0.72 0.026 277)",
          "accent": "oklch(0.28 0.054 277)",
          "accent-foreground": "oklch(0.97 0.006 277)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.183 277)",
          "chart-1": "oklch(0.7 0.159 277)",
          "chart-2": "oklch(0.76 0.16 67)",
          "chart-3": "oklch(0.8 0.134 352)",
          "chart-4": "oklch(0.68 0.117 207)",
          "chart-5": "oklch(0.74 0.16 132)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2gf1-6sax-5gj7-5xdq; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "lumen"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Deep indigo, editorial sans. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "AI products and developer tools",
            "Marketing sites that want a recognisable colour"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-lumen"
      }
    },
    {
      "name": "preset-menubar",
      "type": "registry:theme",
      "title": "Menubar preset",
      "description": "The macOS feel: compact controls, tighter corners, the system font, translucent materials and a precise focus ring. For apps that live next to Finder.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "spacing": "0.225rem",
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.008 255)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.008 255)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.008 255)",
          "primary": "oklch(0.2 0.012 255)",
          "primary-foreground": "oklch(0.985 0.002 255)",
          "secondary": "oklch(0.965 0.004 255)",
          "secondary-foreground": "oklch(0.2 0.012 255)",
          "muted": "oklch(0.965 0.004 255)",
          "muted-foreground": "oklch(0.5 0.008 255)",
          "accent": "oklch(0.955 0.008 255)",
          "accent-foreground": "oklch(0.2 0.012 255)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.004 255)",
          "input": "oklch(0.915 0.004 255)",
          "ring": "oklch(0.62 0.12 255)",
          "chart-1": "oklch(0.6 0.102 255)",
          "chart-2": "oklch(0.66 0.102 45)",
          "chart-3": "oklch(0.68 0.102 330)",
          "chart-4": "oklch(0.58 0.102 185)",
          "chart-5": "oklch(0.64 0.102 110)",
          "radius": "0.375rem",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0.5px 1px rgb(0 0 0 / 0.08), 0 0 0 0.5px rgb(0 0 0 / 0.04)",
          "bm-shadow-sm": "0 1px 3px rgb(0 0 0 / 0.12), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-md": "0 4px 12px -2px rgb(0 0 0 / 0.14), 0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-lg": "0 12px 32px -6px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "bm-shadow-xl": "0 20px 48px -8px rgb(0 0 0 / 0.26), 0 0 0 0.5px rgb(0 0 0 / 0.08)",
          "bm-shadow-2xl": "0 28px 64px -12px rgb(0 0 0 / 0.32), 0 0 0 0.5px rgb(0 0 0 / 0.1)",
          "bm-shadow-popover": "0 8px 30px rgb(0 0 0 / 0.22), 0 0 0 0.5px rgb(0 0 0 / 0.12)",
          "bm-text-xs": "0.6875rem",
          "bm-text-xs-lh": "0.875rem",
          "bm-text-sm": "0.8125rem",
          "bm-text-sm-lh": "1.125rem",
          "bm-text-base": "0.9375rem",
          "bm-text-base-lh": "1.375rem",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "1.75rem",
          "bm-control-h-sm": "1.5rem",
          "bm-control-h-lg": "2rem",
          "bm-target-min": "0px",
          "bm-check-size": "0.875rem",
          "bm-switch-w": "2.375rem",
          "bm-switch-h": "1.375rem",
          "bm-press-dim": "1",
          "bm-material-blur": "24px",
          "bm-material-alpha": "78%",
          "bm-sidebar-item-h": "1.75rem",
          "bm-sidebar-item-radius": "0.375rem",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "1.5rem",
          "bm-menu-item-radius": "0.3125rem",
          "bm-menu-pad": "0.3125rem",
          "bm-scrollbar-width": "thin",
          "bm-titlebar-h": "2.75rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.013 255)",
          "foreground": "oklch(0.97 0.003 255)",
          "card": "oklch(0.2 0.017 255)",
          "card-foreground": "oklch(0.97 0.003 255)",
          "popover": "oklch(0.2 0.017 255)",
          "popover-foreground": "oklch(0.97 0.003 255)",
          "primary": "oklch(0.97 0.003 255)",
          "primary-foreground": "oklch(0.2 0.017 255)",
          "secondary": "oklch(0.25 0.018 255)",
          "secondary-foreground": "oklch(0.97 0.003 255)",
          "muted": "oklch(0.25 0.018 255)",
          "muted-foreground": "oklch(0.72 0.013 255)",
          "accent": "oklch(0.28 0.032 255)",
          "accent-foreground": "oklch(0.97 0.003 255)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.12 255)",
          "chart-1": "oklch(0.7 0.096 255)",
          "chart-2": "oklch(0.76 0.096 45)",
          "chart-3": "oklch(0.8 0.096 330)",
          "chart-4": "oklch(0.68 0.096 185)",
          "chart-5": "oklch(0.74 0.096 110)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2a08-xybq-xekg-ss7c; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "menubar"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "A native Mac app. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Tauri and Electron apps on macOS",
            "Tools used all day on a desktop"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-menubar"
      }
    },
    {
      "name": "preset-pane",
      "type": "registry:theme",
      "title": "Pane preset",
      "description": "The Windows feel: small corners, a visible two-tone focus ring, quick fades and the system font, in a calm Fluent blue.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 248)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 248)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 248)",
          "primary": "oklch(0.556 0.15 248)",
          "primary-foreground": "oklch(0.985 0.004 248)",
          "secondary": "oklch(0.965 0.008 248)",
          "secondary-foreground": "oklch(0.2 0.024 248)",
          "muted": "oklch(0.965 0.008 248)",
          "muted-foreground": "oklch(0.5 0.016 248)",
          "accent": "oklch(0.955 0.012 248)",
          "accent-foreground": "oklch(0.2 0.024 248)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 248)",
          "input": "oklch(0.915 0.008 248)",
          "ring": "oklch(0.62 0.167 248)",
          "chart-1": "oklch(0.6 0.145 248)",
          "chart-2": "oklch(0.66 0.145 38)",
          "chart-3": "oklch(0.684 0.145 323)",
          "chart-4": "oklch(0.58 0.107 178)",
          "chart-5": "oklch(0.64 0.135 103)",
          "radius": "0.25rem",
          "bm-speed": "1.3",
          "bm-bounce": "0",
          "bm-travel": "0.6",
          "bm-hover": "0.5",
          "bm-stagger": "0.5",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "6px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0 2px rgb(0 0 0 / 0.12), 0 1px 2px rgb(0 0 0 / 0.14)",
          "bm-shadow-sm": "0 0 2px rgb(0 0 0 / 0.12), 0 2px 4px rgb(0 0 0 / 0.14)",
          "bm-shadow-md": "0 0 2px rgb(0 0 0 / 0.12), 0 4px 8px rgb(0 0 0 / 0.14)",
          "bm-shadow-lg": "0 0 2px rgb(0 0 0 / 0.12), 0 8px 16px rgb(0 0 0 / 0.14)",
          "bm-shadow-xl": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "bm-shadow-2xl": "0 0 8px rgb(0 0 0 / 0.12), 0 32px 64px rgb(0 0 0 / 0.14)",
          "bm-shadow-popover": "0 0 8px rgb(0 0 0 / 0.12), 0 14px 28px rgb(0 0 0 / 0.14)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "1rem",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "1.25rem",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "1.375rem",
          "bm-focus-width": "2px",
          "bm-focus-alpha": "100%",
          "bm-focus-color": "var(--foreground)",
          "bm-control-h": "2rem",
          "bm-control-h-sm": "1.5rem",
          "bm-control-h-lg": "2.5rem",
          "bm-target-min": "0px",
          "bm-check-size": "1.25rem",
          "bm-switch-w": "2.5rem",
          "bm-switch-h": "1.25rem",
          "bm-press-dim": "1",
          "bm-material-blur": "30px",
          "bm-material-alpha": "85%",
          "bm-sidebar-item-h": "2.5rem",
          "bm-sidebar-item-radius": "0.25rem",
          "bm-sidebar-indicator": "3px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "0.25rem",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "thin",
          "bm-titlebar-h": "2rem",
          "bm-toolbar-h": "48px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 248)",
          "foreground": "oklch(0.97 0.006 248)",
          "card": "oklch(0.2 0.033 248)",
          "card-foreground": "oklch(0.97 0.006 248)",
          "popover": "oklch(0.2 0.033 248)",
          "popover-foreground": "oklch(0.97 0.006 248)",
          "primary": "oklch(0.74 0.141 248)",
          "primary-foreground": "oklch(0.16 0.03 248)",
          "secondary": "oklch(0.25 0.037 248)",
          "secondary-foreground": "oklch(0.97 0.006 248)",
          "muted": "oklch(0.25 0.037 248)",
          "muted-foreground": "oklch(0.72 0.026 248)",
          "accent": "oklch(0.28 0.046 248)",
          "accent-foreground": "oklch(0.97 0.006 248)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.17 248)",
          "chart-1": "oklch(0.7 0.136 248)",
          "chart-2": "oklch(0.76 0.136 38)",
          "chart-3": "oklch(0.8 0.136 323)",
          "chart-4": "oklch(0.68 0.125 178)",
          "chart-5": "oklch(0.74 0.136 103)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 2814-78h6-cb96-2h3p; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "pane"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "A Windows app. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Tauri and Electron apps on Windows",
            "Enterprise and line-of-business tools"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-pane"
      }
    },
    {
      "name": "preset-paper",
      "type": "registry:theme",
      "title": "Paper preset",
      "description": "Off-white paper and terracotta with Newsreader, a serif made for reading, small precise corners and a calm pace. Reads like print.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-newsreader.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Newsreader Variable', serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(0.978 0.018 80)",
          "foreground": "oklch(0.17 0.024 80)",
          "card": "oklch(0.994 0.006 80)",
          "card-foreground": "oklch(0.17 0.024 80)",
          "popover": "oklch(0.994 0.006 80)",
          "popover-foreground": "oklch(0.17 0.024 80)",
          "primary": "oklch(0.56 0.13 40)",
          "primary-foreground": "oklch(0.985 0.006 80)",
          "secondary": "oklch(0.965 0.012 80)",
          "secondary-foreground": "oklch(0.2 0.03 80)",
          "muted": "oklch(0.965 0.012 80)",
          "muted-foreground": "oklch(0.5 0.024 80)",
          "accent": "oklch(0.955 0.009 40)",
          "accent-foreground": "oklch(0.2 0.03 80)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.012 80)",
          "input": "oklch(0.915 0.012 80)",
          "ring": "oklch(0.62 0.13 40)",
          "chart-1": "oklch(0.6 0.111 40)",
          "chart-2": "oklch(0.636 0.11 190)",
          "chart-3": "oklch(0.644 0.111 115)",
          "chart-4": "oklch(0.58 0.111 330)",
          "chart-5": "oklch(0.64 0.111 255)",
          "radius": "0.375rem",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.035 80)",
          "foreground": "oklch(0.97 0.008 80)",
          "card": "oklch(0.2 0.044 80)",
          "card-foreground": "oklch(0.97 0.008 80)",
          "popover": "oklch(0.2 0.044 80)",
          "popover-foreground": "oklch(0.97 0.008 80)",
          "primary": "oklch(0.74 0.13 40)",
          "primary-foreground": "oklch(0.16 0.03 40)",
          "secondary": "oklch(0.25 0.049 80)",
          "secondary-foreground": "oklch(0.97 0.008 80)",
          "muted": "oklch(0.25 0.049 80)",
          "muted-foreground": "oklch(0.72 0.04 80)",
          "accent": "oklch(0.28 0.035 40)",
          "accent-foreground": "oklch(0.97 0.008 80)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.13 40)",
          "chart-1": "oklch(0.7 0.104 40)",
          "chart-2": "oklch(0.76 0.104 190)",
          "chart-3": "oklch(0.8 0.104 115)",
          "chart-4": "oklch(0.68 0.104 330)",
          "chart-5": "oklch(0.74 0.104 255)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 0bqc-xazs-y8hn-rtg2; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "paper"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Printed page, reading serif. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Publications, docs and long reading",
            "Shops with a crafted feel"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-paper"
      }
    },
    {
      "name": "preset-pocket",
      "type": "registry:theme",
      "title": "Pocket preset",
      "description": "The iOS feel: large touch targets, big rounded corners, springy motion and the system font, in a warm rose.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "spacing": "0.275rem",
          "font-sans": "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 12)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 12)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 12)",
          "primary": "oklch(0.56 0.19 12)",
          "primary-foreground": "oklch(0.985 0.004 12)",
          "secondary": "oklch(0.965 0.008 12)",
          "secondary-foreground": "oklch(0.2 0.024 12)",
          "muted": "oklch(0.965 0.008 12)",
          "muted-foreground": "oklch(0.5 0.016 12)",
          "accent": "oklch(0.955 0.013 12)",
          "accent-foreground": "oklch(0.2 0.024 12)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 12)",
          "input": "oklch(0.915 0.008 12)",
          "ring": "oklch(0.62 0.19 12)",
          "chart-1": "oklch(0.6 0.162 12)",
          "chart-2": "oklch(0.652 0.143 162)",
          "chart-3": "oklch(0.668 0.137 87)",
          "chart-4": "oklch(0.58 0.162 302)",
          "chart-5": "oklch(0.64 0.124 227)",
          "radius": "0.75rem",
          "bm-speed": "1.1",
          "bm-bounce": "0.55",
          "bm-travel": "1.1",
          "bm-hover": "0",
          "bm-stagger": "1.1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.026, 0.0947, 0.1927, 0.3084, 0.4319, 0.5553, 0.6724, 0.7789, 0.8718, 0.9497, 1.0122, 1.0596, 1.0932, 1.1143, 1.1249, 1.1268, 1.1219, 1.1121, 1.0989, 1.0839, 1.0681, 1.0526, 1.038, 1.0249, 1.0136, 1.0042, 0.9967, 0.9912, 0.9873, 0.985, 0.984, 0.984, 0.9848, 0.9862, 0.9879, 0.9899, 0.9919, 0.9938, 0.9956, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "11px",
          "bm-lift": "0px",
          "bm-press": "1",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 0 0 0 rgb(0 0 0 / 0)",
          "bm-shadow-sm": "0 0 0 0.5px rgb(0 0 0 / 0.06)",
          "bm-shadow-md": "0 2px 10px rgb(0 0 0 / 0.08)",
          "bm-shadow-lg": "0 10px 40px rgb(0 0 0 / 0.18)",
          "bm-shadow-xl": "0 16px 56px rgb(0 0 0 / 0.22)",
          "bm-shadow-2xl": "0 24px 72px rgb(0 0 0 / 0.28)",
          "bm-shadow-popover": "0 10px 40px rgb(0 0 0 / 0.18)",
          "bm-text-xs": "0.8125rem",
          "bm-text-xs-lh": "1.125rem",
          "bm-text-sm": "0.9375rem",
          "bm-text-sm-lh": "1.375rem",
          "bm-text-base": "1.0625rem",
          "bm-text-base-lh": "1.5rem",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "40%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "2.75rem",
          "bm-control-h-sm": "2.25rem",
          "bm-control-h-lg": "3rem",
          "bm-target-min": "2.75rem",
          "bm-check-size": "1.375rem",
          "bm-switch-w": "3.1875rem",
          "bm-switch-h": "1.9375rem",
          "bm-press-dim": "0.6",
          "bm-material-blur": "30px",
          "bm-material-alpha": "80%",
          "bm-sidebar-item-h": "2.75rem",
          "bm-sidebar-item-radius": "0.625rem",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2.75rem",
          "bm-menu-item-radius": "0px",
          "bm-menu-pad": "0px",
          "bm-scrollbar-width": "none",
          "bm-titlebar-h": "2.75rem",
          "bm-toolbar-h": "44px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 12)",
          "foreground": "oklch(0.97 0.006 12)",
          "card": "oklch(0.2 0.033 12)",
          "card-foreground": "oklch(0.97 0.006 12)",
          "popover": "oklch(0.2 0.033 12)",
          "popover-foreground": "oklch(0.97 0.006 12)",
          "primary": "oklch(0.74 0.162 12)",
          "primary-foreground": "oklch(0.16 0.03 12)",
          "secondary": "oklch(0.25 0.037 12)",
          "secondary-foreground": "oklch(0.97 0.006 12)",
          "muted": "oklch(0.25 0.037 12)",
          "muted-foreground": "oklch(0.72 0.026 12)",
          "accent": "oklch(0.28 0.051 12)",
          "accent-foreground": "oklch(0.97 0.006 12)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.19 12)",
          "chart-1": "oklch(0.7 0.152 12)",
          "chart-2": "oklch(0.76 0.152 162)",
          "chart-3": "oklch(0.8 0.152 87)",
          "chart-4": "oklch(0.68 0.152 302)",
          "chart-5": "oklch(0.74 0.143 227)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 03nw-q8wz-zw0g-e5hm; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "pocket"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "An iOS app, in a browser. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Mobile-first consumer apps",
            "Web apps people add to their home screen"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-pocket"
      }
    },
    {
      "name": "preset-rosewater",
      "type": "registry:theme",
      "title": "Rosewater preset",
      "description": "Warm rose with Fraunces, a soft expressive serif, and a calm, unhurried feel. The opposite of a dashboard.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-fraunces.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Fraunces Variable', serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 12)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 12)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 12)",
          "primary": "oklch(0.56 0.19 12)",
          "primary-foreground": "oklch(0.985 0.004 12)",
          "secondary": "oklch(0.965 0.008 12)",
          "secondary-foreground": "oklch(0.2 0.024 12)",
          "muted": "oklch(0.965 0.008 12)",
          "muted-foreground": "oklch(0.5 0.016 12)",
          "accent": "oklch(0.955 0.013 12)",
          "accent-foreground": "oklch(0.2 0.024 12)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 12)",
          "input": "oklch(0.915 0.008 12)",
          "ring": "oklch(0.62 0.19 12)",
          "chart-1": "oklch(0.6 0.162 12)",
          "chart-2": "oklch(0.652 0.143 162)",
          "chart-3": "oklch(0.668 0.137 87)",
          "chart-4": "oklch(0.58 0.162 302)",
          "chart-5": "oklch(0.64 0.124 227)",
          "radius": "0.75rem",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 12)",
          "foreground": "oklch(0.97 0.006 12)",
          "card": "oklch(0.2 0.033 12)",
          "card-foreground": "oklch(0.97 0.006 12)",
          "popover": "oklch(0.2 0.033 12)",
          "popover-foreground": "oklch(0.97 0.006 12)",
          "primary": "oklch(0.74 0.162 12)",
          "primary-foreground": "oklch(0.16 0.03 12)",
          "secondary": "oklch(0.25 0.037 12)",
          "secondary-foreground": "oklch(0.97 0.006 12)",
          "muted": "oklch(0.25 0.037 12)",
          "muted-foreground": "oklch(0.72 0.026 12)",
          "accent": "oklch(0.28 0.051 12)",
          "accent-foreground": "oklch(0.97 0.006 12)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.19 12)",
          "chart-1": "oklch(0.7 0.152 12)",
          "chart-2": "oklch(0.76 0.152 162)",
          "chart-3": "oklch(0.8 0.152 87)",
          "chart-4": "oklch(0.68 0.152 302)",
          "chart-5": "oklch(0.74 0.143 227)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 03nw-q8wz-rftq-kpqg; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "rosewater"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Blush and soft serif. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Food, lifestyle and wellness",
            "Shops with a personal voice"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-rosewater"
      }
    },
    {
      "name": "preset-signal",
      "type": "registry:theme",
      "title": "Signal preset",
      "description": "A bright sky-blue accent with strong edges and Geist. Looks best in dark mode and moves quickly.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-geist.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'Geist Variable', sans-serif",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.024 250)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.024 250)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.024 250)",
          "primary": "oklch(0.548 0.104 225)",
          "primary-foreground": "oklch(0.985 0.006 250)",
          "secondary": "oklch(0.965 0.012 250)",
          "secondary-foreground": "oklch(0.2 0.03 250)",
          "muted": "oklch(0.965 0.012 250)",
          "muted-foreground": "oklch(0.5 0.024 250)",
          "accent": "oklch(0.955 0.011 225)",
          "accent-foreground": "oklch(0.2 0.03 250)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.668 0.012 250)",
          "input": "oklch(0.668 0.012 250)",
          "ring": "oklch(0.62 0.118 225)",
          "chart-1": "oklch(0.6 0.114 225)",
          "chart-2": "oklch(0.66 0.136 15)",
          "chart-3": "oklch(0.68 0.136 300)",
          "chart-4": "oklch(0.58 0.136 155)",
          "chart-5": "oklch(0.64 0.133 80)",
          "radius": "0.625rem",
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.035 250)",
          "foreground": "oklch(0.97 0.008 250)",
          "card": "oklch(0.2 0.044 250)",
          "card-foreground": "oklch(0.97 0.008 250)",
          "popover": "oklch(0.2 0.044 250)",
          "popover-foreground": "oklch(0.97 0.008 250)",
          "primary": "oklch(0.74 0.14 225)",
          "primary-foreground": "oklch(0.16 0.03 225)",
          "secondary": "oklch(0.25 0.049 250)",
          "secondary-foreground": "oklch(0.97 0.008 250)",
          "muted": "oklch(0.25 0.049 250)",
          "muted-foreground": "oklch(0.72 0.04 250)",
          "accent": "oklch(0.28 0.043 225)",
          "accent-foreground": "oklch(0.97 0.008 250)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(0.5 0.035 250)",
          "input": "oklch(0.5 0.035 250)",
          "ring": "oklch(0.66 0.125 225)",
          "chart-1": "oklch(0.7 0.128 225)",
          "chart-2": "oklch(0.76 0.128 15)",
          "chart-3": "oklch(0.8 0.119 300)",
          "chart-4": "oklch(0.68 0.128 155)",
          "chart-5": "oklch(0.74 0.128 80)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 21bj-14v1-gqcw-jkx0; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "signal"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Electric blue, built for dark. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Developer and gaming products",
            "Apps used mostly in dark mode"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-signal"
      }
    },
    {
      "name": "preset-terminal",
      "type": "registry:theme",
      "title": "Terminal preset",
      "description": "No colour at all: square corners, strong outlines and JetBrains Mono for everything. Fast and uncompromising.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "registryDependencies": [
        "https://ui.ballmac.com/r/font-jetbrains-mono.json"
      ],
      "cssVars": {
        "theme": {
          "font-sans": "'JetBrains Mono Variable', monospace",
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0 0)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0 0)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0 0)",
          "primary": "oklch(0.2 0 0)",
          "primary-foreground": "oklch(0.985 0 0)",
          "secondary": "oklch(0.965 0 0)",
          "secondary-foreground": "oklch(0.2 0 0)",
          "muted": "oklch(0.965 0 0)",
          "muted-foreground": "oklch(0.5 0 0)",
          "accent": "oklch(0.955 0 0)",
          "accent-foreground": "oklch(0.2 0 0)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.668 0 0)",
          "input": "oklch(0.668 0 0)",
          "ring": "oklch(0.62 0 0)",
          "chart-1": "oklch(0.2 0 0)",
          "chart-2": "oklch(0.4 0 0)",
          "chart-3": "oklch(0.56 0 0)",
          "chart-4": "oklch(0.3 0 0)",
          "chart-5": "oklch(0.48 0 0)",
          "radius": "0rem",
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.145 0 0)",
          "foreground": "oklch(0.97 0 0)",
          "card": "oklch(0.2 0 0)",
          "card-foreground": "oklch(0.97 0 0)",
          "popover": "oklch(0.2 0 0)",
          "popover-foreground": "oklch(0.97 0 0)",
          "primary": "oklch(0.97 0 0)",
          "primary-foreground": "oklch(0.2 0 0)",
          "secondary": "oklch(0.25 0 0)",
          "secondary-foreground": "oklch(0.97 0 0)",
          "muted": "oklch(0.25 0 0)",
          "muted-foreground": "oklch(0.72 0 0)",
          "accent": "oklch(0.28 0 0)",
          "accent-foreground": "oklch(0.97 0 0)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(0.5 0 0)",
          "input": "oklch(0.5 0 0)",
          "ring": "oklch(0.66 0 0)",
          "chart-1": "oklch(0.9 0 0)",
          "chart-2": "oklch(0.7 0 0)",
          "chart-3": "oklch(0.55 0 0)",
          "chart-4": "oklch(0.8 0 0)",
          "chart-5": "oklch(0.62 0 0)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "A complete design system: colour, shape, typeface, platform feel and motion. Its code is 0000-0001-krvj-ayah; paste it at https://ui.ballmac.com/themes to change anything.",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "preset",
          "theme",
          "design system",
          "tokens",
          "terminal"
        ],
        "version": "1.0.0",
        "updated": "2026-10-18",
        "ai": {
          "summary": "Black, white, square, monospaced. Sets colours, radius, typeface, platform feel and motion together, with contrast checked in light and dark.",
          "whenToUse": [
            "Technical and brutalist products",
            "Teams that need maximum contrast"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep",
            "You only want part of it: add ?only=colors,font (see the presets guide)"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes with this preset's code to change any setting, then install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/preset-terminal"
      }
    },
    {
      "name": "theme-amber",
      "type": "registry:theme",
      "title": "Amber theme",
      "description": "Near-black buttons with amber focus rings and charts on warm paper-tinted greys.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.375rem",
          "background": "oklch(0.978 0.012 80)",
          "foreground": "oklch(0.17 0.016 80)",
          "card": "oklch(0.994 0.006 80)",
          "card-foreground": "oklch(0.17 0.016 80)",
          "popover": "oklch(0.994 0.006 80)",
          "popover-foreground": "oklch(0.17 0.016 80)",
          "primary": "oklch(0.2 0.024 80)",
          "primary-foreground": "oklch(0.985 0.004 80)",
          "secondary": "oklch(0.965 0.008 80)",
          "secondary-foreground": "oklch(0.2 0.024 80)",
          "muted": "oklch(0.965 0.008 80)",
          "muted-foreground": "oklch(0.5 0.016 80)",
          "accent": "oklch(0.955 0.011 80)",
          "accent-foreground": "oklch(0.2 0.024 80)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 80)",
          "input": "oklch(0.915 0.008 80)",
          "ring": "oklch(0.62 0.129 80)",
          "chart-1": "oklch(0.6 0.125 80)",
          "chart-2": "oklch(0.644 0.129 230)",
          "chart-3": "oklch(0.636 0.136 155)",
          "chart-4": "oklch(0.58 0.136 10)",
          "chart-5": "oklch(0.64 0.136 295)",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 80)",
          "foreground": "oklch(0.97 0.006 80)",
          "card": "oklch(0.2 0.033 80)",
          "card-foreground": "oklch(0.97 0.006 80)",
          "popover": "oklch(0.2 0.033 80)",
          "popover-foreground": "oklch(0.97 0.006 80)",
          "primary": "oklch(0.97 0.006 80)",
          "primary-foreground": "oklch(0.2 0.033 80)",
          "secondary": "oklch(0.25 0.037 80)",
          "secondary-foreground": "oklch(0.97 0.006 80)",
          "muted": "oklch(0.25 0.037 80)",
          "muted-foreground": "oklch(0.72 0.026 80)",
          "accent": "oklch(0.28 0.043 80)",
          "accent-foreground": "oklch(0.97 0.006 80)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.137 80)",
          "chart-1": "oklch(0.7 0.128 80)",
          "chart-2": "oklch(0.76 0.128 230)",
          "chart-3": "oklch(0.8 0.128 155)",
          "chart-4": "oklch(0.68 0.128 10)",
          "chart-5": "oklch(0.74 0.128 295)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/amber",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "amber"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Ink buttons, golden accents. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a native feel for motion.",
          "whenToUse": [
            "Editorial and docs sites",
            "Brands that want warmth without a coloured button"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/amber to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-amber"
      }
    },
    {
      "name": "theme-ember",
      "type": "registry:theme",
      "title": "Ember theme",
      "description": "Orange buttons on warm greys with tighter corners. Energetic but readable.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.5rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 60)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 60)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 60)",
          "primary": "oklch(0.56 0.161 45)",
          "primary-foreground": "oklch(0.985 0.004 60)",
          "secondary": "oklch(0.965 0.008 60)",
          "secondary-foreground": "oklch(0.2 0.024 60)",
          "muted": "oklch(0.965 0.008 60)",
          "muted-foreground": "oklch(0.5 0.016 60)",
          "accent": "oklch(0.955 0.012 45)",
          "accent-foreground": "oklch(0.2 0.024 60)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 60)",
          "input": "oklch(0.915 0.008 60)",
          "ring": "oklch(0.62 0.17 45)",
          "chart-1": "oklch(0.6 0.145 45)",
          "chart-2": "oklch(0.656 0.112 195)",
          "chart-3": "oklch(0.66 0.145 120)",
          "chart-4": "oklch(0.58 0.145 335)",
          "chart-5": "oklch(0.64 0.145 260)",
          "bm-speed": "1.1",
          "bm-bounce": "0.8",
          "bm-travel": "1.4",
          "bm-hover": "1.5",
          "bm-stagger": "1.2",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0819, 0.2862, 0.5499, 0.8166, 1.044, 1.2065, 1.2953, 1.3154, 1.2812, 1.2117, 1.127, 1.044, 0.9753, 0.928, 0.9039, 0.9011, 0.9143, 0.9376, 0.9647, 0.9904, 1.011, 1.0247, 1.031, 1.0309, 1.026, 1.0182, 1.0096, 1.0017, 0.9956, 0.9917, 0.9901, 0.9904, 0.9922, 0.9947, 0.9974, 0.9998, 1.0017, 1.0028, 1.0032, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "14px",
          "bm-lift": "-3px",
          "bm-press": "0.955",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 60)",
          "foreground": "oklch(0.97 0.006 60)",
          "card": "oklch(0.2 0.033 60)",
          "card-foreground": "oklch(0.97 0.006 60)",
          "popover": "oklch(0.2 0.033 60)",
          "popover-foreground": "oklch(0.97 0.006 60)",
          "primary": "oklch(0.74 0.168 45)",
          "primary-foreground": "oklch(0.16 0.03 45)",
          "secondary": "oklch(0.25 0.037 60)",
          "secondary-foreground": "oklch(0.97 0.006 60)",
          "muted": "oklch(0.25 0.037 60)",
          "muted-foreground": "oklch(0.72 0.026 60)",
          "accent": "oklch(0.28 0.046 45)",
          "accent-foreground": "oklch(0.97 0.006 60)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.17 45)",
          "chart-1": "oklch(0.7 0.136 45)",
          "chart-2": "oklch(0.76 0.13 195)",
          "chart-3": "oklch(0.8 0.136 120)",
          "chart-4": "oklch(0.68 0.136 335)",
          "chart-5": "oklch(0.74 0.134 260)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/ember",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "ember"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Burnt orange, crisp. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a playful feel for motion.",
          "whenToUse": [
            "Developer platforms and media",
            "Calls to action that must stand out"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/ember to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-ember"
      }
    },
    {
      "name": "theme-forest",
      "type": "registry:theme",
      "title": "Forest theme",
      "description": "A deep green brand colour with slightly green greys and medium corners.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.5rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 152)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 152)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 152)",
          "primary": "oklch(0.54 0.14 152)",
          "primary-foreground": "oklch(0.985 0.004 152)",
          "secondary": "oklch(0.965 0.008 152)",
          "secondary-foreground": "oklch(0.2 0.024 152)",
          "muted": "oklch(0.965 0.008 152)",
          "muted-foreground": "oklch(0.5 0.016 152)",
          "accent": "oklch(0.955 0.01 152)",
          "accent-foreground": "oklch(0.2 0.024 152)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 152)",
          "input": "oklch(0.915 0.008 152)",
          "ring": "oklch(0.62 0.14 152)",
          "chart-1": "oklch(0.6 0.119 152)",
          "chart-2": "oklch(0.66 0.119 302)",
          "chart-3": "oklch(0.66 0.119 227)",
          "chart-4": "oklch(0.58 0.119 82)",
          "chart-5": "oklch(0.64 0.119 7)",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 152)",
          "foreground": "oklch(0.97 0.006 152)",
          "card": "oklch(0.2 0.033 152)",
          "card-foreground": "oklch(0.97 0.006 152)",
          "popover": "oklch(0.2 0.033 152)",
          "popover-foreground": "oklch(0.97 0.006 152)",
          "primary": "oklch(0.74 0.14 152)",
          "primary-foreground": "oklch(0.16 0.03 152)",
          "secondary": "oklch(0.25 0.037 152)",
          "secondary-foreground": "oklch(0.97 0.006 152)",
          "muted": "oklch(0.25 0.037 152)",
          "muted-foreground": "oklch(0.72 0.026 152)",
          "accent": "oklch(0.28 0.038 152)",
          "accent-foreground": "oklch(0.97 0.006 152)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.14 152)",
          "chart-1": "oklch(0.7 0.112 152)",
          "chart-2": "oklch(0.76 0.112 302)",
          "chart-3": "oklch(0.8 0.112 227)",
          "chart-4": "oklch(0.68 0.112 82)",
          "chart-5": "oklch(0.74 0.112 7)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/forest",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "forest"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Deep green, grounded. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a calm feel for motion.",
          "whenToUse": [
            "Sustainability, finance and wellness",
            "Products that should feel calm and established"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/forest to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-forest"
      }
    },
    {
      "name": "theme-graphite",
      "type": "registry:theme",
      "title": "Graphite theme",
      "description": "Neutral greys with near-black buttons and a calm blue focus ring. The safest starting point for any product.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.5rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.008 255)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.008 255)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.008 255)",
          "primary": "oklch(0.2 0.012 255)",
          "primary-foreground": "oklch(0.985 0.002 255)",
          "secondary": "oklch(0.965 0.004 255)",
          "secondary-foreground": "oklch(0.2 0.012 255)",
          "muted": "oklch(0.965 0.004 255)",
          "muted-foreground": "oklch(0.5 0.008 255)",
          "accent": "oklch(0.955 0.008 255)",
          "accent-foreground": "oklch(0.2 0.012 255)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.004 255)",
          "input": "oklch(0.915 0.004 255)",
          "ring": "oklch(0.62 0.12 255)",
          "chart-1": "oklch(0.6 0.102 255)",
          "chart-2": "oklch(0.66 0.102 45)",
          "chart-3": "oklch(0.68 0.102 330)",
          "chart-4": "oklch(0.58 0.102 185)",
          "chart-5": "oklch(0.64 0.102 110)",
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.013 255)",
          "foreground": "oklch(0.97 0.003 255)",
          "card": "oklch(0.2 0.017 255)",
          "card-foreground": "oklch(0.97 0.003 255)",
          "popover": "oklch(0.2 0.017 255)",
          "popover-foreground": "oklch(0.97 0.003 255)",
          "primary": "oklch(0.97 0.003 255)",
          "primary-foreground": "oklch(0.2 0.017 255)",
          "secondary": "oklch(0.25 0.018 255)",
          "secondary-foreground": "oklch(0.97 0.003 255)",
          "muted": "oklch(0.25 0.018 255)",
          "muted-foreground": "oklch(0.72 0.013 255)",
          "accent": "oklch(0.28 0.032 255)",
          "accent-foreground": "oklch(0.97 0.003 255)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.12 255)",
          "chart-1": "oklch(0.7 0.096 255)",
          "chart-2": "oklch(0.76 0.096 45)",
          "chart-3": "oklch(0.8 0.096 330)",
          "chart-4": "oklch(0.68 0.096 185)",
          "chart-5": "oklch(0.74 0.096 110)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/graphite",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "graphite"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Quiet greys, ink buttons. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a snappy feel for motion.",
          "whenToUse": [
            "Dashboards and admin tools",
            "Products that should look neutral and let content lead"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/graphite to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-graphite"
      }
    },
    {
      "name": "theme-indigo",
      "type": "registry:theme",
      "title": "Indigo theme",
      "description": "Indigo buttons and accents with generous corners. Feels modern without being loud.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.75rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 277)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 277)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 277)",
          "primary": "oklch(0.56 0.2 277)",
          "primary-foreground": "oklch(0.985 0.004 277)",
          "secondary": "oklch(0.965 0.008 277)",
          "secondary-foreground": "oklch(0.2 0.024 277)",
          "muted": "oklch(0.965 0.008 277)",
          "muted-foreground": "oklch(0.5 0.016 277)",
          "accent": "oklch(0.955 0.014 277)",
          "accent-foreground": "oklch(0.2 0.024 277)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 277)",
          "input": "oklch(0.915 0.008 277)",
          "ring": "oklch(0.62 0.2 277)",
          "chart-1": "oklch(0.6 0.17 277)",
          "chart-2": "oklch(0.66 0.146 67)",
          "chart-3": "oklch(0.688 0.17 352)",
          "chart-4": "oklch(0.58 0.1 207)",
          "chart-5": "oklch(0.64 0.17 132)",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 277)",
          "foreground": "oklch(0.97 0.006 277)",
          "card": "oklch(0.2 0.033 277)",
          "card-foreground": "oklch(0.97 0.006 277)",
          "popover": "oklch(0.2 0.033 277)",
          "popover-foreground": "oklch(0.97 0.006 277)",
          "primary": "oklch(0.74 0.135 277)",
          "primary-foreground": "oklch(0.16 0.03 277)",
          "secondary": "oklch(0.25 0.037 277)",
          "secondary-foreground": "oklch(0.97 0.006 277)",
          "muted": "oklch(0.25 0.037 277)",
          "muted-foreground": "oklch(0.72 0.026 277)",
          "accent": "oklch(0.28 0.054 277)",
          "accent-foreground": "oklch(0.97 0.006 277)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.183 277)",
          "chart-1": "oklch(0.7 0.159 277)",
          "chart-2": "oklch(0.76 0.16 67)",
          "chart-3": "oklch(0.8 0.134 352)",
          "chart-4": "oklch(0.68 0.117 207)",
          "chart-5": "oklch(0.74 0.16 132)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/indigo",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "indigo"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Deep blue-violet, rounder. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a native feel for motion.",
          "whenToUse": [
            "Developer tools and AI products",
            "Marketing sites that want a distinct colour"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/indigo to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-indigo"
      }
    },
    {
      "name": "theme-midnight",
      "type": "registry:theme",
      "title": "Midnight theme",
      "description": "A bright sky-blue brand colour with strong outlines. Built to look best in dark mode.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.625rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.024 250)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.024 250)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.024 250)",
          "primary": "oklch(0.548 0.104 225)",
          "primary-foreground": "oklch(0.985 0.006 250)",
          "secondary": "oklch(0.965 0.012 250)",
          "secondary-foreground": "oklch(0.2 0.03 250)",
          "muted": "oklch(0.965 0.012 250)",
          "muted-foreground": "oklch(0.5 0.024 250)",
          "accent": "oklch(0.955 0.011 225)",
          "accent-foreground": "oklch(0.2 0.03 250)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.668 0.012 250)",
          "input": "oklch(0.668 0.012 250)",
          "ring": "oklch(0.62 0.118 225)",
          "chart-1": "oklch(0.6 0.114 225)",
          "chart-2": "oklch(0.66 0.136 15)",
          "chart-3": "oklch(0.68 0.136 300)",
          "chart-4": "oklch(0.58 0.136 155)",
          "chart-5": "oklch(0.64 0.133 80)",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.035 250)",
          "foreground": "oklch(0.97 0.008 250)",
          "card": "oklch(0.2 0.044 250)",
          "card-foreground": "oklch(0.97 0.008 250)",
          "popover": "oklch(0.2 0.044 250)",
          "popover-foreground": "oklch(0.97 0.008 250)",
          "primary": "oklch(0.74 0.14 225)",
          "primary-foreground": "oklch(0.16 0.03 225)",
          "secondary": "oklch(0.25 0.049 250)",
          "secondary-foreground": "oklch(0.97 0.008 250)",
          "muted": "oklch(0.25 0.049 250)",
          "muted-foreground": "oklch(0.72 0.04 250)",
          "accent": "oklch(0.28 0.043 225)",
          "accent-foreground": "oklch(0.97 0.008 250)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(0.5 0.035 250)",
          "input": "oklch(0.5 0.035 250)",
          "ring": "oklch(0.66 0.125 225)",
          "chart-1": "oklch(0.7 0.128 225)",
          "chart-2": "oklch(0.76 0.128 15)",
          "chart-3": "oklch(0.8 0.119 300)",
          "chart-4": "oklch(0.68 0.128 155)",
          "chart-5": "oklch(0.74 0.128 80)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/midnight",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "midnight"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Electric sky blue, strong edges. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a calm feel for motion.",
          "whenToUse": [
            "Developer and gaming products",
            "Apps used mostly in dark mode"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/midnight to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-midnight"
      }
    },
    {
      "name": "theme-mono",
      "type": "registry:theme",
      "title": "Mono theme",
      "description": "No colour at all: black, white and greys, square corners and borders strong enough to meet 3:1 contrast.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0 0)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0 0)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0 0)",
          "primary": "oklch(0.2 0 0)",
          "primary-foreground": "oklch(0.985 0 0)",
          "secondary": "oklch(0.965 0 0)",
          "secondary-foreground": "oklch(0.2 0 0)",
          "muted": "oklch(0.965 0 0)",
          "muted-foreground": "oklch(0.5 0 0)",
          "accent": "oklch(0.955 0 0)",
          "accent-foreground": "oklch(0.2 0 0)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.668 0 0)",
          "input": "oklch(0.668 0 0)",
          "ring": "oklch(0.62 0 0)",
          "chart-1": "oklch(0.2 0 0)",
          "chart-2": "oklch(0.4 0 0)",
          "chart-3": "oklch(0.56 0 0)",
          "chart-4": "oklch(0.3 0 0)",
          "chart-5": "oklch(0.48 0 0)",
          "bm-speed": "1.6",
          "bm-bounce": "0.05",
          "bm-travel": "0.7",
          "bm-hover": "0.8",
          "bm-stagger": "0.5",
          "bm-ambient": "0",
          "bm-ambient-state": "paused",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0141, 0.0505, 0.1017, 0.1621, 0.2274, 0.2945, 0.361, 0.4254, 0.4865, 0.5437, 0.5966, 0.6449, 0.6888, 0.7283, 0.7636, 0.7951, 0.8229, 0.8474, 0.8689, 0.8877, 0.9041, 0.9183, 0.9306, 0.9412, 0.9503, 0.9581, 0.9647, 0.9704, 0.9752, 0.9793, 0.9828, 0.9857, 0.9882, 0.9902, 0.992, 0.9934, 0.9946, 0.9956, 0.9964, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1.6px",
          "bm-press": "0.976",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.145 0 0)",
          "foreground": "oklch(0.97 0 0)",
          "card": "oklch(0.2 0 0)",
          "card-foreground": "oklch(0.97 0 0)",
          "popover": "oklch(0.2 0 0)",
          "popover-foreground": "oklch(0.97 0 0)",
          "primary": "oklch(0.97 0 0)",
          "primary-foreground": "oklch(0.2 0 0)",
          "secondary": "oklch(0.25 0 0)",
          "secondary-foreground": "oklch(0.97 0 0)",
          "muted": "oklch(0.25 0 0)",
          "muted-foreground": "oklch(0.72 0 0)",
          "accent": "oklch(0.28 0 0)",
          "accent-foreground": "oklch(0.97 0 0)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(0.5 0 0)",
          "input": "oklch(0.5 0 0)",
          "ring": "oklch(0.66 0 0)",
          "chart-1": "oklch(0.9 0 0)",
          "chart-2": "oklch(0.7 0 0)",
          "chart-3": "oklch(0.55 0 0)",
          "chart-4": "oklch(0.8 0 0)",
          "chart-5": "oklch(0.62 0 0)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/mono",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "mono"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Pure black and white, square. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a snappy feel for motion.",
          "whenToUse": [
            "Brutalist and technical products",
            "Teams that need maximum contrast"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/mono to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-mono"
      }
    },
    {
      "name": "theme-ocean",
      "type": "registry:theme",
      "title": "Ocean theme",
      "description": "A confident blue brand colour on cool, lightly tinted greys with soft corners.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.625rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 248)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 248)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 248)",
          "primary": "oklch(0.556 0.15 248)",
          "primary-foreground": "oklch(0.985 0.004 248)",
          "secondary": "oklch(0.965 0.008 248)",
          "secondary-foreground": "oklch(0.2 0.024 248)",
          "muted": "oklch(0.965 0.008 248)",
          "muted-foreground": "oklch(0.5 0.016 248)",
          "accent": "oklch(0.955 0.012 248)",
          "accent-foreground": "oklch(0.2 0.024 248)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 248)",
          "input": "oklch(0.915 0.008 248)",
          "ring": "oklch(0.62 0.167 248)",
          "chart-1": "oklch(0.6 0.145 248)",
          "chart-2": "oklch(0.66 0.145 38)",
          "chart-3": "oklch(0.684 0.145 323)",
          "chart-4": "oklch(0.58 0.107 178)",
          "chart-5": "oklch(0.64 0.135 103)",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 248)",
          "foreground": "oklch(0.97 0.006 248)",
          "card": "oklch(0.2 0.033 248)",
          "card-foreground": "oklch(0.97 0.006 248)",
          "popover": "oklch(0.2 0.033 248)",
          "popover-foreground": "oklch(0.97 0.006 248)",
          "primary": "oklch(0.74 0.141 248)",
          "primary-foreground": "oklch(0.16 0.03 248)",
          "secondary": "oklch(0.25 0.037 248)",
          "secondary-foreground": "oklch(0.97 0.006 248)",
          "muted": "oklch(0.25 0.037 248)",
          "muted-foreground": "oklch(0.72 0.026 248)",
          "accent": "oklch(0.28 0.046 248)",
          "accent-foreground": "oklch(0.97 0.006 248)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.17 248)",
          "chart-1": "oklch(0.7 0.136 248)",
          "chart-2": "oklch(0.76 0.136 38)",
          "chart-3": "oklch(0.8 0.136 323)",
          "chart-4": "oklch(0.68 0.125 178)",
          "chart-5": "oklch(0.74 0.136 103)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/ocean",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "ocean"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Clear blue, friendly corners. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a native feel for motion.",
          "whenToUse": [
            "SaaS and fintech products",
            "Anything that should feel trustworthy"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/ocean to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-ocean"
      }
    },
    {
      "name": "theme-rose",
      "type": "registry:theme",
      "title": "Rose theme",
      "description": "A warm rose brand colour with blush-tinted greys and soft corners.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.75rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 12)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 12)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 12)",
          "primary": "oklch(0.56 0.19 12)",
          "primary-foreground": "oklch(0.985 0.004 12)",
          "secondary": "oklch(0.965 0.008 12)",
          "secondary-foreground": "oklch(0.2 0.024 12)",
          "muted": "oklch(0.965 0.008 12)",
          "muted-foreground": "oklch(0.5 0.016 12)",
          "accent": "oklch(0.955 0.013 12)",
          "accent-foreground": "oklch(0.2 0.024 12)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 12)",
          "input": "oklch(0.915 0.008 12)",
          "ring": "oklch(0.62 0.19 12)",
          "chart-1": "oklch(0.6 0.162 12)",
          "chart-2": "oklch(0.652 0.143 162)",
          "chart-3": "oklch(0.668 0.137 87)",
          "chart-4": "oklch(0.58 0.162 302)",
          "chart-5": "oklch(0.64 0.124 227)",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 12)",
          "foreground": "oklch(0.97 0.006 12)",
          "card": "oklch(0.2 0.033 12)",
          "card-foreground": "oklch(0.97 0.006 12)",
          "popover": "oklch(0.2 0.033 12)",
          "popover-foreground": "oklch(0.97 0.006 12)",
          "primary": "oklch(0.74 0.162 12)",
          "primary-foreground": "oklch(0.16 0.03 12)",
          "secondary": "oklch(0.25 0.037 12)",
          "secondary-foreground": "oklch(0.97 0.006 12)",
          "muted": "oklch(0.25 0.037 12)",
          "muted-foreground": "oklch(0.72 0.026 12)",
          "accent": "oklch(0.28 0.051 12)",
          "accent-foreground": "oklch(0.97 0.006 12)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.19 12)",
          "chart-1": "oklch(0.7 0.152 12)",
          "chart-2": "oklch(0.76 0.152 162)",
          "chart-3": "oklch(0.8 0.152 87)",
          "chart-4": "oklch(0.68 0.152 302)",
          "chart-5": "oklch(0.74 0.143 227)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/rose",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "rose"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Warm pink-red, soft. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a native feel for motion.",
          "whenToUse": [
            "Lifestyle, health and community products",
            "Shops with a friendly voice"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/rose to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-rose"
      }
    },
    {
      "name": "theme-sand",
      "type": "registry:theme",
      "title": "Sand theme",
      "description": "Off-white paper tones with terracotta accents and small, precise corners. Reads like print.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.375rem",
          "background": "oklch(0.978 0.018 80)",
          "foreground": "oklch(0.17 0.024 80)",
          "card": "oklch(0.994 0.006 80)",
          "card-foreground": "oklch(0.17 0.024 80)",
          "popover": "oklch(0.994 0.006 80)",
          "popover-foreground": "oklch(0.17 0.024 80)",
          "primary": "oklch(0.56 0.13 40)",
          "primary-foreground": "oklch(0.985 0.006 80)",
          "secondary": "oklch(0.965 0.012 80)",
          "secondary-foreground": "oklch(0.2 0.03 80)",
          "muted": "oklch(0.965 0.012 80)",
          "muted-foreground": "oklch(0.5 0.024 80)",
          "accent": "oklch(0.955 0.009 40)",
          "accent-foreground": "oklch(0.2 0.03 80)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.012 80)",
          "input": "oklch(0.915 0.012 80)",
          "ring": "oklch(0.62 0.13 40)",
          "chart-1": "oklch(0.6 0.111 40)",
          "chart-2": "oklch(0.636 0.11 190)",
          "chart-3": "oklch(0.644 0.111 115)",
          "chart-4": "oklch(0.58 0.111 330)",
          "chart-5": "oklch(0.64 0.111 255)",
          "bm-speed": "0.75",
          "bm-bounce": "0",
          "bm-travel": "0.7",
          "bm-hover": "0.5",
          "bm-stagger": "1.4",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "7px",
          "bm-lift": "-1px",
          "bm-press": "0.985",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.035 80)",
          "foreground": "oklch(0.97 0.008 80)",
          "card": "oklch(0.2 0.044 80)",
          "card-foreground": "oklch(0.97 0.008 80)",
          "popover": "oklch(0.2 0.044 80)",
          "popover-foreground": "oklch(0.97 0.008 80)",
          "primary": "oklch(0.74 0.13 40)",
          "primary-foreground": "oklch(0.16 0.03 40)",
          "secondary": "oklch(0.25 0.049 80)",
          "secondary-foreground": "oklch(0.97 0.008 80)",
          "muted": "oklch(0.25 0.049 80)",
          "muted-foreground": "oklch(0.72 0.04 80)",
          "accent": "oklch(0.28 0.035 40)",
          "accent-foreground": "oklch(0.97 0.008 80)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.13 40)",
          "chart-1": "oklch(0.7 0.104 40)",
          "chart-2": "oklch(0.76 0.104 190)",
          "chart-3": "oklch(0.8 0.104 115)",
          "chart-4": "oklch(0.68 0.104 330)",
          "chart-5": "oklch(0.74 0.104 255)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/sand",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "sand"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Warm paper, terracotta. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a calm feel for motion.",
          "whenToUse": [
            "Portfolios, publications and studios",
            "Shops with a crafted feel"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/sand to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-sand"
      }
    },
    {
      "name": "theme-teal",
      "type": "registry:theme",
      "title": "Teal theme",
      "description": "A fresh teal with cool greys and rounded corners.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "0.875rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.016 200)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.016 200)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.016 200)",
          "primary": "oklch(0.544 0.094 192)",
          "primary-foreground": "oklch(0.985 0.004 200)",
          "secondary": "oklch(0.965 0.008 200)",
          "secondary-foreground": "oklch(0.2 0.024 200)",
          "muted": "oklch(0.965 0.008 200)",
          "muted-foreground": "oklch(0.5 0.016 200)",
          "accent": "oklch(0.955 0.008 192)",
          "accent-foreground": "oklch(0.2 0.024 200)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.008 200)",
          "input": "oklch(0.915 0.008 200)",
          "ring": "oklch(0.62 0.107 192)",
          "chart-1": "oklch(0.6 0.102 192)",
          "chart-2": "oklch(0.66 0.102 342)",
          "chart-3": "oklch(0.672 0.102 267)",
          "chart-4": "oklch(0.58 0.102 122)",
          "chart-5": "oklch(0.64 0.102 47)",
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.026 200)",
          "foreground": "oklch(0.97 0.006 200)",
          "card": "oklch(0.2 0.033 200)",
          "card-foreground": "oklch(0.97 0.006 200)",
          "popover": "oklch(0.2 0.033 200)",
          "popover-foreground": "oklch(0.97 0.006 200)",
          "primary": "oklch(0.74 0.12 192)",
          "primary-foreground": "oklch(0.16 0.03 192)",
          "secondary": "oklch(0.25 0.037 200)",
          "secondary-foreground": "oklch(0.97 0.006 200)",
          "muted": "oklch(0.25 0.037 200)",
          "muted-foreground": "oklch(0.72 0.026 200)",
          "accent": "oklch(0.28 0.032 192)",
          "accent-foreground": "oklch(0.97 0.006 200)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.114 192)",
          "chart-1": "oklch(0.7 0.096 192)",
          "chart-2": "oklch(0.76 0.096 342)",
          "chart-3": "oklch(0.8 0.096 267)",
          "chart-4": "oklch(0.68 0.096 122)",
          "chart-5": "oklch(0.74 0.096 47)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/teal",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "teal"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Fresh blue-green, round. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a native feel for motion.",
          "whenToUse": [
            "Health, data and productivity apps",
            "Dashboards that want a friendly tone"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/teal to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-teal"
      }
    },
    {
      "name": "theme-violet",
      "type": "registry:theme",
      "title": "Violet theme",
      "description": "A saturated purple with pill-like corners and slightly warm greys for a playful, creative feel.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "radius": "1rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.02 305)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.02 305)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.02 305)",
          "primary": "oklch(0.56 0.22 305)",
          "primary-foreground": "oklch(0.985 0.005 305)",
          "secondary": "oklch(0.965 0.01 305)",
          "secondary-foreground": "oklch(0.2 0.03 305)",
          "muted": "oklch(0.965 0.01 305)",
          "muted-foreground": "oklch(0.5 0.02 305)",
          "accent": "oklch(0.955 0.015 305)",
          "accent-foreground": "oklch(0.2 0.03 305)",
          "destructive": "oklch(0.56 0.22 27)",
          "border": "oklch(0.915 0.01 305)",
          "input": "oklch(0.915 0.01 305)",
          "ring": "oklch(0.62 0.22 305)",
          "chart-1": "oklch(0.6 0.187 305)",
          "chart-2": "oklch(0.66 0.136 95)",
          "chart-3": "oklch(0.692 0.187 20)",
          "chart-4": "oklch(0.58 0.123 235)",
          "chart-5": "oklch(0.64 0.145 160)",
          "bm-speed": "1.1",
          "bm-bounce": "0.8",
          "bm-travel": "1.4",
          "bm-hover": "1.5",
          "bm-stagger": "1.2",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0819, 0.2862, 0.5499, 0.8166, 1.044, 1.2065, 1.2953, 1.3154, 1.2812, 1.2117, 1.127, 1.044, 0.9753, 0.928, 0.9039, 0.9011, 0.9143, 0.9376, 0.9647, 0.9904, 1.011, 1.0247, 1.031, 1.0309, 1.026, 1.0182, 1.0096, 1.0017, 0.9956, 0.9917, 0.9901, 0.9904, 0.9922, 0.9947, 0.9974, 0.9998, 1.0017, 1.0028, 1.0032, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "14px",
          "bm-lift": "-3px",
          "bm-press": "0.955",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px"
        },
        "dark": {
          "background": "oklch(0.16 0.033 305)",
          "foreground": "oklch(0.97 0.007 305)",
          "card": "oklch(0.2 0.041 305)",
          "card-foreground": "oklch(0.97 0.007 305)",
          "popover": "oklch(0.2 0.041 305)",
          "popover-foreground": "oklch(0.97 0.007 305)",
          "primary": "oklch(0.74 0.169 305)",
          "primary-foreground": "oklch(0.16 0.03 305)",
          "secondary": "oklch(0.25 0.046 305)",
          "secondary-foreground": "oklch(0.97 0.007 305)",
          "muted": "oklch(0.25 0.046 305)",
          "muted-foreground": "oklch(0.72 0.033 305)",
          "accent": "oklch(0.28 0.059 305)",
          "accent-foreground": "oklch(0.97 0.007 305)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.22 305)",
          "chart-1": "oklch(0.7 0.176 305)",
          "chart-2": "oklch(0.76 0.156 95)",
          "chart-3": "oklch(0.8 0.115 20)",
          "chart-4": "oklch(0.68 0.145 235)",
          "chart-5": "oklch(0.74 0.168 160)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        }
      },
      "docs": "Tune this theme, preview it on real components and copy the CSS at https://ui.ballmac.com/themes/violet",
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "preset",
          "tokens",
          "dark mode",
          "violet"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens at the web feel (no change to how components look). Pick a feel on top with feel-macos, feel-ios or feel-windows.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Adds motion: speed, bounce, travel, hover and stagger tokens that drive Tailwind's duration and easing scales, plus a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-10-02",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Rich purple, very round. A complete set of light and dark tokens, with contrast checked for text, focus rings and charts, and a playful feel for motion.",
          "whenToUse": [
            "Creative tools and communities",
            "Consumer apps"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Open https://ui.ballmac.com/themes/violet to change hue, intensity, radius, density and font, then copy the CSS or install the result"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme-violet"
      }
    },
    {
      "name": "theme",
      "type": "registry:theme",
      "title": "Ballmac Theme",
      "description": "Ballmac UI design tokens in OKLCH: colours, radius, chart colours, motion (speed, bounce, travel, hover, stagger) and the platform feel tokens (focus, shadows, text scale, control sizes), with a reduced-motion fallback.",
      "author": "Ballmac <https://ui.ballmac.com>",
      "cssVars": {
        "theme": {
          "ease-out": "var(--bm-ease-out)",
          "ease-in": "var(--bm-ease-in)",
          "ease-in-out": "var(--bm-ease-in-out)",
          "ease-spring": "var(--bm-ease-spring)",
          "animate-in": "enter var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-out": "exit var(--tw-animation-duration,var(--tw-duration,calc(150ms / var(--bm-speed))))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-down": "accordion-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-accordion-up": "accordion-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-down": "collapsible-down var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "animate-collapsible-up": "collapsible-up var(--tw-animation-duration,var(--tw-duration,calc(200ms / var(--bm-speed))))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)",
          "transition-duration-75": "calc(75ms / var(--bm-speed))",
          "transition-delay-75": "calc(75ms / var(--bm-speed))",
          "transition-duration-100": "calc(100ms / var(--bm-speed))",
          "transition-delay-100": "calc(100ms / var(--bm-speed))",
          "transition-duration-150": "calc(150ms / var(--bm-speed))",
          "transition-delay-150": "calc(150ms / var(--bm-speed))",
          "transition-duration-200": "calc(200ms / var(--bm-speed))",
          "transition-delay-200": "calc(200ms / var(--bm-speed))",
          "transition-duration-300": "calc(300ms / var(--bm-speed))",
          "transition-delay-300": "calc(300ms / var(--bm-speed))",
          "transition-duration-500": "calc(500ms / var(--bm-speed))",
          "transition-delay-500": "calc(500ms / var(--bm-speed))",
          "transition-duration-700": "calc(700ms / var(--bm-speed))",
          "transition-delay-700": "calc(700ms / var(--bm-speed))",
          "transition-duration-1000": "calc(1000ms / var(--bm-speed))",
          "transition-delay-1000": "calc(1000ms / var(--bm-speed))",
          "shadow-xs": "var(--bm-shadow-xs)",
          "shadow-sm": "var(--bm-shadow-sm)",
          "shadow-md": "var(--bm-shadow-md)",
          "shadow-lg": "var(--bm-shadow-lg)",
          "shadow-xl": "var(--bm-shadow-xl)",
          "shadow-2xl": "var(--bm-shadow-2xl)",
          "text-xs": "var(--bm-text-xs)",
          "text-xs--line-height": "var(--bm-text-xs-lh)",
          "text-sm": "var(--bm-text-sm)",
          "text-sm--line-height": "var(--bm-text-sm-lh)",
          "text-base": "var(--bm-text-base)",
          "text-base--line-height": "var(--bm-text-base-lh)"
        },
        "light": {
          "bm-speed": "1",
          "bm-bounce": "0.25",
          "bm-travel": "1",
          "bm-hover": "1",
          "bm-stagger": "1",
          "bm-ambient": "1",
          "bm-ambient-state": "running",
          "bm-ease-out": "cubic-bezier(0.22, 1, 0.36, 1)",
          "bm-ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
          "bm-ease-in": "cubic-bezier(0.55, 0, 1, 0.45)",
          "bm-ease-spring": "linear(0, 0.0168, 0.0608, 0.1231, 0.1971, 0.2773, 0.3594, 0.4403, 0.5178, 0.5902, 0.6566, 0.7164, 0.7695, 0.816, 0.856, 0.8901, 0.9187, 0.9423, 0.9615, 0.9769, 0.989, 0.9982, 1.005, 1.0099, 1.0131, 1.0151, 1.0161, 1.0163, 1.0159, 1.0151, 1.0141, 1.0128, 1.0115, 1.0102, 1.0089, 1.0076, 1.0064, 1.0054, 1.0044, 1.0036, 1)",
          "bm-duration-fast": "calc(140ms / var(--bm-speed))",
          "bm-duration-base": "calc(220ms / var(--bm-speed))",
          "bm-duration-slow": "calc(320ms / var(--bm-speed))",
          "bm-duration-reveal": "calc(600ms / var(--bm-speed))",
          "bm-distance": "10px",
          "bm-lift": "-2px",
          "bm-press": "0.97",
          "bm-stagger-step": "calc(50ms * var(--bm-stagger) / var(--bm-speed))",
          "bm-shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
          "bm-shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
          "bm-shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
          "bm-shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
          "bm-shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
          "bm-shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
          "bm-shadow-popover": "0 12px 36px -10px rgb(0 0 0 / 0.25)",
          "bm-text-xs": "0.75rem",
          "bm-text-xs-lh": "calc(1 / 0.75)",
          "bm-text-sm": "0.875rem",
          "bm-text-sm-lh": "calc(1.25 / 0.875)",
          "bm-text-base": "1rem",
          "bm-text-base-lh": "calc(1.5 / 1)",
          "bm-focus-width": "3px",
          "bm-focus-alpha": "50%",
          "bm-focus-color": "var(--ring)",
          "bm-control-h": "calc(var(--spacing) * 9)",
          "bm-control-h-sm": "calc(var(--spacing) * 8)",
          "bm-control-h-lg": "calc(var(--spacing) * 11)",
          "bm-target-min": "0px",
          "bm-check-size": "calc(var(--spacing) * 4)",
          "bm-switch-w": "calc(var(--spacing) * 9)",
          "bm-switch-h": "calc(var(--spacing) * 5)",
          "bm-press-dim": "1",
          "bm-material-blur": "0px",
          "bm-material-alpha": "100%",
          "bm-sidebar-item-h": "2rem",
          "bm-sidebar-item-radius": "calc(var(--radius) - 2px)",
          "bm-sidebar-indicator": "0px",
          "bm-menu-item-h": "2rem",
          "bm-menu-item-radius": "calc(var(--radius) - 4px)",
          "bm-menu-pad": "0.25rem",
          "bm-scrollbar-width": "auto",
          "bm-titlebar-h": "2.5rem",
          "bm-toolbar-h": "52px",
          "radius": "0.625rem",
          "background": "oklch(1 0 0)",
          "foreground": "oklch(0.17 0.012 265)",
          "card": "oklch(1 0 0)",
          "card-foreground": "oklch(0.17 0.012 265)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "oklch(0.17 0.012 265)",
          "primary": "oklch(0.21 0.02 266)",
          "primary-foreground": "oklch(0.985 0.002 265)",
          "secondary": "oklch(0.965 0.004 265)",
          "secondary-foreground": "oklch(0.21 0.02 266)",
          "muted": "oklch(0.965 0.004 265)",
          "muted-foreground": "oklch(0.5 0.012 265)",
          "accent": "oklch(0.955 0.012 262)",
          "accent-foreground": "oklch(0.21 0.02 266)",
          "destructive": "oklch(0.58 0.22 27)",
          "border": "oklch(0.915 0.006 265)",
          "input": "oklch(0.915 0.006 265)",
          "ring": "oklch(0.62 0.19 262)",
          "chart-1": "oklch(0.62 0.19 262)",
          "chart-2": "oklch(0.7 0.13 175)",
          "chart-3": "oklch(0.78 0.16 75)",
          "chart-4": "oklch(0.6 0.2 300)",
          "chart-5": "oklch(0.66 0.18 35)"
        },
        "dark": {
          "background": "oklch(0.16 0.02 270)",
          "foreground": "oklch(0.97 0.004 265)",
          "card": "oklch(0.2 0.025 268)",
          "card-foreground": "oklch(0.97 0.004 265)",
          "popover": "oklch(0.2 0.025 268)",
          "popover-foreground": "oklch(0.97 0.004 265)",
          "primary": "oklch(0.97 0.004 265)",
          "primary-foreground": "oklch(0.2 0.025 268)",
          "secondary": "oklch(0.25 0.028 268)",
          "secondary-foreground": "oklch(0.97 0.004 265)",
          "muted": "oklch(0.25 0.028 268)",
          "muted-foreground": "oklch(0.72 0.02 265)",
          "accent": "oklch(0.28 0.05 264)",
          "accent-foreground": "oklch(0.97 0.004 265)",
          "destructive": "oklch(0.66 0.2 25)",
          "border": "oklch(1 0 0 / 11%)",
          "input": "oklch(1 0 0 / 15%)",
          "ring": "oklch(0.66 0.18 262)",
          "chart-1": "oklch(0.66 0.18 262)",
          "chart-2": "oklch(0.74 0.12 175)",
          "chart-3": "oklch(0.8 0.15 75)",
          "chart-4": "oklch(0.66 0.19 300)",
          "chart-5": "oklch(0.7 0.17 35)"
        }
      },
      "css": {
        "@media (prefers-reduced-motion: reduce)": {
          ":root": {
            "--bm-speed": "2",
            "--bm-bounce": "0",
            "--bm-travel": "0",
            "--bm-hover": "0",
            "--bm-stagger": "0.4",
            "--bm-ambient": "0",
            "--bm-ambient-state": "paused",
            "--bm-ease-spring": "linear(0, 0.0177, 0.0622, 0.1231, 0.193, 0.2665, 0.3401, 0.4112, 0.4783, 0.5405, 0.5974, 0.6488, 0.6948, 0.7357, 0.7719, 0.8036, 0.8314, 0.8556, 0.8765, 0.8946, 0.9102, 0.9237, 0.9352, 0.945, 0.9534, 0.9606, 0.9667, 0.9719, 0.9763, 0.98, 0.9832, 0.9859, 0.9881, 0.99, 0.9916, 0.993, 0.9941, 0.9951, 0.9959, 0.9965, 1)",
            "--bm-distance": "0px",
            "--bm-lift": "0px",
            "--bm-press": "1"
          }
        },
        "[class*=\"focus-visible:ring-[3px]\"]:focus-visible": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "[class*=\"focus-within:ring-[3px]\"]:focus-within": {
          "--tw-ring-color": "color-mix(in oklab, var(--bm-focus-color, var(--ring)) var(--bm-focus-alpha, 50%), transparent)",
          "--tw-ring-shadow": "var(--tw-ring-inset,) 0 0 0 calc(var(--bm-focus-width, 3px) + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color)"
        },
        "@media (forced-colors: active)": {
          "[class*=\"focus-visible:ring\"]:focus-visible": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[class*=\"focus-within:ring\"]:focus-within": {
            "outline": "2px solid Highlight",
            "outline-offset": "2px"
          },
          "[data-slot=\"button\"]": {
            "border": "1px solid ButtonText"
          }
        },
        "@layer base": {
          "*": {
            "scrollbar-width": "var(--bm-scrollbar-width, auto)"
          }
        }
      },
      "categories": [
        "foundation"
      ],
      "meta": {
        "schema": 1,
        "tier": "free",
        "tags": [
          "theme",
          "tokens",
          "dark mode"
        ],
        "version": "1.2.0",
        "updated": "2026-10-12",
        "changelog": [
          {
            "version": "1.2.0",
            "date": "2026-10-12",
            "note": "Adds the platform feel tokens (focus ring, elevation, text scale, control, menu and sidebar sizes) at the web feel, which is what the components already do.",
            "breaking": false
          },
          {
            "version": "1.1.0",
            "date": "2026-10-11",
            "note": "Motion is part of the theme: speed, bounce, travel, hover and stagger drive Tailwind's duration and easing scales, with a reduced-motion fallback.",
            "breaking": false
          },
          {
            "version": "1.0.0",
            "date": "2026-09-28",
            "note": "First release.",
            "breaking": false
          }
        ],
        "ai": {
          "summary": "Installs Ballmac UI's color, radius and motion tokens as CSS variables. Optional: every Ballmac item also works with any shadcn theme.",
          "whenToUse": [
            "Starting a new project that should look like Ballmac UI",
            "Matching the Ballmac demos exactly"
          ],
          "whenNotToUse": [
            "The project already has a brand theme you want to keep"
          ],
          "composesWith": [],
          "a11y": [],
          "customization": [
            "Change --ring and --chart-1 to your brand color",
            "Adjust --radius for rounder or sharper corners",
            "Change --bm-speed, --bm-bounce, --bm-travel, --bm-hover and --bm-stagger to change how everything moves",
            "Install feel-macos, feel-ios or feel-windows to make everything handle like that platform"
          ]
        },
        "examples": [],
        "url": "https://ui.ballmac.com/components/theme"
      }
    }
  ]
}
