The <dsgn-button> component provides interactive buttons with multiple visual
appearances and sizes. Buttons can function as standard click targets, as links
when an href is provided, or as form controls that submit and reset.
Usage
<dsgn-button appearance="solid">Click me</dsgn-button>
Import the component module in your application entrypoint:
import '@ds-gn/ui/button';
Playground
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| appearance | 'solid' | 'outline' | 'ghost' | 'link' | 'inline' | 'mono-solid' | 'mono-outline' | 'gradient' |
'solid' |
Visual treatment. |
| button-weight | 'normal' | 'medium' | 'semibold' | 'bold' |
'semibold' |
Label font weight. |
| size | 'sm' | 'md' | 'lg' |
'md' |
Control size. |
| surface | 'light' | 'dark' |
'light' |
Semantic token surface to use. |
| href | string |
'' |
When set, renders the component as a link (<a>). |
| target | '_self' | '_blank' |
'_self' |
Target when rendered as a link. _blank automatically adds noopener noreferrer. |
| rel | string |
'' |
Extra rel tokens for link mode, merged with the ones _blank forces. |
| icon-name | IconName | '' |
'' |
Icon to render, by name. Requires the icon registry (see below). |
| icon-position | 'leading' | 'trailing' | 'only' |
'leading' |
Icon position relative to the label. Icon-only buttons require an aria-label. |
| icon | SVGTemplateResult |
undefined |
Icon as a Lit template. Property-only (no attribute); wins over icon-name. |
| type | 'button' | 'submit' | 'reset' |
'button' |
Form behavior on activation. Ignored in link mode. |
| disabled | boolean |
false |
Blocks activation and marks the control inert. |
| loading | boolean |
false |
Busy state: spinner, aria-busy, activation blocked — but still focusable. |
| name | string |
'' |
Submitted with the form when this button is the submitter. |
| value | string |
'' |
Value paired with name on submission. |
button-weight, icon-name, and icon-position are the attribute names; the
matching JavaScript properties are buttonWeight, iconName, and
iconPosition.
Slots
| Slot | Description |
|---|---|
| (default) | Button label content. |
Methods
| Method | Description |
|---|---|
formDisabledCallback(disabled) |
Form-association lifecycle callback. The platform calls it when a <fieldset disabled> or form owner toggles the inherited disabled state. |
Examples
Appearances
<dsgn-button appearance="solid">Solid</dsgn-button>
<dsgn-button appearance="outline">Outline</dsgn-button>
<dsgn-button appearance="ghost">Ghost</dsgn-button>
<dsgn-button appearance="link">Link</dsgn-button>
<dsgn-button appearance="inline">Inline</dsgn-button>
<dsgn-button appearance="mono-solid">Mono Solid</dsgn-button>
<dsgn-button appearance="mono-outline">Mono Outline</dsgn-button>
<dsgn-button appearance="gradient">Gradient</dsgn-button>
Sizes
<dsgn-button size="sm">Small</dsgn-button>
<dsgn-button size="md">Medium</dsgn-button>
<dsgn-button size="lg">Large</dsgn-button>
As a link
<dsgn-button href="/docs" appearance="solid">Go to docs</dsgn-button>
Icons
Two ways in. icon-name is markup, so it survives a CMS or a copy-paste — but
names resolve through a registry you populate once at app entry:
import { Icon } from '@ds-gn/ui/icon';
import * as icons from '@ds-gn/ui/icon/icons';
Icon.registerIcons(icons); // or just the ones you use, to keep the bundle small
<dsgn-button icon-name="arrowRight" icon-position="trailing"
>Get started</dsgn-button
>
<dsgn-button
icon-name="search"
icon-position="only"
aria-label="Search"
></dsgn-button>
icon takes a Lit template instead. It needs no registry and tree-shakes to the
one icon you import, but it can only be set from JS:
import { arrowRight } from '@ds-gn/ui/icon/icons';
html`<dsgn-button .icon=${arrowRight}>Get started</dsgn-button>`;
If both are set, icon wins.
Disabled and loading
<dsgn-button disabled>Disabled</dsgn-button>
<dsgn-button loading>Saving</dsgn-button>
Forms
<dsgn-button> is form-associated, so type="submit" and type="reset" reach an
enclosing <form> even though the real <button> lives in the shadow root:
<form>
<dsgn-input name="email" type="email"></dsgn-input>
<dsgn-button type="submit" name="intent" value="subscribe"
>Subscribe</dsgn-button
>
</form>
The name/value pair is contributed only for the button that was activated,
matching a native submit button. The form owner’s disabled state (e.g. a
<fieldset disabled>) propagates to the component without touching its own
disabled attribute, so re-enabling the fieldset restores it.
SubmitEvent.submitter is preserved: a form-associated custom element cannot be
passed to requestSubmit(), so submission is driven by activating a throwaway
native submit button inside the host. Handlers can recover the component from it:
form.addEventListener('submit', (event) => {
const button = event.submitter?.closest('dsgn-button');
});
Disabled vs loading
disabledsets the nativedisabledattribute on the inner<button>. In link mode it dropshrefand setsaria-disabled="true"instead, since<a>has no native disabled state.loadingblocks activation and setsaria-busy="true"but deliberately leaves the control focusable, so keyboard focus is not lost while an async action runs. It swaps the icon for a spinner (or leads the label when there is no icon), and the spin honorsprefers-reduced-motion. In link mode thehrefis dropped while busy — aclickguard alone would not stop a middle-click’sauxclickfrom opening the target — andtabindex="0"keeps the anchor focusable.
Styling
Buttons use the semantic --radius-button token for their corner radius. If your
application does not load the token theme stylesheet, they fall back to a fully
rounded pill shape. Define --radius-button to customize the shape:
:root {
--radius-button: 0.5rem;
}
Accessibility
- Ensure the slot text describes the action (avoid ambiguous labels like “Click”).
When
hrefis set, the component renders an<a>and inherits link semantics. - Icon-only buttons (
icon-position="only") require anaria-label. - For destructive actions, pair the button with surrounding context or add accessible description text.
Usage patterns
- Use
appearance="solid"for the main action in a view andappearance="outline"orappearance="ghost"for supporting actions. - Prefer
hrefwhen navigating and omithreffor in-page actions.