Eagami UI
@eagami/ui is a lightweight, accessible Angular component library and design system. Sensible defaults out of the box, with a fully customizable design to fit any brand.
Documentation · Components · Icons
Design tokens · Theme builder · Internationalization · Accessibility
Why Eagami UI
Themes to your brand. Give it one color per role and it generates a full, contrast-checked palette.
Lightweight. No runtime dependencies, no CSS framework, and standalone side-effect-free components, so your app bundles only what it imports.
Accessible and localized. Every component meets WCAG 2.2 AA with full keyboard support and its own axe-core test suite. Built-in text ships in 15 languages you can switch at runtime.
Yours to own. Plain Angular and CSS with no lock-in: read, copy, or fork any component like the rest of your app.
Modern Angular. Signals and native control flow throughout, with SSR-safe rendering, prerendering, and hydration.
Install
ng add @eagami/ui
The schematic installs the package and registers the global stylesheet, the fonts, and provideStaleBuildReload(). To wire it up by hand, see Setup.
Use
import { ButtonComponent } from '@eagami/ui';
@Component({
imports: [ButtonComponent],
template: `<ea-button (clicked)="save()">Save</ea-button>`,
})
export class MyComponent {
save() {}
}
Theme
Pass one color per role to provideEagamiUi:
bootstrapApplication(AppComponent, {
providers: [
provideEagamiUi({
palette: {
primary: { base: '#2563eb' },
secondary: { base: '#f97316' },
},
}),
],
});
Focus rings follow the primary color. When the brand hue reads as an error or a warning, give focus a color of its own with focus: { base: '#2563eb' } in the same palette.
Everything else is a CSS custom property you can override. See Design tokens.
Forms
showErrorsOn sets when form components show a validation error:
'change'(the default): once the user changes the field and leaves it, or submits the form. A field the user tabs past stays quiet, and a new error waits until focus leaves the field.'blur': as soon as the user leaves the field, even unchanged, while a new error still waits until focus leaves the field.'touch': as soon as the user leaves the field, even unchanged, and live while they edit it after that.
Set it app-wide with forms, or on a single field with the showErrorsOn input every form component takes:
provideEagamiUi({ forms: { showErrorsOn: 'touch' } });
Deploys
A tab left open across a deploy still runs the old build, so the next page it lazy loads asks for a file the deploy removed. provideStaleBuildReload() from @eagami/ui/router loads that page in full on the new build instead, and tries only once:
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes), provideStaleBuildReload()],
});
Pass version and onReport to log how each reload turned out, and check isStaleBuildReloadError(error) to keep the error it answered out of your error reporting.
Testing
<ea-dialog> and <ea-drawer> are built on the native <dialog> element, and @eagami/ui/testing keeps them working in jsdom, which lacks showModal() and close(). Call installNativeDialogShim() once from your test setup file:
import { installNativeDialogShim } from '@eagami/ui/testing';
installNativeDialogShim();