@bitforgehq/ui 0.3.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 +3665 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/ai/MANIFEST.index.json +383 -0
- package/ai/MANIFEST.json +7528 -0
- package/ai/REFERENCE.index.json +1461 -0
- package/ai/REFERENCE.json +7213 -0
- package/ai/UI_GUIDE.md +1159 -0
- package/ai/components/action-bar.md +209 -0
- package/ai/components/action-sheet.md +526 -0
- package/ai/components/alert-dialog.md +509 -0
- package/ai/components/alert.md +376 -0
- package/ai/components/avatar.md +146 -0
- package/ai/components/back-button.md +286 -0
- package/ai/components/badge.md +171 -0
- package/ai/components/button.md +431 -0
- package/ai/components/card.md +303 -0
- package/ai/components/checkbox.md +418 -0
- package/ai/components/chip-group.md +205 -0
- package/ai/components/chip.md +300 -0
- package/ai/components/content.md +474 -0
- package/ai/components/desktop-toast.md +420 -0
- package/ai/components/dialog.md +962 -0
- package/ai/components/empty-state.md +146 -0
- package/ai/components/field.md +319 -0
- package/ai/components/header.md +809 -0
- package/ai/components/icon-button.md +221 -0
- package/ai/components/icon.md +176 -0
- package/ai/components/input.md +455 -0
- package/ai/components/list-item.md +326 -0
- package/ai/components/list.md +178 -0
- package/ai/components/menu-button.md +377 -0
- package/ai/components/menu.md +661 -0
- package/ai/components/modal.md +613 -0
- package/ai/components/number-input.md +423 -0
- package/ai/components/page.md +299 -0
- package/ai/components/progress.md +215 -0
- package/ai/components/radio-group.md +432 -0
- package/ai/components/refresher.md +377 -0
- package/ai/components/segmented.md +517 -0
- package/ai/components/select.md +510 -0
- package/ai/components/sheet.md +845 -0
- package/ai/components/spinner.md +171 -0
- package/ai/components/stack-outlet.md +661 -0
- package/ai/components/tab-bar.md +427 -0
- package/ai/components/tab.md +295 -0
- package/ai/components/tabs.md +408 -0
- package/ai/components/textarea.md +371 -0
- package/ai/components/toast.md +522 -0
- package/ai/components/toggle.md +387 -0
- package/ai/reference/bf-action-directive.md +21 -0
- package/ai/reference/bf-action-sheet-action-role.md +27 -0
- package/ai/reference/bf-action-sheet-action.md +28 -0
- package/ai/reference/bf-action-sheet-options.md +28 -0
- package/ai/reference/bf-action-sheet-service.md +33 -0
- package/ai/reference/bf-alert-dialog-button-role.md +27 -0
- package/ai/reference/bf-alert-dialog-button.md +27 -0
- package/ai/reference/bf-alert-dialog-options.md +29 -0
- package/ai/reference/bf-alert-dialog-service.md +34 -0
- package/ai/reference/bf-alert-variant.md +28 -0
- package/ai/reference/bf-autocapitalize.md +30 -0
- package/ai/reference/bf-avatar-size.md +27 -0
- package/ai/reference/bf-avatar-variant.md +28 -0
- package/ai/reference/bf-back-at-root.md +28 -0
- package/ai/reference/bf-back-button-service.md +40 -0
- package/ai/reference/bf-badge-variant.md +29 -0
- package/ai/reference/bf-button-size.md +29 -0
- package/ai/reference/bf-button-type.md +28 -0
- package/ai/reference/bf-button-variant.md +29 -0
- package/ai/reference/bf-card-padding.md +26 -0
- package/ai/reference/bf-card-variant.md +28 -0
- package/ai/reference/bf-chip-group-mode.md +27 -0
- package/ai/reference/bf-chip-variant.md +26 -0
- package/ai/reference/bf-compare-with.md +24 -0
- package/ai/reference/bf-component-overlay-ref.md +33 -0
- package/ai/reference/bf-confirm-button-role.md +26 -0
- package/ai/reference/bf-confirm-button.md +27 -0
- package/ai/reference/bf-confirm-options.md +31 -0
- package/ai/reference/bf-confirm-size.md +26 -0
- package/ai/reference/bf-content-scroll-event.md +21 -0
- package/ai/reference/bf-defaults-options.md +32 -0
- package/ai/reference/bf-defaults.md +28 -0
- package/ai/reference/bf-desktop-toast-config.md +28 -0
- package/ai/reference/bf-desktop-toast-harness.md +33 -0
- package/ai/reference/bf-desktop-toast-options.md +28 -0
- package/ai/reference/bf-desktop-toast-position.md +28 -0
- package/ai/reference/bf-desktop-toast-service.md +42 -0
- package/ai/reference/bf-dialog-config.md +44 -0
- package/ai/reference/bf-dialog-harness.md +52 -0
- package/ai/reference/bf-dialog-ref.md +44 -0
- package/ai/reference/bf-dialog-role.md +26 -0
- package/ai/reference/bf-dialog-service.md +55 -0
- package/ai/reference/bf-dialog-size.md +31 -0
- package/ai/reference/bf-dialog-template-context.md +32 -0
- package/ai/reference/bf-empty-state-heading-level.md +26 -0
- package/ai/reference/bf-enter-key-hint.md +31 -0
- package/ai/reference/bf-field-control-class.md +32 -0
- package/ai/reference/bf-field-control-state.md +28 -0
- package/ai/reference/bf-field-size.md +29 -0
- package/ai/reference/bf-haptics-impact-style.md +27 -0
- package/ai/reference/bf-haptics-notification-type.md +27 -0
- package/ai/reference/bf-haptics-service.md +41 -0
- package/ai/reference/bf-harness-filters.md +29 -0
- package/ai/reference/bf-horizontal-scroll-directive.md +129 -0
- package/ai/reference/bf-icon-button-variant.md +28 -0
- package/ai/reference/bf-icon-size.md +27 -0
- package/ai/reference/bf-input-autocapitalize.md +36 -0
- package/ai/reference/bf-input-enter-key-hint.md +38 -0
- package/ai/reference/bf-input-input-mode.md +38 -0
- package/ai/reference/bf-input-mode.md +32 -0
- package/ai/reference/bf-input-type.md +35 -0
- package/ai/reference/bf-jsdom-shim-options.md +22 -0
- package/ai/reference/bf-keyboard-assist-behavior.md +26 -0
- package/ai/reference/bf-keyboard-assist-directive.md +185 -0
- package/ai/reference/bf-keyboard-phase.md +30 -0
- package/ai/reference/bf-keyboard-service.md +50 -0
- package/ai/reference/bf-labels-overrides.md +26 -0
- package/ai/reference/bf-labels.md +44 -0
- package/ai/reference/bf-menu-button-harness.md +40 -0
- package/ai/reference/bf-menu-button-variant.md +27 -0
- package/ai/reference/bf-menu-divider-directive.md +13 -0
- package/ai/reference/bf-menu-group-directive.md +14 -0
- package/ai/reference/bf-menu-harness.md +55 -0
- package/ai/reference/bf-menu-item-checkbox-directive.md +31 -0
- package/ai/reference/bf-menu-item-directive.md +31 -0
- package/ai/reference/bf-menu-item-harness.md +52 -0
- package/ai/reference/bf-menu-item-radio-directive.md +29 -0
- package/ai/reference/bf-menu-placement.md +29 -0
- package/ai/reference/bf-menu-trigger-directive.md +46 -0
- package/ai/reference/bf-modal-options.md +30 -0
- package/ai/reference/bf-modal-presentation.md +26 -0
- package/ai/reference/bf-modal-service.md +38 -0
- package/ai/reference/bf-nav-controller.md +59 -0
- package/ai/reference/bf-nav-direction.md +23 -0
- package/ai/reference/bf-nav-target.md +21 -0
- package/ai/reference/bf-number-input-mode.md +28 -0
- package/ai/reference/bf-number-input-step.md +25 -0
- package/ai/reference/bf-overlay-auto-focus.md +29 -0
- package/ai/reference/bf-overlay-controller.md +22 -0
- package/ai/reference/bf-overlay-host.md +36 -0
- package/ai/reference/bf-overlay-options.md +53 -0
- package/ai/reference/bf-overlay-position.md +30 -0
- package/ai/reference/bf-overlay-ref.md +53 -0
- package/ai/reference/bf-overlay-role.md +27 -0
- package/ai/reference/bf-overlay-service.md +53 -0
- package/ai/reference/bf-overlay-stack-options.md +24 -0
- package/ai/reference/bf-overlay-stack.md +81 -0
- package/ai/reference/bf-overlay-template-context.md +24 -0
- package/ai/reference/bf-overscroll-stretch-directive.md +163 -0
- package/ai/reference/bf-page-context.md +24 -0
- package/ai/reference/bf-platform-service.md +53 -0
- package/ai/reference/bf-platform.md +28 -0
- package/ai/reference/bf-progress-size.md +26 -0
- package/ai/reference/bf-progress-tone.md +28 -0
- package/ai/reference/bf-radio-group-harness.md +49 -0
- package/ai/reference/bf-radio-group-orientation.md +26 -0
- package/ai/reference/bf-radio-option.md +30 -0
- package/ai/reference/bf-refresher-refresh-event.md +22 -0
- package/ai/reference/bf-segment-option.md +29 -0
- package/ai/reference/bf-segmented-harness.md +48 -0
- package/ai/reference/bf-segmented-size.md +29 -0
- package/ai/reference/bf-select-harness.md +70 -0
- package/ai/reference/bf-select-option.md +29 -0
- package/ai/reference/bf-sheet-auto-focus.md +29 -0
- package/ai/reference/bf-sheet-options.md +32 -0
- package/ai/reference/bf-sheet-ref.md +45 -0
- package/ai/reference/bf-sheet-service.md +34 -0
- package/ai/reference/bf-shell-config-mode.md +28 -0
- package/ai/reference/bf-shell-config.md +38 -0
- package/ai/reference/bf-shell-dynamic-type-limit.md +21 -0
- package/ai/reference/bf-shell-dynamic-type.md +25 -0
- package/ai/reference/bf-shell-mode.md +28 -0
- package/ai/reference/bf-shell-testing-options.md +26 -0
- package/ai/reference/bf-size.md +45 -0
- package/ai/reference/bf-spinner-size.md +27 -0
- package/ai/reference/bf-stack-change.md +22 -0
- package/ai/reference/bf-stack-reuse-strategy.md +32 -0
- package/ai/reference/bf-stack-transition-event.md +26 -0
- package/ai/reference/bf-stack-transition.md +26 -0
- package/ai/reference/bf-stacked-overlay.md +23 -0
- package/ai/reference/bf-system-bars-style.md +38 -0
- package/ai/reference/bf-tab-bar-controller.md +51 -0
- package/ai/reference/bf-tab-bar-host.md +52 -0
- package/ai/reference/bf-tab-context.md +32 -0
- package/ai/reference/bf-tab-links.md +37 -0
- package/ai/reference/bf-testing-options.md +27 -0
- package/ai/reference/bf-text-scale-service.md +35 -0
- package/ai/reference/bf-theme.md +27 -0
- package/ai/reference/bf-toast-action.md +25 -0
- package/ai/reference/bf-toast-controller.md +17 -0
- package/ai/reference/bf-toast-dismiss-reason.md +29 -0
- package/ai/reference/bf-toast-options.md +29 -0
- package/ai/reference/bf-toast-position.md +26 -0
- package/ai/reference/bf-toast-ref.md +41 -0
- package/ai/reference/bf-toast-service.md +39 -0
- package/ai/reference/bf-toggle-label-position.md +26 -0
- package/ai/reference/bf-transition-kind.md +28 -0
- package/ai/reference/bf-validation-message.md +31 -0
- package/ai/reference/bf-validation-messages.md +33 -0
- package/ai/reference/bf-view-event.md +28 -0
- package/ai/reference/bf-view-lifecycle.md +41 -0
- package/ai/reference/bf-view-state.md +28 -0
- package/ai/reference/bf_default_labels.md +21 -0
- package/ai/reference/bf_default_values.md +21 -0
- package/ai/reference/bf_defaults.md +21 -0
- package/ai/reference/bf_desktop_toast_defaults.md +21 -0
- package/ai/reference/bf_dialog_data.md +17 -0
- package/ai/reference/bf_labels.md +21 -0
- package/ai/reference/bf_overlay_data.md +19 -0
- package/ai/reference/bf_overlay_host.md +21 -0
- package/ai/reference/bf_sheet_default_snap_points.md +17 -0
- package/ai/reference/bf_shell_config.md +21 -0
- package/ai/reference/bf_shell_defaults.md +21 -0
- package/ai/reference/bf_tab_bar.md +21 -0
- package/ai/reference/bf_tab_bar_controller.md +21 -0
- package/ai/reference/bf_tab_context.md +21 -0
- package/ai/reference/bf_tab_links.md +21 -0
- package/ai/reference/bf_theme_storage.md +19 -0
- package/ai/reference/create-transition.md +36 -0
- package/ai/reference/duration_fast.md +17 -0
- package/ai/reference/duration_md.md +17 -0
- package/ai/reference/duration_overlay.md +17 -0
- package/ai/reference/duration_push.md +17 -0
- package/ai/reference/fade-down.md +26 -0
- package/ai/reference/fade-in.md +25 -0
- package/ai/reference/fade-out.md +25 -0
- package/ai/reference/fade-up.md +26 -0
- package/ai/reference/inject-shell-mode.md +23 -0
- package/ai/reference/install-bf-jsdom-shims.md +31 -0
- package/ai/reference/ios_duration.md +17 -0
- package/ai/reference/ios_easing.md +17 -0
- package/ai/reference/is-text-entry.md +25 -0
- package/ai/reference/max_complete_ms.md +17 -0
- package/ai/reference/md-transition.md +31 -0
- package/ai/reference/md_duration.md +17 -0
- package/ai/reference/md_easing.md +17 -0
- package/ai/reference/overlay_duration.md +21 -0
- package/ai/reference/overlay_easing.md +19 -0
- package/ai/reference/overlay_reduced_duration.md +17 -0
- package/ai/reference/pop-frames-at.md +25 -0
- package/ai/reference/prefers-reduced-motion.md +25 -0
- package/ai/reference/provide-bf-defaults.md +33 -0
- package/ai/reference/provide-bf-desktop-toast.md +28 -0
- package/ai/reference/provide-bf-labels.md +38 -0
- package/ai/reference/provide-bf-shell-testing.md +34 -0
- package/ai/reference/provide-bf-shell.md +41 -0
- package/ai/reference/provide-bf-testing.md +33 -0
- package/ai/reference/reduced-transition.md +28 -0
- package/ai/reference/reduced_duration.md +17 -0
- package/ai/reference/resolve-shell-mode.md +33 -0
- package/ai/reference/scale-in.md +25 -0
- package/ai/reference/settle-duration.md +25 -0
- package/ai/reference/settle-pop.md +33 -0
- package/ai/reference/settle_easing.md +17 -0
- package/ai/reference/should-complete-pop.md +26 -0
- package/ai/reference/slide-down.md +26 -0
- package/ai/reference/slide-up.md +26 -0
- package/ai/reference/with-bf-shell-routing.md +19 -0
- package/bin/bf-ui.js +81 -0
- package/fesm2022/bitforgehq-ui-icons.mjs +230 -0
- package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-mobile.mjs +5530 -0
- package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-number-input.mjs +680 -0
- package/fesm2022/bitforgehq-ui-number-input.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-overlay.mjs +2675 -0
- package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-testing.mjs +402 -0
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui.mjs +7765 -0
- package/fesm2022/bitforgehq-ui.mjs.map +1 -0
- package/llms-full.txt +25394 -0
- package/llms.txt +329 -0
- package/package.json +94 -0
- package/theme.css +253 -0
- package/types/bitforgehq-ui-icons.d.ts +50 -0
- package/types/bitforgehq-ui-mobile.d.ts +2914 -0
- package/types/bitforgehq-ui-number-input.d.ts +282 -0
- package/types/bitforgehq-ui-overlay.d.ts +1514 -0
- package/types/bitforgehq-ui-testing.d.ts +495 -0
- package/types/bitforgehq-ui.d.ts +3499 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# bf-alert
|
|
2
|
+
|
|
3
|
+
Inline status message in four tones with a title and an optional dismiss button
|
|
4
|
+
|
|
5
|
+
`BfAlertComponent` from `@bitforgehq/ui` · Feedback · since 0.1.0
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Component, ElementRef, signal, viewChild } from '@angular/core';
|
|
11
|
+
import { BfAlertComponent, BfButtonComponent } from '@bitforgehq/ui';
|
|
12
|
+
|
|
13
|
+
/** Focuses the native button inside a `bf-button` host (a type guard, not an assertion). */
|
|
14
|
+
function focusButtonIn(host: unknown): void {
|
|
15
|
+
if (host instanceof HTMLElement) {
|
|
16
|
+
host.querySelector('button')?.focus();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The bf-alert overview.
|
|
22
|
+
*
|
|
23
|
+
* Live demo of `bf-alert`: "Save" inserts an `announce` success alert (a new one per press, so
|
|
24
|
+
* each is heard), and dismissing the `urgent` danger alert moves focus to "Save".
|
|
25
|
+
*/
|
|
26
|
+
@Component({
|
|
27
|
+
selector: 'app-example-alert-overview',
|
|
28
|
+
imports: [BfAlertComponent, BfButtonComponent],
|
|
29
|
+
template: `
|
|
30
|
+
<div class="flex flex-col gap-3">
|
|
31
|
+
<div class="flex flex-wrap gap-2">
|
|
32
|
+
<bf-button #saveButton size="sm" (clicked)="save()">Save</bf-button>
|
|
33
|
+
@if (!showDangerAlert()) {
|
|
34
|
+
<bf-button variant="tonal" size="sm" (clicked)="showDangerAlert.set(true)">
|
|
35
|
+
Show again
|
|
36
|
+
</bf-button>
|
|
37
|
+
}
|
|
38
|
+
</div>
|
|
39
|
+
@for (id of saves(); track id) {
|
|
40
|
+
<bf-alert variant="success" title="Saved" announce>Your changes are live.</bf-alert>
|
|
41
|
+
}
|
|
42
|
+
@if (showDangerAlert()) {
|
|
43
|
+
<bf-alert
|
|
44
|
+
variant="danger"
|
|
45
|
+
title="Sync failed"
|
|
46
|
+
urgent
|
|
47
|
+
[dismissible]="true"
|
|
48
|
+
(dismissed)="dismiss()"
|
|
49
|
+
>
|
|
50
|
+
Check your connection and try again.
|
|
51
|
+
</bf-alert>
|
|
52
|
+
}
|
|
53
|
+
</div>
|
|
54
|
+
`,
|
|
55
|
+
})
|
|
56
|
+
export class AlertOverviewExampleComponent {
|
|
57
|
+
readonly showDangerAlert = signal(true);
|
|
58
|
+
/** Holds only the latest save; a new id replaces the alert, so each press is announced. */
|
|
59
|
+
readonly saves = signal<readonly number[]>([]);
|
|
60
|
+
private readonly saveButton = viewChild.required('saveButton', {
|
|
61
|
+
read: ElementRef,
|
|
62
|
+
});
|
|
63
|
+
private nextSave = 0;
|
|
64
|
+
|
|
65
|
+
save(): void {
|
|
66
|
+
this.saves.set([this.nextSave++]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The dismiss button is about to disappear; hand focus to the control that caused the alert. */
|
|
70
|
+
dismiss(): void {
|
|
71
|
+
this.showDangerAlert.set(false);
|
|
72
|
+
focusButtonIn(this.saveButton().nativeElement);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Overview
|
|
78
|
+
|
|
79
|
+
Inline message for the outcome of an action or the state of a screen, in a polite `status`
|
|
80
|
+
region (`urgent` makes it an assertive `alert`; `announce` makes an inserted alert heard).
|
|
81
|
+
|
|
82
|
+
Alerts report the outcome of an action or the state of a screen inline, in the flow of the page. Every alert is a polite live region (`role="status"`); `urgent` makes it interrupt assistive tech (`role="alert"`), and `announce` makes an alert inserted after an action be heard. For a message that needs no permanent home, use a toast instead.
|
|
83
|
+
|
|
84
|
+
## When to use
|
|
85
|
+
|
|
86
|
+
Use `bf-alert` for a message that belongs to a place on the page and stays until the state changes: a failed sync above a list, a warning at the top of a form. Use [BfDesktopToastService](https://bitforge-ui.web.app/api/bf-desktop-toast-service) instead for a passing confirmation ("Saved"), and [BfDialogService](https://bitforge-ui.web.app/api/bf-dialog-service) `confirm()` when the user must answer before going on.
|
|
87
|
+
|
|
88
|
+
## Basic usage
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { Component } from '@angular/core';
|
|
92
|
+
import { BfAlertComponent } from '@bitforgehq/ui';
|
|
93
|
+
|
|
94
|
+
/** An info alert with a title and a message. */
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'app-example-alert-basic',
|
|
97
|
+
imports: [BfAlertComponent],
|
|
98
|
+
template: `<bf-alert title="Saved">Your changes are live.</bf-alert>`,
|
|
99
|
+
})
|
|
100
|
+
export class AlertBasicExampleComponent {}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Variants
|
|
104
|
+
|
|
105
|
+
`neutral` (default) is a plain note; `success`, `warning` and `danger` carry meaning through color. `danger` also gets a visible border. The variant does not change the `role`: add `urgent` to a danger alert that must interrupt (see Announcements).
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { Component } from '@angular/core';
|
|
109
|
+
import { BfAlertComponent } from '@bitforgehq/ui';
|
|
110
|
+
|
|
111
|
+
/** The success, warning and danger alerts. */
|
|
112
|
+
@Component({
|
|
113
|
+
selector: 'app-example-alert-variants',
|
|
114
|
+
imports: [BfAlertComponent],
|
|
115
|
+
template: `
|
|
116
|
+
<div class="flex flex-col gap-3">
|
|
117
|
+
<bf-alert variant="success" title="Saved">Your changes are live.</bf-alert>
|
|
118
|
+
<bf-alert variant="warning" title="Storage almost full">You have 200 MB left.</bf-alert>
|
|
119
|
+
<bf-alert variant="danger" title="Sync failed">Check your connection and try again.</bf-alert>
|
|
120
|
+
</div>
|
|
121
|
+
`,
|
|
122
|
+
})
|
|
123
|
+
export class AlertVariantsExampleComponent {}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Announcements
|
|
127
|
+
|
|
128
|
+
Screen readers announce a live region's changes, not a region that appears with its text already
|
|
129
|
+
in it, so an alert rendered after an action ("Saved") is often missed. Set `announce` on such an
|
|
130
|
+
alert: its region renders empty first and fills on the next frame, which is a change screen
|
|
131
|
+
readers announce. `announce` is read once, when the alert is created; to announce again, render
|
|
132
|
+
a new alert (for example with `@for (id of saves(); track id)` holding only the latest id).
|
|
133
|
+
|
|
134
|
+
`urgent` switches the region from `status` (polite: read when the screen reader is idle) to
|
|
135
|
+
`alert` (assertive: read at once, interrupting). Use it only for an error that needs attention
|
|
136
|
+
now; it is not tied to `variant`. The two combine: `urgent announce` for an error that appears
|
|
137
|
+
after an action.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { Component, signal } from '@angular/core';
|
|
141
|
+
import { BfAlertComponent, BfButtonComponent } from '@bitforgehq/ui';
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Alerts that announce themselves when they appear.
|
|
145
|
+
*
|
|
146
|
+
* Save shows a polite "Saved" alert; Fail sync an urgent one. Both render after an action, so
|
|
147
|
+
* both set `announce`.
|
|
148
|
+
*/
|
|
149
|
+
@Component({
|
|
150
|
+
selector: 'app-example-alert-announce',
|
|
151
|
+
imports: [BfAlertComponent, BfButtonComponent],
|
|
152
|
+
template: `
|
|
153
|
+
<div class="flex flex-col gap-3">
|
|
154
|
+
<div class="flex flex-wrap gap-2">
|
|
155
|
+
<bf-button (clicked)="save()">Save</bf-button>
|
|
156
|
+
<bf-button variant="outline" (clicked)="syncError.set(true)">Fail sync</bf-button>
|
|
157
|
+
</div>
|
|
158
|
+
@if (saved()) {
|
|
159
|
+
<bf-alert variant="success" title="Saved" announce>Your changes are live.</bf-alert>
|
|
160
|
+
}
|
|
161
|
+
@if (syncError()) {
|
|
162
|
+
<bf-alert variant="danger" title="Sync failed" urgent announce
|
|
163
|
+
>Check your connection.</bf-alert
|
|
164
|
+
>
|
|
165
|
+
}
|
|
166
|
+
</div>
|
|
167
|
+
`,
|
|
168
|
+
})
|
|
169
|
+
export class AlertAnnounceExampleComponent {
|
|
170
|
+
protected readonly saved = signal(false);
|
|
171
|
+
protected readonly syncError = signal(false);
|
|
172
|
+
|
|
173
|
+
protected save(): void {
|
|
174
|
+
this.saved.set(true);
|
|
175
|
+
this.syncError.set(false);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
An alert present when the page loads needs neither: it is read with the page.
|
|
181
|
+
|
|
182
|
+
## Dismissible
|
|
183
|
+
|
|
184
|
+
Set `dismissible` to show a close button and handle `dismissed` to remove the alert from your state; the component never hides itself. The button sits outside the `status`/`alert` region so assistive tech reads the message without the control interrupting it. Its accessible name is `dismissLabel` (default `provideBfLabels()`'s `dismiss`, "Dismiss") followed by the title, "Dismiss: Sync failed", so two dismissible alerts on a page have distinct buttons; without a `title` it is the label alone.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { Component, signal } from '@angular/core';
|
|
188
|
+
import { BfAlertComponent, BfButtonComponent } from '@bitforgehq/ui';
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* A dismissible alert with a Retry action.
|
|
192
|
+
*
|
|
193
|
+
* `dismissed` removes it from the state; the component never hides itself.
|
|
194
|
+
*/
|
|
195
|
+
@Component({
|
|
196
|
+
selector: 'app-example-alert-dismissible',
|
|
197
|
+
imports: [BfAlertComponent, BfButtonComponent],
|
|
198
|
+
template: `
|
|
199
|
+
@if (error()) {
|
|
200
|
+
<bf-alert
|
|
201
|
+
variant="danger"
|
|
202
|
+
title="Sync failed"
|
|
203
|
+
[dismissible]="true"
|
|
204
|
+
(dismissed)="error.set(false)"
|
|
205
|
+
>
|
|
206
|
+
Check your connection.
|
|
207
|
+
<bf-button bfSlot="actions" variant="text" size="sm" (clicked)="retry()">Retry</bf-button>
|
|
208
|
+
</bf-alert>
|
|
209
|
+
} @else {
|
|
210
|
+
<bf-button variant="outline" (clicked)="error.set(true)">Show the error again</bf-button>
|
|
211
|
+
}
|
|
212
|
+
`,
|
|
213
|
+
})
|
|
214
|
+
export class AlertDismissibleExampleComponent {
|
|
215
|
+
protected readonly error = signal(true);
|
|
216
|
+
|
|
217
|
+
protected retry(): void {
|
|
218
|
+
this.error.set(false);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Focus after dismissal
|
|
224
|
+
|
|
225
|
+
The dismiss button disappears with the alert, and focus would fall back to the page's start. The
|
|
226
|
+
widget cannot know where focus belongs, so move it in your `dismissed` handler: to the next alert's
|
|
227
|
+
dismiss button, or to the control that caused the alert.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import { Component, ElementRef, signal, viewChild } from '@angular/core';
|
|
231
|
+
import { BfAlertComponent, BfButtonComponent } from '@bitforgehq/ui';
|
|
232
|
+
|
|
233
|
+
/** Focuses the native button inside a `bf-button` host (a type guard, not an assertion). */
|
|
234
|
+
function focusButtonIn(host: unknown): void {
|
|
235
|
+
if (host instanceof HTMLElement) {
|
|
236
|
+
host.querySelector('button')?.focus();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Moving focus after a dismissal.
|
|
242
|
+
*
|
|
243
|
+
* The dismiss button leaves with the alert, so the `dismissed` handler moves focus back to the
|
|
244
|
+
* Save button that caused it.
|
|
245
|
+
*/
|
|
246
|
+
@Component({
|
|
247
|
+
selector: 'app-example-alert-focus',
|
|
248
|
+
imports: [BfAlertComponent, BfButtonComponent],
|
|
249
|
+
template: `
|
|
250
|
+
<div class="flex flex-col items-start gap-3">
|
|
251
|
+
@if (error(); as message) {
|
|
252
|
+
<bf-alert
|
|
253
|
+
variant="danger"
|
|
254
|
+
title="Save failed"
|
|
255
|
+
[dismissible]="true"
|
|
256
|
+
(dismissed)="clearError()"
|
|
257
|
+
>
|
|
258
|
+
{{ message }}
|
|
259
|
+
</bf-alert>
|
|
260
|
+
}
|
|
261
|
+
<bf-button #saveButton (clicked)="error.set('The server did not answer.')">Save</bf-button>
|
|
262
|
+
</div>
|
|
263
|
+
`,
|
|
264
|
+
})
|
|
265
|
+
export class AlertFocusExampleComponent {
|
|
266
|
+
private readonly saveButton = viewChild.required('saveButton', {
|
|
267
|
+
read: ElementRef,
|
|
268
|
+
});
|
|
269
|
+
protected readonly error = signal<string | null>('The server did not answer.');
|
|
270
|
+
|
|
271
|
+
protected clearError(): void {
|
|
272
|
+
this.error.set(null);
|
|
273
|
+
focusButtonIn(this.saveButton().nativeElement);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Desktop
|
|
279
|
+
|
|
280
|
+
The message itself has no hover or pointer state; it is not interactive. The dismiss button fades on hover with the pointer cursor and shows its focus ring on keyboard focus only. It is 32 px with a 44 px hit area at every size. Alerts span their container, so on a wide desktop page put them in the content column, not across the full viewport.
|
|
281
|
+
|
|
282
|
+
## Theming
|
|
283
|
+
|
|
284
|
+
Consumes tokens by variant, background then text:
|
|
285
|
+
|
|
286
|
+
- `neutral`: `surface-sunken` / `text`
|
|
287
|
+
- `success`: `success-soft` / `success`
|
|
288
|
+
- `warning`: `warning-soft` / `warning`
|
|
289
|
+
- `danger`: `danger-soft` / `danger`, with a visible `danger-border` border
|
|
290
|
+
- Dismiss button focus ring: `ring`; its shape is `rounded-control` (`--radius-control`)
|
|
291
|
+
|
|
292
|
+
## Accessibility
|
|
293
|
+
|
|
294
|
+
The message region's `role` is `status` (polite, an implicit `aria-live="polite"`) in every variant and `alert` (assertive) with `urgent` ([APG alert pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alert/)); only a change inside a live region is announced, so `announce` renders the region empty and fills it a frame later, which is how an alert inserted after an action meets [WCAG 4.1.3 Status Messages](https://www.w3.org/WAI/WCAG22/Understanding/status-messages) without moving focus. The dismiss button sits outside that region so it doesn't get read as part of the message; its accessible name is `dismissLabel` (else `provideBfLabels()`'s `dismiss`, "Dismiss") plus ": " and the `title`, so every dismiss button on a page is told apart. After a dismissal the host moves focus (see Focus after dismissal); the widget never does. Title and body break long words anywhere, and while `dismissible` the text column reserves the button's width, so no text runs under the ×. Its focus-visible ring uses the `ring` token.
|
|
295
|
+
|
|
296
|
+
### Keyboard
|
|
297
|
+
|
|
298
|
+
| Key | Action |
|
|
299
|
+
| ----------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
300
|
+
| <kbd>Tab</kbd> | Moves focus to the dismiss button (with `dismissible`) |
|
|
301
|
+
| <kbd>Enter</kbd> / <kbd>Space</kbd> | Activates the dismiss button: emits `dismissed`; your handler removes the alert and moves focus |
|
|
302
|
+
|
|
303
|
+
## Inputs
|
|
304
|
+
|
|
305
|
+
| Name | Type | Default | Description |
|
|
306
|
+
| -------------- | -------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
307
|
+
| `variant` | `BfAlertVariant` (`'neutral' \| 'success' \| 'warning' \| 'danger'`) | `'neutral'` | Meaning of the message. |
|
|
308
|
+
| `title` | `string` | `''` | Bold first line. |
|
|
309
|
+
| `dismissible` | `boolean` | `false` | Shows a dismiss button that emits `dismissed`; the host decides whether to hide the alert. |
|
|
310
|
+
| `urgent` | `boolean` | `false` | `role="alert"` (assertive) instead of `status`; for errors that need attention now. |
|
|
311
|
+
| `announce` | `boolean` | `false` | Renders the live region empty and fills it on the next frame, so an alert inserted after an action is announced; read once, when the alert is created. |
|
|
312
|
+
| `dismissLabel` | `string` | `''` | Accessible name of the dismiss button (empty falls back to `provideBfLabels()`'s `dismiss`, "Dismiss"); with a `title` it becomes the label, a colon and the title ("Dismiss: Saved"). |
|
|
313
|
+
|
|
314
|
+
## Outputs
|
|
315
|
+
|
|
316
|
+
| Name | Payload | Description |
|
|
317
|
+
| ----------- | ------- | ------------------------------------------- |
|
|
318
|
+
| `dismissed` | `void` | Emitted when the dismiss button is pressed. |
|
|
319
|
+
|
|
320
|
+
## Slots
|
|
321
|
+
|
|
322
|
+
- `icon`: An icon before the text, such as a `bf-icon`.
|
|
323
|
+
- `default`: The message, under the title.
|
|
324
|
+
- `actions`: Buttons under the message, such as Retry.
|
|
325
|
+
|
|
326
|
+
## Notes
|
|
327
|
+
|
|
328
|
+
### Do
|
|
329
|
+
|
|
330
|
+
- Pass a `title`; it is the first thing scanned and read aloud.
|
|
331
|
+
- Use `danger` only for something the user must act on now, and add `urgent` when it must interrupt.
|
|
332
|
+
- Set `announce` on an alert you render in response to an action.
|
|
333
|
+
|
|
334
|
+
### Don't
|
|
335
|
+
|
|
336
|
+
- Don't stack more than one alert at a time; resolve or dismiss the first.
|
|
337
|
+
- Don't use `bf-alert` for a message that disappears on its own; that is a toast.
|
|
338
|
+
- Don't make every alert `urgent`; an assertive region cuts off whatever the user is hearing.
|
|
339
|
+
|
|
340
|
+
## Migration notes
|
|
341
|
+
|
|
342
|
+
### 0.3.0
|
|
343
|
+
|
|
344
|
+
**Behaviour:** `dismissLabel` defaults to `''` and falls back to `provideBfLabels()`'s `dismiss`
|
|
345
|
+
("Dismiss"); the rendered English default is unchanged.
|
|
346
|
+
|
|
347
|
+
**Behaviour:** the dismiss button uses `rounded-control` (`--radius-control`).
|
|
348
|
+
|
|
349
|
+
**Behaviour:** the role no longer follows the variant: the region is `role="status"` (polite)
|
|
350
|
+
unless the new `urgent` input makes it `role="alert"` (assertive), in any variant. Migration: add
|
|
351
|
+
`urgent` to danger alerts that must interrupt (see Migration 15).
|
|
352
|
+
|
|
353
|
+
New `announce` input: the live region renders empty and fills on the next frame, so an alert
|
|
354
|
+
inserted after an action is announced (APG alert, WCAG 4.1.3); it is read once, at creation.
|
|
355
|
+
|
|
356
|
+
**Behaviour:** with a `title` the dismiss button is named `<dismissLabel>: <title>` ("Dismiss:
|
|
357
|
+
Sync failed"), so two dismissible alerts have distinct buttons (see Migration 16). The docs show
|
|
358
|
+
moving focus in the `dismissed` handler; the widget never moves it.
|
|
359
|
+
|
|
360
|
+
JSDoc of `alert.component.ts` for the API reference: `@summary`/`@since` on the exported symbols;
|
|
361
|
+
`@slot` docs for `icon`, `default`, `actions`. No behaviour change.
|
|
362
|
+
|
|
363
|
+
### 0.2.0
|
|
364
|
+
|
|
365
|
+
The body text is `text-label` (15 px, was 14) like other body copy; the dismiss glyph is
|
|
366
|
+
`text-heading font-normal` (18 px, was 20; the glyph keeps its regular weight).
|
|
367
|
+
|
|
368
|
+
Fixed: the dismiss button shows a pointer cursor.
|
|
369
|
+
|
|
370
|
+
Fixed: the title and body break long words anywhere (`wrap-anywhere`), and a dismissible alert's text
|
|
371
|
+
column reserves the dismiss button's width (`pe-10`, was `pr-12` without word breaking), so a long
|
|
372
|
+
word no longer runs under the ×. The dismiss button is placed with `end-3` (was `right-3`).
|
|
373
|
+
|
|
374
|
+
### 0.1.0
|
|
375
|
+
|
|
376
|
+
New `bf-alert`: an inline `role="status"` (`role="alert"` for `danger`) message with `neutral` (default), `success`, `warning` and `danger` variants, an `icon` slot, a `title`, and an `actions` slot. `dismissible` shows a close button that emits `dismissed`; the component itself never hides. The dismiss button now renders as a sibling of the `role="status"`/`role="alert"` element (both wrapped in an outer `div`) instead of inside it, so assistive tech reading the status/alert region doesn't also announce the dismiss control as part of the message; the visual position (absolute, top-right) is unchanged. Added `dismissLabel` (default `"Dismiss"`) to customize the button's accessible name. The 32 px dismiss button now extends its hit area to 44 px with `after:-inset-1.5`, a self-contained control so the `::after` extension is the right tool here (unlike a control over projected content).
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# bf-avatar
|
|
2
|
+
|
|
3
|
+
Round avatar showing a photo or initials, in three sizes and four color variants
|
|
4
|
+
|
|
5
|
+
`BfAvatarComponent` from `@bitforgehq/ui` · Data display · since 0.1.0
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Component } from '@angular/core';
|
|
11
|
+
import { BfAvatarComponent } from '@bitforgehq/ui';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The bf-avatar overview.
|
|
15
|
+
*
|
|
16
|
+
* Live demo of `bf-avatar`: the three sizes and the four background variants.
|
|
17
|
+
*/
|
|
18
|
+
@Component({
|
|
19
|
+
selector: 'app-example-avatar-overview',
|
|
20
|
+
imports: [BfAvatarComponent],
|
|
21
|
+
template: `
|
|
22
|
+
<div class="flex flex-col gap-3">
|
|
23
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
24
|
+
<bf-avatar initials="JK" size="sm" />
|
|
25
|
+
<bf-avatar initials="AR" size="md" />
|
|
26
|
+
<bf-avatar initials="LM" size="lg" />
|
|
27
|
+
</div>
|
|
28
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
29
|
+
<bf-avatar initials="TI" variant="tint" />
|
|
30
|
+
<bf-avatar initials="IN" variant="ink" />
|
|
31
|
+
<bf-avatar initials="WA" variant="warning" />
|
|
32
|
+
<bf-avatar initials="NE" variant="neutral" />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
`,
|
|
36
|
+
})
|
|
37
|
+
export class AvatarOverviewExampleComponent {}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Overview
|
|
41
|
+
|
|
42
|
+
Round avatar showing a photo or initials.
|
|
43
|
+
|
|
44
|
+
Avatars identify people in lists, headers and profile screens. Without an image they show initials on a tinted circle.
|
|
45
|
+
|
|
46
|
+
## When to use
|
|
47
|
+
|
|
48
|
+
Use `bf-avatar` to identify a person or an account next to their name: a list row, a comment, a profile header. Use [bf-icon](https://bitforge-ui.web.app/components/icon) instead for things that are not people (a file type, a project), and [bf-badge](https://bitforge-ui.web.app/components/badge) for a status shown beside the avatar.
|
|
49
|
+
|
|
50
|
+
## Basic usage
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { Component } from '@angular/core';
|
|
54
|
+
import { BfAvatarComponent } from '@bitforgehq/ui';
|
|
55
|
+
|
|
56
|
+
/** An avatar with initials and one with an image. */
|
|
57
|
+
@Component({
|
|
58
|
+
selector: 'app-example-avatar-basic',
|
|
59
|
+
imports: [BfAvatarComponent],
|
|
60
|
+
template: `
|
|
61
|
+
<div class="flex items-center gap-3">
|
|
62
|
+
<bf-avatar initials="LM" />
|
|
63
|
+
<bf-avatar src="apple-touch-icon.png" alt="Bitforge" />
|
|
64
|
+
</div>
|
|
65
|
+
`,
|
|
66
|
+
})
|
|
67
|
+
export class AvatarBasicExampleComponent {}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Sizes and variants
|
|
71
|
+
|
|
72
|
+
`sm` 30 px in dense rows, `md` 40 px in lists, `lg` 84 px on profile screens. Variants tint (default), ink, warning, neutral let a list distinguish people.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { Component } from '@angular/core';
|
|
76
|
+
import { BfAvatarComponent } from '@bitforgehq/ui';
|
|
77
|
+
|
|
78
|
+
/** Avatar sizes and colour variants. */
|
|
79
|
+
@Component({
|
|
80
|
+
selector: 'app-example-avatar-sizes',
|
|
81
|
+
imports: [BfAvatarComponent],
|
|
82
|
+
template: `
|
|
83
|
+
<div class="flex items-center gap-3">
|
|
84
|
+
<bf-avatar initials="JK" size="sm" variant="neutral" />
|
|
85
|
+
<bf-avatar initials="AR" variant="warning" />
|
|
86
|
+
<bf-avatar initials="LM" size="lg" variant="ink" />
|
|
87
|
+
</div>
|
|
88
|
+
`,
|
|
89
|
+
})
|
|
90
|
+
export class AvatarSizesExampleComponent {}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Pass `alt` when the avatar is the only place the person's name appears; otherwise it is decorative and hidden from assistive tech.
|
|
94
|
+
|
|
95
|
+
## Theming
|
|
96
|
+
|
|
97
|
+
Consumes tokens by variant, background then text/initials color:
|
|
98
|
+
|
|
99
|
+
- `tint` (default): `primary-soft` / `primary-strong`
|
|
100
|
+
- `ink`: `text` / `bg`
|
|
101
|
+
- `warning`: `warning-soft` / `warning`
|
|
102
|
+
- `neutral`: `neutral-soft` / `neutral`
|
|
103
|
+
|
|
104
|
+
The circle is never smaller than 4.5ex of its initials (`min-w-[4.5ex] min-h-[4.5ex]`; `ex` follows the rendered font), so a text zoom that grows the initials but not the layout (Android's font size setting) grows the circle with them instead of cutting them off; at the default size and with iOS Dynamic Type every size step is larger (sm 30 px against 26.7 px with Manrope), so nothing changes.
|
|
105
|
+
|
|
106
|
+
## Accessibility
|
|
107
|
+
|
|
108
|
+
With `alt` set, the host gets `role="img"` and `aria-label` carrying it, so the avatar is announced as one image with the person's name; the inner `<img>` itself has an empty `alt` to avoid a second announcement. Without `alt`, the host is `aria-hidden` and both the image and the initials span are decorative.
|
|
109
|
+
|
|
110
|
+
## Inputs
|
|
111
|
+
|
|
112
|
+
| Name | Type | Default | Description |
|
|
113
|
+
| ---------- | --------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
114
|
+
| `initials` | `string` | `''` | One or two letters shown when there is no image. |
|
|
115
|
+
| `src` | `string` | `''` | Image URL; when set, the image replaces the initials. |
|
|
116
|
+
| `alt` | `string` | `''` | Accessible name; when unset the avatar is decorative and hidden from assistive tech. |
|
|
117
|
+
| `size` | `BfAvatarSize` (`'sm' \| 'md' \| 'lg'`) | `'md'` | Diameter: sm 30 px, md 40 px (default), lg 84 px; at least 4.5ex of the initials, so a text zoom (Android font scale) grows the circle with its initials. |
|
|
118
|
+
| `variant` | `BfAvatarVariant` (`'tint' \| 'ink' \| 'warning' \| 'neutral'`) | `'tint'` | Background treatment for the initials. |
|
|
119
|
+
|
|
120
|
+
## Notes
|
|
121
|
+
|
|
122
|
+
### Do
|
|
123
|
+
|
|
124
|
+
- Pass `alt` with the person's name when you pass `src`.
|
|
125
|
+
|
|
126
|
+
### Don't
|
|
127
|
+
|
|
128
|
+
- Don't use avatars for icons; use an icon tile.
|
|
129
|
+
|
|
130
|
+
## Migration notes
|
|
131
|
+
|
|
132
|
+
### 0.3.0
|
|
133
|
+
|
|
134
|
+
JSDoc of `avatar.component.ts` for the API reference: `@summary`/`@since` on the exported symbols.
|
|
135
|
+
No behaviour change.
|
|
136
|
+
|
|
137
|
+
**Behaviour:** the circle is at least 4.5ex of its initials (`min-w-[4.5ex] min-h-[4.5ex]`), so at
|
|
138
|
+
Android font scale 2.0 (a text zoom that doubles the rendered initials, and `ex` with them, but not
|
|
139
|
+
em, rem or px lengths) it grows with
|
|
140
|
+
them instead of cutting them off, e.g. the `sm` avatar in a header's `end` slot (F-051). At the
|
|
141
|
+
default size and with iOS Dynamic Type every size is larger than that minimum (with Manrope: sm
|
|
142
|
+
30 px against 26.7, md 40 against 31.5, lg 84 against 63), so nothing changes.
|
|
143
|
+
|
|
144
|
+
### 0.1.0
|
|
145
|
+
|
|
146
|
+
New `bf-avatar`: a round avatar showing a photo (`src`/`alt`) or initials on a tinted circle. `size` is `sm` (30 px), `md` (40 px, default) or `lg` (84 px); `variant` is `tint` (default), `ink`, `warning` or `neutral`. The host now carries `role="img"`/`aria-label` only when `alt` is set; without `alt` the host is `aria-hidden="true"` and decorative, instead of always announcing itself with the initials as a fallback name. The inner `<img>` now always has `alt=""` so the image itself is hidden from the accessibility tree and the host's `aria-label` is the single source of the accessible name.
|