@kit-ng-ui/button
v0.2.0
Published
Kit UI Button component — ant-design feature parity.
Readme
@kit-ng-ui/button
The Button component for Kit UI. Mirrors ant-design's Button API on Angular standalone + signals.
Install
pnpm add @kit-ng-ui/button @kit-ng-ui/core @kit-ng-ui/iconsStyles
Import the package's stylesheet once at the app level (alongside @kit-ng-ui/core/styles):
// app styles.scss
@use '@kit-ng-ui/core/styles' as *;
@use '@kit-ng-ui/button/styles' as button;Namespaces must be distinct from other @kit-ng-ui/<pkg>/styles imports (Sass collapses the default namespace from the last path segment).
Use
import { Component } from '@angular/core';
import { KitButtonComponent, KitButtonGroupComponent } from '@kit-ng-ui/button';
@Component({
standalone: true,
imports: [KitButtonComponent, KitButtonGroupComponent],
template: `
<kit-button type="primary">Primary</kit-button>
<kit-button type="default">Default</kit-button>
<kit-button type="dashed">Dashed</kit-button>
<kit-button type="text">Text</kit-button>
<kit-button type="link" href="/docs">Link</kit-button>
<kit-button type="primary" size="lg" prefix="check">Confirm</kit-button>
<kit-button type="default" prefix="filter" suffix="chevron-down">Filter</kit-button>
<kit-button type="primary" loading>Submitting</kit-button>
<kit-button type="primary" danger>Delete</kit-button>
<kit-button shape="circle" prefix="plus" type="primary" ariaLabel="Add" />
<kit-button-group>
<kit-button>Left</kit-button>
<kit-button>Mid</kit-button>
<kit-button>Right</kit-button>
</kit-button-group>
`,
})
export class ButtonDemo {}API
<kit-button>
| Input | Type | Default | Description |
| ----------- | -------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------- |
| type | 'default' \| 'primary' \| 'dashed' \| 'text' \| 'link' | 'default' | Visual variant |
| size | 'sm' \| 'md' \| 'lg' | 'md' | Control density |
| shape | 'default' \| 'circle' \| 'round' | 'default' | Corner radius / aspect ratio |
| danger | boolean | false | Switch type to a destructive color |
| ghost | boolean | false | Transparent background for dark surfaces |
| block | boolean | false | Fill parent width |
| loading | boolean | false | Show spinner + block clicks; stays focusable & aria-busy (not natively disabled) |
| disabled | boolean | false | Native disabled state (inert, out of tab order) |
| prefix | string \| null | null | Leading icon name from @kit-ng-ui/icons registry |
| suffix | string \| null | null | Trailing icon name. Combine with prefix for both ends |
| htmlType | 'button' \| 'submit' \| 'reset' | 'button' | Native type attribute (when not a link) |
| href | string \| null | null | If set, render as <a> instead of <button> |
| target | string \| null | null | Anchor target attribute |
| rel | string \| null | null | Anchor rel attribute |
| ariaLabel | string \| null | null | Required for icon-only buttons (a11y) |
<kit-button-group>
Lays out adjacent buttons in a row with a consistent 8px gap. Each child keeps its own border and corner radius. No inputs.
Override the spacing per instance with the --kit-btn-group-gap CSS custom property:
<kit-button-group style="--kit-btn-group-gap: 4px;">
<kit-button>One</kit-button>
<kit-button>Two</kit-button>
</kit-button-group>Behavior notes
- When
loading=true, the component renders theloadingicon (spin) and, crucially, keeps the button focusable — it is not natively disabled. A native-disabled element is removed from the tab order and loses focus the instant it becomes disabled, which drops focus to<body>on the common submit/accept/decline pattern (WCAG 2.4.3 Focus Order). Instead, a loading button exposesaria-busy="true"+aria-disabled="true"and blocks activation by suppressing the nativeclick(and its default action, e.g. form submit) while loading. Double-submit protection is preserved: a consumer's(click)handler never fires while[loading]. - When
disabled=true, the underlying<button>gets the nativedisabledattribute (truly inert, out of the tab order). If a button is bothdisabledandloading,disabledwins (native disabled). danger×typeproduces all expected combinations (primary danger, default danger, link danger, text danger, dashed danger).ghostis intended for placement over dark / colored backgrounds — pair withtype="primary"for a colored border-only button.- Icon-only buttons (no projected text) get the
kit-btn--icon-onlymodifier automatically to make padding square. - When
hrefis set, the component renders an<a>and ignoreshtmlType; for accessibility,aria-disabledis applied (and the link is non-navigable) whendisabledorloading. - Icons are referenced by name via
[prefix](leading) and[suffix](trailing). To use a custom icon, register it withprovideKitIcons(...)at app bootstrap (see@kit-ng-ui/icons). There is no[slot=icon]projection — projected content is treated as the button label.
Changelog
0.2.0
- a11y fix (WCAG 2.4.3): a
loadingbutton is no longer mapped to the nativedisabledattribute. It now stays focusable and exposesaria-busy="true"+aria-disabled="true"instead of dropping focus to<body>when it becomes busy mid-submit. Only a genuinelydisabledbutton is natively disabled/inert;disabledstill wins when both are set. - Backward compatible: clicks are still suppressed while
[loading](and[disabled]) — the nativeclickand its default action are guarded — so existing double-submit protection is preserved. The only observable change is that a loading button keeps focus and announcesaria-busy.
