fold-ng 0.2.1 → 0.4.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 +125 -1
- package/README.md +127 -49
- package/fesm2022/fold-ng.mjs +561 -124
- package/fesm2022/fold-ng.mjs.map +1 -1
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/tokens/primitives.css +19 -0
- package/tokens/scales.css +19 -0
- package/tokens/semantic.css +238 -0
- package/types/fold-ng.d.ts +401 -91
- package/types/fold-ng.d.ts.map +1 -1
package/llms.txt
CHANGED
|
@@ -19,15 +19,15 @@ with a `@selector` and an `@example`.
|
|
|
19
19
|
|
|
20
20
|
- [Install & quickstart](https://github.com/hugoheynard/fold-ng#readme): `npm install fold-ng`, import tokens, use standalone components.
|
|
21
21
|
- [Design tokens](https://github.com/hugoheynard/fold-ng#the-two-tier-model): two-tier model — primitives (`--fold-ref-*`) → semantic (`--fold-color-*`); components consume the semantic layer only.
|
|
22
|
-
- [Theming](https://github.com/hugoheynard/fold-ng#consuming-the-tokens): `data-theme="umbra|lumen|bubbly|navi"`; re-theme by re-pointing the semantic layer, never touching a component.
|
|
22
|
+
- [Theming](https://github.com/hugoheynard/fold-ng#consuming-the-tokens): `data-theme="umbra|lumen|bubbly|navi|titan"`; re-theme by re-pointing the semantic layer, never touching a component.
|
|
23
23
|
|
|
24
24
|
## Components
|
|
25
25
|
|
|
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-
|
|
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.
|
|
3
|
+
"version": "0.4.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/primitives.css
CHANGED
|
@@ -108,6 +108,25 @@
|
|
|
108
108
|
--fold-ref-grape-600: #9333ea; /* hover / strong */
|
|
109
109
|
--fold-ref-grape-700: #7e22ce; /* readable brand text */
|
|
110
110
|
|
|
111
|
+
/* ── Steel / Titanium — the TITAN theme families ──────────────
|
|
112
|
+
Brushed titanium, light: a cool near-neutral steel ramp for the
|
|
113
|
+
brushed silver page, the header + rails at its own tint, and the
|
|
114
|
+
bright polished cards that float on it — plus a HEAT-anodized
|
|
115
|
+
titanium brand, the copper-orange the metal takes when torched. */
|
|
116
|
+
--fold-ref-steel-900: #1b1f24; /* graphite body text */
|
|
117
|
+
--fold-ref-steel-600: #566069; /* secondary text */
|
|
118
|
+
--fold-ref-steel-500: #7c8894; /* muted text */
|
|
119
|
+
--fold-ref-steel-400: #9aa6b1; /* faded text */
|
|
120
|
+
--fold-ref-steel-300: #c0c8d0; /* solid brushed-steel border */
|
|
121
|
+
--fold-ref-steel-200: #d4dae1; /* brushed page ground */
|
|
122
|
+
--fold-ref-steel-150: #e2e7ec; /* header · rail 2 · hover · divider */
|
|
123
|
+
--fold-ref-steel-100: #eef1f5; /* raised rail plate · sunken */
|
|
124
|
+
--fold-ref-steel-50: #f8fafc; /* bright polished card */
|
|
125
|
+
|
|
126
|
+
--fold-ref-titanium-700: #863810; /* brand text (burnt copper) */
|
|
127
|
+
--fold-ref-titanium-600: #a5451a; /* hover / strong */
|
|
128
|
+
--fold-ref-titanium-500: #c2521b; /* brand base (copper-orange · AA w/ white) */
|
|
129
|
+
|
|
111
130
|
/* ── Pure black — pairs with white for neutral alpha overlays */
|
|
112
131
|
--fold-ref-black: #000000;
|
|
113
132
|
}
|
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;
|
|
@@ -104,3 +112,14 @@
|
|
|
104
112
|
--fold-radius-md: 16px;
|
|
105
113
|
--fold-radius-lg: 24px;
|
|
106
114
|
}
|
|
115
|
+
|
|
116
|
+
/* ── Theme shape override: TITAN ──────────────────────────────
|
|
117
|
+
Softened, iPhone-premium: corners rounded a step past the base so a
|
|
118
|
+
polished-steel card reads like a device, not a slab — but short of
|
|
119
|
+
bubbly's pill. `pill` and `round` stay: shapes, not scale steps. */
|
|
120
|
+
[data-theme="titan"] {
|
|
121
|
+
--fold-radius-xs: 5px;
|
|
122
|
+
--fold-radius-sm: 10px;
|
|
123
|
+
--fold-radius-md: 14px;
|
|
124
|
+
--fold-radius-lg: 20px;
|
|
125
|
+
}
|
package/tokens/semantic.css
CHANGED
|
@@ -186,6 +186,99 @@
|
|
|
186
186
|
color: var(--fold-color-text);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/* ── Accent surface — an auto-inverting region ────────────────────────────────
|
|
190
|
+
`[data-surface="accent"]` (stamped by fold-card's `surface="accent"`, or the
|
|
191
|
+
`foldSurface` directive) fills with the brand accent and re-points its whole
|
|
192
|
+
content sub-tree to an on-accent palette — text, borders, band gradation and
|
|
193
|
+
even nested buttons / links / icon-tiles read on the accent, with no
|
|
194
|
+
per-component code.
|
|
195
|
+
|
|
196
|
+
The move that makes this both theme-agnostic AND able to *swap* the brand pair
|
|
197
|
+
(`primary` ↔ `on-primary`, needed for a solid button or a filled icon tile)
|
|
198
|
+
without a CSS custom-property cycle: the accent + its ink are CAPTURED on the
|
|
199
|
+
surface element (where the tokens still hold their normal values), then the
|
|
200
|
+
inverted role-set is applied to DESCENDANTS from those captures — so a role can
|
|
201
|
+
reference the pre-inversion value it is replacing. Every value is a `color-mix`
|
|
202
|
+
of the captured pair, so it holds on every theme, and the surface and band
|
|
203
|
+
steps stay a lighter shade of the accent (gradation kept in-hue).
|
|
204
|
+
|
|
205
|
+
A theme that needs to diverge overrides any role by nesting a rule for its own
|
|
206
|
+
`[data-theme=…]` under `[data-surface="accent"]` — the same seam as chrome. */
|
|
207
|
+
[data-surface="accent"] {
|
|
208
|
+
color: var(--fold-color-on-primary);
|
|
209
|
+
--_accent-ink: var(--fold-color-on-primary);
|
|
210
|
+
--_accent-fill: var(--fold-color-primary);
|
|
211
|
+
}
|
|
212
|
+
[data-surface="accent"] * {
|
|
213
|
+
/* text ramp → the light ink. COMPRESSED vs a normal surface: an accent ground
|
|
214
|
+
has little contrast headroom (a mid-bright accent caps white text near 3:1),
|
|
215
|
+
so the accent card is an emphasis surface — its text clears AA-large (3:1),
|
|
216
|
+
asserted by accent-contrast.spec.ts, and secondary/muted keep more ink than
|
|
217
|
+
they would on the page. A light accent that still reads thin overrides the
|
|
218
|
+
ramp per theme (surfaces.md). */
|
|
219
|
+
--fold-color-text: var(--_accent-ink);
|
|
220
|
+
--fold-color-text-secondary: color-mix(
|
|
221
|
+
in srgb,
|
|
222
|
+
var(--_accent-ink) 96%,
|
|
223
|
+
transparent
|
|
224
|
+
);
|
|
225
|
+
--fold-color-text-muted: color-mix(
|
|
226
|
+
in srgb,
|
|
227
|
+
var(--_accent-ink) 74%,
|
|
228
|
+
transparent
|
|
229
|
+
);
|
|
230
|
+
--fold-color-text-faded: color-mix(
|
|
231
|
+
in srgb,
|
|
232
|
+
var(--_accent-ink) 58%,
|
|
233
|
+
transparent
|
|
234
|
+
);
|
|
235
|
+
/* borders + separators → thin ink lines */
|
|
236
|
+
--fold-color-border: color-mix(in srgb, var(--_accent-ink) 24%, transparent);
|
|
237
|
+
--fold-color-border-subtle: color-mix(
|
|
238
|
+
in srgb,
|
|
239
|
+
var(--_accent-ink) 15%,
|
|
240
|
+
transparent
|
|
241
|
+
);
|
|
242
|
+
/* nested surfaces + raised tiles/bands → a lighter step of the ACCENT itself */
|
|
243
|
+
--fold-color-surface-card: color-mix(
|
|
244
|
+
in srgb,
|
|
245
|
+
var(--_accent-ink) 12%,
|
|
246
|
+
var(--_accent-fill)
|
|
247
|
+
);
|
|
248
|
+
--fold-color-surface-raised: color-mix(
|
|
249
|
+
in srgb,
|
|
250
|
+
var(--_accent-ink) 16%,
|
|
251
|
+
var(--_accent-fill)
|
|
252
|
+
);
|
|
253
|
+
--fold-color-surface-hover: color-mix(
|
|
254
|
+
in srgb,
|
|
255
|
+
var(--_accent-ink) 18%,
|
|
256
|
+
var(--_accent-fill)
|
|
257
|
+
);
|
|
258
|
+
--fold-color-surface-sunken: color-mix(
|
|
259
|
+
in srgb,
|
|
260
|
+
var(--_accent-ink) 8%,
|
|
261
|
+
var(--_accent-fill)
|
|
262
|
+
);
|
|
263
|
+
/* the brand pair, SWAPPED from the captures (no cycle): the fill becomes the
|
|
264
|
+
light ink (link text, glass button, chip ground) and its on-colour becomes
|
|
265
|
+
the accent — so a filled icon tile or solid button reads accent-on-light. */
|
|
266
|
+
--fold-color-primary: var(--_accent-ink);
|
|
267
|
+
--fold-color-on-primary: var(--_accent-fill);
|
|
268
|
+
--fold-color-primary-text: var(--_accent-ink);
|
|
269
|
+
--fold-color-primary-strong: var(--_accent-ink);
|
|
270
|
+
--fold-color-primary-surface: color-mix(
|
|
271
|
+
in srgb,
|
|
272
|
+
var(--_accent-ink) 16%,
|
|
273
|
+
transparent
|
|
274
|
+
);
|
|
275
|
+
--fold-color-primary-border: color-mix(
|
|
276
|
+
in srgb,
|
|
277
|
+
var(--_accent-ink) 32%,
|
|
278
|
+
transparent
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
189
282
|
/* ── Elevated surfaces ────────────────────────────────────────
|
|
190
283
|
A `[data-elevated]` (stamped by the `[foldElevated]` directive) is a raised
|
|
191
284
|
card: radius + shadow, riding on the element's own background so its colour
|
|
@@ -702,3 +795,148 @@
|
|
|
702
795
|
transparent
|
|
703
796
|
);
|
|
704
797
|
}
|
|
798
|
+
|
|
799
|
+
/* ── Extra theme: TITAN ───────────────────────────────────────
|
|
800
|
+
Brushed titanium, light + warm. A cool brushed-steel ground — the
|
|
801
|
+
header + rails sit at the page's own tint, so the top reads frameless
|
|
802
|
+
— with bright polished cards that float off it on the shared elevation
|
|
803
|
+
shadow (that lift is the "raised metal piece", no per-theme shadow
|
|
804
|
+
needed). The brand is HEAT-anodized titanium: the copper-orange the
|
|
805
|
+
metal takes when torched, warming the whole steel read. Content borders
|
|
806
|
+
re-point to a SOLID steel primitive (a palpable machined seam, where
|
|
807
|
+
the light themes use an alpha hairline); corners soften in scales.css.
|
|
808
|
+
Status families hold at the lumen (light) tints — only ground + brand
|
|
809
|
+
move. Uniform-polarity, so no chrome override is needed. */
|
|
810
|
+
[data-theme="titan"] {
|
|
811
|
+
/* Surfaces — header + rails at the page's own tint (a frameless top) */
|
|
812
|
+
--fold-color-bg-page: var(--fold-ref-steel-200);
|
|
813
|
+
--fold-color-bg-header: var(--fold-ref-steel-150);
|
|
814
|
+
--fold-color-bg-rail-primary: var(--fold-ref-steel-100);
|
|
815
|
+
--fold-color-bg-rail-secondary: var(--fold-ref-steel-150);
|
|
816
|
+
--fold-color-bg-rail-tertiary: color-mix(
|
|
817
|
+
in srgb,
|
|
818
|
+
var(--fold-ref-black) 3%,
|
|
819
|
+
transparent
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
/* Primary / accent — heat-anodized copper-orange, deep enough for white */
|
|
823
|
+
--fold-color-primary: var(--fold-ref-titanium-500);
|
|
824
|
+
--fold-color-primary-strong: var(--fold-ref-titanium-600);
|
|
825
|
+
--fold-color-on-primary: var(--fold-ref-white);
|
|
826
|
+
--fold-color-primary-text: var(--fold-ref-titanium-700);
|
|
827
|
+
--fold-color-primary-surface: color-mix(
|
|
828
|
+
in srgb,
|
|
829
|
+
var(--fold-ref-titanium-500) 10%,
|
|
830
|
+
transparent
|
|
831
|
+
);
|
|
832
|
+
--fold-color-primary-border: color-mix(
|
|
833
|
+
in srgb,
|
|
834
|
+
var(--fold-ref-titanium-500) 28%,
|
|
835
|
+
transparent
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
/* Info (purple) — lumen tint */
|
|
839
|
+
--fold-color-info: var(--fold-ref-purple-600);
|
|
840
|
+
--fold-color-info-text: var(--fold-ref-purple-500);
|
|
841
|
+
--fold-color-info-surface: color-mix(
|
|
842
|
+
in srgb,
|
|
843
|
+
var(--fold-ref-purple-600) 8%,
|
|
844
|
+
transparent
|
|
845
|
+
);
|
|
846
|
+
--fold-color-info-border: color-mix(
|
|
847
|
+
in srgb,
|
|
848
|
+
var(--fold-ref-purple-600) 22%,
|
|
849
|
+
transparent
|
|
850
|
+
);
|
|
851
|
+
|
|
852
|
+
/* Warning (amber) */
|
|
853
|
+
--fold-color-warning: var(--fold-ref-amber-600);
|
|
854
|
+
--fold-color-warning-text: var(--fold-ref-amber-550);
|
|
855
|
+
--fold-color-warning-surface: color-mix(
|
|
856
|
+
in srgb,
|
|
857
|
+
var(--fold-ref-amber-600) 8%,
|
|
858
|
+
transparent
|
|
859
|
+
);
|
|
860
|
+
--fold-color-warning-border: color-mix(
|
|
861
|
+
in srgb,
|
|
862
|
+
var(--fold-ref-amber-600) 22%,
|
|
863
|
+
transparent
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
/* Alert (red) */
|
|
867
|
+
--fold-color-alert: var(--fold-ref-red-600);
|
|
868
|
+
--fold-color-alert-text: var(--fold-ref-red-450);
|
|
869
|
+
--fold-color-alert-surface: color-mix(
|
|
870
|
+
in srgb,
|
|
871
|
+
var(--fold-ref-red-600) 8%,
|
|
872
|
+
transparent
|
|
873
|
+
);
|
|
874
|
+
--fold-color-alert-border: color-mix(
|
|
875
|
+
in srgb,
|
|
876
|
+
var(--fold-ref-red-600) 22%,
|
|
877
|
+
transparent
|
|
878
|
+
);
|
|
879
|
+
|
|
880
|
+
/* Success (green) */
|
|
881
|
+
--fold-color-success: var(--fold-ref-green-500);
|
|
882
|
+
--fold-color-success-text: var(--fold-ref-green-550);
|
|
883
|
+
--fold-color-success-surface: color-mix(
|
|
884
|
+
in srgb,
|
|
885
|
+
var(--fold-ref-green-500) 10%,
|
|
886
|
+
transparent
|
|
887
|
+
);
|
|
888
|
+
--fold-color-success-border: color-mix(
|
|
889
|
+
in srgb,
|
|
890
|
+
var(--fold-ref-green-500) 25%,
|
|
891
|
+
transparent
|
|
892
|
+
);
|
|
893
|
+
|
|
894
|
+
/* Text — graphite on the light page (high contrast) */
|
|
895
|
+
--fold-color-text: var(--fold-ref-steel-900);
|
|
896
|
+
--fold-color-text-secondary: var(--fold-ref-steel-600);
|
|
897
|
+
--fold-color-text-muted: var(--fold-ref-steel-500);
|
|
898
|
+
--fold-color-text-faded: var(--fold-ref-steel-400);
|
|
899
|
+
|
|
900
|
+
/* Card — a bright polished-steel plate that floats off the silver ground */
|
|
901
|
+
--fold-color-surface-card: var(--fold-ref-steel-50);
|
|
902
|
+
--fold-color-surface-sunken: var(--fold-ref-steel-100);
|
|
903
|
+
|
|
904
|
+
/* Neutral surfaces — faint black overlays for hover/raise cues on light */
|
|
905
|
+
--fold-color-surface-subtle: color-mix(
|
|
906
|
+
in srgb,
|
|
907
|
+
var(--fold-ref-black) 3%,
|
|
908
|
+
transparent
|
|
909
|
+
);
|
|
910
|
+
--fold-color-surface-raised: color-mix(
|
|
911
|
+
in srgb,
|
|
912
|
+
var(--fold-ref-black) 5%,
|
|
913
|
+
transparent
|
|
914
|
+
);
|
|
915
|
+
--fold-color-surface-hover: var(
|
|
916
|
+
--fold-ref-steel-150
|
|
917
|
+
); /* solid raised hover */
|
|
918
|
+
|
|
919
|
+
/* Borders — SOLID brushed-steel seams (the palpable metal edge), where the
|
|
920
|
+
light themes use an alpha hairline. */
|
|
921
|
+
--fold-color-border: var(--fold-ref-steel-300);
|
|
922
|
+
--fold-color-border-subtle: var(--fold-ref-steel-150);
|
|
923
|
+
|
|
924
|
+
/* Glass — frosted brushed steel */
|
|
925
|
+
--fold-color-glass: color-mix(
|
|
926
|
+
in srgb,
|
|
927
|
+
var(--fold-ref-steel-50) 66%,
|
|
928
|
+
transparent
|
|
929
|
+
);
|
|
930
|
+
--fold-color-glass-border: color-mix(
|
|
931
|
+
in srgb,
|
|
932
|
+
var(--fold-ref-black) 12%,
|
|
933
|
+
transparent
|
|
934
|
+
);
|
|
935
|
+
|
|
936
|
+
/* Scrim — a darkening veil behind the mobile nav drawer. */
|
|
937
|
+
--fold-color-scrim: color-mix(
|
|
938
|
+
in srgb,
|
|
939
|
+
var(--fold-ref-black) 45%,
|
|
940
|
+
transparent
|
|
941
|
+
);
|
|
942
|
+
}
|