{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button-variants",
  "title": "Button Variants",
  "description": "The `cva` definition behind Button's variant, size, and shape props.",
  "dependencies": [
    "class-variance-authority@^0.7.1"
  ],
  "files": [
    {
      "path": "src/components/ui/button-variants.ts",
      "content": "/**\n * Variant definitions live beside the component rather than inside it.\n *\n * React Fast Refresh only treats a module as a hot boundary when every export\n * either is a component or keeps a stable identity across re-evaluations.\n * `cva()` builds a fresh object each time its module runs, so exporting it from\n * the component file demoted that file to a full page reload on every edit.\n * Re-exported from here, the binding's identity survives edits to the component.\n */\n\nimport { cva } from \"class-variance-authority\"\n\n/**\n * Material 3 Expressive button.\n *\n * Three things make it read as Material rather than as a generic pill:\n *\n * 1. **Shape.** Fully rounded at rest; on press the corners tighten to the\n *    medium step. That morph is the Expressive signature, and it rides a\n *    spatial spring so it overshoots slightly before settling.\n * 2. **State layer.** Hover/focus/press are a translucent wash of the *content*\n *    color over the container (`::after` at 8% / 10% / 10%), not a different\n *    background per state. One mechanism, every variant.\n * 3. **Size scale.** M3 Expressive defines five heights — 32 / 40 / 56 / 96 /\n *    136 — each with its own type role and padding, rather than one height\n *    scaled up.\n *\n * shadcn's variant names are kept so registry markup keeps working; `elevated`\n * and `tonal` are additions for the Material variants shadcn has no name for.\n */\nexport const buttonVariants = cva(\n  [\n    \"group/button relative isolate inline-flex shrink-0 items-center justify-center\",\n    \"border border-transparent font-m3-medium whitespace-nowrap\",\n    \"outline-none select-none\",\n    \"disabled:pointer-events-none disabled:cursor-not-allowed\",\n    // M3 expresses disabled as opacity on content and container, not a grey fill.\n    // Only `outline` paints a border, and the kit keeps it at outline-variant\n    // when disabled, so no border override is needed here.\n    \"disabled:text-m3-on-surface/38\",\n    // Shape morph: the pressed corner radius is set per size below.\n    //\n    // This deliberately uses the *effects* spring, not the spatial one. Spatial\n    // springs overshoot by ~9%, and an overshoot on border-radius interpolates\n    // past the target into negative values, which CSS clamps to 0 — the button\n    // flicks through a hard-cornered rectangle on the way down.\n    \"transition-[border-radius,box-shadow,background-color,color]\",\n    \"duration-(--m3-spring-effects-default-duration) ease-(--m3-spring-effects-default)\",\n    // State layer. It must cover the *border* box, not the padding box:\n    // `inset-0` would size it to the padding box while `rounded-[inherit]`\n    // gives it the border-box radius, so the corners would not line up. Every\n    // variant carries a 1px border (transparent unless `outline`), which is\n    // why -1px is exact. A negative z-index paints it above the element's own\n    // border — that is correct for Material, where the state layer washes the\n    // whole container shape including its outline.\n    \"after:pointer-events-none after:absolute after:-inset-px after:-z-10\",\n    \"after:rounded-[inherit] after:bg-current after:opacity-0\",\n    \"after:transition-opacity after:duration-(--m3-spring-effects-fast-duration)\",\n    \"after:ease-(--m3-spring-effects-fast)\",\n    \"hover:not-disabled:after:opacity-8 focus-visible:after:opacity-10\",\n    \"active:not-disabled:after:opacity-10\",\n    // Focus ring, per M3: a 3px outline offset from the container.\n    \"focus-visible:outline-m3-secondary focus-visible:outline-3 focus-visible:outline-offset-2\",\n    \"[&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  ],\n  {\n    variants: {\n      variant: {\n        default: \"bg-m3-primary text-m3-on-primary disabled:bg-m3-on-surface/10\",\n        tonal:\n          \"bg-m3-secondary-container text-m3-on-secondary-container disabled:bg-m3-on-surface/10\",\n        // shadcn's `secondary` is Material's tonal button.\n        secondary:\n          \"bg-m3-secondary-container text-m3-on-secondary-container disabled:bg-m3-on-surface/10\",\n        elevated:\n          \"bg-m3-surface-container-low text-m3-primary shadow-m3-1 disabled:bg-m3-on-surface/10 disabled:shadow-m3-0\",\n        outline:\n          \"border-m3-outline-variant text-m3-on-surface-variant bg-transparent\",\n        ghost: \"text-m3-primary bg-transparent\",\n        destructive: \"bg-m3-error text-m3-on-error disabled:bg-m3-on-surface/10\",\n        link: \"text-m3-primary bg-transparent underline-offset-4 hover:underline after:hidden\",\n      },\n      size: {\n        // Pressed radii are the kit's, not a guess: round buttons squeeze to\n        // 8 / 8 / 12 / 16 / 16 across the five sizes. See docs/m3-specs.md.\n        //\n        // The resting radius is written as half the height rather than as\n        // `rounded-m3-full`, because `full` is 9999px and interpolating from\n        // there spends the whole transition far outside the range a viewer can\n        // perceive — a pill looks identical at any radius past half the height.\n        //\n        // Padding is symmetric whether or not a leading icon is present: the\n        // Expressive kit has no icon-side reduction, so there is no\n        // `has-[>svg]:pl-*` here. Per size the kit gives 12 / 16 / 24 / 48 / 64\n        // horizontal padding and 4 / 8 / 8 / 12 / 16 gap.\n        xs: [\n          \"h-8 gap-1 rounded-[16px] px-3 text-m3-label-lg active:not-disabled:rounded-m3-sm\",\n          \"[&_svg:not([class*='size-'])]:size-5\",\n        ],\n        sm: [\n          \"h-10 gap-2 rounded-[20px] px-4 text-m3-label-lg active:not-disabled:rounded-m3-sm\",\n          \"[&_svg:not([class*='size-'])]:size-5\",\n        ],\n        // shadcn's baseline. M3's small button, which is the everyday size.\n        default: [\n          \"h-10 gap-2 rounded-[20px] px-4 text-m3-label-lg active:not-disabled:rounded-m3-sm\",\n          \"[&_svg:not([class*='size-'])]:size-5\",\n        ],\n        lg: [\n          \"h-14 gap-2 rounded-[28px] px-6 text-m3-title-md active:not-disabled:rounded-m3-md\",\n          \"[&_svg:not([class*='size-'])]:size-6\",\n        ],\n        // The two headline sizes set their label in Regular, not Medium.\n        xl: [\n          \"h-24 gap-3 rounded-[48px] px-12 text-m3-headline-sm font-m3-regular active:not-disabled:rounded-m3-lg\",\n          \"[&_svg:not([class*='size-'])]:size-8\",\n        ],\n        \"2xl\": [\n          \"h-34 gap-4 rounded-[68px] px-16 text-m3-headline-lg font-m3-regular active:not-disabled:rounded-m3-lg\",\n          \"[&_svg:not([class*='size-'])]:size-10\",\n        ],\n        icon: \"size-10 rounded-[20px] active:not-disabled:rounded-m3-sm [&_svg:not([class*='size-'])]:size-6\",\n        \"icon-xs\":\n          \"size-8 rounded-[16px] active:not-disabled:rounded-m3-sm [&_svg:not([class*='size-'])]:size-5\",\n        \"icon-sm\":\n          \"size-10 rounded-[20px] active:not-disabled:rounded-m3-sm [&_svg:not([class*='size-'])]:size-6\",\n        \"icon-lg\":\n          \"size-14 rounded-[28px] active:not-disabled:rounded-m3-md [&_svg:not([class*='size-'])]:size-6\",\n      },\n      /** Square buttons keep the size scale but start from a rounded rect. */\n      shape: {\n        round: \"\",\n        square: \"\",\n      },\n    },\n    compoundVariants: [\n      // Text (`ghost`) buttons share the contained padding in the Expressive\n      // kit, so only `link` — an inline affordance, not a kit component —\n      // drops its padding.\n      { variant: \"link\", size: \"xs\", class: \"px-0\" },\n      { variant: \"link\", size: \"sm\", class: \"px-0\" },\n      { variant: \"link\", size: \"default\", class: \"px-0\" },\n      { variant: \"link\", size: \"lg\", class: \"px-0\" },\n      { variant: \"link\", size: \"xl\", class: \"px-0\" },\n      { variant: \"link\", size: \"2xl\", class: \"px-0\" },\n\n      { shape: \"square\", size: \"xs\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"sm\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"default\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"lg\", class: \"rounded-m3-lg active:not-disabled:rounded-m3-md\" },\n      { shape: \"square\", size: \"xl\", class: \"rounded-m3-xl active:not-disabled:rounded-m3-lg\" },\n      { shape: \"square\", size: \"2xl\", class: \"rounded-m3-xl active:not-disabled:rounded-m3-lg\" },\n      { shape: \"square\", size: \"icon\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"icon-xs\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"icon-sm\", class: \"rounded-m3-md active:not-disabled:rounded-m3-sm\" },\n      { shape: \"square\", size: \"icon-lg\", class: \"rounded-m3-lg active:not-disabled:rounded-m3-md\" },\n    ],\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n      shape: \"round\",\n    },\n  },\n)\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "actions"
  ],
  "type": "registry:ui"
}