@nxgt/material-vue 0.40.1 → 0.42.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 +60 -0
- package/README.md +3 -2
- package/dist/{Button-teS2p_af.js → Button-CWmzvv9p.js} +132 -94
- package/dist/{HoverCardTrigger-BEzEsgBo.js → HoverCardTrigger-C5AbAyHE.js} +2 -2
- package/dist/{camera-1QRTmpnM.js → camera-C-9slBUV.js} +4 -4
- package/dist/components/base-content.css +14 -4
- package/dist/{components-XJ95qxB1.js → components-DX4EycMi.js} +10131 -9800
- package/dist/components.js +8 -8
- package/dist/composables.js +2 -2
- package/dist/dnd.js +1 -1
- package/dist/{form-scope-BtEP6yC2.js → form-scope-CN68PTXc.js} +1 -1
- package/dist/{i18n-provider-BpNC9SxV.js → i18n-provider-DmZSTBnp.js} +1 -1
- package/dist/i18n.js +4 -4
- package/dist/{icon-button-Vz4NECf1.js → icon-button-DErh1aJS.js} +43 -5
- package/dist/lib/components/ui/actions/button/Button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/button/button.compound-variants.d.ts +28 -0
- package/dist/lib/components/ui/actions/button/button.variants.d.ts +8 -2
- package/dist/lib/components/ui/actions/copy-button/copy-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/copy-button/use-copy-status.d.ts +3 -1
- package/dist/lib/components/ui/actions/icon-button/icon-button.compound-variants.d.ts +28 -0
- package/dist/lib/components/ui/actions/icon-button/icon-button.variants.d.ts +8 -2
- package/dist/lib/components/ui/actions/icon-button/icon-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/link/icon-link-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/link/link-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/link/responsive-link-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/load-more-button/load-more-button.vue.d.ts +1 -1
- package/dist/lib/components/ui/actions/scroll-to-top/scroll-to-top.vue.d.ts +1 -1
- package/dist/lib/components/ui/display/cards/cards.gallery.d.ts +3 -3
- package/dist/lib/components/ui/display/chip/chip.utils.d.ts +1 -1
- package/dist/lib/components/ui/display/enrolment-secret/enrolment-secret.vue.d.ts +17 -1
- package/dist/lib/components/ui/display/qrcode/qrcode.vue.d.ts +6 -0
- package/dist/lib/components/ui/display/recovery-codes/index.d.ts +1 -1
- package/dist/lib/components/ui/display/recovery-codes/partials/recovery-codes-actions.vue.d.ts +20 -2
- package/dist/lib/components/ui/display/recovery-codes/recovery-codes.vue.d.ts +9 -1
- package/dist/lib/components/ui/display/recovery-codes/types.d.ts +4 -0
- package/dist/lib/components/ui/display/recovery-codes/use-recovery-codes-labels.d.ts +1 -0
- package/dist/lib/components/ui/fields/contacts/consts.d.ts +1 -1
- package/dist/lib/components/ui/fields/otp-field/otp-field.vue.d.ts +2 -0
- package/dist/lib/components/ui/layout/account-menu/account-menu-avatar.vue.d.ts +9 -0
- package/dist/lib/components/ui/layout/account-menu/account-menu.vue.d.ts +38 -0
- package/dist/lib/components/ui/layout/account-menu/index.d.ts +3 -0
- package/dist/lib/components/ui/layout/account-menu/types.d.ts +10 -0
- package/dist/lib/components/ui/layout/app-shell/activity-layout.vue.d.ts +21 -5
- package/dist/lib/components/ui/layout/app-shell/app-brand-logo.vue.d.ts +20 -0
- package/dist/lib/components/ui/layout/app-shell/app-brand.vue.d.ts +30 -0
- package/dist/lib/components/ui/layout/app-shell/app-header.vue.d.ts +13 -5
- package/dist/lib/components/ui/layout/app-shell/app-sidebar.vue.d.ts +12 -2
- package/dist/lib/components/ui/layout/app-shell/index.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-shell/types.d.ts +10 -0
- package/dist/lib/components/ui/layout/index.d.ts +1 -0
- package/dist/lib/components/ui/layout/stepper/stepper.vue.d.ts +7 -2
- package/dist/lib/components/ui/media/carousel/carousel-next.vue.d.ts +1 -1
- package/dist/lib/components/ui/media/carousel/carousel-previous.vue.d.ts +1 -1
- package/dist/lib/components/ui/primitives/input-group/input-group-button.vue.d.ts +1 -1
- package/dist/lib/i18n/resources/en/en.d.ts +5 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +5 -0
- package/dist/lib/i18n/resources/fr/fr.d.ts +5 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +7 -2
- package/dist/lib/i18n/resources/resources.d.ts +10 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/nuxt/component-names.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/dist/main.js +17 -17
- package/dist/map.js +4 -4
- package/dist/material-vue.css +1 -1
- package/dist/{pdf-outline-sidebar-DINCjWKk.js → pdf-outline-sidebar-BU4o_hBI.js} +2 -2
- package/dist/{pdf-page-BLJ0xkS3.js → pdf-page-anNe78Lc.js} +1 -1
- package/dist/{pdf-page-list-BNUPVA9x.js → pdf-page-list-CSY76HH6.js} +2 -2
- package/dist/{pdf-reader-BcB_Kd_F.js → pdf-reader-BhZNrW7R.js} +8 -8
- package/dist/{pdf-sidebar-B7WgcY77.js → pdf-sidebar-DcIpG7eh.js} +3 -3
- package/dist/{pdf-thumbnail-sidebar-BRtyyBPt.js → pdf-thumbnail-sidebar-CUC0V4if.js} +3 -3
- package/dist/{pdf-toolbar-_CBHSMnH.js → pdf-toolbar-C373S-ul.js} +4 -4
- package/dist/pdf.js +2 -2
- package/dist/{print-format.utils-k5W0GBRF.js → print-format.utils-C81c0weJ.js} +2 -2
- package/dist/{sortable-provider-Dw9TBAlq.js → sortable-provider-CL2UGGn8.js} +2 -2
- package/dist/{stored-language-DEyPmUzl.js → stored-language-Wtcj2HsU.js} +12 -2
- package/dist/{stx-player-CgwzX7_k.js → stx-player-CMmM3F5Z.js} +12 -12
- package/dist/{translator-B62GlCBp.js → translator-D5Dp-dob.js} +1 -1
- package/dist/{use-heading-spy-T94lNeNA.js → use-heading-spy-BIBHtUXN.js} +1 -1
- package/dist/{use-material-translation-DxU51--g.js → use-material-translation-COoBTGpB.js} +3 -3
- package/docs/components/README.md +2 -1
- package/docs/components/buttons-and-actions.md +2 -2
- package/docs/components/data-display.md +14 -7
- package/docs/components/data-table-filter-and-lists.md +3 -1
- package/docs/components/feedback-and-status.md +7 -2
- package/docs/components/form-fields.md +2 -1
- package/docs/components/navigation-and-layout.md +62 -2
- package/docs/guides/app-shell.md +99 -19
- package/docs/guides/forms.md +10 -4
- package/docs/guides/i18n.md +1 -1
- package/docs/previews/navigation-layout-accountmenu.webp +0 -0
- package/docs/roadmap.md +9 -0
- package/docs/troubleshooting.md +31 -0
- package/lib/components/base-content.css +14 -4
- package/lib/nuxt/component-names.ts +1 -0
- package/package.json +2 -2
package/docs/guides/app-shell.md
CHANGED
|
@@ -17,10 +17,7 @@ const items: MenuItem[] = [
|
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
19
|
<template>
|
|
20
|
-
<ActivityLayout :items="items" avatar-src="/me.png">
|
|
21
|
-
<template #brand>
|
|
22
|
-
<strong>Acme</strong>
|
|
23
|
-
</template>
|
|
20
|
+
<ActivityLayout :items="items" logo="/logo.svg" name="Acme" avatar-src="/me.png">
|
|
24
21
|
<RouterView />
|
|
25
22
|
</ActivityLayout>
|
|
26
23
|
</template>
|
|
@@ -179,7 +176,11 @@ partitionMenu(items); // { content, footer }
|
|
|
179
176
|
| `content-as` | `'main' \| 'div'` | `'main'` | The content region's element: the page's `<main>` landmark, or a `div` when your app renders its own `<main>` |
|
|
180
177
|
| `scroll` | `'document' \| 'container'` | `'document'` | Who scrolls: the page (header and sidebar sticky), or the content region inside a shell one screen high |
|
|
181
178
|
| `class` | `string` | — | Classes for the outer element (`[data-slot=activity-layout]`), which takes the other attributes too |
|
|
182
|
-
|
|
|
179
|
+
| `logo` | `string \| { src, alt? }` | an atom badge | The app's logo, an image URL: alone in the collapsed rail, beside `name` in the phone's menu sheet (see [The brand](#the-brand-logo-and-name)) |
|
|
180
|
+
| `#logo` | slot | — | The logo as a node (an inline SVG), in place of `logo`; it wins when both are given |
|
|
181
|
+
| `name` | `string` | — | The app's name, already translated: the logo's accessible name and tooltip in the rail, shown beside it in the sheet |
|
|
182
|
+
| `#brand` | slot | — | Replaces the sidebar header entirely, in the rail and in the menu sheet; wins over `logo` and `name` |
|
|
183
|
+
| `#header-title` | slot | — | The header's leading title: the context the app is in (the active organisation's name), right after the phone's menu button, truncated when long |
|
|
183
184
|
| `#header-actions` | slot | — | In the header, before the avatar: notifications, help, `LanguageSwitcher`, `ThemeToggle` |
|
|
184
185
|
| `#avatar` | slot | the `avatar-src` image | Replaces the avatar entirely |
|
|
185
186
|
| default | slot | — | The routed content, usually `<RouterView />` |
|
|
@@ -214,32 +215,26 @@ the slots.
|
|
|
214
215
|
```vue
|
|
215
216
|
<script setup lang="ts">
|
|
216
217
|
import {
|
|
218
|
+
AccountMenu,
|
|
217
219
|
ActivityLayout,
|
|
218
|
-
Avatar,
|
|
219
|
-
AvatarFallback,
|
|
220
|
-
AvatarImage,
|
|
221
220
|
LanguageSwitcher,
|
|
222
221
|
type MenuItem,
|
|
223
222
|
ThemeToggle,
|
|
224
223
|
} from '@nxgt/material-vue/components';
|
|
225
224
|
|
|
226
|
-
defineProps<{ items: MenuItem[]; user: { name: string; picture?: string } }>();
|
|
225
|
+
defineProps<{ items: MenuItem[]; user: { name: string; email: string; picture?: string } }>();
|
|
226
|
+
const emit = defineEmits<{ 'sign-out': [] }>();
|
|
227
227
|
</script>
|
|
228
228
|
|
|
229
229
|
<template>
|
|
230
|
-
<ActivityLayout :items="items">
|
|
231
|
-
<template #
|
|
232
|
-
<img src="/logo.svg" alt="Acme" class="h-8" />
|
|
233
|
-
</template>
|
|
230
|
+
<ActivityLayout :items="items" logo="/logo.svg" name="Acme">
|
|
231
|
+
<template #header-title>Northwind school</template>
|
|
234
232
|
<template #header-actions>
|
|
235
233
|
<LanguageSwitcher />
|
|
236
234
|
<ThemeToggle />
|
|
237
235
|
</template>
|
|
238
236
|
<template #avatar>
|
|
239
|
-
<
|
|
240
|
-
<AvatarImage :src="user.picture ?? ''" :alt="user.name" />
|
|
241
|
-
<AvatarFallback>{{ user.name.slice(0, 2) }}</AvatarFallback>
|
|
242
|
-
</Avatar>
|
|
237
|
+
<AccountMenu :name="user.name" :secondary="user.email" :src="user.picture" @sign-out="emit('sign-out')" />
|
|
243
238
|
</template>
|
|
244
239
|
<RouterView />
|
|
245
240
|
</ActivityLayout>
|
|
@@ -254,7 +249,92 @@ entry closes it — so does any route change, Back included — and focus goes t
|
|
|
254
249
|
the page's `<main>`, unless the new screen already focused an element inside it
|
|
255
250
|
(an error page's `h1`), which keeps it; closed with Escape, the close button or the overlay,
|
|
256
251
|
focus returns to the menu button. Its entries show their labels, so they have
|
|
257
|
-
no tooltip: none opens over the first entry as focus moves in.
|
|
252
|
+
no tooltip: none opens over the first entry as focus moves in. It shows the
|
|
253
|
+
app's `logo` and `name` (or `#brand`) above the entries, as the expanded
|
|
254
|
+
sidebar does.
|
|
255
|
+
|
|
256
|
+
### The app bar: a title, the actions, the account
|
|
257
|
+
|
|
258
|
+
The header reads, from the start: the phone's menu button, `#header-title`
|
|
259
|
+
(the context the app is in, the active school or organisation), then
|
|
260
|
+
`#header-actions` (language, notifications) and `#avatar` at the end. The
|
|
261
|
+
title takes the room left and ends in an ellipsis when it does not fit, so
|
|
262
|
+
the avatar always stays on screen. It is not a heading: the screen's `h1` is
|
|
263
|
+
`ActivityContent`'s title.
|
|
264
|
+
|
|
265
|
+
`AccountMenu` is the `#avatar` most apps want: an avatar button named
|
|
266
|
+
"Account menu, Ada Lovelace" (`material.account-menu.trigger`) that opens a
|
|
267
|
+
menu aligned to its end, headed by the avatar, the name and `secondary`, then
|
|
268
|
+
the app's `items` and a destructive Sign out
|
|
269
|
+
(`material.account-menu.sign-out`). Choosing Sign out emits `sign-out` and
|
|
270
|
+
keeps the menu open: pass `signing-out` while the request runs, and the item
|
|
271
|
+
shows a spinner and ignores a second selection. Without `src`, or until it
|
|
272
|
+
loads, the avatar shows the initials on `bg-primary`.
|
|
273
|
+
|
|
274
|
+
```vue
|
|
275
|
+
<AccountMenu
|
|
276
|
+
:name="user.name"
|
|
277
|
+
:secondary="user.email"
|
|
278
|
+
:src="user.picture"
|
|
279
|
+
:items="[
|
|
280
|
+
{ label: t('menu.profile'), url: '/profile', icon: 'user' },
|
|
281
|
+
{ label: t('menu.settings'), url: '/settings', icon: 'gear' },
|
|
282
|
+
]"
|
|
283
|
+
:signing-out="pending"
|
|
284
|
+
@sign-out="signOut"
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Each entry is an `AccountMenuItem`, exported with it:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
type AccountMenuItem = {
|
|
292
|
+
label: string; // already translated
|
|
293
|
+
url: string; // rendered as a real link through `link-component`
|
|
294
|
+
icon?: IconName; // optional, decorative: the label names the entry
|
|
295
|
+
};
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`icon` is an `IconName`, a symbol id of the Font Awesome duotone sprite you serve (`user`, `gear`, `arrow-right-from-bracket`; browse the names at <https://fontawesome.com/icons>, and see [getting started](../getting-started.md#icons) for serving the sprite).
|
|
299
|
+
|
|
300
|
+
### The brand: logo and name
|
|
301
|
+
|
|
302
|
+
`logo` (or the `#logo` slot) and `name` put the app's brand in the sidebar
|
|
303
|
+
header, in the shape each place has room for. `logo` is typed `AppLogo`
|
|
304
|
+
(`string | AppLogoImage`, where `AppLogoImage` is `{ src: string; alt?: string }`
|
|
305
|
+
and a string is the image URL), both exported from
|
|
306
|
+
`@nxgt/material-vue/components`:
|
|
307
|
+
|
|
308
|
+
- **The collapsed rail** (desktop, about 70 px wide) shows the **logo alone**.
|
|
309
|
+
`name` is its accessible name (an `<img alt>`, or `role="img"` with an
|
|
310
|
+
`aria-label` around the `#logo` node) and shows as a tooltip on hover, to
|
|
311
|
+
its right.
|
|
312
|
+
- **The expanded sidebar and the phone's menu sheet** show the **logo and the
|
|
313
|
+
name side by side**. The name is on screen there, so the logo is decorative
|
|
314
|
+
(`alt=""` or `aria-hidden`), and no tooltip repeats it.
|
|
315
|
+
|
|
316
|
+
```vue
|
|
317
|
+
<ActivityLayout :items="items" logo="/logo.svg" :name="t('app.name')">…</ActivityLayout>
|
|
318
|
+
<!-- An image with its own alt, used when there is no name: -->
|
|
319
|
+
<ActivityLayout :items="items" :logo="{ src: '/logo.svg', alt: 'Acme' }">…</ActivityLayout>
|
|
320
|
+
<!-- A node, an inline SVG for instance: -->
|
|
321
|
+
<ActivityLayout :items="items" name="Acme">
|
|
322
|
+
<template #logo><AcmeMark class="size-8" /></template>
|
|
323
|
+
…
|
|
324
|
+
</ActivityLayout>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Without a logo the header keeps its placeholder atom badge (named by `name`
|
|
328
|
+
in the rail when there is one); fill `logo` in a real app. `#brand` is the
|
|
329
|
+
full override: one node rendered as given, collapsed or expanded alike, in the
|
|
330
|
+
rail and in the menu sheet. `AppSidebar` takes the same props and slots, and
|
|
331
|
+
`AppHeader` takes them for its menu sheet.
|
|
332
|
+
|
|
333
|
+
`#brand` is rendered twice, once in the rail and once in the menu sheet (the
|
|
334
|
+
rail stays in the page on a phone, hidden): an `id` inside it appears twice
|
|
335
|
+
while the sheet is open, so leave ids out of it. A link in `#brand` (a home
|
|
336
|
+
link around the logo) is the sheet's first focusable element, so it takes
|
|
337
|
+
the focus when the sheet opens.
|
|
258
338
|
|
|
259
339
|
## Landmarks, headings and scrolling
|
|
260
340
|
|
|
@@ -375,7 +455,7 @@ home included, is a `RouterLink`, so it goes through the router's base: under
|
|
|
375
455
|
`AppSidebar`, `AppHeader` and `AppBreadcrumb` are exported for a layout of your
|
|
376
456
|
own. `AppSidebar` and `AppHeader` take the same `items`; `AppSidebar` also
|
|
377
457
|
takes `expanded` (`v-model:expanded`) and `with-toggle-icon`, and has the
|
|
378
|
-
`#brand` slot
|
|
458
|
+
`#brand` slot, `logo`, `name` and `#logo`; `AppHeader` takes `avatar-src`, `logo`, `name` and `show-menu-icon` (default
|
|
379
459
|
`true`), with `#actions`, `#avatar` and a default slot for the middle of the
|
|
380
460
|
bar. The lower-level `Sidebar`, `TopAppBar`, `NavigationRail` and `Breadcrumb`
|
|
381
461
|
primitives are on the
|
package/docs/guides/forms.md
CHANGED
|
@@ -315,10 +315,16 @@ shows them right under its fields.
|
|
|
315
315
|
`form-actions` gets the same sticky footer.
|
|
316
316
|
- A focused control or link is scrolled into view clear of the actions and
|
|
317
317
|
a line of helper text below it (`scroll-margin-bottom` on the fields'
|
|
318
|
-
controls: 6rem, plus a dialog's bottom padding,
|
|
319
|
-
|
|
320
|
-
hidden behind them (WCAG 2.4.11).
|
|
321
|
-
in a scroll box of your own too.
|
|
318
|
+
controls: 6rem, 8rem on a phone, plus a dialog's bottom padding, plus the
|
|
319
|
+
safe-area inset beyond 1rem, 7.5rem above a `ConfirmationDialog`'s stacked
|
|
320
|
+
footer), so a field you tab to is never hidden behind them (WCAG 2.4.11).
|
|
321
|
+
It is set on the controls, so it holds in a scroll box of your own too.
|
|
322
|
+
- The actions pad their bottom for the safe area
|
|
323
|
+
(`max(1rem, env(safe-area-inset-bottom))`): in an installed app with
|
|
324
|
+
`viewport-fit=cover`, they clear the home indicator. The phone default
|
|
325
|
+
(below `sm`, where the buttons share the row) comes from
|
|
326
|
+
`--form-actions-clearance-default`, which is internal: override
|
|
327
|
+
`--form-actions-clearance` instead.
|
|
322
328
|
- Taller actions (a third button, labels that wrap) or helper text on
|
|
323
329
|
several lines need more room: raise `--form-actions-clearance` on the
|
|
324
330
|
form. A dialog whose bottom padding is not the default 1.5rem (`p-0` and
|
package/docs/guides/i18n.md
CHANGED
|
@@ -292,7 +292,7 @@ the `LocationPreview` trigger (`material.map.preview` / `preview-named`),
|
|
|
292
292
|
(`material['duration-field']['hours-label']` / `minutes-label`), and
|
|
293
293
|
the delete button of the deprecated `ContactItem` / `OpeningHoursItem`
|
|
294
294
|
(`material.contacts.buttons.remove`,
|
|
295
|
-
`material['opening-hours'].buttons.remove`). `FacetGroup`'s toggle is named "Level, 2 selected" / "Level, 2 sélectionnés" (`material.facet-group.name`, an ICU plural over `{title}` and `{count}`) and its Clear button "Clear Level" / "Effacer Level" (`material.facet-group.clear-label`, with the visible `material.facet-group.clear`). When the form of a
|
|
295
|
+
`material['opening-hours'].buttons.remove`). `FacetGroup`'s toggle is named "Level, 2 selected" / "Level, 2 sélectionnés" (`material.facet-group.name`, an ICU plural over `{title}` and `{count}`) and its Clear button "Clear Level" / "Effacer Level" (`material.facet-group.clear-label`, with the visible `material.facet-group.clear`). `AccountMenu`'s avatar button is named "Account menu, {name}" / "Menu du compte, {name}" (`material.account-menu.trigger`, over `{name}`) and its last item reads "Sign out" / "Se déconnecter" (`material.account-menu.sign-out`), unless you pass `sign-out-label`. When the form of a
|
|
296
296
|
`ConfirmationDialog` with `form-options` cannot be loaded, it says so in the
|
|
297
297
|
form's place: "The form could not be loaded." / "Le formulaire n’a pas pu être
|
|
298
298
|
chargé." (`material.confirm-dialog.form-failed`). The keys and the French are the
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -167,6 +167,15 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
167
167
|
|
|
168
168
|
## Shipped
|
|
169
169
|
|
|
170
|
+
- **The app's brand, a header title and an account menu** — the app shell
|
|
171
|
+
takes the app's `logo` and `name`: the logo alone in the collapsed rail,
|
|
172
|
+
named by the app's name and shown as its tooltip, the logo and the name side
|
|
173
|
+
by side expanded and in the phone's menu sheet, which now shows `brand` too;
|
|
174
|
+
`#header-title`, the context the app is in, right after the phone's menu
|
|
175
|
+
button and truncated when long; and `AccountMenu`, the avatar button named
|
|
176
|
+
"Account menu, <name>" that opens the account's name and e-mail, the app's
|
|
177
|
+
links and a busy-aware Sign out (`sign-out`).
|
|
178
|
+
|
|
170
179
|
- **Rows a user adds, removes and reorders** — `RepeatableGroup` and
|
|
171
180
|
`RepeatableGroupFormField` over the form library's field array: rows from
|
|
172
181
|
the `row` slot, a list for assistive tech, Remove and move buttons named after
|
package/docs/troubleshooting.md
CHANGED
|
@@ -28,6 +28,7 @@ words in your error.
|
|
|
28
28
|
- [A Button's label overflows a card on a phone](#a-buttons-label-overflows-a-card-on-a-phone)
|
|
29
29
|
- [A dialog or sheet scrolls, or clips a child, after upgrading](#a-dialog-or-sheet-scrolls-or-clips-a-child-after-upgrading)
|
|
30
30
|
- [A form's fields no longer scroll in their own box after upgrading](#a-forms-fields-no-longer-scroll-in-their-own-box-after-upgrading)
|
|
31
|
+
- [axe reports `target-size` on a control under a form's sticky actions](#axe-reports-target-size-on-a-control-under-a-forms-sticky-actions)
|
|
31
32
|
- [`JsBarcode is not a function`](#jsbarcode-is-not-a-function)
|
|
32
33
|
- [A `LinkButton` selected as a `button` stops matching](#a-linkbutton-selected-as-a-button-stops-matching)
|
|
33
34
|
- [A `Toc`, `Pager`, `SeeAlso` or `ScrollProgress` inside `Doc` selected by `data-slot` stops matching](#a-toc-pager-seealso-or-scrollprogress-inside-doc-selected-by-data-slot-stops-matching)
|
|
@@ -190,6 +191,7 @@ words in your error.
|
|
|
190
191
|
- [A test's `getByRole('region')` finds more than one region](#a-tests-getbyroleregion-finds-more-than-one-region)
|
|
191
192
|
- [A `DataTable` toolbar is gone](#a-datatable-toolbar-is-gone)
|
|
192
193
|
- [axe reports `target-size` on a `DataTable`'s "Select all"](#axe-reports-target-size-on-a-datatables-select-all)
|
|
194
|
+
- [A French test no longer finds the sort menu's "Asc" or "Desc"](#a-french-test-no-longer-finds-the-sort-menus-asc-or-desc)
|
|
193
195
|
|
|
194
196
|
**PDF reader**
|
|
195
197
|
|
|
@@ -1311,6 +1313,26 @@ actions where they are, make them static:
|
|
|
1311
1313
|
An app's own fixed bottom bar or floating action button now sits under the
|
|
1312
1314
|
sticky actions (`z-index: 10`): give it a z-index above 10 (`class="z-20"`).
|
|
1313
1315
|
|
|
1316
|
+
### axe reports `target-size` on a control under a form's sticky actions
|
|
1317
|
+
|
|
1318
|
+
**When:** since the form's actions stick to the bottom (see above), axe's
|
|
1319
|
+
`target-size` (WCAG 2.5.8) flags a field's control, a link or a button
|
|
1320
|
+
that sits half under the sticky `[data-slot="form-actions"]` bar, wherever
|
|
1321
|
+
the page happens to stop scrolling when the scan runs. The same control passes once scrolled into view.
|
|
1322
|
+
**Why:** axe measures what is visible of a target: the sticky bar covers part
|
|
1323
|
+
of the control, so axe sees a target smaller than 24 by 24 px, or one whose
|
|
1324
|
+
circle meets Cancel or Save. A user scrolls the control out from under the
|
|
1325
|
+
bar; a scan does not.
|
|
1326
|
+
**Fix:** scan with the actions put back in the flow, so nothing covers the
|
|
1327
|
+
fields, and keep the bar's own buttons in the scan:
|
|
1328
|
+
|
|
1329
|
+
```ts
|
|
1330
|
+
await page.addStyleTag({
|
|
1331
|
+
content: '[data-slot="form-actions"] { position: static !important; }',
|
|
1332
|
+
});
|
|
1333
|
+
await expectAccessible(page);
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1314
1336
|
## Feedback
|
|
1315
1337
|
|
|
1316
1338
|
### A toast with an action never goes away
|
|
@@ -3580,6 +3602,15 @@ page.getByRole('region', { name: 'Invoices' });
|
|
|
3580
3602
|
**Why:** axe measures the 16px box itself, not its 24px `::before`, so it asks for a 24px circle around the box clear of every other control. The sort button reaches 12px back into its cell's padding (`-ml-3`), and the `select` cell had no padding after its checkbox: the circle met the button.
|
|
3581
3603
|
**Fix:** upgrade: the `select` column's checkboxes now keep a 12px margin after them. Drop any axe `exclude` of `thead [data-slot="checkbox-field"]` you kept for it. A `select` column of your own (not `predefinedColumns().select`) needs the same: `me-3` on its checkboxes.
|
|
3582
3604
|
|
|
3605
|
+
### A French test no longer finds the sort menu's "Asc" or "Desc"
|
|
3606
|
+
|
|
3607
|
+
**When:** after upgrading, a test running in French clicks the
|
|
3608
|
+
`DataTableColumnHeader` menu item "Asc" or "Desc" and finds nothing.
|
|
3609
|
+
**Why:** `material.table.labels.asc` / `desc` are now translated in French,
|
|
3610
|
+
"Croissant" / "Décroissant" (#612); English keeps "Asc" / "Desc".
|
|
3611
|
+
**Fix:** look for `getByRole('menuitem', { name: 'Croissant' })` (or
|
|
3612
|
+
`'Décroissant'`) in French.
|
|
3613
|
+
|
|
3583
3614
|
---
|
|
3584
3615
|
|
|
3585
3616
|
---
|
|
@@ -139,13 +139,23 @@
|
|
|
139
139
|
[contenteditable]
|
|
140
140
|
) {
|
|
141
141
|
scroll-margin-bottom: calc(
|
|
142
|
-
var(
|
|
143
|
-
|
|
142
|
+
var(
|
|
143
|
+
--form-actions-clearance,
|
|
144
|
+
var(--form-actions-clearance-default, 6rem)
|
|
145
|
+
) +
|
|
146
|
+
var(--form-actions-fill, 0px) +
|
|
147
|
+
max(0px, calc(env(safe-area-inset-bottom, 0px) - 1rem))
|
|
144
148
|
);
|
|
145
149
|
}
|
|
146
|
-
/*
|
|
150
|
+
/* A phone's actions wrap their labels over two lines and a field has an
|
|
151
|
+
error line: 8rem covers both (`--form-actions-clearance` still wins). */
|
|
152
|
+
@variant max-sm {
|
|
153
|
+
--form-actions-clearance-default: 8rem;
|
|
154
|
+
}
|
|
155
|
+
/* Sticky at the bottom of whatever scrolls the form: in reach. Padded
|
|
156
|
+
for the safe area (`viewport-fit=cover`: the home indicator). */
|
|
147
157
|
[data-slot="form-actions"] {
|
|
148
|
-
@apply sticky bottom-0 z-10 flex w-full justify-end gap-2 bg-background/90 p-4 backdrop-blur-sm max-sm:*:flex-1;
|
|
158
|
+
@apply sticky bottom-0 z-10 flex w-full justify-end gap-2 bg-background/90 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] backdrop-blur-sm max-sm:*:flex-1;
|
|
149
159
|
}
|
|
150
160
|
}
|
|
151
161
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material-vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"email": "stevegires@gmail.com"
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"docs:previews": "vitest run --project previews"
|
|
125
125
|
},
|
|
126
126
|
"dependencies": {
|
|
127
|
-
"@nxgt/material-core": "^0.
|
|
127
|
+
"@nxgt/material-core": "^0.12.0",
|
|
128
128
|
"@floating-ui/dom": "^1.8.0",
|
|
129
129
|
"@fortawesome/fontawesome-common-types": "7.3.1",
|
|
130
130
|
"@lucide/vue": "^1.45.0",
|