@bitforgehq/ui 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/README.md +4 -4
- package/ai/MANIFEST.index.json +36 -0
- package/ai/MANIFEST.json +414 -14
- package/ai/REFERENCE.index.json +35 -0
- package/ai/REFERENCE.json +184 -8
- package/ai/UI_GUIDE.md +25 -4
- package/ai/components/badge.md +39 -2
- package/ai/components/list-item.md +105 -9
- package/ai/components/step.md +112 -0
- package/ai/components/steps.md +124 -0
- package/ai/components/table.md +98 -2
- package/ai/components/timeline-event.md +144 -0
- package/ai/components/timeline.md +201 -0
- package/ai/components/toggle.md +11 -1
- package/ai/reference/bf-action-directive.md +3 -1
- package/ai/reference/bf-badge-emphasis.md +27 -0
- package/ai/reference/bf-labels.md +1 -0
- package/ai/reference/bf-step-heading-level.md +28 -0
- package/ai/reference/bf-table-align.md +1 -1
- package/ai/reference/bf-table-column-align.md +33 -0
- package/ai/reference/bf-table-column.md +7 -7
- package/ai/reference/bf-table-harness.md +12 -0
- package/ai/reference/bf-timeline-tone.md +31 -0
- package/ai/reference/bf-toggle-harness.md +55 -0
- package/ai/reference/provide-bf-labels.md +1 -1
- package/dark-ink.css +124 -0
- package/fesm2022/bitforgehq-ui-mobile.mjs +2 -1
- package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-testing.mjs +51 -2
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui.mjs +682 -32
- package/fesm2022/bitforgehq-ui.mjs.map +1 -1
- package/llms-full.txt +1072 -15
- package/llms.txt +9 -0
- package/package.json +2 -1
- package/theme.css +24 -0
- package/types/bitforgehq-ui-testing.d.ts +76 -1
- package/types/bitforgehq-ui.d.ts +288 -8
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# bf-timeline-event
|
|
2
|
+
|
|
3
|
+
One timeline event with a coloured marker, its text, actor and time
|
|
4
|
+
|
|
5
|
+
`BfTimelineEventComponent` from `@bitforgehq/ui` · Data display · since 0.4.0
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Component } from '@angular/core';
|
|
11
|
+
import { RouterLink } from '@angular/router';
|
|
12
|
+
import { BfTimelineComponent, BfTimelineEventComponent } from '@bitforgehq/ui';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The bf-timeline-event overview.
|
|
16
|
+
*
|
|
17
|
+
* Live demo of `bf-timeline-event`: one event per tone in a `bf-timeline`, with and without an
|
|
18
|
+
* actor, one with a link in its text and one with a relative `timeText`.
|
|
19
|
+
*/
|
|
20
|
+
@Component({
|
|
21
|
+
selector: 'app-example-timeline-event-overview',
|
|
22
|
+
imports: [RouterLink, BfTimelineComponent, BfTimelineEventComponent],
|
|
23
|
+
template: `
|
|
24
|
+
<bf-timeline label="Event tones" class="max-w-xl">
|
|
25
|
+
<bf-timeline-event actor="Lena Meier" time="2026-10-28T15:40:00Z" tone="primary">
|
|
26
|
+
Opened
|
|
27
|
+
<a routerLink="/components/timeline" fragment="links-in-events">CVE-2026-1234</a>
|
|
28
|
+
</bf-timeline-event>
|
|
29
|
+
<bf-timeline-event actor="CI" time="2026-10-28T15:10:00Z" tone="success">
|
|
30
|
+
All checks passed
|
|
31
|
+
</bf-timeline-event>
|
|
32
|
+
<bf-timeline-event actor="Dependency bot" time="2026-10-28T14:00:00Z" tone="warning">
|
|
33
|
+
Found an outdated base image
|
|
34
|
+
</bf-timeline-event>
|
|
35
|
+
<bf-timeline-event actor="CI" time="2026-10-28T13:05:00Z" tone="danger">
|
|
36
|
+
CI failed on the security scan
|
|
37
|
+
</bf-timeline-event>
|
|
38
|
+
<bf-timeline-event time="2026-10-28T12:00:00Z" timeText="4 hours ago" tone="info">
|
|
39
|
+
A new advisory was published
|
|
40
|
+
</bf-timeline-event>
|
|
41
|
+
<bf-timeline-event actor="Jonas Keller" time="2026-10-27T16:02:00Z">
|
|
42
|
+
Assigned the finding to Lena Meier
|
|
43
|
+
</bf-timeline-event>
|
|
44
|
+
</bf-timeline>
|
|
45
|
+
`,
|
|
46
|
+
})
|
|
47
|
+
export class TimelineEventOverviewExampleComponent {}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Overview
|
|
51
|
+
|
|
52
|
+
One event of a `bf-timeline`: a marker coloured by `tone`, the event text (the default slot,
|
|
53
|
+
which may hold links), then who did it (`actor`) and when (`time`, in a `time` element).
|
|
54
|
+
|
|
55
|
+
One event of a [`bf-timeline`](https://bitforge-ui.web.app/components/timeline): a marker coloured by `tone`, the event text from the default slot, then a meta line with `actor` and `time`. Place events in a `bf-timeline`, which gives them the list semantics and the time format; the line between the markers ends at the last event.
|
|
56
|
+
|
|
57
|
+
## When to use
|
|
58
|
+
|
|
59
|
+
Use `bf-timeline-event` for each dated entry of a `bf-timeline`: a change, a comment, a CI run. Use [bf-list-item](https://bitforge-ui.web.app/components/list-item) instead for a row the user opens or acts on.
|
|
60
|
+
|
|
61
|
+
## Basic usage
|
|
62
|
+
|
|
63
|
+
`actor`, `time` (a `Date` or an ISO 8601 string) and `tone` are inputs; the text is the content and may hold links, which take the link style. `timeText` replaces the formatted time with your own text while the `datetime` keeps the exact value. `bfSlot="end"` holds a small action, at the inline end on a wide timeline and below the text on a narrow one.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { Component } from '@angular/core';
|
|
67
|
+
import { BfTimelineComponent, BfTimelineEventComponent } from '@bitforgehq/ui';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* An event's actor, time and tone.
|
|
71
|
+
*
|
|
72
|
+
* Two events of a CVE side panel: one by a person with an exact time, one by a bot with a relative
|
|
73
|
+
* `timeText` whose `datetime` keeps the exact value.
|
|
74
|
+
*/
|
|
75
|
+
@Component({
|
|
76
|
+
selector: 'app-example-timeline-event-basic',
|
|
77
|
+
imports: [BfTimelineComponent, BfTimelineEventComponent],
|
|
78
|
+
template: `
|
|
79
|
+
<bf-timeline label="CVE history" class="max-w-sm">
|
|
80
|
+
<bf-timeline-event actor="Lena Meier" time="2026-10-28T15:40:00Z" tone="warning">
|
|
81
|
+
Accepted the risk until the next release
|
|
82
|
+
</bf-timeline-event>
|
|
83
|
+
<bf-timeline-event
|
|
84
|
+
actor="Advisory bot"
|
|
85
|
+
time="2026-10-28T10:00:00Z"
|
|
86
|
+
timeText="6 hours ago"
|
|
87
|
+
tone="info"
|
|
88
|
+
>
|
|
89
|
+
Imported the advisory
|
|
90
|
+
</bf-timeline-event>
|
|
91
|
+
</bf-timeline>
|
|
92
|
+
`,
|
|
93
|
+
})
|
|
94
|
+
export class TimelineEventBasicExampleComponent {}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Desktop
|
|
98
|
+
|
|
99
|
+
An event has no hover and no focus stop of its own; only the links in its text and the controls in its `end` slot are interactive. It renders the same inside `provideBfShell()`.
|
|
100
|
+
|
|
101
|
+
## Theming
|
|
102
|
+
|
|
103
|
+
- Marker: `text-subtle`, `primary`, `success`, `warning`, `danger` or `info`; `CanvasText` under forced colours. Line: `border`.
|
|
104
|
+
- Text `text-body` in `text`, links `primary-text`; meta line `text-caption` in `text-muted`.
|
|
105
|
+
|
|
106
|
+
## Accessibility
|
|
107
|
+
|
|
108
|
+
Inside a `bf-timeline` the event is a `listitem`; on its own it has no role. The marker is `aria-hidden`; the time is a `time` element with an ISO `datetime`, and the separator between actor and time is hidden from assistive technology.
|
|
109
|
+
|
|
110
|
+
## Inputs
|
|
111
|
+
|
|
112
|
+
| Name | Type | Default | Description |
|
|
113
|
+
| ---------- | ------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
114
|
+
| `actor` | `string` | `''` | Who did it, such as a person or a bot; empty for a system event. |
|
|
115
|
+
| `time` | `Date \| string \| null` | `null` | When it happened: a Date or an ISO 8601 string; empty or invalid shows no time. |
|
|
116
|
+
| `timeText` | `string` | `''` | Shown in place of the formatted time, such as "vor 2 Std."; the `time` element's `datetime` keeps the exact value. |
|
|
117
|
+
| `tone` | `BfTimelineTone` (`'neutral' \| 'primary' \| 'success' \| 'warning' \| 'danger' \| 'info'`) | `'neutral'` | The marker's colour. |
|
|
118
|
+
|
|
119
|
+
## Slots
|
|
120
|
+
|
|
121
|
+
- `default`: The event text; links in it take the link style.
|
|
122
|
+
- `end`: Content at the inline end on a wide timeline and below the text on a narrow one, such as a button.
|
|
123
|
+
|
|
124
|
+
## Notes
|
|
125
|
+
|
|
126
|
+
### Do
|
|
127
|
+
|
|
128
|
+
- Write the text as what happened ("Assigned to Lena Meier"), and link the object it names.
|
|
129
|
+
|
|
130
|
+
### Don't
|
|
131
|
+
|
|
132
|
+
- Don't put more than one small action in the `end` slot; open the details elsewhere.
|
|
133
|
+
|
|
134
|
+
## Migration notes
|
|
135
|
+
|
|
136
|
+
### 0.4.0
|
|
137
|
+
|
|
138
|
+
New: `bf-timeline-event`, one event of a `bf-timeline`: a 10 px marker coloured by `tone`
|
|
139
|
+
(`neutral`, `primary`, `success`, `warning`, `danger`, `info`; new type `BfTimelineTone`) on a
|
|
140
|
+
`border` line that ends at the last event, the event text in the default slot (links in it take
|
|
141
|
+
the link style), then `actor` and `time` (a `Date` or an ISO 8601 string, in a `time` element;
|
|
142
|
+
`timeText` shows a relative text while `datetime` keeps the exact value; an invalid time shows
|
|
143
|
+
nothing). A `bfSlot="end"` action sits at the inline end, or under the text once the event is
|
|
144
|
+
narrow.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# bf-timeline
|
|
2
|
+
|
|
3
|
+
Dated list of events with who did what and when, on a vertical line
|
|
4
|
+
|
|
5
|
+
`BfTimelineComponent` from `@bitforgehq/ui` · Data display · since 0.4.0
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Component } from '@angular/core';
|
|
11
|
+
import { RouterLink } from '@angular/router';
|
|
12
|
+
import { BfTimelineComponent, BfTimelineEventComponent } from '@bitforgehq/ui';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The bf-timeline overview.
|
|
16
|
+
*
|
|
17
|
+
* Live demo of `bf-timeline`: the history of a security finding, newest first. A system event has
|
|
18
|
+
* no actor, the pull request is a link in the event text, the failed CI run is `danger` and the
|
|
19
|
+
* fix `success`.
|
|
20
|
+
*/
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'app-example-timeline-overview',
|
|
23
|
+
imports: [RouterLink, BfTimelineComponent, BfTimelineEventComponent],
|
|
24
|
+
template: `
|
|
25
|
+
<bf-timeline label="Finding history" class="max-w-xl">
|
|
26
|
+
<bf-timeline-event actor="Lena Meier" time="2026-10-28T15:40:00Z" tone="success">
|
|
27
|
+
Marked the finding as fixed
|
|
28
|
+
</bf-timeline-event>
|
|
29
|
+
<bf-timeline-event actor="CI" time="2026-10-28T13:05:00Z" tone="danger">
|
|
30
|
+
CI failed on the security scan
|
|
31
|
+
</bf-timeline-event>
|
|
32
|
+
<bf-timeline-event actor="Jonas Keller" time="2026-10-28T11:20:00Z" tone="primary">
|
|
33
|
+
Linked
|
|
34
|
+
<a routerLink="." fragment="links-in-events">PR #123</a>
|
|
35
|
+
to the finding
|
|
36
|
+
</bf-timeline-event>
|
|
37
|
+
<bf-timeline-event actor="Jonas Keller" time="2026-10-27T16:02:00Z">
|
|
38
|
+
Assigned the finding to Lena Meier
|
|
39
|
+
</bf-timeline-event>
|
|
40
|
+
<bf-timeline-event time="2026-10-27T08:14:00Z">
|
|
41
|
+
Created by the nightly dependency scan
|
|
42
|
+
</bf-timeline-event>
|
|
43
|
+
</bf-timeline>
|
|
44
|
+
`,
|
|
45
|
+
})
|
|
46
|
+
export class TimelineOverviewExampleComponent {}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Overview
|
|
50
|
+
|
|
51
|
+
A dated history of events, newest first or oldest first as the consumer orders them: who did
|
|
52
|
+
what and when, each event a `bf-timeline-event` with a marker on a vertical line.
|
|
53
|
+
|
|
54
|
+
A timeline shows the history of one thing as dated events: who did what, and when. Each event is a [`bf-timeline-event`](https://bitforge-ui.web.app/components/timeline-event) with a coloured marker on a vertical line, its text (which may link the objects it names), then the actor and the time. The timeline shows the events in the order you give them, newest first or oldest first; it never sorts. It works the same in a desktop web app, a narrow side panel and the Capacitor shell.
|
|
55
|
+
|
|
56
|
+
## When to use
|
|
57
|
+
|
|
58
|
+
Use `bf-timeline` for a record's history or an audit trail: a finding that was created, assigned, linked to a pull request and fixed; the changes in a CVE side panel; who changed a setting. Use [bf-list](https://bitforge-ui.web.app/components/list) instead for items the user opens or acts on, and for navigation; a timeline is not a stepper through a process either, nor a feed the user scrolls for new items. For the details of one record, use a [bf-description-list](https://bitforge-ui.web.app/components/description-list).
|
|
59
|
+
|
|
60
|
+
## Events and tones
|
|
61
|
+
|
|
62
|
+
`actor` names who did it (leave it empty for a system event), `time` says when (a `Date` or an ISO 8601 string), and the content is the event text. `tone` colours the marker: `neutral` (the default) for routine events, `primary` for the current or most important one, `success` (fixed, merged), `warning`, `danger` (CI failed, a regression) and `info`. The colour only supports the text, so say what happened in words ("CI failed"), never by the colour alone. The line runs from each marker to the next and ends at the last event.
|
|
63
|
+
|
|
64
|
+
## Links in events
|
|
65
|
+
|
|
66
|
+
The event text is the default slot, so the objects it names can be links: a pull request, a repository, a CVE. Put a plain `<a href>` (or `<a routerLink>`) inline in the text; the event styles every link in its text in `primary-text`, underlined, with a thicker underline on hover and the focus ring on keyboard focus. Keep the link text the object's name ("PR #123"), not "here".
|
|
67
|
+
|
|
68
|
+
## Time format
|
|
69
|
+
|
|
70
|
+
The time is formatted with `Intl.DateTimeFormat` in the app's `LOCALE_ID`: a medium date and a short time by default (`28 Oct 2026, 14:30` in `en-GB`, `28.10.2026, 14:30` in `de-CH`), in the browser's time zone. `timeFormat` on the timeline takes any `Intl.DateTimeFormatOptions` for all its events (`{ dateStyle: 'short' }`, or a `timeZone`), and `locale` overrides the language for one timeline. `timeText` on an event shows your own text in place of the formatted time, such as a relative "vor 2 Std."; the `time` element's `datetime` keeps the exact value. An empty or invalid `time` shows no time, and a locale or options the browser refuses fall back to the defaults, so a bad value never throws.
|
|
71
|
+
|
|
72
|
+
## Audit trail
|
|
73
|
+
|
|
74
|
+
An audit trail is actor-heavy: every event names a person or a bot. The `end` slot holds a small action for one event, such as a Show diff button: it sits at the inline end while the timeline is wide, and wraps under the text in a narrow side panel or on a phone (once the text would get narrower than 16rem). It takes no space while empty.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { Component, signal } from '@angular/core';
|
|
78
|
+
import { BfButtonComponent, BfTimelineComponent, BfTimelineEventComponent } from '@bitforgehq/ui';
|
|
79
|
+
|
|
80
|
+
interface AuditEntry {
|
|
81
|
+
id: string;
|
|
82
|
+
actor: string;
|
|
83
|
+
action: string;
|
|
84
|
+
time: string;
|
|
85
|
+
ago: string;
|
|
86
|
+
diff: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const ENTRIES: readonly AuditEntry[] = [
|
|
90
|
+
{
|
|
91
|
+
id: 'severity',
|
|
92
|
+
actor: 'Lena Meier',
|
|
93
|
+
action: 'Raised the severity from Medium to High',
|
|
94
|
+
time: '2026-10-28T14:10:00Z',
|
|
95
|
+
ago: '2 hours ago',
|
|
96
|
+
diff: true,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'policy',
|
|
100
|
+
actor: 'Policy bot',
|
|
101
|
+
action: 'Applied the "Critical CVEs block releases" policy',
|
|
102
|
+
time: '2026-10-28T09:30:00Z',
|
|
103
|
+
ago: '7 hours ago',
|
|
104
|
+
diff: true,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'owner',
|
|
108
|
+
actor: 'Jonas Keller',
|
|
109
|
+
action: 'Set the owner to the Platform team',
|
|
110
|
+
time: '2026-10-27T16:45:00Z',
|
|
111
|
+
ago: 'Yesterday',
|
|
112
|
+
diff: false,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* An audit trail with relative times and an action per event.
|
|
118
|
+
*
|
|
119
|
+
* Every event names its actor, `timeText` shows a relative time while `datetime` keeps the exact
|
|
120
|
+
* one, and the `end` slot holds a Show diff button: at the inline end while the timeline is wide,
|
|
121
|
+
* under the text in a narrow panel.
|
|
122
|
+
*/
|
|
123
|
+
@Component({
|
|
124
|
+
selector: 'app-example-timeline-audit',
|
|
125
|
+
imports: [BfButtonComponent, BfTimelineComponent, BfTimelineEventComponent],
|
|
126
|
+
template: `
|
|
127
|
+
<div class="flex max-w-xl flex-col gap-3">
|
|
128
|
+
<bf-timeline label="Audit trail">
|
|
129
|
+
@for (entry of entries; track entry.id) {
|
|
130
|
+
<bf-timeline-event [actor]="entry.actor" [time]="entry.time" [timeText]="entry.ago">
|
|
131
|
+
{{ entry.action }}
|
|
132
|
+
@if (entry.diff) {
|
|
133
|
+
<bf-button bfSlot="end" variant="outline" size="sm" (clicked)="showDiff(entry)">
|
|
134
|
+
Show diff
|
|
135
|
+
</bf-button>
|
|
136
|
+
}
|
|
137
|
+
</bf-timeline-event>
|
|
138
|
+
}
|
|
139
|
+
</bf-timeline>
|
|
140
|
+
<p data-status aria-live="polite" class="text-caption text-text-muted">{{ status() }}</p>
|
|
141
|
+
</div>
|
|
142
|
+
`,
|
|
143
|
+
})
|
|
144
|
+
export class TimelineAuditExampleComponent {
|
|
145
|
+
readonly entries = ENTRIES;
|
|
146
|
+
readonly status = signal('No diff open.');
|
|
147
|
+
|
|
148
|
+
/** A real app would open the change in a side panel. */
|
|
149
|
+
showDiff(entry: AuditEntry): void {
|
|
150
|
+
this.status.set(`Diff of "${entry.action}" by ${entry.actor}.`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Desktop
|
|
156
|
+
|
|
157
|
+
The timeline itself is not interactive: no hover, no pointer cursor, no focus stop. Only the links in the event text and the controls in an `end` slot take focus, with their own hover and focus ring. Its spacing does not follow `provideBfDefaults()`: the events keep one rhythm at every density, and it has no `size`. Inside `provideBfShell()` it renders and behaves the same; the `end` slot's buttons bring their own 44 px touch height.
|
|
158
|
+
|
|
159
|
+
## Theming
|
|
160
|
+
|
|
161
|
+
- Marker: a 10 px dot (`rounded-control`) in `text-subtle` (neutral), `primary`, `success`, `warning`, `danger` or `info`; `CanvasText` under forced colours.
|
|
162
|
+
- Line: a 1 px `border` line from marker to marker.
|
|
163
|
+
- Text: `text-body` in `text`; links `primary-text`, underlined, `ring` on keyboard focus. Meta line: `text-caption` in `text-muted`.
|
|
164
|
+
- Spacing: 12 px between the marker and the text, 20 px between events.
|
|
165
|
+
|
|
166
|
+
## Accessibility
|
|
167
|
+
|
|
168
|
+
The timeline is a list (`role="list"`, named by `label` through `aria-label`) and each event inside it a `listitem`, so a screen reader announces the number of events and the position of each. An event outside a `bf-timeline` claims no role. The marker and the line are `aria-hidden`; the tone is decoration, so the text must say what happened. The time is a `time` element whose `datetime` is the ISO value, and the separator between actor and time is hidden from assistive technology. Links and `end` slot controls are native elements in reading order.
|
|
169
|
+
|
|
170
|
+
## Inputs
|
|
171
|
+
|
|
172
|
+
| Name | Type | Default | Description |
|
|
173
|
+
| ------------ | ---------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
174
|
+
| `label` | `string` | `''` | The list's accessible name, such as "History"; empty leaves the list unnamed (a visible heading above it already names the section). |
|
|
175
|
+
| `timeFormat` | `Intl.DateTimeFormatOptions` | `TIMELINE_TIME_FORMAT` | `Intl.DateTimeFormat` options of every event's time; by default a medium date and a short time (`dateStyle: 'medium'`, `timeStyle: 'short'`). |
|
|
176
|
+
| `locale` | `string` | `''` | BCP 47 locale of the times, such as `de-CH`; empty follows the app's `LOCALE_ID`. |
|
|
177
|
+
|
|
178
|
+
## Slots
|
|
179
|
+
|
|
180
|
+
- `default`: The events, each a `bf-timeline-event`, in the order to show them.
|
|
181
|
+
|
|
182
|
+
## Notes
|
|
183
|
+
|
|
184
|
+
### Do
|
|
185
|
+
|
|
186
|
+
- Give the timeline a `label` when no visible heading names it, and keep one order (newest first) across the app.
|
|
187
|
+
- Name the actor and the object in every event; link the object.
|
|
188
|
+
|
|
189
|
+
### Don't
|
|
190
|
+
|
|
191
|
+
- Don't use a timeline for navigation or for steps the user still has to take.
|
|
192
|
+
- Don't carry meaning in the tone alone; say "CI failed", not just a red dot.
|
|
193
|
+
|
|
194
|
+
## Migration notes
|
|
195
|
+
|
|
196
|
+
### 0.4.0
|
|
197
|
+
|
|
198
|
+
New: `bf-timeline`, a dated history of events (who did what, and when) for a record's history
|
|
199
|
+
or an audit trail, in both shells. A `role="list"` named by `label`, in the order the consumer
|
|
200
|
+
gives (it never sorts); each event's time is formatted with `Intl.DateTimeFormat` in the app's
|
|
201
|
+
`LOCALE_ID` (`timeFormat`, default a medium date and a short time; `locale` overrides it).
|
package/ai/components/toggle.md
CHANGED
|
@@ -130,9 +130,11 @@ export class ToggleListRowExampleComponent {
|
|
|
130
130
|
}
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
In a table of switches (a settings matrix: alert kinds by channel), each cell's toggle is named after its column and row with `ariaLabel`; see [bf-table](https://bitforge-ui.web.app/components/table)'s Toggle cells.
|
|
134
|
+
|
|
133
135
|
## Sizes
|
|
134
136
|
|
|
135
|
-
`sm` (32 px row, 24×40 track), `md` (default, 40 px row, 28×48 track), `lg` (48 px row, 32×56 track). Unset, `size` follows `provideBfDefaults()`'s `controlSize`, `md` by default (`provideBfDefaults({ size: 'lg' })` enlarges every control of a Capacitor app; `{ size: 'sm' }` in a component's `providers` makes a dense sub-tree). Under a fine pointer the row is the hit area (32 px and up, above the 24 px of WCAG 2.5.8); under a coarse pointer (touch) `sm` and `md` rows grow to 44 px. The knob travels to the inline end, so it moves left under `dir="rtl"`.
|
|
137
|
+
`sm` (32 px row, 24×40 track), `md` (default, 40 px row, 28×48 track), `lg` (48 px row, 32×56 track). Unset, `size` follows `provideBfDefaults()`'s `controlSize`, `md` by default (`provideBfDefaults({ size: 'lg' })` enlarges every control of a Capacitor app; `{ size: 'sm' }` in a component's `providers` makes a dense sub-tree). Under a fine pointer the row is the hit area (32 px and up, above the 24 px of WCAG 2.5.8); under a coarse pointer (touch) `sm` and `md` rows grow to 44 px, and a label-less `sm` switch (40 px wide) also takes a 44 px width, its track centred. The knob travels to the inline end, so it moves left under `dir="rtl"`.
|
|
136
138
|
|
|
137
139
|
```ts
|
|
138
140
|
import { Component, signal } from '@angular/core';
|
|
@@ -325,6 +327,14 @@ Focuses the native switch; Signal Forms calls it from `focusBoundControl()`.
|
|
|
325
327
|
|
|
326
328
|
## Migration notes
|
|
327
329
|
|
|
330
|
+
### 0.4.0
|
|
331
|
+
|
|
332
|
+
A label-less `sm` toggle (a table cell) takes a 44 px min-width under a coarse pointer, its track
|
|
333
|
+
centred, so its touch target is 44 × 44 px (it was 40 px wide). Nothing changes under a fine
|
|
334
|
+
pointer or for `md` and `lg`. `@bitforgehq/ui/testing`: new `BfToggleHarness` (`with({ label })`
|
|
335
|
+
by the switch's computed name, `getLabel()`, `isChecked()`, `isDisabled()`, `isReadonly()`,
|
|
336
|
+
`toggle()`, `check()`, `uncheck()`, `getErrorText()`).
|
|
337
|
+
|
|
328
338
|
### 0.3.0
|
|
329
339
|
|
|
330
340
|
New `ariaLabelledby` input: the id of the element that names the switch when no visible `label`
|
|
@@ -12,7 +12,9 @@ exposed: the heading stays a heading and the accessible name is the title alone.
|
|
|
12
12
|
with the nearest card or row, which then draws the pointer, the hover and, while the action has
|
|
13
13
|
keyboard focus, the focus ring; a card is never lit by the actions of rows nested in it. Give
|
|
14
14
|
secondary controls inside the surface `class="relative z-1"` so they stay clickable above the
|
|
15
|
-
stretched area.
|
|
15
|
+
stretched area. When the surface marks a state that belongs in the name (an `unread` list
|
|
16
|
+
row), the directive names the element `aria-labelledby="<state id> <own id>"`, so the link reads
|
|
17
|
+
"Unread, Account", and restores the element's own `aria-labelledby` when the state goes.
|
|
16
18
|
|
|
17
19
|
```ts
|
|
18
20
|
import { BfActionDirective } from '@bitforgehq/ui';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# BfBadgeEmphasis
|
|
2
|
+
|
|
3
|
+
The two badge emphases, the soft tint or the solid strong fill
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.4.0
|
|
6
|
+
|
|
7
|
+
How loud a `bf-badge` is: `soft`, a pale tint with tinted text (the default), or `strong`, a
|
|
8
|
+
solid fill with contrasting text for the one state that must stand out, such as "Critical".
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfBadgeEmphasis } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfBadgeEmphasis = 'soft' | 'strong'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `soft`
|
|
23
|
+
- `strong`
|
|
24
|
+
|
|
25
|
+
## Used by
|
|
26
|
+
|
|
27
|
+
- [bf-badge](../components/badge.md)
|
|
@@ -85,6 +85,7 @@ import { type BfLabels } from '@bitforgehq/ui';
|
|
|
85
85
|
| `chartValue` | `string` | `'Value'` | The value column header of a bf-donut-chart's data table. |
|
|
86
86
|
| `chartEmpty` | `string` | `'No data to show'` | bf-chart-card's text when it has no data and no `empty` slot. |
|
|
87
87
|
| `chartError` | `string` | `'The data could not be loaded'` | bf-chart-card's text when its data failed to load and it has no `error` slot. |
|
|
88
|
+
| `listItemUnread` | `string` | `'Unread'` | bf-list-item's visually hidden state text before the title of an `unread` row. |
|
|
88
89
|
| `validation` | `BfValidationMessages` | required | Default error text per validator kind (see `BfValidationMessages`). |
|
|
89
90
|
|
|
90
91
|
## Uses
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# BfStepHeadingLevel
|
|
2
|
+
|
|
3
|
+
The heading level a step title can take, two, three or four
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.4.0
|
|
6
|
+
|
|
7
|
+
The heading level of a `bf-step` title, for a guide whose steps hold enough content (screenshots,
|
|
8
|
+
code) that a screen-reader user moves between them by heading.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfStepHeadingLevel } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfStepHeadingLevel = 2 | 3 | 4
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `2`
|
|
23
|
+
- `3`
|
|
24
|
+
- `4`
|
|
25
|
+
|
|
26
|
+
## Used by
|
|
27
|
+
|
|
28
|
+
- [bf-step](../components/step.md)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# BfTableColumnAlign
|
|
2
|
+
|
|
3
|
+
The inline alignment of a table column: start, end, or centred for controls
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.4.0
|
|
6
|
+
|
|
7
|
+
Where a `bf-table` column lines up its header and cells: a `BfTableAlign`, or `center` for a
|
|
8
|
+
column of controls such as the toggles of a settings matrix. A new type, so `Record`s over the
|
|
9
|
+
released `BfTableAlign` keep compiling.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { type BfTableColumnAlign } from '@bitforgehq/ui';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Signature
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
type BfTableColumnAlign = BfTableAlign | 'center'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Values
|
|
22
|
+
|
|
23
|
+
- `start`
|
|
24
|
+
- `end`
|
|
25
|
+
- `center`
|
|
26
|
+
|
|
27
|
+
## Uses
|
|
28
|
+
|
|
29
|
+
- [BfTableAlign](bf-table-align.md)
|
|
30
|
+
|
|
31
|
+
## Used by
|
|
32
|
+
|
|
33
|
+
- [BfTableColumn](bf-table-column.md)
|
|
@@ -12,16 +12,16 @@ import { type BfTableColumn } from '@bitforgehq/ui';
|
|
|
12
12
|
|
|
13
13
|
## Properties
|
|
14
14
|
|
|
15
|
-
| Name | Type
|
|
16
|
-
| ---------- |
|
|
17
|
-
| `key` | `string`
|
|
18
|
-
| `label` | `string`
|
|
19
|
-
| `sortable` | `boolean`
|
|
20
|
-
| `align` | `
|
|
15
|
+
| Name | Type | Default | Description |
|
|
16
|
+
| ---------- | ----------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
17
|
+
| `key` | `string` | required | The row property the default cell shows; also the key a `bfTableCell` template names. |
|
|
18
|
+
| `label` | `string` | required | The header text. |
|
|
19
|
+
| `sortable` | `boolean` | `false` | Whether the header is a button that sets the table's `sort`. |
|
|
20
|
+
| `align` | `BfTableColumnAlign` (`'start' \| 'end' \| 'center'`) | `'start'` | The inline alignment of the header and cells; `end` also sets tabular figures, `center` centres a cell's control (a toggle, a checkbox) in the column. |
|
|
21
21
|
|
|
22
22
|
## Uses
|
|
23
23
|
|
|
24
|
-
- [
|
|
24
|
+
- [BfTableColumnAlign](bf-table-column-align.md)
|
|
25
25
|
|
|
26
26
|
## Used by
|
|
27
27
|
|
|
@@ -41,6 +41,18 @@ The text of one cell.
|
|
|
41
41
|
| `row` | `number` | The row's position, from 0. |
|
|
42
42
|
| `column` | `string` | The column's header text. |
|
|
43
43
|
|
|
44
|
+
### `getCellHarness<T extends ComponentHarness>(row: number, column: string, query: HarnessQuery<T>): Promise<T>`
|
|
45
|
+
|
|
46
|
+
A harness for a control in one cell, such as a `bf-toggle` of a settings matrix or a
|
|
47
|
+
`bf-select` in a custom cell. Throws for an unknown row or column, or when the cell holds no
|
|
48
|
+
matching control.
|
|
49
|
+
|
|
50
|
+
| Parameter | Type | Description |
|
|
51
|
+
| --------- | ----------------- | --------------------------------------------------- |
|
|
52
|
+
| `row` | `number` | The row's position, from 0. |
|
|
53
|
+
| `column` | `string` | The column's header text. |
|
|
54
|
+
| `query` | `HarnessQuery<T>` | The harness type, or a predicate from its `with()`. |
|
|
55
|
+
|
|
44
56
|
### `sortBy(column: string): Promise<void>`
|
|
45
57
|
|
|
46
58
|
Clicks a sortable column's header, as a user would: ascending first, then descending.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# BfTimelineTone
|
|
2
|
+
|
|
3
|
+
The marker colour of a timeline event, neutral, primary or a status
|
|
4
|
+
|
|
5
|
+
Type from `@bitforgehq/ui` · since 0.4.0
|
|
6
|
+
|
|
7
|
+
The colour of a `bf-timeline-event`'s marker: `neutral` (the default), `primary`, or a status
|
|
8
|
+
(`success`, `warning`, `danger`, `info`), such as danger for a failed CI run.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { type BfTimelineTone } from '@bitforgehq/ui';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Signature
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
type BfTimelineTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Values
|
|
21
|
+
|
|
22
|
+
- `neutral`
|
|
23
|
+
- `primary`
|
|
24
|
+
- `success`
|
|
25
|
+
- `warning`
|
|
26
|
+
- `danger`
|
|
27
|
+
- `info`
|
|
28
|
+
|
|
29
|
+
## Used by
|
|
30
|
+
|
|
31
|
+
- [bf-timeline-event](../components/timeline-event.md)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# BfToggleHarness
|
|
2
|
+
|
|
3
|
+
Test harness for the toggle: reads its name and state and switches it
|
|
4
|
+
|
|
5
|
+
Class from `@bitforgehq/ui/testing` · since 0.4.0
|
|
6
|
+
|
|
7
|
+
Harness for `bf-toggle`. Its `label` filter matches the switch's name: the text of the elements
|
|
8
|
+
`ariaLabelledby` names, else `ariaLabel`, else the visible label, so a label-less switch in a
|
|
9
|
+
table cell or a list row is found the same way.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { BfToggleHarness } from '@bitforgehq/ui/testing';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Signature
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
class BfToggleHarness extends ComponentHarness
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Methods
|
|
22
|
+
|
|
23
|
+
### `getLabel(): Promise<string>`
|
|
24
|
+
|
|
25
|
+
The switch's name, as the browser computes it: the text of the elements `ariaLabelledby`
|
|
26
|
+
names, else `ariaLabel`, else the visible label (the `label` text and the default slot).
|
|
27
|
+
|
|
28
|
+
### `isChecked(): Promise<boolean>`
|
|
29
|
+
|
|
30
|
+
Whether the switch is on.
|
|
31
|
+
|
|
32
|
+
### `isDisabled(): Promise<boolean>`
|
|
33
|
+
|
|
34
|
+
Whether the switch is disabled.
|
|
35
|
+
|
|
36
|
+
### `isReadonly(): Promise<boolean>`
|
|
37
|
+
|
|
38
|
+
Whether the switch is read-only (`aria-readonly`): it shows its state but a click does nothing.
|
|
39
|
+
|
|
40
|
+
### `toggle(): Promise<void>`
|
|
41
|
+
|
|
42
|
+
Clicks the switch, as a user would, so it turns on or off. Throws while it is disabled (a
|
|
43
|
+
user's click would do nothing); a read-only switch takes the click and stays as it is.
|
|
44
|
+
|
|
45
|
+
### `check(): Promise<void>`
|
|
46
|
+
|
|
47
|
+
Turns the switch on with a click; an on switch stays on. Throws while it is disabled.
|
|
48
|
+
|
|
49
|
+
### `uncheck(): Promise<void>`
|
|
50
|
+
|
|
51
|
+
Turns the switch off with a click; an off switch stays off. Throws while it is disabled.
|
|
52
|
+
|
|
53
|
+
### `getErrorText(): Promise<string>`
|
|
54
|
+
|
|
55
|
+
The error text under the switch.
|
|
@@ -17,7 +17,7 @@ every string. In a component's `providers` it covers that sub-tree's widgets and
|
|
|
17
17
|
`dateInputUnavailable`, `timeInputHour`, `timeInputMinute`, `timeInputSecond`,
|
|
18
18
|
`timeInputDayPeriod`, `timeInputOpenList`, `timeInputInvalid`, `timeInputMin`, `timeInputMax`,
|
|
19
19
|
`chart`, `chartLegend`, `chartValues`, `chartShowData`, `chartHideData`, `chartCategory`,
|
|
20
|
-
`chartValue`, `chartEmpty`, `chartError`, `validation`); the overlay services (`ok`, `cancel`,
|
|
20
|
+
`chartValue`, `chartEmpty`, `chartError`, `listItemUnread`, `validation`); the overlay services (`ok`, `cancel`,
|
|
21
21
|
`actions`, `sheet`, `modal`, `close`, `expand`, `collapse`, `sheetPosition`, `dialog`,
|
|
22
22
|
`notifications`) are root singletons and pick it up only when the caller passes its injector:
|
|
23
23
|
`open(…, { injector: inject(Injector) })`.
|