yukit-web 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,16 +17,16 @@ Angular UI component library for Yurest web applications. Built on [Spartan](htt
17
17
 
18
18
  ## Requirements
19
19
 
20
- | Dependency | Version | Notes |
21
- |:------------------------------------------------------------------|:----------|:-----------------------------------|
22
- | [Angular](https://angular.dev/) | 21+ | Standalone APIs, signal inputs |
23
- | [Tailwind CSS](https://tailwindcss.com/) | v4 | Required — see [Setup](#setup) |
24
- | [`@spartan-ng/brain`](https://spartan.ng) | ^1.3.0 | Headless primitives |
25
- | [`@angular/cdk`](https://material.angular.dev/cdk/categories) | ^21.0.0 | Overlays, a11y |
26
- | [`@ng-icons/core`](https://ng-icons.github.io/ng-icons/) + lucide | ^32.2.0 | Icons |
27
- | [`@tanstack/angular-table`](https://tanstack.com/table) | ^9.0.0 | `<yuw-datatable>` |
28
- | `embla-carousel-angular` | ^21.0.0 | Carousel primitives |
29
- | `ngx-scrollbar` | ^19.1.5 | Scroll areas |
20
+ | Dependency | Version | Notes |
21
+ | :---------------------------------------------------------------- | :------ | :----------------------------- |
22
+ | [Angular](https://angular.dev/) | 21+ | Standalone APIs, signal inputs |
23
+ | [Tailwind CSS](https://tailwindcss.com/) | v4 | Required — see [Setup](#setup) |
24
+ | [`@spartan-ng/brain`](https://spartan.ng) | ^1.3.0 | Headless primitives |
25
+ | [`@angular/cdk`](https://material.angular.dev/cdk/categories) | ^21.0.0 | Overlays, a11y |
26
+ | [`@ng-icons/core`](https://ng-icons.github.io/ng-icons/) + lucide | ^32.2.0 | Icons |
27
+ | [`@tanstack/angular-table`](https://tanstack.com/table) | ^9.0.0 | `<yuw-datatable>` |
28
+ | `embla-carousel-angular` | ^21.0.0 | Carousel primitives |
29
+ | `ngx-scrollbar` | ^19.1.5 | Scroll areas |
30
30
 
31
31
  ## Installation
32
32
 
@@ -55,21 +55,21 @@ app, or the components render unstyled.
55
55
  ```css
56
56
  @layer theme, base, components, utilities;
57
57
 
58
- @import "tailwindcss";
59
- @import "@spartan-ng/brain/hlm-tailwind-preset.css";
60
- @import "yukit-web/theme.css";
58
+ @import 'tailwindcss';
59
+ @import '@spartan-ng/brain/hlm-tailwind-preset.css';
60
+ @import 'yukit-web/theme.css';
61
61
 
62
62
  @source "../node_modules/yukit-web";
63
63
  ```
64
64
 
65
65
  Order matters:
66
66
 
67
- | Line | Why |
68
- |:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------|
69
- | `@layer …` | Fixes layer precedence before anything registers into a layer. |
70
- | `@import "tailwindcss"` | Must come first — everything below extends it. |
71
- | Spartan preset | Maps token *names* (`--primary`, `--radius`, …) onto Tailwind utilities and registers Spartan's variants (`data-open`, `data-checked`, …). |
72
- | `yukit-web/theme.css` | Supplies the Yurest token *values*. Without the preset above it, the custom properties exist but no utilities are generated. |
67
+ | Line | Why |
68
+ | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69
+ | `@layer …` | Fixes layer precedence before anything registers into a layer. |
70
+ | `@import "tailwindcss"` | Must come first — everything below extends it. |
71
+ | Spartan preset | Maps token _names_ (`--primary`, `--radius`, …) onto Tailwind utilities and registers Spartan's variants (`data-open`, `data-checked`, …). |
72
+ | `yukit-web/theme.css` | Supplies the Yurest token _values_. Without the preset above it, the custom properties exist but no utilities are generated. |
73
73
  | `@source` | **Required.** Tailwind only generates the classes it can see. `yukit-web`'s classes live inside the published package, which Tailwind does not scan by default. |
74
74
 
75
75
  Adjust the `@source` path so it resolves from the file it is written in — the example assumes
@@ -107,7 +107,12 @@ import { lucideMail, lucidePlus } from '@ng-icons/lucide';
107
107
  @Component({
108
108
  imports: [NgIcon, YuwButtonComponent],
109
109
  providers: [provideIcons({ lucideMail, lucidePlus })],
110
- template: `<yuw-button><ng-icon name="lucidePlus" /> New</yuw-button>`,
110
+ template: `
111
+ <yuw-button>
112
+ <ng-icon name="lucidePlus" />
113
+ New
114
+ </yuw-button>
115
+ `,
111
116
  })
112
117
  export class ExampleComponent {}
113
118
  ```
@@ -152,14 +157,14 @@ neutral gray.
152
157
  It also adds Yurest-only semantic colors that Spartan has no equivalent for, registered so they
153
158
  behave like any other Tailwind color:
154
159
 
155
- | Token | Utilities |
156
- |:-------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|
157
- | `--success` / `--success-foreground` | `bg-success`, `text-success-foreground`, … |
158
- | `--warning` / `--warning-foreground` | `bg-warning`, `text-warning-foreground`, … |
159
- | `--info` / `--info-foreground` | `bg-info`, `text-info-foreground`, … |
160
+ | Token | Utilities |
161
+ | :----------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
162
+ | `--success` / `--success-foreground` | `bg-success`, `text-success-foreground`, … |
163
+ | `--warning` / `--warning-foreground` | `bg-warning`, `text-warning-foreground`, … |
164
+ | `--info` / `--info-foreground` | `bg-info`, `text-info-foreground`, … |
160
165
  | `--destructive-foreground` | `text-destructive-foreground` — Spartan defines only `--destructive` and hardcodes `text-white`; Yurest names a contrast color, so the pair is completed. |
161
166
 
162
- To override a token, redefine it in your own `:root` *after* importing the theme.
167
+ To override a token, redefine it in your own `:root` _after_ importing the theme.
163
168
 
164
169
  ### The `color` input
165
170
 
@@ -167,9 +172,7 @@ Components that carry brand color (`<yuw-button>`, `<yuw-badge>`, `<yuw-paginati
167
172
  `color` input typed as `YuwColorDto`:
168
173
 
169
174
  ```ts
170
- type YuwColorDto =
171
- | 'primary' | 'secondary' | 'destructive' | 'success'
172
- | 'warning' | 'info' | 'muted' | 'violet';
175
+ type YuwColorDto = 'primary' | 'secondary' | 'destructive' | 'success' | 'warning' | 'info' | 'muted' | 'violet';
173
176
  ```
174
177
 
175
178
  It sets `data-yuw-color` on the host, and the theme remaps the Spartan semantic variables
@@ -199,7 +202,7 @@ A few rules hold across the whole library. Knowing them removes most of the per-
199
202
 
200
203
  **Text is always yours.** No component hardcodes a translatable string. Anything a user reads —
201
204
  labels, empty-state messages, accessible names for icon-only controls — is an input, often a
202
- *required* one (`ariaLabel`, `previousLabel`, `emptyText`, `label`). Pass it already translated.
205
+ _required_ one (`ariaLabel`, `previousLabel`, `emptyText`, `label`). Pass it already translated.
203
206
 
204
207
  **Presence implies the feature.** Instead of a `removable` flag plus a `removeLabel` string, there
205
208
  is one input: set `removeLabel` and the remove control appears, omit it and there is nothing to
@@ -233,49 +236,49 @@ neither source silently overrides the other.
233
236
 
234
237
  ## Components
235
238
 
236
- | Component | Selector | Import |
237
- |:--------------------------------------|:----------------------------------------|:----------------------------------------------|
238
- | **Actions** | | |
239
- | [Button](#button) | `yuw-button` | `YuwButtonComponent` |
240
- | **Form controls** | | |
241
- | [Input](#input) | `yuw-input` | `YuwInputComponent` |
242
- | [Textarea](#textarea) | `yuw-textarea` | `YuwTextareaComponent` |
243
- | [Search input](#search-input) | `yuw-search-input` | `YuwSearchInputComponent` |
244
- | [Password input](#password-input) | `yuw-password-input` | `YuwPasswordInputComponent` |
245
- | [Input OTP](#input-otp) | `yuw-input-otp` | `YuwInputOtpComponent` |
246
- | [Label](#label) | `label[yuwLabel]` | `YuwLabel` |
247
- | [Checkbox](#checkbox) | `yuw-checkbox` | `YuwCheckboxComponent` |
248
- | [Switch](#switch) | `yuw-switch` | `YuwSwitchComponent` |
249
- | [Radio group](#radio-group) | `yuw-radio-group` | `YuwRadioGroupComponent` |
250
- | [Combobox](#combobox) | `yuw-combobox` | `YuwComboboxComponent` |
251
- | [Datepicker](#datepicker) | `yuw-datepicker` | `YuwDatepickerComponent` |
252
- | **Data display** | | |
253
- | [Avatar](#avatar) | `yuw-avatar` | `YuwAvatarComponent` |
254
- | [Badge](#badge) | `yuw-badge` | `YuwBadgeComponent` |
255
- | [Card](#card) | `[yuwCard]` | `YuwCardImports` |
256
- | [Item](#item) | `[yuwItem]` | `YuwItemImports` |
257
- | [Attachment](#attachment) | `[yuwAttachment]` | `YuwAttachmentDirective`, … |
258
- | [Table](#table) | `[yuwTable]` | `YuwTableImports` |
259
- | [Datatable](#datatable) | `yuw-datatable` | `YuwDatatableComponent` |
260
- | [Empty](#empty) | `[yuwEmpty]` | `YuwEmptyImports` |
261
- | [Skeleton](#skeleton) | `[yuwSkeleton]` | `YuwSkeletonDirective` |
262
- | [Spinner](#spinner) | `yuw-spinner` | `YuwSpinnerComponent` |
263
- | **Navigation** | | |
264
- | [Accordion](#accordion) | `yuw-accordion` | `YuwAccordionImports` |
265
- | [Breadcrumb](#breadcrumb) | `yuw-breadcrumb` | `YuwBreadcrumbComponent` |
266
- | [Pagination](#pagination) | `yuw-pagination` | `YuwPaginationComponent` |
267
- | [Tabs](#tabs) | `yuw-tabs` | `YuwTabsComponent`, `YuwTabPanelDirective` |
268
- | [Sidebar](#sidebar) | `yuw-sidebar` | `YuwSidebarComponent`, … |
269
- | **Overlays** | | |
270
- | [Dialog](#dialog) | `yuw-dialog` | `YuwDialogImports` |
271
- | [Alert dialog](#alert-dialog) | `yuw-alert-dialog` | `YuwAlertDialogComponent` |
272
- | [Sheet](#sheet) | `yuw-sheet` | `YuwSheetImports` |
273
- | [Popover](#popover) | `yuw-popover` | `YuwPopoverComponent` |
274
- | [Tooltip](#tooltip) | `[yuwTooltip]` | `YuwTooltipDirective` |
275
- | [Context menu](#context-menu) | `[yuwContextMenuTrigger]` | `YuwContextMenuImports` |
276
- | **Feedback** | | |
277
- | [Alert](#alert) | `yuw-alert` | `YuwAlertImports` |
278
- | [Toaster](#toaster) | `yuw-toaster` | `YuwToasterComponent`, `yuwToast` |
239
+ | Component | Selector | Import |
240
+ | :-------------------------------- | :------------------------ | :----------------------------------------- |
241
+ | **Actions** | | |
242
+ | [Button](#button) | `yuw-button` | `YuwButtonComponent` |
243
+ | **Form controls** | | |
244
+ | [Input](#input) | `yuw-input` | `YuwInputComponent` |
245
+ | [Textarea](#textarea) | `yuw-textarea` | `YuwTextareaComponent` |
246
+ | [Search input](#search-input) | `yuw-search-input` | `YuwSearchInputComponent` |
247
+ | [Password input](#password-input) | `yuw-password-input` | `YuwPasswordInputComponent` |
248
+ | [Input OTP](#input-otp) | `yuw-input-otp` | `YuwInputOtpComponent` |
249
+ | [Label](#label) | `label[yuwLabel]` | `YuwLabel` |
250
+ | [Checkbox](#checkbox) | `yuw-checkbox` | `YuwCheckboxComponent` |
251
+ | [Switch](#switch) | `yuw-switch` | `YuwSwitchComponent` |
252
+ | [Radio group](#radio-group) | `yuw-radio-group` | `YuwRadioGroupComponent` |
253
+ | [Combobox](#combobox) | `yuw-combobox` | `YuwComboboxComponent` |
254
+ | [Datepicker](#datepicker) | `yuw-datepicker` | `YuwDatepickerComponent` |
255
+ | **Data display** | | |
256
+ | [Avatar](#avatar) | `yuw-avatar` | `YuwAvatarComponent` |
257
+ | [Badge](#badge) | `yuw-badge` | `YuwBadgeComponent` |
258
+ | [Card](#card) | `[yuwCard]` | `YuwCardImports` |
259
+ | [Item](#item) | `[yuwItem]` | `YuwItemImports` |
260
+ | [Attachment](#attachment) | `[yuwAttachment]` | `YuwAttachmentDirective`, … |
261
+ | [Table](#table) | `[yuwTable]` | `YuwTableImports` |
262
+ | [Datatable](#datatable) | `yuw-datatable` | `YuwDatatableComponent` |
263
+ | [Empty](#empty) | `[yuwEmpty]` | `YuwEmptyImports` |
264
+ | [Skeleton](#skeleton) | `[yuwSkeleton]` | `YuwSkeletonDirective` |
265
+ | [Spinner](#spinner) | `yuw-spinner` | `YuwSpinnerComponent` |
266
+ | **Navigation** | | |
267
+ | [Accordion](#accordion) | `yuw-accordion` | `YuwAccordionImports` |
268
+ | [Breadcrumb](#breadcrumb) | `yuw-breadcrumb` | `YuwBreadcrumbComponent` |
269
+ | [Pagination](#pagination) | `yuw-pagination` | `YuwPaginationComponent` |
270
+ | [Tabs](#tabs) | `yuw-tabs` | `YuwTabsComponent`, `YuwTabPanelDirective` |
271
+ | [Sidebar](#sidebar) | `yuw-sidebar` | `YuwSidebarComponent`, … |
272
+ | **Overlays** | | |
273
+ | [Dialog](#dialog) | `yuw-dialog` | `YuwDialogImports` |
274
+ | [Alert dialog](#alert-dialog) | `yuw-alert-dialog` | `YuwAlertDialogComponent` |
275
+ | [Sheet](#sheet) | `yuw-sheet` | `YuwSheetImports` |
276
+ | [Popover](#popover) | `yuw-popover` | `YuwPopoverComponent` |
277
+ | [Tooltip](#tooltip) | `[yuwTooltip]` | `YuwTooltipDirective` |
278
+ | [Context menu](#context-menu) | `[yuwContextMenuTrigger]` | `YuwContextMenuImports` |
279
+ | **Feedback** | | |
280
+ | [Alert](#alert) | `yuw-alert` | `YuwAlertImports` |
281
+ | [Toaster](#toaster) | `yuw-toaster` | `YuwToasterComponent`, `yuwToast` |
279
282
 
280
283
  ---
281
284
 
@@ -298,36 +301,35 @@ Single action button, link, or a welded group of buttons.
298
301
 
299
302
  #### Inputs
300
303
 
301
- | Input | Type | Default |
302
- |:-----------------|:---------------------------------------------------------------------------------|:---------------|
303
- | `variant` | `'default'|'secondary'|'outline'|'destructive'|'ghost'|'link'` | `'default'` |
304
- | `size` | `'default'|'xs'|'sm'|'lg'|'icon'|'icon-xs'|'icon-sm'|'icon-lg'` | `'default'` |
305
- | `color` | `YuwColorDto` | `'secondary'` |
306
- | `disabled` | `boolean` | `false` |
307
- | `type` | `'button'|'submit'|'reset'` | `'button'` |
308
- | `href` | `string|undefined` | `undefined` |
309
- | `target` | `string|undefined` | `undefined` |
310
- | `transparent` | `boolean` — removes background and border | `false` |
311
- | `ariaLabel` | `string|undefined` — required for icon-only buttons | `undefined` |
312
- | `class` | `string` — merged onto the inner button/anchor, wins over defaults | `''` |
313
- | `buttons` | `YuwButtonGroupItemDto[]|undefined` — switches to group mode | `undefined` |
314
- | `orientation` | `'horizontal'|'vertical'` — group layout | `'horizontal'` |
315
- | `groupAriaLabel` | `string|undefined` — accessible name of the group | `undefined` |
316
- | `yuwDropdownMenuTrigger` | `TemplateRef<unknown>|undefined` | `undefined` |
304
+ | Input | Type | Default |
305
+ | :----------------------- | :--------------------------------------------------------------------- | :------------- |
306
+ | `variant` | `'default'|'secondary'|'outline'|'destructive'|'ghost'|'link'` | `'default'` |
307
+ | `size` | `'default'|'xs'|'sm'|'lg'|'icon'|'icon-xs'|'icon-sm'|'icon-lg'` | `'default'` |
308
+ | `color` | `YuwColorDto` | `'secondary'` |
309
+ | `disabled` | `boolean` | `false` |
310
+ | `type` | `'button'|'submit'|'reset'` | `'button'` |
311
+ | `href` | `string|undefined` | `undefined` |
312
+ | `target` | `string|undefined` | `undefined` |
313
+ | `transparent` | `boolean` — removes background and border | `false` |
314
+ | `ariaLabel` | `string|undefined` — required for icon-only buttons | `undefined` |
315
+ | `class` | `string` — merged onto the inner button/anchor, wins over defaults | `''` |
316
+ | `buttons` | `YuwButtonGroupItemDto[]|undefined` — switches to group mode | `undefined` |
317
+ | `orientation` | `'horizontal'|'vertical'` — group layout | `'horizontal'` |
318
+ | `groupAriaLabel` | `string|undefined` — accessible name of the group | `undefined` |
319
+ | `yuwDropdownMenuTrigger` | `TemplateRef<unknown>|undefined` | `undefined` |
317
320
 
318
321
  #### Outputs
319
322
 
320
- | Output | Payload | Description |
321
- |:----------------|:------------------------|:----------------------------------------|
322
- | `clicked` | `MouseEvent` | Single-button mode. |
323
- | `buttonClicked` | `YuwButtonGroupClickDto`| Group mode — `{ id, event }`. |
323
+ | Output | Payload | Description |
324
+ | :-------------- | :----------------------- | :---------------------------- |
325
+ | `clicked` | `MouseEvent` | Single-button mode. |
326
+ | `buttonClicked` | `YuwButtonGroupClickDto` | Group mode — `{ id, event }`. |
324
327
 
325
328
  #### Content slots
326
329
 
327
- | Slot | Description |
328
- |:-----------------|:-------------------------------------|
329
- | `[yuwButtonIcon]`| Leading icon. |
330
- | *(default)* | Button label. |
330
+ | Slot | Description |
331
+ | :---------- | :------------ |
332
+ | _(default)_ | Button label. |
331
333
 
332
334
  `YuwButtonGroupItemDto` entries are `{ id, label }` plus optional `variant`, `size`, `color`,
333
335
  `disabled`, `href`, `target`, `type`, `ariaLabel`, `transparent` — each falling back to the
@@ -350,15 +352,15 @@ Single-line text field with addon slots and form integration.
350
352
  #### Inputs
351
353
 
352
354
  | Input | Type | Default |
353
- |:---------------|:-------------------------------------------------|:------------|
355
+ | :------------- | :----------------------------------------------- | :---------- |
354
356
  | `value` | `string` — two-way | `''` |
355
- | `inputId` | `string|undefined` — for external `<label for>` | `undefined` |
356
- | `type` | `'text'|'email'|'tel'|'url'|'number'` | `'text'` |
357
- | `inputmode` | `YuwInputModeDto|undefined` | `undefined` |
358
- | `placeholder` | `string|undefined` | `undefined` |
359
- | `maxlength` | `number|undefined` | `undefined` |
360
- | `name` | `string|undefined` | `undefined` |
361
- | `autocomplete` | `string|undefined` | `undefined` |
357
+ | `inputId` | `string|undefined` — for external `<label for>` | `undefined` |
358
+ | `type` | `'text'|'email'|'tel'|'url'|'number'` | `'text'` |
359
+ | `inputmode` | `YuwInputModeDto|undefined` | `undefined` |
360
+ | `placeholder` | `string|undefined` | `undefined` |
361
+ | `maxlength` | `number|undefined` | `undefined` |
362
+ | `name` | `string|undefined` | `undefined` |
363
+ | `autocomplete` | `string|undefined` | `undefined` |
362
364
  | `disabled` | `boolean` | `false` |
363
365
  | `readonly` | `boolean` | `false` |
364
366
  | `required` | `boolean` | `false` |
@@ -367,8 +369,8 @@ Single-line text field with addon slots and form integration.
367
369
 
368
370
  #### Outputs
369
371
 
370
- | Output | Payload | Description |
371
- |:------------|:---------|:------------------------------------------------|
372
+ | Output | Payload | Description |
373
+ | :---------- | :------- | :------------------------------------------------- |
372
374
  | `committed` | `string` | Current value on the native `change` (blur/enter). |
373
375
 
374
376
  #### Content slots
@@ -390,14 +392,14 @@ Multi-line text field. Auto-grows where `field-sizing` is supported.
390
392
 
391
393
  Same contract as [Input](#input), minus `type` / `inputmode`, plus:
392
394
 
393
- | Input | Type | Default |
394
- |:-------|:-------------------|:------------|
395
+ | Input | Type | Default |
396
+ | :----- | :------------------ | :---------- |
395
397
  | `rows` | `number|undefined` | `undefined` |
396
398
 
397
399
  #### Outputs
398
400
 
399
- | Output | Payload | Description |
400
- |:------------|:---------|:-------------------------------------------|
401
+ | Output | Payload | Description |
402
+ | :---------- | :------- | :------------------------------------------ |
401
403
  | `committed` | `string` | Current value on the native `change` event. |
402
404
 
403
405
  ---
@@ -419,16 +421,16 @@ Text field with a leading search icon and an optional clear button.
419
421
 
420
422
  Same contract as [Input](#input), minus `type` / `inputmode` / `maxlength`, plus:
421
423
 
422
- | Input | Type | Default |
423
- |:-----------------|:-------------------|:------------|
424
+ | Input | Type | Default |
425
+ | :--------------- | :------------------------------------------------------ | :---------- |
424
426
  | `clearAriaLabel` | `string|undefined` — set it to render the clear button | `undefined` |
425
427
 
426
428
  #### Outputs
427
429
 
428
- | Output | Payload | Description |
429
- |:------------|:---------|:--------------------------------------------------|
430
- | `searched` | `string` | Emitted on every keystroke. |
431
- | `committed` | `string` | Emitted on Enter — for search-on-submit flows. |
430
+ | Output | Payload | Description |
431
+ | :---------- | :------- | :--------------------------------------------- |
432
+ | `searched` | `string` | Emitted on every keystroke. |
433
+ | `committed` | `string` | Emitted on Enter — for search-on-submit flows. |
432
434
 
433
435
  ---
434
436
 
@@ -446,14 +448,14 @@ Password field with an optional reveal toggle.
446
448
  Same contract as [Input](#input), minus `type` / `inputmode` / `maxlength`, plus:
447
449
 
448
450
  | Input | Type | Default |
449
- |:------------------|:----------------------------------------------------|:------------|
450
- | `revealAriaLabel` | `string|undefined` — set it to render the toggle | `undefined` |
451
- | `masked` | `boolean` — two-way; a parent can re-mask the value | `true` |
451
+ | :---------------- | :-------------------------------------------------- | :---------- |
452
+ | `revealAriaLabel` | `string|undefined` — set it to render the toggle | `undefined` |
453
+ | `masked` | `boolean` — two-way; a parent can re-mask the value | `true` |
452
454
 
453
455
  #### Outputs
454
456
 
455
- | Output | Payload | Description |
456
- |:------------|:---------|:-------------------------------------------|
457
+ | Output | Payload | Description |
458
+ | :---------- | :------- | :------------------------------------------ |
457
459
  | `committed` | `string` | Current value on the native `change` event. |
458
460
 
459
461
  ---
@@ -469,23 +471,23 @@ One-time password / verification code field, rendered as grouped slots.
469
471
 
470
472
  #### Inputs
471
473
 
472
- | Input | Type | Default |
473
- |:-----------------|:----------------------------------------------|:------------------------|
474
- | `value` | `string` — two-way | `''` |
475
- | `groupSizes` | `readonly number[]` — `[3, 3]` renders `000-000` | `[6]` |
476
- | `mode` | `'numeric'|'text'` | `'numeric'` |
477
- | `inputId` | `string|undefined` | `undefined` |
478
- | `disabled` | `boolean` | `false` |
479
- | `invalid` | `boolean` | `false` |
480
- | `autofocus` | `boolean` | `false` |
481
- | `transformPaste` | `(pastedText: string, length: number) => string` | identity |
482
- | `class` | `string` | `''` |
474
+ | Input | Type | Default |
475
+ | :--------------- | :----------------------------------------------- | :---------- |
476
+ | `value` | `string` — two-way | `''` |
477
+ | `groupSizes` | `readonly number[]` — `[3, 3]` renders `000-000` | `[6]` |
478
+ | `mode` | `'numeric'|'text'` | `'numeric'` |
479
+ | `inputId` | `string|undefined` | `undefined` |
480
+ | `disabled` | `boolean` | `false` |
481
+ | `invalid` | `boolean` | `false` |
482
+ | `autofocus` | `boolean` | `false` |
483
+ | `transformPaste` | `(pastedText: string, length: number) => string` | identity |
484
+ | `class` | `string` | `''` |
483
485
 
484
486
  #### Outputs
485
487
 
486
- | Output | Payload | Description |
487
- |:------------|:---------|:----------------------------------------------------|
488
- | `completed` | `string` | The full code, once the final slot is filled. |
488
+ | Output | Payload | Description |
489
+ | :---------- | :------- | :-------------------------------------------- |
490
+ | `completed` | `string` | The full code, once the final slot is filled. |
489
491
 
490
492
  ---
491
493
 
@@ -515,19 +517,19 @@ the text toggles it and the text is announced as the accessible name.
515
517
 
516
518
  #### Inputs
517
519
 
518
- | Input | Type | Default |
519
- |:------------------|:---------------------------|:------------|
520
- | `checked` | `boolean` — two-way (alias of `value`) | `false` |
521
- | `indeterminate` | `boolean` — two-way | `false` |
522
- | `secondary` | `boolean` — secondary fill | `false` |
523
- | `disabled` | `boolean` | `false` |
524
- | `required` | `boolean` | `false` |
525
- | `invalid` | `boolean` | `false` |
526
- | `name` | `string|undefined` | `undefined` |
527
- | `inputId` | `string|undefined` | `undefined` |
528
- | `ariaLabel` | `string|undefined` | `undefined` |
529
- | `ariaLabelledby` | `string|undefined` | `undefined` |
530
- | `ariaDescribedby` | `string|undefined` | `undefined` |
520
+ | Input | Type | Default |
521
+ | :---------------- | :------------------------------------- | :---------- |
522
+ | `checked` | `boolean` — two-way (alias of `value`) | `false` |
523
+ | `indeterminate` | `boolean` — two-way | `false` |
524
+ | `secondary` | `boolean` — secondary fill | `false` |
525
+ | `disabled` | `boolean` | `false` |
526
+ | `required` | `boolean` | `false` |
527
+ | `invalid` | `boolean` | `false` |
528
+ | `name` | `string|undefined` | `undefined` |
529
+ | `inputId` | `string|undefined` | `undefined` |
530
+ | `ariaLabel` | `string|undefined` | `undefined` |
531
+ | `ariaLabelledby` | `string|undefined` | `undefined` |
532
+ | `ariaDescribedby` | `string|undefined` | `undefined` |
531
533
 
532
534
  ---
533
535
 
@@ -542,15 +544,15 @@ Toggle for binary settings. Projected content becomes the clickable label.
542
544
 
543
545
  #### Inputs
544
546
 
545
- | Input | Type | Default |
546
- |:------------------|:-------------------|:------------|
547
- | `checked` | `boolean` — two-way (alias of `value`) | `false` |
548
- | `size` | `'default'|'sm'` | `'default'` |
549
- | `disabled` | `boolean` | `false` |
550
- | `inputId` | `string|undefined` | `undefined` |
551
- | `ariaLabel` | `string|undefined` | `undefined` |
552
- | `ariaLabelledby` | `string|undefined` | `undefined` |
553
- | `ariaDescribedby` | `string|undefined` | `undefined` |
547
+ | Input | Type | Default |
548
+ | :---------------- | :------------------------------------- | :---------- |
549
+ | `checked` | `boolean` — two-way (alias of `value`) | `false` |
550
+ | `size` | `'default'|'sm'` | `'default'` |
551
+ | `disabled` | `boolean` | `false` |
552
+ | `inputId` | `string|undefined` | `undefined` |
553
+ | `ariaLabel` | `string|undefined` | `undefined` |
554
+ | `ariaLabelledby` | `string|undefined` | `undefined` |
555
+ | `ariaDescribedby` | `string|undefined` | `undefined` |
554
556
 
555
557
  ---
556
558
 
@@ -572,14 +574,14 @@ interface YuwRadioOptionDto {
572
574
  #### Inputs
573
575
 
574
576
  | Input | Type | Default |
575
- |:-----------------|:----------------------------------------------|:------------|
576
- | `options` | `readonly YuwRadioOptionDto[]` — **required** | — |
577
- | `value` | `string|undefined` — two-way | `undefined` |
578
- | `disabled` | `boolean` — disables the whole group | `false` |
577
+ | :--------------- | :-------------------------------------------- | :---------- |
578
+ | `options` | `readonly YuwRadioOptionDto[]` — **required** | — |
579
+ | `value` | `string|undefined` — two-way | `undefined` |
580
+ | `disabled` | `boolean` — disables the whole group | `false` |
579
581
  | `required` | `boolean` | `false` |
580
- | `name` | `string|undefined` — generated when omitted | `undefined` |
581
- | `ariaLabel` | `string|undefined` | `undefined` |
582
- | `ariaLabelledby` | `string|undefined` | `undefined` |
582
+ | `name` | `string|undefined` — generated when omitted | `undefined` |
583
+ | `ariaLabel` | `string|undefined` | `undefined` |
584
+ | `ariaLabelledby` | `string|undefined` | `undefined` |
583
585
  | `class` | `string` — layout tweaks (`grid-cols-2`, …) | `''` |
584
586
 
585
587
  ---
@@ -601,17 +603,22 @@ optional custom option templates.
601
603
  />
602
604
 
603
605
  <!-- Classic select shape -->
604
- <yuw-combobox readonlyTrigger [options]="colorOptions" [(value)]="color"
605
- searchPlaceholder="Search colors…" triggerAriaLabel="Toggle options" />
606
+ <yuw-combobox
607
+ readonlyTrigger
608
+ [options]="colorOptions"
609
+ [(value)]="color"
610
+ searchPlaceholder="Search colors…"
611
+ triggerAriaLabel="Toggle options"
612
+ />
606
613
 
607
614
  <!-- Multiple, with chips -->
608
- <yuw-combobox multiple [options]="categoryOptions" [(value)]="categories"
609
- triggerAriaLabel="Toggle options" />
615
+ <yuw-combobox multiple [options]="categoryOptions" [(value)]="categories" triggerAriaLabel="Toggle options" />
610
616
 
611
617
  <!-- Custom option template -->
612
618
  <yuw-combobox [options]="users" [(value)]="userId" triggerAriaLabel="Toggle options">
613
619
  <ng-template yuwComboboxItem let-option let-selected="selected">
614
- <img [src]="option.data.avatar" /> {{ option.label }}
620
+ <img [src]="option.data.avatar" />
621
+ {{ option.label }}
615
622
  </ng-template>
616
623
  </yuw-combobox>
617
624
  ```
@@ -621,27 +628,27 @@ interface YuwComboboxOptionDto<TData = unknown> {
621
628
  value: string;
622
629
  label: string;
623
630
  disabled?: boolean;
624
- data?: TData; // available as `option.data` in a custom item template
631
+ data?: TData; // available as `option.data` in a custom item template
625
632
  }
626
633
  ```
627
634
 
628
635
  #### Inputs
629
636
 
630
- | Input | Type | Default |
631
- |:--------------------|:--------------------------------------------------|:------------|
632
- | `options` | `YuwComboboxOptionDto<TData>[]` — **required** | — |
633
- | `value` | `string|string[]|undefined` — two-way | `undefined` |
634
- | `multiple` | `boolean` — chips shape; takes precedence over `readonlyTrigger` | `false` |
635
- | `readonlyTrigger` | `boolean` — button trigger, search inside popover | `false` |
636
- | `search` | `string` — two-way filter query | `''` |
637
- | `placeholder` | `string|undefined` | `undefined` |
638
- | `searchPlaceholder` | `string|undefined` | `undefined` |
639
- | `emptyText` | `string|undefined` | `undefined` |
640
- | `triggerAriaLabel` | `string` — **required** | — |
641
- | `clearAriaLabel` | `string|undefined` — set it to render a clear button | `undefined` |
642
- | `inputId` | `string|undefined` | `undefined` |
643
- | `disabled` | `boolean` | `false` |
644
- | `invalid` | `boolean` | `false` |
637
+ | Input | Type | Default |
638
+ | :------------------ | :--------------------------------------------------------------- | :---------- |
639
+ | `options` | `YuwComboboxOptionDto<TData>[]` — **required** | — |
640
+ | `value` | `string|string[]|undefined` — two-way | `undefined` |
641
+ | `multiple` | `boolean` — chips shape; takes precedence over `readonlyTrigger` | `false` |
642
+ | `readonlyTrigger` | `boolean` — button trigger, search inside popover | `false` |
643
+ | `search` | `string` — two-way filter query | `''` |
644
+ | `placeholder` | `string|undefined` | `undefined` |
645
+ | `searchPlaceholder` | `string|undefined` | `undefined` |
646
+ | `emptyText` | `string|undefined` | `undefined` |
647
+ | `triggerAriaLabel` | `string` — **required** | — |
648
+ | `clearAriaLabel` | `string|undefined` — set it to render a clear button | `undefined` |
649
+ | `inputId` | `string|undefined` | `undefined` |
650
+ | `disabled` | `boolean` | `false` |
651
+ | `invalid` | `boolean` | `false` |
645
652
 
646
653
  ---
647
654
 
@@ -655,20 +662,20 @@ interface YuwComboboxOptionDto<TData = unknown> {
655
662
 
656
663
  #### Inputs
657
664
 
658
- | Input | Type | Default |
659
- |:----------------|:-----------------------------------------------------------------|:------------|
660
- | `mode` | `'single'|'range'|'multiple'|'monthYear'` | `'single'` |
661
- | `value` | `Date|[Date, Date]|Date[]|null` — two-way, shape follows `mode` | `null` |
662
- | `minDate` | `Date|undefined` | `undefined` |
663
- | `maxDate` | `Date|undefined` | `undefined` |
664
- | `captionLayout` | `'label'|'dropdown'|'dropdown-months'|'dropdown-years'` | `'label'` |
665
+ | Input | Type | Default |
666
+ | :-------------- | :----------------------------------------------------------------- | :---------- |
667
+ | `mode` | `'single'|'range'|'multiple'|'monthYear'` | `'single'` |
668
+ | `value` | `Date|[Date, Date]|Date[]|null` — two-way, shape follows `mode` | `null` |
669
+ | `minDate` | `Date|undefined` | `undefined` |
670
+ | `maxDate` | `Date|undefined` | `undefined` |
671
+ | `captionLayout` | `'label'|'dropdown'|'dropdown-months'|'dropdown-years'` | `'label'` |
665
672
  | `align` | `'start'|'center'|'end'` | `'start'` |
666
- | `placeholder` | `string|undefined` | `undefined` |
667
- | `buttonId` | `string|undefined` — generated when omitted | `undefined` |
668
- | `formatDate` | `((date: Date) => string)|undefined` | `undefined` |
669
- | `disabled` | `boolean` | `false` |
670
- | `invalid` | `boolean` | `false` |
671
- | `class` | `string` — merged onto the trigger button | `''` |
673
+ | `placeholder` | `string|undefined` | `undefined` |
674
+ | `buttonId` | `string|undefined` — generated when omitted | `undefined` |
675
+ | `formatDate` | `((date: Date) => string)|undefined` | `undefined` |
676
+ | `disabled` | `boolean` | `false` |
677
+ | `invalid` | `boolean` | `false` |
678
+ | `class` | `string` — merged onto the trigger button | `''` |
672
679
 
673
680
  `captionLayout` is ignored in `monthYear` mode, which renders its own month/year grid.
674
681
 
@@ -693,14 +700,14 @@ interface YuwAvatarGroupItemDto {
693
700
  #### Inputs
694
701
 
695
702
  | Input | Type | Default |
696
- |:-------------|:----------------------------------------|:------------|
703
+ | :----------- | :-------------------------------------- | :---------- |
697
704
  | `alt` | `string` — **required** | — |
698
- | `src` | `string|undefined` | `undefined` |
699
- | `fallback` | `string|undefined` — initials | `undefined` |
700
- | `size` | `'default'|'sm'|'lg'` | `'default'` |
705
+ | `src` | `string|undefined` | `undefined` |
706
+ | `fallback` | `string|undefined` — initials | `undefined` |
707
+ | `size` | `'default'|'sm'|'lg'` | `'default'` |
701
708
  | `badge` | `boolean` — status marker, bottom-right | `false` |
702
- | `group` | `YuwAvatarGroupItemDto[]|undefined` | `undefined` |
703
- | `groupCount` | `string|undefined` — overflow label | `undefined` |
709
+ | `group` | `YuwAvatarGroupItemDto[]|undefined` | `undefined` |
710
+ | `groupCount` | `string|undefined` — overflow label | `undefined` |
704
711
  | `class` | `string` | `''` |
705
712
 
706
713
  #### Content slots
@@ -719,18 +726,18 @@ interface YuwAvatarGroupItemDto {
719
726
 
720
727
  #### Inputs
721
728
 
722
- | Input | Type | Default |
723
- |:--------------|:-------------------------------------------------------------------|:------------|
724
- | `color` | `YuwColorDto` | `'primary'` |
725
- | `variant` | `'default'|'secondary'|'destructive'|'outline'|'ghost'|'link'` | `'default'` |
726
- | `dot` | `boolean` — compact dot, renders no content | `false` |
729
+ | Input | Type | Default |
730
+ | :------------ | :------------------------------------------------------------------ | :---------- |
731
+ | `color` | `YuwColorDto` | `'primary'` |
732
+ | `variant` | `'default'|'secondary'|'destructive'|'outline'|'ghost'|'link'` | `'default'` |
733
+ | `dot` | `boolean` — compact dot, renders no content | `false` |
727
734
  | `removeLabel` | `string|undefined` — set it to render the dismiss button | `undefined` |
728
735
 
729
736
  #### Outputs
730
737
 
731
- | Output | Payload | Description |
732
- |:----------|:--------|:-----------------------------------|
733
- | `removed` | `void` | Dismiss button activated. |
738
+ | Output | Payload | Description |
739
+ | :-------- | :------ | :------------------------ |
740
+ | `removed` | `void` | Dismiss button activated. |
734
741
 
735
742
  #### Content slots
736
743
 
@@ -754,15 +761,15 @@ Directives applied to your own elements — no wrapper element is inserted.
754
761
  </div>
755
762
  ```
756
763
 
757
- | Directive | Notes |
758
- |:--------------------|:-----------------------------|
759
- | `[yuwCard]` | `size`: `'default'|'sm'` |
760
- | `[yuwCardHeader]` | |
761
- | `[yuwCardTitle]` | |
764
+ | Directive | Notes |
765
+ | :--------------------- | :------------------------ |
766
+ | `[yuwCard]` | `size`: `'default'|'sm'` |
767
+ | `[yuwCardHeader]` | |
768
+ | `[yuwCardTitle]` | |
762
769
  | `[yuwCardDescription]` | |
763
- | `[yuwCardAction]` | Top-right action area. |
764
- | `[yuwCardContent]` | |
765
- | `[yuwCardFooter]` | |
770
+ | `[yuwCardAction]` | Top-right action area. |
771
+ | `[yuwCardContent]` | |
772
+ | `[yuwCardFooter]` | |
766
773
 
767
774
  Import them all at once with `YuwCardImports`.
768
775
 
@@ -783,18 +790,18 @@ Row/list layout primitive.
783
790
  </div>
784
791
  ```
785
792
 
786
- | Directive | Notes |
787
- |:-------------------------|:--------------------------------------------------|
788
- | `[yuwItem]` | `variant`: `'default'|'outline'|'muted'`, `size`: `'default'|'sm'|'xs'` |
789
- | `[yuwItemHeader]` | |
790
- | `[yuwItemMedia]` | `variant`: `'default'|'icon'|'image'` |
791
- | `[yuwItemContent]` | |
792
- | `[yuwItemTitle]` | |
793
- | `[yuwItemDescription]` | |
794
- | `[yuwItemActions]` | |
795
- | `[yuwItemFooter]` | |
796
- | `[yuwItemGroup]` | |
797
- | `[yuwItemSeparator]` | |
793
+ | Directive | Notes |
794
+ | :--------------------- | :-------------------------------------------------------------------------- |
795
+ | `[yuwItem]` | `variant`: `'default'|'outline'|'muted'`, `size`: `'default'|'sm'|'xs'` |
796
+ | `[yuwItemHeader]` | |
797
+ | `[yuwItemMedia]` | `variant`: `'default'|'icon'|'image'` |
798
+ | `[yuwItemContent]` | |
799
+ | `[yuwItemTitle]` | |
800
+ | `[yuwItemDescription]` | |
801
+ | `[yuwItemActions]` | |
802
+ | `[yuwItemFooter]` | |
803
+ | `[yuwItemGroup]` | |
804
+ | `[yuwItemSeparator]` | |
798
805
 
799
806
  Import them all at once with `YuwItemImports`. Each directive also accepts the `yuw-item-*` element
800
807
  form (`<yuw-item-title>`).
@@ -818,17 +825,17 @@ File attachment card, with upload states.
818
825
  </div>
819
826
  ```
820
827
 
821
- | Directive | Notes |
822
- |:------------------------------|:----------------------------------------------------------------------|
828
+ | Directive | Notes |
829
+ | :---------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
823
830
  | `[yuwAttachment]` | `state`: `'idle'|'uploading'|'processing'|'error'|'done'`, `size`: `'default'|'sm'|'xs'`, `orientation`: `'horizontal'|'vertical'` |
824
- | `[yuwAttachmentGroup]` | |
825
- | `[yuwAttachmentMedia]` | `variant`: `'icon'|'image'` |
826
- | `[yuwAttachmentContent]` | |
827
- | `[yuwAttachmentTitle]` | |
828
- | `[yuwAttachmentDescription]` | |
829
- | `[yuwAttachmentActions]` | |
830
- | `button[yuwAttachmentAction]` | Action button inside the card. |
831
- | `[yuwAttachmentTrigger]` | Makes a `<button>` / `<a>` the card's primary trigger. |
831
+ | `[yuwAttachmentGroup]` | |
832
+ | `[yuwAttachmentMedia]` | `variant`: `'icon'|'image'` |
833
+ | `[yuwAttachmentContent]` | |
834
+ | `[yuwAttachmentTitle]` | |
835
+ | `[yuwAttachmentDescription]` | |
836
+ | `[yuwAttachmentActions]` | |
837
+ | `button[yuwAttachmentAction]` | Action button inside the card. |
838
+ | `[yuwAttachmentTrigger]` | Makes a `<button>` / `<a>` the card's primary trigger. |
832
839
 
833
840
  ---
834
841
 
@@ -841,10 +848,16 @@ Styling directives for a table you write yourself.
841
848
  <table yuwTable>
842
849
  <caption yuwCaption>Team members and their roles.</caption>
843
850
  <thead yuwTHead>
844
- <tr yuwTr><th yuwTh>Name</th><th yuwTh>Role</th></tr>
851
+ <tr yuwTr>
852
+ <th yuwTh>Name</th>
853
+ <th yuwTh>Role</th>
854
+ </tr>
845
855
  </thead>
846
856
  <tbody yuwTBody>
847
- <tr yuwTr><td yuwTd>Ada Lovelace</td><td yuwTd>Engineer</td></tr>
857
+ <tr yuwTr>
858
+ <td yuwTd>Ada Lovelace</td>
859
+ <td yuwTd>Engineer</td>
860
+ </tr>
848
861
  </tbody>
849
862
  <tfoot yuwTFoot>…</tfoot>
850
863
  </table>
@@ -878,33 +891,33 @@ Sorting, pagination, row selection, column visibility and a loading skeleton, ov
878
891
 
879
892
  #### Inputs
880
893
 
881
- | Input | Type | Default |
882
- |:--------------------|:----------------------------------------------|:-------------------------------|
883
- | `columns` | `YuwDatatableColumnDef<TData>[]` | `[]` |
884
- | `data` | `TData[]` | `[]` |
885
- | `sortable` | `boolean` | `false` |
886
- | `paginated` | `boolean` | `false` |
887
- | `selectable` | `boolean` | `false` |
888
- | `loading` | `boolean` — renders skeleton rows | `false` |
889
- | `loadingRows` | `number` | `5` |
890
- | `emptyText` | `string|undefined` | `undefined` |
891
- | `previousPageLabel` | `string` — **required** | — |
892
- | `nextPageLabel` | `string` — **required** | — |
893
- | `caption` | `string|undefined` | `undefined` |
894
- | `tableClass` | `string|undefined` — merged onto `<table>` | `undefined` |
895
- | `sorting` | `SortingState` — two-way | `[]` |
896
- | `columnFilters` | `ColumnFiltersState` — two-way | `[]` |
897
- | `columnVisibility` | `ColumnVisibilityState` — two-way | `{}` |
898
- | `rowSelection` | `RowSelectionState` — two-way | `{}` |
899
- | `pagination` | `PaginationState` — two-way | `{ pageIndex: 0, pageSize: 10 }` |
894
+ | Input | Type | Default |
895
+ | :------------------ | :------------------------------------------ | :------------------------------- |
896
+ | `columns` | `YuwDatatableColumnDef<TData>[]` | `[]` |
897
+ | `data` | `TData[]` | `[]` |
898
+ | `sortable` | `boolean` | `false` |
899
+ | `paginated` | `boolean` | `false` |
900
+ | `selectable` | `boolean` | `false` |
901
+ | `loading` | `boolean` — renders skeleton rows | `false` |
902
+ | `loadingRows` | `number` | `5` |
903
+ | `emptyText` | `string|undefined` | `undefined` |
904
+ | `previousPageLabel` | `string` — **required** | — |
905
+ | `nextPageLabel` | `string` — **required** | — |
906
+ | `caption` | `string|undefined` | `undefined` |
907
+ | `tableClass` | `string|undefined` — merged onto `<table>` | `undefined` |
908
+ | `sorting` | `SortingState` — two-way | `[]` |
909
+ | `columnFilters` | `ColumnFiltersState` — two-way | `[]` |
910
+ | `columnVisibility` | `ColumnVisibilityState` — two-way | `{}` |
911
+ | `rowSelection` | `RowSelectionState` — two-way | `{}` |
912
+ | `pagination` | `PaginationState` — two-way | `{ pageIndex: 0, pageSize: 10 }` |
900
913
 
901
914
  #### Outputs
902
915
 
903
- | Output | Payload | Description |
904
- |:---------------------|:----------|:----------------------------------------------------------------|
905
- | `selectedRowsChange` | `TData[]` | Selection changes. The initial state does not emit. |
916
+ | Output | Payload | Description |
917
+ | :------------------- | :-------- | :-------------------------------------------------- |
918
+ | `selectedRowsChange` | `TData[]` | Selection changes. The initial state does not emit. |
906
919
 
907
- > `selectable` enables the selection *state*; the checkbox column itself is a display column you
920
+ > `selectable` enables the selection _state_; the checkbox column itself is a display column you
908
921
  > provide (`id: 'select'`, with `flexRenderComponent(...)` header/cell calling TanStack's toggle
909
922
  > handlers).
910
923
 
@@ -952,9 +965,9 @@ Sized with standard CSS height/width classes on the host element.
952
965
 
953
966
  #### Inputs
954
967
 
955
- | Input | Type | Default |
956
- |:--------|:---------|:-------------------|
957
- | `label` | `string` — **required**, the accessible name | — |
968
+ | Input | Type | Default |
969
+ | :------ | :------------------------------------------- | :---------------- |
970
+ | `label` | `string` — **required**, the accessible name | — |
958
971
  | `icon` | `string` — any registered icon name | `'lucideLoader2'` |
959
972
 
960
973
  The spinner inherits its size from the container's font size — wrap it in `text-2xl` to scale it.
@@ -972,12 +985,12 @@ The spinner inherits its size from the container's font size — wrap it in `tex
972
985
  </yuw-accordion>
973
986
  ```
974
987
 
975
- | Element | Inputs / Outputs |
976
- |:--------------------------|:----------------------------------------------------------------------|
977
- | `yuw-accordion` | `type`: `'single'|'multiple'` (default `'single'`), `orientation`: `'vertical'|'horizontal'` (default `'vertical'`) |
978
- | `yuw-accordion-item` | `isOpened`: `boolean`, `disabled`: `boolean`; output `openedChange` |
979
- | `yuw-accordion-trigger` | `triggerClass`: `string` — merged after defaults, so it wins |
980
- | `yuw-accordion-content` | — |
988
+ | Element | Inputs / Outputs |
989
+ | :---------------------- | :-------------------------------------------------------------------------------------------------------------------- |
990
+ | `yuw-accordion` | `type`: `'single'|'multiple'` (default `'single'`), `orientation`: `'vertical'|'horizontal'` (default `'vertical'`) |
991
+ | `yuw-accordion-item` | `isOpened`: `boolean`, `disabled`: `boolean`; output `openedChange` |
992
+ | `yuw-accordion-trigger` | `triggerClass`: `string` — merged after defaults, so it wins |
993
+ | `yuw-accordion-content` | — |
981
994
 
982
995
  Import them all at once with `YuwAccordionImports`.
983
996
 
@@ -986,10 +999,7 @@ Import them all at once with `YuwAccordionImports`.
986
999
  ### Breadcrumb
987
1000
 
988
1001
  ```html
989
- <yuw-breadcrumb
990
- [items]="[{ label: 'Home', href: '/' }, { label: 'Settings' }]"
991
- ariaLabel="Breadcrumb"
992
- />
1002
+ <yuw-breadcrumb [items]="[{ label: 'Home', href: '/' }, { label: 'Settings' }]" ariaLabel="Breadcrumb" />
993
1003
  ```
994
1004
 
995
1005
  ```ts
@@ -1001,11 +1011,11 @@ interface YuwBreadcrumbItemDto {
1001
1011
 
1002
1012
  #### Inputs
1003
1013
 
1004
- | Input | Type | Default |
1005
- |:------------|:------------------------------------|:--------|
1006
- | `items` | `YuwBreadcrumbItemDto[]` — **required** | — |
1007
- | `ariaLabel` | `string` — **required** | — |
1008
- | `separator` | `string` | `'/'` |
1014
+ | Input | Type | Default |
1015
+ | :---------- | :-------------------------------------- | :------ |
1016
+ | `items` | `YuwBreadcrumbItemDto[]` — **required** | — |
1017
+ | `ariaLabel` | `string` — **required** | — |
1018
+ | `separator` | `string` | `'/'` |
1009
1019
 
1010
1020
  The last item is announced as the current page (`aria-current="page"`); intermediate items render
1011
1021
  as links when they have an `href`.
@@ -1027,15 +1037,15 @@ as links when they have an `href`.
1027
1037
 
1028
1038
  #### Inputs
1029
1039
 
1030
- | Input | Type | Default |
1031
- |:-----------------|:-----------------------------------------------------------------------|:------------|
1040
+ | Input | Type | Default |
1041
+ | :--------------- | :--------------------------------------------------------------------- | :---------- |
1032
1042
  | `page` | `number` — two-way, **required** | — |
1033
1043
  | `totalPages` | `number` — **required** | — |
1034
1044
  | `previousLabel` | `string` — **required** | — |
1035
1045
  | `nextLabel` | `string` — **required** | — |
1036
1046
  | `ellipsisSrText` | `string` — **required** | — |
1037
1047
  | `ariaLabel` | `string` — **required** | — |
1038
- | `size` | `'default'|'xs'|'sm'|'lg'|'icon'|'icon-xs'|'icon-sm'|'icon-lg'` | `'icon'` |
1048
+ | `size` | `'default'|'xs'|'sm'|'lg'|'icon'|'icon-xs'|'icon-sm'|'icon-lg'` | `'icon'` |
1039
1049
  | `color` | `YuwColorDto` | `'primary'` |
1040
1050
 
1041
1051
  `getPaginationRange(page, totalPages)` is exported if you need the same page/ellipsis sequence
@@ -1065,10 +1075,10 @@ interface YuwTabItemDto {
1065
1075
 
1066
1076
  #### Inputs
1067
1077
 
1068
- | Input | Type | Default |
1069
- |:-----------------|:--------------------------------|:---------------|
1070
- | `tabs` | `YuwTabItemDto[]` — **required**| — |
1071
- | `activeTab` | `string` — two-way, **required**| — |
1078
+ | Input | Type | Default |
1079
+ | :--------------- | :------------------------------- | :------------- |
1080
+ | `tabs` | `YuwTabItemDto[]` — **required** | — |
1081
+ | `activeTab` | `string` — two-way, **required** | — |
1072
1082
  | `variant` | `'default'|'line'` | `'default'` |
1073
1083
  | `orientation` | `'horizontal'|'vertical'` | `'horizontal'` |
1074
1084
  | `activationMode` | `'automatic'|'manual'` | `'automatic'` |
@@ -1117,79 +1127,80 @@ Instead of hand-writing the group/menu/item tree, hand the sidebar a `YuwSidebar
1117
1127
  Header stays projected markup.
1118
1128
 
1119
1129
  ```html
1120
- <yuw-sidebar collapsible="icon" [content]="nav" [footer]="account"
1121
- (itemClicked)="onAction($event.id)">
1130
+ <yuw-sidebar collapsible="icon" [content]="nav" [footer]="account" (itemClicked)="onAction($event.id)">
1122
1131
  <div yuwSidebarHeader>Yurest</div>
1123
1132
  </yuw-sidebar>
1124
1133
  ```
1125
1134
 
1126
1135
  ```ts
1127
1136
  nav: YuwSidebarContentDto = {
1128
- groups: [{
1129
- id: 'management',
1130
- label: 'Management',
1131
- separatorAfter: true,
1132
- items: [
1133
- // route → routerLink anchor; active state resolves itself
1134
- { id: 'orders', label: 'Orders', icon: 'lucideShoppingCart', route: '/orders', badge: '12' },
1135
- // children → one nested submenu level
1136
- { id: 'reports', label: 'Reports', children: [{ id: 'sales', label: 'Sales', route: '/reports/sales' }] },
1137
- // href → plain anchor, full navigation
1138
- { id: 'docs', label: 'Docs', href: 'https://example.com', target: '_blank' },
1139
- // neither → <button>, reported through (itemClicked)
1140
- { id: 'sync', label: 'Sync now' },
1141
- ],
1142
- }],
1137
+ groups: [
1138
+ {
1139
+ id: 'management',
1140
+ label: 'Management',
1141
+ separatorAfter: true,
1142
+ items: [
1143
+ // route → routerLink anchor; active state resolves itself
1144
+ { id: 'orders', label: 'Orders', icon: 'lucideShoppingCart', route: '/orders', badge: '12' },
1145
+ // children → one nested submenu level
1146
+ { id: 'reports', label: 'Reports', children: [{ id: 'sales', label: 'Sales', route: '/reports/sales' }] },
1147
+ // href → plain anchor, full navigation
1148
+ { id: 'docs', label: 'Docs', href: 'https://example.com', target: '_blank' },
1149
+ // neither → <button>, reported through (itemClicked)
1150
+ { id: 'sync', label: 'Sync now' },
1151
+ ],
1152
+ },
1153
+ ],
1143
1154
  };
1144
1155
  ```
1145
1156
 
1146
1157
  An item's shape follows from its data — no `kind` field to keep in sync:
1147
1158
 
1148
- | Item has | Renders as | Active state |
1149
- |:----------------|:--------------------------|:--------------------------------------------------------|
1150
- | `route` | `[routerLink]` anchor | Automatic via `routerLinkActive` → `aria-current="page"` and `pointer-events: none`, so an active entry takes no hover, click or tooltip. Set `exact: true` for a root path like `/`. |
1151
- | `href` | plain `<a href>` | None — the browser leaves the page. |
1152
- | neither | `<button>` | None — emits `itemClicked` with `{id, event}`. |
1159
+ | Item has | Renders as | Active state |
1160
+ | :------- | :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1161
+ | `route` | `[routerLink]` anchor | Automatic via `routerLinkActive` → `aria-current="page"` and `pointer-events: none`, so an active entry takes no hover, click or tooltip. Set `exact: true` for a root path like `/`. |
1162
+ | `href` | plain `<a href>` | None — the browser leaves the page. |
1163
+ | neither | `<button>` | None — emits `itemClicked` with `{id, event}`. |
1153
1164
 
1154
1165
  `label` and `tooltip` are consumer-supplied strings, already translated — the sidebar owns no
1155
1166
  user-facing copy. `icon` names an icon **your** app registers with `provideIcons` (see
1156
1167
  [Icons](#3-icons)).
1157
1168
 
1158
1169
  Both forms compose: `content`/`footer` render their own regions, and anything projected still
1159
- renders too. To place hand-written markup *inside* an object-rendered region — where it scrolls
1170
+ renders too. To place hand-written markup _inside_ an object-rendered region — where it scrolls
1160
1171
  with the nav and shares the content area's flex sizing — mark it `[yuwSidebarContentExtra]` or
1161
1172
  `[yuwSidebarFooterExtra]`.
1162
1173
 
1163
1174
  #### `<yuw-sidebar>` inputs
1164
1175
 
1165
- | Input | Type | Default |
1166
- |:------------------------|:------------------------------------------|:---------------|
1167
- | `side` | `'left'|'right'` | `'left'` |
1168
- | `variant` | `'sidebar'|'floating'|'inset'` | `'sidebar'` |
1169
- | `collapsible` | `'offcanvas'|'icon'|'none'` | `'offcanvas'` |
1170
- | `sidebarWidthMobile` | `string` — any CSS length | `'18rem'` |
1171
- | `sidebarContainerClass` | `string` — merged onto the desktop container | `''` |
1172
- | `content` | `YuwSidebarContentDto|undefined` — data-driven nav | `undefined` |
1173
- | `footer` | `YuwSidebarContentDto|undefined` — data-driven footer | `undefined` |
1176
+ | Input | Type | Default |
1177
+ | :---------------------- | :----------------------------------------------------- | :------------ |
1178
+ | `side` | `'left'|'right'` | `'left'` |
1179
+ | `variant` | `'sidebar'|'floating'|'inset'` | `'sidebar'` |
1180
+ | `collapsible` | `'offcanvas'|'icon'|'none'` | `'offcanvas'` |
1181
+ | `sidebarWidthMobile` | `string` — any CSS length | `'18rem'` |
1182
+ | `sidebarContainerClass` | `string` — merged onto the desktop container | `''` |
1183
+ | `content` | `YuwSidebarContentDto|undefined` — data-driven nav | `undefined` |
1184
+ | `footer` | `YuwSidebarContentDto|undefined` — data-driven footer | `undefined` |
1174
1185
 
1175
1186
  Output: `itemClicked` → `YuwSidebarItemClickDto` (`{id, event}`), for entries with no `route`/`href`.
1176
1187
 
1177
1188
  #### Structure directives
1178
1189
 
1179
- | Directive | Notes |
1180
- |:-------------------------------------|:------------------------------------------------------------------|
1181
- | `[yuwSidebarWrapper]` | `sidebarWidth`, `sidebarWidthIcon` |
1182
- | `[yuwSidebarHeader]` / `[yuwSidebarContent]` / `[yuwSidebarFooter]` | |
1183
- | `[yuwSidebarGroup]` / `[yuwSidebarGroupLabel]` / `[yuwSidebarGroupContent]` | |
1184
- | `ul[yuwSidebarMenu]` / `li[yuwSidebarMenuItem]` | |
1185
- | `a[yuwSidebarMenuButton]`, `button[…]` | `variant`: `'default'|'outline'`, `size`: `'default'|'sm'|'lg'`, `isActive`, `closeMobileSidebarOnClick`; add Spartan's `tooltip` to label items while collapsed to icons |
1186
- | `[yuwSidebarMenuBadge]` | Trailing count/status. |
1187
- | `ul[yuwSidebarMenuSub]` / `li[yuwSidebarMenuSubItem]` / `a[yuwSidebarMenuSubButton]` | Nested level. |
1188
- | `[yuwSidebarSeparator]` | |
1189
- | `[yuwSidebarContentExtra]` / `[yuwSidebarFooterExtra]` | Projection markers: place hand-written markup inside the region rendered from `content`/`footer`. Inert when that input is unset. |
1190
- | `button[yuwSidebarRail]` | `label` — **required**, thin edge toggle. |
1191
- | `main[yuwSidebarInset]` | Main content area. |
1192
- | `<yuw-sidebar-trigger>` | `label` — **required**, screen-reader-only. |
1190
+ | Directive | Notes |
1191
+ | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1192
+ | `[yuwSidebarWrapper]` | `sidebarWidth`, `sidebarWidthIcon` |
1193
+ | `[yuwSidebarHeader]` / `[yuwSidebarContent]` / `[yuwSidebarFooter]` | |
1194
+ | `[yuwSidebarGroup]` / `[yuwSidebarGroupLabel]` / `[yuwSidebarGroupContent]` | |
1195
+ | `ul[yuwSidebarMenu]` / `li[yuwSidebarMenuItem]` | |
1196
+ | `a[yuwSidebarMenuButton]`, `button[…]` | `variant`: `'default'|'outline'`, `size`: `'default'|'sm'|'lg'`, `isActive`, `closeMobileSidebarOnClick`; add Spartan's `tooltip` to label items while collapsed to icons |
1197
+ | `[yuwSidebarMenuBadge]` | Trailing count/status. |
1198
+ | `ul[yuwSidebarMenuSub]` / `li[yuwSidebarMenuSubItem]` / `a[yuwSidebarMenuSubButton]` | Nested level. |
1199
+ | `[yuwSidebarSeparator]` | |
1200
+ | `[yuwSidebarContentExtra]` / `[yuwSidebarFooterExtra]` | Projection markers: place hand-written markup inside the region rendered from `content`/`footer`. Inert when that input is unset. |
1201
+ | `button[yuwSidebarRail]` | `label` — **required**, thin edge toggle. |
1202
+ | `main[yuwSidebarInset]` | Main content area. |
1203
+ | `<yuw-sidebar-trigger>` | `label` — **required**, screen-reader-only. |
1193
1204
 
1194
1205
  Inject `YuwSidebarService` to read or drive the state (`state()`, `isMobile()`, `openMobile()`,
1195
1206
  `toggle()`); configure defaults app-wide with `provideYuwSidebarConfig({ … })`.
@@ -1205,8 +1216,7 @@ viewport.
1205
1216
  > anonymous dialog by screen readers.
1206
1217
 
1207
1218
  ```html
1208
- <yuw-dialog [(open)]="isOpen" title="Create project"
1209
- description="Give it a name to get started." closeLabel="Close">
1219
+ <yuw-dialog [(open)]="isOpen" title="Create project" description="Give it a name to get started." closeLabel="Close">
1210
1220
  <ng-container yuwDialogTrigger>Create project</ng-container>
1211
1221
 
1212
1222
  <yuw-input [(value)]="name" placeholder="Project name" />
@@ -1219,17 +1229,17 @@ viewport.
1219
1229
 
1220
1230
  #### Inputs
1221
1231
 
1222
- | Input | Type | Default |
1223
- |:-----------------|:---------------------------------|:------------|
1224
- | `open` | `boolean` — two-way | `false` |
1225
- | `showTrigger` | `boolean` — set `false` when driving via `[(open)]` only | `true` |
1226
- | `title` | `string|undefined` | `undefined` |
1227
- | `description` | `string|undefined` | `undefined` |
1228
- | `ariaLabel` | `string|undefined` | `undefined` |
1229
- | `closeLabel` | `string|undefined` — set it to render the corner ✕ | `undefined` |
1230
- | `panelClass` | `string|undefined` — e.g. `sm:max-w-lg` | `undefined` |
1231
- | `triggerVariant` | button variant | `'outline'` |
1232
- | `triggerSize` | button size | `'default'` |
1232
+ | Input | Type | Default |
1233
+ | :--------------- | :------------------------------------------------------- | :---------- |
1234
+ | `open` | `boolean` — two-way | `false` |
1235
+ | `showTrigger` | `boolean` — set `false` when driving via `[(open)]` only | `true` |
1236
+ | `title` | `string|undefined` | `undefined` |
1237
+ | `description` | `string|undefined` | `undefined` |
1238
+ | `ariaLabel` | `string|undefined` | `undefined` |
1239
+ | `closeLabel` | `string|undefined` — set it to render the corner ✕ | `undefined` |
1240
+ | `panelClass` | `string|undefined` — e.g. `sm:max-w-lg` | `undefined` |
1241
+ | `triggerVariant` | button variant | `'outline'` |
1242
+ | `triggerSize` | button size | `'default'` |
1233
1243
 
1234
1244
  #### Content slots
1235
1245
 
@@ -1257,25 +1267,25 @@ dismissed by clicking the backdrop.
1257
1267
 
1258
1268
  #### Inputs
1259
1269
 
1260
- | Input | Type | Default |
1261
- |:-----------------|:--------------------|:------------|
1262
- | `open` | `boolean` — two-way | `false` |
1263
- | `showTrigger` | `boolean` | `true` |
1264
- | `title` | `string` — **required** | — |
1265
- | `confirmLabel` | `string` — **required** | — |
1266
- | `cancelLabel` | `string` — **required** | — |
1267
- | `description` | `string|undefined` | `undefined` |
1268
- | `confirmVariant` | button variant | `'default'` |
1269
- | `size` | `'default'|'sm'` | `'default'` |
1270
- | `triggerVariant` | button variant | `'outline'` |
1271
- | `triggerSize` | button size | `'default'` |
1270
+ | Input | Type | Default |
1271
+ | :--------------- | :---------------------- | :---------- |
1272
+ | `open` | `boolean` — two-way | `false` |
1273
+ | `showTrigger` | `boolean` | `true` |
1274
+ | `title` | `string` — **required** | — |
1275
+ | `confirmLabel` | `string` — **required** | — |
1276
+ | `cancelLabel` | `string` — **required** | — |
1277
+ | `description` | `string|undefined` | `undefined` |
1278
+ | `confirmVariant` | button variant | `'default'` |
1279
+ | `size` | `'default'|'sm'` | `'default'` |
1280
+ | `triggerVariant` | button variant | `'outline'` |
1281
+ | `triggerSize` | button size | `'default'` |
1272
1282
 
1273
1283
  #### Outputs
1274
1284
 
1275
- | Output | Payload | Description |
1276
- |:------------|:--------|:--------------------------------------------------------------------------|
1277
- | `confirmed` | `void` | Confirm action activated. |
1278
- | `cancelled` | `void` | Cancel **button** activated — programmatic closes do not emit it. |
1285
+ | Output | Payload | Description |
1286
+ | :---------- | :------ | :---------------------------------------------------------------- |
1287
+ | `confirmed` | `void` | Confirm action activated. |
1288
+ | `cancelled` | `void` | Cancel **button** activated — programmatic closes do not emit it. |
1279
1289
 
1280
1290
  #### Content slots
1281
1291
 
@@ -1289,8 +1299,13 @@ Slide-in panel for side drawers and detail views. Same accessible-name rule as
1289
1299
  [Dialog](#dialog).
1290
1300
 
1291
1301
  ```html
1292
- <yuw-sheet [(open)]="isOpen" side="right" title="Edit profile"
1293
- description="Update your account details." closeLabel="Close">
1302
+ <yuw-sheet
1303
+ [(open)]="isOpen"
1304
+ side="right"
1305
+ title="Edit profile"
1306
+ description="Update your account details."
1307
+ closeLabel="Close"
1308
+ >
1294
1309
  <ng-container yuwSheetTrigger>Edit profile</ng-container>
1295
1310
 
1296
1311
  <p>Sheet form content goes here.</p>
@@ -1305,9 +1320,9 @@ Slide-in panel for side drawers and detail views. Same accessible-name rule as
1305
1320
 
1306
1321
  Same as [Dialog](#dialog), plus:
1307
1322
 
1308
- | Input | Type | Default |
1309
- |:-------|:----------------------------------|:----------|
1310
- | `side` | `'top'|'bottom'|'left'|'right'` | `'right'` |
1323
+ | Input | Type | Default |
1324
+ | :----- | :--------------------------------- | :-------- |
1325
+ | `side` | `'top'|'bottom'|'left'|'right'` | `'right'` |
1311
1326
 
1312
1327
  #### Content slots
1313
1328
 
@@ -1318,8 +1333,7 @@ Same as [Dialog](#dialog), plus:
1318
1333
  ### Popover
1319
1334
 
1320
1335
  ```html
1321
- <yuw-popover [(open)]="isOpen" align="start" title="Notifications"
1322
- description="You're all caught up.">
1336
+ <yuw-popover [(open)]="isOpen" align="start" title="Notifications" description="You're all caught up.">
1323
1337
  <button yuwPopoverTrigger>View notifications</button>
1324
1338
 
1325
1339
  <p>No new notifications since your last visit.</p>
@@ -1328,17 +1342,17 @@ Same as [Dialog](#dialog), plus:
1328
1342
 
1329
1343
  #### Inputs
1330
1344
 
1331
- | Input | Type | Default |
1332
- |:-----------------|:---------------------------|:-----------|
1333
- | `open` | `boolean` — two-way | `false` |
1334
- | `showTrigger` | `boolean` | `true` |
1335
- | `align` | `'start'|'center'|'end'` | `'center'` |
1336
- | `sideOffset` | `number` — px | `4` |
1337
- | `title` | `string|undefined` | `undefined`|
1338
- | `description` | `string|undefined` | `undefined`|
1345
+ | Input | Type | Default |
1346
+ | :--------------- | :-------------------------------- | :---------- |
1347
+ | `open` | `boolean` — two-way | `false` |
1348
+ | `showTrigger` | `boolean` | `true` |
1349
+ | `align` | `'start'|'center'|'end'` | `'center'` |
1350
+ | `sideOffset` | `number` — px | `4` |
1351
+ | `title` | `string|undefined` | `undefined` |
1352
+ | `description` | `string|undefined` | `undefined` |
1339
1353
  | `panelClass` | `string|undefined` — e.g. `w-80` | `undefined` |
1340
- | `triggerVariant` | button variant | `'outline'`|
1341
- | `triggerSize` | button size | `'default'`|
1354
+ | `triggerVariant` | button variant | `'outline'` |
1355
+ | `triggerSize` | button size | `'default'` |
1342
1356
 
1343
1357
  #### Content slots
1344
1358
 
@@ -1357,13 +1371,13 @@ Applied directly to the trigger element — no wrapper markup.
1357
1371
 
1358
1372
  #### Inputs
1359
1373
 
1360
- | Input | Type | Default |
1361
- |:------------------|:----------------------------------------|:--------|
1362
- | `yuwTooltip` | `string|TemplateRef` — the content | — |
1363
- | `position` | `'top'|'bottom'|'left'|'right'` | `'top'` |
1364
- | `showDelay` | `number` — ms | `150` |
1365
- | `hideDelay` | `number` — ms | `100` |
1366
- | `tooltipDisabled` | `boolean` | `false` |
1374
+ | Input | Type | Default |
1375
+ | :---------------- | :---------------------------------- | :------ |
1376
+ | `yuwTooltip` | `string|TemplateRef` — the content | — |
1377
+ | `position` | `'top'|'bottom'|'left'|'right'` | `'top'` |
1378
+ | `showDelay` | `number` — ms | `150` |
1379
+ | `hideDelay` | `number` — ms | `100` |
1380
+ | `tooltipDisabled` | `boolean` | `false` |
1367
1381
 
1368
1382
  ---
1369
1383
 
@@ -1379,7 +1393,8 @@ Right-click menu, declared as a template and attached to any element.
1379
1393
  <div yuwContextMenuLabel>Actions</div>
1380
1394
 
1381
1395
  <button yuwContextMenuItem (triggered)="edit()">
1382
- Edit <span yuwContextMenuShortcut>⌘E</span>
1396
+ Edit
1397
+ <span yuwContextMenuShortcut>⌘E</span>
1383
1398
  </button>
1384
1399
 
1385
1400
  <div yuwContextMenuSeparator></div>
@@ -1404,16 +1419,16 @@ Right-click menu, declared as a template and attached to any element.
1404
1419
  </ng-template>
1405
1420
  ```
1406
1421
 
1407
- | Directive | Inputs / Outputs |
1408
- |:----------------------------|:----------------------------------------------------------------|
1409
- | `[yuwContextMenuTrigger]` | Menu `TemplateRef`; `yuwContextMenuTriggerData`; outputs `opened`, `closed` |
1410
- | `[yuwContextMenu]` | Menu panel. |
1411
- | `[yuwContextMenuItem]` | Output `triggered`. |
1412
- | `[yuwContextMenuCheckbox]` | `checked`, `disabled`; output `triggered`. |
1413
- | `[yuwContextMenuRadio]` | `checked`, `disabled`; output `triggered`. |
1414
- | `[yuwContextMenuGroup]` / `[yuwContextMenuLabel]` / `[yuwContextMenuSeparator]` / `[yuwContextMenuShortcut]` | Structure. |
1415
- | `[yuwContextMenuSub]` / `[yuwContextMenuSubTrigger]` | Nested menus. |
1416
- | `<yuw-context-menu-checkbox-indicator>` / `…-radio-indicator>` / `…-sub-indicator>` | Indicators. |
1422
+ | Directive | Inputs / Outputs |
1423
+ | :----------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------- |
1424
+ | `[yuwContextMenuTrigger]` | Menu `TemplateRef`; `yuwContextMenuTriggerData`; outputs `opened`, `closed` |
1425
+ | `[yuwContextMenu]` | Menu panel. |
1426
+ | `[yuwContextMenuItem]` | Output `triggered`. |
1427
+ | `[yuwContextMenuCheckbox]` | `checked`, `disabled`; output `triggered`. |
1428
+ | `[yuwContextMenuRadio]` | `checked`, `disabled`; output `triggered`. |
1429
+ | `[yuwContextMenuGroup]` / `[yuwContextMenuLabel]` / `[yuwContextMenuSeparator]` / `[yuwContextMenuShortcut]` | Structure. |
1430
+ | `[yuwContextMenuSub]` / `[yuwContextMenuSubTrigger]` | Nested menus. |
1431
+ | `<yuw-context-menu-checkbox-indicator>` / `…-radio-indicator>` / `…-sub-indicator>` | Indicators. |
1417
1432
 
1418
1433
  Checkbox and radio items keep the menu open; drive their `checked` state from `triggered`. Import
1419
1434
  them all at once with `YuwContextMenuImports`.
@@ -1425,27 +1440,33 @@ them all at once with `YuwContextMenuImports`.
1425
1440
  Inline, non-blocking message panel.
1426
1441
 
1427
1442
  ```html
1428
- <yuw-alert variant="destructive" title="Payment declined"
1429
- description="Check the card details and try again.">
1443
+ <yuw-alert variant="destructive" title="Payment declined" description="Check the card details and try again.">
1430
1444
  <ng-icon yuwAlertIcon name="lucideTriangleAlert" />
1431
1445
  <yuw-button yuwAlertAction size="sm" variant="ghost">Retry</yuw-button>
1432
1446
  </yuw-alert>
1433
1447
 
1434
1448
  <!-- Rich content replaces the plain-text inputs -->
1435
1449
  <yuw-alert>
1436
- <span yuwAlertTitle>Terms <strong>updated</strong></span>
1437
- <span yuwAlertDescription>Review the <a href="/changes">changes</a> before continuing.</span>
1450
+ <span yuwAlertTitle>
1451
+ Terms
1452
+ <strong>updated</strong>
1453
+ </span>
1454
+ <span yuwAlertDescription>
1455
+ Review the
1456
+ <a href="/changes">changes</a>
1457
+ before continuing.
1458
+ </span>
1438
1459
  </yuw-alert>
1439
1460
  ```
1440
1461
 
1441
1462
  #### Inputs
1442
1463
 
1443
- | Input | Type | Default |
1444
- |:--------------|:----------------------------|:------------|
1445
- | `variant` | `'default'|'destructive'` | `'default'` |
1446
- | `title` | `string|undefined` | `undefined` |
1447
- | `description` | `string|undefined` | `undefined` |
1448
- | `class` | `string` | `''` |
1464
+ | Input | Type | Default |
1465
+ | :------------ | :------------------------- | :---------- |
1466
+ | `variant` | `'default'|'destructive'` | `'default'` |
1467
+ | `title` | `string|undefined` | `undefined` |
1468
+ | `description` | `string|undefined` | `undefined` |
1469
+ | `class` | `string` | `''` |
1449
1470
 
1450
1471
  #### Content slots
1451
1472
 
@@ -1485,28 +1506,28 @@ yuwToast('Item deleted', {
1485
1506
 
1486
1507
  #### Inputs
1487
1508
 
1488
- | Input | Type | Default |
1489
- |:----------------|:-----------------------------------------------------------------------------------|:-----------------|
1509
+ | Input | Type | Default |
1510
+ | :-------------- | :-------------------------------------------------------------------------------------- | :--------------- |
1490
1511
  | `position` | `'top-left'|'top-center'|'top-right'|'bottom-left'|'bottom-center'|'bottom-right'` | `'bottom-right'` |
1491
- | `richColors` | `boolean` — per-type coloring (deviates from the Spartan default) | `true` |
1492
- | `theme` | `'light'|'dark'|'system'` | `'light'` |
1493
- | `duration` | `number` — ms | `4000` |
1494
- | `visibleToasts` | `number` | `3` |
1495
- | `closeButton` | `boolean` | `false` |
1496
- | `expand` | `boolean` — keeps the stack expanded | `false` |
1497
- | `toastOptions` | `ToastOptions` — defaults applied to every toast | `{}` |
1512
+ | `richColors` | `boolean` — per-type coloring (deviates from the Spartan default) | `true` |
1513
+ | `theme` | `'light'|'dark'|'system'` | `'light'` |
1514
+ | `duration` | `number` — ms | `4000` |
1515
+ | `visibleToasts` | `number` | `3` |
1516
+ | `closeButton` | `boolean` | `false` |
1517
+ | `expand` | `boolean` — keeps the stack expanded | `false` |
1518
+ | `toastOptions` | `ToastOptions` — defaults applied to every toast | `{}` |
1498
1519
 
1499
1520
  ## Utilities and services
1500
1521
 
1501
- | Export | Description |
1502
- |:--------------------------|:-----------------------------------------------------------------------------------------------|
1503
- | `cn(...classes)` | `clsx` + `tailwind-merge`. Merges class lists so a later class overrides an earlier one of the same Tailwind group. |
1504
- | `yuwToast` | Toast API (`success`, `error`, `warning`, `info`, `promise`, …). |
1505
- | `YuwSidebarService` | Sidebar open/collapsed state, shared across the page. |
1506
- | `provideYuwSidebarConfig` | App-wide sidebar defaults (widths, variant). |
1507
- | `provideValueAccessor` | Registers a component as a form control — used by the library's own controls. |
1508
- | `getPaginationRange` | The page/ellipsis sequence `<yuw-pagination>` renders. |
1509
- | `YuwColorDto`, `YuwInputTypeDto`, `YuwInputModeDto`, `YuwTextFieldContract` | Shared type vocabulary. |
1522
+ | Export | Description |
1523
+ | :-------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ |
1524
+ | `cn(...classes)` | `clsx` + `tailwind-merge`. Merges class lists so a later class overrides an earlier one of the same Tailwind group. |
1525
+ | `yuwToast` | Toast API (`success`, `error`, `warning`, `info`, `promise`, …). |
1526
+ | `YuwSidebarService` | Sidebar open/collapsed state, shared across the page. |
1527
+ | `provideYuwSidebarConfig` | App-wide sidebar defaults (widths, variant). |
1528
+ | `provideValueAccessor` | Registers a component as a form control — used by the library's own controls. |
1529
+ | `getPaginationRange` | The page/ellipsis sequence `<yuw-pagination>` renders. |
1530
+ | `YuwColorDto`, `YuwInputTypeDto`, `YuwInputModeDto`, `YuwTextFieldContract` | Shared type vocabulary. |
1510
1531
 
1511
1532
  ### Spartan helm layer
1512
1533