fold-ng 0.3.0 → 0.5.1

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
@@ -90,12 +90,14 @@ set `data-theme` on an ancestor — usually `<html>`:
90
90
  <html data-theme="lumen"></html>
91
91
  ```
92
92
 
93
- Four themes ship: `umbra` (the dark base, no attribute), `lumen` (light),
94
- `bubbly`
95
- (festive lavender, violet brand, rounded) and `navi` (dark chrome, light page).
96
- The extras exist to prove the point — each is the umbra or lumen block with its
97
- primitive families re-pointed. Adding a fifth is a new `[data-theme]` block in
98
- `semantic.css` plus the primitives it names.
93
+ Five themes ship: `umbra` (the dark base, no attribute), `lumen` (light),
94
+ `bubbly` (festive lavender, violet brand, rounded), `navi` (dark chrome, light
95
+ page) and `titan` (brushed titanium — a light brushed-steel ground with a
96
+ frameless top and floating rails, bright cards, a heat-anodized copper-orange
97
+ brand, solid steel borders, iPhone-soft corners). The extras exist to prove the point — each
98
+ is the umbra or lumen block with its primitive families re-pointed. Adding a
99
+ sixth is a new `[data-theme]` block in `semantic.css` plus the primitives it
100
+ names.
99
101
 
100
102
  `bubbly` and `navi` also change their corners — **radius is the one scale a theme may
101
103
  re-declare**, because corner softness is a brand axis (friendly vs
@@ -111,6 +113,81 @@ roles cannot express. It gets there by re-declaring those roles on
111
113
  theme never names a component's internals. Variables only. If mixed chrome ever
112
114
  stops being a demo, the catalogue should grow real `*-on-chrome` roles.
113
115
 
116
+ ## Auto-inverting surfaces
117
+
118
+ The same `[data-surface]` seam powers an **accent** surface — a region filled
119
+ with the brand accent whose entire content sub-tree flips to a compatible
120
+ on-accent palette **with no per-component code**. Drop a `fold-card` in a grid
121
+ and set `surface="accent"` (or stamp `foldSurface="accent"` on any element):
122
+
123
+ ```html
124
+ <fold-card surface="accent">
125
+ <h3>Studio plan</h3>
126
+ <p>Everything in Pro, plus shared workspaces.</p>
127
+ <fold-badge content="Popular" variant="accent" />
128
+ <fold-link href="/plans">Compare plans</fold-link>
129
+ <button foldButton>Choose</button>
130
+ </fold-card>
131
+ ```
132
+
133
+ Every nested thing — the text ramp, the hairline border, a raised band, the
134
+ badge, the link, the button, even a filled icon tile — reads correctly on the
135
+ accent. Not because the card special-cases them, but because the region
136
+ **re-points the semantic roles** they already resolve against.
137
+
138
+ ### How it works (and why it survives a solid button)
139
+
140
+ An inverting surface has to do something a chrome surface never does: **swap the
141
+ brand pair**. On the accent, `--fold-color-primary` should become the light ink
142
+ (so a link or a filled tile's ground reads), and `--fold-color-on-primary` should
143
+ become the accent itself (so the label _on_ that tile reads). Written naively
144
+ that's a CSS custom-property cycle (`a: var(b); b: var(a)` → both invalid).
145
+
146
+ The trick: **capture on the surface, invert on the descendants.** The surface
147
+ element records the accent and its ink into two private vars _while the tokens
148
+ still hold their normal values_, and the inverted role-set is applied to
149
+ descendants from those captures — so a role can reference the pre-inversion value
150
+ it is replacing, no cycle:
151
+
152
+ ```css
153
+ [data-surface="accent"] {
154
+ --_accent-ink: var(--fold-color-on-primary); /* captured here… */
155
+ --_accent-fill: var(--fold-color-primary);
156
+ }
157
+ [data-surface="accent"] * {
158
+ --fold-color-text: var(--_accent-ink); /* …consumed here */
159
+ --fold-color-primary: var(--_accent-ink); /* fill → light ink */
160
+ --fold-color-on-primary: var(--_accent-fill); /* on-fill → the accent */
161
+ /* …surfaces/borders as color-mix of the captured pair… */
162
+ }
163
+ ```
164
+
165
+ Every value is a `color-mix` of the captured pair, so it is **derived, not
166
+ authored** — one definition holds on all five themes, and the surface/band steps
167
+ stay a lighter shade of the accent (gradation kept in-hue).
168
+
169
+ ### Overriding per theme
170
+
171
+ None of this is a cage. Writing your own CSS in a card is always free — raw
172
+ values don't reference the roles, so a surface never touches them. An _override_
173
+ isn't a hack: it re-anchors one **relationship** (text ↔ ground ↔ accent) inside
174
+ a controlled frame, and coherence follows because the ratios are preserved. Speak
175
+ in roles and gain the adaptation, or paint a pixel and own it — both coexist.
176
+
177
+ The derived defaults are good, not sacred. A theme that wants a different
178
+ on-accent ramp (a light accent might want darker text, say) overrides any role by
179
+ nesting its own theme selector under the surface — the same seam chrome uses:
180
+
181
+ ```css
182
+ [data-theme="titan"] [data-surface="accent"] * {
183
+ --fold-color-text: var(--fold-ref-steel-900); /* dark ink on a light accent */
184
+ }
185
+ ```
186
+
187
+ The one honest limit: an accent surface is a _single_ ground, so `surface`
188
+ stays one axis — there is no `accent` × `sunken`. That is a feature (a card in a
189
+ grid has one job: stand out), not a gap.
190
+
114
191
  Then style against the semantic tokens — never a raw colour:
115
192
 
116
193
  ```css
@@ -210,50 +287,59 @@ radius / text / icon-size / space / motion / blur scales — see
210
287
  All standalone, signals-first, styled against the semantic tokens. Import from
211
288
  the package root.
212
289
 
213
- | Component | Selector | What it is |
214
- | -------------------------------------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
215
- | `FoldAppShellComponent` | `fold-app-shell` | Responsive app skeleton (rails + header + content + self-collapsing `footer` slots; `headerLayout`/`footerLayout` inset·full, `footerBehavior` pinned·scroll; `mobileNav` drawer·none — `[(mobileNavOpen)]` off-canvas drawer for the primary rail on mobile, or `none` to compose an `fold-nav-launcher`; `contentScroll` clip·auto; built-in skip-link to a focusable `<main>`. Regions float per-surface via `foldElevated`, not a shell flag). |
216
- | `FoldMenuComponent` (+ `Item` / `Section` / `Separator`) | `fold-menu` | Collapsible nav rail — coloured sections, `tint="follow"`, depth `level`, collapse-toggle placement. Items are `a[fold-menu-item]`. |
217
- | `FoldNavLauncherComponent` (+ `FoldNavTileComponent`) | `fold-nav-launcher` | Full-screen mobile nav launcher — a centred tile grid over a blurred scrim (scrim / `Escape` / close dismissal, focus-trap, scroll-lock). `columns="auto"` scales tiles to the count. Pairs with `fold-app-shell mobileNav="none"`. Tiles are `a[fold-nav-tile]` — `variant="surface"`·`filled`. |
218
- | `FoldPageLayoutComponent` | `fold-page-layout` | Page scaffold — gutter + header + body rhythm; fills its container (width is a content concern). Tokens `--fold-page-gutter` / `--fold-page-gap`; sections can `bleed` edge-to-edge. |
219
- | `FoldPageSectionComponent` | `fold-page-section` | Semantic `<section>` grouping — eyebrow title (names the region via `aria-labelledby`) + description + actions; `stack` / `bleed` helpers. Not a box — compose a `fold-card` inside for that. |
220
- | `FoldHeroSectionComponent` | `fold-hero-section` | Full-bleed page splash — the borderless intro band at the top of a page (carries the `<h1>`). Direct child of `fold-page-layout`: cancels the gutter + top pad to sit flush, brand-tinted wash + hairline. `align` center·start, `wash`, `[heroBackdrop]` decorative lane. (For a bordered header card, see `fold-hero-card`.) |
221
- | `FoldAsideLayoutComponent` | `fold-aside-layout` | Detail-page grid — a centred column flanked by up to two sticky rails (`[asideLeft]` / `[asideRight]`), collapsing to one column on its own container width (`:has()`-driven, container queries). Labelled rails become `complementary` landmarks; every track is a CSS var. |
222
- | `FoldNavLayoutComponent` | `fold-nav-layout` | Places a bar (`[tabNav]` — a `fold-view-nav` or a `fold-tabs`) with its content — `placement="top"` or a `side` rail that folds back on top (hysteretic, on its own width) below `foldAt`. `exportAs="foldNavLayout"` exposes `stacked()` so the projected bar follows in one binding. |
223
- | `FoldCardComponent` | `fold-card` | Raised content surface (`surface-card` + consistent radius). |
224
- | `FoldContextCardComponent` | `fold-context-card` | Titled info card: icon header + body + optional footer action. |
225
- | `FoldHeroCardComponent` | `fold-hero-card` | Prominent header **card** — bordered surface × accent overlay + optional accent bar. (For a full-bleed page splash, see `fold-hero-section`.) |
226
- | `FoldElementTitleComponent` | `fold-element-title` | Uppercase section/card mini-title (eyebrow · bar variants). |
227
- | `FoldFieldListComponent` / `…Field` | `fold-field-list` | Read-only `dl/dt/dd` recap — label/value pairs (`[empty]` placeholder). The _display_ half of a record; `fold-input` is the _edit_ half. |
228
- | `FoldInputComponent` | `fold-input` | Text-input control (`value: string`) — Signal Forms (`[formField]`) or standalone `[(value)]`; size × align × variant, `label` / `required` / `hint`. The _edit_ half of a record (`fold-field` reads). |
229
- | `FoldNumberInputComponent` | `fold-number-input` | Numeric sibling of `fold-input` (`value: number \| null`, empty ⇒ `null`); owns `min` / `max` / `step` + `label` / `required` / `hint`. Split so each control keeps its true type. |
230
- | `FoldSearchComponent` | `fold-search` | Debounced search box — an `fold-input` that emits `searchChange` once typing settles (`delayMs`), trimmed + de-duplicated. |
231
- | `FoldSliderComponent` | `fold-slider` | Single-value range slider — a styled native `<input type="range">` (design-system track/fill/thumb), two-way `[(value)]`. |
232
- | `FoldRangeSliderComponent` | `fold-range-slider` | Dual-thumb slider selecting a `{ min, max }` window over `[min, max]`; shares the slider track/fill/thumb. |
233
- | `FoldFileDropzoneComponent` | `fold-file-dropzone` | File-picker dropzone — drag-over visuals, keyboard activation, hidden `<input type=file>` plumbing; emits the picked `File[]` (presentational — never uploads). |
234
- | `FoldLinkComponent` | `fold-link` | Inline text link / link-button (icons, accent · muted). |
235
- | `FoldButtonComponent` | `button[foldButton]` · `a[foldButton]` | Action button — applied to a real `<button>` **or** `<a>` (link that looks like a button, gets `href`/`routerLink`); orthogonal `emphasis` (solid·soft·outline) × `intent` (primary·neutral·warning·danger) × 3 sizes × shape/`block`; `icon`/`iconTrailing` shorthand (auto-sized) or project content; `loading` (spinner + `aria-busy`). Use native `(click)`. |
236
- | `FoldButtonIconComponent` | `fold-button-icon` | Icon-only **momentary** button — shape × size × tone; a one-shot action (no pressed state). For a text button use `fold-button`; for on/off use `fold-toggle-icon`. |
237
- | `FoldToggleIconComponent` | `fold-toggle-icon` | Icon-only **toggle** — the same surface as `fold-button-icon`, plus `[(active)]` + `aria-pressed` (true/false) and a pressed state. Emits `toggled`. |
238
- | `FoldDataTableComponent` | `fold-data-table` | Controlled roster table (sortable, tone rows, mobile cards). |
239
- | `FoldPaginatorComponent` | `fold-paginator` | Server-side paginator (size selector + range + page nav). |
240
- | `FoldTimelineComponent` | `fold-timeline` | Connected rail of nodes (dot + optional date + label) — `vertical` navigable history or `horizontal` step progress; nodes optionally clickable. |
241
- | `FoldBadgeComponent` | `fold-badge` | Status / count pill (accent/info/warning/alert/success). |
242
- | `FoldStatusBadgeComponent` | `fold-status-badge` | Status→colour badge (maps a domain status key to a tone). |
243
- | `FoldChoiceRowComponent` | `fold-choice-row` | Segmented / chip selector. |
244
- | `FoldViewNavComponent` | `fold-view-nav` | Navigation bar styled as tabs. Items carry a `link` (routerLink → a real `<a>`: cmd-click, deep-links, active state auto), an `href`, or nothing (a button); `aria-current="page"` on the active one. `direction="auto"` follows a wrapping `fold-nav-layout`; `collapsed` for an icon rail. For in-page panel switching use `fold-tabs` instead. |
245
- | `FoldTabsComponent` + `FoldTabPanelComponent` | `fold-tabs` + `fold-tab-panel` | The in-page ARIA Tabs widget: `role="tablist"` + roving arrow-key keyboard, `aria-selected`/`aria-orientation`, each tab wired to its `fold-tab-panel` (`aria-controls` ↔ `aria-labelledby`). Panels take the bar by ref (`[tabs]="t"`) so they coordinate across `fold-nav-layout` slots. |
246
- | `FoldIconComponent` | `fold-icon` | SVG icon (114-icon built-in set + `FoldIconRegistry`). |
247
- | `FoldSpinnerComponent` | `fold-spinner` | Indeterminate loading arc (`currentColor`, icon-sized, reduced-motion aware). Decorative by default; `label` → `role="status"`. Powers `loading` on the buttons. |
248
- | `FoldAvatarComponent` / `…Detail` | `fold-avatar` | Initials/image avatar (square, muted, status ring) + identity cell. |
249
- | `FoldAvatarListComponent` | `fold-avatar-list` | Overlapping avatar cluster (per-face variant, `limit` + a `+N` overflow chip). |
250
- | `FoldToastComponent` / `…Container` | `fold-toast` | Frosted snackbar (variant glyph + dismiss) + queue host (+ `FoldToastService`). |
251
- | `FoldLoadingStateComponent` | `fold-loading` | Loading placeholder — `fold-spinner` + message, in a `role="status"` region; `size` input; stretches to fill. |
252
- | `FoldEmptyStateComponent` | `fold-empty-state` | Empty-state block (icon + title + message + optional action). |
253
- | `FoldCalloutComponent` | `fold-callout` | Tinted message row — status colour + icon + message + optional trailing actions; `inset` (bordered, in-flow) appearance. |
254
- | `FoldDisclosureComponent` | `fold-disclosure` | One summary toggling one collapsible panel — the accordion primitive (open-state is the consumer's to bind); keeps content mounted, unlike native `<details>`. |
255
- | `FoldPanelHostComponent` | `fold-panel-host` | Side-panel / overlay host (+ `FoldPanelHostService` / `FoldPanelRef` / `FoldPanelToggle`). Modal: accessible name, `inert` background barrier, top-most focus trap, scroll-lock. Localise the close label once via `provideFoldPanelLabels({ close })`. |
256
- | `FoldPanelHeaderComponent` | `fold-panel-header` | Standard panel header (title/eyebrow, self-closing). Names its dialog (`aria-labelledby`) and reads the app-wide close label. |
290
+ | Component | Selector | What it is |
291
+ | -------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
292
+ | `FoldAppShellComponent` | `fold-app-shell` | Responsive app skeleton (rails + header + content + self-collapsing `footer` slots; `headerLayout`/`footerLayout` inset·full, `footerBehavior` pinned·scroll; `mobileNav` drawer·none — `[(mobileNavOpen)]` off-canvas drawer for the primary rail on mobile, or `none` to compose an `fold-nav-launcher`; `contentScroll` clip·auto; built-in skip-link to a focusable `<main>`. Regions float per-surface via `foldElevated`, not a shell flag). |
293
+ | `FoldMenuComponent` (+ `Item` / `Section` / `Separator`) | `fold-menu` | Collapsible nav rail — coloured sections, `tint="follow"`, depth `level`, collapse-toggle placement. Items are `a[fold-menu-item]`. |
294
+ | `FoldNavLauncherComponent` (+ `FoldNavTileComponent`) | `fold-nav-launcher` | Full-screen mobile nav launcher — a centred tile grid over a blurred scrim (scrim / `Escape` / close dismissal, focus-trap, scroll-lock). `columns="auto"` scales tiles to the count. Pairs with `fold-app-shell mobileNav="none"`. Tiles are `a[fold-nav-tile]` — `variant="surface"`·`filled`. |
295
+ | `FoldPageLayoutComponent` | `fold-page-layout` | Page scaffold — gutter + header + body rhythm; fills its container (width is a content concern). Tokens `--fold-page-gutter` / `--fold-page-gap`; sections can `bleed` edge-to-edge. |
296
+ | `FoldPageSectionComponent` | `fold-page-section` | Semantic `<section>` grouping — eyebrow title (names the region via `aria-labelledby`) + description + actions; `stack` / `bleed` helpers. Not a box — compose a `fold-card` inside for that. |
297
+ | `FoldHeroSectionComponent` | `fold-hero-section` | Full-bleed page splash — the borderless intro band at the top of a page (carries the `<h1>`). Direct child of `fold-page-layout`: cancels the gutter + top pad to sit flush, brand-tinted wash + hairline. `align` center·start, `wash`, `[heroBackdrop]` decorative lane. (For a bordered header card, see `fold-hero-card`.) |
298
+ | `FoldAsideLayoutComponent` | `fold-aside-layout` | Detail-page grid — a centred column flanked by up to two sticky rails (`[asideLeft]` / `[asideRight]`), collapsing to one column on its own container width (`:has()`-driven, container queries). Labelled rails become `complementary` landmarks; every track is a CSS var. |
299
+ | `FoldNavLayoutComponent` | `fold-nav-layout` | Places a bar (`[tabNav]` — a `fold-view-nav` or a `fold-tabs`) with its content — `placement="top"` or a `side` rail that folds back on top (hysteretic, on its own width) below `foldAt`. `exportAs="foldNavLayout"` exposes `stacked()` so the projected bar follows in one binding. |
300
+ | `FoldCardComponent` | `fold-card` | Raised content surface (`surface` = `card`/`sunken`/`accent`, hairline border, consistent radius). `accent` is an **auto-inverting** accent-filled card: the whole content sub-tree re-points to a compatible on-accent palette (text, borders, band gradation, nested buttons/links/icon-tiles) — every value a `color-mix` of the accent, so it holds on all themes (see [auto-inverting surfaces](#auto-inverting-surfaces)). Optional projected `[cardHeader]`/`[cardFooter]` bands with per-band chrome (`separators`/`raisedBands` = `none`/`header`/`footer`/`both`); the body padding never shifts when a band toggles. `interactive` makes the whole card an accessible button (`role`/`tabindex`, focus ring, Enter/Space/click → `(activated)`). |
301
+ | `FoldContextCardComponent` | `fold-context-card` | Titled info card: icon header + body + optional footer action. |
302
+ | `FoldHeroCardComponent` | `fold-hero-card` | Prominent header **card** — bordered surface × accent overlay + optional accent bar. (For a full-bleed page splash, see `fold-hero-section`.) |
303
+ | `FoldElementTitleComponent` | `fold-element-title` | Uppercase section/card mini-title (eyebrow · bar variants). |
304
+ | `FoldFieldListComponent` / `…Field` | `fold-field-list` | Read-only `dl/dt/dd` recap — label/value pairs (`[empty]` placeholder). The _display_ half of a record; `fold-input` is the _edit_ half. |
305
+ | `FoldInputComponent` | `fold-input` | Text-input control (`value: string`) — Signal Forms (`[formField]`) or standalone `[(value)]`; size × align × variant, `label` / `required` / `hint`. The _edit_ half of a record (`fold-field` reads). |
306
+ | `FoldNumberInputComponent` | `fold-number-input` | Numeric sibling of `fold-input` (`value: number \| null`, empty ⇒ `null`); owns `min` / `max` / `step` + `label` / `required` / `hint`. Split so each control keeps its true type. |
307
+ | `FoldCheckboxComponent` | `fold-checkbox` | Boolean control — a native `<input type="checkbox">` (keyboard, `indeterminate`, forms) restyled to tokens. Signal Forms (`[formField]`, a `FormCheckboxControl`) or standalone `[(checked)]`; `indeterminate`, `label`/`ariaLabel`, `hint`/`errors`, `size`. |
308
+ | `FoldPasswordFieldComponent` | `fold-password-field` | Password input + a live requirements checklist (a dot/tick per rule). Rules injected via `FoldPasswordRule` (`{ label, test }` — regex/zod/anything); `revealable` eye (a `fold-input` capability); `marker` dot/check; `[rules]` slot to redesign the list; `validChange`; Signal Forms. |
309
+ | `FoldViewToggleComponent` | `fold-view-toggle` | Segmented single-select (Cards/Table, density, chart-mode…). Generic `options` (`{ value, icon?, label?, ariaLabel?, disabled? }`) + `[(value)]`; a real `role="radiogroup"` — roving tabindex, arrow keys, Home/End, disabled-skip; `size`, `iconOnly`, `activeStyle` (raised / accent). |
310
+ | `FoldSearchComponent` | `fold-search` | Debounced search box — an `fold-input` that emits `searchChange` once typing settles (`delayMs`), trimmed + de-duplicated. |
311
+ | `FoldListboxComponent` / `FoldOptionComponent` | `fold-listbox` / `fold-option` | Styleable single-select — the richer sibling of `fold-select` (native `<select>`) for options that need custom rows (icon, second line, status). On `fold-popover`; `role="listbox"` + `aria-activedescendant`, full keyboard (↑/↓, `Home`/`End`, type-ahead, `Enter`). Signal Forms (`FormValueControl<string>`, `[formField]`/`[(value)]`); shares `fold-input`'s box chrome. |
312
+ | `FoldMultiselectComponent` | `fold-multiselect` | Multi-select sibling of `fold-listbox` (same popover + `fold-option` rows). Value is a set (`readonly string[]`); activating a row toggles it and the panel stays open. Separate component — not a `multiple` flag — so the Signal-Forms value type stays honest. `role="listbox"` + `aria-multiselectable`; the trigger summarises the picks. |
313
+ | `FoldSliderComponent` | `fold-slider` | Single-value range slider — a styled native `<input type="range">` (design-system track/fill/thumb). Signal Forms (`[formField]`, a `FormValueControl<number>`) or `[(value)]`; real `<label for>`, `aria-valuetext`, `hint`/`errors`, focus ring. |
314
+ | `FoldRangeSliderComponent` | `fold-range-slider` | Dual-thumb range slider selecting a `{ min, max }` window (shares the slider track/thumb). Two-way `[(value)]`; a labelled `role="group"`, per-thumb i18n aria (`minLabel`/`maxLabel`) + formatted `aria-valuetext`, `disabled`. |
315
+ | `FoldRangeSliderComponent` | `fold-range-slider` | Dual-thumb slider selecting a `{ min, max }` window over `[min, max]`; shares the slider track/fill/thumb. |
316
+ | `FoldFileDropzoneComponent` | `fold-file-dropzone` | File-picker dropzone — drag-over visuals, keyboard activation, hidden `<input type=file>` plumbing; emits the picked `File[]` (presentational — never uploads). |
317
+ | `FoldLinkComponent` | `fold-link` | Inline text link / link-button (icons, accent · muted). |
318
+ | `FoldButtonComponent` | `button[foldButton]` · `a[foldButton]` | Action button — applied to a real `<button>` **or** `<a>` (link that looks like a button, gets `href`/`routerLink`); orthogonal `emphasis` (solid·soft·outline) × `intent` (primary·neutral·warning·danger) × 3 sizes × shape/`block`; `icon`/`iconTrailing` shorthand (auto-sized) or project content; `loading` (spinner + `aria-busy`). Use native `(click)`. |
319
+ | `FoldButtonIconComponent` | `fold-button-icon` | Icon-only **momentary** button — shape × size × tone; a one-shot action (no pressed state). For a text button use `fold-button`; for on/off use `fold-toggle-icon`. |
320
+ | `FoldToggleIconComponent` | `fold-toggle-icon` | Icon-only **toggle** — the same surface as `fold-button-icon`, plus `[(active)]` + `aria-pressed` (true/false) and a pressed state. Emits `toggled`. |
321
+ | `FoldInlineConfirmComponent` | `fold-inline-confirm` | In-place “are you sure?” guard — the projected trigger swaps to a confirm/cancel row (no modal). Simple (`confirmed` emits `""`), type-to-confirm (`[match]`), or secret (`password`, masked, emits the value). `confirmIcon` + a chosen `cancelIcon`; `Escape` cancels; `message` announced via `aria-describedby`; focus in-then-back; controlled `[(open)]` + `keepOpenOnConfirm` for async pending; i18n via `provideFoldInlineConfirmLabels`. |
322
+ | `FoldDataTableComponent` | `fold-data-table` | Controlled roster table — sortable sticky header, tone rows, controlled selection (checkbox column), roving-keyboard nav, `mobileLayout` (scroll / auto-cards / custom `foldRowCard`), an optional `foldToolbar` bar, sticky-first, density. |
323
+ | `FoldPaginatorComponent` | `fold-paginator` | Server-side paginator (size selector + range + page nav). |
324
+ | `FoldTimelineComponent` | `fold-timeline` | Connected rail of nodes (dot + optional date + label) — `vertical` navigable history or `horizontal` step progress; nodes optionally clickable. |
325
+ | `FoldBadgeComponent` | `fold-badge` | Status / count pill (accent/info/warning/alert/success). |
326
+ | `FoldStatusBadgeComponent` | `fold-status-badge` | Status→colour badge (maps a domain status key to a tone). |
327
+ | `FoldChoiceRowComponent` | `fold-choice-row` | Segmented / chip selector. |
328
+ | `FoldViewNavComponent` | `fold-view-nav` | Navigation bar styled as tabs. Items carry a `link` (routerLink → a real `<a>`: cmd-click, deep-links, active state auto), an `href`, or nothing (a button); `aria-current="page"` on the active one. `direction="auto"` follows a wrapping `fold-nav-layout`; `collapsed` for an icon rail. For in-page panel switching use `fold-tabs` instead. |
329
+ | `FoldTabsComponent` + `FoldTabPanelComponent` | `fold-tabs` + `fold-tab-panel` | The in-page ARIA Tabs widget: `role="tablist"` + roving arrow-key keyboard, `aria-selected`/`aria-orientation`, each tab wired to its `fold-tab-panel` (`aria-controls` ↔ `aria-labelledby`). Panels take the bar by ref (`[tabs]="t"`) so they coordinate across `fold-nav-layout` slots. |
330
+ | `FoldIconComponent` | `fold-icon` | SVG icon (114-icon built-in set + `FoldIconRegistry`). |
331
+ | `FoldSpinnerComponent` | `fold-spinner` | Indeterminate loading arc (`currentColor`, icon-sized, reduced-motion aware). Decorative by default; `label` → `role="status"`. Powers `loading` on the buttons. |
332
+ | `FoldAvatarComponent` / `…Detail` | `fold-avatar` | Initials/image avatar (square, muted, status ring) + identity cell. |
333
+ | `FoldAvatarListComponent` | `fold-avatar-list` | Overlapping avatar cluster (per-face variant, `limit` + a `+N` overflow chip). |
334
+ | `FoldToastComponent` / `…Container` | `fold-toast` | Frosted snackbar (variant glyph + dismiss) + queue host (+ `FoldToastService`). |
335
+ | `FoldLoadingStateComponent` | `fold-loading` | Loading placeholder — `fold-spinner` + message, in a `role="status"` region; `size` input; stretches to fill. |
336
+ | `FoldEmptyStateComponent` | `fold-empty-state` | Empty-state block (icon + title + message + optional action). |
337
+ | `FoldCalloutComponent` | `fold-callout` | Tinted message row — status colour + icon + message + optional trailing actions; `inset` (bordered, in-flow) appearance. |
338
+ | `FoldDisclosureComponent` | `fold-disclosure` | One summary toggling one collapsible panel — the accordion primitive (open-state is the consumer's to bind); keeps content mounted, unlike native `<details>`. |
339
+ | `FoldPanelHostComponent` | `fold-panel-host` | Side-panel / overlay host (+ `FoldPanelHostService` / `FoldPanelRef` / `FoldPanelToggle`). Modal: accessible name, `inert` background barrier, top-most focus trap, scroll-lock. Localise the close label once via `provideFoldPanelLabels({ close })`. |
340
+ | `FoldPanelHeaderComponent` | `fold-panel-header` | Standard panel header (title/eyebrow, self-closing). Names its dialog (`aria-labelledby`) and reads the app-wide close label. |
341
+ | `FoldPopoverComponent` | `fold-popover` | Anchored floating layer — projected content in the native top layer (escapes `overflow`/`z-index`), positioned by a dependency-free **flip → size → shift** engine (`computePlacement`): a tall panel gets a `max-height` and scrolls inside the viewport. `[(open)]`; `autoUpdate` (ResizeObserver); optional `arrow`; native CSS enter/exit (`@starting-style` + `allow-discrete`); outside-click + `Escape` dismissal, focus-return, auto-wired `aria-haspopup`/`expanded`/`controls`. |
342
+ | `FoldDropdownComponent` | `fold-dropdown` | Actions menu on `fold-popover` — `role="menu"` with `<fold-dropdown-item>`s, ↑/↓ roving, `Home`/`End`, type-ahead; opens onto the first enabled item, closes returning focus to the trigger. Give the trigger `foldPopoverTrigger="menu"`. |
257
343
 
258
344
  Directives worth knowing: **`foldSurface`** (`page`·`chrome` — the seam a mixed
259
345
  theme re-colours across), **`foldElevated`** (raise any bg-owning element into