Button
Terminal-inspired button with bracket notation and 7 variants.
Installation
dgadd is not public on npm yet. Until the first release, pack @diffgazer/add from the repository and install that tarball into this app, which is what puts dgadd on pnpm exec.
The hosted registry is not public yet because r.b4r7.dev does not resolve. Use this source checkout or a local registry preview until the endpoint returns 200.
Diffgazer packages are not yet published to npm. Until the first release, pack @diffgazer/ui and @diffgazer/keys from the repository and install those tarballs.
UI components require Tailwind CSS v4. Local copy mode imports src/styles/styles.css; package mode uses @diffgazer/ui CSS once packages are available.
Usage
Examples
Variants
States
Highlighted (collection focus)
Link (as anchor)
Render-Prop
API Reference
Button
Data attributes
Accessibility
Notes
One Filled Voice
Only the primary variant is filled, and it paints the --action / --action-foreground pair. Semantic intents stay outlined — success and destructive carry meaning through colour, priority through fill — so the variant set keeps one filled voice per screen while success and destructive stay recognisable by hue alone.
--action, not --primary
The filled variant paints --action / --action-foreground, the call-to-action pair, and not --primary. They are different roles that happen to coincide in dark: --primary is monochrome emphasis (filled progress, completed steps, checked indicators) and stays mono in both themes; --action is the one place per screen a theme is allowed to spend chroma, so the light palette resolves it to the accent violet while dark keeps it white. A button that reads --primary would lose that distinction in light and turn every filled control into a call to action.
Disabled Primary
Disabled and loading primaries drop the --action fill for a half-strength solid --border edge and a --muted-foreground label rather than fading it. Fading a filled button drags its label toward the page background with it and the pair falls under 4.5:1; emptying the fill leaves the label on the ambient surface, where it keeps its own contrast in both themes, and the retained edge keeps the button's shape readable. No control in the system draws a dashed or dotted edge.
Coarse-Pointer Hit Area
On pointer:coarse the sm, md, and icon sizes extend a transparent ::before to a 44x44 effective target instead of growing: buttons live in fixed-height toolbars and panel headers where a real min-height would reflow the row. lg is already 44px tall and is left alone. Those three sizes therefore carry position:relative so the size itself is the pseudo-element's containing block — do not rely on Button being relatively positioned at lg. Two preconditions belong to the call site: no overflow-hidden ancestor between the button and the scroll root (it clips the overhang and the target silently shrinks back), and a minimum vertical gap to the next interactive row — 16px for sm, 8px for md and icon — otherwise stacked hit areas overlap and taps land on the wrong control. The extension is vertical only, so horizontal neighbours in a button row are safe; icon additionally widens by 4px per side to reach 44px across.
Bracket Mode
The bracket prop wraps the button label in [ ] characters, mimicking terminal UI conventions. When loading is true, bracket mode shows [ ... ] instead of [...].
Polymorphic Element
Use as="a" to render a semantic anchor element for navigation. The link variant is purely visual — combine it with as="a" for semantic anchor navigation.
Render-Prop Composition
Pass a function as children to control the rendered element. Button provides computed props, including an onClick activation guard. Spread them onto the rendered host so disabled and loading states prevent navigation for anchors and framework links.
Source
Install via CLI: pnpm exec dgadd add ui/button.
Highlighted source loads after this disclosure opens. Browse the source repository.