# @letsprogram/ng-oat : Full API Reference
> Signal-first Angular UI component library built on Oat CSS. 40+ standalone components, directive wrappers, Signal Forms integration, CVA adapters, 87 design tokens, and 12 ready-made recipe layouts. Requires Angular 21 and above.
Package: `@letsprogram/ng-oat` v0.1.8
Install: `npm i @letsprogram/ng-oat`
Peer deps: `@angular/core@^21`, `@angular/common@^21`, `@angular/forms@^21`
## Setup
```typescript
// app.config.ts
import { provideNgOat } from '@letsprogram/ng-oat';
export const appConfig = {
providers: [provideNgOat()]
};
```
Include the Oat CSS stylesheet and tokens CSS in your angular.json styles array or import them globally.
Optional theming:
```typescript
import { provideNgOatTheme } from '@letsprogram/ng-oat';
providers: [
provideNgOat(),
provideNgOatTheme({
tokens: {
'--oat-primary': '#3b82f6',
'--oat-radius-medium': '0.5rem',
}
})
]
```
---
## Components
### NgOatButton
Selector: `ng-oat-button`
Import: `import { NgOatButton } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| variant | `'default' \| 'secondary' \| 'danger'` | `'default'` |
| btnStyle | `'filled' \| 'outline' \| 'ghost'` | `'filled'` |
| size | `'default' \| 'small' \| 'large'` | `'default'` |
| icon | `boolean` | `false` |
| type | `'button' \| 'submit' \| 'reset'` | `'button'` |
| disabled | `boolean` | `false` |
| ariaLabel | `string` | `''` |
Output: `clicked: MouseEvent`
Content: projects button label text/icons.
```html
Save
Delete
```
---
### NgOatSplitButton
Selector: `ng-oat-split-button`
Import: `import { NgOatSplitButton } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| label | `string` | **required** |
| variant | `'default' \| 'secondary' \| 'danger'` | `'default'` |
| btnStyle | `'filled' \| 'outline' \| 'ghost'` | `'filled'` |
| size | `'default' \| 'small' \| 'large'` | `'default'` |
| disabled | `boolean` | `false` |
Output: `clicked: MouseEvent`
Content: project `[role="menuitem"]` elements for the dropdown menu.
```html
```
---
### NgOatBadge
Selector: `ng-oat-badge`
Import: `import { NgOatBadge } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| variant | `'default' \| 'secondary' \| 'outline' \| 'danger' \| 'success'` | `'default'` |
Content: projects badge text.
```html
Active
Error
```
---
### NgOatAlert
Selector: `ng-oat-alert`
Import: `import { NgOatAlert } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| variant | `'default' \| 'success' \| 'danger' \| 'warning'` | `'default'` |
| size | `'compact' \| 'default' \| 'comfortable'` | `'default'` |
| dismissible | `boolean` | `false` |
Output: `dismissed: void`
Content: projects alert body. Host has `role="alert"`.
```html
Your changes have been saved.
```
---
### NgOatCard / NgOatCardHeader / NgOatCardFooter
Selectors: `ng-oat-card`, `ng-oat-card-header`, `ng-oat-card-footer`
Import: `import { NgOatCard, NgOatCardHeader, NgOatCardFooter } from '@letsprogram/ng-oat';`
No inputs/outputs : pure content projection.
```html
Card Title
Card body content
Action
```
---
### NgOatAccordion
Selector: `ng-oat-accordion`
Import: `import { NgOatAccordion } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| items | `NgOatAccordionItem[]` | **required** |
| group | `string \| undefined` | `undefined` |
NgOatAccordionItem: `{ title: string; content: string; open?: boolean }`
Output: `toggled: { item: NgOatAccordionItem; open: boolean }`
```typescript
items: NgOatAccordionItem[] = [
{ title: 'Section 1', content: 'Content for section 1' },
{ title: 'Section 2', content: 'Content for section 2', open: true },
];
```
```html
```
---
### NgOatTable
Selector: `ng-oat-table`
Import: `import { NgOatTable } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| columns | `NgOatTableColumn[]` | **required** |
| data | `Record[]` | **required** |
| striped | `boolean` | `false` |
| clickable | `boolean` | `false` |
| emptyText | `string` | `'No data available.'` |
| scrollX | `boolean` | `false` |
| scrollY | `string` | `''` |
NgOatTableColumn: `{ key: string; label: string; width?: string; align?: 'left'|'center'|'right'; render?: (val, row) => string }`
Output: `rowClick: Record`
```html
```
---
### NgOatBreadcrumb
Selector: `ng-oat-breadcrumb`
Import: `import { NgOatBreadcrumb, NgOatBreadcrumbIcon } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| items | `OatBreadcrumbItem[]` | **required** |
OatBreadcrumbItem: `{ label: string; url?: string; icon?: string }`
Output: `navigate: OatBreadcrumbItem`
Content: optional `ng-template[ngOatBreadcrumbIcon]` for custom icon rendering.
```html
```
---
### NgOatPagination
Selector: `ng-oat-pagination`
Import: `import { NgOatPagination } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| totalPages | `number` | **required** |
| currentPage | `number` | `1` |
| maxVisible | `number` | `5` |
Output: `pageChange: number`
```html
```
---
### NgOatProgress
Selector: `ng-oat-progress`
Import: `import { NgOatProgress } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| value | `number` | **required** |
| max | `number` | `100` |
```html
```
---
### NgOatMeter
Selector: `ng-oat-meter`
Import: `import { NgOatMeter } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| value | `number` | **required** |
| min | `number` | `0` |
| max | `number` | `1` |
| low | `number \| undefined` | `undefined` |
| high | `number \| undefined` | `undefined` |
| optimum | `number \| undefined` | `undefined` |
```html
```
---
### NgOatSpinner
Selector: `ng-oat-spinner`
Import: `import { NgOatSpinner } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| size | `'small' \| 'default' \| 'large'` | `'default'` |
| overlay | `boolean` | `false` |
Host: `aria-busy="true"`. Content projection supported.
```html
Loading data...
```
---
### NgOatSwitch
Selector: `ng-oat-switch`
Import: `import { NgOatSwitch } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| checked | `boolean` | `false` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
Output: `changed: boolean`
Implements `FormCheckboxControl` for Signal Forms.
```html
```
---
### NgOatSkeleton
Selector: `ng-oat-skeleton`
Import: `import { NgOatSkeleton } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| type | `'line' \| 'box'` | `'line'` |
| width | `string \| undefined` | `undefined` |
```html
```
---
### NgOatAvatar
Selector: `ng-oat-avatar`
Import: `import { NgOatAvatar } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| src | `string` | `''` |
| alt | `string` | `''` |
| initials | `string` | `''` |
| fallback | `string` | `''` |
| size | `'sm' \| 'default' \| 'lg' \| 'xl'` | `'default'` |
Auto-generates initials from `alt` if `src` fails and `initials` not set.
```html
```
---
### NgOatSeparator
Selector: `ng-oat-separator`
Import: `import { NgOatSeparator } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` |
| label | `string` | `''` |
```html
```
---
### NgOatFileUpload
Selector: `ng-oat-file-upload`
Import: `import { NgOatFileUpload } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| accept | `string` | `''` |
| multiple | `boolean` | `false` |
| maxSize | `number` | `0` |
| disabled | `boolean` | `false` |
| label | `string` | `''` |
Output: `filesSelected: File[]`
Methods: `openFilePicker()`, `removeFile(index)`
Public signal: `files`
```html
```
---
### NgOatInputOtp
Selector: `ng-oat-input-otp`
Import: `import { NgOatInputOtp } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| length | `number` | `6` | input |
| separator | `number` | `0` | input |
| mask | `boolean` | `false` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
Implements `FormValueControl` for Signal Forms.
```html
```
---
### NgOatSearchInput
Selector: `ng-oat-search-input`
Import: `import { NgOatSearchInput } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| placeholder | `string` | `'Search...'` | input |
| shortcut | `string` | `''` | input |
| debounceMs | `number` | `300` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
Output: `search: string`
Implements `FormValueControl`. Methods: `clear()`, `focus()`.
```html
```
---
### NgOatCarousel
Selector: `ng-oat-carousel`
Import: `import { NgOatCarousel } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| slides | `NgOatCarouselSlide[]` | `[]` | input |
| autoplay | `boolean` | `false` | input |
| interval | `number` | `5000` | input |
| loop | `boolean` | `true` | input |
| showArrows | `boolean` | `true` | input |
| showDots | `boolean` | `true` | input |
| aspectRatio | `'auto' \| '16:9' \| '4:3' \| '1:1'` | `'auto'` | input |
| activeIndex | `number` | `0` | model (two-way) |
NgOatCarouselSlide: `{ src: string; alt?: string; caption?: string }`
Output: `slideChange: number`
Methods: `next()`, `prev()`, `goTo(index)`
```html
```
---
### NgOatCardCarousel
Selector: `ng-oat-card-carousel`
Import: `import { NgOatCardCarousel } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| heading | `string` | `''` |
| ariaLabel | `string` | `'Product carousel'` |
| items | `NgOatProductCard[]` | `[]` |
| showSeeAll | `boolean` | `false` |
NgOatProductCard: `{ title: string; image: string; price?: string; description?: string }`
Outputs: `seeAllClick: void`, `cardClick: NgOatProductCard`
```html
```
---
### NgOatToolbar / NgOatToolbarRow
Selectors: `ng-oat-toolbar`, `ng-oat-toolbar-row`
Import: `import { NgOatToolbar, NgOatToolbarRow } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| color | `'default' \| 'primary' \| 'accent'` | `'default'` |
| dense | `boolean` | `false` |
| fixed | `boolean` | `true` |
Content slots: `[toolbarStart]`, default, `[toolbarEnd]`.
```html
App Name
Nav links here
☰
```
---
### NgOatThemeSelector
Selector: `ng-oat-theme-selector`
Import: `import { NgOatThemeSelector } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| mode | `'dropdown' \| 'toggle'` | `'dropdown'` |
| initialTheme | `NgOatTheme \| undefined` | `undefined` |
| themes | `NgOatThemeOption[]` | `[light, dark, system]` |
NgOatTheme: `'light' | 'dark' | 'system'`
Output: `themeChange: NgOatTheme`
Persists to localStorage.
```html
```
---
### NgOatToggle
Selector: `ng-oat-toggle`
Import: `import { NgOatToggle } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| variant | `'default' \| 'outline'` | `'default'` | input |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | input |
| disabled | `boolean` | `false` | input |
| toggleValue | `string` | `''` | input |
| pressed | `boolean` | `false` | model (two-way) |
Output: `pressedChange: boolean`
```html
Bold
```
---
### NgOatToggleGroup
Selector: `ng-oat-toggle-group`
Import: `import { NgOatToggleGroup } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| multiple | `boolean` | `false` | input |
| disabled | `boolean` | `false` | input |
| variant | `'default' \| 'outline'` | `'default'` | input |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | input |
| value | `string` | `''` | model (two-way) |
```html
Left
Center
Right
```
---
### NgOatChip / NgOatChipGroup / NgOatChipInput
Selectors: `ng-oat-chip`, `ng-oat-chip-group`, `ng-oat-chip-input`
Import: `import { NgOatChip, NgOatChipGroup, NgOatChipInput } from '@letsprogram/ng-oat';`
**NgOatChip:**
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| variant | `'default' \| 'secondary' \| 'outline' \| 'success' \| 'warning' \| 'danger'` | `'default'` | input |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | input |
| removable | `boolean` | `false` | input |
| selectable | `boolean` | `false` | input |
| chipValue | `string` | `''` | input |
| label | `string` | `''` | input |
| selected | `boolean` | `false` | model (two-way) |
Outputs: `removed: void`, `selectedChange: boolean`
**NgOatChipGroup:**
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| multiple | `boolean` | `false` | input |
| value | `string` | `''` | model (two-way) |
Output: `chipRemoved: string`
**NgOatChipInput:**
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| placeholder | `string` | `'Add item...'` | input |
| maxChips | `number` | `Infinity` | input |
| chips | `string[]` | `[]` | model (two-way) |
Outputs: `chipAdded: string`, `chipRemovedEvent: string`
```html
Angular
React
```
---
## Directive Wrappers (Component Versions)
### NgOatDropdownComponent
Selector: `ng-oat-dropdown`
Import: `import { NgOatDropdownComponent } from '@letsprogram/ng-oat';`
Output: `openChange: boolean`
Methods: `open()`, `close()`, `toggle()`
Content: `[trigger]` attribute for trigger button, `[role="menuitem"]` for items.
```html
```
---
### NgOatTooltipComponent
Selector: `ng-oat-tooltip`
Import: `import { NgOatTooltipComponent } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| text | `string` | `''` |
| template | `TemplateRef \| undefined` | `undefined` |
| position | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` |
| delay | `number` | `700` |
| disabled | `boolean` | `false` |
Methods: `show()`, `hide()`. Signal: `isVisible`.
```html
```
---
### NgOatSidebarComponent
Selector: `ng-oat-sidebar`
Import: `import { NgOatSidebarComponent } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| mode | `'fixed' \| 'overlay'` | `'fixed'` |
| scrollLock | `boolean` | `true` |
| initialOpen | `boolean` | `false` |
Output: `openChange: boolean`
Methods: `open()`, `close()`, `toggle()`. Signal: `isOpen`.
```html
Main content
```
---
### NgOatTabsComponent
Selector: `ng-oat-tabs`
Import: `import { NgOatTabsComponent } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| tabs | `(string \| NgOatTabItem)[]` | **required** |
NgOatTabItem: `{ label: string; disabled?: boolean }`
Output: `tabChange: { index: number; tab: HTMLElement }`
Method: `selectTab(index)`. Signal: `activeIndex`.
```html
Overview content
Details content
Reviews content
```
---
### NgOatDialogComponent
Selector: `ng-oat-dialog`
Import: `import { NgOatDialogComponent } from '@letsprogram/ng-oat';`
Output: `closed: string`
Methods: `showModal()`, `show()`, `close(returnValue?)`
Content slots: `[header]`, default body, `[footer]`.
```html
Confirm
Are you sure?
Cancel
OK
Open Dialog
```
---
## Signal Forms Fields
All form field components implement Angular Signal Forms control interfaces, enabling model-based reactive forms without RxJS.
### NgOatInput
Selector: `ng-oat-input`
Import: `import { NgOatInput } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| type | `'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url' \| 'search' \| 'date' \| 'datetime-local' \| 'time' \| 'month' \| 'week' \| 'color'` | `'text'` | input |
| placeholder | `string` | `''` | input |
| readonly | `boolean` | `false` | input |
| required | `boolean` | `false` | input |
| invalid | `boolean` | `false` | input |
| showErrors | `boolean` | `true` | input |
| min | `number \| undefined` | `undefined` | input |
| max | `number \| undefined` | `undefined` | input |
| minLength | `number \| undefined` | `undefined` | input |
| maxLength | `number \| undefined` | `undefined` | input |
| autocomplete | `string \| undefined` | `undefined` | input |
| errors | `ValidationError[]` | `[]` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
| touched | `boolean` | `false` | model (two-way) |
Implements `FormValueControl`.
```html
```
---
### NgOatTextarea
Selector: `ng-oat-textarea`
Import: `import { NgOatTextarea } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| placeholder | `string` | `''` | input |
| rows | `number` | `4` | input |
| readonly | `boolean` | `false` | input |
| required | `boolean` | `false` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
```html
```
---
### NgOatSelect
Selector: `ng-oat-select`
Import: `import { NgOatSelect } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| placeholder | `string` | `''` | input |
| options | `NgOatSelectOption[]` | **required** | input |
| required | `boolean` | `false` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
NgOatSelectOption: `{ label: string; value: string; disabled?: boolean }`
```html
```
---
### NgOatCheckbox
Selector: `ng-oat-checkbox`
Import: `import { NgOatCheckbox } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| checked | `boolean` | `false` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
Implements `FormCheckboxControl`.
```html
```
---
### NgOatRadioGroup
Selector: `ng-oat-radio-group`
Import: `import { NgOatRadioGroup } from '@letsprogram/ng-oat';`
| Input/Model | Type | Default | Kind |
|-------------|------|---------|------|
| label | `string` | `''` | input |
| options | `NgOatRadioOption[]` | **required** | input |
| required | `boolean` | `false` | input |
| value | `string` | `''` | model (two-way) |
| disabled | `boolean` | `false` | model (two-way) |
NgOatRadioOption: `{ label: string; value: string; disabled?: boolean }`
```html
```
---
### NgOatFormError
Selector: `ng-oat-form-error`
Import: `import { NgOatFormError } from '@letsprogram/ng-oat';`
| Input | Type | Default |
|-------|------|---------|
| control | `FieldState \| undefined` | `undefined` |
| errors | `string[]` | `[]` |
| show | `boolean` | `false` |
Use `control` for Signal Forms, or `errors` + `show` for Reactive/Template forms.
```html
```
---
## Directives
### NgOatDropdown
Selector: `[ngOatDropdown]`
Import: `import { NgOatDropdown } from '@letsprogram/ng-oat';`
Attribute directive that initializes Oat dropdown behavior on a container element.
### NgOatTooltip
Selector: `[ngOatTooltip]`
Import: `import { NgOatTooltip } from '@letsprogram/ng-oat';`
Attribute directive for native Oat tooltips via `data-tooltip`.
### NgOatSidebar
Selector: `[ngOatSidebar]`
Import: `import { NgOatSidebar } from '@letsprogram/ng-oat';`
Attribute directive for Oat sidebar initialization.
### NgOatTabs
Selector: `[ngOatTabs]`
Import: `import { NgOatTabs } from '@letsprogram/ng-oat';`
Attribute directive for Oat tabs initialization.
### NgOatDialog
Selector: `[ngOatDialog]`
Import: `import { NgOatDialog } from '@letsprogram/ng-oat';`
Attribute directive for native `