forty-cdk 0.26.0 → 0.27.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.
Files changed (86) hide show
  1. package/accordion/README.md +24 -24
  2. package/aspect-ratio/README.md +7 -7
  3. package/avatar/README.md +5 -5
  4. package/breadcrumbs/README.md +3 -5
  5. package/breakpoints/README.md +17 -17
  6. package/button/README.md +14 -14
  7. package/calendar/README.md +40 -42
  8. package/carousel/README.md +20 -20
  9. package/checkbox/README.md +55 -27
  10. package/combobox/README.md +86 -86
  11. package/context-menu/README.md +38 -40
  12. package/date-field/README.md +22 -22
  13. package/date-picker/README.md +45 -45
  14. package/dialog/README.md +42 -42
  15. package/disclosure/README.md +14 -25
  16. package/drag-drop/README.md +37 -37
  17. package/drawer/README.md +45 -44
  18. package/dropdown-menu/README.md +45 -44
  19. package/fesm2022/forty-cdk-combobox.mjs +6 -3
  20. package/fesm2022/forty-cdk-combobox.mjs.map +1 -1
  21. package/fesm2022/forty-cdk-core.mjs +35 -8
  22. package/fesm2022/forty-cdk-core.mjs.map +1 -1
  23. package/fesm2022/forty-cdk-date-picker.mjs +3 -3
  24. package/fesm2022/forty-cdk-date-picker.mjs.map +1 -1
  25. package/fesm2022/forty-cdk-dialog.mjs +7 -1
  26. package/fesm2022/forty-cdk-dialog.mjs.map +1 -1
  27. package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -1
  28. package/fesm2022/forty-cdk-field.mjs +61 -25
  29. package/fesm2022/forty-cdk-field.mjs.map +1 -1
  30. package/fesm2022/forty-cdk-fieldset.mjs +6 -1
  31. package/fesm2022/forty-cdk-fieldset.mjs.map +1 -1
  32. package/fesm2022/forty-cdk-select.mjs +3 -3
  33. package/fesm2022/forty-cdk-select.mjs.map +1 -1
  34. package/fesm2022/forty-cdk-time-picker.mjs +3 -3
  35. package/fesm2022/forty-cdk-time-picker.mjs.map +1 -1
  36. package/fesm2022/forty-cdk-tooltip.mjs +1 -0
  37. package/fesm2022/forty-cdk-tooltip.mjs.map +1 -1
  38. package/fesm2022/forty-cdk-tree.mjs +14 -1
  39. package/fesm2022/forty-cdk-tree.mjs.map +1 -1
  40. package/field/README.md +21 -27
  41. package/fieldset/README.md +12 -21
  42. package/file-upload/README.md +13 -29
  43. package/hover-card/README.md +22 -22
  44. package/input/README.md +38 -65
  45. package/internationalized-date/README.md +3 -3
  46. package/listbox/README.md +39 -40
  47. package/menu/README.md +50 -50
  48. package/menubar/README.md +46 -48
  49. package/meter/README.md +8 -8
  50. package/navigation-menu/README.md +14 -14
  51. package/number-input/README.md +16 -17
  52. package/otp-input/README.md +10 -10
  53. package/package.json +1 -1
  54. package/pagination/README.md +2 -2
  55. package/pane-resizer/README.md +20 -20
  56. package/popover/README.md +35 -33
  57. package/progress/README.md +6 -6
  58. package/radio-group/README.md +38 -21
  59. package/scroll-area/README.md +38 -38
  60. package/search/README.md +10 -10
  61. package/select/README.md +83 -83
  62. package/separator/README.md +6 -6
  63. package/shared/README.md +23 -23
  64. package/slider/README.md +29 -31
  65. package/stepper/README.md +22 -22
  66. package/switch/README.md +18 -18
  67. package/table/README.md +77 -77
  68. package/table-virtualization/README.md +19 -19
  69. package/tabs/README.md +23 -23
  70. package/time-field/README.md +17 -17
  71. package/time-picker/README.md +11 -11
  72. package/toast/README.md +54 -54
  73. package/toggle/README.md +41 -43
  74. package/toolbar/README.md +11 -11
  75. package/tooltip/README.md +29 -29
  76. package/tree/README.md +50 -38
  77. package/types/forty-cdk-combobox.d.ts +1 -0
  78. package/types/forty-cdk-core.d.ts +43 -14
  79. package/types/forty-cdk-dialog.d.ts +2 -1
  80. package/types/forty-cdk-drag-drop.d.ts +2 -2
  81. package/types/forty-cdk-field.d.ts +26 -9
  82. package/types/forty-cdk-tooltip.d.ts +6 -5
  83. package/types/forty-cdk-tree.d.ts +9 -0
  84. package/virtual-reorder/README.md +7 -7
  85. package/virtualization/README.md +7 -7
  86. package/visually-hidden/README.md +14 -14
@@ -11,9 +11,9 @@ A stack of collapsible sections, optionally allowing multiple panels open at onc
11
11
 
12
12
  ## When to choose
13
13
 
14
- - **Accordion** — a group of collapsible items under one root. `[(value)]` holds which are open, `multiple` decides whether more than one may be, and ArrowUp / ArrowDown / Home / End move focus across the triggers.
15
- - **[Disclosure](../disclosure/README.md)** — a single trigger and its region, with no shared state and no arrow-key navigation. Stacking several of them is not an accordion, and that is the right shape when the panels are unrelated.
16
- - **[Tabs](../tabs/README.md)** — when exactly one panel is ever visible and the panels are alternatives rather than sections the reader may open together.
14
+ - **Accordion**: a group of collapsible items under one root. `[(value)]` holds which are open, `multiple` decides whether more than one may be, and ArrowUp / ArrowDown / Home / End move focus across the triggers.
15
+ - **[Disclosure](../disclosure/README.md)**: a single trigger and its region, with no shared state and no arrow-key navigation. Stacking several of them is not an accordion, and that is the right shape when the panels are unrelated.
16
+ - **[Tabs](../tabs/README.md)**: when exactly one panel is ever visible and the panels are alternatives rather than sections the reader may open together.
17
17
 
18
18
  ## Anatomy
19
19
 
@@ -111,14 +111,14 @@ A disabled item cannot be toggled and is skipped by the arrow keys, while stayin
111
111
 
112
112
  ### `ForAccordion`
113
113
 
114
- | Property | Type | Description |
115
- | ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
116
- | `value` | `model<readonly string[]>` | Currently open item values. In single mode the array has 0 or 1 element.<br>**Default:** — |
117
- | `multiple` | `input<boolean>` | When true, multiple items can be open simultaneously.<br>**Default:** `false` |
118
- | `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` |
119
- | `disabled` | `input<boolean>` | When true, disables every item — each trigger reflects the native `disabled` attribute and cannot toggle. Composes with a per-item `[disabled]`.<br>**Default:** `false` |
120
- | `orientation` | `input<'horizontal' \| 'vertical'>` | Layout direction of the trigger list. In horizontal mode ArrowLeft/Right replace ArrowUp/Down.<br>**Default:** `'vertical'` |
121
- | `dir` | `input<'ltr' \| 'rtl'>` | Writing direction. Only relevant in horizontal mode — swaps the meaning of Left/Right arrows.<br>**Default:** — |
114
+ | Property | Type | Description |
115
+ | ------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
116
+ | `value` | `model<readonly string[]>` | Currently open item values. In single mode the array has 0 or 1 element.<br>**Default:** — |
117
+ | `multiple` | `input<boolean>` | When true, multiple items can be open simultaneously.<br>**Default:** `false` |
118
+ | `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` |
119
+ | `disabled` | `input<boolean>` | When true, disables every item: each trigger reflects the native `disabled` attribute and cannot toggle. Composes with a per-item `[disabled]`.<br>**Default:** `false` |
120
+ | `orientation` | `input<'horizontal' \| 'vertical'>` | Layout direction of the trigger list. In horizontal mode ArrowLeft/Right replace ArrowUp/Down.<br>**Default:** `'vertical'` |
121
+ | `dir` | `input<'ltr' \| 'rtl'>` | Writing direction. Only relevant in horizontal mode, where it swaps the meaning of Left/Right arrows.<br>**Default:** — |
122
122
 
123
123
  | Data attribute | Values |
124
124
  | ------------------ | -------------------------- |
@@ -154,35 +154,35 @@ A disabled item cannot be toggled and is skipped by the arrow keys, while stayin
154
154
 
155
155
  ## Keyboard
156
156
 
157
- | Key | Action |
158
- | -------------------------------------------- | -------------------------------------------------------------------------------------------------- |
159
- | <kbd>Enter</kbd> / <kbd>Space</kbd> | Toggle the focused trigger (native button). |
160
- | <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> | Move focus between triggers (vertical, default). Wrap-around, skips disabled. |
161
- | <kbd>ArrowLeft</kbd> / <kbd>ArrowRight</kbd> | Move focus between triggers (horizontal — flipped under `dir='rtl'`). Wrap-around, skips disabled. |
162
- | <kbd>Home</kbd> | Jump to the first trigger. |
163
- | <kbd>End</kbd> | Jump to the last trigger. |
157
+ | Key | Action |
158
+ | -------------------------------------------- | ------------------------------------------------------------------------------------------------- |
159
+ | <kbd>Enter</kbd> / <kbd>Space</kbd> | Toggle the focused trigger (native button). |
160
+ | <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> | Move focus between triggers (vertical, default). Wrap-around, skips disabled. |
161
+ | <kbd>ArrowLeft</kbd> / <kbd>ArrowRight</kbd> | Move focus between triggers (horizontal, flipped under `dir='rtl'`). Wrap-around, skips disabled. |
162
+ | <kbd>Home</kbd> | Jump to the first trigger. |
163
+ | <kbd>End</kbd> | Jump to the last trigger. |
164
164
 
165
165
  ## Accessibility
166
166
 
167
- - **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.
167
+ - **Heading wrapper is your job.** The library does not render a heading around the trigger, so wrap it in the heading level (`<h2>`–`<h6>`) appropriate to your document outline. Without it, screen-reader landmark navigation is broken.
168
168
  - **Use a real `<button type="button">` for the trigger.** Native Enter / Space activation and focus come for free; the directive does not synthesize them.
169
169
  - **`role="region"`** is added to every panel automatically. APG recommends suppressing it on accordions with 6+ panels to avoid landmark proliferation; there is currently no opt-out.
170
170
  - **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:
171
- - **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.
172
- - **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.
171
+ - **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.
172
+ - **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.
173
173
  - **`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.
174
174
  - **A truly disabled item (`[disabled]` on `[forAccordionItem]`) uses the native `disabled` attribute on the trigger, by design.** 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.
175
175
 
176
176
  ## Styling
177
177
 
178
- 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.
178
+ 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.
179
179
 
180
180
  ```css
181
- .trigger-chevron {
181
+ .chevron {
182
182
  transition: transform 150ms ease;
183
183
  }
184
184
 
185
- .accordion-trigger[data-state='open'] .trigger-chevron {
185
+ .acc-trigger[data-state='open'] .chevron {
186
186
  transform: rotate(180deg);
187
187
  }
188
188
  ```
@@ -8,21 +8,21 @@ archetype: [composable-ui]
8
8
 
9
9
  A container that keeps its content at a fixed width-to-height ratio.
10
10
 
11
- 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.
11
+ It is a pure visual utility that 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.
12
12
 
13
13
  ## Why this exists
14
14
 
15
- A fixed, never-changing ratio is one line of CSS — you don't need this primitive for that:
15
+ You don't need this primitive for a fixed, never-changing ratio, which is one line of CSS:
16
16
 
17
17
  ```css
18
- .card-cover {
18
+ .box {
19
19
  aspect-ratio: 16 / 9;
20
20
  }
21
21
  ```
22
22
 
23
23
  `[forAspectRatio]` earns its place when the ratio is **dynamic or must be validated**. It is more than the static declaration:
24
24
 
25
- - **Reactive `ratio` input.** Bind `[ratio]="ratio()"` and the host style recomputes as the value changes — no manual style writes.
25
+ - **Reactive `ratio` input.** Bind `[ratio]="ratio()"` and the host style recomputes as the value changes, with no manual style writes.
26
26
  - **Invalid-value guarding.** `0`, negative, and non-finite ratios fall back to `1`, so a bad computed value never emits invalid CSS.
27
27
  - **SSR-safe.** The `aspect-ratio` style is bound declaratively (never touched imperatively), so it renders identically on the server and hydrates cleanly.
28
28
  - **Consistent headless API.** Same shape as the other primitives, so it composes the same way.
@@ -39,7 +39,7 @@ If your ratio is a literal constant, prefer the CSS property directly and keep t
39
39
 
40
40
  ## Examples
41
41
 
42
- Resize the preview and watch the frame hold its 16 / 9 ratio — the primitive writes the ratio and nothing else, so every border, colour and inset below is your own CSS.
42
+ Resize the preview and watch the frame hold its 16 / 9 ratio. The primitive writes the ratio and nothing else, so every border, colour and inset below is your own CSS.
43
43
 
44
44
  ```ts
45
45
  import { ChangeDetectionStrategy, Component } from '@angular/core';
@@ -60,7 +60,7 @@ export class AspectRatioDefaultExample {}
60
60
 
61
61
  ### Square (1 / 1)
62
62
 
63
- Set `ratio` to `1` to keep a box perfectly square at any width — handy for avatars, thumbnails, or uniform grid cards.
63
+ Set `ratio` to `1` to keep a box perfectly square at any width. That is handy for avatars, thumbnails, or uniform grid cards.
64
64
 
65
65
  ## API
66
66
 
@@ -76,7 +76,7 @@ Set `ratio` to `1` to keep a box perfectly square at any width — handy for ava
76
76
 
77
77
  ## Styling
78
78
 
79
- 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]`.
79
+ 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]`.
80
80
 
81
81
  ## Behavior notes
82
82
 
package/avatar/README.md CHANGED
@@ -8,7 +8,7 @@ archetype: [composable-ui]
8
8
 
9
9
  A user image with a graceful fallback across its loading lifecycle.
10
10
 
11
- 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.
11
+ It is 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.
12
12
 
13
13
  ## Anatomy
14
14
 
@@ -64,7 +64,7 @@ export class AvatarDefaultExample {
64
64
 
65
65
  ### Failed load
66
66
 
67
- When the image errors, the directive flips `shouldShowFallback()` and the initials render in its place — an error shows the fallback at once, skipping the `fallbackDelayMs` wait.
67
+ When the image errors, the directive flips `shouldShowFallback()` and the initials render in its place. An error shows the fallback at once, skipping the `fallbackDelayMs` wait.
68
68
 
69
69
  ## API
70
70
 
@@ -102,7 +102,7 @@ The directive does not impose a `role`. Pair the avatar with visible name text o
102
102
 
103
103
  ## Styling
104
104
 
105
- 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
+ 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.
106
106
 
107
107
  ```css
108
108
  .avatar-image:not([data-status='loaded']) {
@@ -115,9 +115,9 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
115
115
 
116
116
  ## Behavior notes
117
117
 
118
- - **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`.
118
+ - **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`.
119
119
  - **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.
120
- - **`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.
120
+ - **`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.
121
121
  - **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.
122
122
 
123
123
  ## Wrapping in a design system
@@ -23,7 +23,7 @@ A labelled navigation landmark for a breadcrumb trail: links with aria-current='
23
23
 
24
24
  ## Examples
25
25
 
26
- Walk the trail with `Tab` — the last crumb is the page you are on, so it carries `aria-current="page"` and is not a link back to itself.
26
+ Walk the trail with `Tab`: the last crumb is the page you are on, so it carries `aria-current="page"` and is not a link back to itself.
27
27
 
28
28
  ```ts
29
29
  import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
@@ -82,11 +82,9 @@ export class BreadcrumbsDefaultExample {
82
82
  }
83
83
  ```
84
84
 
85
- 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.
86
-
87
85
  ### Collapsing a long trail
88
86
 
89
- The primitive renders whatever items you give it, so collapsing a deep path is a consumer decision. Here the middle is folded into an expandable ellipsis button that reveals the hidden crumbs — the trail stays a single accessible navigation landmark either way.
87
+ The primitive renders whatever items you give it, so collapsing a deep path is a consumer decision. Here the middle is folded into an expandable ellipsis button that reveals the hidden crumbs. The trail stays a single accessible navigation landmark either way.
90
88
 
91
89
  ## Localizing the label
92
90
 
@@ -120,7 +118,7 @@ bootstrapApplication(App, {
120
118
 
121
119
  Implements the [WAI-ARIA Breadcrumb pattern](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/).
122
120
 
123
- - **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.
121
+ - **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. When a page hosts more than one trail, name each with `[ariaLabel]`, or point a native `aria-labelledby` at a visible heading.
124
122
  - **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.
125
123
  - **Decorative separators.** `[forBreadcrumbSeparator]` reflects `aria-hidden="true"` so the visual divider (e.g. `/`) is skipped by screen readers.
126
124
 
@@ -6,13 +6,13 @@ archetype: [headless-utility]
6
6
 
7
7
  # Breakpoints
8
8
 
9
- A signal-first, zoneless, SSR-safe viewport breakpoint observer (injectBreakpoints). Configure the breakpoint map once via provideForBreakpointsDefaults — or use the Tailwind scale by default — then read up / down / between / only / active or any arbitrary media query, each as a live Signal&lt;boolean&gt;.
9
+ A signal-first, zoneless, SSR-safe viewport breakpoint observer (injectBreakpoints). Configure the breakpoint map once via provideForBreakpointsDefaults (or use the Tailwind scale by default), then read up / down / between / only / active or any arbitrary media query, each as a live Signal&lt;boolean&gt;.
10
10
 
11
- 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.
11
+ It is a headless reactive utility, not a UI primitive: no DOM, no ARIA, no template. Configure the breakpoint map **once** via a provider and read it anywhere with `injectBreakpoints()`, so there is no need to repeat the breakpoint set at every call site.
12
12
 
13
13
  ## Setup
14
14
 
15
- Configuring is optional — without a provider the Tailwind scale (`sm` 640, `md` 768, `lg` 1024, `xl` 1280, `2xl` 1536) is used. To define your own:
15
+ Configuring is optional: without a provider the Tailwind scale (`sm` 640, `md` 768, `lg` 1024, `xl` 1280, `2xl` 1536) is used. To define your own:
16
16
 
17
17
  ```ts
18
18
  import { ApplicationConfig } from '@angular/core';
@@ -95,25 +95,17 @@ export class BreakpointsActiveExample {
95
95
  }
96
96
  ```
97
97
 
98
- 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:
99
-
100
- <!-- snippet: fragment -->
101
-
102
- ```ts
103
- protected columns = computed(() => (this.bp.up('xl')() ? 4 : this.bp.up('md')() ? 2 : 1));
104
- ```
105
-
106
98
  ### Responsive layout
107
99
 
108
100
  Derive UI from the breakpoint inside `computed()` and `@if` instead of repeating media queries in the template. The card grid picks its column count from `up('md')` / `up('lg')` / `up('xl')`, and the sidebar is only mounted at `lg` and wider.
109
101
 
110
102
  ### Arbitrary media queries
111
103
 
112
- `matches(query)` is the escape hatch for any media feature the named width helpers don't cover — orientation, pointer, hover, and the `prefers-*` user settings. Each call returns a live `Signal<boolean>` from the same cached `MediaQueryList` layer.
104
+ `matches(query)` is the escape hatch for any media feature the named width helpers don't cover: orientation, pointer, hover, and the `prefers-*` user settings. Each call returns a live `Signal<boolean>` from the same cached `MediaQueryList` layer.
113
105
 
114
106
  ## Typed custom names
115
107
 
116
- The default map gives you fully-typed names out of the box (`up('md')` autocompletes; `up('foo')` is a type error). When you provide a custom map, recover the same typing by augmenting `BreakpointRegistry` once — derive the keys from your map so you never write them twice:
108
+ The default map gives you fully-typed names out of the box (`up('md')` autocompletes; `up('foo')` is a type error). When you provide a custom map, recover the same typing by augmenting `BreakpointRegistry` once. Derive the keys from your map so you never write them twice:
117
109
 
118
110
  ```ts
119
111
  // breakpoints.ts
@@ -137,13 +129,21 @@ Now `injectBreakpoints()` autocompletes `'mobile' | 'tablet' | 'laptop' | 'deskt
137
129
 
138
130
  | Method | Matches |
139
131
  | ---------------- | ------------------------------------------------------------------------------ |
140
- | `up(name)` | the breakpoint and wider — `(min-width: N px)` |
141
- | `down(name)` | narrower than the breakpoint — `(max-width: (N − 0.02) px)` |
132
+ | `up(name)` | the breakpoint and wider: `(min-width: N px)` |
133
+ | `down(name)` | narrower than the breakpoint: `(max-width: (N − 0.02) px)` |
142
134
  | `between(a, b)` | from `a` (inclusive) up to but not including `b` |
143
135
  | `only(name)` | the breakpoint's own band, up to but not including the next-larger one |
144
136
  | `active` | the largest breakpoint whose `min-width` matches, or `null` below the smallest |
145
137
  | `matches(query)` | escape hatch for an arbitrary media query (orientation, `prefers-*`, …) |
146
138
 
139
+ 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:
140
+
141
+ <!-- snippet: fragment -->
142
+
143
+ ```ts
144
+ protected columns = computed(() => (this.bp.up('xl')() ? 4 : this.bp.up('md')() ? 2 : 1));
145
+ ```
146
+
147
147
  ### `injectPrefersReducedMotion`
148
148
 
149
149
  The same shape for a different query: `injectPrefersReducedMotion()` returns a `Signal<boolean>` that is `true` while the user has asked their OS to suppress animation, and flips if they change the setting mid-session. Call it from an injection context, like `injectBreakpoints()`.
@@ -161,9 +161,9 @@ export class Panel {
161
161
  }
162
162
  ```
163
163
 
164
- It is published here because forty-cdk ships no styles: the animation on a `data-state` change is yours, so honouring the preference is yours too — and a signal is what a `computed()` or a `[style]` binding can branch on, which a CSS `@media` block cannot. Treat `true` as "skip the animated path entirely", not "shorten the duration": the setting asks for no motion, not less of it.
164
+ It is published here because forty-cdk ships no styles: the animation on a `data-state` change is yours, so honouring the preference is yours too. A signal is also what a `computed()` or a `[style]` binding can branch on, which a CSS `@media` block cannot. Treat `true` as "skip the animated path entirely", not "shorten the duration": the setting asks for no motion, not less of it.
165
165
 
166
- `bp.matches('(prefers-reduced-motion: reduce)')` resolves to the same thing. Prefer the named helper — it is the one the library's own motion-bearing primitives (drag gestures, carousel, drawer) read, so the query string stays spelled in one place.
166
+ `bp.matches('(prefers-reduced-motion: reduce)')` resolves to the same thing. Prefer the named helper: it is the one the library's own motion-bearing primitives (drag gestures, carousel, drawer) read, so the query string stays spelled in one place.
167
167
 
168
168
  ## SSR
169
169
 
package/button/README.md CHANGED
@@ -7,7 +7,7 @@ apgUrl: https://www.w3.org/WAI/ARIA/apg/patterns/button/
7
7
 
8
8
  # ForButton
9
9
 
10
- 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.
10
+ 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.
11
11
 
12
12
  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.
13
13
 
@@ -23,7 +23,7 @@ A single `[forButton]` directive does all of this. On a native `<button>` host t
23
23
 
24
24
  ## Examples
25
25
 
26
- Press and hold either control — a native `<button>` and a `<span>` — and watch `data-pressed`, `data-hovered` and `data-focus-visible` appear on both, so one rule styles the pair.
26
+ Press and hold either control (a native `<button>` and a `<span>`) and watch `data-pressed`, `data-hovered` and `data-focus-visible` appear on both, so one rule styles the pair.
27
27
 
28
28
  ```ts
29
29
  import { ChangeDetectionStrategy, Component } from '@angular/core';
@@ -45,7 +45,7 @@ export class ButtonDefaultExample {}
45
45
 
46
46
  ### Disabled stays focusable
47
47
 
48
- Per the APG, a disabled button must stay reachable so assistive tech can announce it. `forButton` never sets the native `disabled` attribute — it reflects `aria-disabled='true'` + `data-disabled` and makes activation a no-op. The native disabled button is skipped entirely.
48
+ Per the APG, a disabled button must stay reachable so assistive tech can announce it. `forButton` never sets the native `disabled` attribute. Instead, it reflects `aria-disabled='true'` + `data-disabled` and makes activation a no-op. The native disabled button is skipped entirely.
49
49
 
50
50
  ## Disabled
51
51
 
@@ -55,7 +55,7 @@ Disabled buttons stay focusable so assistive technology can announce them. The n
55
55
  <button forButton [disabled]="isSaving()" (activate)="save()">Save</button>
56
56
  ```
57
57
 
58
- A surrounding disabled `[forFieldset]` disables the button too — its `disabled` input is OR'd with the group's, so `aria-disabled` / `data-disabled` are reflected and activation is suppressed. This matters most on a non-native host (`<div forButton>`), which a native `<fieldset disabled>` cannot reach.
58
+ A surrounding disabled `[forFieldset]` disables the button too: its `disabled` input is OR'd with the group's, so `aria-disabled` / `data-disabled` are reflected and activation is suppressed. This matters most on a non-native host (`<div forButton>`), which a native `<fieldset disabled>` cannot reach.
59
59
 
60
60
  ```html
61
61
  <fieldset forFieldset [disabled]="locked()">
@@ -81,7 +81,7 @@ A native `<button>` without an explicit `type` attribute defaults to `type="butt
81
81
  | `disabled` | `input<boolean>` | Suppresses activation and reflects `aria-disabled` + `data-disabled`. OR'd with a surrounding `[forFieldset]`'s disabled state.<br>**Default:** `false` |
82
82
  | `activate` | `output<void>` | Fires once per user activation (click, Enter, Space). Never fires when disabled.<br>**Default:** — |
83
83
 
84
- 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.
84
+ The directive reflects boolean `data-*` attributes (present with an empty-string value when true, absent when false). There is no `data-state`, because this primitive has no open/closed or checked/unchecked logical state.
85
85
 
86
86
  | Data attribute | Values |
87
87
  | -------------------- | ----------------- |
@@ -94,14 +94,14 @@ The directive reflects boolean `data-*` attributes (present with an empty-string
94
94
 
95
95
  ## Keyboard
96
96
 
97
- On a native `<button>` host the platform owns activation: every key handler the directive binds returns immediately, and nothing in this table is its doing. On any other host (`<div forButton>`, `<span forButton>`) it synthesizes the activation itself, through the same `(click)` path a pointer takes — on a deliberately asymmetric split, because that is what a native button does.
97
+ On a native `<button>` host the platform owns activation: every key handler the directive binds returns immediately, and nothing in this table is its doing. On any other host (`<div forButton>`, `<span forButton>`) it synthesizes the activation itself, through the same `(click)` path a pointer takes. The split between the two keys is deliberately asymmetric, because that is what a native button does.
98
98
 
99
- | Key | Action |
100
- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
101
- | `Enter` — native `<button>` | The platform synthesizes the click; the directive adds nothing. |
102
- | `Enter` — any other host | Activates on `keydown`, so `(activate)` fires while the key is still held. While disabled the event is left alone entirely — not even its default is prevented. |
103
- | `Space` — native `<button>` | The platform synthesizes the click on release and suppresses the page scroll itself. |
104
- | `Space` — any other host | Activates on `keyup`, and only when the matching `keydown` reached the same host — focus leaving mid-press drops the press. Its `keydown` always calls `preventDefault()` to stop the page scrolling, **even while the button is disabled**. |
99
+ | Key | Action |
100
+ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
101
+ | `Enter` on a native `<button>` | The platform synthesizes the click; the directive adds nothing. |
102
+ | `Enter` on any other host | Activates on `keydown`, so `(activate)` fires while the key is still held. While disabled the event is left alone entirely: not even its default is prevented. |
103
+ | `Space` on a native `<button>` | The platform synthesizes the click on release and suppresses the page scroll itself. |
104
+ | `Space` on any other host | Activates on `keyup`, and only when the matching `keydown` reached the same host. Focus leaving mid-press drops the press. Its `keydown` always calls `preventDefault()` to stop the page scrolling, **even while the button is disabled**. |
105
105
 
106
106
  Both keys drive `data-pressed` on every host: present from `keydown` until `keyup`, until focus leaves, or until the pointer is released. `data-focus-visible` instead follows the keyboard modality, so a `keydown` carrying `Meta` / `Control` / `Alt` is read as a shortcut and does not turn it on, while `Shift` does.
107
107
 
@@ -110,12 +110,12 @@ Both keys drive `data-pressed` on every host: present from `keydown` until `keyu
110
110
  Implements the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).
111
111
 
112
112
  - **Native `<button>` semantics are preserved.** On a native host, no extra ARIA is added; the browser's built-in button role, keyboard activation, and `type` handling all apply.
113
- - **Non-button hosts get `role="button"` and `tabindex="0"`**, and the directive synthesizes the activation the platform would have — see [Keyboard](#keyboard).
113
+ - **Non-button hosts get `role="button"` and `tabindex="0"`**, and the directive synthesizes the activation the platform would have (see [Keyboard](#keyboard)).
114
114
  - **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.
115
115
 
116
116
  ## Styling
117
117
 
118
- 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.
118
+ 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.
119
119
 
120
120
  ```css
121
121
  [forButton][data-disabled] {