forty-cdk 0.5.0 → 0.6.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/accordion/README.md +80 -71
- package/aspect-ratio/README.md +24 -22
- package/avatar/README.md +50 -33
- package/breadcrumbs/README.md +34 -8
- package/breakpoints/README.md +16 -12
- package/button/README.md +55 -18
- package/calendar/README.md +105 -83
- package/carousel/README.md +153 -112
- package/checkbox/README.md +60 -37
- package/combobox/README.md +106 -95
- package/context-menu/README.md +55 -37
- package/date-field/README.md +110 -60
- package/date-picker/README.md +78 -64
- package/date-range-field/README.md +139 -61
- package/dialog/README.md +83 -67
- package/disclosure/README.md +65 -59
- package/drag-drop/README.md +60 -5
- package/drawer/README.md +118 -92
- package/dropdown-menu/README.md +62 -49
- package/fesm2022/forty-cdk-core.mjs +63 -4
- package/fesm2022/forty-cdk-core.mjs.map +1 -1
- package/fesm2022/forty-cdk-listbox.mjs +6 -2
- package/fesm2022/forty-cdk-listbox.mjs.map +1 -1
- package/fesm2022/forty-cdk-table.mjs +202 -6
- package/fesm2022/forty-cdk-table.mjs.map +1 -1
- package/fesm2022/forty-cdk-toast.mjs +22 -1
- package/fesm2022/forty-cdk-toast.mjs.map +1 -1
- package/fesm2022/forty-cdk-tooltip.mjs +17 -9
- package/fesm2022/forty-cdk-tooltip.mjs.map +1 -1
- package/fesm2022/forty-cdk-virtualization.mjs +338 -4
- package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
- package/field/README.md +62 -21
- package/fieldset/README.md +35 -15
- package/file-upload/README.md +38 -14
- package/hover-card/README.md +103 -82
- package/input/README.md +81 -47
- package/listbox/README.md +215 -194
- package/menu/README.md +53 -29
- package/menubar/README.md +65 -39
- package/meter/README.md +67 -57
- package/navigation-menu/README.md +128 -115
- package/number-input/README.md +86 -68
- package/otp-input/README.md +78 -65
- package/package.json +1 -1
- package/pagination/README.md +57 -9
- package/pane-resizer/README.md +68 -51
- package/popover/README.md +110 -97
- package/progress/README.md +47 -39
- package/radio-group/README.md +78 -57
- package/scroll-area/README.md +81 -39
- package/search/README.md +39 -10
- package/select/README.md +141 -118
- package/separator/README.md +28 -26
- package/slider/README.md +95 -64
- package/stepper/README.md +100 -87
- package/switch/README.md +61 -40
- package/table/README.md +175 -46
- package/tabs/README.md +87 -70
- package/time-field/README.md +109 -57
- package/time-picker/README.md +74 -51
- package/time-range-field/README.md +142 -60
- package/toast/README.md +104 -68
- package/toggle/README.md +125 -104
- package/toolbar/README.md +97 -43
- package/tooltip/README.md +151 -131
- package/tree/README.md +120 -80
- package/types/forty-cdk-core.d.ts +70 -3
- package/types/forty-cdk-table.d.ts +81 -2
- package/types/forty-cdk-toast.d.ts +33 -0
- package/types/forty-cdk-tooltip.d.ts +16 -9
- package/types/forty-cdk-virtualization.d.ts +70 -3
- package/virtualization/README.md +52 -20
package/accordion/README.md
CHANGED
|
@@ -1,56 +1,22 @@
|
|
|
1
1
|
# Accordion
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
| API | Type | Description |
|
|
20
|
-
| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
21
|
-
| `value` | `model<readonly string[]>` | Currently open item values. In single mode the array has 0 or 1 element. |
|
|
22
|
-
| `multiple` | `input<boolean>` | When true, multiple items can be open simultaneously. Defaults to `false`. |
|
|
23
|
-
| `collapsible` | `input<boolean>` | Single mode only: when true, the open item can be collapsed by clicking it. Defaults to `false` — once any item is open, exactly one stays open. |
|
|
24
|
-
| `orientation` | `input<'horizontal' \| 'vertical'>` | Layout direction of the trigger list. Defaults to `'vertical'`; in horizontal mode ArrowLeft/Right replace ArrowUp/Down. |
|
|
25
|
-
| `dir` | `input<'ltr' \| 'rtl'>` | Writing direction. Only relevant in horizontal mode — swaps the meaning of Left/Right arrows. |
|
|
26
|
-
|
|
27
|
-
### `ForAccordionItem`
|
|
28
|
-
|
|
29
|
-
| API | Type | Description |
|
|
30
|
-
| ---------- | ------------------------ | ---------------------------------------------------------------------------------- |
|
|
31
|
-
| `value` | `input.required<string>` | Unique identifier within the accordion. Required. |
|
|
32
|
-
| `disabled` | `input<boolean>` | When true, the trigger ignores clicks and exposes the native `disabled` attribute. |
|
|
33
|
-
|
|
34
|
-
The host gets `data-state="open" \| "closed"` and `data-disabled` for CSS hooks.
|
|
35
|
-
|
|
36
|
-
### `ForAccordionTrigger`
|
|
37
|
-
|
|
38
|
-
Reflects on its host: `id`, `aria-expanded`, `aria-controls`, `aria-disabled` (when collapse is disallowed), `disabled` (real, when item is disabled), `data-state`. Toggles on click. Handles `ArrowDown` / `ArrowUp` / `Home` / `End` for navigation between triggers.
|
|
39
|
-
|
|
40
|
-
`aria-controls` is emitted only while the item is expanded — mirroring the overlay triggers' open-only gating — so the reference never dangles at an unmounted panel under the recommended `@if (item.expanded())` mount pattern.
|
|
41
|
-
|
|
42
|
-
Wrap it in a heading element (`<h2>`–`<h6>`) — APG requires that for landmark navigation. Use a real `<button type="button">` so Enter / Space activation comes for free.
|
|
43
|
-
|
|
44
|
-
### `ForAccordionContent`
|
|
45
|
-
|
|
46
|
-
Reflects on its host: `id`, `role="region"`, `aria-labelledby` (the trigger's id), `data-state`, `aria-hidden` (when closed), `inert` (when closed).
|
|
47
|
-
|
|
48
|
-
The directive does **not** apply `[hidden]`. Two patterns work:
|
|
49
|
-
|
|
50
|
-
- **Mount/unmount with `@if (item.expanded())`** — the panel is absent from the DOM while closed, which is the cleanest path for `animate.enter` / `animate.leave`.
|
|
51
|
-
- **Leave it mounted** — preserve internal state or run CSS-only transitions off `data-state`. While closed, the directive sets `aria-hidden="true"` and `inert` on the host so the panel is removed from the accessibility tree and focus order. Add `display: none` (or your own collapse animation) keyed on `[data-state="closed"]` to also hide it visually.
|
|
3
|
+
A stack of collapsible sections, optionally allowing multiple panels open at once.
|
|
4
|
+
|
|
5
|
+
## Anatomy
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<div forAccordion>
|
|
9
|
+
<div forAccordionItem value="item-1">
|
|
10
|
+
<h3>
|
|
11
|
+
<button type="button" forAccordionTrigger>Trigger</button>
|
|
12
|
+
</h3>
|
|
13
|
+
<div forAccordionContent>Panel content</div>
|
|
14
|
+
</div>
|
|
15
|
+
<!-- repeat forAccordionItem per section -->
|
|
16
|
+
</div>
|
|
17
|
+
```
|
|
52
18
|
|
|
53
|
-
##
|
|
19
|
+
## Examples
|
|
54
20
|
|
|
55
21
|
```ts
|
|
56
22
|
import { Component, signal } from '@angular/core';
|
|
@@ -86,22 +52,73 @@ export class DemoFaq {
|
|
|
86
52
|
}
|
|
87
53
|
```
|
|
88
54
|
|
|
89
|
-
##
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### `ForAccordion`
|
|
90
58
|
|
|
91
|
-
|
|
59
|
+
| Property | Type | Description |
|
|
60
|
+
| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
61
|
+
| `value` | `model<readonly string[]>` | Currently open item values. In single mode the array has 0 or 1 element.<br>**Default:** — |
|
|
62
|
+
| `multiple` | `input<boolean>` | When true, multiple items can be open simultaneously.<br>**Default:** `false` |
|
|
63
|
+
| `collapsible` | `input<boolean>` | Single mode only: when true, the open item can be collapsed by clicking it. Otherwise once any item is open, exactly one stays open.<br>**Default:** `false` |
|
|
64
|
+
| `orientation` | `input<'horizontal' \| 'vertical'>` | Layout direction of the trigger list. In horizontal mode ArrowLeft/Right replace ArrowUp/Down.<br>**Default:** `'vertical'` |
|
|
65
|
+
| `dir` | `input<'ltr' \| 'rtl'>` | Writing direction. Only relevant in horizontal mode — swaps the meaning of Left/Right arrows.<br>**Default:** — |
|
|
92
66
|
|
|
93
|
-
|
|
67
|
+
| Data attribute | Values |
|
|
68
|
+
| ------------------ | -------------------------- |
|
|
69
|
+
| `data-orientation` | `horizontal` \| `vertical` |
|
|
94
70
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
| `
|
|
71
|
+
### `ForAccordionItem`
|
|
72
|
+
|
|
73
|
+
| Property | Type | Description |
|
|
74
|
+
| ---------- | ------------------------ | ---------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `value` | `input.required<string>` | Unique identifier within the accordion. Required.<br>**Default:** — |
|
|
76
|
+
| `disabled` | `input<boolean>` | When true, the trigger ignores clicks and exposes the native `disabled` attribute.<br>**Default:** — |
|
|
77
|
+
|
|
78
|
+
| Data attribute | Values |
|
|
79
|
+
| ------------------ | -------------------------- |
|
|
80
|
+
| `data-state` | `open` \| `closed` |
|
|
81
|
+
| `data-disabled` | present \| absent |
|
|
82
|
+
| `data-orientation` | `horizontal` \| `vertical` |
|
|
83
|
+
|
|
84
|
+
### `ForAccordionTrigger`
|
|
85
|
+
|
|
86
|
+
| Data attribute | Values |
|
|
87
|
+
| ------------------ | -------------------------- |
|
|
88
|
+
| `data-state` | `open` \| `closed` |
|
|
89
|
+
| `data-orientation` | `horizontal` \| `vertical` |
|
|
90
|
+
|
|
91
|
+
### `ForAccordionContent`
|
|
92
|
+
|
|
93
|
+
| Data attribute | Values |
|
|
94
|
+
| ------------------ | -------------------------- |
|
|
95
|
+
| `data-state` | `open` \| `closed` |
|
|
96
|
+
| `data-orientation` | `horizontal` \| `vertical` |
|
|
97
|
+
|
|
98
|
+
## Keyboard
|
|
99
|
+
|
|
100
|
+
| Key | Action |
|
|
101
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
102
|
+
| <kbd>Enter</kbd> / <kbd>Space</kbd> | Toggle the focused trigger (native button). |
|
|
103
|
+
| <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> | Move focus between triggers (vertical, default). Wrap-around, skips disabled. |
|
|
104
|
+
| <kbd>ArrowLeft</kbd> / <kbd>ArrowRight</kbd> | Move focus between triggers (horizontal — flipped under `dir='rtl'`). Wrap-around, skips disabled. |
|
|
105
|
+
| <kbd>Home</kbd> | Jump to the first trigger. |
|
|
106
|
+
| <kbd>End</kbd> | Jump to the last trigger. |
|
|
107
|
+
|
|
108
|
+
## Accessibility
|
|
109
|
+
|
|
110
|
+
- **Heading wrapper is your job.** The library does not render a heading around the trigger — wrap it in the heading level (`<h2>`–`<h6>`) appropriate to your document outline. Without it, screen-reader landmark navigation is broken.
|
|
111
|
+
- **Use a real `<button type="button">` for the trigger.** Native Enter / Space activation and focus come for free; the directive does not synthesize them.
|
|
112
|
+
- **`role="region"`** is added to every panel automatically. APG recommends suppressing it on accordions with 6+ panels to avoid landmark proliferation. An opt-out input will be added to `ForAccordionContent` if this surfaces in real usage.
|
|
113
|
+
- **Closed panels leave the accessibility tree.** While closed, `ForAccordionContent` sets `aria-hidden="true"` and `inert` on the panel, removing it from both the accessibility tree and the focus order. The directive does **not** apply `[hidden]`, so pick how to hide it visually:
|
|
114
|
+
- **Mount / unmount with `@if (item.expanded())`** — the panel is absent from the DOM while closed; the cleanest path for `animate.enter` / `animate.leave`. The trigger emits `aria-controls` only while expanded, so the reference never dangles at an unmounted panel.
|
|
115
|
+
- **Leave it mounted** — preserve internal state or run CSS-only transitions off `data-state`. Add `display: none` (or your own collapse animation) keyed on `[data-state="closed"]` to also hide it visually.
|
|
116
|
+
- **`aria-disabled`** is applied to the open trigger only when single mode is active and `collapsible=false`, indicating the user cannot collapse it from this trigger.
|
|
117
|
+
- **A truly disabled item (`[disabled]` on `[forAccordionItem]`) uses the native `disabled` attribute on the trigger, by design.** This is the sanctioned exception in [rule #561](https://github.com/tutkli/forty-cdk/issues/561): the trigger is a real single-purpose `<button>`, not a roving-tabindex collection item (each trigger stays independently in the Tab order; arrow-key navigation is the APG-optional enhancement on top). The disabled trigger leaves the Tab order and the arrow-key navigation (which already skips it), but stays in the accessibility tree so screen readers announce it as unavailable in browse mode. The [APG Accordion pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) does not require disabled headers to remain focusable.
|
|
118
|
+
|
|
119
|
+
## Styling
|
|
120
|
+
|
|
121
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
105
122
|
|
|
106
123
|
```css
|
|
107
124
|
.trigger-chevron {
|
|
@@ -112,11 +129,3 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
112
129
|
transform: rotate(180deg);
|
|
113
130
|
}
|
|
114
131
|
```
|
|
115
|
-
|
|
116
|
-
## Accessibility notes
|
|
117
|
-
|
|
118
|
-
- **Heading wrapper is your job.** The library does not render a heading around the trigger — wrap it in the heading level appropriate to your document outline. Without it, screen-reader landmark navigation is broken.
|
|
119
|
-
- **`role="region"`** is added to every panel automatically. APG recommends suppressing it on accordions with 6+ panels to avoid landmark proliferation. An opt-out input will be added to `ForAccordionContent` if this surfaces in real usage.
|
|
120
|
-
- **Keyboard**: Enter and Space toggle the focused trigger (native button). ArrowDown / ArrowUp (vertical, default) or ArrowLeft / ArrowRight (horizontal — flipped under `dir='rtl'`) move focus between triggers (wrap-around, skip disabled). Home / End jump to the first/last trigger.
|
|
121
|
-
- **`aria-disabled`** is applied to the open trigger only when single mode is active and `collapsible=false`, indicating the user cannot collapse it from this trigger.
|
|
122
|
-
- **A truly disabled item (`[disabled]` on `[forAccordionItem]`) uses the native `disabled` attribute on the trigger, by design.** This is the sanctioned exception in [rule #561](https://github.com/tutkli/forty-cdk/issues/561): the trigger is a real single-purpose `<button>`, not a roving-tabindex collection item (each trigger stays independently in the Tab order; arrow-key navigation is the APG-optional enhancement on top). The disabled trigger leaves the Tab order and the arrow-key navigation (which already skips it), but stays in the accessibility tree so screen readers announce it as unavailable in browse mode. The [APG Accordion pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) does not require disabled headers to remain focusable.
|
package/aspect-ratio/README.md
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
# AspectRatio
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A container that keeps its content at a fixed width-to-height ratio.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Pure visual utility — it locks an element's box via the native CSS `aspect-ratio` property, with no ARIA semantics. Reach for it to reserve space for media before it loads (preventing layout shift), keep cards on a grid uniform, or wrap responsive iframes.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Anatomy
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| API | Type | Description |
|
|
16
|
-
| ------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
-
| `ratio` | `input<number>` | Width / height ratio (e.g. `16 / 9`, `4 / 3`, `1`). Accepts both numeric expressions and string attributes. Defaults to `1`. Non-positive or non-finite values fall back to `1`. |
|
|
9
|
+
```html
|
|
10
|
+
<div forAspectRatio [ratio]="16 / 9">
|
|
11
|
+
<!-- your content fills the box -->
|
|
12
|
+
</div>
|
|
13
|
+
```
|
|
18
14
|
|
|
19
|
-
##
|
|
15
|
+
## Examples
|
|
20
16
|
|
|
21
17
|
```ts
|
|
22
18
|
import { Component } from '@angular/core';
|
|
@@ -58,19 +54,25 @@ import { ForAspectRatio } from 'forty-cdk/aspect-ratio';
|
|
|
58
54
|
export class DemoAspectRatio {}
|
|
59
55
|
```
|
|
60
56
|
|
|
61
|
-
##
|
|
57
|
+
## API
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
### `ForAspectRatio`
|
|
60
|
+
|
|
61
|
+
| Property | Type | Description |
|
|
62
|
+
| -------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `ratio` | `input<number>` | Width / height ratio (e.g. `16 / 9`, `4 / 3`, `1`). Accepts both numeric expressions and string attributes. Non-positive or non-finite values fall back to `1`.<br>**Default:** `1` |
|
|
64
|
+
|
|
65
|
+
| Data attribute | Values |
|
|
66
|
+
| ------------------ | ------- |
|
|
67
|
+
| `[forAspectRatio]` | present |
|
|
67
68
|
|
|
68
69
|
## Styling
|
|
69
70
|
|
|
70
71
|
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../../../docs/styling.md)). This primitive is purely structural: its only host effect is the native `aspect-ratio` style, so it reflects no `data-*` attributes and writes no CSS custom properties. Style the host through your own class on `[forAspectRatio]`.
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
## Behavior notes
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
- **Browser support.** Native `aspect-ratio` is in Baseline 2021 (Chrome 88+, Firefox 89+, Safari 15+) — same target as Angular 20+, so no polyfill is needed.
|
|
76
|
+
- **Width still on you.** The directive only sets `aspect-ratio`; you decide width / max-width / display. The height is computed from the ratio.
|
|
77
|
+
- **Children fill the box.** Use `width: 100%; height: 100%; object-fit: cover` on inner media to fill without distortion. The directive imposes no styles on children.
|
|
78
|
+
- **No role, no a11y.** This is a layout utility. The element it sits on keeps whatever semantics you give it (`<div>`, `<figure>`, `<a>`, …).
|
package/avatar/README.md
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
# Avatar
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A user image with a graceful fallback across its loading lifecycle.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Headless and presentational — it tracks the load lifecycle of an `<img>` and lets you choose what to show while loading or after an error. There is no WAI-ARIA pattern for avatars, so the directive imposes no `role` of its own.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Anatomy
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
| API | Type | Owner | Description |
|
|
18
|
-
| --------------------- | ------------------------- | ---------------- | ----------------------------------------------------------------------------------------- |
|
|
19
|
-
| `fallbackDelayMs` | `input<number>` | `ForAvatar` | ms to wait before `shouldShowFallback()` flips to `true` while idle/loading. Default `0`. |
|
|
20
|
-
| `status` | `Signal<ForAvatarStatus>` | `ForAvatar` | Read-only current status. |
|
|
21
|
-
| `shouldShowFallback` | `Signal<boolean>` | `ForAvatar` | `true` when the consumer should render the fallback. Drives `@if`. |
|
|
22
|
-
| `(loadStatusChanged)` | `output<ForAvatarStatus>` | `ForAvatarImage` | Emits whenever the lifecycle transitions. |
|
|
23
|
-
|
|
24
|
-
The host element of every piece carries `data-status="idle" \| "loading" \| "loaded" \| "error"`.
|
|
9
|
+
```html
|
|
10
|
+
<span forAvatar #avatar="forAvatar">
|
|
11
|
+
<img forAvatarImage [src]="src" [alt]="name" />
|
|
12
|
+
<!-- rendered only when avatar.shouldShowFallback() is true -->
|
|
13
|
+
<span forAvatarFallback>{{ initials }}</span>
|
|
14
|
+
</span>
|
|
15
|
+
```
|
|
25
16
|
|
|
26
|
-
##
|
|
17
|
+
## Examples
|
|
27
18
|
|
|
28
19
|
```ts
|
|
29
20
|
import { Component, signal } from '@angular/core';
|
|
@@ -71,24 +62,43 @@ export class DemoAvatar {
|
|
|
71
62
|
}
|
|
72
63
|
```
|
|
73
64
|
|
|
74
|
-
##
|
|
65
|
+
## API
|
|
75
66
|
|
|
76
|
-
|
|
77
|
-
- **Multiple images per avatar are not supported.** Each `[forAvatar]` expects exactly one `[forAvatarImage]`. If you need cascading sources (CDN → fallback URL → fallback content), swap `src` on a single image.
|
|
78
|
-
- **`alt` is consumer territory.** Because `<img>` is the host element, the consumer keeps full control of `alt` — set `""` for purely decorative avatars next to a name, or describe the person if the avatar stands alone.
|
|
79
|
-
- **The image stays in the DOM.** Hide it via CSS `[data-status="loading"], [data-status="error"] { display: none }` if your consumer-side styling needs it gone. The fallback uses `@if`, so it only mounts when needed.
|
|
67
|
+
### `ForAvatar`
|
|
80
68
|
|
|
81
|
-
|
|
69
|
+
| Property | Type | Description |
|
|
70
|
+
| -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
71
|
+
| `fallbackDelayMs` | `input<number>` | ms to wait before `shouldShowFallback()` flips to `true` while idle/loading.<br>**Default:** `0` |
|
|
72
|
+
| `status` | `Signal<ForAvatarStatus>` | Read-only current status.<br>**Default:** — |
|
|
73
|
+
| `shouldShowFallback` | `Signal<boolean>` | `true` when the consumer should render the fallback. Drives `@if`.<br>**Default:** — |
|
|
74
|
+
|
|
75
|
+
| Data attribute | Values |
|
|
76
|
+
| -------------- | ------------------------------------------ |
|
|
77
|
+
| `data-status` | `idle` \| `loading` \| `loaded` \| `error` |
|
|
78
|
+
|
|
79
|
+
### `ForAvatarImage`
|
|
80
|
+
|
|
81
|
+
| Property | Type | Description |
|
|
82
|
+
| --------------------- | ------------------------- | ------------------------------------------------------------------- |
|
|
83
|
+
| `(loadStatusChanged)` | `output<ForAvatarStatus>` | Output. Emits whenever the lifecycle transitions.<br>**Default:** — |
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
| Data attribute | Values |
|
|
86
|
+
| -------------- | ------------------------------------------ |
|
|
87
|
+
| `data-status` | `idle` \| `loading` \| `loaded` \| `error` |
|
|
84
88
|
|
|
85
|
-
###
|
|
89
|
+
### `ForAvatarFallback`
|
|
86
90
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
| `
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
| Data attribute | Values |
|
|
92
|
+
| -------------- | ------------------------------------------ |
|
|
93
|
+
| `data-status` | `idle` \| `loading` \| `loaded` \| `error` |
|
|
94
|
+
|
|
95
|
+
## Accessibility
|
|
96
|
+
|
|
97
|
+
The directive does not impose a `role`. Pair the avatar with visible name text or `aria-label` on the surrounding element when identity matters. Set `alt=""` on the `<img>` for purely decorative avatars next to a name, or provide a meaningful `alt` description if the avatar stands alone.
|
|
98
|
+
|
|
99
|
+
## Styling
|
|
100
|
+
|
|
101
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
92
102
|
|
|
93
103
|
```css
|
|
94
104
|
.avatar-image:not([data-status='loaded']) {
|
|
@@ -98,3 +108,10 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
98
108
|
color: #b00020;
|
|
99
109
|
}
|
|
100
110
|
```
|
|
111
|
+
|
|
112
|
+
## Behavior notes
|
|
113
|
+
|
|
114
|
+
- **Cached images are detected on first render.** If the browser already has the image cached, `load`/`error` may not fire — the directive checks `<img>.complete` and `naturalWidth` after the first render and reports `loaded` / `error` accordingly. A cached image that is `complete` but has zero intrinsic width (e.g. an SVG without explicit dimensions) is ambiguous, so the directive stays `loading` and confirms validity with `img.decode()` rather than pessimistically flagging `error`.
|
|
115
|
+
- **Multiple images per avatar are not supported.** Each `[forAvatar]` expects exactly one `[forAvatarImage]`. If you need cascading sources (CDN → fallback URL → fallback content), swap `src` on a single image.
|
|
116
|
+
- **`alt` is consumer territory.** Because `<img>` is the host element, the consumer keeps full control of `alt` — set `""` for purely decorative avatars next to a name, or describe the person if the avatar stands alone.
|
|
117
|
+
- **The image stays in the DOM.** Hide it via CSS `[data-status="loading"], [data-status="error"] { display: none }` if your consumer-side styling needs it gone. The fallback uses `@if`, so it only mounts when needed.
|
package/breadcrumbs/README.md
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
# Breadcrumbs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A labelled navigation landmark for a breadcrumb trail: links with aria-current='page' on the current page and decorative separators hidden from assistive technology.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Anatomy
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```html
|
|
8
|
+
<nav forBreadcrumbs>
|
|
9
|
+
<ol>
|
|
10
|
+
<li><a forBreadcrumbItem href="/">Home</a></li>
|
|
11
|
+
<li forBreadcrumbSeparator>/</li>
|
|
12
|
+
<li><a forBreadcrumbItem href="/data" current>Data</a></li>
|
|
13
|
+
</ol>
|
|
14
|
+
</nav>
|
|
15
|
+
```
|
|
12
16
|
|
|
13
|
-
##
|
|
17
|
+
## Examples
|
|
14
18
|
|
|
15
19
|
```ts
|
|
16
20
|
import { Component } from '@angular/core';
|
|
@@ -36,6 +40,28 @@ export class DemoBreadcrumbs {}
|
|
|
36
40
|
|
|
37
41
|
The root defaults its label to `Breadcrumb`. Override it with `ariaLabel="…"` (or point a native `aria-labelledby` at a visible heading) when a page hosts more than one breadcrumb trail.
|
|
38
42
|
|
|
43
|
+
## API
|
|
44
|
+
|
|
45
|
+
### `ForBreadcrumbs`
|
|
46
|
+
|
|
47
|
+
| Property | Type | Description |
|
|
48
|
+
| ----------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `ariaLabel` | `input<string>` | Accessible label for the `navigation` landmark. Override when a page hosts more than one breadcrumb trail.<br>**Default:** `'Breadcrumb'` |
|
|
50
|
+
|
|
51
|
+
### `ForBreadcrumbItem`
|
|
52
|
+
|
|
53
|
+
| Property | Type | Description |
|
|
54
|
+
| --------- | ---------------- | ------------------------------------------------------------------------ |
|
|
55
|
+
| `current` | `input<boolean>` | When true, reflects `aria-current="page"` on the link.<br>**Default:** — |
|
|
56
|
+
|
|
57
|
+
## Accessibility
|
|
58
|
+
|
|
59
|
+
Implements the [WAI-ARIA Breadcrumb pattern](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/).
|
|
60
|
+
|
|
61
|
+
- **Navigation landmark.** `[forBreadcrumbs]` applies `role="navigation"` and labels it `aria-label="Breadcrumb"` by default, creating a named landmark that screen-reader users can jump to directly.
|
|
62
|
+
- **Current page.** Set `current` on `[forBreadcrumbItem]` for the active page; the directive reflects `aria-current="page"` so assistive technology announces the user's location in the trail.
|
|
63
|
+
- **Decorative separators.** `[forBreadcrumbSeparator]` reflects `aria-hidden="true"` so the visual divider (e.g. `/`) is skipped by screen readers.
|
|
64
|
+
|
|
39
65
|
## Styling
|
|
40
66
|
|
|
41
67
|
forty-cdk ships no styles. Style the current item via `[aria-current="page"]`.
|
package/breakpoints/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Breakpoints
|
|
2
2
|
|
|
3
|
-
A signal-first, zoneless, SSR-safe viewport breakpoint observer. Configure the breakpoint map
|
|
3
|
+
A signal-first, zoneless, SSR-safe viewport breakpoint observer (injectBreakpoints). Configure the breakpoint map once via provideForBreakpoints — or use the Tailwind scale by default — then read up / down / between / only / active or any arbitrary media query, each as a live Signal<boolean>.
|
|
4
4
|
|
|
5
|
-
It is a headless reactive utility, not a UI primitive: no DOM, no ARIA, no template.
|
|
5
|
+
It is a headless reactive utility, not a UI primitive: no DOM, no ARIA, no template. Configure the breakpoint map **once** via a provider; read it anywhere with `injectBreakpoints()` — no need to repeat the breakpoint set at every call site.
|
|
6
6
|
|
|
7
7
|
## Setup
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ export const appConfig: ApplicationConfig = {
|
|
|
18
18
|
|
|
19
19
|
Providing it again on a component injector replaces the map for that subtree only (nearest scope wins; the map is replaced wholesale, never merged key-by-key).
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Examples
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
24
|
import { Component, inject } from '@angular/core';
|
|
@@ -41,15 +41,6 @@ export class Layout {
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
| Method | Matches |
|
|
45
|
-
| ---------------- | ------------------------------------------------------------------------------ |
|
|
46
|
-
| `up(name)` | the breakpoint and wider — `(min-width: N px)` |
|
|
47
|
-
| `down(name)` | narrower than the breakpoint — `(max-width: (N − 0.02) px)` |
|
|
48
|
-
| `between(a, b)` | from `a` (inclusive) up to but not including `b` |
|
|
49
|
-
| `only(name)` | the breakpoint's own band, up to but not including the next-larger one |
|
|
50
|
-
| `active` | the largest breakpoint whose `min-width` matches, or `null` below the smallest |
|
|
51
|
-
| `matches(query)` | escape hatch for an arbitrary media query (orientation, `prefers-*`, …) |
|
|
52
|
-
|
|
53
44
|
The returned handle captures its injection context, so the query methods can be called lazily from a `computed()` or a template, not only during construction:
|
|
54
45
|
|
|
55
46
|
```ts
|
|
@@ -76,6 +67,19 @@ declare module 'forty-cdk' {
|
|
|
76
67
|
|
|
77
68
|
Now `injectBreakpoints()` autocompletes `'mobile' | 'tablet' | 'laptop' | 'desktop'` across the whole app.
|
|
78
69
|
|
|
70
|
+
## API
|
|
71
|
+
|
|
72
|
+
### `injectBreakpoints`
|
|
73
|
+
|
|
74
|
+
| Method | Matches |
|
|
75
|
+
| ---------------- | ------------------------------------------------------------------------------ |
|
|
76
|
+
| `up(name)` | the breakpoint and wider — `(min-width: N px)` |
|
|
77
|
+
| `down(name)` | narrower than the breakpoint — `(max-width: (N − 0.02) px)` |
|
|
78
|
+
| `between(a, b)` | from `a` (inclusive) up to but not including `b` |
|
|
79
|
+
| `only(name)` | the breakpoint's own band, up to but not including the next-larger one |
|
|
80
|
+
| `active` | the largest breakpoint whose `min-width` matches, or `null` below the smallest |
|
|
81
|
+
| `matches(query)` | escape hatch for an arbitrary media query (orientation, `prefers-*`, …) |
|
|
82
|
+
|
|
79
83
|
## SSR
|
|
80
84
|
|
|
81
85
|
On the server (or where `matchMedia` is unavailable) every query signal reads `false` and `active` reads `null`. No `matchMedia` access happens server-side, so the helper is safe under Angular Universal.
|
package/button/README.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
# ForButton
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turns any element — a native <button> or a custom host like <div> / <span> — into an accessible button with keyboard activation. Disabled stays focusable (aria-disabled, never the native attribute) and pressed / hovered / focus-visible are reflected as data-\* hooks.
|
|
4
4
|
|
|
5
|
-
A single `[forButton]` directive
|
|
5
|
+
A single `[forButton]` directive does all of this. On a native `<button>` host the platform owns Enter/Space activation and `type` handling; on any non-button host the directive adds `role="button"`, `tabindex="0"`, and keyboard activation so the contract matches.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<!-- Native button — platform owns Enter/Space and type handling -->
|
|
11
|
+
<button forButton [disabled]="saving()" (activate)="save()">Save</button>
|
|
12
|
+
|
|
13
|
+
<!-- Non-button host — role="button", tabindex="0", keyboard activation added -->
|
|
14
|
+
<div forButton (activate)="save()">Save</div>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### Basic usage
|
|
8
20
|
|
|
9
21
|
```html
|
|
10
22
|
<!-- Native button — platform handles Enter/Space → click synthesis -->
|
|
@@ -14,7 +26,7 @@ A single `[forButton]` directive turns any element into an accessible, interacti
|
|
|
14
26
|
<div forButton (activate)="save()">Save</div>
|
|
15
27
|
```
|
|
16
28
|
|
|
17
|
-
|
|
29
|
+
### Disabled
|
|
18
30
|
|
|
19
31
|
Disabled buttons stay focusable so assistive technology can announce them. The native `disabled` attribute is never set; instead `aria-disabled="true"` is reflected.
|
|
20
32
|
|
|
@@ -22,7 +34,7 @@ Disabled buttons stay focusable so assistive technology can announce them. The n
|
|
|
22
34
|
<button forButton [disabled]="isSaving()" (activate)="save()">Save</button>
|
|
23
35
|
```
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
### Preserve consumer `type`
|
|
26
38
|
|
|
27
39
|
A native `<button>` without an explicit `type` attribute defaults to `type="button"`. A consumer-set `type="submit"` is preserved:
|
|
28
40
|
|
|
@@ -30,20 +42,45 @@ A native `<button>` without an explicit `type` attribute defaults to `type="butt
|
|
|
30
42
|
<button type="submit" forButton>Submit form</button>
|
|
31
43
|
```
|
|
32
44
|
|
|
33
|
-
##
|
|
45
|
+
## API
|
|
34
46
|
|
|
35
|
-
|
|
47
|
+
### `ForButton`
|
|
36
48
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `data-hovered` | Mouse/pen pointer is over the element |
|
|
42
|
-
| `data-focus-visible` | Focused via keyboard (keyboard modality active) |
|
|
49
|
+
| Property | Type | Description |
|
|
50
|
+
| ---------- | ---------------- | -------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `disabled` | `input<boolean>` | Suppresses activation and reflects `aria-disabled` + `data-disabled`.<br>**Default:** `false` |
|
|
52
|
+
| `activate` | `output<void>` | Fires once per user activation (click, Enter, Space). Never fires when disabled.<br>**Default:** — |
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
The directive reflects boolean `data-*` attributes (present with an empty-string value when true, absent when false). There is no `data-state` — this primitive has no open/closed or checked/unchecked logical state.
|
|
45
55
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
| `disabled`
|
|
49
|
-
| `
|
|
56
|
+
| Data attribute | Values |
|
|
57
|
+
| -------------------- | ----------------- |
|
|
58
|
+
| `data-disabled` | present \| absent |
|
|
59
|
+
| `data-pressed` | present \| absent |
|
|
60
|
+
| `data-hovered` | present \| absent |
|
|
61
|
+
| `data-focus-visible` | present \| absent |
|
|
62
|
+
|
|
63
|
+
`data-pressed` is present while the primary pointer is held down or Enter/Space is held. `data-hovered` is present while a mouse/pen pointer is over the element. `data-focus-visible` is present when focused via keyboard (keyboard modality active).
|
|
64
|
+
|
|
65
|
+
## Accessibility
|
|
66
|
+
|
|
67
|
+
Implements the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).
|
|
68
|
+
|
|
69
|
+
- **Native `<button>` semantics are preserved.** On a native host, no extra ARIA is added; the browser's built-in button role, Enter/Space activation, and `type` handling all apply.
|
|
70
|
+
- **Non-button hosts get `role="button"` and `tabindex="0"`** plus keyboard activation (Enter/Space), matching the native button contract.
|
|
71
|
+
- **Disabled buttons stay focusable.** `aria-disabled="true"` is used instead of the native `disabled` attribute so assistive technology can still announce the control's purpose.
|
|
72
|
+
|
|
73
|
+
## Styling
|
|
74
|
+
|
|
75
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
76
|
+
|
|
77
|
+
```css
|
|
78
|
+
[forButton][data-disabled] {
|
|
79
|
+
opacity: 0.4;
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
[forButton][data-pressed] {
|
|
84
|
+
transform: scale(0.97);
|
|
85
|
+
}
|
|
86
|
+
```
|