@keepui/ui
v0.6.4
Published
KeepUI — Angular cross-platform UI component library with optional Capacitor support
Maintainers
Readme
KeepUI
Component library for Angular with multi-platform support (web and Angular + Capacitor). Built on Tailwind CSS v4 with full light/dark theming and i18n via
@jsverse/transloco.Auto-generated from JSDoc in the source files. Do not edit manually — run
npm run docs:generateto update.
1. Package identity
| Field | Value |
|---|---|
| Package name | @keepui/ui |
| Angular compat | >= 21 |
| Style engine | Tailwind CSS v4 |
| i18n engine | @jsverse/transloco |
2. Installation
Option A — local build (development)
npm run build # outputs to dist/keep-ui
npm install /absolute/path/to/dist/keep-uiOption B — npm registry
npm install @keepui/uiRequired peer dependencies
npm install @angular/common @angular/core @jsverse/transloco3. Global styles (required)
Add once to the host application's global stylesheet (e.g. src/styles.css):
@import "@keepui/ui/styles";Provides:
- Light theme CSS custom properties (default)
- Dark theme via
[data-theme="dark"] - Auto dark via
@media (prefers-color-scheme: dark) - Tailwind v4
@theme inlinemappings for allbg-keepui-*,text-keepui-*,border-keepui-*,shadow-keepui-*utilities
Theme switching at runtime
document.documentElement.setAttribute('data-theme', 'dark'); // force dark
document.documentElement.setAttribute('data-theme', 'light'); // force light
document.documentElement.removeAttribute('data-theme'); // follow OS4. Provider setup (app.config.ts)
Web application
import { provideKeepUi, provideKeepUiI18n } from '@keepui/ui';
export const appConfig: ApplicationConfig = {
providers: [
provideKeepUi(), // registers WebFileService for FILE_PORT
provideKeepUiI18n(), // default language: 'en'
// provideKeepUiI18n({ defaultLang: 'es' }),
],
};Angular + Capacitor application
import { provideKeepUiCapacitor } from '@keepui/ui/capacitor';
import { provideKeepUiI18n } from '@keepui/ui';
export const appConfig: ApplicationConfig = {
providers: [provideKeepUiCapacitor(), provideKeepUiI18n()],
};Rule: Never register both
provideKeepUi()andprovideKeepUiCapacitor()at the same time.
Available provider functions
provideKeepUiI18n(options?: KeepUiI18nOptions = {}): EnvironmentProviders
Registers all providers required for KeepUI internationalisation.
- Configures a self-contained Transloco instance scoped to
'keepui'. - Bundles all translations inline — no HTTP assets required.
- Provides {@link KeepUiLanguageService} so the host app can switch locale.
Usage in app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
provideKeepUi(),
provideKeepUiI18n(), // default language: 'en'
provideKeepUiI18n({ defaultLang: 'es' }), // or start in Spanish
],
};Changing language at runtime
const lang = inject(KeepUiLanguageService);
lang.setLanguage('de');Note: If your application already calls
provideTransloco(), do NOT callprovideKeepUiI18n()— instead configure your Transloco loader to handle the'keepui/{lang}'scope paths, and provideKeepUiLanguageServicemanually.
provideKeepUi(): EnvironmentProviders
Registers KeepUI core providers for a web Angular application.
Registers WebFileService as the implementation of FILE_PORT, enabling
all KeepUI components to use the browser's native file picker.
Add to app.config.ts:
export const appConfig: ApplicationConfig = {
providers: [provideKeepUi()],
};5. Component API reference
All components are standalone. Import directly from @keepui/ui.
5.1 ButtonComponent
Selector: keepui-button
Import: import { ButtonComponent } from '@keepui/ui';
Accessible, themed action button with support for variants, shapes, sizes, loading state, full-width layout, and named icon slots.
Works identically on web and Angular + Capacitor (no native API usage).
<!-- Basic usage -->
<keepui-button (clicked)="save()">Save</keepui-button>
<!-- Primary, pill-shaped, fixed width -->
<keepui-button variant="primary" shape="pill">Confirm</keepui-button>
<!-- With leading icon (any inline element) -->
<keepui-button variant="outline" size="auto">
<svg slot="leading" width="16" height="16" aria-hidden="true">…</svg>
Upload
</keepui-button>
<!-- Loading state -->
<keepui-button [loading]="isSaving()">Saving…</keepui-button>
<!-- Full-width, danger -->
<keepui-button variant="danger" [fullWidth]="true">Delete account</keepui-button>
<!-- Icon-only (requires ariaLabel for accessibility) -->
<keepui-button variant="ghost" size="auto" ariaLabel="Close dialog">
<svg slot="leading" …>…</svg>
</keepui-button>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| variant | ButtonVariant | 'primary' | Visual style of the button. |
| size | ButtonSize | 'md' | Size mode.
md→ fixed 160 px wide, 40 px tall.auto→ padding-driven width, 40 px tall. | |shape|ButtonShape|'pill'| Border-radius style. | |type|ButtonType|'button'| HTMLtypeattribute of the inner<button>. | |disabled|boolean|false| Disables the button whentrue. | |loading|boolean|false| Replaces the content with an animated spinner and setsaria-busy. Also disables the button until the operation completes. | |fullWidth|boolean|false| Expands the button to fill its container width. | |ariaLabel|string|''| Accessible label for icon-only buttons. When provided, sets thearia-labelattribute on the inner<button>. |
Outputs
| Output | Emitter type | Description |
|---|---|---|
| clicked | OutputEmitterRef<void> | Emitted when the button is clicked and is not disabled or loading. |
Content slots (ng-content)
| Slot | Description |
|---|---|
| (default) | Main projected content |
| [slot='leading'] | Leading icon/element. Hidden while loading. |
| [slot='trailing'] | Trailing icon/element. Hidden while loading. |
5.2 CardComponent
Selector: keepui-card
Import: import { CardComponent } from '@keepui/ui';
Contenedor versátil con soporte de variante, padding, color, estado clickable, seleccionado y scrollable.
padding="screen" aplica padding lateral y superior pero omite el inferior
intencionadamente para que el contenido parezca continuar más allá del área visible,
invitando al usuario a hacer scroll. Un div espaciador se inserta automáticamente
al final del contenido proyectado: cuando el usuario llega al fondo, el espaciador
reproduce el padding inferior correcto sin que el consumidor deba declararlo.
<keepui-card>Contenido</keepui-card>
<keepui-card variant="flat" padding="lg" [clickable]="true" (clicked)="onSelect()">
Card clicable
</keepui-card>
<div class="h-screen overflow-hidden">
<keepui-card padding="screen" [scrollable]="true" [fullHeight]="true">
Contenido largo — el padding inferior se gestiona automáticamente
</keepui-card>
</div>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| variant | CardVariant | 'outlined' | |
| padding | CardPadding | 'md' | |
| colors | CardColors | 'primary' | |
| clickable | boolean | false | |
| selected | boolean | false | |
| scrollable | boolean | false | |
| fullHeight | boolean | false | |
Outputs
| Output | Emitter type | Description |
|---|---|---|
| clicked | OutputEmitterRef<void> | |
5.3 IconActionButtonComponent
Selector: keepui-icon-action-button
Import: import { IconActionButtonComponent } from '@keepui/ui';
Circular icon-only action button with default and danger variants,
loading state, and full accessibility support.
Because this button renders no visible text, ariaLabel is required to
satisfy WCAG 2.1 SC 4.1.2 (Name, Role, Value).
The icon color is inherited automatically via currentColor from the button's
text color, so SVG symbols defined with stroke="currentColor" will adapt to
both variants and themes without extra classes.
<keepui-icon-action-button icon="edit-icon" ariaLabel="Editar" />
<keepui-icon-action-button
icon="trash-icon"
variant="danger"
ariaLabel="Eliminar elemento"
[loading]="isDeleting()"
/>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| icon | unknown | — | ID of the SVG symbol to render (without the # prefix). |
| ariaLabel | unknown | — | Accessible label for the button. Always required — icon-only buttons must
have a programmatic name for screen readers (WCAG 2.1 SC 4.1.2). |
| variant | IconActionButtonVariant | 'default' | Visual style variant. |
| iconSize | number | 20 | Size of the inner icon in pixels. |
| type | IconActionButtonType | 'button' | HTML type attribute of the inner <button>. |
| disabled | boolean | false | Disables the button when true. |
| loading | boolean | false | Shows an animated spinner and disables the button.
Also sets aria-busy="true" on the element. |
5.4 IconComponent
Selector: keepui-icon
Import: import { IconComponent } from '@keepui/ui';
Generic SVG sprite icon renderer.
Renders a <use href="#name"> reference pointing to an SVG symbol pre-registered
in the DOM by the consuming application (e.g. via IconRegistryService).
Accessibility:
- When used decoratively (default), the SVG carries
aria-hidden="true"automatically. - When used as a standalone meaningful icon, supply an
ariaLabel— the SVG will receiverole="img"andaria-labelaccordingly.
<!-- Decorative — hidden from screen readers -->
<keepui-icon name="check-icon" [size]="20" aria-hidden="true" />
<!-- Meaningful standalone icon -->
<keepui-icon name="close-icon" ariaLabel="Cerrar" />Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| name | unknown | — | ID of the SVG symbol to render (without the # prefix). |
| size | number | 24 | Width and height of the icon in pixels. |
| viewBox | string | '0 0 24 24' | viewBox attribute forwarded to the <svg> element. |
| ariaLabel | string | '' | Accessible label for standalone icons.
When provided, sets role="img" and aria-label on the SVG.
When omitted, the SVG is marked aria-hidden="true" (decorative). |
5.5 ImagePreviewComponent
Selector: keepui-image-preview
Import: import { ImagePreviewComponent } from '@keepui/ui';
Standalone component that allows the user to pick and preview an image.
This component is fully platform-agnostic. It delegates file picking to
whatever FilePort implementation is provided via FILE_PORT.
UI strings are fully internationalised via Transloco (scope 'keepui').
Call provideKeepUiI18n() in your app.config.ts and use
KeepUiLanguageService.setLanguage(lang) to change locale at runtime.
Usage:
<keepui-image-preview />Prerequisites — register providers in app.config.ts:
- Web:
provideKeepUi()+provideKeepUiI18n() - Capacitor:
provideKeepUiCapacitor()+provideKeepUiI18n()
Public signals (readable from outside)
| Signal | Type | Description |
|---|---|---|
| imageUrl | Signal<string | null> | URL of the selected image, ready to bind to [src]. |
| error | Signal<string | null> | Error message if the last pick operation failed. |
| loading | Signal<boolean> | True while the pick operation is in progress. |
5.6 SignalDropdownComponent
Selector: keepui-signal-dropdown
Import: import { SignalDropdownComponent } from '@keepui/ui';
Signal-based accessible dropdown / select component.
Fully platform-agnostic — no native API usage. The panel opens in fixed
position so it is never clipped by overflow-hidden ancestors. It repositions
itself automatically on scroll and resize.
The value and touched properties are model() signals so the component
integrates seamlessly with Angular signal-based forms.
<keepui-signal-dropdown
label="País"
placeholder="Selecciona un país"
[options]="countries"
[(value)]="selectedCountry"
/>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| label | string | '' | Optional label text rendered above the dropdown. |
| placeholder | string | '' | Placeholder shown when no value is selected. |
| options | unknown | — | Array of options to display in the panel. |
| width | SignalDropdownWidth | 'full' | Layout width of the wrapper. |
| required | boolean | false | Marks the field as required. Adds aria-required and a visual asterisk. |
| errorMessage | string | '' | Human-readable error message shown below the dropdown. Takes precedence over errors[0]. |
| errors | readonly string[] | [] | Array of error strings. The first item is displayed when errorMessage is empty.
Set together with invalid=true to trigger the error state. |
| selectId | string | ``ku-dropdown-${Math.random(| Stableidused to link thewith the trigger.
A random suffix is generated by default. |
| disabled|boolean|false| Disables the dropdown. |
|invalid|boolean|false| Forces the error visual state regardless of thetouched` model.
Useful for external form validation. |
Outputs
| Output | Emitter type | Description |
|---|---|---|
| valueChange | OutputEmitterRef<T | null> | Emitted when the selected value changes. |
5.7 SignalTextareaComponent
Selector: keepui-signal-textarea
Import: import { SignalTextareaComponent } from '@keepui/ui';
Signal-based accessible textarea component with character counter, resize control, and integrated error display.
The value and touched properties are model() signals so the component
integrates seamlessly with Angular signal-based forms.
<keepui-signal-textarea
label="Descripción"
placeholder="Escribe aquí…"
[rows]="5"
[maxLength]="500"
[(value)]="description"
/>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| label | string | '' | Optional label text rendered above the textarea. |
| placeholder | string | '' | Placeholder passed to the underlying <textarea>. |
| rows | number | 4 | Number of visible text rows. |
| width | SignalTextareaWidth | 'full' | Layout width of the wrapper. |
| resize | SignalTextareaResize | 'none' | CSS resize behaviour. |
| required | boolean | false | Marks the field as required. |
| errorMessage | string | '' | Human-readable error message. Takes precedence over errors[0]. |
| errors | readonly string[] | [] | Array of error strings. The first item is displayed when errorMessage is empty.
Set together with invalid=true to trigger the error state. |
| textareaId | string | ``ku-textarea-${Math.random(| Stableidused to link thewith the.
A random suffix is generated by default. |
| disabled|boolean|false| Disables the textarea. |
|maxLength|number | undefined|undefined| Maximum number of characters allowed. Shows a character counter when set. |
|invalid|boolean|false| Forces the error visual state regardless of thetouched` model.
Useful for external form validation. |
5.8 SignalTextInputComponent
Selector: keepui-signal-text-input
Import: import { SignalTextInputComponent } from '@keepui/ui';
Signal-based accessible text input supporting all common HTML input types,
leading/trailing icons, a trailing content slot, and a built-in
password-visibility toggle (when type="password").
The value and touched properties are model() signals so the component
integrates seamlessly with Angular signal-based forms.
Password toggle labels are translated via Transloco (scope 'keepui').
Call provideKeepUiI18n() in your app.config.ts to activate i18n.
<keepui-signal-text-input
label="Email"
type="email"
placeholder="[email protected]"
leadingIcon="mail-icon"
[(value)]="email"
/>
<!-- Password with toggle -->
<keepui-signal-text-input
label="Contraseña"
type="password"
[(value)]="password"
/>Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| label | string | '' | Optional label text rendered above the input. |
| placeholder | string | '' | Placeholder passed to the underlying <input>. |
| type | SignalTextInputType | 'text' | HTML type attribute. Use 'password' to enable the visibility toggle. |
| width | SignalTextInputWidth | 'full' | Layout width of the wrapper. |
| leadingIcon | string | '' | Name of the leading icon (SVG symbol ID). Leave empty for no icon. |
| trailingIcon | string | '' | Name of the trailing icon (SVG symbol ID). Ignored when type="password". |
| hasTrailingSlot | boolean | false | When true, a slot for custom trailing content is enabled
(projects [trailingSlot] content). Overrides trailingIcon. |
| required | boolean | false | Marks the field as required. Adds aria-required and a visual asterisk. |
| showRequiredIndicator | boolean | true | When false, hides the visual asterisk even if required=true. |
| errorMessage | string | '' | Human-readable error message. Takes precedence over errors[0]. |
| errors | readonly string[] | [] | Array of error strings. The first item is displayed when errorMessage is empty.
Set together with invalid=true to trigger the error state. |
| inputId | string | ``ku-text-input-${Math.random(| Stableidused to link thewith the.
A random suffix is generated by default. |
| disabled|boolean|false| Disables the input. |
|invalid|boolean|false| Forces the error visual state regardless of thetouched` model.
Useful for external form validation. |
6. Type definitions
Visual style variant of the button.
type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';Size mode of the button.
md: fixed width (160 px) and height (40 px).auto: height fixed (40 px), width grows with padding to fit content.
type ButtonSize = 'md' | 'auto';Border-radius style of the button.
pill: fully rounded (rounded-full).rounded: moderately rounded (rounded-2xl).
type ButtonShape = 'pill' | 'rounded';HTML
typeattribute for the underlying<button>element.
type ButtonType = 'button' | 'submit' | 'reset';type CardVariant = 'flat' | 'outlined';type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'screen';type CardColors = 'primary' | 'secondary';type IconActionButtonVariant = 'default' | 'danger';type IconActionButtonType = 'button' | 'submit' | 'reset';Layout width of the dropdown wrapper.
type SignalDropdownWidth = 'full' | 'half' | 'auto';Layout width of the text input wrapper.
type SignalTextInputWidth = 'full' | 'half' | 'auto';HTML
typeattribute for the underlying<input>element. Use'password'to enable the built-in show/hide toggle.
type SignalTextInputType = | 'text'
| 'email'
| 'tel'
| 'number'
| 'password'
| 'search'
| 'url'
| 'date';Layout width of the textarea wrapper.
type SignalTextareaWidth = 'full' | 'half' | 'auto';CSS
resizebehaviour of the<textarea>element.
none→ not resizable (default).vertical→ user can drag to resize vertically.horizontal→ user can drag to resize horizontally.both→ user can drag freely.
type SignalTextareaResize = 'none' | 'vertical' | 'horizontal' | 'both';7. Interfaces & models
FileResult
Represents the result of a file/image selection operation. This model is platform-agnostic and used across all adapters.
interface FileResult {
/** A data URL (e.g. `data:image/jpeg;base64,...`) or an HTTP/file URL ready to display. */
dataUrl: string;
/** MIME type of the selected file, e.g. `image/jpeg`. */
mimeType: string;
}FilePort
Platform-agnostic port (interface) for file/image selection.
Provide a concrete implementation via the FILE_PORT injection token.
- Web:
WebFileService - Capacitor:
CapacitorFileService(from@keepui/ui/capacitor)
interface FilePort {
/** Opens a platform-native image picker and returns the selected image.
Resolves with a `FileResult` containing a displayable URL and MIME type.
Rejects if the user cancels or an error occurs. */
pickImage(): Promise<FileResult>;
}8. Services
KeepUiLanguageService
Service that exposes a public API for changing the active language of all KeepUI components at runtime.
Usage
// Inject anywhere in the host application
const lang = inject(KeepUiLanguageService);
// Switch to Spanish
lang.setLanguage('es');
// Read the active language
console.log(lang.activeLanguage()); // 'es'Register via provideKeepUiI18n() in app.config.ts.
Public properties:
| Property | Type | Description |
|---|---|---|
| activeLanguage | — | Signal that reflects the currently active KeepUI locale. |
| availableLanguages | readonly KeepUiLanguage[] | Ordered list of all supported locales. |
Public methods:
setLanguage(lang: KeepUiLanguage): void— Changes the active language for all KeepUI components.
WebFileService
Web implementation of FilePort.
Uses a hidden <input type="file"> and the FileReader API to let the user
pick an image from the file system in a browser environment.
This implementation has no dependency on Capacitor or any native plugin.
Public methods:
pickImage(): Promise<FileResult>—
9. Internationalisation (i18n)
Use typed constants instead of raw strings:
import { KEEPUI_TRANSLATION_KEYS as T } from '@keepui/ui';
// Example
translocoService.translate(T.IMAGE_PREVIEW.SELECT_IMAGE);Supported languages: en (English), es (Spanish), de (German)
Translation keys:
| Constant path | Translation key |
|---|---|
| IMAGE_PREVIEW.SELECT_IMAGE | imagePreview.selectImage |
| IMAGE_PREVIEW.LOADING | imagePreview.loading |
| IMAGE_PREVIEW.PREVIEW_ALT | imagePreview.previewAlt |
| IMAGE_PREVIEW.ERROR_UNEXPECTED | imagePreview.errorUnexpected |
| SIGNAL_TEXT_INPUT.SHOW_PASSWORD | signalTextInput.showPassword |
| SIGNAL_TEXT_INPUT.HIDE_PASSWORD | signalTextInput.hidePassword |
Changing language at runtime:
import { KeepUiLanguageService } from '@keepui/ui';
const lang = inject(KeepUiLanguageService);
lang.setLanguage('es'); // 'en' | 'es' | 'de'10. CSS design tokens
Override any variable in your CSS to customise the theme:
:root {
--keepui-primary: #3b82f6;
--keepui-primary-hover: #2563eb;
--keepui-primary-active: #1d4ed8;
--keepui-primary-foreground: #ffffff;
--keepui-background: #f5f5f5;
--keepui-surface: #ffffff;
--keepui-surface-hover: #f0f0f0;
--keepui-border: #e0e0e0;
--keepui-border-strong: #cccccc;
--keepui-text: #1f2937;
--keepui-text-muted: #6b7280;
--keepui-text-disabled: #9ca3af;
--keepui-error: #dc2626;
--keepui-error-foreground: #ffffff;
--keepui-success: #16a34a;
--keepui-warning: #f59e0b;
--keepui-shadow-sm: 0 1px 3px rgba(0,0,0,.12);
--keepui-shadow-md: 0 3px 6px rgba(0,0,0,.15);
--keepui-shadow-lg: 0 6px 12px rgba(0,0,0,.18);
}
[data-theme="dark"] {
--keepui-primary: #60a5fa;
--keepui-primary-foreground: #0f172a;
--keepui-background: #0f172a;
--keepui-surface: #1e293b;
--keepui-surface-hover: #334155;
--keepui-border: #334155;
--keepui-border-strong: #475569;
--keepui-text: #f1f5f9;
--keepui-text-muted: #94a3b8;
--keepui-text-disabled: #64748b;
--keepui-error: #f87171;
--keepui-error-foreground: #0f172a;
--keepui-success: #4ade80;
--keepui-warning: #fbbf24;
}11. Tailwind utility classes
Generated automatically after @import "@keepui/ui/styles" with Tailwind v4:
bg-keepui-background bg-keepui-surface bg-keepui-surface-hover
bg-keepui-primary bg-keepui-primary-hover bg-keepui-primary-active
bg-keepui-error bg-keepui-success bg-keepui-warning
text-keepui-text text-keepui-text-muted text-keepui-text-disabled
text-keepui-primary text-keepui-primary-fg text-keepui-error
border-keepui-border border-keepui-border-strong border-keepui-primary
shadow-keepui-sm shadow-keepui-md shadow-keepui-lg
focus-visible:ring-keepui-primary5.10 TabGroupComponent
Selector: keepui-tab-group
Import: import { TabGroupComponent, Tab, TabGroupVariant } from '@keepui/ui';
Accessible pill-style tab group implementing the WAI-ARIA tablist pattern.
Supports icons, disabled tabs, keyboard navigation (arrow keys, Home, End)
and two visual variants. No internal i18n strings — tab labels are provided
by the consumer.
<!-- Default variant -->
<keepui-tab-group
[tabs]="tabs"
[selectedTabId]="activeTab"
(tabChange)="activeTab = $event"
ariaLabel="Main sections"
/>
<!-- Filled variant -->
<keepui-tab-group
variant="filled"
[tabs]="tabs"
[selectedTabId]="activeTab"
(tabChange)="activeTab = $event"
/>readonly tabs: Tab[] = [
{ id: 'home', label: 'Home' },
{ id: 'profile', label: 'Profile', icon: 'user-icon' },
{ id: 'settings', label: 'Settings', disabled: true },
];Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| tabs | Tab[] | (required) | List of tabs to render. |
| selectedTabId | string | (required) | ID of the currently active tab. |
| variant | TabGroupVariant | 'default' | Visual style: 'default' or 'filled'. |
| ariaLabel | string | '' | Accessible label for the tablist element. |
Outputs
| Output | Emitter type | Description |
|---|---|---|
| tabChange | OutputEmitterRef<string> | Emits the id of the selected tab. |
Tab interface
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Unique identifier. |
| label | string | ✅ | Visible tab label. |
| icon | string | — | SVG symbol ID (without #) for an optional icon. |
| disabled | boolean | — | When true, the tab is not selectable. Default false. |
Accessibility
- Container:
role="tablist"with optionalaria-label. - Each button:
role="tab",aria-selected,aria-disabled, managedtabindex. - Keyboard:
ArrowRight/ArrowLeft(andDown/Up) navigate between tabs;Home/Endjump to extremes. - Focus ring:
focus-visible:ring-2 focus-visible:ring-ku-action-primary. - Touch target:
min-h-[2.75rem]on every tab button.
5.11 StepperComponent
Selector: keepui-stepper
Import: import { StepperComponent, StepperStep, StepperSize, StepperOrientation } from '@keepui/ui';
Visual step-progress indicator with optional interactive navigation. Renders numbered circles connected by animated progress bars. Completed steps show a check-mark; the active step is highlighted with a ring; future steps are muted. Steps can carry an icon that replaces the number.
<!-- Read-only progress indicator -->
<keepui-stepper [steps]="steps" [activeIndex]="1" />
<!-- Interactive (allows going back to completed steps) -->
<keepui-stepper
[steps]="steps"
[activeIndex]="currentStep"
(stepChange)="currentStep = $event"
ariaLabel="Registration process"
/>
<!-- Small, vertical -->
<keepui-stepper
[steps]="steps"
[activeIndex]="currentStep"
size="sm"
orientation="vertical"
/>readonly steps: StepperStep[] = [
{ id: '1', label: 'Account' },
{ id: '2', label: 'Profile', icon: 'user-icon' },
{ id: '3', label: 'Plan' },
{ id: '4', label: 'Confirm', disabled: true },
];Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| steps | StepperStep[] | (required) | List of steps to render. |
| activeIndex | number | 0 | Zero-based index of the currently active step. |
| size | StepperSize | 'md' | Size of step circles and connectors: 'md' or 'sm'. |
| orientation | StepperOrientation | 'horizontal' | Layout direction: 'horizontal' or 'vertical'. |
| ariaLabel | string | '' | Accessible label for the <nav> element. |
Outputs
| Output | Emitter type | Description |
|---|---|---|
| stepChange | OutputEmitterRef<number> | Emits the zero-based index of the clicked step (completed or active steps only). |
StepperStep interface
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Unique identifier. |
| label | string | ✅ | Label shown below the step circle. |
| icon | string | — | SVG symbol ID (without #) rendered inside the circle instead of the step number. |
| disabled | boolean | — | When true, the step is not interactive. Default false. |
Accessibility
- Container:
<nav>with optionalaria-label. - List:
role="list"/role="listitem"witharia-current="step"on the active item. - Completed and active steps render as
<button>elements witharia-labelequal to the step label. - Future and disabled steps render as inert
<span>elements. - Focus ring:
focus-visible:ring-2 focus-visible:ring-ku-action-primary. - Touch target:
min-h-[2.75rem] min-w-[2.75rem]on every interactive step bubble.
12. Integration checklist
- [ ]
@keepui/uiinstalled inpackage.json - [ ]
@import "@keepui/ui/styles"in global stylesheet - [ ] Tailwind v4 configured (via
@tailwindcss/postcssor@tailwindcss/vite) - [ ]
provideKeepUi()orprovideKeepUiCapacitor()registered inapp.config.ts - [ ]
provideKeepUiI18n()registered inapp.config.ts - [ ] Components imported individually in each standalone component or NgModule
- [ ]
[data-theme="dark"]toggle wired if dark mode switching is needed - [ ]
KeepUiLanguageService.setLanguage()called if runtime i18n is needed
13. What NOT to do
- Do not import from
@keepui/ui/src/lib/...— only from@keepui/uior@keepui/ui/capacitor. - Do not call both
provideKeepUi()andprovideKeepUiCapacitor(). - Do not hardcode
FILE_PORTimplementations inside components — always use the token. - Do not skip
@import "@keepui/ui/styles"— without it, all theme utility classes are missing. - Do not import
@capacitor/*in code that also imports@keepui/uicore.
