@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.
Files changed (158) hide show
  1. package/CHANGELOG.md +598 -0
  2. package/README.md +18 -11
  3. package/ai/MANIFEST.index.json +306 -0
  4. package/ai/MANIFEST.json +8915 -3788
  5. package/ai/REFERENCE.index.json +476 -0
  6. package/ai/REFERENCE.json +5810 -2905
  7. package/ai/UI_GUIDE.md +212 -58
  8. package/ai/components/app-frame.md +328 -0
  9. package/ai/components/back-button.md +42 -2
  10. package/ai/components/badge.md +17 -7
  11. package/ai/components/bar-chart.md +188 -0
  12. package/ai/components/breadcrumb-item.md +121 -0
  13. package/ai/components/breadcrumb.md +277 -0
  14. package/ai/components/button.md +82 -15
  15. package/ai/components/calendar.md +300 -0
  16. package/ai/components/card.md +119 -4
  17. package/ai/components/chart-card.md +283 -0
  18. package/ai/components/combobox.md +411 -0
  19. package/ai/components/date-input.md +396 -0
  20. package/ai/components/datetime-input.md +215 -0
  21. package/ai/components/description-item.md +111 -0
  22. package/ai/components/description-list.md +160 -0
  23. package/ai/components/donut-chart.md +169 -0
  24. package/ai/components/empty-state.md +99 -6
  25. package/ai/components/header.md +71 -2
  26. package/ai/components/icon-button.md +74 -16
  27. package/ai/components/icon.md +63 -7
  28. package/ai/components/line-chart.md +234 -0
  29. package/ai/components/list.md +70 -6
  30. package/ai/components/menu.md +5 -0
  31. package/ai/components/multi-combobox.md +257 -0
  32. package/ai/components/nav-group.md +178 -0
  33. package/ai/components/nav-item.md +210 -0
  34. package/ai/components/page-header.md +237 -0
  35. package/ai/components/pagination.md +173 -0
  36. package/ai/components/popover.md +250 -0
  37. package/ai/components/side-panel.md +391 -0
  38. package/ai/components/sidebar-toggle.md +287 -0
  39. package/ai/components/sidebar.md +541 -0
  40. package/ai/components/skeleton.md +215 -0
  41. package/ai/components/sparkline.md +188 -0
  42. package/ai/components/stat.md +297 -0
  43. package/ai/components/tab-group.md +226 -0
  44. package/ai/components/tab-panel.md +163 -0
  45. package/ai/components/table.md +697 -0
  46. package/ai/components/tabs.md +46 -2
  47. package/ai/components/theme-menu-button.md +182 -0
  48. package/ai/components/theme-switch.md +170 -0
  49. package/ai/components/time-input.md +240 -0
  50. package/ai/components/toolbar.md +354 -0
  51. package/ai/components/tooltip.md +230 -0
  52. package/ai/components/top-nav.md +159 -0
  53. package/ai/reference/bf-app-frame-breakpoint.md +27 -0
  54. package/ai/reference/bf-app-frame-content-width.md +29 -0
  55. package/ai/reference/bf-badge-appearance.md +36 -0
  56. package/ai/reference/bf-badge-variant.md +1 -1
  57. package/ai/reference/bf-bar-chart-orientation.md +27 -0
  58. package/ai/reference/bf-button-appearance.md +36 -0
  59. package/ai/reference/bf-button-variant.md +1 -1
  60. package/ai/reference/bf-calendar-disabled-date.md +23 -0
  61. package/ai/reference/bf-calendar-harness.md +51 -0
  62. package/ai/reference/bf-calendar-weekday.md +31 -0
  63. package/ai/reference/bf-chart-card-heading-level.md +26 -0
  64. package/ai/reference/bf-chart-curve.md +28 -0
  65. package/ai/reference/bf-chart-harness.md +51 -0
  66. package/ai/reference/bf-chart-legend-position.md +30 -0
  67. package/ai/reference/bf-chart-series.md +23 -0
  68. package/ai/reference/bf-chart-value-format.md +23 -0
  69. package/ai/reference/bf-color-scheme-service.md +30 -0
  70. package/ai/reference/bf-color-scheme.md +31 -0
  71. package/ai/reference/bf-combobox-filter.md +27 -0
  72. package/ai/reference/bf-combobox-harness.md +89 -0
  73. package/ai/reference/bf-combobox-option.md +33 -0
  74. package/ai/reference/bf-compare-with.md +2 -0
  75. package/ai/reference/bf-date-input-harness.md +67 -0
  76. package/ai/reference/bf-date-input-picker.md +27 -0
  77. package/ai/reference/bf-date-time-input-harness.md +76 -0
  78. package/ai/reference/bf-date-time-input-picker.md +27 -0
  79. package/ai/reference/bf-description-list-layout.md +26 -0
  80. package/ai/reference/bf-donut-slice.md +22 -0
  81. package/ai/reference/bf-empty-state-heading-level.md +1 -1
  82. package/ai/reference/bf-empty-state-heading.md +33 -0
  83. package/ai/reference/bf-labels.md +73 -20
  84. package/ai/reference/bf-menu-button-variant.md +1 -0
  85. package/ai/reference/bf-menu-placement.md +1 -0
  86. package/ai/reference/bf-overlay-options.md +28 -27
  87. package/ai/reference/bf-overlay-placement.md +34 -0
  88. package/ai/reference/bf-overlay-position.md +1 -1
  89. package/ai/reference/bf-overlay-service.md +5 -3
  90. package/ai/reference/bf-page-header-heading-level.md +26 -0
  91. package/ai/reference/bf-pagination-harness.md +61 -0
  92. package/ai/reference/bf-platform-service.md +17 -15
  93. package/ai/reference/bf-popover-harness.md +42 -0
  94. package/ai/reference/bf-popover-placement.md +28 -0
  95. package/ai/reference/bf-popover-trigger-directive.md +56 -0
  96. package/ai/reference/bf-side-panel-config.md +35 -0
  97. package/ai/reference/bf-side-panel-harness.md +34 -0
  98. package/ai/reference/bf-side-panel-ref.md +44 -0
  99. package/ai/reference/bf-side-panel-service.md +43 -0
  100. package/ai/reference/bf-side-panel-template-context.md +32 -0
  101. package/ai/reference/bf-side-panel-width.md +28 -0
  102. package/ai/reference/bf-sidebar-state-service.md +21 -0
  103. package/ai/reference/bf-sidebar-toggle-harness.md +32 -0
  104. package/ai/reference/bf-size.md +13 -0
  105. package/ai/reference/bf-skeleton-shape.md +28 -0
  106. package/ai/reference/bf-stat-appearance.md +33 -0
  107. package/ai/reference/bf-stat-trend-intent.md +27 -0
  108. package/ai/reference/bf-stat-trend.md +27 -0
  109. package/ai/reference/bf-stat-variant.md +26 -0
  110. package/ai/reference/bf-tab-group-harness.md +44 -0
  111. package/ai/reference/bf-table-align.md +26 -0
  112. package/ai/reference/bf-table-cell-context.md +24 -0
  113. package/ai/reference/bf-table-cell-directive.md +22 -0
  114. package/ai/reference/bf-table-column.md +28 -0
  115. package/ai/reference/bf-table-harness.md +77 -0
  116. package/ai/reference/bf-table-row-key.md +21 -0
  117. package/ai/reference/bf-table-sort-direction.md +26 -0
  118. package/ai/reference/bf-table-sort.md +27 -0
  119. package/ai/reference/bf-table-stack.md +29 -0
  120. package/ai/reference/bf-theme.md +5 -4
  121. package/ai/reference/bf-time-input-harness.md +67 -0
  122. package/ai/reference/bf-time-input-hour-cycle.md +27 -0
  123. package/ai/reference/bf-time-input-picker.md +27 -0
  124. package/ai/reference/bf-tooltip-directive.md +43 -0
  125. package/ai/reference/bf-tooltip-harness.md +43 -0
  126. package/ai/reference/bf-tooltip-placement.md +28 -0
  127. package/ai/reference/bf_color_scheme_storage.md +20 -0
  128. package/ai/reference/bf_side_panel_data.md +17 -0
  129. package/ai/reference/bf_sidebar_state_storage.md +20 -0
  130. package/ai/reference/bf_theme_storage.md +3 -1
  131. package/ai/reference/provide-bf-color-scheme.md +20 -0
  132. package/ai/reference/provide-bf-labels.md +13 -4
  133. package/ai/reference/provide-bf-sidebar-state.md +20 -0
  134. package/ai/reference/slide-in-from-end.md +24 -0
  135. package/ai/reference/slide-out-to-end.md +24 -0
  136. package/bin/bf-ui.js +433 -3
  137. package/fesm2022/bitforgehq-ui-charts.mjs +3045 -0
  138. package/fesm2022/bitforgehq-ui-charts.mjs.map +1 -0
  139. package/fesm2022/bitforgehq-ui-icons.mjs +107 -3
  140. package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -1
  141. package/fesm2022/bitforgehq-ui-mobile.mjs +14 -59
  142. package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
  143. package/fesm2022/bitforgehq-ui-overlay.mjs +6566 -38
  144. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
  145. package/fesm2022/bitforgehq-ui-testing.mjs +634 -1
  146. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  147. package/fesm2022/bitforgehq-ui.mjs +5708 -137
  148. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  149. package/llms-full.txt +26766 -14470
  150. package/llms.txt +106 -1
  151. package/package.json +7 -3
  152. package/theme.css +101 -0
  153. package/types/bitforgehq-ui-charts.d.ts +967 -0
  154. package/types/bitforgehq-ui-icons.d.ts +13 -1
  155. package/types/bitforgehq-ui-mobile.d.ts +25 -18
  156. package/types/bitforgehq-ui-overlay.d.ts +1895 -7
  157. package/types/bitforgehq-ui-testing.d.ts +782 -1
  158. package/types/bitforgehq-ui.d.ts +2393 -45
@@ -0,0 +1,230 @@
1
+ # bf-tooltip
2
+
3
+ Short hint beside a control on hover or keyboard focus, for desktop
4
+
5
+ `BfTooltipComponent` from `@bitforgehq/ui/overlay` · Overlays · since 0.3.1
6
+
7
+ ## Example
8
+
9
+ ```ts
10
+ import { Component, signal } from '@angular/core';
11
+ import { BfIconButtonComponent } from '@bitforgehq/ui';
12
+ import { BfIconComponent } from '@bitforgehq/ui/icons';
13
+ import { BfTooltipDirective } from '@bitforgehq/ui/overlay';
14
+ import { Bold, Italic, Link, Underline } from 'lucide';
15
+
16
+ /**
17
+ * The bf-tooltip overview.
18
+ *
19
+ * Live demo of `bfTooltip`: a formatting toolbar of icon buttons, each named by its `label` and
20
+ * showing the same name, with its keyboard shortcut, in a tooltip on hover or keyboard focus. The
21
+ * result line reports each press.
22
+ */
23
+ @Component({
24
+ selector: 'app-example-tooltip-overview',
25
+ imports: [BfIconButtonComponent, BfIconComponent, BfTooltipDirective],
26
+ template: `
27
+ <div class="flex flex-col gap-3">
28
+ <div role="group" aria-label="Formatting" class="flex flex-wrap items-center gap-2">
29
+ <bf-icon-button
30
+ label="Bold"
31
+ variant="text"
32
+ bfTooltip="Bold (Ctrl+B)"
33
+ (clicked)="press('Bold')"
34
+ >
35
+ <bf-icon [icon]="bold" />
36
+ </bf-icon-button>
37
+ <bf-icon-button
38
+ label="Italic"
39
+ variant="text"
40
+ bfTooltip="Italic (Ctrl+I)"
41
+ (clicked)="press('Italic')"
42
+ >
43
+ <bf-icon [icon]="italic" />
44
+ </bf-icon-button>
45
+ <bf-icon-button
46
+ label="Underline"
47
+ variant="text"
48
+ bfTooltip="Underline (Ctrl+U)"
49
+ (clicked)="press('Underline')"
50
+ >
51
+ <bf-icon [icon]="underline" />
52
+ </bf-icon-button>
53
+ <bf-icon-button
54
+ label="Insert link"
55
+ variant="text"
56
+ bfTooltip="Insert link (Ctrl+K)"
57
+ (clicked)="press('Insert link')"
58
+ >
59
+ <bf-icon [icon]="link" />
60
+ </bf-icon-button>
61
+ </div>
62
+ <p data-status aria-live="polite" class="text-caption text-text-muted">{{ status() }}</p>
63
+ </div>
64
+ `,
65
+ })
66
+ export class TooltipOverviewExampleComponent {
67
+ readonly bold = Bold;
68
+ readonly italic = Italic;
69
+ readonly underline = Underline;
70
+ readonly link = Link;
71
+ readonly status = signal('Hover or tab to a button for its tooltip.');
72
+
73
+ press(label: string): void {
74
+ this.status.set(`Pressed ${label}.`);
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Overview
80
+
81
+ The small dark pill of a tooltip (role `tooltip`). A `[bfTooltip]` directive renders it in the
82
+ CDK overlay beside its element while the pointer rests on it or it has keyboard focus, so you
83
+ rarely place it yourself; the directive is how you add a tooltip.
84
+
85
+ Short hints for desktop and web apps, from `@bitforgehq/ui/overlay` (needs `@angular/cdk`, no
86
+ Capacitor). Put `bfTooltip="Text"` on a control and a small dark `bf-tooltip` pill shows beside it
87
+ when a mouse rests on it for half a second, or at once when it gets keyboard focus. It hides when
88
+ the pointer leaves, on blur and on `Escape`. While it shows, the control is described by it
89
+ (`aria-describedby`), so a screen reader reads the hint after the control's name. The pill
90
+ renders in the CDK overlay container, so it works inside a `BfDialogService` dialog.
91
+
92
+ Import `BfTooltipDirective` from `@bitforgehq/ui/overlay`. You rarely place `bf-tooltip`
93
+ (`BfTooltipComponent`) yourself: the directive renders it.
94
+
95
+ ## When to use
96
+
97
+ Use a tooltip to repeat the name of an icon-only control (`bf-icon-button`, a collapsed sidebar
98
+ link) for mouse users, or to add a keyboard shortcut to it. A tooltip never holds information
99
+ found nowhere else: touch screens never show it, so the control's own name and the page must say
100
+ everything that matters. Use [bf-popover](https://bitforge-ui.web.app/components/popover) instead for content a user reads at
101
+ length or interacts with (links, fields, buttons), [bf-field](https://bitforge-ui.web.app/components/field) help text for
102
+ guidance on a form field, and in a Capacitor app the control's visible label.
103
+
104
+ ## Placement
105
+
106
+ `bfTooltipPlacement` puts the tooltip on the `top` (default), `bottom`, `start` or `end` side of
107
+ its element, centred along it, 8 px away. `start` and `end` follow the text direction, so they
108
+ swap sides in right-to-left pages. A tooltip without room on its side flips to the opposite side
109
+ first, then to the other two. The placement is read each time the tooltip shows.
110
+
111
+ ```ts
112
+ import { Component } from '@angular/core';
113
+ import { BfButtonComponent } from '@bitforgehq/ui';
114
+ import { BfTooltipDirective, type BfTooltipPlacement } from '@bitforgehq/ui/overlay';
115
+
116
+ /**
117
+ * Tooltips on each side of their button.
118
+ *
119
+ * `bfTooltipPlacement` puts the tooltip on the `top` (default), `bottom`, `start` or `end` side;
120
+ * `start` and `end` follow the text direction, and a tooltip without room flips to the other side.
121
+ */
122
+ @Component({
123
+ selector: 'app-example-tooltip-placement',
124
+ imports: [BfButtonComponent, BfTooltipDirective],
125
+ template: `
126
+ <div class="flex flex-wrap items-center justify-center gap-3 py-8">
127
+ @for (side of sides; track side) {
128
+ <bf-button
129
+ variant="outline"
130
+ size="sm"
131
+ [bfTooltip]="'Shown on the ' + side + ' side'"
132
+ [bfTooltipPlacement]="side"
133
+ >
134
+ {{ side }}
135
+ </bf-button>
136
+ }
137
+ </div>
138
+ `,
139
+ })
140
+ export class TooltipPlacementExampleComponent {
141
+ protected readonly sides: readonly BfTooltipPlacement[] = ['top', 'bottom', 'start', 'end'];
142
+ }
143
+ ```
144
+
145
+ ## Text
146
+
147
+ Keep the text to a few words on one line: the name of the control, and maybe its shortcut
148
+ ("Bold (Ctrl+B)"). Longer text wraps at 20 rem. A bound text that changes while the tooltip shows
149
+ ("Copy link", then "Copied") updates it in place; an empty text shows no tooltip.
150
+
151
+ On an icon-only `bf-icon-button` the tooltip repeats its `label`: the `label` stays the accessible
152
+ name, and the tooltip describes the button. A collapsed `bf-sidebar` link (`a[bfNavItem]`) shows
153
+ its name in the browser's `title` tooltip; add `bfTooltip` with the same text and
154
+ `bfTooltipPlacement="end"` for a styled one that also shows on keyboard focus. Bind it to an empty
155
+ text while the sidebar is expanded, where the label is visible.
156
+
157
+ ## Desktop
158
+
159
+ Built for a mouse and a keyboard. Hovering shows the tooltip after a 500 ms rest, so a pointer
160
+ that only passes over a toolbar shows nothing; moving the pointer from the control onto the
161
+ tooltip keeps it open (so it can be read under a magnifier). Keyboard focus (`focus-visible`)
162
+ shows it at once; a mouse click that focuses the control does not. The tooltip fades in over
163
+ 120 ms, without the fade when the system asks for reduced motion.
164
+
165
+ Under a coarse pointer (`(pointer: coarse)`, touch screens and the Capacitor shell) no tooltip
166
+ ever shows: there is no hover there, and a tooltip after a tap would sit under the finger. That
167
+ is why a tooltip never carries information found nowhere else.
168
+
169
+ ## Theming
170
+
171
+ - Pill: `bg-tooltip` with `text-on-tooltip` (14.9:1 in light, 13.8:1 in dark; the pill is dark
172
+ on a light page and light on a dark one), `rounded-field`, `shadow-raised`, `text-label-xs`,
173
+ 10 px by 4 px padding, at most 20 rem wide.
174
+ - Under forced colours (Windows High Contrast) the pill drops its fill and draws a 1 px border in
175
+ the text colour.
176
+
177
+ ## Accessibility
178
+
179
+ - The pill is `role="tooltip"` with an id. While it shows, the control (the host, or the first
180
+ control inside it, such as the button of a `bf-icon-button`) gets that id added to its
181
+ `aria-describedby`, next to any ids it already has; the id is removed when the tooltip hides.
182
+ - A tooltip is a description, never the name: an icon-only button keeps its `label` or
183
+ `aria-label`.
184
+ - WCAG 1.4.13 (content on hover or focus): the tooltip can be dismissed with `Escape` without
185
+ moving the pointer or focus, stays while the pointer is over it, and stays until the pointer
186
+ leaves, focus leaves or `Escape` is pressed.
187
+ - `Escape` goes to the tooltip first: inside a dialog or a popover, the first `Escape` hides the
188
+ tooltip and the next one closes the dialog.
189
+ - A disabled native button fires no pointer events, so its tooltip never shows; explain why a
190
+ control is disabled in the page instead.
191
+
192
+ ### Keyboard
193
+
194
+ | Key | Action |
195
+ | ------------------------------------------------ | -------------------------------------------------------- |
196
+ | <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> | Focusing the control shows its tooltip; leaving hides it |
197
+ | <kbd>Escape</kbd> | Hides the tooltip, focus stays where it is |
198
+
199
+ ## Inputs
200
+
201
+ | Name | Type | Default | Description |
202
+ | ------ | -------- | ------- | -------------------------------------------------------------------------- |
203
+ | `text` | `string` | `''` | The tooltip's text: a few words that repeat or explain the control's name. |
204
+
205
+ ## Notes
206
+
207
+ ### Do
208
+
209
+ - Repeat the name of icon-only controls, and add their keyboard shortcut.
210
+ - Keep the text to a few words.
211
+ - Put tooltips on controls that take focus, so keyboard users get them too.
212
+
213
+ ### Don't
214
+
215
+ - Don't put information only in a tooltip: touch screens never show it.
216
+ - Don't put links, buttons or other controls in a tooltip; use a popover.
217
+ - Don't use a tooltip as the accessible name of a control.
218
+ - Don't add a tooltip that repeats a visible text label word for word.
219
+
220
+ ## Migration notes
221
+
222
+ ### 0.3.1
223
+
224
+ New `[bfTooltip]` (`BfTooltipDirective`) and its `bf-tooltip` pill (`BfTooltipComponent`) in
225
+ `@bitforgehq/ui/overlay`: a short hint beside a control after a 500 ms hover or at once on keyboard
226
+ focus, hidden on leave, blur and `Escape`, and kept while the pointer moves onto it (WCAG 1.4.13).
227
+ `bfTooltipPlacement` (`BfTooltipPlacement`: `top` default, `bottom`, `start`, `end`, logical)
228
+ flips when it would overflow. While it shows, the control is described by it
229
+ (`aria-describedby`). Nothing shows under a coarse pointer. Fades in over 120 ms, not under
230
+ reduced motion. New `BfTooltipHarness` in `@bitforgehq/ui/testing`.
@@ -0,0 +1,159 @@
1
+ # bf-top-nav
2
+
3
+ Horizontal app navigation, a wrapping row of links for apps with few sections
4
+
5
+ `BfTopNavComponent` from `@bitforgehq/ui` · Navigation · since 0.3.1
6
+
7
+ ## Example
8
+
9
+ ```ts
10
+ import { Component } from '@angular/core';
11
+ import { RouterLink, RouterLinkActive } from '@angular/router';
12
+ import { BfNavItemComponent, BfTopNavComponent } from '@bitforgehq/ui';
13
+
14
+ /**
15
+ * The bf-top-nav overview.
16
+ *
17
+ * Live demo of `bf-top-nav`: a row of `a[bfNavItem]` router links for an app with few sections.
18
+ * This page is the current one; in a narrow container the row wraps onto more lines.
19
+ */
20
+ @Component({
21
+ selector: 'app-example-top-nav-overview',
22
+ imports: [RouterLink, RouterLinkActive, BfNavItemComponent, BfTopNavComponent],
23
+ template: `
24
+ <bf-top-nav label="Desktop navigation">
25
+ @for (link of links; track link.path) {
26
+ <a bfNavItem [routerLink]="link.path" routerLinkActive ariaCurrentWhenActive="page">{{
27
+ link.label
28
+ }}</a>
29
+ }
30
+ </bf-top-nav>
31
+ `,
32
+ })
33
+ export class TopNavOverviewExampleComponent {
34
+ protected readonly links: readonly { path: string; label: string }[] = [
35
+ { path: '/components/sidebar', label: 'Sidebar' },
36
+ { path: '/components/top-nav', label: 'Top nav' },
37
+ { path: '/components/nav-item', label: 'Nav item' },
38
+ { path: '/components/nav-group', label: 'Nav group' },
39
+ ];
40
+ }
41
+ ```
42
+
43
+ ## Overview
44
+
45
+ The horizontal navigation of a desktop app with few sections: a `nav` landmark holding a row
46
+ of `a[bfNavItem]` links that wraps onto more lines in a narrow container. Each link marks the
47
+ current page from `aria-current="page"`, as in `bf-sidebar`.
48
+
49
+ The horizontal navigation of a desktop web app with few sections: a `nav` landmark holding a row of [`a[bfNavItem]`](https://bitforge-ui.web.app/components/nav-item) links, usually in the app's header bar. In a narrow container the row wraps onto more lines. It shares its item with [`bf-sidebar`](https://bitforge-ui.web.app/components/sidebar), so the current page, the count badge and the focus ring look the same in both.
50
+
51
+ ## When to use
52
+
53
+ Use `bf-top-nav` for the two to five top-level destinations of a desktop web app. Use [bf-sidebar](https://bitforge-ui.web.app/components/sidebar) instead for more sections or sections in groups, and [bf-segmented](https://bitforge-ui.web.app/components/segmented) to switch a view in place. In the Capacitor shell use [bf-tabs](https://bitforge-ui.web.app/components/tabs) with [bf-tab-bar](https://bitforge-ui.web.app/components/tab-bar) instead.
54
+
55
+ ## Basic usage
56
+
57
+ Put `bfNavItem` on your own `<a routerLink routerLinkActive ariaCurrentWhenActive="page">`: the router sets `aria-current="page"` on the current page's link and the item shows it in the tonal fill. Items lay out inline at their own width; an icon in `bfSlot="icon"` and a `badge` work as in the sidebar. Name the landmark with `label` (it falls back to `provideBfLabels()`'s `navigation`, "Main").
58
+
59
+ ## Icons and badges
60
+
61
+ An icon in `bfSlot="icon"` sits before the label and `badge` adds a count pill, announced as "4 new", as in the sidebar.
62
+
63
+ ```ts
64
+ import { Component } from '@angular/core';
65
+ import { RouterLink, RouterLinkActive } from '@angular/router';
66
+ import { BfNavItemComponent, BfTopNavComponent } from '@bitforgehq/ui';
67
+ import { BfIconComponent } from '@bitforgehq/ui/icons';
68
+ import { ChartColumn, Inbox, LayoutDashboard } from 'lucide';
69
+
70
+ /**
71
+ * Icons and a count badge in a top nav.
72
+ *
73
+ * Each `a[bfNavItem]` takes an icon in `bfSlot="icon"` and a `badge`, as in the sidebar.
74
+ */
75
+ @Component({
76
+ selector: 'app-example-top-nav-icons',
77
+ imports: [RouterLink, RouterLinkActive, BfIconComponent, BfNavItemComponent, BfTopNavComponent],
78
+ template: `
79
+ <bf-top-nav label="Sections with icons">
80
+ <a bfNavItem routerLink="/components/top-nav" routerLinkActive ariaCurrentWhenActive="page">
81
+ <bf-icon bfSlot="icon" [icon]="dashboard" />
82
+ Overview
83
+ </a>
84
+ <a
85
+ bfNavItem
86
+ routerLink="/components/badge"
87
+ routerLinkActive
88
+ ariaCurrentWhenActive="page"
89
+ [badge]="4"
90
+ >
91
+ <bf-icon bfSlot="icon" [icon]="inbox" />
92
+ Inbox
93
+ </a>
94
+ <a bfNavItem routerLink="/density" routerLinkActive ariaCurrentWhenActive="page">
95
+ <bf-icon bfSlot="icon" [icon]="chart" />
96
+ Reports
97
+ </a>
98
+ </bf-top-nav>
99
+ `,
100
+ })
101
+ export class TopNavIconsExampleComponent {
102
+ protected readonly dashboard = LayoutDashboard;
103
+ protected readonly inbox = Inbox;
104
+ protected readonly chart = ChartColumn;
105
+ }
106
+ ```
107
+
108
+ ## Small screens
109
+
110
+ The row wraps rather than scrolling sideways. When it would wrap onto too many lines, drive a [`bf-menu-button`](https://bitforge-ui.web.app/components/menu-button) of `a[bfMenuItem]` links below a breakpoint from the same array (`class="hidden md:block"` on `bf-top-nav`, `class="md:hidden"` on the menu button), as the [sidebar's responsive layout](https://bitforge-ui.web.app/components/sidebar) shows.
111
+
112
+ ## Desktop
113
+
114
+ The top nav is a desktop pattern. Its items take a `surface-muted` fill and the pointer on hover, a `surface-pressed` fill while pressed and the focus ring on keyboard focus only; the current page keeps its tonal fill with its own hover and pressed steps. Item height follows `provideBfDefaults()` (`controlSize`); under a coarse pointer every item is at least 44 px tall. Ctrl/Cmd-click and a middle click open a link in a new tab.
115
+
116
+ ## Theming
117
+
118
+ - Layout: `flex flex-wrap` with a 4 px gap; no surface of its own, so it sits on the header bar or page behind it.
119
+ - The items' tokens are on the [nav item](https://bitforge-ui.web.app/components/nav-item#theming) page.
120
+
121
+ ## Accessibility
122
+
123
+ `bf-top-nav` renders a native `<nav>` landmark named by `label`, else `provideBfLabels()`'s `navigation` ("Main"); give each landmark on a page a different name. Its links are plain `<a>` elements in DOM order; the current page is the one with `aria-current="page"`, which screen readers announce ("current page") and which an outline marks under forced colours.
124
+
125
+ ### Keyboard
126
+
127
+ | Key | Action |
128
+ | ------------------------------------------------ | ------------------------ |
129
+ | <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> | Moves between the links |
130
+ | <kbd>Enter</kbd> | Follows the focused link |
131
+
132
+ ## Inputs
133
+
134
+ | Name | Type | Default | Description |
135
+ | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
136
+ | `label` | `string` | `''` | Accessible name of the navigation; empty falls back to `provideBfLabels()`'s `navigation` ("Main"). Name each landmark differently when a page has more than one. |
137
+
138
+ ## Slots
139
+
140
+ - `default`: The destinations, `a[bfNavItem]` links.
141
+
142
+ ## Notes
143
+
144
+ ### Do
145
+
146
+ - Keep it to a few short labels that fit one line at the usual window width.
147
+ - Mark the current page with `routerLinkActive` and `ariaCurrentWhenActive="page"`.
148
+
149
+ ### Don't
150
+
151
+ - Don't put more than five or six destinations in it; use a `bf-sidebar`.
152
+ - Don't use it to switch a view inside a page; use a `bf-segmented`.
153
+
154
+ ## Migration notes
155
+
156
+ ### 0.3.1
157
+
158
+ New `bf-top-nav`: the horizontal navigation of a desktop app with few sections, a `nav` row of
159
+ `a[bfNavItem]` links that wraps in a narrow container, named by `label` (else `navigation`).
@@ -0,0 +1,27 @@
1
+ # BfAppFrameBreakpoint
2
+
3
+ The breakpoint where an app frame switches from its header bar to the sidebar
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.2
6
+
7
+ The viewport width from which `bf-app-frame` shows its sidebar column instead of the narrow
8
+ header bar: Tailwind's `md` (768 px) or `lg` (1024 px).
9
+
10
+ ```ts
11
+ import { type BfAppFrameBreakpoint } from '@bitforgehq/ui';
12
+ ```
13
+
14
+ ## Signature
15
+
16
+ ```ts
17
+ type BfAppFrameBreakpoint = 'md' | 'lg'
18
+ ```
19
+
20
+ ## Values
21
+
22
+ - `md`
23
+ - `lg`
24
+
25
+ ## Used by
26
+
27
+ - [bf-app-frame](../components/app-frame.md)
@@ -0,0 +1,29 @@
1
+ # BfAppFrameContentWidth
2
+
3
+ The maximum width of an app frame's content column, from medium to full
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.2
6
+
7
+ The maximum width of `bf-app-frame`'s content column: `md` 48rem, `lg` 64rem, `xl` 80rem, or
8
+ `full` for no limit.
9
+
10
+ ```ts
11
+ import { type BfAppFrameContentWidth } from '@bitforgehq/ui';
12
+ ```
13
+
14
+ ## Signature
15
+
16
+ ```ts
17
+ type BfAppFrameContentWidth = 'md' | 'lg' | 'xl' | 'full'
18
+ ```
19
+
20
+ ## Values
21
+
22
+ - `md`
23
+ - `lg`
24
+ - `xl`
25
+ - `full`
26
+
27
+ ## Used by
28
+
29
+ - [bf-app-frame](../components/app-frame.md)
@@ -0,0 +1,36 @@
1
+ # BfBadgeAppearance
2
+
3
+ Every badge tone, the five variants plus the informational info tone
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.1
6
+
7
+ Every tone the `variant` input of a `bf-badge` takes: the five `BfBadgeVariant` tones plus
8
+ `info`, for an informational label such as a category. A new type, so `Record`s and exhaustive
9
+ switches over `BfBadgeVariant` keep compiling.
10
+
11
+ ```ts
12
+ import { type BfBadgeAppearance } from '@bitforgehq/ui';
13
+ ```
14
+
15
+ ## Signature
16
+
17
+ ```ts
18
+ type BfBadgeAppearance = BfBadgeVariant | 'info'
19
+ ```
20
+
21
+ ## Values
22
+
23
+ - `neutral`
24
+ - `primary`
25
+ - `success`
26
+ - `warning`
27
+ - `danger`
28
+ - `info`
29
+
30
+ ## Uses
31
+
32
+ - [BfBadgeVariant](bf-badge-variant.md)
33
+
34
+ ## Used by
35
+
36
+ - [bf-badge](../components/badge.md)
@@ -26,4 +26,4 @@ type BfBadgeVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'danger'
26
26
 
27
27
  ## Used by
28
28
 
29
- - [bf-badge](../components/badge.md)
29
+ - [BfBadgeAppearance](bf-badge-appearance.md)
@@ -0,0 +1,27 @@
1
+ # BfBarChartOrientation
2
+
3
+ The two bar directions, vertical columns or horizontal bars
4
+
5
+ Type from `@bitforgehq/ui/charts` · since 0.3.1
6
+
7
+ The direction of a `bf-bar-chart`'s bars: up from a horizontal baseline, or along from a
8
+ vertical one (for long category names or many categories).
9
+
10
+ ```ts
11
+ import { type BfBarChartOrientation } from '@bitforgehq/ui/charts';
12
+ ```
13
+
14
+ ## Signature
15
+
16
+ ```ts
17
+ type BfBarChartOrientation = 'vertical' | 'horizontal'
18
+ ```
19
+
20
+ ## Values
21
+
22
+ - `vertical`
23
+ - `horizontal`
24
+
25
+ ## Used by
26
+
27
+ - [bf-bar-chart](../components/bar-chart.md)
@@ -0,0 +1,36 @@
1
+ # BfButtonAppearance
2
+
3
+ Every button style, the five variants plus the quiet neutral ghost
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.1
6
+
7
+ Every value the `variant` input of a `bf-button` takes: the five `BfButtonVariant` styles plus
8
+ `ghost`, the quiet neutral one. A new type, so `Record`s and exhaustive switches over
9
+ `BfButtonVariant` keep compiling.
10
+
11
+ ```ts
12
+ import { type BfButtonAppearance } from '@bitforgehq/ui';
13
+ ```
14
+
15
+ ## Signature
16
+
17
+ ```ts
18
+ type BfButtonAppearance = BfButtonVariant | 'ghost'
19
+ ```
20
+
21
+ ## Values
22
+
23
+ - `primary`
24
+ - `tonal`
25
+ - `outline`
26
+ - `text`
27
+ - `danger`
28
+ - `ghost`
29
+
30
+ ## Uses
31
+
32
+ - [BfButtonVariant](bf-button-variant.md)
33
+
34
+ ## Used by
35
+
36
+ - [bf-button](../components/button.md)
@@ -26,4 +26,4 @@ type BfButtonVariant = 'primary' | 'tonal' | 'outline' | 'text' | 'danger'
26
26
 
27
27
  ## Used by
28
28
 
29
- - [bf-button](../components/button.md)
29
+ - [BfButtonAppearance](bf-button-appearance.md)
@@ -0,0 +1,23 @@
1
+ # BfCalendarDisabledDate
2
+
3
+ A function that marks an ISO date as not pickable in a calendar
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.1
6
+
7
+ Tells `bf-calendar` which dates cannot be picked, such as weekends or booked days.
8
+
9
+ ```ts
10
+ import { type BfCalendarDisabledDate } from '@bitforgehq/ui';
11
+ ```
12
+
13
+ ## Signature
14
+
15
+ ```ts
16
+ type BfCalendarDisabledDate = (iso: string) => boolean
17
+ ```
18
+
19
+ ## Used by
20
+
21
+ - [bf-calendar](../components/calendar.md)
22
+ - [bf-date-input](../components/date-input.md)
23
+ - [bf-datetime-input](../components/datetime-input.md)
@@ -0,0 +1,51 @@
1
+ # BfCalendarHarness
2
+
3
+ Test harness for the calendar: reads the month and picks a date by ISO string
4
+
5
+ Class from `@bitforgehq/ui/testing` · since 0.3.1
6
+
7
+ Harness for `bf-calendar`. It works with ISO dates ('YYYY-MM-DD'), as the calendar's value
8
+ does, and drives it as a user would: `selectDate()` jumps to another month through the month
9
+ and year views, then clicks the day.
10
+
11
+ ```ts
12
+ import { BfCalendarHarness } from '@bitforgehq/ui/testing';
13
+ ```
14
+
15
+ ## Signature
16
+
17
+ ```ts
18
+ class BfCalendarHarness extends ComponentHarness
19
+ ```
20
+
21
+ ## Methods
22
+
23
+ ### `getLabel(): Promise<string>`
24
+
25
+ The calendar's accessible name (`label`, else `ariaLabel`); it is not rendered visibly.
26
+
27
+ ### `getMonthLabel(): Promise<string>`
28
+
29
+ The shown month and year as the header writes them, in the calendar's locale.
30
+
31
+ ### `getSelected(): Promise<string | null>`
32
+
33
+ The picked date while it is in the shown month.
34
+
35
+ ### `nextMonth(): Promise<void>`
36
+
37
+ Clicks the next-month button. Throws when it is disabled (the month is past `max`).
38
+
39
+ ### `previousMonth(): Promise<void>`
40
+
41
+ Clicks the previous-month button. Throws when it is disabled (the month is before `min`).
42
+
43
+ ### `selectDate(iso: string): Promise<void>`
44
+
45
+ Picks a date as a user would: when it is in another month, opens the month view, then the
46
+ year view, clicks its year and month, then clicks the day. Throws for an invalid date, one
47
+ the views do not list, and a disabled date or calendar.
48
+
49
+ | Parameter | Type | Description |
50
+ | --------- | -------- | ------------------------------------------- |
51
+ | `iso` | `string` | The ISO date to pick, such as '2026-11-03'. |
@@ -0,0 +1,31 @@
1
+ # BfCalendarWeekday
2
+
3
+ A weekday number from 0 for Sunday to 6 for Saturday, as Date counts
4
+
5
+ Type from `@bitforgehq/ui` · since 0.3.1
6
+
7
+ A weekday as `Date.getDay()` counts it: 0 Sunday, 1 Monday … 6 Saturday.
8
+
9
+ ```ts
10
+ import { type BfCalendarWeekday } from '@bitforgehq/ui';
11
+ ```
12
+
13
+ ## Signature
14
+
15
+ ```ts
16
+ type BfCalendarWeekday = 0 | 1 | 2 | 3 | 4 | 5 | 6
17
+ ```
18
+
19
+ ## Values
20
+
21
+ - `0`
22
+ - `1`
23
+ - `2`
24
+ - `3`
25
+ - `4`
26
+ - `5`
27
+ - `6`
28
+
29
+ ## Used by
30
+
31
+ - [bf-calendar](../components/calendar.md)