@bitforgehq/ui 0.3.0 → 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.
- package/CHANGELOG.md +598 -0
- package/README.md +18 -11
- package/ai/MANIFEST.index.json +306 -0
- package/ai/MANIFEST.json +8915 -3788
- package/ai/REFERENCE.index.json +476 -0
- package/ai/REFERENCE.json +5810 -2905
- package/ai/UI_GUIDE.md +212 -58
- package/ai/components/app-frame.md +328 -0
- package/ai/components/back-button.md +42 -2
- package/ai/components/badge.md +17 -7
- package/ai/components/bar-chart.md +188 -0
- package/ai/components/breadcrumb-item.md +121 -0
- package/ai/components/breadcrumb.md +277 -0
- package/ai/components/button.md +82 -15
- package/ai/components/calendar.md +300 -0
- package/ai/components/card.md +119 -4
- package/ai/components/chart-card.md +283 -0
- package/ai/components/combobox.md +411 -0
- package/ai/components/date-input.md +396 -0
- package/ai/components/datetime-input.md +215 -0
- package/ai/components/description-item.md +111 -0
- package/ai/components/description-list.md +160 -0
- package/ai/components/donut-chart.md +169 -0
- package/ai/components/empty-state.md +99 -6
- package/ai/components/header.md +71 -2
- package/ai/components/icon-button.md +74 -16
- package/ai/components/icon.md +63 -7
- package/ai/components/line-chart.md +234 -0
- package/ai/components/list.md +70 -6
- package/ai/components/menu.md +5 -0
- package/ai/components/multi-combobox.md +257 -0
- package/ai/components/nav-group.md +178 -0
- package/ai/components/nav-item.md +210 -0
- package/ai/components/page-header.md +237 -0
- package/ai/components/pagination.md +173 -0
- package/ai/components/popover.md +250 -0
- package/ai/components/side-panel.md +391 -0
- package/ai/components/sidebar-toggle.md +287 -0
- package/ai/components/sidebar.md +541 -0
- package/ai/components/skeleton.md +215 -0
- package/ai/components/sparkline.md +188 -0
- package/ai/components/stat.md +297 -0
- package/ai/components/tab-group.md +226 -0
- package/ai/components/tab-panel.md +163 -0
- package/ai/components/table.md +697 -0
- package/ai/components/tabs.md +46 -2
- package/ai/components/theme-menu-button.md +182 -0
- package/ai/components/theme-switch.md +170 -0
- package/ai/components/time-input.md +240 -0
- package/ai/components/toolbar.md +354 -0
- package/ai/components/tooltip.md +230 -0
- package/ai/components/top-nav.md +159 -0
- package/ai/reference/bf-app-frame-breakpoint.md +27 -0
- package/ai/reference/bf-app-frame-content-width.md +29 -0
- package/ai/reference/bf-badge-appearance.md +36 -0
- package/ai/reference/bf-badge-variant.md +1 -1
- package/ai/reference/bf-bar-chart-orientation.md +27 -0
- package/ai/reference/bf-button-appearance.md +36 -0
- package/ai/reference/bf-button-variant.md +1 -1
- package/ai/reference/bf-calendar-disabled-date.md +23 -0
- package/ai/reference/bf-calendar-harness.md +51 -0
- package/ai/reference/bf-calendar-weekday.md +31 -0
- package/ai/reference/bf-chart-card-heading-level.md +26 -0
- package/ai/reference/bf-chart-curve.md +28 -0
- package/ai/reference/bf-chart-harness.md +51 -0
- package/ai/reference/bf-chart-legend-position.md +30 -0
- package/ai/reference/bf-chart-series.md +23 -0
- package/ai/reference/bf-chart-value-format.md +23 -0
- package/ai/reference/bf-color-scheme-service.md +30 -0
- package/ai/reference/bf-color-scheme.md +31 -0
- package/ai/reference/bf-combobox-filter.md +27 -0
- package/ai/reference/bf-combobox-harness.md +89 -0
- package/ai/reference/bf-combobox-option.md +33 -0
- package/ai/reference/bf-compare-with.md +2 -0
- package/ai/reference/bf-date-input-harness.md +67 -0
- package/ai/reference/bf-date-input-picker.md +27 -0
- package/ai/reference/bf-date-time-input-harness.md +76 -0
- package/ai/reference/bf-date-time-input-picker.md +27 -0
- package/ai/reference/bf-description-list-layout.md +26 -0
- package/ai/reference/bf-donut-slice.md +22 -0
- package/ai/reference/bf-empty-state-heading-level.md +1 -1
- package/ai/reference/bf-empty-state-heading.md +33 -0
- package/ai/reference/bf-labels.md +73 -20
- package/ai/reference/bf-menu-button-variant.md +1 -0
- package/ai/reference/bf-menu-placement.md +1 -0
- package/ai/reference/bf-overlay-options.md +28 -27
- package/ai/reference/bf-overlay-placement.md +34 -0
- package/ai/reference/bf-overlay-position.md +1 -1
- package/ai/reference/bf-overlay-service.md +5 -3
- package/ai/reference/bf-page-header-heading-level.md +26 -0
- package/ai/reference/bf-pagination-harness.md +61 -0
- package/ai/reference/bf-platform-service.md +17 -15
- package/ai/reference/bf-popover-harness.md +42 -0
- package/ai/reference/bf-popover-placement.md +28 -0
- package/ai/reference/bf-popover-trigger-directive.md +56 -0
- package/ai/reference/bf-side-panel-config.md +35 -0
- package/ai/reference/bf-side-panel-harness.md +34 -0
- package/ai/reference/bf-side-panel-ref.md +44 -0
- package/ai/reference/bf-side-panel-service.md +43 -0
- package/ai/reference/bf-side-panel-template-context.md +32 -0
- package/ai/reference/bf-side-panel-width.md +28 -0
- package/ai/reference/bf-sidebar-state-service.md +21 -0
- package/ai/reference/bf-sidebar-toggle-harness.md +32 -0
- package/ai/reference/bf-size.md +13 -0
- package/ai/reference/bf-skeleton-shape.md +28 -0
- package/ai/reference/bf-stat-appearance.md +33 -0
- package/ai/reference/bf-stat-trend-intent.md +27 -0
- package/ai/reference/bf-stat-trend.md +27 -0
- package/ai/reference/bf-stat-variant.md +26 -0
- package/ai/reference/bf-tab-group-harness.md +44 -0
- package/ai/reference/bf-table-align.md +26 -0
- package/ai/reference/bf-table-cell-context.md +24 -0
- package/ai/reference/bf-table-cell-directive.md +22 -0
- package/ai/reference/bf-table-column.md +28 -0
- package/ai/reference/bf-table-harness.md +77 -0
- package/ai/reference/bf-table-row-key.md +21 -0
- package/ai/reference/bf-table-sort-direction.md +26 -0
- package/ai/reference/bf-table-sort.md +27 -0
- package/ai/reference/bf-table-stack.md +29 -0
- package/ai/reference/bf-theme.md +5 -4
- package/ai/reference/bf-time-input-harness.md +67 -0
- package/ai/reference/bf-time-input-hour-cycle.md +27 -0
- package/ai/reference/bf-time-input-picker.md +27 -0
- package/ai/reference/bf-tooltip-directive.md +43 -0
- package/ai/reference/bf-tooltip-harness.md +43 -0
- package/ai/reference/bf-tooltip-placement.md +28 -0
- package/ai/reference/bf_color_scheme_storage.md +20 -0
- package/ai/reference/bf_side_panel_data.md +17 -0
- package/ai/reference/bf_sidebar_state_storage.md +20 -0
- package/ai/reference/bf_theme_storage.md +3 -1
- package/ai/reference/provide-bf-color-scheme.md +20 -0
- package/ai/reference/provide-bf-labels.md +13 -4
- package/ai/reference/provide-bf-sidebar-state.md +20 -0
- package/ai/reference/slide-in-from-end.md +24 -0
- package/ai/reference/slide-out-to-end.md +24 -0
- package/bin/bf-ui.js +433 -3
- package/fesm2022/bitforgehq-ui-charts.mjs +3045 -0
- package/fesm2022/bitforgehq-ui-charts.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-icons.mjs +107 -3
- package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-mobile.mjs +14 -59
- package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-overlay.mjs +6566 -38
- package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-testing.mjs +634 -1
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui.mjs +5708 -137
- package/fesm2022/bitforgehq-ui.mjs.map +1 -1
- package/llms-full.txt +26766 -14470
- package/llms.txt +106 -1
- package/package.json +7 -3
- package/theme.css +101 -0
- package/types/bitforgehq-ui-charts.d.ts +967 -0
- package/types/bitforgehq-ui-icons.d.ts +13 -1
- package/types/bitforgehq-ui-mobile.d.ts +25 -18
- package/types/bitforgehq-ui-overlay.d.ts +1895 -7
- package/types/bitforgehq-ui-testing.d.ts +782 -1
- package/types/bitforgehq-ui.d.ts +2393 -45
package/ai/UI_GUIDE.md
CHANGED
|
@@ -72,7 +72,7 @@ In `src/index.html`, give `<body>` the theme background and text colour, so the
|
|
|
72
72
|
|
|
73
73
|
### 7. Switch to dark mode
|
|
74
74
|
|
|
75
|
-
Add the `dark` class to `<html>` (and remove it for light mode). Every token is redefined under `.dark`, and the theme sets `color-scheme`, so scrollbars and native controls follow too. Components need no `dark:` classes.
|
|
75
|
+
Add the `dark` class to `<html>` (and remove it for light mode). Every token is redefined under `.dark`, and the theme sets `color-scheme`, so scrollbars and native controls follow too. Components need no `dark:` classes. To let users choose System, Light or Dark, add `provideBfColorScheme()` to the app providers: it sets the class, follows the OS and remembers the choice.
|
|
76
76
|
|
|
77
77
|
```html
|
|
78
78
|
<html lang="en" class="dark">
|
|
@@ -117,7 +117,12 @@ the widgets style their native controls themselves.
|
|
|
117
117
|
Optional per-app overrides go after the import. A brand colour is a set: override
|
|
118
118
|
`--color-primary` together with `--color-primary-text` (primary as text, ≥ 4.5:1 on `bg` and
|
|
119
119
|
`surface`) and the rest of the `--color-primary-*` tokens, in `@theme` and in `.dark`; the docs
|
|
120
|
-
site's theme configurator derives the whole contrast-checked set from one colour.
|
|
120
|
+
site's theme configurator derives the whole contrast-checked set from one colour. From a
|
|
121
|
+
terminal, `bunx bf-ui theme '<hex>' [--dark '<hex>']` prints the set (`primary`, its hover,
|
|
122
|
+
pressed, soft and strong steps, `on-primary`, `primary-text`, `selected`, `ring`) as a `@theme`
|
|
123
|
+
and a `.dark` block with each contrast pair's ratio, and exits 1 naming the pairs below their
|
|
124
|
+
minimum and a shade that passes; paste its output, never hand-pick the steps. Example (the
|
|
125
|
+
Meadow Sage green): `bunx bf-ui theme '#238652' --dark '#5cc48a'`.
|
|
121
126
|
`--radius-control` (`9999px`, pills) reshapes buttons, chips, badges, segmented, the tab bar, the
|
|
122
127
|
action bar and toggles at once:
|
|
123
128
|
|
|
@@ -138,15 +143,17 @@ Render library components only in the browser, for example in a `@defer` block o
|
|
|
138
143
|
route. Support will be decided before 1.0.
|
|
139
144
|
|
|
140
145
|
The one server-side check is a render smoke, not a support test: the library repository's
|
|
141
|
-
`tools/ssr-smoke.ts` renders
|
|
142
|
-
`bf-number-input`, a `/mobile` page with `provideBfShell()`, `bf-page`,
|
|
143
|
-
`bf-content`, `bf-tabs` with `bf-stack-outlet` under the router, and an `/overlay`
|
|
144
|
-
of them render without an error.
|
|
145
|
-
differently on every render, from a module-level counter, so they could not
|
|
146
|
-
`bf-
|
|
147
|
-
`bf-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
`tools/ssr-smoke.ts` renders 43 fixtures with `renderApplication()` (every root widget, `bf-icon`,
|
|
147
|
+
`bf-number-input`, a `/charts` line chart, a `/mobile` page with `provideBfShell()`, `bf-page`,
|
|
148
|
+
`bf-header` and `bf-content`, `bf-tabs` with `bf-stack-outlet` under the router, and an `/overlay`
|
|
149
|
+
dialog), and all of them render without an error. 27 of them render identically twice. The other 16
|
|
150
|
+
number their ids differently on every render, from a module-level counter, so they could not
|
|
151
|
+
hydrate: `bf-app-frame`, `bf-calendar`, `bf-checkbox`, `bf-input`, `bf-radio-group`, `bf-segmented`,
|
|
152
|
+
`bf-select`, `bf-sidebar`, `bf-tab-group`, `bf-table`, `bf-textarea`, `bf-theme-switch`,
|
|
153
|
+
`bf-toggle`, `bf-line-chart`, `bf-number-input` and the `/overlay` dialog. Hydration itself is still
|
|
154
|
+
not supported or tested, and more stands in its way: `/mobile` writes to `<html>` and adds a
|
|
155
|
+
keyboard probe to `<body>`, and an `/overlay` dialog renders outside the app root and marks it
|
|
156
|
+
inert.
|
|
150
157
|
|
|
151
158
|
## Keeping this guide in sync
|
|
152
159
|
|
|
@@ -165,6 +172,11 @@ or out of date — wire it into CI so agent guidance never drifts from the insta
|
|
|
165
172
|
- Number field: `import { BfNumberInputComponent } from '@bitforgehq/ui/number-input';`. It is
|
|
166
173
|
the one widget in its own entry point, because it loads Angular Forms (`@angular/forms`, a
|
|
167
174
|
required peer); `@bitforgehq/ui` itself loads no forms code, so an app without forms ships none.
|
|
175
|
+
- Charts: `import { BfLineChartComponent } from '@bitforgehq/ui/charts';` (also `BfBarChartComponent`,
|
|
176
|
+
`BfDonutChartComponent`, `BfSparklineComponent`, `BfChartCardComponent`). Our own SVG charts,
|
|
177
|
+
themed with the `--color-chart-1` … `--color-chart-8` tokens; pass `series` (`{ name, values }`) and
|
|
178
|
+
`categories`, and a `label` that names the figure. Prefer them to a chart library unless you need a
|
|
179
|
+
chart form they do not draw.
|
|
168
180
|
- Layout classes go on the element (`<bf-button class="mt-4">`); never restyle a widget's internals.
|
|
169
181
|
- Colors: use only the semantic tokens (`bg-primary`, `text-text-muted`, `bg-surface`,
|
|
170
182
|
`border-border`, `rounded-field`, `shadow-raised`, `text-body`). Never raw palette classes and
|
|
@@ -260,7 +272,7 @@ toolbar or a German settings page); a key you leave out keeps the parent's value
|
|
|
260
272
|
(hence `fieldSize: 'lg'` for touch). Keep `gap-2` or more between wrapping rows of `sm` controls.
|
|
261
273
|
- `provideBfLabels({ ... })` replaces the built-in English strings (`loading`, `dismiss`, `tabBar`,
|
|
262
274
|
`tabBadge(count)`, `back`, `ok`, `cancel`, `actions`, `sheet`, `modal`, `refreshing`, `close`,
|
|
263
|
-
`dialog`) and the
|
|
275
|
+
`dialog`, `theme`, `themeSystem`, `themeLight`, `themeDark`) and the
|
|
264
276
|
default error text per validator kind (`validation`: `required`, `email`, `pattern`, `parse`,
|
|
265
277
|
`min(n)`, `max(n)`, `minLength(n)`, `maxLength(n)`, `minDate(d)`, `maxDate(d)`, `fallback`),
|
|
266
278
|
merged key by key; a key set to `undefined` also keeps the parent's string. Use it for any
|
|
@@ -272,7 +284,7 @@ toolbar or a German settings page); a key you leave out keeps the parent's value
|
|
|
272
284
|
fall back to `sheet`/`modal`.
|
|
273
285
|
- What a component-level `provideBfLabels()` covers: the widgets, form controls and
|
|
274
286
|
`bf-back-button`/`bf-refresher` rendered inside that component (`loading`, `dismiss`, `tabBar`,
|
|
275
|
-
`tabBadge`, `back`, `refreshing`, `validation`). The overlay services (`BfAlertDialogService`
|
|
287
|
+
`tabBadge`, `back`, `refreshing`, the `theme…` keys, `validation`). The overlay services (`BfAlertDialogService`
|
|
276
288
|
`ok`, `BfActionSheetService` `cancel`/`actions`, `BfSheetService` `sheet`, `BfModalService`
|
|
277
289
|
`modal`, `BfDialogService` `close`/`dialog`/`ok`/`cancel`, `BfDesktopToastService`
|
|
278
290
|
`notifications`) are root singletons: they read the app-level labels unless the call passes the
|
|
@@ -302,6 +314,101 @@ export const appConfig: ApplicationConfig = {
|
|
|
302
314
|
};
|
|
303
315
|
```
|
|
304
316
|
|
|
317
|
+
### Colour scheme
|
|
318
|
+
|
|
319
|
+
A System / Light / Dark choice needs no code of your own. In a desktop web app add
|
|
320
|
+
`provideBfColorScheme()` to `ApplicationConfig.providers`; `BfColorSchemeService` (both from
|
|
321
|
+
`@bitforgehq/ui`, no Capacitor) then toggles `dark` on `<html>`, follows `prefers-color-scheme`
|
|
322
|
+
while the choice is `system`, and stores the choice in `localStorage` under `bf-theme`
|
|
323
|
+
(`BF_COLOR_SCHEME_STORAGE` moves it elsewhere). Read `dark()`, and switch with
|
|
324
|
+
`scheme.set('dark')`. For the control, bind `bf-theme-switch` (three segments, for a settings page
|
|
325
|
+
or a header row with room) or `bf-theme-menu-button` (`@bitforgehq/ui/overlay`, a menu for a
|
|
326
|
+
crowded top bar, icon in `bfSlot="icon"`) two-way: `[(value)]="colorScheme.scheme"`. Storage and
|
|
327
|
+
the media query are read in the browser only, so a server render starts light and writes nothing.
|
|
328
|
+
A Capacitor app gets the same service from `provideBfShell()`: `BfPlatformService.theme` and
|
|
329
|
+
`dark` are the same signals, and the system bars follow them. Never write your own `matchMedia`
|
|
330
|
+
listener, storage key or `<html>` class toggle.
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
export const appConfig: ApplicationConfig = { providers: [provideBfColorScheme()] };
|
|
334
|
+
// In a settings component:
|
|
335
|
+
protected readonly colorScheme = inject(BfColorSchemeService);
|
|
336
|
+
// <bf-theme-switch [(value)]="colorScheme.scheme" />
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Desktop layout
|
|
340
|
+
|
|
341
|
+
`bf-tabs`, `bf-back-button` and `bf-header` are Capacitor shell parts. A desktop web app (no
|
|
342
|
+
`provideBfShell()`) uses their desktop counterparts from `@bitforgehq/ui`:
|
|
343
|
+
|
|
344
|
+
- **App frame:** wrap the whole app in `<bf-app-frame>` (never build the frame by hand): the
|
|
345
|
+
`bf-sidebar` in `bfSlot="sidebar"` (sticky, full height, from `md` up), and below the
|
|
346
|
+
breakpoint a header bar with `bfSlot="brand"`, `bfSlot="menu"` (a `bf-menu-button` of
|
|
347
|
+
`a[bfMenuItem]` links from the same destinations array) and `bfSlot="actions"` (the theme
|
|
348
|
+
menu); the router outlet is the content. It brings the skip link and the focusable main
|
|
349
|
+
landmark; `breakpoint` and `contentWidth` adjust it. Desktop only: never inside
|
|
350
|
+
`provideBfShell()`.
|
|
351
|
+
- **Sidebar collapse:** `<bf-sidebar-toggle>` (`/overlay`, icons in `bfSlot="collapse-icon"` and
|
|
352
|
+
`bfSlot="expand-icon"`) in the sidebar footer beside the icon-only theme menu; with
|
|
353
|
+
`provideBfSidebarState()` bind `[(collapsed)]="sidebarState.collapsed"`
|
|
354
|
+
(`BfSidebarStateService`) so the choice is remembered.
|
|
355
|
+
- **Navigation:** `bf-sidebar` (groups in `bf-nav-group`, `[(collapsed)]` for an icon rail) or
|
|
356
|
+
`bf-top-nav` for a few sections, holding
|
|
357
|
+
`<a bfNavItem routerLink="…" routerLinkActive ariaCurrentWhenActive="page">` links with an icon
|
|
358
|
+
in `bfSlot="icon"` and an optional `[badge]` count. The router sets `aria-current="page"` and
|
|
359
|
+
the item shows it. Drive the sidebar, a below-`md` `bf-menu-button` of `a[bfMenuItem]` links and,
|
|
360
|
+
in the shell, the `bf-tab`s of a `bf-tab-bar` from one array of destinations.
|
|
361
|
+
- **Breadcrumb:** `<bf-breadcrumb>` of `<li bfBreadcrumbItem><a routerLink>…</a></li>`, the
|
|
362
|
+
current page last as plain text (marked `aria-current="page"`); `maxItems` collapses a long
|
|
363
|
+
trail, and a `bfSlot="overflow"` `bf-menu-button` turns the collapse into a menu. On mobile it is
|
|
364
|
+
`bf-back-button` in `bf-header`.
|
|
365
|
+
- **Page header:** `<bf-page-header title="…" subtitle="…">` with the breadcrumb in
|
|
366
|
+
`bfSlot="breadcrumb"`, badges in `bfSlot="meta"` and the actions in `bfSlot="actions"` (the main
|
|
367
|
+
action a primary `bf-button`, secondary ones `ghost`, the rest in an icon-only `bf-menu-button`).
|
|
368
|
+
An icon-only link (back, open, edit) is `a[bfIconButton]`.
|
|
369
|
+
- **Toolbar:** `<bf-toolbar label="…" [status]="count">` under the page header: search and filters
|
|
370
|
+
in the default slot, a view switch in `bfSlot="view"`, actions in `bfSlot="actions"`; its
|
|
371
|
+
controls default to `sm`, and `status` is a polite live region for the result count.
|
|
372
|
+
- **Table:** `<bf-table [rows] [columns] [(sort)] selectable [(selection)]>` with
|
|
373
|
+
`ng-template[bfTableCell]` for rich cells and `bfSlot="empty"` for the empty state; the app
|
|
374
|
+
sorts the rows in a `computed()`, and a selection shows a `bf-action-bar`. `stack="narrow"`
|
|
375
|
+
(below 36rem of its own width) or `stack="coarse"` turns each row into a label/value tile with
|
|
376
|
+
a sort and select bar; in the Capacitor shell use `bf-list-item` rows instead.
|
|
377
|
+
- **Details:** `bf-description-list` of `div[bfDescriptionItem]` label/value pairs, and `bf-stat`
|
|
378
|
+
figure tiles in a grid; both work in both shells.
|
|
379
|
+
- **Cards in a grid:** the grid stretches each `bf-card` and its `bfSlot="footer"` sits on the
|
|
380
|
+
bottom edge, so footers line up; put a footer's parts in one element.
|
|
381
|
+
- **Rows on a card:** `<bf-list [inset]="false" divided class="-mx-card">`, flush to the card's
|
|
382
|
+
edges with lines between the rows.
|
|
383
|
+
- **Theme switch:** `<bf-theme-switch [(value)]="colorScheme.scheme" />` (or
|
|
384
|
+
`bf-theme-menu-button` from `/overlay` in a crowded top bar) with `provideBfColorScheme()` (see
|
|
385
|
+
"Colour scheme").
|
|
386
|
+
- **Tabs in a page:** `<bf-tab-group [(selected)]="tab">` of `<bf-tab-panel value="…" label="…">`
|
|
387
|
+
(content in an `ng-template` inside renders only while shown). Not `bf-tabs`/`bf-tab-bar` (the
|
|
388
|
+
shell's bottom tabs), and not for routes (use `bf-top-nav` links).
|
|
389
|
+
- **Paging and loading:** `<bf-pagination [(page)]="page" [total]="count" [pageSize]="20">` under a
|
|
390
|
+
`bf-table` (the app slices its rows); `bf-skeleton` (`shape` text/rect/circle, `lines`) as the
|
|
391
|
+
placeholder while data loads, inside a region with `aria-busy="true"`.
|
|
392
|
+
- **Dates and times:** `<bf-calendar [(value)]="date">` for an inline month view;
|
|
393
|
+
`bf-date-input`, `bf-time-input` and `bf-datetime-input` (`/overlay`) for a field: typed parts
|
|
394
|
+
in locale order plus a calendar or time-list popover (`picker="none"` for typed only, `native`
|
|
395
|
+
for the platform picker on touch). Values are ISO strings (`'2026-10-28'`, `'14:30'`,
|
|
396
|
+
`'2026-10-28T14:30'`); month and day names come from `Intl` in the document's language.
|
|
397
|
+
- **Picking from many options:** `bf-combobox` (`/overlay`) for one value with search, groups and
|
|
398
|
+
server search (`queried`, `loading`); `bf-multi-combobox` for tags. `bf-select` stays the choice
|
|
399
|
+
for a short fixed list.
|
|
400
|
+
- **Dashboards:** `bf-stat` with `delta`, `trend` and `trendIntent` for a figure and its change;
|
|
401
|
+
`@bitforgehq/ui/charts` for `bf-line-chart`, `bf-bar-chart`, `bf-donut-chart` and
|
|
402
|
+
`bf-sparkline` inside a `bf-chart-card` (title, period slot, loading, empty and error states),
|
|
403
|
+
themed by the `chart-1`…`chart-8` tokens. Every chart takes a `label` and offers its data as a
|
|
404
|
+
table.
|
|
405
|
+
- **Surfaces:** one surface style per level. A raised `bf-card` holds sunken tiles
|
|
406
|
+
(`bf-stat variant="tile"`), never an outlined surface (`variant="card"` or a `flat` card) inside
|
|
407
|
+
a raised one; next to raised cards on a dashboard, use raised cards.
|
|
408
|
+
- **Empty pages:** a 404, "no access" or "nothing here yet" page is a `bf-empty-state` with
|
|
409
|
+
`headingLevel` 1, centred in the content area, with the main action and an optional link.
|
|
410
|
+
- **Toolbar on a phone:** `bf-toolbar` keeps its status and actions together on the last row.
|
|
411
|
+
|
|
305
412
|
## Overlays (`@bitforgehq/ui/overlay`)
|
|
306
413
|
|
|
307
414
|
A desktop or plain web app (no Capacitor, no router required) installs `@angular/cdk` and `rxjs`
|
|
@@ -331,6 +438,13 @@ injector? })` stacks up to three cards bottom-right (configurable with
|
|
|
331
438
|
keys, arrow navigation with wrap, Home/End, type-ahead, `Escape`/`Tab` close with focus back on
|
|
332
439
|
the trigger, `ArrowRight`/`ArrowLeft` for submenus. A menu opened from inside a `bf-dialog`:
|
|
333
440
|
`Escape` closes only the menu, never the dialog underneath.
|
|
441
|
+
- **Tooltip and popover:** `[bfTooltip]="'Text'"` on a focusable element shows a short hint on
|
|
442
|
+
hover and keyboard focus (never on touch, never the only place the information lives).
|
|
443
|
+
`[bfPopoverTriggerFor]="panel"` opens a non-modal `bf-popover` panel anchored to its button
|
|
444
|
+
(filters, details); focus moves in, `Escape` and an outside click close it.
|
|
445
|
+
- **Side panel:** `BfSidePanelService.open(component | template, { width, modal, data })` slides a
|
|
446
|
+
full-height `bf-side-panel` in from the inline end: a record's details or edit form beside the
|
|
447
|
+
list. `modal: false` keeps the page usable. In the Capacitor shell use `bf-sheet`/`bf-modal`.
|
|
334
448
|
- **`closeOnNavigation`:** every overlay (`BfDialogConfig`, `confirm()`, and the `/mobile` sheet,
|
|
335
449
|
modal, action sheet and alert options) closes when the URL path changes by default (`true`);
|
|
336
450
|
pass `closeOnNavigation: false` to keep one open across a navigation (e.g. a draft that must
|
|
@@ -862,7 +976,7 @@ describe('bf-button in a consumer app (Vitest)', () => {
|
|
|
862
976
|
|
|
863
977
|
### 6. Drive a form widget through its harness
|
|
864
978
|
|
|
865
|
-
The entry ships CDK harnesses for the widgets whose markup is not obvious to drive: `BfSelectHarness`, `BfRadioGroupHarness`, `BfSegmentedHarness`, `BfDialogHarness`, `BfMenuHarness`, `BfMenuItemHarness`, `BfMenuButtonHarness` and `
|
|
979
|
+
The entry ships CDK harnesses for the widgets whose markup is not obvious to drive: `BfSelectHarness`, `BfRadioGroupHarness`, `BfSegmentedHarness`, `BfDialogHarness`, `BfMenuHarness`, `BfMenuItemHarness`, `BfMenuButtonHarness`, `BfDesktopToastHarness`, `BfTableHarness`, `BfPaginationHarness` `BfTabGroupHarness`, `BfCalendarHarness` and `BfChartHarness`. `with({ label })` finds a widget by its label. Load an in-page widget with `TestbedHarnessEnvironment.loader(fixture)`.
|
|
866
980
|
|
|
867
981
|
`select-harness.spec.ts`:
|
|
868
982
|
|
|
@@ -1048,10 +1162,16 @@ Don't assert on the library's CSS classes or internal markup. They are styling d
|
|
|
1048
1162
|
|
|
1049
1163
|
## Design foundations (Meadow Sage)
|
|
1050
1164
|
|
|
1051
|
-
Warm off-white canvas (`bg-bg`), white surfaces,
|
|
1165
|
+
Warm off-white canvas (`bg-bg`), white surfaces, a neutral indigo default primary
|
|
1166
|
+
(`#2b26ba`), pill-shaped controls,
|
|
1052
1167
|
radii 12/16/24 px (`rounded-tile/field/card`), 1.5 px control borders, soft layered shadows
|
|
1053
1168
|
(`shadow-raised`, `shadow-floating`), Manrope type (`text-display/title/heading/body/caption`).
|
|
1054
1169
|
|
|
1170
|
+
The palette is Meadow Sage, but the primary is not its sage green: the indigo default is neutral
|
|
1171
|
+
on purpose and meant to be overridden with the app's brand colour (`--color-primary` and the rest
|
|
1172
|
+
of its set, in `@theme` and `.dark`). An indigo primary right after install is expected; it does
|
|
1173
|
+
not mean the theme failed to load.
|
|
1174
|
+
|
|
1055
1175
|
### Type and spacing scale
|
|
1056
1176
|
|
|
1057
1177
|
- Type (rem tokens; px at a 16 px root): `text-display` 40, `text-title` 28, `text-heading` 18,
|
|
@@ -1076,33 +1196,50 @@ notes.
|
|
|
1076
1196
|
| `bf-action-bar` | `@bitforgehq/ui` | Floating pill of contextual actions that appears while items are selected |
|
|
1077
1197
|
| `bf-button` | `@bitforgehq/ui` | Pill-shaped action button with five variants, three sizes and a loading state |
|
|
1078
1198
|
| `bf-icon-button` | `@bitforgehq/ui` | Round icon-only button for toolbars and rows, with a required accessible label |
|
|
1199
|
+
| `bf-toolbar` | `@bitforgehq/ui` | Dense row of search, filters, view switch, result count and actions |
|
|
1079
1200
|
|
|
1080
1201
|
### Forms
|
|
1081
1202
|
|
|
1082
|
-
| Component
|
|
1083
|
-
|
|
|
1084
|
-
| `bf-
|
|
1085
|
-
| `bf-
|
|
1086
|
-
| `bf-chip
|
|
1087
|
-
| `bf-
|
|
1088
|
-
| `bf-
|
|
1089
|
-
| `bf-
|
|
1090
|
-
| `bf-
|
|
1091
|
-
| `bf-
|
|
1092
|
-
| `bf-
|
|
1093
|
-
| `bf-
|
|
1094
|
-
| `bf-
|
|
1203
|
+
| Component | Entry point | Purpose |
|
|
1204
|
+
| ------------------- | ----------------------------- | ------------------------------------------------------------------------------------------- |
|
|
1205
|
+
| `bf-calendar` | `@bitforgehq/ui` | Inline month calendar for picking one date, with month and year jumps |
|
|
1206
|
+
| `bf-checkbox` | `@bitforgehq/ui` | Rounded checkbox with an optional label that binds to Signal Forms |
|
|
1207
|
+
| `bf-chip` | `@bitforgehq/ui` | Toggleable filter chip with a check mark when selected, in tonal or ink style |
|
|
1208
|
+
| `bf-chip-group` | `@bitforgehq/ui` | Named row of chips that picks one like radios, or groups independent toggles |
|
|
1209
|
+
| `bf-combobox` | `@bitforgehq/ui/overlay` | Text field that filters a list of options as you type and picks one |
|
|
1210
|
+
| `bf-date-input` | `@bitforgehq/ui/overlay` | Typed date field with a calendar popover, valued as an ISO date string |
|
|
1211
|
+
| `bf-datetime-input` | `@bitforgehq/ui/overlay` | Typed date and time field with a calendar and time list in one popover |
|
|
1212
|
+
| `bf-field` | `@bitforgehq/ui` | Label, help text and error text wrapper that wires ids for assistive tech |
|
|
1213
|
+
| `bf-input` | `@bitforgehq/ui` | Single-line text field with label, help and error text, icon slots and Signal Forms binding |
|
|
1214
|
+
| `bf-multi-combobox` | `@bitforgehq/ui/overlay` | Text field that filters options as you type and picks several as tags |
|
|
1215
|
+
| `bf-number-input` | `@bitforgehq/ui/number-input` | Number field that binds number or null, with native min, max and step |
|
|
1216
|
+
| `bf-radio-group` | `@bitforgehq/ui` | Group of radio buttons for choosing one option, with optional per-option descriptions |
|
|
1217
|
+
| `bf-segmented` | `@bitforgehq/ui` | Segmented control for switching between two to four views, keyboard-navigable like radios |
|
|
1218
|
+
| `bf-select` | `@bitforgehq/ui` | Native single-choice dropdown styled like the text field, with Signal Forms binding |
|
|
1219
|
+
| `bf-textarea` | `@bitforgehq/ui` | Multi-line text field with label, help and error text, and Signal Forms binding |
|
|
1220
|
+
| `bf-theme-switch` | `@bitforgehq/ui` | Segmented System, Light and Dark switch bound two-way to the app colour scheme |
|
|
1221
|
+
| `bf-time-input` | `@bitforgehq/ui/overlay` | Typed time-of-day field with a popover list of times, valued as an ISO string |
|
|
1222
|
+
| `bf-toggle` | `@bitforgehq/ui` | On/off switch for settings that apply immediately, with Signal Forms binding |
|
|
1095
1223
|
|
|
1096
1224
|
### Data display
|
|
1097
1225
|
|
|
1098
|
-
| Component
|
|
1099
|
-
|
|
|
1100
|
-
| `bf-avatar`
|
|
1101
|
-
| `bf-badge`
|
|
1102
|
-
| `bf-
|
|
1103
|
-
| `bf-
|
|
1104
|
-
| `bf-
|
|
1105
|
-
| `
|
|
1226
|
+
| Component | Entry point | Purpose |
|
|
1227
|
+
| ------------------------ | ----------------------- | --------------------------------------------------------------------------------------- |
|
|
1228
|
+
| `bf-avatar` | `@bitforgehq/ui` | Round avatar showing a photo or initials, in three sizes and four color variants |
|
|
1229
|
+
| `bf-badge` | `@bitforgehq/ui` | Small status label in semantic tones, or a compact numeric pill for counts |
|
|
1230
|
+
| `bf-bar-chart` | `@bitforgehq/ui/charts` | Bar chart of series over categories, grouped or stacked, vertical or horizontal |
|
|
1231
|
+
| `bf-card` | `@bitforgehq/ui` | Content surface with an optional header slot, in four visual styles from raised to flat |
|
|
1232
|
+
| `bf-chart-card` | `@bitforgehq/ui/charts` | Card around one chart with a title, period control and loading, empty and error states |
|
|
1233
|
+
| `div[bfDescriptionItem]` | `@bitforgehq/ui` | One label and value pair of a description list, label as term, content as value |
|
|
1234
|
+
| `bf-description-list` | `@bitforgehq/ui` | Native description list of label-value pairs, as divided rows or a tile grid |
|
|
1235
|
+
| `bf-donut-chart` | `@bitforgehq/ui/charts` | Donut chart of the parts of a whole, with a legend, tooltip and centre slot |
|
|
1236
|
+
| `bf-line-chart` | `@bitforgehq/ui/charts` | Line chart of series over categories, with tooltip, legend and data table |
|
|
1237
|
+
| `bf-list` | `@bitforgehq/ui` | Container for list rows, inset by default with rounded corners on a warm background |
|
|
1238
|
+
| `bf-list-item` | `@bitforgehq/ui` | List row with leading slot, title, subtitle, trailing slot and an optional chevron |
|
|
1239
|
+
| `bf-progress` | `@bitforgehq/ui` | Progress bar in two sizes and four tones for completion, quotas and unknown waits |
|
|
1240
|
+
| `bf-sparkline` | `@bitforgehq/ui/charts` | Tiny trend line with no axes or legend, for stats and table cells |
|
|
1241
|
+
| `bf-stat` | `@bitforgehq/ui` | One labelled figure with an optional icon tile and a supporting line |
|
|
1242
|
+
| `bf-table` | `@bitforgehq/ui` | Desktop data table with sortable headers, row selection, custom cells and an empty slot |
|
|
1106
1243
|
|
|
1107
1244
|
### Feedback
|
|
1108
1245
|
|
|
@@ -1110,35 +1247,52 @@ notes.
|
|
|
1110
1247
|
| ---------------- | ---------------- | ---------------------------------------------------------------------------------- |
|
|
1111
1248
|
| `bf-alert` | `@bitforgehq/ui` | Inline status message in four tones with a title and an optional dismiss button |
|
|
1112
1249
|
| `bf-empty-state` | `@bitforgehq/ui` | Placeholder for an empty screen or list with icon, title, message and action |
|
|
1250
|
+
| `bf-skeleton` | `@bitforgehq/ui` | Loading placeholder shaped as text lines, a rectangle or a circle, with a shimmer |
|
|
1113
1251
|
| `bf-spinner` | `@bitforgehq/ui` | Indeterminate loading spinner in three sizes that inherits its parent's text color |
|
|
1114
1252
|
|
|
1115
1253
|
### Navigation
|
|
1116
1254
|
|
|
1117
|
-
| Component
|
|
1118
|
-
|
|
|
1119
|
-
| `bf-
|
|
1120
|
-
| `bf-
|
|
1121
|
-
| `bf-
|
|
1122
|
-
| `
|
|
1123
|
-
| `bf-
|
|
1124
|
-
| `bf-
|
|
1125
|
-
| `bf-
|
|
1126
|
-
| `
|
|
1127
|
-
| `bf-
|
|
1255
|
+
| Component | Entry point | Purpose |
|
|
1256
|
+
| ---------------------- | ------------------------ | ------------------------------------------------------------------------------------------- |
|
|
1257
|
+
| `bf-app-frame` | `@bitforgehq/ui` | Desktop app frame with skip link, sticky sidebar, narrow header and main content |
|
|
1258
|
+
| `bf-back-button` | `@bitforgehq/ui/mobile` | Header back button that pops the page stack or falls back to a default route |
|
|
1259
|
+
| `bf-breadcrumb` | `@bitforgehq/ui` | Desktop breadcrumb trail of links to the current page, with optional collapsing |
|
|
1260
|
+
| `li[bfBreadcrumbItem]` | `@bitforgehq/ui` | One level of a breadcrumb trail: a link, or the current page as text |
|
|
1261
|
+
| `bf-content` | `@bitforgehq/ui/mobile` | Page's single scroll container that keeps focused fields clear of the soft keyboard |
|
|
1262
|
+
| `bf-header` | `@bitforgehq/ui/mobile` | Page header toolbar with a large title that collapses into the toolbar on scroll |
|
|
1263
|
+
| `bf-nav-group` | `@bitforgehq/ui` | A titled group of sidebar links with a small heading that names it |
|
|
1264
|
+
| `a[bfNavItem]` | `@bitforgehq/ui` | Navigation link for a sidebar or top nav, with icon, label and count |
|
|
1265
|
+
| `bf-page` | `@bitforgehq/ui/mobile` | Frame for one stacked mobile screen that supplies lifecycle events and shared page state |
|
|
1266
|
+
| `bf-page-header` | `@bitforgehq/ui` | Desktop page header with breadcrumb, title, subtitle, badges and a row of actions |
|
|
1267
|
+
| `bf-pagination` | `@bitforgehq/ui` | Previous, next and numbered page buttons for a long list or table |
|
|
1268
|
+
| `bf-refresher` | `@bitforgehq/ui/mobile` | Pull-to-refresh indicator with haptic feedback, native iOS bounce and an Android-style pull |
|
|
1269
|
+
| `bf-sidebar` | `@bitforgehq/ui` | Vertical app navigation with brand, grouped links, footer and an icon rail mode |
|
|
1270
|
+
| `bf-sidebar-toggle` | `@bitforgehq/ui/overlay` | Icon button inside a sidebar that collapses it to an icon rail and back |
|
|
1271
|
+
| `bf-stack-outlet` | `@bitforgehq/ui/mobile` | Router outlet keeping a live page stack with slide transitions and iOS swipe back |
|
|
1272
|
+
| `bf-tab` | `@bitforgehq/ui` | One tab bar destination with an icon, a label and an optional count badge |
|
|
1273
|
+
| `bf-tab-bar` | `@bitforgehq/ui` | Floating pill tab bar for mobile apps with arrow-key selection and count badges |
|
|
1274
|
+
| `bf-tab-group` | `@bitforgehq/ui` | In-page tabs that switch between content panels, with keyboard navigation and badges |
|
|
1275
|
+
| `bf-tab-panel` | `@bitforgehq/ui` | One tab of a tab group with its label, badge, icon and lazy content |
|
|
1276
|
+
| `bf-tabs` | `@bitforgehq/ui/mobile` | Tabs page with one navigation stack per tab, wiring the tab bar to the router |
|
|
1277
|
+
| `bf-top-nav` | `@bitforgehq/ui` | Horizontal app navigation, a wrapping row of links for apps with few sections |
|
|
1128
1278
|
|
|
1129
1279
|
### Overlays
|
|
1130
1280
|
|
|
1131
|
-
| Component
|
|
1132
|
-
|
|
|
1133
|
-
| `bf-action-sheet`
|
|
1134
|
-
| `bf-alert-dialog`
|
|
1135
|
-
| `bf-desktop-toast`
|
|
1136
|
-
| `bf-dialog`
|
|
1137
|
-
| `bf-menu`
|
|
1138
|
-
| `bf-menu-button`
|
|
1139
|
-
| `bf-modal`
|
|
1140
|
-
| `bf-
|
|
1141
|
-
| `bf-
|
|
1281
|
+
| Component | Entry point | Purpose |
|
|
1282
|
+
| ---------------------- | ------------------------ | --------------------------------------------------------------------------------------------- |
|
|
1283
|
+
| `bf-action-sheet` | `@bitforgehq/ui/mobile` | Bottom panel of labelled actions with a separate cancel button, destructive ones shown in red |
|
|
1284
|
+
| `bf-alert-dialog` | `@bitforgehq/ui/mobile` | Centred confirmation dialog with a title, message and a row of role-styled buttons |
|
|
1285
|
+
| `bf-desktop-toast` | `@bitforgehq/ui/overlay` | Desktop notification card in a bottom corner stack of up to three |
|
|
1286
|
+
| `bf-dialog` | `@bitforgehq/ui/overlay` | Desktop modal dialog with a title, scrolling body, footer actions and focus trap |
|
|
1287
|
+
| `bf-menu` | `@bitforgehq/ui/overlay` | Keyboard-operable menu panel with items, checkbox and radio items, groups and submenus |
|
|
1288
|
+
| `bf-menu-button` | `@bitforgehq/ui/overlay` | Styled button that opens a menu, with outline, text, tonal and icon-only looks |
|
|
1289
|
+
| `bf-modal` | `@bitforgehq/ui/mobile` | Modal overlay shown as an inset card over the scaled-down page, or full screen |
|
|
1290
|
+
| `bf-popover` | `@bitforgehq/ui/overlay` | Anchored, non-modal panel for filters, details or a small form |
|
|
1291
|
+
| `bf-sheet` | `@bitforgehq/ui/mobile` | Bottom sheet with snap points, drag to dismiss and a backdrop |
|
|
1292
|
+
| `bf-side-panel` | `@bitforgehq/ui/overlay` | Desktop panel sliding in from the end edge, with a title, body and footer actions |
|
|
1293
|
+
| `bf-theme-menu-button` | `@bitforgehq/ui/overlay` | Menu button with System, Light and Dark radio items bound to the colour scheme |
|
|
1294
|
+
| `bf-toast` | `@bitforgehq/ui/mobile` | Passive status pill with an optional action that never steals focus |
|
|
1295
|
+
| `bf-tooltip` | `@bitforgehq/ui/overlay` | Short hint beside a control on hover or keyboard focus, for desktop |
|
|
1142
1296
|
|
|
1143
1297
|
### Icons
|
|
1144
1298
|
|