{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "type": "registry:ui",
  "title": "Button",
  "description": "The system's one button.",
  "registryDependencies": [
    "https://gitu.github.io/clean-design-system/r/styles.json",
    "https://gitu.github.io/clean-design-system/r/cx.json",
    "https://gitu.github.io/clean-design-system/r/spinner.json"
  ],
  "files": [
    {
      "path": "src/components/Button/Button.css",
      "type": "registry:file",
      "target": "@ui/cds/button/Button.css",
      "content": ".cds-btn {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  gap: var(--cds-space-2);\n  font-family: var(--cds-font-sans);\n  font-weight: var(--cds-weight-medium);\n  line-height: 1;\n  white-space: nowrap;\n  border: var(--cds-border-width) solid transparent;\n  border-radius: var(--cds-radius-sm);\n  cursor: pointer;\n  user-select: none;\n  transition: background-color var(--cds-duration-fast) var(--cds-ease-standard),\n    border-color var(--cds-duration-fast) var(--cds-ease-standard),\n    color var(--cds-duration-fast) var(--cds-ease-standard);\n}\n\n.cds-btn:disabled {\n  cursor: not-allowed;\n  opacity: 0.5;\n}\n\n.cds-btn--full {\n  width: 100%;\n}\n\n.cds-btn__icon,\n.cds-btn__spinner {\n  display: inline-flex;\n  flex: none;\n}\n\n/* --- Sizes --- */\n\n.cds-btn--sm {\n  height: var(--cds-control-height-sm);\n  padding-inline: var(--cds-space-2);\n  font-size: var(--cds-text-sm);\n  gap: var(--cds-space-1);\n}\n.cds-btn--md {\n  height: var(--cds-control-height-md);\n  padding-inline: var(--cds-space-3);\n  font-size: var(--cds-text-md);\n}\n.cds-btn--lg {\n  height: var(--cds-control-height-lg);\n  padding-inline: var(--cds-space-4);\n  font-size: var(--cds-text-md);\n}\n\n/* --- Variants --- */\n\n.cds-btn--primary {\n  background-color: var(--cds-color-ink);\n  color: var(--cds-color-on-ink);\n}\n.cds-btn--primary:hover:not(:disabled) {\n  background-color: var(--cds-color-ink-hover);\n}\n.cds-btn--primary:active:not(:disabled) {\n  background-color: var(--cds-color-ink-active);\n}\n\n.cds-btn--accent {\n  background-color: var(--cds-color-accent);\n  color: var(--cds-color-on-accent);\n}\n.cds-btn--accent:hover:not(:disabled) {\n  background-color: var(--cds-color-accent-hover);\n}\n.cds-btn--accent:active:not(:disabled) {\n  background-color: var(--cds-color-accent-active);\n}\n\n.cds-btn--secondary {\n  background-color: var(--cds-color-surface);\n  border-color: var(--cds-color-rule-strong);\n  color: var(--cds-color-text);\n}\n.cds-btn--secondary:hover:not(:disabled) {\n  background-color: var(--cds-color-surface-hover);\n  border-color: var(--cds-color-rule-heavy);\n}\n.cds-btn--secondary:active:not(:disabled) {\n  background-color: var(--cds-color-surface-active);\n}\n\n.cds-btn--ghost {\n  background-color: transparent;\n  color: var(--cds-color-text-muted);\n}\n.cds-btn--ghost:hover:not(:disabled) {\n  background-color: var(--cds-color-surface-hover);\n  color: var(--cds-color-text);\n}\n.cds-btn--ghost:active:not(:disabled) {\n  background-color: var(--cds-color-surface-active);\n}\n\n.cds-btn--danger {\n  background-color: transparent;\n  border-color: var(--cds-color-danger-border);\n  color: var(--cds-color-danger);\n}\n.cds-btn--danger:hover:not(:disabled) {\n  background-color: var(--cds-color-danger-bg);\n  border-color: var(--cds-color-danger);\n}\n\n/* Pressed/selected toolbar buttons, e.g. an active view mode. Only the two\n * quiet variants take a pressed treatment — a filled button is already loud\n * enough that changing its ground would read as a different button. */\n.cds-btn--ghost[aria-pressed='true'],\n.cds-btn--ghost[aria-expanded='true'],\n.cds-btn--secondary[aria-pressed='true'] {\n  background-color: var(--cds-color-surface-active);\n  color: var(--cds-color-text-strong);\n}\n"
    },
    {
      "path": "src/components/Button/Button.tsx",
      "type": "registry:ui",
      "target": "@ui/cds/button/Button.tsx",
      "content": "import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react'\nimport { cx } from '../lib/cx'\nimport { Spinner } from '../spinner/Spinner'\nimport './Button.css'\n\nexport type ButtonVariant = 'primary' | 'accent' | 'secondary' | 'ghost' | 'danger'\nexport type ButtonSize = 'sm' | 'md' | 'lg'\n\nexport interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'prefix'> {\n  /**\n   * `primary` is a solid ink fill — the one obvious action on a view.\n   * `accent` is the accent fill, reserved for the search/submit action itself.\n   * `secondary` is ruled, `ghost` is bare, `danger` is ruled in red.\n   */\n  variant?: ButtonVariant\n  size?: ButtonSize\n  /** Stretch to the width of the container. */\n  fullWidth?: boolean\n  /** Swap the leading icon for a spinner and block interaction. */\n  loading?: boolean\n  /** Icon shown before the label. */\n  iconStart?: ReactNode\n  /** Icon shown after the label — chevrons, external-link marks. */\n  iconEnd?: ReactNode\n}\n\n/**\n * The system's one button.\n *\n * Five variants rather than a `tone` and a `fill` that multiply into twenty:\n * a design system's job here is to make the loud choice rare, and a matrix\n * makes it easy. `primary` is the obvious action on a view, `accent` is\n * reserved for search itself, and `danger` is ruled rather than filled —\n * red is the one colour this system will not use as a ground.\n *\n * `loading` swaps the leading icon for a spinner and disables the button, so\n * the width does not jump and a second click cannot land.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n  {\n    variant = 'secondary',\n    size = 'md',\n    fullWidth = false,\n    loading = false,\n    iconStart,\n    iconEnd,\n    disabled,\n    className,\n    children,\n    type = 'button',\n    ...rest\n  },\n  ref\n) {\n  const spinnerSize = size === 'lg' ? 'md' : 'sm'\n  return (\n    <button\n      ref={ref}\n      type={type}\n      className={cx(\n        'cds-btn',\n        `cds-btn--${variant}`,\n        `cds-btn--${size}`,\n        fullWidth && 'cds-btn--full',\n        loading && 'is-loading',\n        className\n      )}\n      disabled={disabled || loading}\n      aria-busy={loading || undefined}\n      {...rest}\n    >\n      {loading ? (\n        <Spinner size={spinnerSize} label={null} className=\"cds-btn__spinner\" />\n      ) : (\n        iconStart && <span className=\"cds-btn__icon\">{iconStart}</span>\n      )}\n      {children != null && children !== false && <span className=\"cds-btn__label\">{children}</span>}\n      {iconEnd && !loading && <span className=\"cds-btn__icon\">{iconEnd}</span>}\n    </button>\n  )\n})\n"
    },
    {
      "path": "src/components/Button/index.ts",
      "type": "registry:ui",
      "target": "@ui/cds/button/index.ts",
      "content": "export { Button } from './Button'\nexport type { ButtonProps, ButtonVariant, ButtonSize } from './Button'\n"
    }
  ],
  "meta": {
    "loc": 206,
    "source": "src/components/Button"
  }
}
