@konce-pt/angular 0.9.1 → 0.10.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 +307 -0
- package/fesm2022/konce-pt-angular.mjs +5429 -1758
- package/fesm2022/konce-pt-angular.mjs.map +1 -1
- package/package.json +11 -11
- package/src/lib/accordion/llms.txt +6 -0
- package/src/lib/alert/llms.txt +7 -0
- package/src/lib/app-shell/llms.txt +4 -3
- package/src/lib/autocomplete/llms.txt +13 -0
- package/src/lib/avatar/llms.txt +6 -3
- package/src/lib/avatar-group/llms.txt +6 -0
- package/src/lib/badge/llms.txt +11 -2
- package/src/lib/bottom-sheet/llms.txt +8 -1
- package/src/lib/breadcrumb/llms.txt +5 -0
- package/src/lib/button/llms.txt +3 -0
- package/src/lib/card/llms.txt +8 -0
- package/src/lib/carousel/llms.txt +13 -1
- package/src/lib/checkbox/llms.txt +10 -0
- package/src/lib/chip/llms.txt +6 -0
- package/src/lib/chips-input/llms.txt +12 -0
- package/src/lib/color-picker/llms.txt +14 -0
- package/src/lib/confirm/llms.txt +5 -0
- package/src/lib/context-menu/llms.txt +8 -0
- package/src/lib/data-table/llms.txt +5 -4
- package/src/lib/date-range/llms.txt +24 -2
- package/src/lib/datepicker/llms.txt +25 -5
- package/src/lib/dialog/llms.txt +18 -0
- package/src/lib/drawer/llms.txt +7 -1
- package/src/lib/empty/llms.txt +6 -0
- package/src/lib/fab/llms.txt +5 -2
- package/src/lib/file-upload/llms.txt +12 -1
- package/src/lib/form-field/llms.txt +24 -4
- package/src/lib/galleria/llms.txt +13 -1
- package/src/lib/i18n/llms.txt +2 -2
- package/src/lib/icon/llms.txt +9 -1
- package/src/lib/icon-button/llms.txt +3 -1
- package/src/lib/image/llms.txt +10 -1
- package/src/lib/input/llms.txt +6 -0
- package/src/lib/input-mask/llms.txt +11 -0
- package/src/lib/input-number/llms.txt +18 -0
- package/src/lib/input-otp/llms.txt +14 -0
- package/src/lib/knob/llms.txt +8 -0
- package/src/lib/listbox/llms.txt +16 -1
- package/src/lib/megamenu/llms.txt +21 -1
- package/src/lib/menu/llms.txt +14 -4
- package/src/lib/menubar/llms.txt +21 -0
- package/src/lib/meter-group/llms.txt +10 -0
- package/src/lib/order-list/llms.txt +11 -2
- package/src/lib/panel/llms.txt +7 -0
- package/src/lib/password/llms.txt +9 -1
- package/src/lib/pick-list/llms.txt +12 -2
- package/src/lib/popover/llms.txt +11 -0
- package/src/lib/radio-group/llms.txt +11 -0
- package/src/lib/rating/llms.txt +18 -4
- package/src/lib/rich-text/llms.txt +18 -0
- package/src/lib/scroll-top/llms.txt +12 -0
- package/src/lib/select/llms.txt +23 -5
- package/src/lib/sidenav/llms.txt +6 -0
- package/src/lib/skeleton/llms.txt +2 -1
- package/src/lib/slider/llms.txt +13 -0
- package/src/lib/speed-dial/llms.txt +8 -0
- package/src/lib/spinner/llms.txt +10 -1
- package/src/lib/split-button/llms.txt +11 -2
- package/src/lib/splitter/llms.txt +10 -1
- package/src/lib/stepper/llms.txt +8 -0
- package/src/lib/switch/llms.txt +11 -0
- package/src/lib/switch-group/llms.txt +11 -0
- package/src/lib/tabs/llms.txt +7 -0
- package/src/lib/textarea/llms.txt +12 -0
- package/src/lib/toast/llms.txt +19 -1
- package/src/lib/tooltip/llms.txt +12 -0
- package/src/lib/tree/llms.txt +21 -0
- package/types/konce-pt-angular.d.ts +1047 -73
- package/types/konce-pt-angular.d.ts.map +1 -1
|
@@ -12,7 +12,7 @@ Import: `import { KptFormField } from '@konce-pt/angular';`
|
|
|
12
12
|
- `hint`: string — a hint (hidden while there is an error)
|
|
13
13
|
- `error`: string | null — the error message; when non-empty, the field is marked invalid
|
|
14
14
|
- `required`: boolean — an asterisk next to the label
|
|
15
|
-
- `controlId`: string — the control's id
|
|
15
|
+
- `controlId`: string — optional; the control's id for `label[for]` (library controls report theirs)
|
|
16
16
|
- `labelType`: 'fixed' | 'over' | 'in' | 'on' — the label variant (default `fixed`)
|
|
17
17
|
|
|
18
18
|
## Label variants (labelType)
|
|
@@ -48,11 +48,30 @@ reports being filled itself — it provides the `KPT_FORM_FIELD_CONTROL` token w
|
|
|
48
48
|
Once a control provides the token, `kpt-form-field` stops looking into the DOM and trusts the
|
|
49
49
|
`filled` signal alone — which is why the label rises the instant the value changes.
|
|
50
50
|
|
|
51
|
+
## Linking the control (label, hint, error)
|
|
52
|
+
`kpt-form-field` provides the `KPT_FORM_FIELD` context to its content, and every library control
|
|
53
|
+
uses it: the control reports its `id` (its own, or a generated one) and `label[for]` points at it,
|
|
54
|
+
so **`controlId` is optional**. A control on a `div` with a role (`kpt-select`, `kpt-datepicker`,
|
|
55
|
+
`kpt-radio-group`, `kpt-rich-text`…) is not named by `label[for]`, so it gets `aria-labelledby`
|
|
56
|
+
pointing at the label. The visible hint or error has an `id` and lands in the control's
|
|
57
|
+
`aria-describedby` — a screen reader hears it when it reaches the field, not only when the error appears.
|
|
58
|
+
|
|
59
|
+
A custom control links itself with `kptFieldA11y`:
|
|
60
|
+
|
|
61
|
+
import { kptFieldA11y } from '@konce-pt/angular';
|
|
62
|
+
|
|
63
|
+
readonly id = input<string | null>(null);
|
|
64
|
+
protected readonly field = kptFieldA11y(this.id, 'my-control');
|
|
65
|
+
// template: [id]="field.id()" [attr.aria-labelledby]="field.labelledBy()"
|
|
66
|
+
// [attr.aria-describedby]="field.describedBy()"
|
|
67
|
+
|
|
68
|
+
`controlId` given explicitly still wins, and a control without its own `id` takes it.
|
|
69
|
+
|
|
51
70
|
## Content projection
|
|
52
71
|
The control goes into the content (ng-content):
|
|
53
72
|
|
|
54
|
-
<kpt-form-field label="E-mail" [error]="emailError()" hint="Your work address" required
|
|
55
|
-
<kpt-input [formField]="loginForm.email" type="email"
|
|
73
|
+
<kpt-form-field label="E-mail" [error]="emailError()" hint="Your work address" required>
|
|
74
|
+
<kpt-input [formField]="loginForm.email" type="email" />
|
|
56
75
|
</kpt-form-field>
|
|
57
76
|
|
|
58
77
|
## Integration with Signal Forms
|
|
@@ -77,4 +96,5 @@ The float variants add: `--kpt-form-field-placeholder` (the resting label),
|
|
|
77
96
|
|
|
78
97
|
## Accessibility
|
|
79
98
|
- The error message carries `role="alert"`.
|
|
80
|
-
-
|
|
99
|
+
- The label, hint and error are linked to the control automatically (`label[for]` or `aria-labelledby`,
|
|
100
|
+
plus `aria-describedby`) — see "Linking the control" above.
|
|
@@ -11,5 +11,17 @@ Import: `import { KptGalleria } from '@konce-pt/angular';`
|
|
|
11
11
|
## Example
|
|
12
12
|
<kpt-galleria [items]="photos" [(activeIndex)]="idx" />
|
|
13
13
|
|
|
14
|
+
## Keyboard
|
|
15
|
+
Anywhere inside the gallery, `ArrowLeft`/`ArrowRight` move to the neighbouring image (reversed in
|
|
16
|
+
RTL) and `Home`/`End` to the first/last. When focus is on a thumbnail, it follows the active one.
|
|
17
|
+
|
|
14
18
|
## Tokens
|
|
15
|
-
The stage `--kpt-color-muted`; the active thumbnail `--kpt-color-primary`.
|
|
19
|
+
The stage `--kpt-color-muted`; the active thumbnail `--kpt-color-primary`; the arrows `--kpt-color-surface` (85% via `color-mix`, solid on hover) / `--kpt-color-on-surface` with `--kpt-elevation-2`.
|
|
20
|
+
|
|
21
|
+
## Accessibility
|
|
22
|
+
The large image carries its `alt`. Each thumbnail is a button named by the item's `alt` (or
|
|
23
|
+
`galleria.image` — “Image 3” — when there is none), with `alt=""` on the thumbnail image so the
|
|
24
|
+
name is not read twice; the active one carries `aria-current`. The arrows use `aria-disabled` at
|
|
25
|
+
the ends instead of `disabled`, so they keep the focus. A change of image is announced politely
|
|
26
|
+
through a hidden live region — `galleria.position` (“Image 2 of 4”) plus the `alt` — only after the
|
|
27
|
+
user acts, never on first render.
|
package/src/lib/i18n/llms.txt
CHANGED
|
@@ -26,9 +26,9 @@ Import: `import { provideKptI18n, KptI18n } from '@konce-pt/angular';`
|
|
|
26
26
|
## The key contract (KptMessages)
|
|
27
27
|
Namespaces: `common` (close/remove/previous/next/clear/done/all), `paginator` (rowsPerPage/range/prevPage/nextPage),
|
|
28
28
|
`select`, `listbox`, `dataView`, `dataTable`, `confirm`, `fileUpload`, `chipsInput`, `dateRange`, `datepicker`,
|
|
29
|
-
`pickList`, `orderList`, `inputNumber`, `password`, `rating`, `spinner`, `speedDial`, `scrollTop`, `splitButton`, `panel`,
|
|
29
|
+
`pickList`, `orderList`, `inputNumber`, `password`, `rating`, `slider`, `colorPicker`, `inputOtp`, `autocomplete`, `spinner`, `speedDial`, `scrollTop`, `splitButton`, `panel`, `splitter`, `stepper`, `image`, `toast`, `avatarGroup`, `meterGroup`,
|
|
30
30
|
`breadcrumb`, `richText`, `auth` (including `auth.promo.*`). Interpolations: `paginator.range` ({start},{end},{total}), `dataTable.filter*` ({column}),
|
|
31
|
-
`richText.styleHeading` ({level}), `auth.continueWith` ({provider}), `auth.passwordHint` and `auth.errorMinLength` ({min}), `rating.star` ({value},{max}). Day and month names in calendars are derived from `Intl` per locale (not from the dictionary).
|
|
31
|
+
`richText.styleHeading` ({level}), `auth.continueWith` ({provider}), `auth.passwordHint` and `auth.errorMinLength` ({min}), `rating.star` ({value},{max}), `panel.toggleNamed` ({header}), `stepper.step*` ({index},{label}), `carousel.slideOf` and `galleria.position` ({index},{total}), `image.previewOf` ({alt}), `avatarGroup.more` ({count}), `inputOtp.cell` ({index},{count}), `autocomplete.results` ({count}), `chipsInput.added`/`removed`/`duplicate` ({value}), `dateRange.rangeStart`/`rangeEnd`/`inRange`/`pickEnd` ({date}) and `dateRange.picked` ({start},{end}). Day and month names in calendars are derived from `Intl` per locale (not from the dictionary).
|
|
32
32
|
|
|
33
33
|
## Note
|
|
34
34
|
Individual labels can also be overridden per component through the matching `input()` (e.g. `emptyMessage`, `acceptLabel`) —
|
package/src/lib/icon/llms.txt
CHANGED
|
@@ -11,6 +11,7 @@ the color from `currentColor`. Import: `import { KptIcon } from '@konce-pt/angul
|
|
|
11
11
|
built-in names: once the Tabler set is registered there are 5130 legal names, so a closed
|
|
12
12
|
union would reject icons that work at runtime.
|
|
13
13
|
- `size`: string (optional, e.g. '1.25rem') — otherwise inherited from font-size
|
|
14
|
+
- `label`: string — a name for screen readers; with it the icon is `role="img"`, without it `aria-hidden`
|
|
14
15
|
|
|
15
16
|
## Available names (built in, no configuration)
|
|
16
17
|
menu, x, chevron-up, chevron-down, chevron-left, chevron-right, check, search
|
|
@@ -23,7 +24,8 @@ clipboard, clipboard-text, table, mail, share, external-link, crosshair
|
|
|
23
24
|
adjustments-horizontal, sun, moon, bell, settings, users, user-circle, logout, login
|
|
24
25
|
layout-dashboard, home, activity, cube, shopping-cart, currency-dollar, arrow-left
|
|
25
26
|
arrow-right, arrow-up-right, arrow-down-right, chart-bar, chart-line, filter, download
|
|
26
|
-
refresh, dots, brand-github, brand-google
|
|
27
|
+
refresh, dots, brand-github, brand-google, layout-grid, grid-dots, checks, paperclip
|
|
28
|
+
send, message-circle, corner-up-left, mood-smile, device-floppy, arrow-back-up, printer
|
|
27
29
|
|
|
28
30
|
These cover both what the components themselves draw and the staples of an application shell
|
|
29
31
|
(theme, notifications, account, navigation, KPI). A typical admin panel needs nothing else.
|
|
@@ -66,3 +68,9 @@ at build time, never straight from runtime/CMS/upload data.
|
|
|
66
68
|
## Icon license
|
|
67
69
|
Tabler Icons (MIT). The icons are extracted inline into `icons.ts`. See ICONS-LICENSE at the root.
|
|
68
70
|
Adding an icon: add an entry to `KPT_ICONS`/`KptIconName` (a 24×24 grid, 2px stroke).
|
|
71
|
+
|
|
72
|
+
## Accessibility
|
|
73
|
+
By default an icon is `aria-hidden` — decorative, which is right next to a text label or inside
|
|
74
|
+
an icon button with its own name. An icon that carries meaning on its own gets `label`: it becomes
|
|
75
|
+
`role="img"` with that `aria-label`. In development builds an unknown name logs one console
|
|
76
|
+
warning per name instead of rendering silently empty.
|
|
@@ -4,7 +4,9 @@ An icon-only button. `ariaLabel` is required.
|
|
|
4
4
|
Import: `import { KptIconButton } from '@konce-pt/angular';`
|
|
5
5
|
|
|
6
6
|
## Inputs
|
|
7
|
-
- `variant`: 'filled'|'tonal'|'outline'|'text'|'danger'; `size`: 'sm'|'md'|'lg'
|
|
7
|
+
- `variant`: 'filled'|'tonal'|'outline'|'text'|'danger' (default 'text'); `size`: 'sm'|'md'|'lg' (default 'md');
|
|
8
|
+
`shape`: 'round'|'square' (default 'round'). The type is the wider `KptButtonVariant` / `KptButtonSize`,
|
|
9
|
+
but only these values have a style
|
|
8
10
|
- `type`, `disabled`, `loading`, `ariaLabel` (required)
|
|
9
11
|
- `ariaPressed`: `boolean | null` = `null` — toggle state; lands on the inner `<button>`, so a screen reader announces it (`[attr.aria-pressed]` on the tag would sit on the host, which has no button role)
|
|
10
12
|
- `ariaExpanded`: `boolean | null` = `null` — disclosure state for a button that opens a panel; lands on the inner `<button>` for the same reason
|
package/src/lib/image/llms.txt
CHANGED
|
@@ -12,4 +12,13 @@ Import: `import { KptImage } from '@konce-pt/angular';`
|
|
|
12
12
|
<kpt-image src="/photo.jpg" alt="Photo" preview width="240px" />
|
|
13
13
|
|
|
14
14
|
## Tokens
|
|
15
|
-
|
|
15
|
+
The radius `--kpt-radius-md`; the backdrop and the hover mask `--kpt-color-overlay-scrim`; the × button and the magnifier disc `--kpt-color-surface` / `--kpt-color-on-surface` with `--kpt-elevation-2`.
|
|
16
|
+
|
|
17
|
+
## Accessibility
|
|
18
|
+
With `preview`, the thumbnail is a `<button aria-haspopup="dialog">` named “Show full size: <alt>”
|
|
19
|
+
(`image.previewOf`, or `image.preview` without `alt`), so it is reached with Tab and opened with
|
|
20
|
+
Enter or Space; the magnifier shows on hover and on `:focus-visible`. The preview is a native modal
|
|
21
|
+
`<dialog>` opened with `showModal()` and named by `alt`: focus moves to its × button and stays inside,
|
|
22
|
+
Escape closes it, the page behind is inert, document scrolling is locked while it is open, and focus
|
|
23
|
+
returns to the thumbnail. It sits in the top layer, so no ancestor with `transform` or
|
|
24
|
+
`overflow: hidden` can clip it.
|
package/src/lib/input/llms.txt
CHANGED
|
@@ -39,6 +39,12 @@ The full flow: the `## A form from scratch (Signal Forms)` section in the root l
|
|
|
39
39
|
`value` (model, required), `disabled`, `readonly`, `required`, `invalid`, `errors`,
|
|
40
40
|
`touched`; the `touch` output (emitted on blur). Do not set them by hand when used with a form.
|
|
41
41
|
|
|
42
|
+
## Label and description
|
|
43
|
+
`id` goes to the native field — the host never carries it; without one it is generated. Inside
|
|
44
|
+
`kpt-form-field` the control links itself: the wrapper's `label[for]` points at it and the hint or
|
|
45
|
+
error is added to `aria-describedby`, so `controlId` is not needed. Without a wrapper, name it with
|
|
46
|
+
`ariaLabel`.
|
|
47
|
+
|
|
42
48
|
## Tokens
|
|
43
49
|
`--kpt-form-field-{bg,text,placeholder,border,border-hover,border-focus,border-error,radius}`.
|
|
44
50
|
|
|
@@ -16,5 +16,16 @@ Import: `import { KptInputMask } from '@konce-pt/angular';`
|
|
|
16
16
|
<kpt-input-mask [formField]="f.phone" mask="(999) 999-99-99" />
|
|
17
17
|
<kpt-input-mask [(value)]="zip" mask="99-999" />
|
|
18
18
|
|
|
19
|
+
## Screen reader and keyboard
|
|
20
|
+
The on-screen keyboard follows the mask: only `9` tokens (phone, postal code) give
|
|
21
|
+
`inputmode="numeric"`, otherwise `text`; override it with `inputMode`. `autocomplete` (`tel`,
|
|
22
|
+
`postal-code`…) lets the browser fill the field in.
|
|
23
|
+
|
|
24
|
+
## Label and description
|
|
25
|
+
`id` goes to the native field — the host never carries it; without one it is generated. Inside
|
|
26
|
+
`kpt-form-field` the control links itself: the wrapper's `label[for]` points at it and the hint or
|
|
27
|
+
error is added to `aria-describedby`, so `controlId` is not needed. Without a wrapper, name it with
|
|
28
|
+
`ariaLabel`. New: `aria-invalid` after touch.
|
|
29
|
+
|
|
19
30
|
## Tokens
|
|
20
31
|
The field uses `--kpt-form-field-*`.
|
|
@@ -62,5 +62,23 @@ and would not show up under any control.
|
|
|
62
62
|
the error belongs to. Messages are supplied through `errorFor()` with a `touched()` gate — do not
|
|
63
63
|
gate the validators. The full submit flow: `## A form from scratch (Signal Forms)` in the root llms.txt.
|
|
64
64
|
|
|
65
|
+
## Keyboard
|
|
66
|
+
The field is `role="spinbutton"` with `aria-valuemin`/`aria-valuemax`/`aria-valuenow` (and
|
|
67
|
+
`aria-valuetext` with the `suffix`, "5 pcs"). `↑`/`↓` change the value by `step`,
|
|
68
|
+
`PageUp`/`PageDown` by ten steps; stepping is rounded to the precision of `step`. A typed value is
|
|
69
|
+
**not** clamped while typing ("150" with `max` 99 stays "150", so the form's `max()` can report it) —
|
|
70
|
+
it is clamped on blur. The `−`/`+` buttons sit outside the Tab order and do not take focus from the
|
|
71
|
+
field, so focus never drops to `<body>` when a button goes disabled at a limit.
|
|
72
|
+
|
|
73
|
+
## Screen reader and keyboard
|
|
74
|
+
The value is shown in the active locale's notation (PL `12,5`), without thousands separators — the
|
|
75
|
+
field accepts both a dot and a comma, and digit grouping would clash with what the user types.
|
|
76
|
+
|
|
77
|
+
## Label and description
|
|
78
|
+
`id` goes to the native field — the host never carries it; without one it is generated. Inside
|
|
79
|
+
`kpt-form-field` the control links itself: the wrapper's `label[for]` points at it and the hint or
|
|
80
|
+
error is added to `aria-describedby`, so `controlId` is not needed. Without a wrapper, name it with
|
|
81
|
+
`ariaLabel`. New: `id`, `ariaLabel`, `required` and `aria-invalid` on the field.
|
|
82
|
+
|
|
65
83
|
## Tokens
|
|
66
84
|
The field `--kpt-form-field-*`; the buttons `--kpt-color-muted`.
|
|
@@ -15,5 +15,19 @@ Typing a character moves to the next box; Backspace goes back; pasting spreads t
|
|
|
15
15
|
## Example
|
|
16
16
|
<kpt-input-otp [formField]="f.code" [length]="6" integerOnly />
|
|
17
17
|
|
|
18
|
+
## Screen reader and keyboard
|
|
19
|
+
The first cell has `autocomplete="one-time-code"`, so phones offer the code from an SMS; a code that
|
|
20
|
+
arrives in one cell at once (autofill, an on-screen keyboard paste) is spread over the cells like a
|
|
21
|
+
paste. `touch` fires when focus leaves the whole group — not after a paste, and not when moving
|
|
22
|
+
between cells.
|
|
23
|
+
|
|
24
|
+
## Label and description
|
|
25
|
+
`id` goes to the focusable element — the host never carries it; without one it is generated. A `div`
|
|
26
|
+
with a role is not named by `label[for]`, so inside `kpt-form-field` it gets `aria-labelledby`
|
|
27
|
+
pointing at the wrapper's label (unless `ariaLabel` is set), and the hint or error is added to
|
|
28
|
+
`aria-describedby`. No `controlId` needed. The cells form a named `role="group"`; `id` goes to the
|
|
29
|
+
first cell (clicking the label starts at the beginning), and each cell is named "Character 2 of 6"
|
|
30
|
+
(`inputOtp.cell`).
|
|
31
|
+
|
|
18
32
|
## Tokens
|
|
19
33
|
The boxes use `--kpt-form-field-*`.
|
package/src/lib/knob/llms.txt
CHANGED
|
@@ -19,5 +19,13 @@ Import: `import { KptKnob } from '@konce-pt/angular';`
|
|
|
19
19
|
<kpt-knob [formField]="f.level" [step]="5" /> <!-- bounds from min()/max() in form() -->
|
|
20
20
|
<kpt-knob [(value)]="level" [min]="0" [max]="100" [step]="5" />
|
|
21
21
|
|
|
22
|
+
## Label and description
|
|
23
|
+
`id` goes to the focusable element — the host never carries it; without one it is generated. A `div`
|
|
24
|
+
with a role is not named by `label[for]`, so inside `kpt-form-field` it gets `aria-labelledby`
|
|
25
|
+
pointing at the wrapper's label (unless `ariaLabel` is set), and the hint or error is added to
|
|
26
|
+
`aria-describedby`. No `controlId` needed. New: `id`, `ariaLabel`; `aria-valuetext` includes
|
|
27
|
+
`suffix` ("40%"), and a disabled knob leaves the Tab order. Use `ariaLabel`, not `aria-label` on the
|
|
28
|
+
host — that one lands on the wrapper.
|
|
29
|
+
|
|
22
30
|
## Tokens
|
|
23
31
|
The background arc `--kpt-color-border`; the value `--kpt-color-primary`; text `--kpt-color-on-surface`.
|
package/src/lib/listbox/llms.txt
CHANGED
|
@@ -7,11 +7,26 @@ Value: `T` (single) or `T[]` (multiple). Import: `import { KptListbox } from '@k
|
|
|
7
7
|
- `value`: model<T | T[] | null> (or `formField`)
|
|
8
8
|
- `options`: KptOption<T>[] — { label, value, disabled? }
|
|
9
9
|
- `multiple`: boolean; `filter`: boolean (a search field)
|
|
10
|
-
- `
|
|
10
|
+
- `id`/`ariaLabel`: string|null; `required`: boolean
|
|
11
|
+
- `disabled`/`invalid`/`touched`: boolean; `touch`: output (blur of the list)
|
|
11
12
|
|
|
12
13
|
## Example
|
|
13
14
|
<kpt-listbox [formField]="f.role" [options]="roles" filter />
|
|
14
15
|
<kpt-listbox [(value)]="tags" [options]="tagOptions" multiple />
|
|
15
16
|
|
|
17
|
+
## Keyboard
|
|
18
|
+
The WAI-ARIA listbox pattern: the list is one Tab stop and the active option is announced through
|
|
19
|
+
`aria-activedescendant`. `↑`/`↓`, `Home`/`End` and `PageUp`/`PageDown` move the active option,
|
|
20
|
+
skipping disabled ones (no wrapping); typing letters jumps to the next match, diacritics ignored;
|
|
21
|
+
`Space`/`Enter` picks; in `multiple` mode `Ctrl`/`⌘`+`A` selects every visible option (again —
|
|
22
|
+
clears them). The filter field sits before the list (outside the `listbox`) and `↓` moves focus
|
|
23
|
+
from it into the list; the filter itself ignores diacritics ("lodz" finds "Łódź").
|
|
24
|
+
|
|
25
|
+
## Label and description
|
|
26
|
+
`id` goes to the list (`role="listbox"`), never the host. A `div` with a role is not named by
|
|
27
|
+
`label[for]`, so inside `kpt-form-field` the list gets `aria-labelledby` pointing at the wrapper's
|
|
28
|
+
label (unless `ariaLabel` is set) and the hint or error in `aria-describedby`. New: `id`,
|
|
29
|
+
`ariaLabel`, `required` (→ `aria-required`); `aria-invalid` after touch; `touch` fires on blur of the list.
|
|
30
|
+
|
|
16
31
|
## Tokens
|
|
17
32
|
The frame `--kpt-form-field-*`; selection `--kpt-color-primary`.
|
|
@@ -8,7 +8,8 @@ Import: `import { KptMegamenu } from '@konce-pt/angular';`
|
|
|
8
8
|
|
|
9
9
|
## Inputs / outputs
|
|
10
10
|
- `items`: KptMenuItem<T>[] (3 levels: top → columns → links)
|
|
11
|
-
- `
|
|
11
|
+
- `ariaLabel`: string — the bar's name for screen readers, e.g. "Main menu"
|
|
12
|
+
- `selected`: KptMenuItem<T> (the clicked link, or a top item without columns)
|
|
12
13
|
|
|
13
14
|
## Example
|
|
14
15
|
items = [{
|
|
@@ -19,5 +20,24 @@ Import: `import { KptMegamenu } from '@konce-pt/angular';`
|
|
|
19
20
|
],
|
|
20
21
|
}];
|
|
21
22
|
|
|
23
|
+
## Links (`url`)
|
|
24
|
+
An entry with `url` and no children (and not disabled) renders as a real `<a href>` with the same
|
|
25
|
+
look, so the browser handles navigation — opening in a new tab, the status-bar preview. `selected`
|
|
26
|
+
still fires before the browser follows the link.
|
|
27
|
+
|
|
22
28
|
## Tokens
|
|
23
29
|
The panel `--kpt-color-surface-raised`, `--kpt-elevation-3`.
|
|
30
|
+
|
|
31
|
+
## Keyboard
|
|
32
|
+
The same as `kpt-menubar`: the bar is a single `Tab` stop (roving `tabindex`), `ArrowLeft`/`ArrowRight`
|
|
33
|
+
and `Home`/`End` move along it, `ArrowDown` (or `Enter`/`Space`) opens the panel with focus on the
|
|
34
|
+
first link, `ArrowUp` on the last one. In the panel `ArrowDown`/`ArrowUp`/`Home`/`End` walk through
|
|
35
|
+
all links column by column, `ArrowLeft`/`ArrowRight` show the neighbouring item's panel, and
|
|
36
|
+
`Escape` or `Tab` close it and return focus to the top item.
|
|
37
|
+
|
|
38
|
+
## ARIA
|
|
39
|
+
The bar is `role="menubar"` (`aria-orientation="horizontal"`, named by `ariaLabel`); top items with
|
|
40
|
+
columns carry `aria-haspopup="menu"`, `aria-expanded` and `aria-controls`. The panel is
|
|
41
|
+
`role="menu"` named after the open item, each column is `role="group"` named by its title
|
|
42
|
+
(`aria-labelledby`), and links are `role="menuitem"`. A top item without columns acts as an action:
|
|
43
|
+
it emits `selected` instead of opening an empty panel, and has no caret.
|
package/src/lib/menu/llms.txt
CHANGED
|
@@ -21,7 +21,7 @@ Import: `import { KptMenu, KptMenuItem } from '@konce-pt/angular';`
|
|
|
21
21
|
- `header?: boolean` — a header row: a non-clickable block of text instead of a menu entry. It holds the
|
|
22
22
|
signed-in user's details (`avatar` + `label` + `description`) or a description of what the menu does. Rendered
|
|
23
23
|
as a `<div role="presentation">` — it does not take focus and is not a `menuitem`.
|
|
24
|
-
- `items?`, `url?` — used by the menubar / megamenu
|
|
24
|
+
- `items?`, `url?` — used by the menubar / megamenu; an entry with `url` (no children, not disabled) renders as `<a href>`
|
|
25
25
|
|
|
26
26
|
The `header`, `description`, `badge` and `avatar` fields are honored by `kpt-context-menu` and `kpt-split-button` too.
|
|
27
27
|
|
|
@@ -43,12 +43,22 @@ The `header`, `description`, `badge` and `avatar` fields are honored by `kpt-con
|
|
|
43
43
|
The panel `--kpt-color-surface-raised`, `--kpt-elevation-3`; a danger entry `--kpt-color-danger`;
|
|
44
44
|
descriptions and icons `--kpt-color-on-surface-muted`, `--kpt-font-size-xs`.
|
|
45
45
|
|
|
46
|
+
## Keyboard
|
|
47
|
+
- `↓` / `↑` on the trigger open the menu with focus on the first / last item; a click, `Enter`
|
|
48
|
+
or `Space` opens it on the first.
|
|
49
|
+
- Inside: `↓` / `↑` move between items and wrap around, `Home` / `End` jump to the ends;
|
|
50
|
+
disabled items, separators and headers are skipped.
|
|
51
|
+
- `Escape` and `Tab` close the menu, and so does picking an item — focus returns to the trigger.
|
|
52
|
+
- Items carry `tabindex="-1"` (roving focus), so an open menu is one Tab stop, not one per item.
|
|
53
|
+
|
|
54
|
+
The logic lives in `menu-keys.ts`, shared with `kpt-split-button`; the other port has a twin file.
|
|
55
|
+
|
|
46
56
|
## A11y
|
|
47
|
-
The panel is `role="menu"`, entries are `role="menuitem"` (native `<button>` elements
|
|
48
|
-
extra code). The header sits outside keyboard navigation. The badge value becomes part of the entry's accessible
|
|
57
|
+
The panel is `role="menu"`, entries are `role="menuitem"` (native `<button>` elements). The header sits outside keyboard navigation. The badge value becomes part of the entry's accessible
|
|
49
58
|
name ("Notifications 4").
|
|
50
59
|
|
|
51
|
-
The trigger gets `aria-haspopup="menu"
|
|
60
|
+
The trigger gets `aria-haspopup="menu"`, a live `aria-expanded` and, while open, `aria-controls`
|
|
61
|
+
pointing at the panel. They are placed on the
|
|
52
62
|
interactive control INSIDE the slot (the projected `<button>`/`<a>`), never on the
|
|
53
63
|
`.kpt-menu__trigger` wrapper — giving that wrapper a role would create a nested control and a second
|
|
54
64
|
tab stop, and state attributes on a roleless element violate `aria-allowed-attr`.
|
package/src/lib/menubar/llms.txt
CHANGED
|
@@ -7,6 +7,7 @@ Import: `import { KptMenubar } from '@konce-pt/angular';`
|
|
|
7
7
|
|
|
8
8
|
## Inputs / outputs
|
|
9
9
|
- `items`: KptMenuItem<T>[] — the top-level entries; submenus live in each entry's `items?`
|
|
10
|
+
- `ariaLabel`: string — the bar's name for screen readers, e.g. "Editor menu"
|
|
10
11
|
- `selected`: KptMenuItem<T>
|
|
11
12
|
|
|
12
13
|
## Example
|
|
@@ -17,5 +18,25 @@ Import: `import { KptMenubar } from '@konce-pt/angular';`
|
|
|
17
18
|
{ label: 'Help' },
|
|
18
19
|
];
|
|
19
20
|
|
|
21
|
+
## Links (`url`)
|
|
22
|
+
An entry with `url` and no children (and not disabled) renders as a real `<a href>` with the same
|
|
23
|
+
look, so the browser handles navigation — opening in a new tab, the status-bar preview. `selected`
|
|
24
|
+
still fires before the browser follows the link.
|
|
25
|
+
|
|
20
26
|
## Tokens
|
|
21
27
|
The bar `--kpt-color-surface-raised`; the dropdown `--kpt-elevation-3`.
|
|
28
|
+
|
|
29
|
+
## Keyboard
|
|
30
|
+
The bar follows the WAI-ARIA menubar pattern and is a single `Tab` stop (roving `tabindex`).
|
|
31
|
+
- On a top item: `ArrowLeft`/`ArrowRight` move along the bar (wrapping, skipping disabled items),
|
|
32
|
+
`Home`/`End` jump to the ends; `ArrowDown`, `Enter` or `Space` open the submenu with focus on its
|
|
33
|
+
first entry, `ArrowUp` on its last one.
|
|
34
|
+
- In a submenu: `ArrowDown`/`ArrowUp`/`Home`/`End` move between entries, `ArrowLeft`/`ArrowRight`
|
|
35
|
+
open the neighbouring submenu, `Escape` and `Tab` close it and return focus to the top item.
|
|
36
|
+
- While a submenu is open, moving along the bar opens the neighbour's submenu as well.
|
|
37
|
+
|
|
38
|
+
## ARIA
|
|
39
|
+
The bar is `role="menubar"` with `aria-orientation="horizontal"`, named by `ariaLabel`. Top items
|
|
40
|
+
with a submenu carry `aria-haspopup="menu"`, `aria-expanded` and (while open) `aria-controls`; each
|
|
41
|
+
submenu is `role="menu"` named after its top item. The bar is a plain `<div>`, not `<nav>` — wrap
|
|
42
|
+
it in your own `<nav aria-label="…">` when it is the site navigation.
|
|
@@ -7,9 +7,19 @@ Import: `import { KptMeterGroup } from '@konce-pt/angular';`
|
|
|
7
7
|
- `values`: KptMeterItem[] — { label, value, color? }
|
|
8
8
|
- `max`: number | undefined — the reference total (by default the sum of the values = 100%)
|
|
9
9
|
- `showLegend`: boolean (default true)
|
|
10
|
+
- `label`: string — the meter's name; empty = `meterGroup.label`
|
|
11
|
+
- `legendValue`: 'percent' | 'value' (default 'percent') — what the legend shows next to each label
|
|
12
|
+
- `unit`: string — appended to the values in the legend and in `aria-valuetext` (e.g. 'GB')
|
|
10
13
|
|
|
11
14
|
## Example
|
|
12
15
|
<kpt-meter-group [values]="[{label:'Used', value:70}, {label:'Free', value:30}]" />
|
|
13
16
|
|
|
14
17
|
## Tokens
|
|
15
18
|
Segments: the `--kpt-color-{primary,info,success,warning,danger}` palette or a custom `color`.
|
|
19
|
+
|
|
20
|
+
## Accessibility
|
|
21
|
+
The track is `role="meter"` named by `label` (or `meterGroup.label`), with `aria-valuemin="0"`,
|
|
22
|
+
`aria-valuenow` set to the sum and `aria-valuemax` set to the real total — `max`, or the sum without
|
|
23
|
+
it. `aria-valuetext` spells out the split (“Photos 42 GB, Videos 28 GB, …”), so the segments reach
|
|
24
|
+
the screen reader even with the legend hidden. Keep the legend visible anyway: it is the text
|
|
25
|
+
alternative to the colours.
|
|
@@ -23,6 +23,15 @@ end. Either way the selection follows the item, so the next button press moves t
|
|
|
23
23
|
## Tokens
|
|
24
24
|
Selection `--kpt-color-primary`; buttons `--kpt-color-surface-raised`.
|
|
25
25
|
|
|
26
|
+
## Keyboard
|
|
27
|
+
The list is a `listbox` with a single Tab stop (roving tabindex), and the selection follows focus:
|
|
28
|
+
- `↓` / `↑` select the next / previous item (wrapping), `Home` / `End` the first / last;
|
|
29
|
+
- `Alt`+`↑` / `Alt`+`↓` move the selected item one place up / down — focus travels with it, so
|
|
30
|
+
repeated presses keep moving the same entry.
|
|
31
|
+
The up / down buttons stay and act on the same selection.
|
|
32
|
+
|
|
26
33
|
## Accessibility
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
The list is named after `header` (`aria-label`) and the selected item carries `aria-selected`.
|
|
35
|
+
Both buttons are labelled from the dictionary and go disabled while nothing is selected. Native
|
|
36
|
+
HTML5 drag and drop has no keyboard equivalent — `Alt`+arrows and the buttons cover it, and
|
|
37
|
+
`dragdrop` adds to them, it never replaces them.
|
package/src/lib/panel/llms.txt
CHANGED
|
@@ -18,3 +18,10 @@ A panel with a header and optional collapsing. Import: `import { KptPanel } from
|
|
|
18
18
|
|
|
19
19
|
## Tokens
|
|
20
20
|
The header `--kpt-color-surface-variant`; the border `--kpt-color-border`.
|
|
21
|
+
|
|
22
|
+
## Accessibility
|
|
23
|
+
The toggle is a native button with `aria-expanded` and `aria-controls` pointing at the body. Its
|
|
24
|
+
name says which panel it collapses — `panel.toggleNamed` (“Collapse / expand Settings”) when there
|
|
25
|
+
is a `header`, `panel.toggle` otherwise — so several panels on one page are told apart. A collapsed
|
|
26
|
+
body is `inert` and `aria-hidden`. The header title is not a heading — add your own when the panel
|
|
27
|
+
should appear in the document outline.
|
|
@@ -7,7 +7,7 @@ Import: `import { KptPassword } from '@konce-pt/angular';`
|
|
|
7
7
|
- `value`: model<string> (or `formField`)
|
|
8
8
|
- `feedback`: boolean — shows the strength meter (4 bars + a label)
|
|
9
9
|
- `placeholder`: string
|
|
10
|
-
- `id`: string — the id of the native field
|
|
10
|
+
- `id`: string|null — the id of the native field (the host never carries it); generated when absent
|
|
11
11
|
- `autocomplete`: string | null = 'current-password' — in sign-up and reset flows set it to
|
|
12
12
|
`new-password`, otherwise the password manager fills in the old password instead of proposing a new one
|
|
13
13
|
- `disabled`/`invalid`/`touched`: boolean; `touch`: output
|
|
@@ -19,5 +19,13 @@ A 0–4 score: length ≥8, lower+upper case, a digit, a special character. Colo
|
|
|
19
19
|
<kpt-password [formField]="f.password" feedback />
|
|
20
20
|
<kpt-password [(value)]="pass" />
|
|
21
21
|
|
|
22
|
+
## Label and description
|
|
23
|
+
`id` goes to the native field — the host never carries it; without one it is generated. Inside
|
|
24
|
+
`kpt-form-field` the control links itself: the wrapper's `label[for]` points at it and the hint or
|
|
25
|
+
error is added to `aria-describedby`, so `controlId` is not needed. Without a wrapper, name it with
|
|
26
|
+
`ariaLabel`. The host no longer carries the `id` (it used to, so `label[for]` pointed at
|
|
27
|
+
`kpt-password` and the same id existed twice). New: `ariaLabel`, `required`, `readonly`/`readOnly`,
|
|
28
|
+
`aria-invalid` after touch; with `feedback` the strength label is added to `aria-describedby`.
|
|
29
|
+
|
|
22
30
|
## Tokens
|
|
23
31
|
The field `--kpt-form-field-*`; the meter bars `--kpt-color-{danger,warning,info,success}`.
|
|
@@ -28,6 +28,16 @@ leaves a panel also leaves that panel's selection.
|
|
|
28
28
|
## Tokens
|
|
29
29
|
Selection `--kpt-color-primary`; headers `--kpt-color-surface-variant`.
|
|
30
30
|
|
|
31
|
+
## Keyboard
|
|
32
|
+
Each list is a `listbox` with `aria-multiselectable` and a single Tab stop (roving tabindex):
|
|
33
|
+
- `↓` / `↑` move between items (wrapping), `Home` / `End` jump to the ends;
|
|
34
|
+
- `Space` toggles the focused item's selection (`aria-selected`), the same as a click;
|
|
35
|
+
- `Enter` moves the focused item to the other list, the same as a double-click — focus stays at
|
|
36
|
+
that position in the list, on the next item.
|
|
37
|
+
The move buttons act on the same selection, so the whole control works without a mouse.
|
|
38
|
+
|
|
31
39
|
## Accessibility
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
Each list is named after its header (`aria-label`). The four move buttons are labelled from the
|
|
41
|
+
dictionary, so "move all right" is distinguishable from "move right" without seeing the double
|
|
42
|
+
chevron. Native HTML5 drag and drop has no keyboard equivalent — `Enter` and the buttons cover
|
|
43
|
+
everything it does, and `dragdrop` adds to them, it never replaces them.
|
package/src/lib/popover/llms.txt
CHANGED
|
@@ -4,6 +4,10 @@ A popover — arbitrary content in a bubble on CDK Overlay (richer than a toolti
|
|
|
4
4
|
Requires `import '@angular/cdk/overlay-prebuilt.css';`
|
|
5
5
|
Import: `import { KptPopover } from '@konce-pt/angular';`
|
|
6
6
|
|
|
7
|
+
## Inputs / model
|
|
8
|
+
- `placement`: 'bottom' | 'top' (default 'bottom') — the preferred side; CDK flips it when there is no room
|
|
9
|
+
- `open`: model<boolean> (default false) — two-way, so the application can close the bubble from code
|
|
10
|
+
|
|
7
11
|
## Slots
|
|
8
12
|
- the element carrying the `kptPopoverTrigger` attribute = the trigger; everything else = the panel
|
|
9
13
|
|
|
@@ -13,5 +17,12 @@ Import: `import { KptPopover } from '@konce-pt/angular';`
|
|
|
13
17
|
<div>Rich popover content…</div>
|
|
14
18
|
</kpt-popover>
|
|
15
19
|
|
|
20
|
+
## Focus and keyboard
|
|
21
|
+
The control inside the trigger slot gets `aria-haspopup="dialog"`, a live `aria-expanded` and, while
|
|
22
|
+
open, `aria-controls` — on the real `<button>`, not on the wrapper. Opening moves focus to the first
|
|
23
|
+
interactive element of the bubble; `Escape` or a click outside closes it, and focus returns to the
|
|
24
|
+
trigger when it was inside the bubble. Focus is not trapped — the popover is supporting content, not
|
|
25
|
+
a modal.
|
|
26
|
+
|
|
16
27
|
## Tokens
|
|
17
28
|
`--kpt-color-surface-raised`, `--kpt-elevation-3`.
|
|
@@ -11,5 +11,16 @@ Import: `import { KptRadioGroup, KptOption } from '@konce-pt/angular';`
|
|
|
11
11
|
- `value`: model<T>; `options`: KptOption<T>[] `{ label, value, disabled? }`
|
|
12
12
|
- `disabled`/`invalid`/`touched`: boolean; `name`: string (automatic); the `touch` output.
|
|
13
13
|
|
|
14
|
+
## Screen reader and keyboard
|
|
15
|
+
`orientation`: 'vertical' (default) | 'horizontal' — options in a column or in a wrapping row; also
|
|
16
|
+
sets `aria-orientation`.
|
|
17
|
+
|
|
18
|
+
## Label and description
|
|
19
|
+
`id` goes to the focusable element — the host never carries it; without one it is generated. A `div`
|
|
20
|
+
with a role is not named by `label[for]`, so inside `kpt-form-field` it gets `aria-labelledby`
|
|
21
|
+
pointing at the wrapper's label (unless `ariaLabel` is set), and the hint or error is added to
|
|
22
|
+
`aria-describedby`. No `controlId` needed. New: `id`, `ariaLabel` and `required` (→ `aria-required`)
|
|
23
|
+
on the `radiogroup`.
|
|
24
|
+
|
|
14
25
|
## Tokens
|
|
15
26
|
`--kpt-color-primary`, `--kpt-form-field-border`.
|
package/src/lib/rating/llms.txt
CHANGED
|
@@ -4,15 +4,29 @@ A star rating on Signal Forms. Import: `import { KptRating } from '@konce-pt/ang
|
|
|
4
4
|
|
|
5
5
|
## Inputs
|
|
6
6
|
- `value`: model<number>; `count`: number (number of stars, default 5)
|
|
7
|
-
- `
|
|
7
|
+
- `allowHalf`: boolean — half stars, the value goes in steps of 0.5
|
|
8
|
+
- `readonly`/`disabled`/`required`/`invalid`/`touched`: boolean; `touch`: output
|
|
9
|
+
- `id`/`ariaLabel`: string|null — `id` goes to the group, never the host
|
|
8
10
|
|
|
9
11
|
## Example
|
|
10
12
|
<kpt-rating [formField]="f.score" [count]="5" />
|
|
11
|
-
<kpt-rating [value]="
|
|
13
|
+
<kpt-rating [(value)]="score" allowHalf ariaLabel="Rating" />
|
|
14
|
+
<kpt-rating [value]="4.3" readonly />
|
|
12
15
|
|
|
13
16
|
## Accessibility
|
|
14
|
-
`role="
|
|
15
|
-
`rating.star` (`{value}`, `{max}`) — EN `1 of 5`,
|
|
17
|
+
`role="radiogroup"` named by `ariaLabel` or the `kpt-form-field` label; each star is
|
|
18
|
+
`role="radio"` with `aria-checked`, labelled from `rating.star` (`{value}`, `{max}`) — EN `1 of 5`,
|
|
19
|
+
PL `1 z 5`. One Tab stop: `→`/`↑` raise the score by one, `←`/`↓` lower it (mirrored in RTL),
|
|
20
|
+
`Home`/`End` set the extremes, `Delete`/`Backspace` clear it; clicking the chosen star also clears it.
|
|
21
|
+
`readonly` renders `role="img"` named "4 of 5" with no buttons, so a screen reader does not announce
|
|
22
|
+
a row of disabled controls. `touch` fires when focus leaves the group.
|
|
23
|
+
|
|
24
|
+
## Half stars
|
|
25
|
+
`allowHalf` splits every star into two halves, each its own `role="radio"` ("3.5 of 5" — the number
|
|
26
|
+
follows the page language, PL "3,5 z 5"), so the group keeps the radio pattern: clicking the left half
|
|
27
|
+
gives x.5, and the arrows step by 0.5. Read-only stars show the value rounded to a half (4.3 → four
|
|
28
|
+
and a half stars) while the name carries the exact score ("4.3 of 5"), so an average can be shown
|
|
29
|
+
as it is.
|
|
16
30
|
|
|
17
31
|
## Tokens
|
|
18
32
|
Filled stars `--kpt-color-warning`; empty ones `--kpt-color-border-strong`.
|
|
@@ -51,6 +51,9 @@ they are inert, so they open no new door.
|
|
|
51
51
|
- `link` (a URL prompt), `clear` (remove formatting), `html` (a toggle for the HTML source view — editing raw HTML)
|
|
52
52
|
|
|
53
53
|
## Keyboard
|
|
54
|
+
- The toolbar is a named `role="toolbar"` ("Formatting", `richText.toolbar`) with one Tab stop:
|
|
55
|
+
`←`/`→` (mirrored in RTL) and `Home`/`End` move between tools, skipping disabled ones; the stop
|
|
56
|
+
remembers the last tool, so Tab from the toolbar goes straight to the editor.
|
|
54
57
|
- Tab / Shift+Tab inside a list item = indent / one level up (the same as `indent`/`outdent`).
|
|
55
58
|
- Tab / Shift+Tab inside a table cell = the next / previous cell (with its content selected).
|
|
56
59
|
A list inside a cell takes precedence — only once it can no longer be indented does Tab move to another cell.
|
|
@@ -77,3 +80,18 @@ potentially untrusted (a database, another user, a CMS); on the way out of the c
|
|
|
77
80
|
The "paste"/"paste without formatting" clipboard tools use the async Clipboard API (which needs browser permission).
|
|
78
81
|
An exception to execCommand: list indentation is done with our own DOM code — `execCommand('indent')` produces
|
|
79
82
|
invalid `ul > ul` in Chrome (or a `blockquote` with a margin, which the sanitizer would strip anyway).
|
|
83
|
+
|
|
84
|
+
## Screen reader and keyboard
|
|
85
|
+
`link` opens a small dialog instead of the browser's `prompt()`: a labelled URL field (prefilled
|
|
86
|
+
with the current link), `Enter` inserts, `Escape` returns to the text with the selection restored.
|
|
87
|
+
The table context menu is a `role="menu"` of `menuitem`s: it also opens from the keyboard (the menu
|
|
88
|
+
key or `Shift+F10` in a cell), the arrows and `Home`/`End` move, `Escape`/`Tab` close it, and focus
|
|
89
|
+
goes back to the cell. Colour swatches are named ("Dark grey", `richText.swatches.*`) instead of
|
|
90
|
+
their hex codes. The table size grid is still mouse-only.
|
|
91
|
+
|
|
92
|
+
## Label and description
|
|
93
|
+
`id` goes to the focusable element — the host never carries it; without one it is generated. A `div`
|
|
94
|
+
with a role is not named by `label[for]`, so inside `kpt-form-field` it gets `aria-labelledby`
|
|
95
|
+
pointing at the wrapper's label (unless `ariaLabel` is set), and the hint or error is added to
|
|
96
|
+
`aria-describedby`. No `controlId` needed. New: `id`, `ariaLabel` and `required` (→ `aria-required`)
|
|
97
|
+
on the `role="textbox"` area.
|
|
@@ -11,5 +11,17 @@ Import: `import { KptScrollTop } from '@konce-pt/angular';`
|
|
|
11
11
|
<kpt-scroll-top [threshold]="300" />
|
|
12
12
|
<kpt-scroll-top target="#panel" />
|
|
13
13
|
|
|
14
|
+
## The scrolled element
|
|
15
|
+
Without `target` the button watches the window. `target` is a selector, resolved after render, so
|
|
16
|
+
the element must already be in the page; changing it re-attaches the listener, and the listener is
|
|
17
|
+
removed when the component is destroyed.
|
|
18
|
+
|
|
14
19
|
## Tokens
|
|
15
20
|
The button uses `--kpt-color-primary` / `--kpt-color-on-primary`, `--kpt-elevation-3`.
|
|
21
|
+
|
|
22
|
+
## Accessibility
|
|
23
|
+
A real `<button>` labelled from `scrollTop.label`; while hidden it is `visibility: hidden`, so it is
|
|
24
|
+
out of the tab order and the accessibility tree. It sits in the bottom-end corner
|
|
25
|
+
(`inset-inline-end`), so it moves to the left in RTL. With `prefers-reduced-motion` the scroll is a
|
|
26
|
+
jump instead of smooth and the button appears without a transition. Focus stays on the button after
|
|
27
|
+
the jump — move it to your page heading if that matters.
|