fold-ng 0.2.1 → 0.3.0

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/llms.txt CHANGED
@@ -26,8 +26,8 @@ with a `@selector` and an `@example`.
26
26
  - Actions: `[foldButton]` (on a real `<button>`/`<a>`; `emphasis` × `intent` axes; `loading`), `fold-button-icon` (momentary), `fold-toggle-icon` (toggle), `fold-link`.
27
27
  - Forms: `fold-input`, `fold-number-input`, `fold-select`, `fold-search`, `fold-slider`, `fold-range-slider`, `fold-file-dropzone` (Angular Signal Forms — no `ngModel`/`ReactiveFormsModule`).
28
28
  - Overlays: `fold-panel-host` / `fold-panel-header` (modal side panels with accessible name, `inert` background barrier, focus trap, scroll-lock; imperative `open<TData,TResult>()` → typed `FoldPanelRef`).
29
- - Navigation: `fold-menu`, `fold-nav-launcher`, `fold-tab-nav`.
30
- - Layout: `fold-app-shell`, `fold-page-layout`, `fold-aside-layout`, `fold-tab-layout`, `fold-hero-section`.
29
+ - Navigation: `fold-menu`, `fold-nav-launcher`, `fold-view-nav` (tab-styled nav bar; items with a `link` render real `<a routerLink>` with `aria-current` + auto active state, else buttons; `direction="auto"`, `collapsed` icon rail), `fold-tabs` + `fold-tab-panel` (the in-page ARIA Tabs widget — `role="tablist"`, roving arrow keys).
30
+ - Layout: `fold-app-shell`, `fold-page-layout`, `fold-aside-layout`, `fold-nav-layout` (places a nav/tabs bar + content, folds side↔top), `fold-hero-section`.
31
31
  - Content: `fold-card`, `fold-hero-card`, `fold-badge`, `fold-status-badge`, `fold-avatar`, `fold-avatar-list`, `fold-timeline`, `fold-data-table`, `fold-paginator`, `fold-field`.
32
32
  - Feedback: `fold-callout`, `fold-disclosure`, `fold-toast`, `fold-loading`, `fold-empty-state`.
33
33
  - Foundations: `fold-icon` (114 built-in SVGs + registry), `fold-spinner`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fold-ng",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Accessible, dark-first Angular 22 UI component library & design system — signals-first, standalone, zoneless, SSR-ready. Design tokens + WCAG-minded components, themeable to the bone.",
5
5
  "keywords": [
6
6
  "angular",
package/tokens/scales.css CHANGED
@@ -55,6 +55,14 @@
55
55
  --fold-space-lg: 16px;
56
56
  --fold-space-xl: 20px;
57
57
 
58
+ /* Rail-width scale — the shared widths for the nav-rail hierarchy, named to
59
+ pair 1:1 with the `--fold-color-bg-rail-*` colour tokens (primary app menu →
60
+ secondary workspace/aside → tertiary in-page nav). Retune once, every rail
61
+ follows; each layout's own `--fold-<layout>-rail-*` var still overrides. */
62
+ --fold-rail-primary: 64px; /* app menu — the compact icon rail (fold-app-shell) */
63
+ --fold-rail-secondary: 220px; /* workspace / content aside (fold-aside-layout) */
64
+ --fold-rail-tertiary: 200px; /* in-page / section nav (fold-nav-layout) */
65
+
58
66
  /* Motion scale — transition shorthands (duration + easing bundled, matching
59
67
  the app so `--t-*` bridge onto these 1:1). One knob per interaction speed. */
60
68
  --fold-motion-fast: 0.1s ease;
@@ -2954,7 +2954,21 @@ declare class FoldAsideLayoutComponent {
2954
2954
  }
2955
2955
 
2956
2956
  /**
2957
- * `<fold-tab-layout>` — pairs a tab bar with the content it drives, and owns the
2957
+ * The slice of a {@link FoldNavLayoutComponent} that a projected bar reads to
2958
+ * follow the layout — exposed through DI so a `fold-view-nav` / `fold-tabs` with
2959
+ * `direction="auto"` orients itself without the consumer wiring `tl.stacked()`.
2960
+ */
2961
+ interface FoldNavLayoutContext {
2962
+ /**
2963
+ * True when the layout currently stacks the bar **above** the content (a `top`
2964
+ * placement, or a `side` rail that has folded) — i.e. the bar should be
2965
+ * horizontal. False when it sits as a vertical rail beside the content.
2966
+ */
2967
+ readonly stacked: Signal<boolean>;
2968
+ }
2969
+
2970
+ /**
2971
+ * `<fold-nav-layout>` — pairs a tab bar with the content it drives, and owns the
2958
2972
  * one thing every tabbed page hand-rolls: where the nav sits.
2959
2973
  *
2960
2974
  * - `placement="top"` (default) — the nav above the content.
@@ -2962,39 +2976,62 @@ declare class FoldAsideLayoutComponent {
2962
2976
  * top when the layout gets narrower than {@link foldAt} (so the menu always
2963
2977
  * precedes the content it drives, never below it).
2964
2978
  *
2965
- * Content projection — the nav stays yours (tabs, active key, events):
2966
- * - `[tabNav]` → the tab bar (an `fold-tab-nav`, or anything else).
2967
- * - default slot → the content for the active tab.
2979
+ * Content projection — the bar stays yours (tabs, active key, events):
2980
+ * - `[tabNav]` → the bar. Project a {@link FoldViewNavComponent} if the tabs
2981
+ * **navigate** (route between views) or a {@link FoldTabsComponent} if they
2982
+ * **switch panels in place** — this layout is agnostic, it only places the bar.
2983
+ * - default slot → the content (routed views, or the tabs' `fold-tab-panel`s).
2968
2984
  *
2969
- * **A11y — this owns placement, not the ARIA tabs pattern.** The projected bar
2970
- * carries the `tablist`/`tab` roles; the content is yours. If the tabs switch
2971
- * in-page panels, give that content `role="tabpanel"` named by the active tab;
2972
- * if they navigate between routes, keep plain nav semantics and add no tab
2973
- * roles (the tabs pattern is for panel-switching, not navigation).
2985
+ * **A11y lives in the bar, not here.** `fold-view-nav` brings `<nav>` +
2986
+ * `aria-current`; `fold-tabs` brings the full `role="tablist"` widget with its
2987
+ * `fold-tab-panel`s. This component adds no tab semantics — it only decides where
2988
+ * the bar sits and folds it responsively.
2974
2989
  *
2975
- * A side rail needs a *vertical* bar, a folded one a *horizontal* bar. Rather
2976
- * than guess, the layout exposes {@link stacked} (`exportAs`) so the projected
2977
- * nav follows the layout in one binding:
2990
+ * A side rail needs a *vertical* bar, a folded one a *horizontal* bar. The
2991
+ * projected bar handles that itself with `direction="auto"` (its default) — it
2992
+ * reads this layout through DI ({@link FoldNavLayoutContext}), no wiring:
2978
2993
  *
2979
2994
  * ```html
2980
- * <fold-tab-layout placement="side" #tl="foldTabLayout">
2981
- * <fold-tab-nav
2982
- * tabNav
2983
- * [direction]="tl.stacked() ? 'horizontal' : 'vertical'"
2984
- * [tabs]="tabs"
2985
- * [activeKey]="tab()"
2986
- * (tabChange)="tab.set($event)"
2987
- * />
2988
- * <app-tab-content />
2989
- * </fold-tab-layout>
2995
+ * <fold-nav-layout placement="side">
2996
+ * <fold-view-nav tabNav [items]="items" />
2997
+ * <router-outlet />
2998
+ * </fold-nav-layout>
2999
+ * ```
3000
+ *
3001
+ * The layout also exposes {@link stacked} via `exportAs` for consumers that want
3002
+ * to read the folded state themselves.
3003
+ *
3004
+ * **Two roles — same component, composed differently.**
3005
+ * - **Page scaffold** — the tab rail *is* the page's primary structure: use it
3006
+ * directly (usually `placement="side"`), the folded bar leading the content.
3007
+ * - **Tabbed section** — a tabbed block *inside* a page, among other sections.
3008
+ * Don't reach for a new mode — wrap it in a {@link FoldPageSectionComponent}.
3009
+ * The section owns the title, the `<section>` + heading semantics, the vertical
3010
+ * rhythm and the optional `bleed`; tab-layout stays pure placement. It paints
3011
+ * nothing (no card), so it sits **flat** — add `bleed` on the section for an
3012
+ * edge-to-edge band. The rail folds on the **section's** width (it measures
3013
+ * itself), not the viewport, so nested tabs collapse on their own.
3014
+ *
3015
+ * ```html
3016
+ * <!-- a tabbed section: flat structure (page-section) + tab placement -->
3017
+ * <fold-page-section title="Settings" bleed>
3018
+ * <fold-nav-layout placement="side">
3019
+ * <fold-view-nav tabNav [items]="items" />
3020
+ * <app-settings-panel />
3021
+ * </fold-nav-layout>
3022
+ * </fold-page-section>
2990
3023
  * ```
2991
3024
  *
2992
- * Sizing is CSS custom properties: `--fold-tab-layout-gap` (16px) and
2993
- * `--fold-tab-layout-nav-width` (200px, the side rail track).
3025
+ * Sizing is CSS custom properties: `--fold-nav-layout-gap` (16px) and
3026
+ * `--fold-nav-layout-rail-width` — the side-rail track, defaulting to the shared
3027
+ * `--fold-rail-tertiary` (200px). That's the **tertiary** step of the rail
3028
+ * hierarchy — the same level the `--fold-color-bg-rail-tertiary` colour names
3029
+ * (app menu → workspace → in-page nav) — so every rail in the app stays on one
3030
+ * scale. Override the local var per instance.
2994
3031
  *
2995
- * @selector `fold-tab-layout`
3032
+ * @selector `fold-nav-layout`
2996
3033
  */
2997
- declare class FoldTabLayoutComponent {
3034
+ declare class FoldNavLayoutComponent implements FoldNavLayoutContext {
2998
3035
  /** Where the nav sits: above the content, or as a rail beside it. */
2999
3036
  readonly placement: _angular_core.InputSignal<"top" | "side">;
3000
3037
  /** Width (px) at or below which a `side` nav folds back on top. */
@@ -3018,10 +3055,28 @@ declare class FoldTabLayoutComponent {
3018
3055
  * forever. A dead band wider than any scrollbar breaks that loop.
3019
3056
  */
3020
3057
  private measure;
3021
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldTabLayoutComponent, never>;
3022
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldTabLayoutComponent, "fold-tab-layout", ["foldTabLayout"], { "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "foldAt": { "alias": "foldAt"; "required": false; "isSignal": true; }; }, {}, never, ["[tabNav]", "*"], true, never>;
3058
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldNavLayoutComponent, never>;
3059
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldNavLayoutComponent, "fold-nav-layout", ["foldNavLayout"], { "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "foldAt": { "alias": "foldAt"; "required": false; "isSignal": true; }; }, {}, never, ["[tabNav]", "*"], true, never>;
3023
3060
  }
3024
3061
 
3062
+ /**
3063
+ * Marks a custom page title projected into {@link FoldPageLayoutComponent} — put
3064
+ * it on inline heading content when the plain `icon` + `title` inputs aren't
3065
+ * enough (an avatar, a two-tone title, a live status). It renders inside the
3066
+ * page's `<h1>`, so keep it inline and text-like. Its presence switches the
3067
+ * header on in place of the input-driven title.
3068
+ *
3069
+ * @example
3070
+ * ```html
3071
+ * <fold-page-layout>
3072
+ * <span pageTitle><fold-avatar … /> Acme Records</span>
3073
+ * </fold-page-layout>
3074
+ * ```
3075
+ */
3076
+ declare class FoldPageTitleDirective {
3077
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldPageTitleDirective, never>;
3078
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<FoldPageTitleDirective, "[pageTitle]", never, {}, {}, never, never, true, never>;
3079
+ }
3025
3080
  /**
3026
3081
  * `<fold-page-layout>` — the vertical scaffold for a settings/admin-style page:
3027
3082
  * an optional `icon` + `title` header with a description slot, an optional
@@ -3043,6 +3098,10 @@ declare class FoldTabLayoutComponent {
3043
3098
  *
3044
3099
  * Content projection:
3045
3100
  * - default slot → the page body (sections, cards, banners…).
3101
+ * - `[pageTitle]` ({@link FoldPageTitleDirective}) → a custom title, rendered
3102
+ * inside the `<h1>` in place of the `icon` + `title` inputs, for when a plain
3103
+ * string won't do (an avatar, a two-tone title). Its presence alone switches
3104
+ * the header on.
3046
3105
  * - `[titleBadge]` → an inline pill beside the title (e.g. a status/kind badge).
3047
3106
  * - `p[description]` → the intro under the title. A **slot**, not a string
3048
3107
  * input: a description that needs a `<code>`, a link or a second sentence is
@@ -3071,8 +3130,11 @@ declare class FoldPageLayoutComponent {
3071
3130
  readonly title: _angular_core.InputSignal<string | undefined>;
3072
3131
  /** An optional leading icon shown beside the title. */
3073
3132
  readonly icon: _angular_core.InputSignal<FoldIconName | undefined>;
3133
+ /** A projected `[pageTitle]`, if any — switches the header on for a custom
3134
+ * title even without the `title` input. */
3135
+ protected readonly customTitle: _angular_core.Signal<FoldPageTitleDirective | undefined>;
3074
3136
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldPageLayoutComponent, never>;
3075
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldPageLayoutComponent, "fold-page-layout", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; }, {}, never, ["[titleBadge]", "p[description]", "[pageActions]", "*"], true, never>;
3137
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldPageLayoutComponent, "fold-page-layout", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; }, {}, ["customTitle"], ["[pageTitle]", "[titleBadge]", "p[description]", "[pageActions]", "*"], true, never>;
3076
3138
  }
3077
3139
 
3078
3140
  /**
@@ -3251,8 +3313,8 @@ declare class FoldPaginatorComponent {
3251
3313
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldPaginatorComponent, "fold-paginator", never, { "currentPage": { "alias": "currentPage"; "required": true; "isSignal": true; }; "totalItems": { "alias": "totalItems"; "required": true; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": true; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "siblingCount": { "alias": "siblingCount"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; }, never, never, true, never>;
3252
3314
  }
3253
3315
 
3254
- type FoldTabNavItem = {
3255
- /** Unique key — identifies the tab and is emitted on click. */
3316
+ type FoldViewNavItem = {
3317
+ /** Unique key — identifies the item and is emitted by `activeChange`. */
3256
3318
  key: string;
3257
3319
  /** Display label. */
3258
3320
  label: string;
@@ -3260,55 +3322,222 @@ type FoldTabNavItem = {
3260
3322
  icon?: FoldIconName;
3261
3323
  /** Optional trailing badge (e.g. a count). `undefined`/`null` hides it. */
3262
3324
  badge?: string | number | null;
3325
+ /**
3326
+ * Router target — makes this item a real `routerLink` `<a>`: cmd/middle-click
3327
+ * opens a new tab, the URL is a deep link, and the active state is driven
3328
+ * automatically by `routerLinkActive` (no `activeKey` needed). Accepts the
3329
+ * same value as `[routerLink]` — a path string or a commands array.
3330
+ */
3331
+ link?: string | unknown[];
3332
+ /** External URL — renders a plain `<a href>` (no router). */
3333
+ href?: string;
3334
+ /** Disable the item: non-interactive + dimmed. */
3335
+ disabled?: boolean;
3263
3336
  };
3264
3337
  /**
3265
- * `<fold-tab-nav>` — a tab navigation bar (buttons only; the parent renders the
3266
- * content for the active key).
3338
+ * `<fold-view-nav>` — a **navigation** bar styled as tabs: a `<nav>` whose items
3339
+ * *go somewhere*. Give each item a `link` (or `href`) and it renders a real
3340
+ * `<a>` — so cmd/middle-click opens a new tab, the URL is a deep link, and the
3341
+ * active item is driven automatically by `routerLinkActive` +
3342
+ * `aria-current="page"`. Without a link an item is a `<button>` that emits
3343
+ * `activeChange` and reads its active state from `activeKey` (view switching
3344
+ * with no route).
3345
+ *
3346
+ * **Navigation, not the tabs widget.** Reach for this when a tab routes / switches
3347
+ * views. When tabs toggle **layered panels in place** (same URL), use
3348
+ * {@link FoldTabsComponent} — same look, but the ARIA Tabs pattern
3349
+ * (`role="tablist"`, arrow keys, `tabpanel`).
3267
3350
  *
3268
- * - `activeStyle` — `underline` (accent border on the active tab) or `fill`
3269
- * (accent background pill, good for sidebars).
3270
- * - `direction` — `horizontal` (row, equal-width) or `vertical` (stacked
3271
- * sidebar; auto-collapses to a horizontal icon-accordion at ≤768px).
3351
+ * - `activeStyle` — `underline` (accent border) or `fill` (accent pill).
3352
+ * - `direction` — `auto` (default: follows a wrapping `fold-nav-layout`, else
3353
+ * vertical), `vertical`, or `horizontal`.
3272
3354
  *
3273
- * @selector `fold-tab-nav`
3355
+ * @selector `fold-view-nav`
3274
3356
  *
3275
3357
  * @example
3276
3358
  * ```html
3277
- * <fold-tab-nav
3278
- * [tabs]="[{ key: 'members', label: 'Members', badge: 3 }, { key: 'settings', label: 'Settings' }]"
3279
- * [activeKey]="tab()"
3280
- * activeStyle="underline"
3281
- * direction="horizontal"
3282
- * (tabChange)="tab.set($event)"
3283
- * />
3359
+ * <!-- real navigation: link items, active state automatic -->
3360
+ * <fold-view-nav [items]="[
3361
+ * { key: 'members', label: 'Members', link: 'members', badge: 3 },
3362
+ * { key: 'settings', label: 'Settings', link: 'settings' },
3363
+ * ]" />
3364
+ * <router-outlet />
3284
3365
  * ```
3285
3366
  */
3286
- declare class FoldTabNavComponent {
3287
- /** The tabs to render, in order. */
3288
- readonly tabs: _angular_core.InputSignal<FoldTabNavItem[]>;
3289
- /** The `key` of the currently active tab. */
3367
+ declare class FoldViewNavComponent {
3368
+ /** The items to render, in order. */
3369
+ readonly items: _angular_core.InputSignal<FoldViewNavItem[]>;
3370
+ /**
3371
+ * The active item's `key` — for **button** items (no `link`). Link items ignore
3372
+ * it: their active state comes from the URL via `routerLinkActive`.
3373
+ */
3290
3374
  readonly activeKey: _angular_core.InputSignal<string>;
3291
- /** How the active tab reads: accent underline, or accent fill. */
3375
+ /** How the active item reads: accent underline, or accent fill. */
3292
3376
  readonly activeStyle: _angular_core.InputSignal<"fill" | "underline">;
3293
- /** Bar orientation (vertical auto-collapses to horizontal on mobile). */
3294
- readonly direction: _angular_core.InputSignal<"vertical" | "horizontal">;
3295
3377
  /**
3296
- * Density, from tightest to roomiest:
3297
- * - `reduce` — an icon accordion: every tab but the active one drops its label
3298
- * (and badge) to just its icon, while the active tab keeps its label and
3299
- * takes the remaining room. A tab with no icon keeps its label, so nothing
3300
- * is left unlabelled. Swap to it from your own breakpoint when the bar is
3301
- * too tight for every label.
3378
+ * Bar orientation. Defaults to `auto`: inside a `fold-nav-layout` it follows
3379
+ * the layout (vertical rail, horizontal once folded) with no wiring; on its
3380
+ * own it is `vertical` — the readable-first shape, reading as the app's
3381
+ * **third navigation rail** (app menu → workspace → in-page views, the
3382
+ * `--fold-rail-tertiary` level). Force `horizontal` for a page-level top bar.
3383
+ */
3384
+ readonly direction: _angular_core.InputSignal<"auto" | "vertical" | "horizontal">;
3385
+ /**
3386
+ * Density — pure padding/typography:
3302
3387
  * - `compact` (default) — inline / popover bars.
3303
3388
  * - `comfortable` — a prominent, page-level bar.
3304
3389
  */
3305
- readonly size: _angular_core.InputSignal<"reduce" | "compact" | "comfortable">;
3306
- /** `surface` (filled bar, default) or `transparent` (blends with the app). */
3390
+ readonly size: _angular_core.InputSignal<"compact" | "comfortable">;
3391
+ /**
3392
+ * Collapse the bar to icons (independent of {@link size}). **Horizontal**, an
3393
+ * icon accordion: every item but the active one drops to its icon, the active
3394
+ * one keeps its label. **Vertical**, a collapsed icon rail (like a folded
3395
+ * menu): every item shows just its icon, its label a hover/focus tooltip and
3396
+ * its count a corner bubble — narrow the layout's `--fold-nav-layout-rail-width`
3397
+ * to match. An item with no icon falls back to a square glyph of its label's
3398
+ * initial, so the rail stays icon-width whether or not items carry icons.
3399
+ * Toggle it from your own breakpoint when the bar is too tight.
3400
+ */
3401
+ readonly collapsed: _angular_core.InputSignalWithTransform<boolean, unknown>;
3402
+ /**
3403
+ * `transparent` (default — blends with the app, so the items read directly) or
3404
+ * `surface` (a filled bar that carries its own rail background).
3405
+ */
3307
3406
  readonly background: _angular_core.InputSignal<"transparent" | "surface">;
3308
- /** Emits the `key` of the clicked tab. */
3407
+ /** Emits the `key` of a clicked **button** item (link items just navigate). */
3408
+ readonly activeChange: _angular_core.OutputEmitterRef<string>;
3409
+ /** The nearest layout, if any — lets `direction="auto"` follow it. */
3410
+ private readonly layout;
3411
+ /** `direction` with `auto` resolved against the wrapping layout. */
3412
+ protected readonly resolvedDirection: _angular_core.Signal<"vertical" | "horizontal">;
3413
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldViewNavComponent, never>;
3414
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldViewNavComponent, "fold-view-nav", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "activeKey": { "alias": "activeKey"; "required": false; "isSignal": true; }; "activeStyle": { "alias": "activeStyle"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "background": { "alias": "background"; "required": false; "isSignal": true; }; }, { "activeChange": "activeChange"; }, never, never, true, never>;
3415
+ }
3416
+
3417
+ /** A tab in a {@link FoldTabsComponent} bar. */
3418
+ type FoldTabItem = {
3419
+ /** Unique key — identifies the tab / its panel, emitted on change. */
3420
+ key: string;
3421
+ /** Display label. */
3422
+ label: string;
3423
+ /** Optional leading icon. */
3424
+ icon?: FoldIconName;
3425
+ /** Optional trailing count badge. `undefined`/`null` hides it. */
3426
+ badge?: string | number | null;
3427
+ };
3428
+ /**
3429
+ * The read side a {@link FoldTabPanelComponent} needs to wire itself to a tab —
3430
+ * exposed by `fold-tabs` via `exportAs="foldTabs"`. Decouples the panel from the
3431
+ * concrete component.
3432
+ */
3433
+ interface FoldTabsContext {
3434
+ /** The active tab's key. */
3435
+ activeKey(): string;
3436
+ /** The DOM id of the tab for `key` (a panel's `aria-labelledby`). */
3437
+ tabId(key: string): string;
3438
+ /** The DOM id of the panel for `key` (a tab's `aria-controls`). */
3439
+ panelId(key: string): string;
3440
+ }
3441
+ /**
3442
+ * `<fold-tabs>` — the **in-page tabs widget** (the ARIA Tabs pattern): a
3443
+ * `role="tablist"` of `role="tab"` buttons that switch layered panels **without
3444
+ * navigating**. Arrow keys move between tabs (roving tabindex — only the active
3445
+ * tab is in the Tab order), `Home`/`End` jump to the ends, and each tab is wired
3446
+ * to its panel via `aria-controls` ↔ `aria-labelledby`.
3447
+ *
3448
+ * Pair it with one {@link FoldTabPanelComponent} per key, handed the bar via a
3449
+ * template ref so the two coordinate across slots (e.g. inside a
3450
+ * `fold-nav-layout`). Same visual as {@link FoldViewNavComponent}; the
3451
+ * difference is **semantics** — use `fold-tabs` for in-page panel switching, and
3452
+ * `fold-view-nav` when the tabs actually navigate (route) between views.
3453
+ *
3454
+ * ```html
3455
+ * <fold-nav-layout>
3456
+ * <fold-tabs
3457
+ * nav
3458
+ * #t="foldTabs"
3459
+ * [tabs]="tabs"
3460
+ * [activeKey]="tab()"
3461
+ * (tabChange)="tab.set($event)"
3462
+ * />
3463
+ * <fold-tab-panel [tabs]="t" key="overview">…</fold-tab-panel>
3464
+ * <fold-tab-panel [tabs]="t" key="settings">…</fold-tab-panel>
3465
+ * </fold-nav-layout>
3466
+ * ```
3467
+ *
3468
+ * Same visual knobs as `fold-view-nav` (`activeStyle` · `direction` · `size` ·
3469
+ * `background`). Sizing shares the tab-bar tokens.
3470
+ *
3471
+ * @selector `fold-tabs`
3472
+ */
3473
+ declare class FoldTabsComponent implements FoldTabsContext {
3474
+ /** The tabs to render, in order. */
3475
+ readonly tabs: _angular_core.InputSignal<FoldTabItem[]>;
3476
+ /** The `key` of the active tab (the shown panel). */
3477
+ readonly activeKey: _angular_core.InputSignal<string>;
3478
+ /** How the active tab reads: accent underline, or accent fill. */
3479
+ readonly activeStyle: _angular_core.InputSignal<"fill" | "underline">;
3480
+ /**
3481
+ * Bar orientation (drives `aria-orientation`). Defaults to `auto`: follows a
3482
+ * wrapping `fold-nav-layout`, else `horizontal`.
3483
+ */
3484
+ readonly direction: _angular_core.InputSignal<"auto" | "vertical" | "horizontal">;
3485
+ /** Density — see {@link FoldViewNavComponent} for the same scale. */
3486
+ readonly size: _angular_core.InputSignal<"compact" | "comfortable">;
3487
+ /** Collapse to icons — see {@link FoldViewNavComponent.collapsed}. */
3488
+ readonly collapsed: _angular_core.InputSignalWithTransform<boolean, unknown>;
3489
+ /** `surface` (filled bar, default) or `transparent`. */
3490
+ readonly background: _angular_core.InputSignal<"transparent" | "surface">;
3491
+ /** Emits the newly-selected tab's `key`. */
3309
3492
  readonly tabChange: _angular_core.OutputEmitterRef<string>;
3310
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldTabNavComponent, never>;
3311
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldTabNavComponent, "fold-tab-nav", never, { "tabs": { "alias": "tabs"; "required": true; "isSignal": true; }; "activeKey": { "alias": "activeKey"; "required": true; "isSignal": true; }; "activeStyle": { "alias": "activeStyle"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "background": { "alias": "background"; "required": false; "isSignal": true; }; }, { "tabChange": "tabChange"; }, never, never, true, never>;
3493
+ /** The nearest layout, if any — lets `direction="auto"` follow it. */
3494
+ private readonly layout;
3495
+ /** `direction` with `auto` resolved against the wrapping layout. */
3496
+ protected readonly resolvedDirection: _angular_core.Signal<"vertical" | "horizontal">;
3497
+ /** Per-instance id root, so ids are unique + stable across SSR. */
3498
+ private readonly uid;
3499
+ private readonly tabButtons;
3500
+ tabId(key: string): string;
3501
+ panelId(key: string): string;
3502
+ protected select(key: string): void;
3503
+ /**
3504
+ * Roving-tabindex keyboard model (APG Tabs, automatic activation): arrows move
3505
+ * — and select — the adjacent tab, `Home`/`End` the ends. Both axes work, so
3506
+ * it stays correct whether the bar is horizontal, vertical, or a
3507
+ * mobile-collapsed vertical.
3508
+ */
3509
+ protected onKeydown(event: KeyboardEvent): void;
3510
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldTabsComponent, never>;
3511
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldTabsComponent, "fold-tabs", ["foldTabs"], { "tabs": { "alias": "tabs"; "required": true; "isSignal": true; }; "activeKey": { "alias": "activeKey"; "required": true; "isSignal": true; }; "activeStyle": { "alias": "activeStyle"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "background": { "alias": "background"; "required": false; "isSignal": true; }; }, { "tabChange": "tabChange"; }, never, never, true, never>;
3512
+ }
3513
+
3514
+ /**
3515
+ * `<fold-tab-panel>` — one panel of a {@link FoldTabsComponent}. Handed the bar
3516
+ * via a template ref (`[tabs]="t"`, where `#t="foldTabs"`) plus its `key`, it
3517
+ * becomes a `role="tabpanel"` named by its tab (`aria-labelledby`), reachable by
3518
+ * `aria-controls` from that tab, focusable while active, and `hidden` otherwise.
3519
+ *
3520
+ * The ref pairing is what lets the tabs bar and its panels sit in **different**
3521
+ * slots (e.g. the bar in a `fold-nav-layout`'s nav slot, the panels in its
3522
+ * content) and still coordinate.
3523
+ *
3524
+ * ```html
3525
+ * <fold-tabs #t="foldTabs" [tabs]="tabs" [activeKey]="tab()" (tabChange)="tab.set($event)" />
3526
+ * <fold-tab-panel [tabs]="t" key="overview">…</fold-tab-panel>
3527
+ * ```
3528
+ *
3529
+ * @selector `fold-tab-panel`
3530
+ */
3531
+ declare class FoldTabPanelComponent {
3532
+ /** The owning `fold-tabs`, read via its template ref (`#t="foldTabs"`). */
3533
+ readonly tabs: _angular_core.InputSignal<FoldTabsContext>;
3534
+ /** This panel's tab key — must match one tab in the bar. */
3535
+ readonly key: _angular_core.InputSignal<string>;
3536
+ protected readonly isActive: _angular_core.Signal<boolean>;
3537
+ protected readonly panelId: _angular_core.Signal<string>;
3538
+ protected readonly labelledBy: _angular_core.Signal<string>;
3539
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FoldTabPanelComponent, never>;
3540
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FoldTabPanelComponent, "fold-tab-panel", never, { "tabs": { "alias": "tabs"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
3312
3541
  }
3313
3542
 
3314
3543
  /** The tone of a toast — drives its accent color + icon. */
@@ -3835,6 +4064,6 @@ declare class FoldPaletteRegistry {
3835
4064
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<FoldPaletteRegistry>;
3836
4065
  }
3837
4066
 
3838
- export { FOLD_AUTO_PALETTES, FOLD_BLUR_TOKENS, FOLD_BUILTIN_ICONS, FOLD_MOTION_TOKENS, FOLD_PALETTE_DEFAULT, FOLD_PANEL_CLOSE_LABEL, FOLD_RADIUS_TOKENS, FOLD_SEMANTIC_COLOR_TOKENS, FOLD_SHADOW_TOKENS, FOLD_SPACE_TOKENS, FOLD_TEXT_TOKENS, FOLD_TOAST_CONFIG, FoldAppShellComponent, FoldAsideLayoutComponent, FoldAvatarComponent, FoldAvatarDetailComponent, FoldAvatarListComponent, FoldBadgeComponent, FoldButtonComponent, FoldButtonIconComponent, FoldCalloutComponent, FoldCardComponent, FoldChoiceRowComponent, FoldContextCardComponent, FoldDataTableCellDirective, FoldDataTableComponent, FoldDisclosureComponent, FoldElementTitleComponent, FoldElevatedDirective, FoldEmptyStateComponent, FoldFieldComponent, FoldFieldIdDirective, FoldFieldListComponent, FoldFileDropzoneComponent, FoldHeroCardComponent, FoldHeroSectionComponent, FoldIconComponent, FoldIconRegistry, FoldIdService, FoldInputComponent, FoldLinkComponent, FoldLoadingStateComponent, FoldMenuComponent, FoldMenuItemComponent, FoldMenuSectionComponent, FoldMenuSeparatorComponent, FoldNavLauncherComponent, FoldNavTileComponent, FoldNumberInputComponent, FoldPageLayoutComponent, FoldPageSectionComponent, FoldPaginatorComponent, FoldPaletteRegistry, FoldPanelComponentOutletDirective, FoldPanelHeaderComponent, FoldPanelHostComponent, FoldPanelHostService, FoldPanelRef, FoldPanelToggle, FoldRangeSliderComponent, FoldRepeatPressDirective, FoldSearchComponent, FoldSelectComponent, FoldSliderComponent, FoldSpinnerComponent, FoldStatusBadgeComponent, FoldStickyColumnDirective, FoldSurfaceDirective, FoldTabLayoutComponent, FoldTabNavComponent, FoldTimelineComponent, FoldToastComponent, FoldToastContainerComponent, FoldToastService, FoldToggleIconComponent, foldBlurVar, foldColorProperty, foldColorVar, foldHashSeed, foldMotionVar, foldRadiusVar, foldResolvePalette, foldShadowVar, foldSpaceVar, foldTextVar, observeElementWidth, provideFoldIcons, provideFoldPalette, provideFoldPanelLabels, provideFoldToasts };
3839
- export type { FoldAutoPaletteName, FoldAvatarListItem, FoldAvatarRing, FoldAvatarRingStyle, FoldAvatarVariant, FoldBadgeVariant, FoldBlurToken, FoldBuiltinIconName, FoldButtonEmphasis, FoldButtonIconShape, FoldButtonIconSize, FoldButtonIconTone, FoldButtonIntent, FoldButtonShape, FoldButtonSize, FoldCalloutAppearance, FoldCalloutVariant, FoldChoiceOption, FoldComponentPanelDescriptor, FoldIconName, FoldIconSet, FoldIconSize, FoldMenuItemBadgeTone, FoldMenuLevel, FoldMenuTint, FoldMenuTogglePlacement, FoldMotionToken, FoldNumberControls, FoldNumberSpinner, FoldPageItem, FoldPaletteInput, FoldPanelConfig, FoldPanelContent, FoldPanelDescriptor, FoldPanelHandle, FoldPanelLabels, FoldPanelSide, FoldRadiusToken, FoldRangeValue, FoldSemanticColorToken, FoldShadowToken, FoldSpaceToken, FoldSpinnerSize, FoldStickyColumnAnchor, FoldSurfaceName, FoldTabNavItem, FoldTableColumn, FoldTableEmpty, FoldTableSort, FoldTableSortDir, FoldTableTone, FoldTemplatePanelDescriptor, FoldTextToken, FoldTimelineDatePlacement, FoldTimelineNode, FoldToast, FoldToastConfig, FoldToastVariant };
4067
+ export { FOLD_AUTO_PALETTES, FOLD_BLUR_TOKENS, FOLD_BUILTIN_ICONS, FOLD_MOTION_TOKENS, FOLD_PALETTE_DEFAULT, FOLD_PANEL_CLOSE_LABEL, FOLD_RADIUS_TOKENS, FOLD_SEMANTIC_COLOR_TOKENS, FOLD_SHADOW_TOKENS, FOLD_SPACE_TOKENS, FOLD_TEXT_TOKENS, FOLD_TOAST_CONFIG, FoldAppShellComponent, FoldAsideLayoutComponent, FoldAvatarComponent, FoldAvatarDetailComponent, FoldAvatarListComponent, FoldBadgeComponent, FoldButtonComponent, FoldButtonIconComponent, FoldCalloutComponent, FoldCardComponent, FoldChoiceRowComponent, FoldContextCardComponent, FoldDataTableCellDirective, FoldDataTableComponent, FoldDisclosureComponent, FoldElementTitleComponent, FoldElevatedDirective, FoldEmptyStateComponent, FoldFieldComponent, FoldFieldIdDirective, FoldFieldListComponent, FoldFileDropzoneComponent, FoldHeroCardComponent, FoldHeroSectionComponent, FoldIconComponent, FoldIconRegistry, FoldIdService, FoldInputComponent, FoldLinkComponent, FoldLoadingStateComponent, FoldMenuComponent, FoldMenuItemComponent, FoldMenuSectionComponent, FoldMenuSeparatorComponent, FoldNavLauncherComponent, FoldNavLayoutComponent, FoldNavTileComponent, FoldNumberInputComponent, FoldPageLayoutComponent, FoldPageSectionComponent, FoldPageTitleDirective, FoldPaginatorComponent, FoldPaletteRegistry, FoldPanelComponentOutletDirective, FoldPanelHeaderComponent, FoldPanelHostComponent, FoldPanelHostService, FoldPanelRef, FoldPanelToggle, FoldRangeSliderComponent, FoldRepeatPressDirective, FoldSearchComponent, FoldSelectComponent, FoldSliderComponent, FoldSpinnerComponent, FoldStatusBadgeComponent, FoldStickyColumnDirective, FoldSurfaceDirective, FoldTabPanelComponent, FoldTabsComponent, FoldTimelineComponent, FoldToastComponent, FoldToastContainerComponent, FoldToastService, FoldToggleIconComponent, FoldViewNavComponent, foldBlurVar, foldColorProperty, foldColorVar, foldHashSeed, foldMotionVar, foldRadiusVar, foldResolvePalette, foldShadowVar, foldSpaceVar, foldTextVar, observeElementWidth, provideFoldIcons, provideFoldPalette, provideFoldPanelLabels, provideFoldToasts };
4068
+ export type { FoldAutoPaletteName, FoldAvatarListItem, FoldAvatarRing, FoldAvatarRingStyle, FoldAvatarVariant, FoldBadgeVariant, FoldBlurToken, FoldBuiltinIconName, FoldButtonEmphasis, FoldButtonIconShape, FoldButtonIconSize, FoldButtonIconTone, FoldButtonIntent, FoldButtonShape, FoldButtonSize, FoldCalloutAppearance, FoldCalloutVariant, FoldChoiceOption, FoldComponentPanelDescriptor, FoldIconName, FoldIconSet, FoldIconSize, FoldMenuItemBadgeTone, FoldMenuLevel, FoldMenuTint, FoldMenuTogglePlacement, FoldMotionToken, FoldNumberControls, FoldNumberSpinner, FoldPageItem, FoldPaletteInput, FoldPanelConfig, FoldPanelContent, FoldPanelDescriptor, FoldPanelHandle, FoldPanelLabels, FoldPanelSide, FoldRadiusToken, FoldRangeValue, FoldSemanticColorToken, FoldShadowToken, FoldSpaceToken, FoldSpinnerSize, FoldStickyColumnAnchor, FoldSurfaceName, FoldTabItem, FoldTableColumn, FoldTableEmpty, FoldTableSort, FoldTableSortDir, FoldTableTone, FoldTabsContext, FoldTemplatePanelDescriptor, FoldTextToken, FoldTimelineDatePlacement, FoldTimelineNode, FoldToast, FoldToastConfig, FoldToastVariant, FoldViewNavItem };
3840
4069
  //# sourceMappingURL=fold-ng.d.ts.map