Skip to content
Kinetixui

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.

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:

  1. DTCG token source — the JSON files in tokens/.
  2. Style Dictionary — pnpm build:tokens generates every platform's output.
  3. CSS custom properties — the web output, shipped as @kinetixui/tokens/css.
  4. 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.
  • OnPush change 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>.
  • ControlValueAccessor on form controls, so [(ngModel)], formControl and formControlName work — including disabled set 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: disabled is the native attribute, checkboxes report aria-checked (including mixed), switches use role="switch", and the error state follows aria-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.

WaveRemaining
Inputs and forms3
Layout11
Navigation8
Overlays17
Data display7
Advanced interaction7

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:

  1. Catalogue target reached — the waves above complete, or every remaining gap reclassified as a native equivalent or a composition with a reason.
  2. Overlays complete, on one shared architecture with focus trapping, scroll locking, dismissal and return-focus behaviour.
  3. Forms complete — every control a ControlValueAccessor, validation states wired to aria-invalid, and error messaging tested.
  4. Documentation complete — every shipped component reachable from its own page with a compiled example.
  5. Accessibility suite — an automated axe pass over the Angular components, not unit tests alone.
  6. Browser tests — real-browser keyboard and focus coverage, matching what @kinetixui/ui already has.
  7. Distribution ready — the built package verified by scripts/check-dist.mjs, including the stylesheet.
  8. 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.
  9. 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.