@pienter/ui 0.18.0 → 0.19.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 +19 -0
- package/CONVENTIONS.md +5 -2
- package/components/feedback/toast/Toast.vue +4 -1
- package/components/feedback/toast/ToastHost.vue +5 -0
- package/components/form/number-field/NumberField.vue +8 -2
- package/components/layout/table/DataTable.vue +10 -0
- package/components/layout/table/Table.vue +4 -1
- package/components/navigation/breadcrumb/Breadcrumb.vue +9 -4
- package/components/navigation/pagination/Pagination.vue +12 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.19.0 - 2026-09-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- The English accessibility text the icon-only controls and landmarks used
|
|
10
|
+
to hardcode is now a prop with that text as its default, following
|
|
11
|
+
`AppLayout`'s `skipLabel` / `drawerLabel` / `navigationLabel`, so a
|
|
12
|
+
single-language consumer can name them in its own language. `Pagination`
|
|
13
|
+
takes `label` (the `<nav>` landmark, `Pagination`), `previousLabel`
|
|
14
|
+
(`Previous page`) and `nextLabel` (`Next page`); `Breadcrumb` takes
|
|
15
|
+
`label` (`Breadcrumb`); `NumberField` takes `increaseLabel` (`Increase`)
|
|
16
|
+
and `decreaseLabel` (`Decrease`); `Table` takes `selectAllLabel`
|
|
17
|
+
(`Select all rows`), which `DataTable` forwards alongside its own
|
|
18
|
+
`selectRowLabel`, a string or a function of the row that replaces the
|
|
19
|
+
default `Select <first cell>` name; `Toast` takes `closeLabel` (`Close`),
|
|
20
|
+
and `ToastHost` takes the same `closeLabel` for every toast it renders
|
|
21
|
+
next to its existing `label` for the notifications region.
|
|
22
|
+
`PaginationFooter` has no text of its own and is unchanged.
|
|
23
|
+
|
|
5
24
|
## 0.18.0 - 2026-09-16
|
|
6
25
|
|
|
7
26
|
### Changed
|
package/CONVENTIONS.md
CHANGED
|
@@ -1498,8 +1498,11 @@ counts the selected values, with a Clear, joining values on the comma
|
|
|
1498
1498
|
convention) and `FilterRange` (`name`, `label`, `min`, `max`, `step`; two
|
|
1499
1499
|
NumberFields writing `<name>_min` and `<name>_max` on change). Each binds
|
|
1500
1500
|
through `useIndexFilters` to the provided state, or to a `state` prop, and
|
|
1501
|
-
touches only its own names; without a state it warns and does nothing.
|
|
1502
|
-
|
|
1501
|
+
touches only its own names; without a state it warns and does nothing. On a
|
|
1502
|
+
module index they live in the `PageAside`: the definition renders them
|
|
1503
|
+
inside `<PageAside title="Filters">` beside `<Index :state>`, both under the
|
|
1504
|
+
component that created and provided the state, and the aside's content grid
|
|
1505
|
+
stacks them. The `filters` slot stays for a toolbar placement; elsewhere a
|
|
1503
1506
|
column of them is a consumer grid with a spacing token for its gap. Options
|
|
1504
1507
|
and counts are the consumer's (`CONTEXT.md`: Facet).
|
|
1505
1508
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
v-if="dismissible"
|
|
20
20
|
class="pui-toast__close"
|
|
21
21
|
type="button"
|
|
22
|
-
aria-label="
|
|
22
|
+
:aria-label="closeLabel"
|
|
23
23
|
@click="$emit('dismiss')"
|
|
24
24
|
>
|
|
25
25
|
<Icon name="x" size="sm" />
|
|
@@ -48,6 +48,8 @@ const props = withDefaults(
|
|
|
48
48
|
dismissible?: boolean;
|
|
49
49
|
icon?: IconName;
|
|
50
50
|
action?: { label: string };
|
|
51
|
+
/** Accessible name of the icon-only close button. */
|
|
52
|
+
closeLabel?: string;
|
|
51
53
|
}>(),
|
|
52
54
|
{
|
|
53
55
|
tone: undefined,
|
|
@@ -55,6 +57,7 @@ const props = withDefaults(
|
|
|
55
57
|
dismissible: true,
|
|
56
58
|
icon: undefined,
|
|
57
59
|
action: undefined,
|
|
60
|
+
closeLabel: 'Close',
|
|
58
61
|
},
|
|
59
62
|
);
|
|
60
63
|
|
|
@@ -17,11 +17,15 @@ interface Timer {
|
|
|
17
17
|
const props = withDefaults(
|
|
18
18
|
defineProps<{
|
|
19
19
|
controller?: ToastController;
|
|
20
|
+
/** Accessible name of the notifications region. */
|
|
20
21
|
label?: string;
|
|
22
|
+
/** Accessible name of every toast's close button. */
|
|
23
|
+
closeLabel?: string;
|
|
21
24
|
}>(),
|
|
22
25
|
{
|
|
23
26
|
controller: () => defaultController,
|
|
24
27
|
label: 'Notifications',
|
|
28
|
+
closeLabel: 'Close',
|
|
25
29
|
},
|
|
26
30
|
);
|
|
27
31
|
const items = computed(() => props.controller.visible.value);
|
|
@@ -151,6 +155,7 @@ onBeforeUnmount(() => {
|
|
|
151
155
|
:dismissible="item.dismissible"
|
|
152
156
|
:icon="item.icon"
|
|
153
157
|
:action="item.action"
|
|
158
|
+
:close-label="closeLabel"
|
|
154
159
|
aria-keyshortcuts="Escape"
|
|
155
160
|
@dismiss="dismiss(item.id)"
|
|
156
161
|
@action="runAction(item)"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
type="button"
|
|
44
44
|
class="pui-number-field__step"
|
|
45
45
|
data-direction="increment"
|
|
46
|
-
aria-label="
|
|
46
|
+
:aria-label="increaseLabel"
|
|
47
47
|
:disabled="disabled"
|
|
48
48
|
@click="handleStep('increment')"
|
|
49
49
|
>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
type="button"
|
|
54
54
|
class="pui-number-field__step"
|
|
55
55
|
data-direction="decrement"
|
|
56
|
-
aria-label="
|
|
56
|
+
:aria-label="decreaseLabel"
|
|
57
57
|
:disabled="disabled"
|
|
58
58
|
@click="handleStep('decrement')"
|
|
59
59
|
>
|
|
@@ -100,6 +100,10 @@ const props = withDefaults(
|
|
|
100
100
|
readonly?: boolean;
|
|
101
101
|
/** The +/− buttons beside the input; off, the field is a plain number input. */
|
|
102
102
|
steppers?: boolean;
|
|
103
|
+
/** Accessible name of the + stepper. */
|
|
104
|
+
increaseLabel?: string;
|
|
105
|
+
/** Accessible name of the − stepper. */
|
|
106
|
+
decreaseLabel?: string;
|
|
103
107
|
hint?: string;
|
|
104
108
|
errors?: string[];
|
|
105
109
|
status?: 'error' | 'success';
|
|
@@ -118,6 +122,8 @@ const props = withDefaults(
|
|
|
118
122
|
disabled: false,
|
|
119
123
|
readonly: false,
|
|
120
124
|
steppers: true,
|
|
125
|
+
increaseLabel: 'Increase',
|
|
126
|
+
decreaseLabel: 'Decrease',
|
|
121
127
|
hint: undefined,
|
|
122
128
|
errors: () => [],
|
|
123
129
|
status: undefined,
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
:selectable="selectable"
|
|
11
11
|
:clickable="clickable"
|
|
12
12
|
:all-selected="allSelected"
|
|
13
|
+
:select-all-label="selectAllLabel"
|
|
13
14
|
:label="label"
|
|
14
15
|
:labelledby="labelledby"
|
|
15
16
|
@toggle-all="toggleAll"
|
|
@@ -76,6 +77,10 @@ const props = withDefaults(
|
|
|
76
77
|
selectable?: boolean;
|
|
77
78
|
/** Show a pointer cursor on rows. */
|
|
78
79
|
clickable?: boolean;
|
|
80
|
+
/** Accessible name of the header select-all checkbox. */
|
|
81
|
+
selectAllLabel?: string;
|
|
82
|
+
/** Accessible name of a row's checkbox; a function receives the row. Default: `Select <first cell>`, or `Select row` when that cell is empty. */
|
|
83
|
+
selectRowLabel?: string | ((row: T) => string);
|
|
79
84
|
/** Which column is sorted, and how. `rows` is passed through untouched — ordering them is the consumer's job (ADR 0005). */
|
|
80
85
|
sort?: SortState;
|
|
81
86
|
/** Frosts and disables the body while the rows are stale, and suppresses the empty state. */
|
|
@@ -90,6 +95,8 @@ const props = withDefaults(
|
|
|
90
95
|
selected: () => [],
|
|
91
96
|
selectable: false,
|
|
92
97
|
clickable: false,
|
|
98
|
+
selectAllLabel: 'Select all rows',
|
|
99
|
+
selectRowLabel: undefined,
|
|
93
100
|
sort: null,
|
|
94
101
|
loading: false,
|
|
95
102
|
label: undefined,
|
|
@@ -112,6 +119,9 @@ function keyOf(row: T): string | number {
|
|
|
112
119
|
return cellValue(row, props.rowKey) as string | number;
|
|
113
120
|
}
|
|
114
121
|
function rowLabel(row: T): string {
|
|
122
|
+
if (typeof props.selectRowLabel === 'function')
|
|
123
|
+
return props.selectRowLabel(row);
|
|
124
|
+
if (props.selectRowLabel !== undefined) return props.selectRowLabel;
|
|
115
125
|
const first = props.columns[0];
|
|
116
126
|
const value = first ? String(cellValue(row, first.key) ?? '').trim() : '';
|
|
117
127
|
return value ? `Select ${value}` : 'Select row';
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
class="pui-table__check"
|
|
28
28
|
type="checkbox"
|
|
29
29
|
:checked="allSelected"
|
|
30
|
-
aria-label="
|
|
30
|
+
:aria-label="selectAllLabel"
|
|
31
31
|
@change="emit('toggle-all')"
|
|
32
32
|
/>
|
|
33
33
|
</th>
|
|
@@ -106,6 +106,8 @@ const props = withDefaults(
|
|
|
106
106
|
clickable?: boolean;
|
|
107
107
|
/** Checked state of the header select-all checkbox. */
|
|
108
108
|
allSelected?: boolean;
|
|
109
|
+
/** Accessible name of the header select-all checkbox. */
|
|
110
|
+
selectAllLabel?: string;
|
|
109
111
|
/** Which column is sorted, and how. Rendered, never changed here; `null` is unsorted (ADR 0005). */
|
|
110
112
|
sort?: SortState;
|
|
111
113
|
/** Frosts and disables the body while the rows are stale, leaving the header usable. */
|
|
@@ -119,6 +121,7 @@ const props = withDefaults(
|
|
|
119
121
|
selectable: false,
|
|
120
122
|
clickable: false,
|
|
121
123
|
allSelected: false,
|
|
124
|
+
selectAllLabel: 'Select all rows',
|
|
122
125
|
sort: null,
|
|
123
126
|
loading: false,
|
|
124
127
|
label: undefined,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<nav aria-label="
|
|
2
|
+
<nav :aria-label="label" class="pui-breadcrumb">
|
|
3
3
|
<ol class="pui-breadcrumb__trail">
|
|
4
4
|
<template v-for="(item, index) in items" :key="index">
|
|
5
5
|
<li
|
|
@@ -36,9 +36,14 @@
|
|
|
36
36
|
</template>
|
|
37
37
|
|
|
38
38
|
<script setup lang="ts">
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
39
|
+
withDefaults(
|
|
40
|
+
defineProps<{
|
|
41
|
+
items: { label: string; href?: string }[];
|
|
42
|
+
/** Accessible name of the `<nav>` landmark. */
|
|
43
|
+
label?: string;
|
|
44
|
+
}>(),
|
|
45
|
+
{ label: 'Breadcrumb' },
|
|
46
|
+
);
|
|
42
47
|
|
|
43
48
|
defineSlots<{
|
|
44
49
|
link?: (scope: {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<nav class="pui-pagination-nav" aria-label="
|
|
2
|
+
<nav class="pui-pagination-nav" :aria-label="label">
|
|
3
3
|
<ul class="pui-pagination">
|
|
4
4
|
<li>
|
|
5
5
|
<button
|
|
6
6
|
class="pui-pagination__item"
|
|
7
7
|
:disabled="currentPage <= 1"
|
|
8
|
-
aria-label="
|
|
8
|
+
:aria-label="previousLabel"
|
|
9
9
|
@click="emit('update:currentPage', currentPage - 1)"
|
|
10
10
|
>
|
|
11
11
|
<Icon name="chevron-left" size="sm" />
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<button
|
|
34
34
|
class="pui-pagination__item"
|
|
35
35
|
:disabled="currentPage >= totalPages"
|
|
36
|
-
aria-label="
|
|
36
|
+
:aria-label="nextLabel"
|
|
37
37
|
@click="emit('update:currentPage', currentPage + 1)"
|
|
38
38
|
>
|
|
39
39
|
<Icon name="chevron-right" size="sm" />
|
|
@@ -52,9 +52,18 @@ const props = withDefaults(
|
|
|
52
52
|
currentPage: number;
|
|
53
53
|
totalPages: number;
|
|
54
54
|
maxVisible?: number;
|
|
55
|
+
/** Accessible name of the `<nav>` landmark. */
|
|
56
|
+
label?: string;
|
|
57
|
+
/** Accessible name of the icon-only previous button. */
|
|
58
|
+
previousLabel?: string;
|
|
59
|
+
/** Accessible name of the icon-only next button. */
|
|
60
|
+
nextLabel?: string;
|
|
55
61
|
}>(),
|
|
56
62
|
{
|
|
57
63
|
maxVisible: 5,
|
|
64
|
+
label: 'Pagination',
|
|
65
|
+
previousLabel: 'Previous page',
|
|
66
|
+
nextLabel: 'Next page',
|
|
58
67
|
},
|
|
59
68
|
);
|
|
60
69
|
|