import { Button } from '@/components/button';
import type { ButtonProps } from '@/components/button';
import { CheckIcon, ChevronRightIcon, SearchIcon } from '@/icons';
import { CONTROL_SIZES, PALETTES, VARIANTS } from './axis-values';
import type { Entry } from './types';
export const button: Entry = {
slug: 'button',
name: 'Button',
group: 'Actions',
description:
"The kit's primary interactive control. Treatment and hue are separate props, the way CBAR models them: `variant` says how filled in the button is, `colorPalette` says which colour it wears — any of the five treatments combines with any of the seven palettes.",
imports: { subpath: 'button', names: ['Button'] },
figma: {
set: 'Button',
/* CBAR draws the four interaction states as separate variants; the kit
draws all but `disabled` in CSS, so that axis is fed by the one prop
that does exist. `third` is CBAR's own name for the tertiary ramp. */
axisMap: { state: 'disabled' },
valueMap: {
state: { true: 'disabled', false: 'default' },
colorPalette: { tertiary: 'third' },
},
},
axes: {
variant: VARIANTS,
colorPalette: PALETTES,
size: CONTROL_SIZES,
disabled: [false, true],
},
defaults: { variant: 'solid', colorPalette: 'primary', size: 'md', disabled: false },
render: (props) => ,
matrices: [
{
title: 'Variant × colorPalette',
description:
'The two axes that compose. Five treatments against seven palettes — 35 combinations that cost 12 cva entries, because a variant reads the --ctl-* roles the palette class sets rather than naming a colour.',
rows: 'variant',
cols: 'colorPalette',
pin: { size: 'md' },
},
{
title: 'Variant × size',
description:
'Heights come from CBAR: 32 / 36 / 40 / 48 / 56px. Note the horizontal padding is not monotonic — lg is roomier than xl — which holds across all 35 Figma variants and is reproduced rather than smoothed.',
rows: 'variant',
cols: 'size',
pin: { colorPalette: 'primary' },
},
{
title: 'Disabled',
description: 'Every treatment at 50% opacity with pointer events off.',
rows: 'variant',
cols: 'colorPalette',
pin: { size: 'md', disabled: true },
},
],
compositions: [
{
name: 'Shorthands',
description:
'Three one-word variants for the combinations that come up constantly. They paint from the semantic roles in theme.css, so they pin their own colour and ignore `colorPalette` instead of racing it on specificity.',
render: () => (
),
},
{
name: 'Icon slots',
description:
"CBAR's Button set carries `iconLeft?` and `iconRight?` as two independent booleans — both default to on — so all four combinations are drawn. There is no prop for it here: any `svg` child is sized by the button's own rung and spaced by its `gap`, so position is decided by where you put the element.",
render: () => (
),
},
{
name: 'Icon slots across sizes',
description:
'Both the gap and the icon itself come from the size, not from the icon element. CBAR draws a 16px glyph on `xs` and 24px from `md` up, so the jump is visible between the second and third button here — `sm` sits on the small side because CBAR has no `sm` Button to copy. Pass your own `size-*` on the icon to opt out.',
render: () => (
{(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
))}
),
},
{
name: 'Icon only',
description: 'Square sizes for a lone icon. Always pair one with `aria-label`.',
render: () => (
),
},
{
name: 'asChild',
description:
'Forwards every class to the child, so a router link can look like a button without an anchor nested inside one.',
render: () => (
),
},
],
/*
* Only what the docgen cannot see.
*
* `variant`, `colorPalette`, `size` and `asChild` used to be restated here in
* full; they are now generated from the types by `scripts/gen-props.mjs`,
* including their defaults and their prose — the descriptions moved into
* JSDoc on the cva keys in `button.tsx`, where they also reach a consumer's
* editor rather than only this page.
*
* `disabled` is React's, declared in `@types/react`, and the generator emits
* only what the kit declares itself. So it is added here, which is exactly
* what `Entry.props` is for — see `registry/props.ts`.
*/
props: [
{
name: 'disabled',
type: 'boolean',
default: 'false',
description: 'Standard button attribute. Also honoured as aria-disabled.',
},
],
spec: {
caption:
'Straight from CBAR\'s Button component set. Note the icon steps 16 → 24px at `md`: CBAR draws a small glyph only on `xs`. `sm` is the one rung CBAR does not draw for Button — it jumps xs → md — so it is filled in at the height CBAR\'s IconButton uses, keeping a small button and a small icon button aligned, and it keeps the 16px icon that is all a 36px box has room for.',
head: ['Size', 'Height', 'Padding X', 'Gap', 'Text', 'Icon', 'Radius'],
rows: [
['xs', '32px', '10px', '4px', '12px', '16px', '4px'],
['sm', '36px', '12px', '6px', '14px', '16px', '4px'],
['md', '40px', '16px', '8px', '14px', '24px', '4px'],
['lg', '48px', '20px', '10px', '16px', '24px', '4px'],
['xl', '56px', '16px', '10px', '18px', '24px', '4px'],
],
},
};