fold-ng 0.18.0 → 0.19.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/CHANGELOG.md CHANGED
@@ -8,6 +8,30 @@ All notable changes to **fold-ng** are documented here. The format follows
8
8
 
9
9
  _Nothing yet._
10
10
 
11
+ ## [0.19.0] - 2026-08-28
12
+
13
+ ### Added
14
+
15
+ - **`fold-element-title` : la variante `caps`** — les capitales à la taille et à
16
+ l'encre du titre, pour une RÉGION qui s'annonce : un puits, un rail, une
17
+ bande.
18
+
19
+ `eyebrow` chuchote au-dessus d'une chose, `caps` NOMME la chose — d'où
20
+ l'encre pleine et non la teinte atténuée. Elle comblait un trou réel : entre
21
+ un sur-titre de 10 px et un titre en bas de casse, il n'existait aucun
22
+ registre pour la tête d'une section qui doit se lire d'un bout de l'écran à
23
+ l'autre.
24
+
25
+ ⚠️ Son interlettrage reste **positif** (`--fold-tracking-caps`). Des capitales
26
+ ont besoin d'air entre les fûts : le resserrement qui flatte une grande ligne
27
+ d'affichage les soude à cette taille-là. C'est un défaut qui ne se voit que
28
+ sur fond clair — sur un fond sombre, la halation du texte le rattrape — et
29
+ qui fait donc rendre deux titres différemment pour des règles identiques.
30
+
31
+ Le glyphe de tête y reste **plein**, sans la tuile de 40 px du variant
32
+ `title` : une tuile à côté d'une ligne de capitales de 14 px pèserait plus
33
+ lourd que les mots qu'elle introduit.
34
+
11
35
  ## [0.18.0] - 2026-08-28
12
36
 
13
37
  ### Added
@@ -2246,7 +2270,8 @@ design-token stylesheet.
2246
2270
  `currentColor`; `prefers-reduced-motion` + `forced-colors` are respected;
2247
2271
  strings localise via inputs / providers (`provideFoldPanelLabels`).
2248
2272
 
2249
- [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.18.0...HEAD
2273
+ [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.19.0...HEAD
2274
+ [0.19.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.19.0
2250
2275
  [0.18.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.18.0
2251
2276
  [0.17.1]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.17.1
2252
2277
  [0.17.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.17.0
@@ -3682,6 +3682,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
3682
3682
  * - `title` — normal-case, `text-md`, primary. A card/panel heading; a leading
3683
3683
  * `icon` renders in a tile whose tone is set by `iconTone`
3684
3684
  * (`neutral` raised · `primary` filled brand · `faded` dim).
3685
+ * - `caps` — uppercase at the title's size and in primary ink. The register for
3686
+ * a REGION that announces itself: a well, a rail, a band. `eyebrow` whispers
3687
+ * above a thing, `caps` names the thing — which is why it takes the full text
3688
+ * colour and not the muted one.
3685
3689
  *
3686
3690
  * A trailing action (edit/add button, lock badge) projects into `[titleAction]`,
3687
3691
  * right-aligned. The title — not the action — is the heading for assistive tech.
@@ -3692,6 +3696,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
3692
3696
  * ```html
3693
3697
  * <fold-element-title title="Documents" variant="bar" />
3694
3698
  * <fold-element-title variant="title" icon="company" title="Contexte" subtitle="Activité de l'espace" />
3699
+ * <fold-element-title variant="caps" title="Mes suivis" subtitle="3 en cours" />
3695
3700
  * <fold-element-title title="Poste">
3696
3701
  * <button titleAction (click)="edit()">✎</button>
3697
3702
  * </fold-element-title>
@@ -3710,7 +3715,8 @@ class FoldElementTitleComponent {
3710
3715
  /** Optional secondary line under the title. */
3711
3716
  subtitle = input(/* @ts-ignore */
3712
3717
  ...(ngDevMode ? [undefined, { debugName: "subtitle" }] : /* istanbul ignore next */ []));
3713
- /** Emphasis — `eyebrow` (10px muted), `bar` (11px secondary), `title` (text-md, normal-case). */
3718
+ /** Emphasis — `eyebrow` (10px muted), `bar` (11px secondary), `title` (text-md,
3719
+ * normal-case), `caps` (title-size uppercase, primary ink). */
3714
3720
  variant = input("eyebrow", /* @ts-ignore */
3715
3721
  ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
3716
3722
  /** Heading outline depth exposed to assistive tech (`aria-level`). */
@@ -3723,19 +3729,20 @@ class FoldElementTitleComponent {
3723
3729
  iconSize = computed(() => this.variant() === "title" ? "md" : "sm", /* @ts-ignore */
3724
3730
  ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
3725
3731
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldElementTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3726
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldElementTitleComponent, isStandalone: true, selector: "fold-element-title", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconTone: { classPropertyName: "iconTone", publicName: "iconTone", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, headingId: { classPropertyName: "headingId", publicName: "headingId", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.v-bar": "variant() === 'bar'", "class.v-title": "variant() === 'title'", "class.it-primary": "iconTone() === 'primary'", "class.it-faded": "iconTone() === 'faded'", "attr.title": "null" } }, ngImport: i0, template: "@if (icon(); as ic) {\n <span class=\"et-icon\"><fold-icon [name]=\"ic\" [size]=\"iconSize()\" /></span>\n}\n<span class=\"et-main\">\n <span class=\"et-row\">\n <span\n class=\"et-label\"\n role=\"heading\"\n [attr.id]=\"headingId()\"\n [attr.aria-level]=\"level()\"\n >{{ title() }}</span\n >\n <span class=\"et-action\"><ng-content select=\"[titleAction]\" /></span>\n </span>\n @if (subtitle(); as s) {\n <span class=\"et-sub\">{{ s }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--fold-space-md);margin:0}.et-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.et-row{display:flex;align-items:center;justify-content:space-between;gap:var(--fold-space-sm)}.et-label{min-width:0;font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase;color:var(--fold-color-text-muted)}:host(.v-bar) .et-label{font-size:var(--fold-text-xs);color:var(--fold-color-text-secondary)}:host(.v-title) .et-label{font-size:var(--fold-text-base);letter-spacing:var(--fold-tracking-normal);text-transform:none;color:var(--fold-color-text)}.et-sub{font-size:var(--fold-text-xs);color:var(--fold-color-text-muted)}.et-action{flex:none;display:inline-flex;align-items:center;gap:var(--fold-space-sm)}.et-action:empty{display:none}.et-icon{flex:none;display:grid;place-items:center;color:var(--fold-color-primary)}:host(.v-title) .et-icon{width:40px;height:40px;border-radius:var(--fold-radius-md);border:1px solid var(--fold-color-border);background:var(--fold-color-surface-raised)}:host(.v-title.it-primary) .et-icon{background:var(--fold-color-primary);border-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}:host(.v-title.it-faded) .et-icon{background:var(--fold-color-surface-sunken);border-color:var(--fold-color-border-subtle);color:var(--fold-color-text-muted)}\n"], dependencies: [{ kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
3732
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldElementTitleComponent, isStandalone: true, selector: "fold-element-title", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconTone: { classPropertyName: "iconTone", publicName: "iconTone", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, headingId: { classPropertyName: "headingId", publicName: "headingId", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.v-bar": "variant() === 'bar'", "class.v-title": "variant() === 'title'", "class.v-caps": "variant() === 'caps'", "class.it-primary": "iconTone() === 'primary'", "class.it-faded": "iconTone() === 'faded'", "attr.title": "null" } }, ngImport: i0, template: "@if (icon(); as ic) {\n <span class=\"et-icon\"><fold-icon [name]=\"ic\" [size]=\"iconSize()\" /></span>\n}\n<span class=\"et-main\">\n <span class=\"et-row\">\n <span\n class=\"et-label\"\n role=\"heading\"\n [attr.id]=\"headingId()\"\n [attr.aria-level]=\"level()\"\n >{{ title() }}</span\n >\n <span class=\"et-action\"><ng-content select=\"[titleAction]\" /></span>\n </span>\n @if (subtitle(); as s) {\n <span class=\"et-sub\">{{ s }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--fold-space-md);margin:0}.et-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.et-row{display:flex;align-items:center;justify-content:space-between;gap:var(--fold-space-sm)}.et-label{min-width:0;font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase;color:var(--fold-color-text-muted)}:host(.v-bar) .et-label{font-size:var(--fold-text-xs);color:var(--fold-color-text-secondary)}:host(.v-caps) .et-label{font-size:var(--fold-text-base);font-weight:var(--fold-weight-extrabold);letter-spacing:var(--fold-tracking-caps);color:var(--fold-color-text)}:host(.v-title) .et-label{font-size:var(--fold-text-base);letter-spacing:var(--fold-tracking-normal);text-transform:none;color:var(--fold-color-text)}.et-sub{font-size:var(--fold-text-xs);color:var(--fold-color-text-muted)}.et-action{flex:none;display:inline-flex;align-items:center;gap:var(--fold-space-sm)}.et-action:empty{display:none}.et-icon{flex:none;display:grid;place-items:center;color:var(--fold-color-primary)}:host(.v-title) .et-icon{width:40px;height:40px;border-radius:var(--fold-radius-md);border:1px solid var(--fold-color-border);background:var(--fold-color-surface-raised)}:host(.v-title.it-primary) .et-icon{background:var(--fold-color-primary);border-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}:host(.v-title.it-faded) .et-icon{background:var(--fold-color-surface-sunken);border-color:var(--fold-color-border-subtle);color:var(--fold-color-text-muted)}\n"], dependencies: [{ kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
3727
3733
  }
3728
3734
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldElementTitleComponent, decorators: [{
3729
3735
  type: Component,
3730
3736
  args: [{ selector: "fold-element-title", standalone: true, imports: [FoldIconComponent], host: {
3731
3737
  "[class.v-bar]": "variant() === 'bar'",
3732
3738
  "[class.v-title]": "variant() === 'title'",
3739
+ "[class.v-caps]": "variant() === 'caps'",
3733
3740
  "[class.it-primary]": "iconTone() === 'primary'",
3734
3741
  "[class.it-faded]": "iconTone() === 'faded'",
3735
3742
  // `title` is a heading input — strip the reflected native attribute so it
3736
3743
  // never doubles as a browser tooltip.
3737
3744
  "[attr.title]": "null",
3738
- }, template: "@if (icon(); as ic) {\n <span class=\"et-icon\"><fold-icon [name]=\"ic\" [size]=\"iconSize()\" /></span>\n}\n<span class=\"et-main\">\n <span class=\"et-row\">\n <span\n class=\"et-label\"\n role=\"heading\"\n [attr.id]=\"headingId()\"\n [attr.aria-level]=\"level()\"\n >{{ title() }}</span\n >\n <span class=\"et-action\"><ng-content select=\"[titleAction]\" /></span>\n </span>\n @if (subtitle(); as s) {\n <span class=\"et-sub\">{{ s }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--fold-space-md);margin:0}.et-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.et-row{display:flex;align-items:center;justify-content:space-between;gap:var(--fold-space-sm)}.et-label{min-width:0;font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase;color:var(--fold-color-text-muted)}:host(.v-bar) .et-label{font-size:var(--fold-text-xs);color:var(--fold-color-text-secondary)}:host(.v-title) .et-label{font-size:var(--fold-text-base);letter-spacing:var(--fold-tracking-normal);text-transform:none;color:var(--fold-color-text)}.et-sub{font-size:var(--fold-text-xs);color:var(--fold-color-text-muted)}.et-action{flex:none;display:inline-flex;align-items:center;gap:var(--fold-space-sm)}.et-action:empty{display:none}.et-icon{flex:none;display:grid;place-items:center;color:var(--fold-color-primary)}:host(.v-title) .et-icon{width:40px;height:40px;border-radius:var(--fold-radius-md);border:1px solid var(--fold-color-border);background:var(--fold-color-surface-raised)}:host(.v-title.it-primary) .et-icon{background:var(--fold-color-primary);border-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}:host(.v-title.it-faded) .et-icon{background:var(--fold-color-surface-sunken);border-color:var(--fold-color-border-subtle);color:var(--fold-color-text-muted)}\n"] }]
3745
+ }, template: "@if (icon(); as ic) {\n <span class=\"et-icon\"><fold-icon [name]=\"ic\" [size]=\"iconSize()\" /></span>\n}\n<span class=\"et-main\">\n <span class=\"et-row\">\n <span\n class=\"et-label\"\n role=\"heading\"\n [attr.id]=\"headingId()\"\n [attr.aria-level]=\"level()\"\n >{{ title() }}</span\n >\n <span class=\"et-action\"><ng-content select=\"[titleAction]\" /></span>\n </span>\n @if (subtitle(); as s) {\n <span class=\"et-sub\">{{ s }}</span>\n }\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--fold-space-md);margin:0}.et-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.et-row{display:flex;align-items:center;justify-content:space-between;gap:var(--fold-space-sm)}.et-label{min-width:0;font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase;color:var(--fold-color-text-muted)}:host(.v-bar) .et-label{font-size:var(--fold-text-xs);color:var(--fold-color-text-secondary)}:host(.v-caps) .et-label{font-size:var(--fold-text-base);font-weight:var(--fold-weight-extrabold);letter-spacing:var(--fold-tracking-caps);color:var(--fold-color-text)}:host(.v-title) .et-label{font-size:var(--fold-text-base);letter-spacing:var(--fold-tracking-normal);text-transform:none;color:var(--fold-color-text)}.et-sub{font-size:var(--fold-text-xs);color:var(--fold-color-text-muted)}.et-action{flex:none;display:inline-flex;align-items:center;gap:var(--fold-space-sm)}.et-action:empty{display:none}.et-icon{flex:none;display:grid;place-items:center;color:var(--fold-color-primary)}:host(.v-title) .et-icon{width:40px;height:40px;border-radius:var(--fold-radius-md);border:1px solid var(--fold-color-border);background:var(--fold-color-surface-raised)}:host(.v-title.it-primary) .et-icon{background:var(--fold-color-primary);border-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}:host(.v-title.it-faded) .et-icon{background:var(--fold-color-surface-sunken);border-color:var(--fold-color-border-subtle);color:var(--fold-color-text-muted)}\n"] }]
3739
3746
  }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconTone", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], headingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingId", required: false }] }] } });
3740
3747
 
3741
3748
  /**