@bitforgehq/ui 0.3.1 → 0.3.2

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +9 -8
  3. package/ai/MANIFEST.index.json +18 -0
  4. package/ai/MANIFEST.json +368 -31
  5. package/ai/REFERENCE.index.json +63 -0
  6. package/ai/REFERENCE.json +247 -5
  7. package/ai/UI_GUIDE.md +59 -33
  8. package/ai/components/app-frame.md +328 -0
  9. package/ai/components/card.md +56 -2
  10. package/ai/components/empty-state.md +99 -6
  11. package/ai/components/header.md +5 -1
  12. package/ai/components/sidebar-toggle.md +287 -0
  13. package/ai/components/sidebar.md +188 -10
  14. package/ai/components/stat.md +74 -10
  15. package/ai/components/table.md +134 -5
  16. package/ai/components/tabs.md +5 -1
  17. package/ai/components/toolbar.md +69 -4
  18. package/ai/reference/bf-app-frame-breakpoint.md +27 -0
  19. package/ai/reference/bf-app-frame-content-width.md +29 -0
  20. package/ai/reference/bf-empty-state-heading-level.md +1 -1
  21. package/ai/reference/bf-empty-state-heading.md +33 -0
  22. package/ai/reference/bf-labels.md +6 -0
  23. package/ai/reference/bf-sidebar-state-service.md +21 -0
  24. package/ai/reference/bf-sidebar-toggle-harness.md +32 -0
  25. package/ai/reference/bf-size.md +1 -0
  26. package/ai/reference/bf-stat-appearance.md +33 -0
  27. package/ai/reference/bf-stat-variant.md +1 -1
  28. package/ai/reference/bf-table-harness.md +1 -1
  29. package/ai/reference/bf-table-stack.md +29 -0
  30. package/ai/reference/bf_sidebar_state_storage.md +20 -0
  31. package/ai/reference/provide-bf-labels.md +4 -3
  32. package/ai/reference/provide-bf-sidebar-state.md +20 -0
  33. package/bin/bf-ui.js +433 -3
  34. package/fesm2022/bitforgehq-ui-overlay.mjs +571 -446
  35. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
  36. package/fesm2022/bitforgehq-ui-testing.mjs +18 -2
  37. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  38. package/fesm2022/bitforgehq-ui.mjs +759 -127
  39. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  40. package/llms-full.txt +1560 -43
  41. package/llms.txt +11 -0
  42. package/package.json +1 -1
  43. package/types/bitforgehq-ui-overlay.d.ts +51 -0
  44. package/types/bitforgehq-ui-testing.d.ts +35 -1
  45. package/types/bitforgehq-ui.d.ts +276 -20
package/CHANGELOG.md CHANGED
@@ -4,6 +4,122 @@ All notable changes to `@bitforgehq/ui`. One `##` section per version; one `###`
4
4
 
5
5
  The heading for the version being worked on carries `(unreleased)` in place of a date. At release time, that placeholder is replaced with the release date (`## 0.3.1 (unreleased)` becomes `## 0.3.1 (YYYY-MM-DD)`) in the same commit that bumps `projects/ui/package.json`. See "Releasing" in the root `README.md`. 0.3.0 is the first version published to npm; the 0.2.0 and 0.1.0 sections below are the history of versions that were never published.
6
6
 
7
+ ## 0.3.2 (2026-10-29)
8
+
9
+ ### docs site
10
+
11
+ The docs initial bundle (620 kB) warns at 640 kB instead of 600 kB: the example registry ships in
12
+ the initial bundle and gained this release's examples (moving it into a lazy chunk is the lasting
13
+ fix). The web demo loads its app frame lazily, like its pages, and its initial bundle (542 kB, the
14
+ stylesheet with every widget's classes) warns at 560 kB instead of 540 kB.
15
+
16
+ ### tabs
17
+
18
+ The `## Desktop` docs point at `bf-app-frame` for the frame around the desktop navigation.
19
+
20
+ ### header
21
+
22
+ The `## Desktop` docs say `bf-app-frame` supplies the app-level header bar below its breakpoint.
23
+
24
+ ### app-frame
25
+
26
+ New `bf-app-frame` in `@bitforgehq/ui`: the frame of a desktop web app. Slots `sidebar` (a
27
+ `bf-sidebar`, in a column that sticks to the viewport at full height from the breakpoint up),
28
+ `brand`, `menu` (the narrow-screen `bf-menu-button`) and `actions` (the header bar shown below
29
+ the breakpoint) and the default slot (the page, in the `main` landmark). `breakpoint`
30
+ (`BfAppFrameBreakpoint`: `'md'` default, `'lg'`), `contentWidth` (`BfAppFrameContentWidth`:
31
+ `'md'` 48rem, `'lg'` 64rem, `'xl'` 80rem default, `'full'`) and `mainId`. A skip link, first in
32
+ the tab order and hidden until focused, moves focus to the main landmark by script, so it works
33
+ under `<base href="/">`; new label key `skipToContent` ("Skip to main content"). Inside another
34
+ `main` landmark the content drops its `main` role. Desktop only: the Capacitor shell keeps
35
+ `bf-tabs`.
36
+
37
+ ### toolbar
38
+
39
+ On a narrow row the actions no longer end up alone on a row of their own: the status and the
40
+ actions are now one group that takes the rest of the last row and wraps as a whole, with the
41
+ status at the start and the actions at the inline end. The wide layout is unchanged, and a
42
+ toolbar without actions keeps the status as a plain item of the row. New `toolbar/narrow`
43
+ example at phone width.
44
+
45
+ ### stat
46
+
47
+ New `variant="tile"`: a sunken, borderless tile (`surface-sunken`, the `card` radius and
48
+ padding) for a row of stats inside a raised `bf-card`; on it the icon tile turns `surface`.
49
+ `variant` now takes the new named type `BfStatAppearance` (`BfStatVariant | 'tile'`); the
50
+ released `BfStatVariant` keeps its two members, so `Record`s over it keep compiling. New
51
+ `stat/dashboard` example with one surface per level.
52
+
53
+ ### card
54
+
55
+ New "Nesting surfaces" docs section: a raised card holds sunken tiles, never an outlined
56
+ surface (`flat`, a `card` stat), and each level of a dashboard keeps one surface style. New
57
+ `card/nesting` example. No code change.
58
+
59
+ ### empty-state
60
+
61
+ `headingLevel` now takes the new named type `BfEmptyStateHeading` (`BfEmptyStateHeadingLevel |
62
+ 1`): `1` renders the title as the page's `h1`, for an empty state that is the page (a not-found
63
+ or no-access page). The released `BfEmptyStateHeadingLevel` keeps its two members, so `Record`s
64
+ over it keep compiling. New "As the page" docs section with the `empty-state/page` example
65
+ (centred in a tall area, a primary action and a secondary link) and the code-only
66
+ `empty-state/not-found-page`.
67
+
68
+ ### table
69
+
70
+ New opt-in `stack` input (`BfTableStack`: `'never'` by default, so existing tables do not
71
+ change, `'narrow'` or `'coarse'`): while the table is narrower than 36rem (a container query on
72
+ the host, which then gets `@container`) or, for `'coarse'`, under a coarse pointer at any width,
73
+ each body row renders as a sunken tile of label/value pairs. The markup stays a `table` with
74
+ explicit `table`, `rowgroup`, `row`, `columnheader` and `cell` roles (some browsers drop a
75
+ table's semantics once its display changes), the header row is visually hidden but still read,
76
+ the selection checkbox and the first cell head each tile, and every other cell shows its column
77
+ label (`data-label`, a `::before` with empty alternative text, so it is not read twice). A bar
78
+ above the tiles holds a labelled Select all checkbox and a Sort by `bf-select`, since the hidden
79
+ header's controls are not shown. New label keys `tableSortBy` ("Sort by"), `tableSortAscending`
80
+ and `tableSortDescending` (`"Hours, ascending"`). `BfTableHarness` reads and drives a stacked
81
+ table the same way. New `table/stacked` example and a Stacked rows docs section.
82
+
83
+ ### sidebar-toggle
84
+
85
+ New `bf-sidebar-toggle` in `@bitforgehq/ui/overlay`: a text icon button placed inside a
86
+ `bf-sidebar` (header or footer) that flips the sidebar between full width and an icon rail by
87
+ writing its `collapsed` model, so `[(collapsed)]` sees every press. Its name and `bfTooltip` say
88
+ what the next press does (new label keys `sidebarCollapse` "Collapse sidebar" and `sidebarExpand`
89
+ "Expand sidebar"); `aria-expanded` follows the sidebar and `aria-controls` points at its `nav`.
90
+ Icons are the `collapse-icon` and `expand-icon` slots, only the matching one shown; `size` as
91
+ `bf-icon-button`. Outside a sidebar (in a `bf-top-nav`, or alone) it renders nothing. A
92
+ `BfSidebarToggleHarness` in `@bitforgehq/ui/testing` (`getLabel()`, `isExpanded()`, `toggle()`).
93
+
94
+ ### sidebar
95
+
96
+ New `BfSidebarStateService` (a `collapsed` signal) and `provideBfSidebarState()` in
97
+ `@bitforgehq/ui`: bind the sidebar's `[(collapsed)]` to `sidebarState.collapsed` and the provider
98
+ stores every change under `bf-sidebar-collapsed` in `BF_SIDEBAR_STATE_STORAGE` (`localStorage` in
99
+ the browser, memory elsewhere), read back at the next start; without the provider nothing is
100
+ written, and on the server nothing is read. The sidebar's `nav` now has an id, for a toggle's
101
+ `aria-controls`. The docs gain "Remember the collapsed sidebar" and a "Footer" composition
102
+ (Settings link, theme menu, toggle, version line) that works expanded and as an icon rail.
103
+
104
+ ### theme
105
+
106
+ Decision: the default primary stays indigo (`#2b26ba`). Making the Meadow Sage green the default
107
+ would recolour every app that relies on the indigo, a breaking change; a brand override recipe
108
+ gives a new app the green (or any brand) on day one instead. No token changes.
109
+
110
+ New `bf-ui theme <hex> [--dark <hex>]` command in the package's CLI (no new dependencies): it
111
+ derives the brand set (`--color-primary`, `-hover`, `-pressed`, `-soft`, `-soft-hover`,
112
+ `-soft-pressed`, `-strong`, `--color-on-primary`, `--color-primary-text`, `--color-selected`,
113
+ `--color-ring`) for light and dark mode with the docs configurator's OKLCH steps, keeping white
114
+ text on the brand in light mode; `--dark` sets the dark-mode primary (else the brand is lifted to
115
+ OKLCH lightness 0.76). It prints a `@theme` and a `.dark` block to paste after the theme import,
116
+ with every brand contrast pair's ratio in a comment (the pairs of the theme's contrast test, plus
117
+ `primary` at 3:1 on `bg` and `surface`), and exits 1 naming each pair below its minimum and the
118
+ nearest darker (light) or lighter (dark) shade that passes. The docs Theming page gains a "Brand
119
+ colour: the recipe" section (each token, how it is derived in light and dark, and why) with a
120
+ Meadow Sage green worked example (`bf-ui theme '#238652' --dark '#5cc48a'`; the design's
121
+ `#2f8f5b` gives white text only 4.04:1), and the agent guide and README point to the command.
122
+
7
123
  ## 0.3.1 (2026-10-29)
8
124
 
9
125
  ### calendar
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Bitforge's shared Angular component library: Meadow Sage design, Tailwind CSS v4, signals-first, Angular 22.
4
4
 
5
- The theme is the Meadow Sage palette (warm off-white canvas, white surfaces, sage-tinted neutrals and status colours, pill controls). Its default primary is a neutral indigo (`#2b26ba`), not the design's sage green: it is meant to be overridden with your brand colour (`--color-primary` and its set; the docs site's theme configurator derives them), so an indigo primary after install is expected, not a broken install.
5
+ The theme is the Meadow Sage palette (warm off-white canvas, white surfaces, sage-tinted neutrals and status colours, pill controls). Its default primary is a neutral indigo (`#2b26ba`), not the design's sage green: it is meant to be overridden with your brand colour (`--color-primary` and its set; the docs site's theme configurator derives them), so an indigo primary after install is expected, not a broken install. `bunx bf-ui theme '#238652' --dark '#5cc48a'` prints the whole set for a brand colour, as a `@theme` and a `.dark` block to paste after the theme import, with every contrast pair's ratio, and exits 1 naming the failing pairs and a shade that passes (the docs site's Theming page has the recipe and a Meadow Sage green worked example).
6
6
 
7
7
  - Widgets: `@bitforgehq/ui`
8
8
  - Number field: `@bitforgehq/ui/number-input` (`bf-number-input`; loads Angular Forms, peer
@@ -140,16 +140,17 @@ Render library components only in the browser, for example in a `@defer` block o
140
140
  route. Support will be decided before 1.0.
141
141
 
142
142
  The one server-side check is a render smoke, not a support test: the library repository's
143
- `tools/ssr-smoke.ts` renders 42 fixtures with `renderApplication()` (every root widget, `bf-icon`,
143
+ `tools/ssr-smoke.ts` renders 43 fixtures with `renderApplication()` (every root widget, `bf-icon`,
144
144
  `bf-number-input`, a `/charts` line chart, a `/mobile` page with `provideBfShell()`, `bf-page`,
145
145
  `bf-header` and `bf-content`, `bf-tabs` with `bf-stack-outlet` under the router, and an `/overlay`
146
- dialog), and all of them render without an error. 27 of them render identically twice. The other 15
146
+ dialog), and all of them render without an error. 27 of them render identically twice. The other 16
147
147
  number their ids differently on every render, from a module-level counter, so they could not
148
- hydrate: `bf-calendar`, `bf-checkbox`, `bf-input`, `bf-radio-group`, `bf-segmented`, `bf-select`,
149
- `bf-sidebar`, `bf-tab-group`, `bf-table`, `bf-textarea`, `bf-theme-switch`, `bf-toggle`,
150
- `bf-line-chart`, `bf-number-input` and the `/overlay` dialog. Hydration itself is still not
151
- supported or tested, and more stands in its way: `/mobile` writes to `<html>` and adds a keyboard
152
- probe to `<body>`, and an `/overlay` dialog renders outside the app root and marks it inert.
148
+ hydrate: `bf-app-frame`, `bf-calendar`, `bf-checkbox`, `bf-input`, `bf-radio-group`, `bf-segmented`,
149
+ `bf-select`, `bf-sidebar`, `bf-tab-group`, `bf-table`, `bf-textarea`, `bf-theme-switch`,
150
+ `bf-toggle`, `bf-line-chart`, `bf-number-input` and the `/overlay` dialog. Hydration itself is still
151
+ not supported or tested, and more stands in its way: `/mobile` writes to `<html>` and adds a
152
+ keyboard probe to `<body>`, and an `/overlay` dialog renders outside the app root and marks it
153
+ inert.
153
154
 
154
155
  ## Testing
155
156
 
@@ -37,6 +37,15 @@
37
37
  "summary": "Centred confirmation dialog with a title, message and a row of role-styled buttons",
38
38
  "since": "0.2.0"
39
39
  },
40
+ {
41
+ "name": "app-frame",
42
+ "selector": "bf-app-frame",
43
+ "className": "BfAppFrameComponent",
44
+ "category": "Navigation",
45
+ "entryPoint": "@bitforgehq/ui",
46
+ "summary": "Desktop app frame with skip link, sticky sidebar, narrow header and main content",
47
+ "since": "0.3.2"
48
+ },
40
49
  {
41
50
  "name": "avatar",
42
51
  "selector": "bf-avatar",
@@ -487,6 +496,15 @@
487
496
  "summary": "Vertical app navigation with brand, grouped links, footer and an icon rail mode",
488
497
  "since": "0.3.1"
489
498
  },
499
+ {
500
+ "name": "sidebar-toggle",
501
+ "selector": "bf-sidebar-toggle",
502
+ "className": "BfSidebarToggleComponent",
503
+ "category": "Navigation",
504
+ "entryPoint": "@bitforgehq/ui/overlay",
505
+ "summary": "Icon button inside a sidebar that collapses it to an icon rail and back",
506
+ "since": "0.3.2"
507
+ },
490
508
  {
491
509
  "name": "skeleton",
492
510
  "selector": "bf-skeleton",