Button

Primary actions with variants, text sizes, icon sizes, and a plain icon-only style.

Also known as: cta, action button, icon button, plain icon button, outline button, transparent outline

Installation

Install with the CLI, or copy the component source into your project.

Add button (npm)

npx --yes -p @default-file/ui df-ui add button

Default

Primary action button.

Variants

All visual variants.

Outline transparent

Outline only. Set transparent to drop the resting fill.

Sizes

Text button sizes from xs to 2xl.

Chrome

Override padding, height, width, type size, line height, font, and radius on one button. Props write --df-button-* on the host. Size still supplies defaults when a prop is omitted.

Icon sizes

Square icon-only controls from icon-2xs to icon-2xl. These keep the standard control plate. Use the Plain icon demo for chrome without a resting plate.

Plain icon

Icon-only chrome with no resting plate. The hit box matches the glyph; hover and focus expand a soft pad without layout shift. Pair with icon-2xs to icon-2xl and an aria-label. Prefer over ghost on media and dense overlays.

With icon

Icon only control, plus leading and trailing icons on text buttons including xs.

Slots

Leading and trailing accept any node: badge, counter, close, avatar.

Loading

Muted appearance. Spinner in the leading or trailing icon slot. Works on every variant except link. Icon only sizes replace the icon.

Loading solid

Solid appearance. Background stays at full strength, the label fades, and the Spinner stays fully visible.

Badge edge

Corner count with badgeSide end and badgePosition edge (defaults). Sits on the trailing top corner. Badge contrast flips on the filled default variant.

Badge start

Corner count with badgeSide start. Places the badge on the leading top corner instead of the usual trailing side.

Badge inset

Corner count with badgePosition inset. Pulls the badge a notch inside the button on the trailing side.

Properties

Primary actions with variants, text and icon sizes, optional leading or trailing content, loading state, and a corner count badge. plain is the icon-only variant with no resting plate. Use transparent on outline to drop the resting fill.

Button

PropTypeDefaultNotes
variant"default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "plain""default"Visual style of the button. plain is icon-only chrome with no resting plate; hover and focus expand a soft pad around the glyph without shifting layout. Use ghost for labeled transparent actions on UI chrome. Prefer plain on media, gradients, and dense overlays. Give plain buttons an aria-label. link is inline text with no control height or horizontal padding. On outline, set transparent to drop the resting fill.
size"default" | "xs" | "sm" | "lg" | "xl" | "2xl" | "icon" | "icon-2xs" | "icon-xs" | "icon-sm" | "icon-lg" | "icon-xl" | "icon-2xl""default"Text sizes use padding, type size, and line height (xs to 2xl). Height follows those tokens unless you set height. Icon sizes are square controls (icon-2xs to icon-2xl) on the form control height tokens. Override padding, size, type, font, and radius with chrome props or --df-button-* variables. plain requires an icon size; the resting box matches the glyph for that step. If plain is paired with a text size, size falls back to icon-xs.
underlinebooleantrueLink variant only. When true, show underline on hover. Set false to keep the label plain on hover.
transparentbooleanfalseOutline variant only. When true, drop the resting fill (data-transparent). Theme the filled plate with --df-button-outline-fill. Hover and expanded washes stay for affordance. Ignored on other variants.
leadingReactNode-Content before the label, such as an icon.
trailingReactNode-Content after the label, such as an icon or badge.
loadingbooleanfalseShows a Spinner in the icon area, keeps the label, and disables the control. Unsupported on the link variant. Supported on plain icon sizes.
loadingPlacement"leading" | "trailing""leading"Which icon slot shows the Spinner while loading. Ignored for icon-only sizes, which replace the icon child.
loadingAppearance"muted" | "solid""muted"muted fades the whole control like disabled. solid keeps the default background, fades the label only, and leaves the Spinner at full opacity.
badgenumber | string-Corner count badge anchored to the top end of the button. Count ink is optically centered to cap height with text-box when available, and a 1cap line box otherwise. Hidden when empty, null, or 0. Include the count in aria-label for icon buttons.
badgeVariant"default" | "secondary" | "destructive" | "outline" | "ghost" | "link"-Badge visual style. Defaults to secondary on the default button variant, otherwise default, so the count stays readable on dark fills.
badgePosition"edge" | "inset""edge"edge sits on the corner. inset pulls the badge a notch inside the button.
badgeSide"start" | "end""end"Which top corner hosts the badge. end is the trailing side (right in left to right layouts). start is the leading side.
disabledboolean-Disables the button.
classNamestring-Additional styles.

Chrome overrides

String props write --df-button-* on the host. Prefer token expressions such as var(--df-text-sm), var(--df-font-sans), var(--radius-md), or calc(4 * var(--spacing-unit)). Size still supplies defaults when a prop is omitted. On dfButtonClass hosts, pass the same values through dfButtonChromeStyle into style.

PropTypeDefaultNotes
paddingstring-Padding on all sides. Sets --df-button-padding-block-start, --df-button-padding-block-end, --df-button-padding-inline-start, and --df-button-padding-inline-end.
paddingXstring-Horizontal padding. Sets --df-button-padding-inline-start and --df-button-padding-inline-end. Overrides padding on those sides.
paddingYstring-Vertical padding. Sets --df-button-padding-block-start and --df-button-padding-block-end. Overrides padding on those sides.
paddingTopstring-Top padding. Sets --df-button-padding-block-start and wins over paddingY and padding.
paddingRightstring-Trailing-edge padding. Sets --df-button-padding-inline-end and wins over paddingX and padding.
paddingBottomstring-Bottom padding. Sets --df-button-padding-block-end and wins over paddingY and padding.
paddingLeftstring-Leading-edge padding. Sets --df-button-padding-inline-start and wins over paddingX and padding.
heightstring-Control height. Default auto so height follows padding and line height. Sets --df-button-height.
widthstring-Control width. Default auto so width follows content and padding. Sets --df-button-width.
fontSizestring-Label type size. Prefer type tokens such as var(--df-text-sm). Sets --df-button-font-size.
lineHeightstring-Label line height. Prefer leading tokens such as var(--df-leading-5). Sets --df-button-line-height.
fontFamilystring-Label font family. Prefer family tokens such as var(--df-font-sans) or var(--df-font-mono). Sets --df-button-font-family.
fontWeightstring-Label font weight. Prefer weight tokens such as var(--df-font-weight-medium). Sets --df-button-font-weight.
radiusstring-Corner radius. Prefer radius tokens such as var(--radius-md). Default is --radius-4xl. Sets --df-button-radius.

Helpers

Class helper for applying button styles to a host that is not a button.

PropTypeDefaultNotes
dfButtonClass(opts?: { variant?, size?, className? }) => string-Builds the same class string Button uses internally. Resolves plain with a non-icon size to icon-xs, matching Button. For link hosts, set the underline data attribute to hover or none to match the underline prop. For outline hosts without a resting fill, set data-transparent.
dfButtonChromeStyle(opts?: ButtonChromeProps) => CSSProperties-Writes the same --df-button-* variables the chrome props set on Button. Merge into style on a dfButtonClass host.

Tokens

Theme defaults live on :root. Override these globally or on a local host.

TokenTypeDefaultNotes
--spacing-unitCSS length0.25remBase unit for padding, gap, and icon button size.
--primaryCSS colorvar(--df-neutral-850, var(--df-neutral-900))Default variant fill.
--primary-foregroundCSS colorvar(--df-neutral-0)Default variant label.
--secondaryCSS colorvar(--df-neutral-50)Secondary variant fill.
--secondary-foregroundCSS colorvar(--df-neutral-850, var(--df-neutral-900))Secondary variant label.
--destructiveCSS coloroklch(0.577 0.245 27.325)Destructive variant fill.
--borderCSS colorvar(--df-neutral-100)Outline variant border.
--df-button-outline-fillCSS colorcolor-mix(in oklch, var(--input) 30%, var(--background))Outline variant resting fill from the theme tables (:root and .dark). Overridden when transparent is true.
--df-button-outline-fill-hoverCSS colorcolor-mix(in oklch, var(--input) 50%, var(--background))Outline variant hover fill from the theme tables (:root and .dark).
--mutedCSS colorvar(--df-neutral-50)Ghost variant hover fill.
--ringCSS colorvar(--df-neutral-400)Focus ring color.
--df-button-plain-hover-outsetCSS lengthcalc(1 * var(--spacing-unit))How far the plain icon hover pad expands beyond the glyph.
--df-button-plain-hover-fillCSS colorcolor-mix(in oklch, var(--foreground) 14%, transparent)Plain icon hover pad fill.
--df-button-plain-hover-radiusCSS lengthvar(--radius-md)Corner radius of the plain icon hover pad.
--df-affordance-size-2xsCSS lengthcalc(2 * var(--spacing-unit))Glyph size for icon-2xs and plain icon-2xs.
--df-press-offsetCSS length1pxActive press translate distance.
--df-underline-offsetCSS length4pxLink variant underline offset.
--df-button-radiusCSS lengthvar(--radius-4xl)Corner radius. Default is --radius-4xl. Set by the radius chrome prop.
--radius-4xlCSS lengthcalc(var(--radius) * 2.6)Default corner radius.
--df-button-badge-sizeCSS lengthcalc(4 * var(--spacing-unit))Corner badge height and minimum width.
--df-button-badge-pad-inlineCSS lengthcalc(1 * var(--spacing-unit))Horizontal padding inside the corner badge for longer counts.
--df-button-badge-insetCSS lengthcalc(1 * var(--spacing-unit))Offset used when badgePosition is inset.
--df-button-font-familyCSS font-familyvar(--df-font-sans)Label font family.
--df-button-font-weightCSS font-weightvar(--df-font-weight-medium)Label font weight.
--df-button-height-mdCSS lengthautoDefault text size height. Auto follows padding and line height. Same pattern on --df-button-height-xs to --df-button-height-2xl.
--df-button-width-mdCSS lengthautoDefault text size width. Auto follows content and padding. Same pattern on --df-button-width-xs to --df-button-width-2xl.
--df-button-font-size-xsCSS lengthvar(--df-text-xs)xs text size. Maps to --df-text-xs (0.75rem).
--df-button-font-size-smCSS lengthvar(--df-text-sm)sm text size. Maps to --df-text-sm (0.875rem).
--df-button-font-size-mdCSS lengthvar(--df-text-sm)Default text size. Maps to --df-text-sm (0.875rem).
--df-button-font-size-lgCSS lengthvar(--df-text-sm)lg text size. Maps to --df-text-sm (0.875rem).
--df-button-font-size-xlCSS lengthvar(--df-text-sm)xl text size. Maps to --df-text-sm (0.875rem).
--df-button-font-size-2xlCSS lengthvar(--df-text-sm)2xl text size. Maps to --df-text-sm (0.875rem).
--df-button-line-height-xsCSS lengthvar(--df-leading-4)xs line height. Maps to --df-leading-4 (1rem).
--df-button-line-height-smCSS lengthvar(--df-leading-4)sm line height. Maps to --df-leading-4 (1rem).
--df-button-line-height-mdCSS lengthvar(--df-leading-5)Default line height. Maps to --df-leading-5 (1.25rem).
--df-button-line-height-lgCSS lengthvar(--df-leading-5)lg line height. Maps to --df-leading-5 (1.25rem).
--df-button-line-height-xlCSS lengthvar(--df-leading-5)xl line height. Maps to --df-leading-5 (1.25rem).
--df-button-line-height-2xlCSS lengthvar(--df-leading-5)2xl line height. Maps to --df-leading-5 (1.25rem).
--df-button-padding-block-xsCSS lengthcalc(1 * var(--spacing-unit))xs vertical padding. One spacing unit (4px).
--df-button-padding-block-smCSS lengthcalc(2 * var(--spacing-unit))sm vertical padding. Two spacing units (8px).
--df-button-padding-block-mdCSS lengthcalc(2 * var(--spacing-unit))Default vertical padding. Two spacing units (8px).
--df-button-padding-block-lgCSS lengthcalc(2.5 * var(--spacing-unit))lg vertical padding. Two and a half spacing units (10px).
--df-button-padding-block-xlCSS lengthcalc(3 * var(--spacing-unit))xl vertical padding. Three spacing units (12px).
--df-button-padding-block-2xlCSS lengthcalc(3.5 * var(--spacing-unit))2xl vertical padding. Three and a half spacing units (14px).
--df-button-padding-inline-xsCSS lengthcalc(2.5 * var(--spacing-unit))xs horizontal padding. Two and a half spacing units (10px).
--df-button-padding-inline-smCSS lengthcalc(4 * var(--spacing-unit))sm horizontal padding. Four spacing units (1rem).
--df-button-padding-inline-mdCSS lengthcalc(4 * var(--spacing-unit))Default horizontal padding. Four spacing units (1rem).
--df-button-padding-inline-lgCSS lengthcalc(5 * var(--spacing-unit))lg horizontal padding. Five spacing units (1.25rem).
--df-button-padding-inline-xlCSS lengthcalc(6 * var(--spacing-unit))xl horizontal padding. Six spacing units (1.5rem).
--df-button-padding-inline-2xlCSS lengthcalc(7 * var(--spacing-unit))2xl horizontal padding. Seven spacing units (1.75rem).
--df-button-padding-inline-startCSS lengthvar(--df-button-padding-inline-md)Default text size padding on the leading edge. Aliases --df-button-padding-inline-md.
--df-button-padding-inline-endCSS lengthvar(--df-button-padding-inline-md)Default text size padding on the trailing edge. Aliases --df-button-padding-inline-md.
--df-button-padding-inline-icon-xsCSS lengthcalc(2 * var(--spacing-unit))xs icon-adjacent inline padding. Two spacing units (8px).
--df-button-padding-inline-icon-smCSS lengthcalc(3 * var(--spacing-unit))sm icon-adjacent inline padding. Three spacing units (0.75rem).
--df-button-padding-inline-icon-mdCSS lengthcalc(3 * var(--spacing-unit))Default icon-adjacent inline padding. Three spacing units (0.75rem).
--df-button-padding-inline-icon-lgCSS lengthcalc(4 * var(--spacing-unit))lg icon-adjacent inline padding. Four spacing units (1rem).
--df-button-padding-inline-icon-xlCSS lengthcalc(5 * var(--spacing-unit))xl icon-adjacent inline padding. Five spacing units (1.25rem).
--df-button-padding-inline-icon-2xlCSS lengthcalc(6 * var(--spacing-unit))2xl icon-adjacent inline padding. Six spacing units (1.5rem).
--df-button-padding-inline-start-iconCSS lengthvar(--df-button-padding-inline-icon-md)Default text size leading-edge padding when a leading icon is present. Aliases --df-button-padding-inline-icon-md.
--df-button-padding-inline-end-iconCSS lengthvar(--df-button-padding-inline-icon-md)Default text size trailing-edge padding when a trailing icon is present. Aliases --df-button-padding-inline-icon-md.
--z-raisednumber1Stacking level for the corner badge.
--df-label-line-heightCSS line-heightvar(--df-leading-none)Line box for label flex centering. Defaults to --df-leading-none. When text-box is unavailable and the cap unit is supported, the kit sets this to 1cap so flex centering matches cap-height ink.
--df-corner-shapeCSS corner-shapevar(--df-corner-shape-round)Theme corner curve for all kit chrome. round = circular arcs; smooth = continuous squircle. Set with df-ui init --corner-shape, or override on :root. Default round.