A signals-native, zoneless, accessible component library — themed by design tokens and built on native browser primitives.
Live demo apps
Sales Overview
Recent Opportunities
| Company | Value | Status | Owner | Actions |
|---|---|---|---|---|
| $1,250,000 | Closed Won | |||
| $840,000 | Negotiation | |||
| $12,400 | Discovery | |||
| $96,000 | Proposal | |||
| $38,500 | Discovery |
Quick Add Deal
- Discovery1%
- Proposal8%
- Negotiation36%
- Closed Won55%
Quick start
So simple to use
Import a control, bind your signal, ship. No boilerplate, no ceremony.
volume.component.ts
import { Component, signal } from '@angular/core';
import { JigSlider } from '@awdlab/jig/slider';
import { JigSwitch } from '@awdlab/jig/switch';
@Component({
selector: 'app-volume',
imports: [JigSlider, JigSwitch],
``,
})
export class VolumeComponent {
protected readonly volume = signal(57);
protected readonly muted = signal(true);
} No ngModel, no subscriptions, no change-detection calls — the signal is the binding.
Theming
Your design system, not ours
Every color, space and radius is a design token. Pick a theme and a color — every control follows.
live preview · Nova
Sign in
Customization
Total control over every control
One list-box, four levels of control — open a level and watch the same control morph from a light restyle all the way to your own theme.
Developer experience
Your editor already knows the API
Typed inputs, models and events — discoverable without leaving the file. Switch between single and multiple selection: the control changes, and the value type changes with it.
deal-form.component.ts
type StageId = 'discovery' | 'proposal' | 'won';
@Component({
imports: [JigInputField, JigSelect],
``,
})
export class DealFormComponent {
stages: JigItem<unknown, StageId>[] = STAGES;
stage = signal<StageId | null>(null);
}Typed public API
Inputs, models and outputs are generic — no any, no string keys, no guessing.
Import per control
Own entry point each, so only what you render reaches the bundle.
Unit + visual tests
Screenshot regression and axe checks run on every control, every release.
Locale aware
Bundled UI translations; dates and numbers follow the active locale.
Accessibility
Drive it with the keyboard
Focus management, roving tabindex, ARIA state and live-region announcements ship with every control. The stage below is real library code, driven by the same key handling your users get.
keys the demo is pressing
- roving tabindex
- Groups are one tab stop; arrows, Home and End move inside them.
- focus return
- Dialogs trap focus while open and hand it back to the trigger on close.
- aria state
- Checked, expanded, selected and disabled land on the real element, not a wrapper.
- axe in CI
- Every control is asserted against axe on every release, not audited once.
toolbar — one tab stop, arrows inside
Under the hood
Let the browser do it
Native where the platform is strong. Ours where it isn't — so you never wire it yourself.
platform native
Dialogs in the top layer
Opened with showModal(): focus trap, ::backdrop, Esc to close and correct stacking all come from the browser. No z-index wars, no portals.
platform native
Popovers, natively
Selects, menus and tooltips ride the Popover API — light dismiss, top-layer stacking and Shadow DOM support without an overlay engine.
we built it for you
Overflow that handles itself
Chips collapse into a counter and breadcrumbs fold into a menu — measured per container, not per viewport. No media queries. Drag the width down and watch.
we built it for you
Server-rendered, flash-free
Controls render fully styled on the server — your theme's colors and control styles are in the first byte, so there is no unstyled flash and no client round-trip. This page arrived that way.
<html> from the server
├ theme variables + control styles
├ real content, real ARIA, no JS
└ hydrates into the same DOM
Components
A taste of 68+ controls
Twelve interactive samples below. Every control ships with a full documentation page — hover for a preview, click through for the docs.
Get started
Start with one control
Install, import, bind a signal — that is the whole learning curve. Swap in a single control where you need it and leave the rest of your app untouched, or point your coding agent at our MCP server and let it migrate the whole app in one pass. Your call.
MIT licensed · Angular 22+ · zoneless and signals-native
jig