Buttons

Real <button> elements styled with the .ds-btn family. Hover, active, and focus states use native pseudoclasses.

Variants

Primary for the main action; secondary for cancel/dismiss; ghost for inline edits; ghost-danger for destructive actions.

Solid color variants

Filled buttons with the same gradient + border + hard-offset shadow treatment as primary, drawn from status and marketing colors. Use sparingly — primary should still be the dominant action on most surfaces.

Ghost color hover

Default ghost is text-only. On hover, the button gains an outline that matches its text color and a transparent fill of that same color.

Sizes

States

Hover and active states use real CSS pseudoclasses — interact with the buttons to see them.

Reveal pattern

Use this pattern any time multiple CTAs appear in a list. Resting state: muted (looks secondary). Hover the parent — only one button blooms to primary. Reduces the number of CTAs drawing the user's attention at once.

Stripe
Staff Engineer · San Francisco
Senior Product Designer
Acme Robotics · 2022 — Present
Product Designer
Northbeam · 2019 — 2022
UX Designer
Lumen Labs · 2017 — 2019

Follow-up: a v-reveal-parent directive could ship later so consumers don't need to remember the class name on the wrapping element.

With icons

Lead with an icon when the action is concrete (download, print, send) and the label needs reinforcement. Production source for the download trio: src/components/resume-builder/DownloadResumeButton.vue. The wrapper collapses into direct DSBtn usage with a leading icon — no new component needed.

Focus toolbar

Inline editor controls that appear when the row gains focus and stay for 5 seconds after focus leaves — long enough for a click to a confirm dialog without the toolbar vanishing mid-click. The pattern is a directive (v-focus-toolbar) that toggles is-toolbar-active on the host. Pair with absolute-positioned descendant chips. Used by DSHighlightRow; reusable anywhere a row needs ephemeral row-level actions (move up/down, delete) without the chrome bloat of always-on controls.

Click into the textarea, then click outside — the toolbar stays for 5 seconds. The delete button opens a useSpeedbump-driven confirm dialog (same composable the production app uses).

Remove highlight

Icon-only buttons

The .ds-icon-btn utility class shapes any DSBtn variant into a 1.875rem square with the icon centered. Pair with an aria-label so the action stays accessible. The dialog close button is the canonical use; the same class works for trash, more-menu, settings, and plus glyphs across the app.