fold-ng 0.0.0 → 0.2.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 ADDED
@@ -0,0 +1,45 @@
1
+ # fold-ng
2
+
3
+ > Accessible, dark-first Angular 22 UI component library and design system —
4
+ > signals-first, standalone, zoneless, SSR-ready. A two-tier design-token model
5
+ > plus WCAG-minded components, styled against CSS variables (no NgModule, no
6
+ > zone.js, no runtime CSS-in-JS).
7
+
8
+ Status: production-quality, pre-1.0 (0.x) — fully tested and dogfooded in a real
9
+ application; it stays 0.x only because the API is not frozen until 1.0.0 (not
10
+ because it is unstable). Pin the version; 0.x minor bumps may still refine the API.
11
+
12
+ fold-ng is consumed as standalone Angular components imported from the package
13
+ root (`import { FoldButtonComponent } from "fold-ng"`) plus a token stylesheet
14
+ (`@import "fold-ng/tokens.css"`). Dark ("umbra") is the default theme; light
15
+ ("lumen") and others are opt-in via `data-theme`. Every component ships JSDoc
16
+ with a `@selector` and an `@example`.
17
+
18
+ ## Getting started
19
+
20
+ - [Install & quickstart](https://github.com/hugoheynard/fold-ng#readme): `npm install fold-ng`, import tokens, use standalone components.
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.
23
+
24
+ ## Components
25
+
26
+ - Actions: `[foldButton]` (on a real `<button>`/`<a>`; `emphasis` × `intent` axes; `loading`), `fold-button-icon` (momentary), `fold-toggle-icon` (toggle), `fold-link`.
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
+ - 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`.
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
+ - Feedback: `fold-callout`, `fold-disclosure`, `fold-toast`, `fold-loading`, `fold-empty-state`.
33
+ - Foundations: `fold-icon` (114 built-in SVGs + registry), `fold-spinner`.
34
+
35
+ ## Conventions
36
+
37
+ - Angular 22, standalone, signals (`input()`/`output()`/`computed()`/`effect()`), zoneless, SSR-safe.
38
+ - Accessibility: overlays trap focus + `inert` the background + carry an accessible name; icons inherit `currentColor`; forced-colors + reduced-motion honoured.
39
+ - Localise strings via inputs / providers (e.g. `provideFoldPanelLabels({ close })`).
40
+
41
+ ## Full API
42
+
43
+ - [Component & selector table (README)](https://github.com/hugoheynard/fold-ng#components)
44
+ - [Release readiness, per component](https://github.com/hugoheynard/fold-ng/blob/main/docs/RELEASE-READINESS.md)
45
+ - [Roadmap](https://github.com/hugoheynard/fold-ng/blob/main/docs/TODO.md)
package/package.json CHANGED
@@ -1,20 +1,70 @@
1
1
  {
2
2
  "name": "fold-ng",
3
- "version": "0.0.0",
4
- "description": "A dark-first Angular design system — signals-first, standalone, zoneless, SSR-ready. Coming soon.",
5
- "author": "Hugo Heynard",
6
- "license": "MIT",
3
+ "version": "0.2.0",
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.",
7
5
  "keywords": [
8
6
  "angular",
9
- "design-system",
7
+ "angular-22",
8
+ "angular-components",
9
+ "ui-library",
10
+ "ui-components",
10
11
  "component-library",
12
+ "design-system",
13
+ "design-tokens",
14
+ "css-variables",
11
15
  "signals",
12
16
  "zoneless",
17
+ "standalone",
13
18
  "ssr",
14
- "dark-theme"
19
+ "dark-theme",
20
+ "theme",
21
+ "theming",
22
+ "accessible",
23
+ "a11y",
24
+ "wcag",
25
+ "overlay",
26
+ "dialog",
27
+ "angular-ui",
28
+ "signals-first"
29
+ ],
30
+ "author": "Hugo Heynard",
31
+ "license": "MIT",
32
+ "homepage": "https://hugoheynard.github.io/fold-ng/",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/hugoheynard/fold-ng.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/hugoheynard/fold-ng/issues"
39
+ },
40
+ "type": "module",
41
+ "private": false,
42
+ "packageManager": "pnpm@10.12.1",
43
+ "sideEffects": [
44
+ "**/*.css"
15
45
  ],
16
- "files": [
17
- "README.md",
18
- "LICENSE"
19
- ]
46
+ "exports": {
47
+ "./tokens.css": "./tokens/index.css",
48
+ "./tokens/primitives.css": "./tokens/primitives.css",
49
+ "./tokens/scales.css": "./tokens/scales.css",
50
+ "./tokens/semantic.css": "./tokens/semantic.css",
51
+ ".": {
52
+ "types": "./types/fold-ng.d.ts",
53
+ "default": "./fesm2022/fold-ng.mjs"
54
+ },
55
+ "./package.json": {
56
+ "default": "./package.json"
57
+ }
58
+ },
59
+ "peerDependencies": {
60
+ "@angular/common": "^22",
61
+ "@angular/core": "^22",
62
+ "@angular/forms": "^22",
63
+ "@angular/platform-browser": "^22"
64
+ },
65
+ "dependencies": {
66
+ "tslib": "^2.3.0"
67
+ },
68
+ "module": "fesm2022/fold-ng.mjs",
69
+ "typings": "types/fold-ng.d.ts"
20
70
  }
@@ -0,0 +1,14 @@
1
+ /* ============================================================
2
+ SH3PHERD · Design tokens — entry point
3
+ ------------------------------------------------------------
4
+ The single file an app imports to get the whole token set:
5
+
6
+ @import 'fold-ng/tokens.css';
7
+
8
+ Order matters: primitives first (they define the raw palette),
9
+ then the semantic layer that points at them.
10
+ ============================================================ */
11
+
12
+ @import "./primitives.css";
13
+ @import "./scales.css";
14
+ @import "./semantic.css";
@@ -0,0 +1,113 @@
1
+ /* ============================================================
2
+ SH3PHERD · Design tokens — TIER 1: PRIMITIVES
3
+ ------------------------------------------------------------
4
+ The raw palette. These are the ONLY place a literal colour
5
+ value is allowed to live. They are theme-INVARIANT: the same
6
+ ink/teal/cloud values in dark and light — it is the semantic
7
+ layer (semantic.css) that decides which primitive a role
8
+ points to per theme.
9
+
10
+ Never reference a --fold-ref-* token from a component.
11
+ Components consume the semantic layer only.
12
+ ============================================================ */
13
+
14
+ :root {
15
+ /* ── Ink — the dark chrome family (deep blue-black) ───────────
16
+ Ordered by depth: 950 is the darkest, 850 the lightest. */
17
+ --fold-ref-ink-950: #0a0e14; /* header bar */
18
+ --fold-ref-ink-925: #090d13; /* rail 1 · app menu */
19
+ --fold-ref-ink-900: #0c1018; /* rail 2 · workspace menu */
20
+ --fold-ref-ink-850: #11161e; /* page background */
21
+ --fold-ref-ink-800: #1f2733; /* raised card surface */
22
+ --fold-ref-ink-700: #28323f; /* raised hover surface */
23
+
24
+ /* ── Cloud — the light chrome family ──────────────────────────
25
+ Ordered by depth too: 50 is the lightest, 200 the darkest. */
26
+ --fold-ref-white: #ffffff; /* header bar */
27
+ --fold-ref-cloud-50: #f9fafb; /* rail 2 · workspace menu */
28
+ --fold-ref-cloud-100: #f4f5f7; /* page background */
29
+ --fold-ref-cloud-150: #f0f1f3; /* rail 1 · app menu */
30
+
31
+ /* ── Teal — the brand / primary family ────────────────────── */
32
+ --fold-ref-teal-400: #2dd4d4; /* lightest — hover on dark */
33
+ --fold-ref-teal-500: #06a4a4; /* brand base (dark theme) */
34
+ --fold-ref-teal-550: #069090; /* muted — brand on light */
35
+ --fold-ref-teal-600: #057a7a; /* darkest — hover on light */
36
+
37
+ /* ── Amber — the warning family ───────────────────────────── */
38
+ --fold-ref-amber-300: #e8b84a; /* light tint (dark theme) */
39
+ --fold-ref-amber-500: #d4a017; /* base (dark theme) */
40
+ --fold-ref-amber-550: #d4940e; /* light tint (light theme) */
41
+ --fold-ref-amber-600: #b8860b; /* base (light theme) */
42
+
43
+ /* ── Red — the alert family ───────────────────────────────── */
44
+ --fold-ref-red-400: #e06450; /* light tint (dark theme) */
45
+ --fold-ref-red-450: #d4493a; /* light tint (light theme) */
46
+ --fold-ref-red-500: #c44230; /* base (dark theme) */
47
+ --fold-ref-red-600: #b33a2a; /* base (light theme) */
48
+
49
+ /* ── Purple — the info family ─────────────────────────────── */
50
+ --fold-ref-purple-300: #b794f4; /* light tint (dark theme) */
51
+ --fold-ref-purple-400: #9f7aea; /* surface/border base (dark) */
52
+ --fold-ref-purple-500: #7c5bbf; /* base (dark) · text (light) */
53
+ --fold-ref-purple-600: #6c4ab6; /* base (light theme) */
54
+
55
+ /* ── Green — the success family ───────────────────────────── */
56
+ --fold-ref-green-300: #4bd6a0; /* light tint (dark theme) */
57
+ --fold-ref-green-500: #1a9e6a; /* base (both themes) */
58
+ --fold-ref-green-550: #38a169; /* light tint (light theme) */
59
+
60
+ /* ── Slate — the neutral text family ──────────────────────── */
61
+ --fold-ref-slate-50: #eef1ff; /* primary text (dark theme) */
62
+ --fold-ref-slate-350: #9ca3af; /* faded text (light theme) */
63
+ --fold-ref-slate-400: #8892b0; /* secondary text (dark) */
64
+ --fold-ref-slate-500: #5e6a86; /* muted text (dark) */
65
+ --fold-ref-slate-550: #6b7280; /* muted text (light) */
66
+ --fold-ref-slate-600: #5f6b7a; /* secondary text (light) */
67
+ --fold-ref-slate-700: #4a5470; /* faded text (dark theme) */
68
+ --fold-ref-slate-900: #1a1d23; /* primary text (light theme) */
69
+
70
+ /* ── Azure — a cyan, BUBBLY's info family ──────────────────────
71
+ Moved bubbly's info off its violet brand's hue, the way a status
72
+ that collides with the brand always must. */
73
+ --fold-ref-azure-500: #0ea5e9; /* base — bubbly info */
74
+
75
+ /* ── Navy — the NAVI theme family ─────────────────────────────
76
+ One corporate midnight-blue family serving both jobs: the brand
77
+ on the light page (500/600) and the dark chrome behind it
78
+ (800→950), so rails, header and primary are visibly related.
79
+ 300/400 are the tints readable ON the dark chrome. */
80
+ --fold-ref-navy-300: #9db8ea; /* text tint on dark chrome */
81
+ --fold-ref-navy-400: #5a7fd0; /* hover tint on dark chrome */
82
+ --fold-ref-navy-500: #24448f; /* brand base (light page) */
83
+ --fold-ref-navy-600: #1b3573; /* hover / readable brand text */
84
+ --fold-ref-navy-750: #1a3157; /* header — set apart from the rails */
85
+ --fold-ref-navy-800: #16294f; /* raised surface on the chrome */
86
+ --fold-ref-navy-850: #13233f; /* rail 2 · workspace menu */
87
+ --fold-ref-navy-900: #101d3a; /* rail 1 · app menu (deepest) */
88
+ --fold-ref-navy-950: #0b152b; /* sunken surface on the chrome */
89
+
90
+ /* ── Ivory — the NAVI page ────────────────────────────────────
91
+ White, off by two points of blue. The opposition is the point: a
92
+ cool page beside a cool rail is merely consistent, where warm-on-
93
+ cool is what makes navy read as navy — and it works at a very low
94
+ dose. Any warmer and the page starts looking like cream, a whole
95
+ warm theme rather than a warm page. */
96
+ --fold-ref-ivory-50: #fdfcfb; /* page background (navi) */
97
+
98
+ /* ── Bubble / Grape — the BUBBLY theme families ────────────────
99
+ Festive light: soft lavender-white chrome and a joyful violet
100
+ brand, rounded off. Text reuses slate, info reuses azure (cyan)
101
+ so it never blurs into the violet brand. */
102
+ --fold-ref-bubble-0: #ffffff; /* header · card · text on solid */
103
+ --fold-ref-bubble-50: #faf7ff; /* rail 2 · workspace menu */
104
+ --fold-ref-bubble-100: #f4eefe; /* page background */
105
+ --fold-ref-bubble-150: #ebe1fd; /* rail 1 · app menu */
106
+
107
+ --fold-ref-grape-500: #a855f7; /* brand base */
108
+ --fold-ref-grape-600: #9333ea; /* hover / strong */
109
+ --fold-ref-grape-700: #7e22ce; /* readable brand text */
110
+
111
+ /* ── Pure black — pairs with white for neutral alpha overlays */
112
+ --fold-ref-black: #000000;
113
+ }
@@ -0,0 +1,106 @@
1
+ /* ============================================================
2
+ SH3PHERD · Design tokens — SCALES (radius, type)
3
+ ------------------------------------------------------------
4
+ Sizing + elevation scales. Single-tier: a radius or a font size
5
+ IS its value, so there is no primitive/semantic split — just the
6
+ scale, on :root. Elevation is the one exception that touches
7
+ colour, but stays theme-invariant (black-ink shadows via the black
8
+ primitive, legible on every theme).
9
+
10
+ RADIUS is the one scale a theme may re-declare. Corner softness is
11
+ a brand axis, not a measurement: the same product reads friendly
12
+ or institutional on the same layout. Type, space, motion and
13
+ elevation stay theme-invariant — retheming must never re-flow a
14
+ page, and only radius can change without moving a single box. The
15
+ contract test enforces exactly that split.
16
+ ============================================================ */
17
+
18
+ :root {
19
+ /* Radius scale.
20
+ NB: `lg` is a real large radius and `pill` is the capsule —
21
+ two separate tokens. (The app historically overloaded a single
22
+ `--radius-lg` as the pill, which left no token for a card's
23
+ ~14px corner. Fixed here.) */
24
+ --fold-radius-xs: 3px;
25
+ --fold-radius-sm: 6px;
26
+ --fold-radius-md: 10px;
27
+ --fold-radius-lg: 14px;
28
+ --fold-radius-pill: 9999px;
29
+ --fold-radius-round: 50%;
30
+
31
+ /* Type scale — absolute px, matching claudeDesign-ref exactly (the app root
32
+ is 14px, so rem would render ~12% small; px is root-independent). */
33
+ --fold-text-xs: 11px;
34
+ --fold-text-sm: 12px;
35
+ --fold-text-md: 14px;
36
+ --fold-text-lg: 16px;
37
+ --fold-text-xl: 20px;
38
+
39
+ /* Icon size scale — the length a `fold-icon` renders at (width = height),
40
+ selected by its size preset. A measurement, so theme-invariant like type
41
+ and space. The component keeps a px fallback, so icons still render if a
42
+ consumer loads components without the token layer. */
43
+ --fold-icon-size-xs: 12px;
44
+ --fold-icon-size-sm: 16px;
45
+ --fold-icon-size-md: 20px;
46
+ --fold-icon-size-lg: 24px;
47
+ --fold-icon-size-xl: 32px;
48
+
49
+ /* Space scale — the shared spacing rhythm (gap / padding / margin). Promoted
50
+ once a 2nd+ component needed it (icon, paginator, panel-header, data-table);
51
+ the app's `--gap-*` bridge onto these 1:1. */
52
+ --fold-space-xs: 4px;
53
+ --fold-space-sm: 8px;
54
+ --fold-space-md: 12px;
55
+ --fold-space-lg: 16px;
56
+ --fold-space-xl: 20px;
57
+
58
+ /* Motion scale — transition shorthands (duration + easing bundled, matching
59
+ the app so `--t-*` bridge onto these 1:1). One knob per interaction speed. */
60
+ --fold-motion-fast: 0.1s ease;
61
+ --fold-motion-base: 0.18s ease;
62
+ --fold-motion-slow: 0.28s ease;
63
+
64
+ /* Backdrop-blur radii (for frosted `--fold-color-glass` surfaces). */
65
+ --fold-blur-glass: 20px;
66
+
67
+ /* Elevation scale — the shared depth language. Components name a level, never
68
+ spell their own shadow. Theme-invariant: the ink is the black primitive via
69
+ color-mix (no raw rgba), which reads acceptably on dark and light.
70
+ `panel-*` are the directional side-panel shadows (+ inset glass highlight). */
71
+ --fold-shadow-sm: 0 1px 2px
72
+ color-mix(in srgb, var(--fold-ref-black) 20%, transparent);
73
+ --fold-shadow-md: 0 10px 30px -12px
74
+ color-mix(in srgb, var(--fold-ref-black) 50%, transparent);
75
+ --fold-shadow-lg:
76
+ 0 12px 32px color-mix(in srgb, var(--fold-ref-black) 50%, transparent),
77
+ 0 4px 12px color-mix(in srgb, var(--fold-ref-black) 35%, transparent);
78
+ --fold-shadow-panel-right:
79
+ -12px 0 40px color-mix(in srgb, var(--fold-ref-black) 45%, transparent),
80
+ inset 1px 0 0 color-mix(in srgb, var(--fold-ref-white) 4%, transparent);
81
+ --fold-shadow-panel-left:
82
+ 12px 0 40px color-mix(in srgb, var(--fold-ref-black) 45%, transparent),
83
+ inset -1px 0 0 color-mix(in srgb, var(--fold-ref-white) 4%, transparent);
84
+ }
85
+
86
+ /* ── Theme shape override: NAVI ───────────────────────────────
87
+ Back-office corporate: corners nearly squared off. `pill` and
88
+ `round` are shapes, not scale steps — flattening them would turn
89
+ avatars into squares and capsules into slabs — so they stay. */
90
+ [data-theme="navi"] {
91
+ --fold-radius-xs: 1px;
92
+ --fold-radius-sm: 2px;
93
+ --fold-radius-md: 3px;
94
+ --fold-radius-lg: 4px;
95
+ }
96
+
97
+ /* ── Theme shape override: BUBBLY ─────────────────────────────
98
+ The opposite of navi: corners rounded right up, so every surface
99
+ reads soft and pill-like. `pill` and `round` stay — they are
100
+ shapes, not scale steps. */
101
+ [data-theme="bubbly"] {
102
+ --fold-radius-xs: 6px;
103
+ --fold-radius-sm: 12px;
104
+ --fold-radius-md: 16px;
105
+ --fold-radius-lg: 24px;
106
+ }