Button
Free9 variants × 6 styles × 5 sizes × 3 shapes — solid, outline, soft, ghost, link and gradient with loading states and icon support.
import { SvButtonComponent } from '@styloviz/button';Demo & usage
Basic usage
Live, interactive instance.
More examples
Styles & variants
Mix btnStyle with a semantic variant to cover every action weight.
<sv-button label="Solid" variant="primary" /> <sv-button label="Outline" btnStyle="outline" variant="primary" /> <sv-button label="Ghost" btnStyle="ghost" variant="secondary" /> <sv-button label="Gradient" btnStyle="gradient" variant="primary" /> <sv-button label="Danger" variant="danger" />
Icons, counter & sizes
Lead/trail icons, a counter badge, and the size scale.
<sv-button label="New" icon="plus" /> <sv-button label="Inbox" trailingIcon="chevron-down" [counter]="12" /> <sv-button label="Small" size="sm" /> <sv-button label="Large" size="lg" shape="pill" />
Custom / third-party icons
`iconTemplate` / `trailingIconTemplate` accept a TemplateRef, so you can render any third-party icon component, an <img>, an icon font, or a multi-color SVG — not just single-path currentColor icons.
<ng-template #rocket> <img src="/assets/icons/rocket.svg" alt="" /> <!-- or a real icon component: <lucide-icon name="rocket" /> --> </ng-template> <sv-button label="Launch" [iconTemplate]="rocket" />
Link button
Set href to render a semantic anchor that still looks like a button.
<sv-button label="View docs" href="/docs" target="_blank" btnStyle="soft" />
Accessibility & safe links
target="_blank" auto-adds rel="noopener noreferrer". Use ariaLabel for icon-only buttons, counterLabel so badges are announced, and name/value in multi-button forms.
<sv-button href="https://angular.dev" target="_blank" label="Docs" /> <sv-button iconPosition="only" icon="plus" ariaLabel="Add item" /> <sv-button iconPosition="only" label="Inbox" [counter]="5" counterLabel="unread" icon="plus" /> <sv-button type="submit" name="action" value="publish" label="Publish" />
When to use
- Triggering an in-page action: submit, save, open a dialog, confirm a step.
- You need a single, visually dominant call-to-action — use one primary button per view.
- For navigation to another URL, set `href` so it renders a real anchor.
Async states
- loading
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| variant | ButtonVariant | 'primary' | Semantic color/intent: primary, secondary, success, danger, etc. |
| btnStyle | ButtonStyle | 'solid' | Visual treatment: solid, soft, outline, ghost, link or gradient. |
| size | ButtonSize | 'md' | Button size from xs to xl. |
| shape | ButtonShape | 'rounded' | Corner style: rounded, pill or square. |
| block | boolean | false | Stretch to 100% width. |
| elevated | boolean | false | Add drop shadow. |
| label | string | '' | Button text. Omit when projecting custom content. |
| icon | string | '' | Icon-library NAME for the built-in leading/trailing icon — e.g. `'plus'`. Ignored when `iconTemplate` is set. BREAKING (icon sweep): was `iconPath`, a raw SVG `d` string. A name resolves through `@styloviz/icons`, so `check:icons` catches a typo that a `d` string rendered as a blank button. ⚠️ The old attribute was usually written STATICALLY (`iconPath="M12 4.5v15…"`), and Angular silently ignores an unknown static attribute — so a missed call site renders no icon rather than failing the build. All 157 in-repo sites were rewritten tag-scoped. |
| trailingIcon | string | '' | Icon-library NAME for the secondary/dual trailing icon. Ignored when `trailingIconTemplate` is set. Was `trailingIconPath`. |
| iconTemplate | ButtonIconTemplate | null | Custom template for the primary icon — use this to render a third-party icon component (e.g. lucide-angular, ngx-heroicons), an `<img>`, an icon font `<i>`, or arbitrary custom SVG instead of the built-in `icon`. Positioned per `iconPosition()`. Takes precedence over `icon` when set. |
| trailingIconTemplate | ButtonIconTemplate | null | Custom template for the secondary/dual trailing icon. Takes precedence over `trailingIcon` when set. See `iconTemplate` for usage. |
| iconPosition | ButtonIconPos | 'leading' | Where the main icon sits relative to the label. |
| counter | number | null | null | Numeric counter badge. null = hidden. |
| counterMax | number | 99 | Value above which the counter shows "{max}+". |
| counterLabel | string | '' | Noun describing the counter for screen readers, e.g. "unread". |
| type | ButtonType | 'button' | Native button type when not in link mode. |
| disabled | boolean | false | Disable interaction and dim the button. |
| loading | boolean | false | Show a loading indicator and block activation. |
| loadingStyle | ButtonLoader | 'spinner' | Loading indicator style: spinner or dots. |
| loadingLabel | string | '' | Optional text shown beside the loading indicator. |
| preventDoubleSubmit | boolean | false | Ignore a second activation that lands within `doubleSubmitWindowMs` of the one before it. |
| doubleSubmitWindowMs | number | 400 | How long a repeat activation is ignored for, in milliseconds. |
| announceLoading | boolean | true | Announce the loading state in a live region. |
| href | string | '' | When set, renders an <a> anchor instead of a <button>. |
| target | string | '_self' | Anchor target (e.g. _blank) when href is set. |
| rel | string | '' | Anchor rel. `noopener noreferrer` is auto-added for target="_blank". |
| download | string | null | null | Anchor download attribute (filename or empty string to use the URL). |
| name | string | '' | Native `name` for the button when submitted as part of a form. |
| value | string | '' | Native `value` submitted with `name` for multi-button forms. |
| ariaLabel | string | '' | Explicit accessible name. Required for icon-only buttons; overrides label. |
| pressed | boolean | null | null | Toggle state, published as `aria-pressed`. A BUTTON THAT STAYS ON IS A TOGGLE, AND A TOGGLE HAS TO SAY SO. Filter chips, "pin", "mute", "bold" — every one of them is a button whose variant changes to show it is active, and to a screen reader that change is invisible: the name is identical in both states, so the control reads as an ordinary button that does nothing. `aria-pressed` is the whole difference between "Filter" and "Filter, pressed". `null` — the default — omits the attribute entirely, because a button that is not a toggle must NOT claim to be one. `aria-pressed="false"` on an ordinary button tells the reader there is a state to toggle. |
| title | string | '' | Native tooltip / title attribute. |
| autofocus | boolean | false | Autofocus the control on render. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| clicked | MouseEvent | Emitted on click (suppressed while disabled or loading). |
| focused | FocusEvent | Emitted when the control receives focus. |
| blurred | FocusEvent | Emitted when the control loses focus. |
Customization & theming
- Switch the look with `variant` (primary, secondary, success…) and `btnStyle` (solid, soft, outline, ghost, link, gradient).
- Size with `size` (xs–xl) and shape with `shape` (rounded, pill, square); stretch with `block` and lift with `elevated`.
- Add icons via `icon` / `trailingIcon` — icon-library names such as `plus` or `chevron-down`, resolved through `@styloviz/icons` — and a badge with `counter`; tune overflow with `counterMax` and announce it with `counterLabel`.
- Bring your own icon with `iconTemplate` / `trailingIconTemplate` — pass a `TemplateRef` to render any third-party icon component, `<img>`, icon font, or multi-color SVG; it takes precedence over `icon` / `trailingIcon` when set.
- Loading state via `[loading]="true"` with `loadingStyle` (spinner · dots · pulse) and an optional `loadingLabel`.
- Link mode with `href` / `target` / `rel` / `download`; form integration with `name` / `value`; tooltip with `title`.
Best practices
- Do: Reserve `variant="primary"` for the single most important action on the screen.
- Do: Set `[loading]="true"` during async work so the button blocks duplicate submits.
- Don't: Avoid stacking multiple solid primary buttons side by side — downgrade secondary actions to soft/ghost.
- Tip: Use `icon` with a concise `label` rather than icon-only buttons unless you also set `ariaLabel`.
Accessibility
- Renders a native <button> (or <a> when `href` is set) so keyboard and screen-reader semantics work out of the box.
- Set `ariaLabel` for an explicit accessible name — required for icon-only buttons; the `counter` is folded into it (e.g. "Inbox, 5 unread") via `counterLabel`.
- Disabled and loading states set `aria-disabled` / `aria-busy` and block activation; disabled links are removed from the tab order.
- External links opening a new tab automatically receive `rel="noopener noreferrer"` to prevent reverse tabnabbing.
- A visually-hidden status label announces the loading state when no text is visible. Visible focus ring with a theme-aware offset in light and dark mode.
Feedback on Button
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.