Angular
packages/ui-angular is KinetixUI's Angular implementation, packaged as
@kinetixui/angular. Its maturity is
Preview: it covers
43 of the 98
KinetixUI components today — a foundation subset, not the full catalogue —
and grows incrementally.
Install#
npm i @kinetixui/angular @kinetixui/tokens@kinetixui/tokens is a peer dependency, not a convenience: the components
spend generated CSS custom properties and never define them, so the token
contract has to be present for anything to render as designed. Load both
stylesheets before the component styles — globals.css carries colour, spacing
and radius, and extras.css carries the elevation and typography ramps the
components also use:
@import "@kinetixui/tokens/css";
@import "@kinetixui/tokens/css/extras";
@import "@kinetixui/angular/styles.css";Angular 21 is the tested and supported range (@angular/core and
@angular/forms, ^21.0.0). Every export is standalone, so a template imports
the directives it uses and nothing else — there is no NgModule.
@kinetixui/angular versions independently of @kinetixui/ui,
@kinetixui/tokens and @kinetixui/cli, which release together. Its version
number will not match theirs, and that is deliberate — it is a
Preview package on its own release
cadence, so its API may still change.
What's available#
Every component below is a real export of @kinetixui/angular. This list is
read from components.manifest.json, and CI checks every entry against the
package's public API — it can't claim a component the package doesn't ship.
- Alert
- AspectRatio
- Avatar
- AvatarGroup
- Badge
- Banner
- Button
- ButtonGroup
- Card
- Checkbox
- CircularProgress
- CodeBlock
- DescriptionList
- Empty
- Fab
- Field
- Image
- Inform
- Input
- Kbd
- Label
- List
- Marquee
- Metric
- NativeSelect
- NumberInput
- PageHeader
- PasswordInput
- Progress
- Quote
- RadioGroup
- SegmentedControl
- Separator
- Skeleton
- Slider
- Spinner
- Switch
- Tabs
- Tag
- Textarea
- Timeline
- Toggle
- ToggleGroup
For every platform side by side, see Platforms.
How it's built#
Angular shares KinetixUI's design and token contract with React, SwiftUI, Jetpack Compose and Flutter — not their source. These are not React components wrapped for Angular: each one is written as a standalone Angular component or directive.
Styling comes from the same pipeline as every other platform:
- DTCG token source — the JSON files in
tokens/. - Style Dictionary —
pnpm build:tokensgenerates every platform's output. - CSS custom properties — the web output, shipped as
@kinetixui/tokens/css. - Angular styles —
@kinetixui/angular/styles.css, plain CSS that only spends those custom properties (hsl(var(--action)),var(--spacing-3)).
There is no Angular-specific token set and no copied value, so a token change
reaches Angular exactly as it reaches React. Tailwind is not required: the
React package is a Tailwind consumer, but an Angular app can use KinetixUI
without adopting it. Dark mode is the same .dark class contract.
That is also why retheming is not Angular-specific. A theme from
Create is an override block over the same custom properties this
package spends, so its Web CSS target applies to an Angular app exactly as it
does to a React one — there is no Angular export target because there would be
nothing different in it. Import it after @kinetixui/tokens/css and after
@kinetixui/angular/styles.css.
Conventions#
- Standalone components and directives — import the ones a template uses. No NgModule.
OnPushchange detection throughout.- Signal APIs:
input(),model()for two-way values,output()for events. - Directives where the native element should stay the semantic element:
<button kxButton>,<input kxInput>,<label kxLabel>. - Components where KinetixUI generates the markup:
<kx-card>,<kx-badge>,<kx-tabs>. ControlValueAccessoron form controls, so[(ngModel)],formControlandformControlNamework — includingdisabledset by the form model.- The variant and size names are the shared contract:
variant="Outline",size="lg"mean the same thing on every platform.
Example#
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { KxButton, KxSwitch } from '@kinetixui/angular';
@Component({
selector: 'app-preferences',
imports: [FormsModule, KxButton, KxSwitch],
template: `
<kx-switch [(ngModel)]="notifications" aria-label="Email notifications" />
<button kxButton variant="Outline" (click)="save()">Save</button>
`,
})
export class PreferencesComponent {
notifications = signal(true);
save() {}
}This exact template is compiled and exercised by the package's own test suite, so it can't drift from the real API.
Accessibility#
- Native semantics first. Buttons, inputs and labels stay real
<button>,<input>and<label>elements, keeping their built-in focus, keyboard activation and form behaviour. - States map to real semantics:
disabledis the native attribute, checkboxes reportaria-checked(includingmixed), switches userole="switch", and the error state followsaria-invalid. - Tabs implement the APG keyboard pattern — arrow keys, Home and End, one tab stop — with arrow direction reversed in right-to-left documents.
These behaviours are covered by unit tests. That is not an accessibility certification, and there is no browser-level axe suite for Angular yet.
What is left, by wave#
Angular ships in waves rather than alphabetically, so each release is a usable
group rather than a scattering. The counts below are read from
components.manifest.json — every component with no Angular implementation
carries the wave it is in, so this table cannot drift from the plan.
| Wave | Remaining |
|---|---|
| Inputs and forms | 3 |
| Layout | 11 |
| Navigation | 8 |
| Overlays | 17 |
| Data display | 7 |
| Advanced interaction | 7 |
43 shipped. 2 more need no port at all — they are a native equivalent or a composition on Angular, and each says so on its own page.
Every component page already has an Angular tab. Where the port has not been written, the tab says so and names the wave; it does not show an invented example. Where Angular or the DOM already provides the concept — Direction Provider, Form — the tab shows that idiom, labelled Native equivalent, and it is not counted as Angular coverage.
Overlays are deliberately one wave. Dialog, Alert Dialog, Select, Popover, Tooltip, Dropdown Menu, Context Menu, Hover Card, Sheet and Drawer need one shared overlay and focus-management architecture. Implementing them individually would mean building that architecture five times and getting it subtly different each time, so they arrive together.
What Stable would require#
Angular's maturity is Preview, and it stays there until all of the following are true. Adding more components does not by itself change the label, and nothing here is graded on a curve:
- Catalogue target reached — the waves above complete, or every remaining gap reclassified as a native equivalent or a composition with a reason.
- Overlays complete, on one shared architecture with focus trapping, scroll locking, dismissal and return-focus behaviour.
- Forms complete — every control a
ControlValueAccessor, validation states wired toaria-invalid, and error messaging tested. - Documentation complete — every shipped component reachable from its own page with a compiled example.
- Accessibility suite — an automated axe pass over the Angular components, not unit tests alone.
- Browser tests — real-browser keyboard and focus coverage, matching what
@kinetixui/uialready has. - Distribution ready — the built package verified by
scripts/check-dist.mjs, including the stylesheet. Published to npm— done in 0.24.0. Availability was never the blocker on its own, and reaching it does not move the label: the rest of this list still has to be true.- API stability reviewed — a deliberate pass over the public surface, with any breaking change made before the label changes rather than after.
Current scope#
- Preview subset. Angular covers part of the catalogue, and full parity with the other platforms is not claimed. Because its catalogue is not yet complete, Angular is left out of the "on every platform" figure on Platforms rather than counted against it.
- Published, not settled. Being installable from npm says nothing about the API having stopped moving — the maturity label above is the thing to read, and it is independent of distribution.
- No Angular browser axe suite yet — accessibility is covered by unit tests only for now.