Installation
import { WrButton } from 'ngwr/button';
@Component({ imports: [WrButton] })
export class MyComponent {}Basic usage
The same selector matches a custom element, a native button, and an anchor.
<wr-btn>Default</wr-btn>
<button wr-btn>Native button</button>
<a wr-btn>Anchor</a>Inside a form
<wr-btn> is a custom element with a button role, and no custom element submits a form — the platform submits for <button>, <input type=submit> and <input type=image> and nothing else. So it takes no type input, and Enter in a text field will not reach it either. A submit or reset button has to be the native form: <button wr-btn type=submit>. Where the element form is what you want, bind the click and call the handler yourself.
<form (ngSubmit)="save()">
<!-- Submits: a real <button>, with the type the platform reads. -->
<button wr-btn type="submit" color="primary">Save</button>
<!-- Does NOT submit: <wr-btn> is a custom element. Bind the click. -->
<wr-btn (click)="save()" color="primary">Save</wr-btn>
</form>Colors
<wr-btn color="primary">Primary</wr-btn>
<wr-btn color="success">Success</wr-btn>Outlined
<wr-btn color="primary" outlined>Outlined</wr-btn>Sizes
<wr-btn size="sm">Small</wr-btn>
<wr-btn size="md">Medium</wr-btn>
<wr-btn size="lg">Large</wr-btn>Shape
shape is rounded (default, small radius), pill (fully rounded ends) or squircle. Every button already asks for corner-shape: squircle where the browser supports it, so squircle mostly picks a larger anchor radius to make those smooth corners read — and pill deliberately opts back to a round arc, since squircle maths draws a different shape at pill radii rather than degenerating into one. Where corner-shape is unsupported the corners are ordinary arcs; [wrSquircle] is the clip-path route that works regardless — see the Squircle docs.
<!-- Three shapes -->
<wr-btn color="primary">Rounded (default)</wr-btn>
<wr-btn color="primary" shape="pill">Pill</wr-btn>
<wr-btn color="primary" shape="squircle">Squircle</wr-btn>
<!-- No corner-shape support? [wrSquircle] clips the same look everywhere.
Its own entry point: import { WrSquircle } from 'ngwr/squircle' and add
WrSquircle to imports — the attribute is inert without it. -->
<wr-btn color="primary" wrSquircle [radius]="14">Squircle</wr-btn>With icon
Pass any icon registered via provideWrIcons. iconPosition switches between start/end.
<wr-btn icon="add" color="primary">Add</wr-btn>
<wr-btn icon="download" iconPosition="end" color="success">Download</wr-btn>Disabled
<wr-btn disabled>Disabled</wr-btn>Loading
The spinner overlays the label so layout stays put. By default pointer events are blocked while loading.
<wr-btn [loading]="loading()" color="primary" (click)="loading.set(!loading())">
Click to toggle
</wr-btn>Block
Fills the parent's width.
<wr-btn color="primary" block>Full width</wr-btn>API
| Name | Description | Type | Default |
|---|---|---|---|
color | Color variant. Omit for the neutral default style. Deliberately NOT configurable app-wide: the library's own chrome binds [color]="isCurrent ? 'primary' : null", where null means neutral, and a configured intent would repaint every one of those buttons. See WrConfig. | WrColor | null | null |
size | Size variant. Unset, it resolves through provideWrConfig({ button: { size } }) and then to md. | WrButtonSize | null | 'md' |
shape | Corner treatment — rounded, pill or squircle. null (default) falls back to rounded. Inside a <wr-btn-group shape="…">, the group's shape ALWAYS wins over this input — the group enforces a consistent corner treatment across its members. | WrButtonShape | null | null |
icon | Icon name to render alongside the label. The icon is hidden while loading is true so the spinner can take its place. | WrIconName | null | null |
iconPosition | Position of the icon relative to the label. | WrButtonIconPosition | 'start' |
disabled | Disable the button. | boolean | false |
outlined | Outlined variant — colored text and border on a transparent background. | boolean | false |
block | Stretch the button to fill its parent's width. | boolean | false |
loading | Show a spinner overlaying the label. Layout is preserved. | boolean | false |
disabledWhenLoading | When loading is true and this is also true, pointer events are suppressed and the button reports as disabled to assistive tech. | boolean | true |
CSS variables
Custom properties ngwr/button publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.
| Variable | Default | Declared on |
|---|---|---|
--wr-btn-bg | var(--wr-color-surface) | .wr-btn +8 variant overrides |
--wr-btn-border | var(--wr-color-outline) | .wr-btn +6 variant overrides |
--wr-btn-color | var(--wr-color-on-surface) | .wr-btn +4 variant overrides |
--wr-btn-font-size | var(--wr-control-font-size-md) | .wr-btn +2 variant overrides |
--wr-btn-font-weight | 500 | .wr-btn |
--wr-btn-gap | 0.375rem | .wr-btn +2 variant overrides |
--wr-btn-icon-size | 1rem | .wr-btn +2 variant overrides |
--wr-btn-line-height | var(--wr-control-line-height-md) | .wr-btn +2 variant overrides |
--wr-btn-padding-x | 0.875rem | .wr-btn +2 variant overrides |
--wr-btn-padding-y | var(--wr-control-padding-y-md) | .wr-btn +2 variant overrides |
--wr-btn-radius | var(--wr-control-radius-md) | .wr-btn +4 variant overrides |