@bitforgehq/ui 0.4.0 → 0.5.0-next.4
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 +350 -0
- package/README.md +12 -12
- package/ai/MANIFEST.index.json +74 -2
- package/ai/MANIFEST.json +3507 -1763
- package/ai/REFERENCE.index.json +189 -0
- package/ai/REFERENCE.json +1617 -139
- package/ai/UI_GUIDE.md +70 -20
- package/ai/components/app-frame.md +1 -1
- package/ai/components/badge.md +41 -1
- package/ai/components/chat-composer.md +357 -0
- package/ai/components/chat-message.md +251 -0
- package/ai/components/chat-thread.md +521 -0
- package/ai/components/checkbox.md +7 -0
- package/ai/components/combobox.md +12 -0
- package/ai/components/date-input.md +9 -0
- package/ai/components/datetime-input.md +2 -0
- package/ai/components/field.md +10 -0
- package/ai/components/file-input.md +498 -0
- package/ai/components/header.md +1 -1
- package/ai/components/image-input.md +368 -0
- package/ai/components/image-tile.md +452 -0
- package/ai/components/image-viewer.md +309 -0
- package/ai/components/media-card.md +478 -0
- package/ai/components/menu-button.md +67 -9
- package/ai/components/menu.md +10 -0
- package/ai/components/multi-combobox.md +7 -0
- package/ai/components/nav-group.md +10 -3
- package/ai/components/nav-item.md +11 -2
- package/ai/components/number-input.md +2 -7
- package/ai/components/pagination.md +59 -11
- package/ai/components/popover.md +13 -0
- package/ai/components/radio-group.md +6 -0
- package/ai/components/segmented.md +14 -2
- package/ai/components/select.md +100 -42
- package/ai/components/sidebar-toggle.md +16 -9
- package/ai/components/sidebar.md +41 -13
- package/ai/components/tab-group.md +18 -2
- package/ai/components/table.md +17 -2
- package/ai/components/theme-menu-button.md +1 -0
- package/ai/components/time-input.md +2 -0
- package/ai/components/toolbar.md +7 -18
- package/ai/reference/bf-chat-composer-harness.md +64 -0
- package/ai/reference/bf-chat-message-role.md +27 -0
- package/ai/reference/bf-chat-message-status.md +28 -0
- package/ai/reference/bf-fade-in-directive.md +18 -0
- package/ai/reference/bf-file-input-harness.md +67 -0
- package/ai/reference/bf-file-input-variant.md +27 -0
- package/ai/reference/bf-image-input-harness.md +67 -0
- package/ai/reference/bf-image-input-shape.md +27 -0
- package/ai/reference/bf-image-tile-aspect.md +28 -0
- package/ai/reference/bf-image-tile-caption-placement.md +27 -0
- package/ai/reference/bf-image-tile-harness.md +70 -0
- package/ai/reference/bf-image-viewer-actions-context.md +29 -0
- package/ai/reference/bf-image-viewer-harness.md +87 -0
- package/ai/reference/bf-image-viewer-image.md +25 -0
- package/ai/reference/bf-image-viewer-options.md +33 -0
- package/ai/reference/bf-image-viewer-origin.md +23 -0
- package/ai/reference/bf-image-viewer-ref.md +55 -0
- package/ai/reference/bf-image-viewer-service.md +32 -0
- package/ai/reference/bf-labels.md +107 -75
- package/ai/reference/bf-media-card-aspect.md +28 -0
- package/ai/reference/bf-media-card-harness.md +66 -0
- package/ai/reference/bf-motion-list-directive.md +22 -0
- package/ai/reference/bf-pagination-position-label.md +22 -0
- package/ai/reference/bf-prose-directive.md +16 -0
- package/ai/reference/bf-rejected-file-reason.md +28 -0
- package/ai/reference/bf-rejected-file.md +28 -0
- package/ai/reference/bf-select-harness.md +14 -5
- package/ai/reference/bf-select-option.md +2 -0
- package/ai/reference/bf-size.md +3 -0
- package/ai/reference/bf_table_sort_select.md +23 -0
- package/ai/reference/provide-bf-labels.md +11 -3
- package/ai/reference/provide-bf-select.md +20 -0
- package/bin/bf-ui.js +1 -0
- package/fesm2022/bitforgehq-ui-overlay.mjs +2660 -594
- package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-testing.mjs +414 -10
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui.mjs +8056 -3993
- package/fesm2022/bitforgehq-ui.mjs.map +1 -1
- package/llms-full.txt +4923 -132
- package/llms.txt +36 -1
- package/package.json +1 -1
- package/theme.css +60 -0
- package/types/bitforgehq-ui-overlay.d.ts +695 -7
- package/types/bitforgehq-ui-testing.d.ts +517 -6
- package/types/bitforgehq-ui.d.ts +1699 -181
|
@@ -41,11 +41,13 @@ interface NavLink {
|
|
|
41
41
|
template: `
|
|
42
42
|
<div class="border-border bg-bg rounded-card flex h-72 overflow-hidden border">
|
|
43
43
|
<bf-sidebar label="Toggle demo" [(collapsed)]="collapsed">
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
<!-- The brand fades while it narrows to nothing, so the toggle slides with the edge. -->
|
|
45
|
+
<div bfSlot="header" class="flex items-center">
|
|
46
|
+
<span
|
|
47
|
+
class="text-heading text-text ease-md min-w-0 flex-1 truncate ps-3 pe-2 transition-[opacity,padding] duration-(--bf-duration-layout) in-data-collapsed:ps-0 in-data-collapsed:pe-0 in-data-collapsed:opacity-0 motion-reduce:transition-none"
|
|
48
|
+
>Atlas</span
|
|
49
|
+
>
|
|
50
|
+
<bf-sidebar-toggle class="shrink-0">
|
|
49
51
|
<bf-icon bfSlot="collapse-icon" [icon]="panelClose" />
|
|
50
52
|
<bf-icon bfSlot="expand-icon" [icon]="panelOpen" />
|
|
51
53
|
</bf-sidebar-toggle>
|
|
@@ -134,7 +136,7 @@ interface NavLink {
|
|
|
134
136
|
* The footer slot holds a Settings link (`a[bfNavItem]`), a row with an icon-only
|
|
135
137
|
* `bf-theme-menu-button` and the `bf-sidebar-toggle`, and a version line. Expanded, the two
|
|
136
138
|
* buttons sit at either end of the row; as an icon rail the row stacks vertically and the version
|
|
137
|
-
* line
|
|
139
|
+
* line closes and fades out. The theme binds a local signal so the docs site keeps its theme; an app binds
|
|
138
140
|
* `BfColorSchemeService.scheme`.
|
|
139
141
|
*/
|
|
140
142
|
@Component({
|
|
@@ -176,8 +178,13 @@ interface NavLink {
|
|
|
176
178
|
<bf-icon bfSlot="expand-icon" [icon]="panelOpen" />
|
|
177
179
|
</bf-sidebar-toggle>
|
|
178
180
|
</div>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
+
<!-- The version line closes and fades on the sidebar's timing (a grid row from 1fr to
|
|
182
|
+
0fr), so the footer shrinks smoothly instead of jumping. -->
|
|
183
|
+
<p
|
|
184
|
+
bfSlot="footer"
|
|
185
|
+
class="text-caption text-text-muted ease-md grid grid-rows-[1fr] ps-3 transition-[grid-template-rows,opacity] duration-(--bf-duration-layout) in-data-collapsed:grid-rows-[0fr] in-data-collapsed:opacity-0 motion-reduce:transition-none"
|
|
186
|
+
>
|
|
187
|
+
<span class="min-h-0 min-w-0 truncate">Version 0.3.2</span>
|
|
181
188
|
</p>
|
|
182
189
|
</bf-sidebar>
|
|
183
190
|
<div class="min-w-0 flex-1 p-4">
|
|
@@ -195,7 +202,7 @@ export class SidebarFooterExampleComponent {
|
|
|
195
202
|
|
|
196
203
|
/** Expanded: one row, the buttons at either end. Collapsed: a column in the rail. */
|
|
197
204
|
protected readonly rowClasses = computed(() =>
|
|
198
|
-
this.collapsed() ? 'flex flex-col items-
|
|
205
|
+
this.collapsed() ? 'flex flex-col items-start gap-1' : 'flex items-center justify-between',
|
|
199
206
|
);
|
|
200
207
|
protected readonly themeIcon = computed(
|
|
201
208
|
() => ({ system: SunMoon, light: Sun, dark: Moon })[this.scheme()],
|
package/ai/components/sidebar.md
CHANGED
|
@@ -41,7 +41,8 @@ interface NavLink {
|
|
|
41
41
|
* Live demo of `bf-sidebar`: a brand and a collapse toggle in the header, two `bf-nav-group`s of
|
|
42
42
|
* `a[bfNavItem]` router links (this page is the current one, one item has a count badge) and a
|
|
43
43
|
* footer link. The toggle binds `[(collapsed)]`; collapsed, the items show their icon only and
|
|
44
|
-
* name themselves in a tooltip. The
|
|
44
|
+
* name themselves in a tooltip. The width, the labels and the brand animate together (instantly
|
|
45
|
+
* under reduced motion). The result line reports the state.
|
|
45
46
|
*/
|
|
46
47
|
@Component({
|
|
47
48
|
selector: 'app-example-sidebar-overview',
|
|
@@ -57,11 +58,15 @@ interface NavLink {
|
|
|
57
58
|
template: `
|
|
58
59
|
<div class="border-border bg-bg rounded-card flex h-96 overflow-hidden border">
|
|
59
60
|
<bf-sidebar label="Docs" [(collapsed)]="collapsed">
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
<!-- The brand stays in the DOM and fades while it narrows to nothing, on the sidebar's
|
|
62
|
+
own timing, so the toggle slides with the edge instead of jumping. -->
|
|
63
|
+
<div bfSlot="header" class="flex items-center">
|
|
64
|
+
<span
|
|
65
|
+
class="text-heading text-text ease-md min-w-0 flex-1 truncate ps-3 pe-2 transition-[opacity,padding] duration-(--bf-duration-layout) in-data-collapsed:ps-0 in-data-collapsed:pe-0 in-data-collapsed:opacity-0 motion-reduce:transition-none"
|
|
66
|
+
>Atlas</span
|
|
67
|
+
>
|
|
64
68
|
<bf-icon-button
|
|
69
|
+
class="shrink-0"
|
|
65
70
|
variant="text"
|
|
66
71
|
[label]="collapsed() ? 'Expand sidebar' : 'Collapse sidebar'"
|
|
67
72
|
(clicked)="collapsed.set(!collapsed())"
|
|
@@ -157,7 +162,13 @@ Put `bfNavItem` on your own `<a routerLink routerLinkActive ariaCurrentWhenActiv
|
|
|
157
162
|
|
|
158
163
|
## Collapsing to an icon rail
|
|
159
164
|
|
|
160
|
-
`collapsed` is a model. Put a [`bf-sidebar-toggle`](https://bitforge-ui.web.app/components/sidebar-toggle) (`@bitforgehq/ui/overlay`) in the header or footer: it flips the model, names itself by what the next press does ("Collapse sidebar", "Expand sidebar") and takes its two icons as slots, since a widget never imports one. Bind `[(collapsed)]` to keep the state in your own signal, or bind it to your own button outside the sidebar. Collapsed, every item shows only its icon, centred in a square; its label stays in the DOM as screen-reader text, so its accessible name does not change, and becomes the link's `title`, the tooltip a pointer user sees on hover. A count badge becomes a small dot that is still announced, and the group headings are hidden visually but still name their groups.
|
|
165
|
+
`collapsed` is a model. Put a [`bf-sidebar-toggle`](https://bitforge-ui.web.app/components/sidebar-toggle) (`@bitforgehq/ui/overlay`) in the header or footer: it flips the model, names itself by what the next press does ("Collapse sidebar", "Expand sidebar") and takes its two icons as slots, since a widget never imports one. Bind `[(collapsed)]` to keep the state in your own signal, or bind it to your own button outside the sidebar. Collapsed, every item shows only its icon, centred in a square; its label stays in the DOM as screen-reader text, so its accessible name does not change, and becomes the link's `title`, the tooltip a pointer user sees on hover. A count badge becomes a small dot that is still announced, and the group headings are hidden visually but still name their groups. Expanded the sidebar is `w-60` (240 px); the rail is one item square of the app's `controlSize` plus the 12 px padding on each side: 56, 64 or 72 px for `sm`, `md` and `lg`, and 68 px under a coarse pointer for `sm` and `md`, where items are 44 px wide.
|
|
166
|
+
|
|
167
|
+
## Motion
|
|
168
|
+
|
|
169
|
+
Collapsing and expanding animate on the layout timing (`--bf-duration-layout`, 200 ms, on `ease-md`): the width moves, the item labels and group headings fade while the row narrows to its icon, the icons stay where they are, and the count pill shrinks away while its dot grows in. Content beside the sidebar, such as the [`bf-app-frame`](https://bitforge-ui.web.app/components/app-frame) content column, moves with it. Under `prefers-reduced-motion: reduce` the sidebar switches at once, and the first render never animates, so a collapsed state restored by `provideBfSidebarState()` is simply there on load.
|
|
170
|
+
|
|
171
|
+
Your own `header` and `footer` content can follow on the same timing: the host carries `data-collapsed` while collapsed, so Tailwind's `in-data-collapsed:` variant styles anything inside it. Keep the content in the DOM and let the sidebar clip it rather than removing it with `@if`, which makes it jump: fade a brand name with `transition-opacity duration-(--bf-duration-layout) ease-md in-data-collapsed:opacity-0 motion-reduce:transition-none`, and close a block (an account card, a version line) with a grid row, `grid grid-rows-[1fr] in-data-collapsed:grid-rows-[0fr]` around a `min-h-0 overflow-hidden` child, transitioning `grid-template-rows`. The overview and footer examples do both.
|
|
161
172
|
|
|
162
173
|
## Remember the collapsed sidebar
|
|
163
174
|
|
|
@@ -218,7 +229,7 @@ export class SidebarRememberedExampleComponent {
|
|
|
218
229
|
|
|
219
230
|
## Footer
|
|
220
231
|
|
|
221
|
-
The footer slot takes several elements, stacked with a 4 px gap: a Settings link as an `a[bfNavItem]`, a row holding an icon-only text [`bf-theme-menu-button`](https://bitforge-ui.web.app/components/theme-menu-button) and the `bf-sidebar-toggle`, and an optional version line in `text-caption text-text-muted`. Expanded, the row puts the two buttons at either end (`flex items-center justify-between`). As an icon rail
|
|
232
|
+
The footer slot takes several elements, stacked with a 4 px gap: a Settings link as an `a[bfNavItem]`, a row holding an icon-only text [`bf-theme-menu-button`](https://bitforge-ui.web.app/components/theme-menu-button) and the `bf-sidebar-toggle`, and an optional version line in `text-caption text-text-muted`. Expanded, the row puts the two buttons at either end (`flex items-center justify-between`). As an icon rail switch the row to a column (`flex flex-col items-start gap-1`) so both buttons fit the rail; aligned to the start, the theme button does not move while the width animates. Close the version line, which has no icon to shrink to, with a grid row (`in-data-collapsed:grid-rows-[0fr]`, see Motion) so the footer shrinks smoothly. Open the theme menu upwards (`placement="above-start"`), since the footer sits at the bottom of the screen.
|
|
222
233
|
|
|
223
234
|
```ts
|
|
224
235
|
import { Component, computed, signal } from '@angular/core';
|
|
@@ -250,7 +261,7 @@ interface NavLink {
|
|
|
250
261
|
* The footer slot holds a Settings link (`a[bfNavItem]`), a row with an icon-only
|
|
251
262
|
* `bf-theme-menu-button` and the `bf-sidebar-toggle`, and a version line. Expanded, the two
|
|
252
263
|
* buttons sit at either end of the row; as an icon rail the row stacks vertically and the version
|
|
253
|
-
* line
|
|
264
|
+
* line closes and fades out. The theme binds a local signal so the docs site keeps its theme; an app binds
|
|
254
265
|
* `BfColorSchemeService.scheme`.
|
|
255
266
|
*/
|
|
256
267
|
@Component({
|
|
@@ -292,8 +303,13 @@ interface NavLink {
|
|
|
292
303
|
<bf-icon bfSlot="expand-icon" [icon]="panelOpen" />
|
|
293
304
|
</bf-sidebar-toggle>
|
|
294
305
|
</div>
|
|
295
|
-
|
|
296
|
-
|
|
306
|
+
<!-- The version line closes and fades on the sidebar's timing (a grid row from 1fr to
|
|
307
|
+
0fr), so the footer shrinks smoothly instead of jumping. -->
|
|
308
|
+
<p
|
|
309
|
+
bfSlot="footer"
|
|
310
|
+
class="text-caption text-text-muted ease-md grid grid-rows-[1fr] ps-3 transition-[grid-template-rows,opacity] duration-(--bf-duration-layout) in-data-collapsed:grid-rows-[0fr] in-data-collapsed:opacity-0 motion-reduce:transition-none"
|
|
311
|
+
>
|
|
312
|
+
<span class="min-h-0 min-w-0 truncate">Version 0.3.2</span>
|
|
297
313
|
</p>
|
|
298
314
|
</bf-sidebar>
|
|
299
315
|
<div class="min-w-0 flex-1 p-4">
|
|
@@ -311,7 +327,7 @@ export class SidebarFooterExampleComponent {
|
|
|
311
327
|
|
|
312
328
|
/** Expanded: one row, the buttons at either end. Collapsed: a column in the rail. */
|
|
313
329
|
protected readonly rowClasses = computed(() =>
|
|
314
|
-
this.collapsed() ? 'flex flex-col items-
|
|
330
|
+
this.collapsed() ? 'flex flex-col items-start gap-1' : 'flex items-center justify-between',
|
|
315
331
|
);
|
|
316
332
|
protected readonly themeIcon = computed(
|
|
317
333
|
() => ({ system: SunMoon, light: Sun, dark: Moon })[this.scheme()],
|
|
@@ -481,12 +497,13 @@ The sidebar is a desktop pattern. Its items take a `surface-muted` fill and the
|
|
|
481
497
|
## Theming
|
|
482
498
|
|
|
483
499
|
- Surface: `surface` with a `border` line on its inline-end edge (`border-e`); 12 px padding and 24 px between the header, the groups and the footer.
|
|
484
|
-
- Width: `w-60` (240 px) expanded,
|
|
500
|
+
- Width: `w-60` (240 px) expanded; collapsed, a rail of one `controlSize` square plus padding (`w-14`, `w-16` or `w-18`; `w-17` under a coarse pointer for `sm` and `md`).
|
|
501
|
+
- Motion: `--bf-duration-layout` and `--ease-md` for the width, the labels, the headings and the badge.
|
|
485
502
|
- The items' and the groups' tokens are on the [nav item](https://bitforge-ui.web.app/components/nav-item#theming) and [nav group](https://bitforge-ui.web.app/components/nav-group#theming) pages.
|
|
486
503
|
|
|
487
504
|
## Accessibility
|
|
488
505
|
|
|
489
|
-
`bf-sidebar` renders a native `<nav>` landmark named by `label`, else `provideBfLabels()`'s `navigation` ("Main"); give each landmark on a page a different name. The header, the destinations and the footer all sit inside it, in that DOM order. The current page is the link the router marks with `aria-current="page"`; the tonal fill is never the only cue under forced colours, where an outline marks it. Collapsing changes only what is visible: every item keeps its label as screen-reader text and each group its name, so the accessible names stay the same. `bf-sidebar-toggle` is a native button named by what it does ("Collapse sidebar"), with `aria-expanded` and `aria-controls` on the `nav`; your own toggle should do the same, and sit in the sidebar or right before it.
|
|
506
|
+
`bf-sidebar` renders a native `<nav>` landmark named by `label`, else `provideBfLabels()`'s `navigation` ("Main"); give each landmark on a page a different name. The header, the destinations and the footer all sit inside it, in that DOM order. The current page is the link the router marks with `aria-current="page"`; the tonal fill is never the only cue under forced colours, where an outline marks it. Collapsing changes only what is visible, and it animates only without `prefers-reduced-motion: reduce`: every item keeps its label as screen-reader text and each group its name, so the accessible names stay the same. `bf-sidebar-toggle` is a native button named by what it does ("Collapse sidebar"), with `aria-expanded` and `aria-controls` on the `nav`; your own toggle should do the same, and sit in the sidebar or right before it.
|
|
490
507
|
|
|
491
508
|
### Keyboard
|
|
492
509
|
|
|
@@ -515,14 +532,25 @@ The sidebar is a desktop pattern. Its items take a `surface-muted` fill and the
|
|
|
515
532
|
- Mark the current page with `routerLinkActive` and `ariaCurrentWhenActive="page"` on every link.
|
|
516
533
|
- Drive the sidebar, the small-screen menu and the shell's tab bar from one array of destinations.
|
|
517
534
|
- Remember the collapsed state with `BfSidebarStateService` and `provideBfSidebarState()`.
|
|
535
|
+
- Let header and footer content fade or close with `in-data-collapsed:` on `--bf-duration-layout`, so it moves with the sidebar.
|
|
518
536
|
|
|
519
537
|
### Don't
|
|
520
538
|
|
|
521
539
|
- Don't put actions (Create, Log out) among the destinations; a sidebar is for places, so put an action in the header or footer as a button.
|
|
522
540
|
- Don't use `bf-sidebar` inside the Capacitor shell; use `bf-tabs` with a `bf-tab-bar` there.
|
|
541
|
+
- Don't remove header or footer content with `@if` on the collapsed state; it disappears before the width has moved.
|
|
523
542
|
|
|
524
543
|
## Migration notes
|
|
525
544
|
|
|
545
|
+
### 0.5.0
|
|
546
|
+
|
|
547
|
+
Collapsing and expanding now animate: the width moves over `--bf-duration-layout` on `ease-md`
|
|
548
|
+
from `w-60` to a fixed rail (see Migration 4), and the content beside it (the `bf-app-frame`
|
|
549
|
+
column) moves with it. Under `prefers-reduced-motion: reduce` it still switches at once. The first
|
|
550
|
+
render never animates, so a collapsed state restored by `provideBfSidebarState()` does not slide
|
|
551
|
+
on load. The host carries `data-collapsed` as before; header and footer content can follow on the
|
|
552
|
+
same timing with `in-data-collapsed:` (new Motion section in the docs).
|
|
553
|
+
|
|
526
554
|
### 0.3.2
|
|
527
555
|
|
|
528
556
|
New `BfSidebarStateService` (a `collapsed` signal) and `provideBfSidebarState()` in
|
|
@@ -148,6 +148,8 @@ export class TabGroupLazyExampleComponent {
|
|
|
148
148
|
|
|
149
149
|
`[(selected)]` holds the shown panel's `value`; `(changed)` emits the new value after a user change, never for a write of `selected`. While `selected` matches no panel (unset, or a value that went away), the first enabled panel shows; `selected` itself keeps its value until the user picks a tab.
|
|
150
150
|
|
|
151
|
+
The underline slides to the newly selected tab, changing width as it goes (200 ms, `--bf-duration-layout`); it lands in place at once on the first render and after a resize, and always under `prefers-reduced-motion`. The panel a user switches to fades in over 200 ms (`animate-panel-in`); the first panel shown, and every panel under reduced motion, appears at once.
|
|
152
|
+
|
|
151
153
|
## Sizes and width
|
|
152
154
|
|
|
153
155
|
`size` sets the tabs' height: `sm` 32 px, `md` 40 px, `lg` 48 px. Unset, it follows `provideBfDefaults()`'s `controlSize`, `md` by default. `fitted` stretches the tabs to share the group's width (two or three tabs on a phone). When the tabs do not fit, the row scrolls sideways; focusing a tab with the keyboard scrolls it into view.
|
|
@@ -159,7 +161,7 @@ Under a mouse an unselected tab takes a `surface-muted` fill and `text` on hover
|
|
|
159
161
|
## Theming
|
|
160
162
|
|
|
161
163
|
- Tabs: `text-muted` at rest, hover `surface-muted` with `text`, pressed `surface-pressed`; top corners `rounded-tile`.
|
|
162
|
-
- Selected tab: `primary-text` with a 2 px `primary` underline on its bottom edge, so the selection never rests on colour alone (`CanvasText` under forced colours; `text-disabled` on a disabled selected tab).
|
|
164
|
+
- Selected tab: `primary-text` with a 2 px `primary` underline on its bottom edge, so the selection never rests on colour alone (`CanvasText` under forced colours; `text-disabled` on a disabled selected tab). It slides over `--bf-duration-layout` with the `ease-md` curve.
|
|
163
165
|
- Disabled tab: `text-disabled` (never opacity).
|
|
164
166
|
- The row: a 1 px `border` line under the tabs, across the group's width.
|
|
165
167
|
- Badge: `primary` with `on-primary` text, `rounded-control`, `text-micro`.
|
|
@@ -168,7 +170,7 @@ Under a mouse an unselected tab takes a `surface-muted` fill and `text` on hover
|
|
|
168
170
|
|
|
169
171
|
## Accessibility
|
|
170
172
|
|
|
171
|
-
The row is a `role="tablist"` named by `label`, else `provideBfLabels()`'s `tabGroup` ("Tabs"); give each group on a page its own `label`. Each tab is a native `<button role="tab">` with `aria-selected` and `aria-controls` naming its panel; each `bf-tab-panel` is a `role="tabpanel"` with `aria-labelledby` naming its tab and `tabindex="0"`, and an unselected panel is `hidden`. Only the selected tab is in the tab order (a roving tab stop), so <kbd>Tab</kbd> moves from it into the panel. Selection follows focus (automatic activation): the arrow keys, <kbd>Home</kbd> and <kbd>End</kbd> move to a tab and show its panel at once, so keep a panel's first render quick. A disabled tab is native-disabled and skipped. A badge's pill is `aria-hidden`; its count is read after the label from visually hidden text (`tabBadge(n)`, "3 new").
|
|
173
|
+
The row is a `role="tablist"` named by `label`, else `provideBfLabels()`'s `tabGroup` ("Tabs"); give each group on a page its own `label`. Each tab is a native `<button role="tab">` with `aria-selected` and `aria-controls` naming its panel; each `bf-tab-panel` is a `role="tabpanel"` with `aria-labelledby` naming its tab and `tabindex="0"`, and an unselected panel is `hidden`. Only the selected tab is in the tab order (a roving tab stop), so <kbd>Tab</kbd> moves from it into the panel. Selection follows focus (automatic activation): the arrow keys, <kbd>Home</kbd> and <kbd>End</kbd> move to a tab and show its panel at once, so keep a panel's first render quick. A disabled tab is native-disabled and skipped. The sliding underline is one decorative `aria-hidden` element of the row. A badge's pill is `aria-hidden`; its count is read after the label from visually hidden text (`tabBadge(n)`, "3 new").
|
|
172
174
|
|
|
173
175
|
### Keyboard
|
|
174
176
|
|
|
@@ -213,6 +215,20 @@ The row is a `role="tablist"` named by `label`, else `provideBfLabels()`'s `tabG
|
|
|
213
215
|
|
|
214
216
|
## Migration notes
|
|
215
217
|
|
|
218
|
+
### 0.5.0
|
|
219
|
+
|
|
220
|
+
The selected tab's underline is now one indicator element of the row that slides to the newly
|
|
221
|
+
selected tab, changing width as it goes (`--bf-duration-layout`, `ease-md`). The first placement
|
|
222
|
+
and a resize land at once, and so does everything under `prefers-reduced-motion`. It is measured
|
|
223
|
+
from the selected tab's inline-start offset, so it mirrors under `dir="rtl"`, and is re-measured
|
|
224
|
+
on resize and when labels, badges, size or `fitted` change. Until it has been measured (jsdom,
|
|
225
|
+
server render, a hidden group) the tab keeps drawing its own underline, so unit tests and the
|
|
226
|
+
first paint are unchanged. The indicator is `aria-hidden`; roles, keyboard and focus are
|
|
227
|
+
unchanged.
|
|
228
|
+
|
|
229
|
+
The panel a user switches to fades in (200 ms of opacity, new `--animate-panel-in`, behind
|
|
230
|
+
`motion-safe:`); the panel shown on the first render never does.
|
|
231
|
+
|
|
216
232
|
### 0.3.1
|
|
217
233
|
|
|
218
234
|
New `bf-tab-group`: in-page tabs over the content they switch, in both shells. A `tablist` of
|
package/ai/components/table.md
CHANGED
|
@@ -489,11 +489,12 @@ export class TablePagedExampleComponent {
|
|
|
489
489
|
|
|
490
490
|
`stack` lets the table itself fit a narrow space. With `stack="narrow"` it stacks while the table is narrower than 36rem (576 px at the default root size, Tailwind's `xl` container size): a container query on the table's own width, so a table in a narrow column or a side panel stacks even on a wide screen. The host is then a size container (`container-type: inline-size`), so give the table its width from its parent (a block or `w-full` / `flex-1`), not from its columns. With `stack="coarse"` it stacks under a coarse pointer at any width (phones, tablets, the Capacitor shell). The default `never` keeps the table as it is.
|
|
491
491
|
|
|
492
|
-
Stacked, each row is a sunken tile (`surface-sunken`, `rounded-tile`, the tile a raised card holds; a selected row keeps `primary-soft`). Its checkbox and first cell head the tile in bold; every other cell shows its column label at the start and its value at the end. The header row is visually hidden, and a bar above the tiles holds a labelled Select all checkbox (with `selectable`) and a Sort by select, since the hidden header's buttons are not shown. Its first option, Not sorted, shows while `sort` is null and sets it back to null; then every sortable column, ascending and descending (`tableSortBy`, `tableSortNone`, `tableSortAscending`, `tableSortDescending` labels). Choosing a column option sets `sort`, as a header click does. In a test, `BfTableHarness.getSortSelect()` returns that select's `BfSelectHarness
|
|
492
|
+
Stacked, each row is a sunken tile (`surface-sunken`, `rounded-tile`, the tile a raised card holds; a selected row keeps `primary-soft`). Its checkbox and first cell head the tile in bold; every other cell shows its column label at the start and its value at the end. The header row is visually hidden, and a bar above the tiles holds a labelled Select all checkbox (with `selectable`) and a Sort by select, since the hidden header's buttons are not shown. Its first option, Not sorted, shows while `sort` is null and sets it back to null; then every sortable column, ascending and descending (`tableSortBy`, `tableSortNone`, `tableSortAscending`, `tableSortDescending` labels). Choosing a column option sets `sort`, as a header click does. The Sort by select is a native `<select>` unless the app adds `provideBfSelect()` from `@bitforgehq/ui/overlay` to its providers: then it is the styled [bf-select](https://bitforge-ui.web.app/components/select) (still native under touch), through the `BF_TABLE_SORT_SELECT` token, so `@bitforgehq/ui` itself never loads the CDK. In a test, `BfTableHarness.getSortSelect()` returns that select's `BfSelectHarness`, in either form.
|
|
493
493
|
|
|
494
494
|
```ts
|
|
495
495
|
import { Component, computed, signal } from '@angular/core';
|
|
496
496
|
import {
|
|
497
|
+
BF_TABLE_SORT_SELECT,
|
|
497
498
|
BfBadgeComponent,
|
|
498
499
|
BfSegmentedComponent,
|
|
499
500
|
BfTableCellDirective,
|
|
@@ -502,6 +503,7 @@ import {
|
|
|
502
503
|
type BfTableColumn,
|
|
503
504
|
type BfTableSort,
|
|
504
505
|
} from '@bitforgehq/ui';
|
|
506
|
+
import { BfSelectComponent } from '@bitforgehq/ui/overlay';
|
|
505
507
|
|
|
506
508
|
interface Task {
|
|
507
509
|
id: string;
|
|
@@ -526,10 +528,16 @@ type Width = 'phone' | 'full';
|
|
|
526
528
|
* than 36rem: the selection checkbox and the first cell head the tile, and a bar above the tiles
|
|
527
529
|
* holds Select all and a Sort by select, whose first option, Not sorted, shows while `sort` is
|
|
528
530
|
* null and clears it. Switch the box between phone width and full width.
|
|
531
|
+
*
|
|
532
|
+
* The Sort by select is the styled `bf-select`. In an app, add `provideBfSelect()` from
|
|
533
|
+
* `@bitforgehq/ui/overlay` to `app.config.ts` once; this page provides `BF_TABLE_SORT_SELECT`
|
|
534
|
+
* on the example instead, so the docs site loads the select only with this example.
|
|
529
535
|
*/
|
|
530
536
|
@Component({
|
|
531
537
|
selector: 'app-example-table-stacked',
|
|
532
538
|
imports: [BfTableComponent, BfTableCellDirective, BfBadgeComponent, BfSegmentedComponent],
|
|
539
|
+
// In an app: provideBfSelect() in app.config.ts (see the comment above).
|
|
540
|
+
providers: [{ provide: BF_TABLE_SORT_SELECT, useValue: BfSelectComponent }],
|
|
533
541
|
template: `
|
|
534
542
|
<!-- A stacking table is a size container: its width comes from its parent, never its columns. -->
|
|
535
543
|
<div class="flex w-152 max-w-full flex-col gap-3">
|
|
@@ -684,7 +692,7 @@ A table that can stack (`stack` other than `never`) sets explicit `table`, `rowg
|
|
|
684
692
|
| <kbd>Space</kbd> | Toggles the focused checkbox, or sorts by the focused header |
|
|
685
693
|
| <kbd>Enter</kbd> | Sorts by the focused header |
|
|
686
694
|
|
|
687
|
-
A stacked table's Sort by select
|
|
695
|
+
A stacked table's Sort by select has its own keys: the native select's, or with `provideBfSelect()` those of [bf-select](https://bitforge-ui.web.app/components/select#keyboard).
|
|
688
696
|
|
|
689
697
|
Text fields, selects and composite widgets (radios, comboboxes, sliders) in a cell keep their own arrow keys.
|
|
690
698
|
|
|
@@ -751,6 +759,13 @@ Selects or clears one row.
|
|
|
751
759
|
|
|
752
760
|
## Migration notes
|
|
753
761
|
|
|
762
|
+
### 0.5.0
|
|
763
|
+
|
|
764
|
+
New `BF_TABLE_SORT_SELECT` injection token: the component a stacked table renders as its "Sort
|
|
765
|
+
by" select (`null`, the default, keeps the native one). `provideBfSelect()` from
|
|
766
|
+
`@bitforgehq/ui/overlay` sets it to the styled `bf-select`, so the core entry still never imports
|
|
767
|
+
the CDK. `BfTableHarness.getSortSelect()` returns a working `BfSelectHarness` either way.
|
|
768
|
+
|
|
754
769
|
### 0.4.0
|
|
755
770
|
|
|
756
771
|
New: toggle cells for a settings matrix (rows of alert kinds, columns of channels, a `bf-toggle`
|
|
@@ -127,6 +127,7 @@ The button consumes `bf-menu-button`'s tokens (`bf-button`'s, or `bf-icon-button
|
|
|
127
127
|
- The three items are `role="menuitemradio"` with `aria-checked`, so a screen reader announces the current choice. The dot is drawn in CSS and adds nothing to the name.
|
|
128
128
|
- Choosing an item closes the menu and returns focus to the button.
|
|
129
129
|
- Hit area: at least 32 px, 44 px under a coarse pointer, as `bf-menu-button`.
|
|
130
|
+
- Motion: the menu fades and grows out of the button as it opens, and closes at once. Under `prefers-reduced-motion` it only fades in.
|
|
130
131
|
|
|
131
132
|
### Keyboard
|
|
132
133
|
|
|
@@ -138,6 +138,8 @@ The field shows the `primary` border and focus ring while any part has focus, th
|
|
|
138
138
|
|
|
139
139
|
The parts are a `role="group"` named by `label` (else `ariaLabel` or `ariaLabelledby`); each part is a `role="spinbutton"` named from the `timeInputHour`, `timeInputMinute`, `timeInputSecond` and `timeInputDayPeriod` labels, with `aria-valuemin`, `aria-valuemax`, `aria-valuenow` and `aria-valuetext` (the AM or PM name), and the field's `aria-invalid`, `aria-errormessage`, `aria-required`, `aria-readonly` and `aria-disabled`. The clock button is named by `timeInputOpenList`, with `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`. The list is a `role="listbox"` named by the same label, its times `role="option"` with `aria-selected` and `aria-disabled`; focus stays on the list and `aria-activedescendant` names the active time.
|
|
140
140
|
|
|
141
|
+
Motion: the list grows out of the field as it opens (a fade, a slight scale and a 4 px slide, 180 ms) and fades back as it closes (130 ms). Focus returns at once and the closing list is inert. Under `prefers-reduced-motion` it only fades.
|
|
142
|
+
|
|
141
143
|
### Keyboard
|
|
142
144
|
|
|
143
145
|
| Key | Where | Action |
|
package/ai/components/toolbar.md
CHANGED
|
@@ -12,11 +12,10 @@ import {
|
|
|
12
12
|
BfButtonComponent,
|
|
13
13
|
BfInputComponent,
|
|
14
14
|
BfSegmentedComponent,
|
|
15
|
-
BfSelectComponent,
|
|
16
15
|
BfToolbarComponent,
|
|
17
16
|
type BfSegmentOption,
|
|
18
|
-
type BfSelectOption,
|
|
19
17
|
} from '@bitforgehq/ui';
|
|
18
|
+
import { BfSelectComponent, type BfSelectOption } from '@bitforgehq/ui/overlay';
|
|
20
19
|
|
|
21
20
|
type ProjectStatus = 'active' | 'paused' | 'done';
|
|
22
21
|
type StatusFilter = ProjectStatus | 'all';
|
|
@@ -125,7 +124,7 @@ export class ToolbarOverviewExampleComponent {
|
|
|
125
124
|
Row of search, filters, a view switch and trailing actions above a list or table. Every
|
|
126
125
|
control projected into it is `sm` unless it sets `size` itself.
|
|
127
126
|
|
|
128
|
-
A dense row above a list or table: the search field and filters, a view switch, a live result count and the trailing actions. `bf-toolbar` lays the row out, wraps it in a narrow column and makes every control in it `sm`; the controls themselves are ordinary `bf-input`, `bf-select
|
|
127
|
+
A dense row above a list or table: the search field and filters, a view switch, a live result count and the trailing actions. `bf-toolbar` lays the row out, wraps it in a narrow column and makes every control in it `sm`; the controls themselves are ordinary `bf-input`, `bf-select` (from `@bitforgehq/ui/overlay`), `bf-chip-group`, `bf-segmented` and `bf-button`s.
|
|
129
128
|
|
|
130
129
|
## When to use
|
|
131
130
|
|
|
@@ -191,13 +190,8 @@ The row is a wrapping flex row with an 8 px gap between items and between rows.
|
|
|
191
190
|
|
|
192
191
|
```ts
|
|
193
192
|
import { Component } from '@angular/core';
|
|
194
|
-
import {
|
|
195
|
-
|
|
196
|
-
BfInputComponent,
|
|
197
|
-
BfSelectComponent,
|
|
198
|
-
BfToolbarComponent,
|
|
199
|
-
type BfSelectOption,
|
|
200
|
-
} from '@bitforgehq/ui';
|
|
193
|
+
import { BfButtonComponent, BfInputComponent, BfToolbarComponent } from '@bitforgehq/ui';
|
|
194
|
+
import { BfSelectComponent, type BfSelectOption } from '@bitforgehq/ui/overlay';
|
|
201
195
|
|
|
202
196
|
/**
|
|
203
197
|
* A toolbar that wraps.
|
|
@@ -238,13 +232,8 @@ At phone width (in a desktop web app's narrow window or a narrow column) the sea
|
|
|
238
232
|
|
|
239
233
|
```ts
|
|
240
234
|
import { Component, signal } from '@angular/core';
|
|
241
|
-
import {
|
|
242
|
-
|
|
243
|
-
BfInputComponent,
|
|
244
|
-
BfSelectComponent,
|
|
245
|
-
BfToolbarComponent,
|
|
246
|
-
type BfSelectOption,
|
|
247
|
-
} from '@bitforgehq/ui';
|
|
235
|
+
import { BfButtonComponent, BfInputComponent, BfToolbarComponent } from '@bitforgehq/ui';
|
|
236
|
+
import { BfSelectComponent, type BfSelectOption } from '@bitforgehq/ui/overlay';
|
|
248
237
|
|
|
249
238
|
/**
|
|
250
239
|
* A toolbar at phone width.
|
|
@@ -317,7 +306,7 @@ The `status` element is `role="status"` (an `aria-live="polite"` region), always
|
|
|
317
306
|
|
|
318
307
|
## Slots
|
|
319
308
|
|
|
320
|
-
- `default`: The search field and the filters (bf-input, bf-
|
|
309
|
+
- `default`: The search field and the filters (bf-input, bf-chip-group, bf-select from /overlay), in order.
|
|
321
310
|
- `view`: A view switch after the filters, such as a bf-segmented of list and grid.
|
|
322
311
|
- `actions`: The trailing actions, kept together at the inline end of the row, beside the status.
|
|
323
312
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# BfChatComposerHarness
|
|
2
|
+
|
|
3
|
+
Test harness for the chat composer: types, sends, stops and reads its state
|
|
4
|
+
|
|
5
|
+
Class from `@bitforgehq/ui/testing` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
Harness for `bf-chat-composer` (`@bitforgehq/ui/overlay`). Its `label` filter matches the text
|
|
8
|
+
field's name: the visible label, else its `aria-label` ("Message" by default).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { BfChatComposerHarness } from '@bitforgehq/ui/testing';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
class BfChatComposerHarness extends ComponentHarness
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Methods
|
|
21
|
+
|
|
22
|
+
### `getLabel(): Promise<string>`
|
|
23
|
+
|
|
24
|
+
The text field's name: the visible label, else its `aria-label`.
|
|
25
|
+
|
|
26
|
+
### `getValue(): Promise<string>`
|
|
27
|
+
|
|
28
|
+
The text in the field.
|
|
29
|
+
|
|
30
|
+
### `setValue(text: string): Promise<void>`
|
|
31
|
+
|
|
32
|
+
Replaces the text as the user would type it (`changed` and the value update).
|
|
33
|
+
|
|
34
|
+
| Parameter | Type | Description |
|
|
35
|
+
| --------- | -------- | ------------- |
|
|
36
|
+
| `text` | `string` | The new text. |
|
|
37
|
+
|
|
38
|
+
### `send(): Promise<void>`
|
|
39
|
+
|
|
40
|
+
Sends the text with the send button, as a click does. Does nothing while it cannot send.
|
|
41
|
+
|
|
42
|
+
### `pressEnter(): Promise<void>`
|
|
43
|
+
|
|
44
|
+
Sends the text with `Enter` in the field, as the keyboard does.
|
|
45
|
+
|
|
46
|
+
### `stop(): Promise<void>`
|
|
47
|
+
|
|
48
|
+
Stops the running reply with the stop button. Does nothing unless a reply is running.
|
|
49
|
+
|
|
50
|
+
### `isRunning(): Promise<boolean>`
|
|
51
|
+
|
|
52
|
+
Whether a reply is running, so the button stops instead of sending.
|
|
53
|
+
|
|
54
|
+
### `isDisabled(): Promise<boolean>`
|
|
55
|
+
|
|
56
|
+
Whether the composer is disabled (its text field is).
|
|
57
|
+
|
|
58
|
+
### `canAct(): Promise<boolean>`
|
|
59
|
+
|
|
60
|
+
Whether the button can send (or stop) now: not disabled and, to send, with text.
|
|
61
|
+
|
|
62
|
+
### `getButtonLabel(): Promise<string>`
|
|
63
|
+
|
|
64
|
+
The button's name, "Send" or "Stop" by default.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# BfChatMessageRole
|
|
2
|
+
|
|
3
|
+
Who wrote a chat message, the user or the assistant
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
Who wrote a `bf-chat-message`: `user` (a tinted bubble at the inline end) or `assistant` (full
|
|
8
|
+
width, no bubble).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfChatMessageRole } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfChatMessageRole = 'user' | 'assistant'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `user`
|
|
23
|
+
- `assistant`
|
|
24
|
+
|
|
25
|
+
## Used by
|
|
26
|
+
|
|
27
|
+
- [bf-chat-message](../components/chat-message.md)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# BfChatMessageStatus
|
|
2
|
+
|
|
3
|
+
How a chat message ended: done, stopped by the user, or failed
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
How a `bf-chat-message` ended: `done` (the default, no status line), `stopped` (the user
|
|
8
|
+
stopped the reply) or `failed` (it did not arrive or was not sent).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfChatMessageStatus } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfChatMessageStatus = 'done' | 'stopped' | 'failed'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `done`
|
|
23
|
+
- `stopped`
|
|
24
|
+
- `failed`
|
|
25
|
+
|
|
26
|
+
## Used by
|
|
27
|
+
|
|
28
|
+
- [bf-chat-message](../components/chat-message.md)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# BfFadeInDirective
|
|
2
|
+
|
|
3
|
+
Fades an image in once it has loaded instead of popping in
|
|
4
|
+
|
|
5
|
+
Directive from `@bitforgehq/ui` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
Fades an image in when it has loaded instead of letting it pop in line by line: put
|
|
8
|
+
`bfFadeIn` on the `<img>`. The image stays transparent until its `load` (or `error`) event,
|
|
9
|
+
then fades in over 260 ms (`duration-slow`), at once under `prefers-reduced-motion: reduce`. An
|
|
10
|
+
image that is already loaded when it renders (from the cache) shows straight away. Reserve its
|
|
11
|
+
space (`width`/`height` attributes or an aspect ratio) so the layout does not move when it
|
|
12
|
+
arrives; for a placeholder while it loads, put a `bf-skeleton` behind it.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { BfFadeInDirective } from '@bitforgehq/ui';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Selector: `img[bfFadeIn]`
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# BfFileInputHarness
|
|
2
|
+
|
|
3
|
+
Test harness for the file input: drops files and reads the list and rejections
|
|
4
|
+
|
|
5
|
+
Class from `@bitforgehq/ui/testing` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
Harness for `bf-file-input`, in both looks. `addFiles()` drops files on the field, so they go
|
|
8
|
+
through the same `accept`, `maxSize` and `maxFiles` rules as a real drop; read the outcome with
|
|
9
|
+
`getFileNames()` and `getRejected()`. It works by file name, so a test never needs the rows.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { BfFileInputHarness } from '@bitforgehq/ui/testing';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Signature
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
class BfFileInputHarness extends ComponentHarness
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Methods
|
|
22
|
+
|
|
23
|
+
### `getLabel(): Promise<string>`
|
|
24
|
+
|
|
25
|
+
The visible label without the required mark, else `ariaLabel`.
|
|
26
|
+
|
|
27
|
+
### `getErrorText(): Promise<string>`
|
|
28
|
+
|
|
29
|
+
The error text under the field (an explicit message, or the first form error once touched).
|
|
30
|
+
|
|
31
|
+
### `getVariant(): Promise<'field' | 'dropzone'>`
|
|
32
|
+
|
|
33
|
+
The look of the field.
|
|
34
|
+
|
|
35
|
+
### `isDisabled(): Promise<boolean>`
|
|
36
|
+
|
|
37
|
+
Whether the field is disabled.
|
|
38
|
+
|
|
39
|
+
### `isReadonly(): Promise<boolean>`
|
|
40
|
+
|
|
41
|
+
Whether the field is read-only: it has no pick target.
|
|
42
|
+
|
|
43
|
+
### `addFiles(files: File[]): Promise<void>`
|
|
44
|
+
|
|
45
|
+
Drops files on the field, as a user would. On a disabled or read-only field it does nothing,
|
|
46
|
+
like the UI.
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Description |
|
|
49
|
+
| --------- | -------- | ------------------ |
|
|
50
|
+
| `files` | `File[]` | The files to drop. |
|
|
51
|
+
|
|
52
|
+
### `getFileNames(): Promise<string[]>`
|
|
53
|
+
|
|
54
|
+
The names of the chosen files, in order (rejected files are not included).
|
|
55
|
+
|
|
56
|
+
### `getRejected(): Promise<{ name: string; message: string }[]>`
|
|
57
|
+
|
|
58
|
+
The files the last pick or drop refused, each with its reason, until they are dismissed.
|
|
59
|
+
|
|
60
|
+
### `removeFile(name: string): Promise<void>`
|
|
61
|
+
|
|
62
|
+
Removes the chosen file with this name, as the row's remove button does. Throws when no
|
|
63
|
+
chosen file has that name or the field cannot be edited.
|
|
64
|
+
|
|
65
|
+
| Parameter | Type | Description |
|
|
66
|
+
| --------- | -------- | ---------------- |
|
|
67
|
+
| `name` | `string` | The file's name. |
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# BfFileInputVariant
|
|
2
|
+
|
|
3
|
+
The two looks of a file picker, a compact field or a drop zone
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.5.0
|
|
6
|
+
|
|
7
|
+
The look of a `bf-file-input`: a compact field with a pick button (`field`), or a drop zone
|
|
8
|
+
(`dropzone`). Both have the same API and behaviour.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfFileInputVariant } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfFileInputVariant = 'field' | 'dropzone'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `field`
|
|
23
|
+
- `dropzone`
|
|
24
|
+
|
|
25
|
+
## Used by
|
|
26
|
+
|
|
27
|
+
- [bf-file-input](../components/file-input.md)
|