@nxgt/material 3.85.0 → 3.86.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 +36 -0
- package/README.md +39 -5
- package/dist/{alert-dialog-1t6ULy5i.js → alert-dialog-DZnt8PYE.js} +1 -1
- package/dist/{async-slice-xyA9Uzct.js → async-slice-D3OdV2BS.js} +1 -1
- package/dist/{button-DhiNGrdT.js → button-MAL5an7L.js} +1 -1
- package/dist/{calculator-BcgxxScL.js → calculator-CyBjPONf.js} +10 -10
- package/dist/calculator-field.js +6 -6
- package/dist/{calculator-segment-C4WQAHcN.js → calculator-segment-BigMpjhn.js} +1 -1
- package/dist/calculator.js +1 -1
- package/dist/charts.js +3 -3
- package/dist/{chip-m0_usuzd.js → chip-DKAKoNxq.js} +2 -2
- package/dist/{code-editor-BgKFrcld.js → code-editor-B6dFQSUJ.js} +4 -4
- package/dist/code-editor.js +4 -4
- package/dist/{code-language-items-BWw17W9s.js → code-language-items-CXEMiWoF.js} +2 -2
- package/dist/components/components.css +2 -0
- package/dist/components/theme-tokens.css +18 -0
- package/dist/components/ui/layout/app-bar/top-app-bar/top-app-bar-collapse.css +60 -0
- package/dist/components/ui/layout/app-bar/top-app-bar/top-app-bar.css +205 -0
- package/dist/components/ui/layout/app-shell/app-header.css +70 -63
- package/dist/{components-cgUDvVTe.js → components-BVHbzzju.js} +17330 -16928
- package/dist/components.js +24 -24
- package/dist/{conversion-variant-DultZZQm.js → conversion-variant-BT5n4-jm.js} +3 -3
- package/dist/{currency-field-CPbaM7ay.js → currency-field-t41sFYg_.js} +4 -4
- package/dist/{dialog-DmlG9opW.js → dialog-BjKiRXJg.js} +3 -3
- package/dist/dnd.js +1 -1
- package/dist/{dropdown-menu-CDKev8dk.js → dropdown-menu-IRFp4CH9.js} +1 -1
- package/dist/editor.js +7 -7
- package/dist/{empty-state-C56000TB.js → empty-state-C70prDDr.js} +1 -1
- package/dist/{financial-variant-BYjQ690K.js → financial-variant-DqW4HJ_v.js} +5 -5
- package/dist/{hooks-BTwLAy_A.js → hooks-CjO11MS7.js} +2 -2
- package/dist/hooks.js +2 -2
- package/dist/{hover-card-CDtW6utN.js → hover-card-cU_aJa18.js} +1 -1
- package/dist/i18n.js +3 -3
- package/dist/{icon-badge-ec7MmUGA.js → icon-badge-D3KO6uEQ.js} +1 -1
- package/dist/{icon-button-CG4aO8Gh.js → icon-button-DrqNk1Ww.js} +1 -1
- package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-bar/index.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/index.d.ts +1 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-actions.d.ts +15 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-headline.d.ts +4 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-link.d.ts +9 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-menu-section.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-primary-action.d.ts +12 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-row.d.ts +23 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/partials/top-app-bar-title-block.d.ts +18 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar.actions.d.ts +43 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar.d.ts +9 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar.types.d.ts +120 -0
- package/dist/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar.utils.d.ts +43 -0
- package/dist/lib/components/ui/layout/app-shell/activity-app-bar.d.ts +6 -6
- package/dist/lib/components/ui/layout/app-shell/activity-chrome.d.ts +6 -3
- package/dist/lib/components/ui/layout/app-shell/activity-column-props.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-shell/activity-column.d.ts +2 -2
- package/dist/lib/components/ui/layout/app-shell/activity-layout-navigation.types.d.ts +32 -4
- package/dist/lib/components/ui/layout/app-shell/activity-layout.types.d.ts +12 -2
- package/dist/lib/components/ui/layout/app-shell/app-header.d.ts +9 -3
- package/dist/lib/components/ui/layout/app-shell/header-look.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-shell/header-title.d.ts +9 -36
- package/dist/lib/components/ui/layout/app-shell/header.utils.d.ts +13 -3
- package/dist/lib/components/ui/layout/app-shell/index.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-shell/navigation.utils.d.ts +7 -2
- package/dist/lib/components/ui/layout/app-shell/shell-scroll.d.ts +23 -1
- package/dist/lib/components/ui/layout/app-shell/shell-top-app-bar.d.ts +10 -0
- package/dist/lib/components/ui/layout/app-shell/shell-top-app-bar.parts.d.ts +58 -0
- package/dist/lib/components/ui/layout/app-shell/shell-top-app-bar.types.d.ts +26 -0
- package/dist/lib/components/ui/layout/app-shell/use-header-scroll.d.ts +16 -9
- package/dist/lib/components/ui/layout/app-shell/use-shell-header.d.ts +1 -1
- package/dist/lib/i18n/resources/en/en.d.ts +4 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +4 -0
- package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +4 -0
- package/dist/lib/i18n/resources/resources.d.ts +8 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/dist/main.js +28 -28
- package/dist/map.js +7 -7
- package/dist/material.css +1 -1
- package/dist/pdf-reader.js +1 -1
- package/dist/{percent-field-8_pILs15.js → percent-field-D47IlaPF.js} +1 -1
- package/dist/{picker-surface-pyGv-Qh9.js → picker-surface-Cg4V4-E0.js} +4 -4
- package/dist/{popover-3EF4q2CT.js → popover-Dzk4-l9U.js} +1 -1
- package/dist/{pos-types-Dv2UxKSN.js → pos-types-JOXMY4Y2.js} +1 -1
- package/dist/{pos-variant-DJvtN9N8.js → pos-variant-B2mS8bMB.js} +4 -4
- package/dist/print.js +1 -1
- package/dist/{programmer-variant-Bmcq2KzC.js → programmer-variant-C_Tl0P4_.js} +2 -2
- package/dist/{public-BNebh4z0.js → public-ByAsqBOf.js} +9 -9
- package/dist/{rich-code-block-DmX7d58S.js → rich-code-block-CJAfqk6b.js} +5 -5
- package/dist/{scientific-variant-DijUrpP8.js → scientific-variant-CskM4MLV.js} +2 -2
- package/dist/{sortable-provider-Cnmt_gWu.js → sortable-provider-ICS_vkLA.js} +2 -2
- package/dist/{spinner-C6LP2Rw8.js → spinner-CweqX5A9.js} +1 -1
- package/dist/styles.css +2 -0
- package/dist/{tabs-Bj1zOe7-.js → tabs-BOT9B4le.js} +1 -1
- package/dist/theme-picker.js +2 -2
- package/dist/{theme-toggle-Cxku5iBP.js → theme-toggle-WAFkncYx.js} +1 -1
- package/dist/{toolbar-items-CEIuSxU_.js → toolbar-items-BsgzHSNf.js} +4 -4
- package/dist/{translate-material-DI3nmQ6I.js → translate-material-DTIAPmlU.js} +1 -1
- package/dist/{translator-BstxG_hN.js → translator-BRZNhsy5.js} +8 -0
- package/dist/{use-chat-composer-BqLkk_iH.js → use-chat-composer-67MgWAHz.js} +15 -15
- package/dist/{use-heading-spy-nFyb9_KE.js → use-heading-spy-D8WbHJuK.js} +4 -4
- package/dist/{use-material-translation-1kCHtB0p.js → use-material-translation-CCy1Me0h.js} +1 -1
- package/dist/{use-return-focus-Hv8rn55-.js → use-return-focus-BA8G1qVU.js} +1 -1
- package/docs/README.md +1 -0
- package/docs/components/navigation-and-layout.md +85 -32
- package/docs/guides/app-shell.md +158 -63
- package/docs/guides/drawing.md +2 -0
- package/docs/guides/layouts.md +3 -3
- package/docs/guides/migrating-to-top-app-bar.md +156 -0
- package/docs/guides/theming.md +5 -0
- package/docs/previews/navigation-layout-appshell-blue-moon.webp +0 -0
- package/docs/previews/navigation-layout-appshell-footer-icon.webp +0 -0
- package/docs/previews/navigation-layout-appshell-menu-badge.webp +0 -0
- package/docs/previews/navigation-layout-appshell-page-ground.webp +0 -0
- package/docs/previews/navigation-layout-appshell-themes.webp +0 -0
- package/docs/previews/navigation-layout-appshell.webp +0 -0
- package/docs/previews/navigation-layout-topappbar.webp +0 -0
- package/docs/roadmap.md +17 -6
- package/docs/troubleshooting.md +80 -0
- package/lib/components/components.css +2 -0
- package/lib/components/theme-tokens.css +18 -0
- package/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar-collapse.css +60 -0
- package/lib/components/ui/layout/app-bar/top-app-bar/top-app-bar.css +205 -0
- package/lib/components/ui/layout/app-shell/app-header.css +70 -63
- package/lib/styles.css +2 -0
- package/lib/themes/ambre.css +5 -1
- package/lib/themes/ardoise.css +5 -1
- package/lib/themes/bleumono.css +5 -1
- package/lib/themes/bluemoon.css +5 -1
- package/lib/themes/corail.css +5 -1
- package/lib/themes/foret.css +5 -1
- package/lib/themes/lavande.css +5 -1
- package/lib/themes/menthe.css +5 -1
- package/lib/themes/ocean.css +5 -1
- package/lib/themes/pink.css +5 -1
- package/lib/themes/prune.css +5 -1
- package/lib/themes/sable.css +5 -1
- package/lib/themes/slate.css +5 -1
- package/lib/themes/teal.css +5 -1
- package/package.json +2 -2
- package/dist/lib/components/ui/layout/app-bar/top-app-bar.d.ts +0 -18
- package/dist/lib/components/ui/layout/app-shell/app-header-row.d.ts +0 -3
- package/dist/lib/components/ui/layout/app-shell/header-context.d.ts +0 -10
- package/dist/lib/components/ui/layout/app-shell/page-title.d.ts +0 -27
- /package/dist/lib/components/ui/layout/{app-shell → app-bar/top-app-bar}/use-truncated-title.d.ts +0 -0
package/docs/guides/app-shell.md
CHANGED
|
@@ -201,10 +201,11 @@ partitionMenu(items); // { content, footer }
|
|
|
201
201
|
| `linkComponent` | `AppShellLinkComponent` | React Router `Link` | The link each menu entry renders, given `href` (see below). Defaults to the [`LinkComponentProvider`](../components/primitives.md#linkcomponentprovider)'s link when one is set. |
|
|
202
202
|
| `headerTitle` | `ReactNode` | — | 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; when it is cut off, its full text is the `title` tooltip (#629) |
|
|
203
203
|
| `titleAfter` | `ReactNode` | — | A node right after the page's title in the app bar, outside its `h1` (a record's `Switcher`); wins over a route's `handle.titleAfter` (see [A slot after the title](#a-slot-after-the-title)) |
|
|
204
|
-
| `headerContext` | `ReactNode` | — |
|
|
204
|
+
| `headerContext` | `ReactNode` | — | The bar's `subtitle`: a small muted context line (the tenant's name) under the page's title, from `md` up: outside the `h1`, truncated, its full text the tooltip once cut off. Not shown on a phone, where the menu sheet's `context` carries it (see [A context line](#a-context-line-after-the-title)) |
|
|
205
205
|
| `breadcrumb` | `boolean` | `true` | `false` hides the breadcrumb trail, for an error page whose matched routes would show a misleading one (see [Breadcrumbs](#breadcrumbs)) |
|
|
206
206
|
| `breadcrumbRoot` | `AppBreadcrumbRoot` (`{ label: ReactNode; to: string }`, or `{ label: string; to: string; icon: true }`) | — | The breadcrumb's first crumb, in place of the default home icon: a text link to `to`, or with `icon: true` the home icon alone, linked to `to` and named `label` (see [Breadcrumbs](#breadcrumbs)) |
|
|
207
|
-
| `headerActions` | `ReactNode` | — | In the header, before the avatar: notifications, help, `ThemeToggle
|
|
207
|
+
| `headerActions` | `ReactNode \| TopAppBarAction[]` | — | In the header, before the avatar: notifications, help, `ThemeToggle`; an array of data draws free icon buttons, the rest in the account menu |
|
|
208
|
+
| `headerPrimaryAction` | `TopAppBarPrimaryAction` (`{ label, icon, onClick?, disabled? }`) | — | The screen's main action in the header: a `Button` from 768 px, a `Fab` on a phone |
|
|
208
209
|
| `children` | `ReactNode` | — | The routed content, usually `<Outlet />` |
|
|
209
210
|
| `contentAs` | `'main' \| 'div'` | `'main'` | The content region's element: the page's `<main>` landmark, or a `div` when your app renders its own `<main>` |
|
|
210
211
|
| `scroll` | `'document' \| 'container'` | `'document'` | Who scrolls: the page (header and sidebar sticky), or the content region inside a shell one screen high |
|
|
@@ -212,7 +213,7 @@ partitionMenu(items); // { content, footer }
|
|
|
212
213
|
| `menuOpen` | `boolean` | — | Controls the phone's menu sheet: open while `true`. Leave it out and the layout manages the sheet. Only a phone shows the sheet |
|
|
213
214
|
| `onMenuOpenChange` | `(open: boolean) => void` | — | Called for every change of the sheet: the menu button, Escape, the close button, a followed link, a new location |
|
|
214
215
|
| `navigation` | `ShellNavigation \| { phone?, tablet?, desktop?, hideOnScroll?, persistKey? }` | `modal-drawer` / `rail` / `rail` | The navigation per window size; see [`navigation` and `header`](#navigation-and-header) |
|
|
215
|
-
| `header` | `'small' \| '
|
|
216
|
+
| `header` | `'small' \| 'medium-flexible' \| 'large-flexible' \| 'search' \| 'none' \| { size?, align?, collapse?, hideOnScroll?, tabs?, search? }` | `'small'` | The app bar's size, overridable per route with `handle.header`; the old `'center'`, `'medium'`, `'large'` and `variant` are deprecated; see [Top app bar sizes](#top-app-bar-sizes) |
|
|
216
217
|
| `backdrop` | `ReactNode \| false` | — | An exception to the theme's background (the page ground, [`--ground`](#the-page-ground), is painted either way), which the layout draws by default (Lavande's: the built-in gradient and blobs). A node replaces it for this screen: usually a `Background` preset from `@nxgt/material/backgrounds` (see [Use a background preset behind the shell](#use-a-background-preset-behind-the-shell)); `false` draws no background, a plain page |
|
|
217
218
|
| `keepClear` | `boolean \| 'gaps'` | `true` | how the backdrop's glyphs keep clear of the page: `true` drops every glyph within 8px of a surface, a text or a control; `'gaps'` also keeps a glyph that fits in a gap of 24px or more between two surfaces; `false` keeps nothing clear (the edge and the header band still are). See [Keep the backdrop clear of the content](#keep-the-backdrop-clear-of-the-content) |
|
|
218
219
|
|
|
@@ -250,11 +251,49 @@ const MyLink: AppShellLinkComponent = ({ href, ...props }) => <Link to={href} {.
|
|
|
250
251
|
// <ActivityLayout items={items} linkComponent={MyLink}>…</ActivityLayout>
|
|
251
252
|
```
|
|
252
253
|
|
|
254
|
+
Actions as data: `headerActions` also takes a `TopAppBarAction[]` (`label`,
|
|
255
|
+
`icon`, `onClick` or `href`, `placement: 'bar' | 'account'`, `group`, `selected`,
|
|
256
|
+
`disabled`). The first ones are free icon buttons in the bar (one on a phone, two
|
|
257
|
+
from 768 px); the others, and every `'account'` action, go to the menu opened by
|
|
258
|
+
the `avatar`, which then must hold no link or button. `headerPrimaryAction` is
|
|
259
|
+
the screen's main action:
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
<ActivityLayout
|
|
263
|
+
items={items}
|
|
264
|
+
avatar={<Avatar src={user.photo} />}
|
|
265
|
+
headerActions={[
|
|
266
|
+
{ label: 'Notifications', icon: <Icon name="bell" />, onClick: openInbox },
|
|
267
|
+
{ label: 'Help', icon: <Icon name="circle-question" />, href: '/help' },
|
|
268
|
+
{ label: 'Sign out', placement: 'account', onClick: signOut },
|
|
269
|
+
]}
|
|
270
|
+
headerPrimaryAction={{ label: 'New invoice', icon: <Icon name="plus" />, onClick: create }}
|
|
271
|
+
>
|
|
272
|
+
<Outlet />
|
|
273
|
+
</ActivityLayout>
|
|
274
|
+
```
|
|
275
|
+
|
|
253
276
|
`className` and the rest of the `div` props (`id`, `data-*`…) go to the outer
|
|
254
277
|
element, `[data-slot=activity-layout]`. The sticky app bar (menu button,
|
|
255
278
|
`headerTitle`, `headerActions` and avatar) is `[data-slot=app-header]`, so a
|
|
256
279
|
test or an accessibility helper can name it without a structural selector;
|
|
257
|
-
`AppHeader` carries the same slot when used on
|
|
280
|
+
`AppHeader` (deprecated, use `TopAppBar`) carries the same slot when used on
|
|
281
|
+
its own. The bar is a `TopAppBar` drawn as the page's `<header>` banner; it keeps
|
|
282
|
+
the `app-header*` slot names below, which `TopAppBar` styles too. They become
|
|
283
|
+
`top-app-bar*` at the next major.
|
|
284
|
+
|
|
285
|
+
| `data-slot` | Marks |
|
|
286
|
+
| --- | --- |
|
|
287
|
+
| `app-header` | the bar's root (`<header>`) |
|
|
288
|
+
| `app-header-page-title` | the page's `h1` |
|
|
289
|
+
| `app-header-context` | the muted line under the title (`headerContext`) |
|
|
290
|
+
| `app-header-headline` | the second row of a medium or large bar |
|
|
291
|
+
| `app-header-collapsed-title` | the title's copy in the small row of a collapsing bar |
|
|
292
|
+
| `app-header-tabs` | the tab row under the bar |
|
|
293
|
+
| `app-header-title` | the leading `headerTitle` |
|
|
294
|
+
| `app-header-title-after` | the slot after the title (`titleAfter`) |
|
|
295
|
+
| `app-header-back` | the back arrow |
|
|
296
|
+
|
|
258
297
|
`avatar` and `headerActions` are props because the shell holds no session:
|
|
259
298
|
read the user wherever your app keeps it and pass the node.
|
|
260
299
|
|
|
@@ -328,7 +367,7 @@ today: the menu sheet on a phone, the rail from `md`, a small header.
|
|
|
328
367
|
<ActivityLayout
|
|
329
368
|
items={items}
|
|
330
369
|
navigation={{ phone: 'modal-drawer', tablet: 'rail', desktop: 'rail' }}
|
|
331
|
-
header={{
|
|
370
|
+
header={{ size: 'small' }}
|
|
332
371
|
>
|
|
333
372
|
<Outlet />
|
|
334
373
|
</ActivityLayout>
|
|
@@ -346,9 +385,10 @@ today: the menu sheet on a phone, the rail from `md`, a small header.
|
|
|
346
385
|
name alone draws them at every size, the phone included. Every name is drawn:
|
|
347
386
|
`'modal-drawer'`, `'rail'`, `'rail-expanded'`, `'drawer'`, `'sidebar'`, `'top'`,
|
|
348
387
|
`'two-level'`, `'floating'`, `'bar'` and `'none'`.
|
|
349
|
-
- `header`: `'small'`, `'
|
|
350
|
-
`{
|
|
351
|
-
`
|
|
388
|
+
- `header`: `'small'`, `'medium-flexible'`, `'large-flexible'`, `'search'` or
|
|
389
|
+
`'none'`, or `{ size, align, collapse, hideOnScroll, tabs, search }` (the old
|
|
390
|
+
`'center'`, `'medium'`, `'large'` and `variant` are deprecated). The sizes and
|
|
391
|
+
`hideOnScroll` are drawn (see [Top app bar sizes](#top-app-bar-sizes));
|
|
352
392
|
`search` and `tabs` are drawn (see [The app bar's search](#the-app-bars-search) and
|
|
353
393
|
[Tabs under the app bar](#tabs-under-the-app-bar)). A route's `handle.back` draws a
|
|
354
394
|
back arrow ([The back arrow](#the-back-arrow)).
|
|
@@ -676,71 +716,122 @@ the user asked for less motion: skip the slide and snap. The header
|
|
|
676
716
|
(`navigation.hideOnScroll`) read it; the shell tracks the scroll only when one of
|
|
677
717
|
them asks, and `NavigationToolbar` reads it by hand too.
|
|
678
718
|
|
|
679
|
-
###
|
|
719
|
+
### Top app bar sizes
|
|
680
720
|
|
|
681
|
-
`header` chooses the bar's size, the way Material 3 does
|
|
682
|
-
|
|
721
|
+
`header` chooses the bar's size, the way Material 3 does, and the shell draws it
|
|
722
|
+
with [`TopAppBar`](../components/navigation-and-layout.md#topappbar). Unset is
|
|
723
|
+
`'small'`: one row, the title beside the actions.
|
|
683
724
|
|
|
684
725
|
```tsx
|
|
685
726
|
import { ActivityLayout, type AppShellHandle } from '@nxgt/material/components';
|
|
686
727
|
|
|
687
|
-
<ActivityLayout items={items} header="large">
|
|
728
|
+
<ActivityLayout items={items} header="large-flexible">
|
|
688
729
|
<Outlet />
|
|
689
730
|
</ActivityLayout>
|
|
690
731
|
|
|
691
732
|
// a route opts in, whatever the layout says
|
|
692
|
-
export const handle = { title: 'Projects', header: 'large' } satisfies AppShellHandle;
|
|
733
|
+
export const handle = { title: 'Projects', header: 'large-flexible' } satisfies AppShellHandle;
|
|
693
734
|
|
|
694
|
-
// a bar that goes away on the way down
|
|
695
|
-
<ActivityLayout items={items} header={{
|
|
735
|
+
// a centred small bar that goes away on the way down
|
|
736
|
+
<ActivityLayout items={items} header={{ size: 'small', align: 'center', hideOnScroll: true }} />
|
|
696
737
|
```
|
|
697
738
|
|
|
698
|
-
Defaults: `
|
|
699
|
-
|
|
700
|
-
bar's CSS ships with it.
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
the
|
|
719
|
-
the
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
The
|
|
739
|
+
Defaults: `size` is `'small'`, `align` is `'start'`, `collapse` is `true` for the
|
|
740
|
+
two flexible sizes, `hideOnScroll` is `false`. Nothing to import beyond
|
|
741
|
+
`styles.css`: the bar's CSS ships with it.
|
|
742
|
+
|
|
743
|
+
| Size | Use it for | What it draws |
|
|
744
|
+
| --- | --- | --- |
|
|
745
|
+
| `'small'` | most screens, a dense tool | one row: the title beside the actions. `align: 'center'` centres the title between the menu button and the actions |
|
|
746
|
+
| `'medium-flexible'` | a section's landing screen | the page's title on a second row (28 px), under the small row |
|
|
747
|
+
| `'large-flexible'` | a screen that opens a flow or a long list | the title on a second row, bigger (40 px, 36 px on a phone) and up to two lines |
|
|
748
|
+
| `'search'` | a search-first screen | the `header.search` field is the bar's centre; the title stays in the page as a visually hidden `h1`, so the screen keeps its heading |
|
|
749
|
+
| `'none'` | a full-screen tool that draws its own chrome | no bar. The screen's own `ActivityContent` title is then the page's `h1`; the phone's menu button goes with the bar, so pair it with a navigation that has one on its own (`navigation="bar"`) |
|
|
750
|
+
|
|
751
|
+
- **Collapse.** A flexible bar folds its second row into the small row as the
|
|
752
|
+
page scrolls: the headline fades and the bar shrinks over the headline row's
|
|
753
|
+
measured height, the title shrinks to 90% from its start edge, and the small
|
|
754
|
+
row then shows the title (a copy hidden from assistive technology). A scrolled
|
|
755
|
+
bar takes a soft tint and a 1px hairline. `collapse: false` keeps the headline
|
|
756
|
+
however far the page scrolls.
|
|
757
|
+
- **`hideOnScroll`**: the bar slides away while the page scrolls down (past 64px)
|
|
758
|
+
and comes back on the way up. While away it is `inert` and out of the tab order;
|
|
759
|
+
if the focus was inside it, the focus moves to the content region.
|
|
760
|
+
- **Subtitle.** `headerContext` is the bar's subtitle, a muted line under the title
|
|
761
|
+
(see [A context line after the title](#a-context-line-after-the-title)).
|
|
762
|
+
- **Actions and main action.** `headerActions` takes nodes or a `TopAppBarAction[]`,
|
|
763
|
+
and `headerPrimaryAction` the screen's main action (see
|
|
764
|
+
[The app bar](#the-app-bar-a-title-the-actions-the-account)).
|
|
765
|
+
|
|
766
|
+
The bar's height is `--nxgt-header-height` (default `4rem`, see
|
|
767
|
+
[the header height](./theming.md#the-header-height)): the row is that height
|
|
768
|
+
less the bar's own vertical padding, so a custom value resizes the bar, the
|
|
769
|
+
rail's header and the first-paint total together. A `className` on the bar (a
|
|
770
|
+
background, a radius, a shadow) wins over its at-rest look; once the page
|
|
771
|
+
scrolls, the scrolled tint replaces a `className` background. The bar is drawn
|
|
772
|
+
as the page's `<header>`; `title` on a standalone `TopAppBar` is its `<h1>` (it
|
|
773
|
+
was the HTML `title` attribute), and its root is a column whose children sit in
|
|
774
|
+
a `[data-slot="top-app-bar-row"]`, so layout utilities on the root's `className`
|
|
775
|
+
(`justify-between`, `gap-*`, `items-*`) no longer reach them (see
|
|
776
|
+
[Moving to TopAppBar](./migrating-to-top-app-bar.md#what-looks-different)).
|
|
777
|
+
|
|
778
|
+
A route gives its own through `handle.header`: a size (`'large-flexible'`) or the
|
|
779
|
+
options (`{ size, align, collapse, hideOnScroll, tabs, search }`, like the prop).
|
|
780
|
+
The deepest route that declares one wins, and its options win over the layout's
|
|
781
|
+
one by one: a route that only names a size keeps the layout's `hideOnScroll` and
|
|
782
|
+
`align`. It is read from the matched routes, so the server and the browser draw
|
|
783
|
+
the same bar.
|
|
784
|
+
|
|
785
|
+
The title **is** the page's one `h1` (the small row's copy is `aria-hidden`).
|
|
724
786
|
A medium or large header needs a title in the bar, a route's `handle.title`;
|
|
725
787
|
without one the bar stays small, so nothing changes for a screen that titles
|
|
726
788
|
itself with `ActivityContent`. The server always renders the bar expanded and
|
|
727
789
|
shown; the browser then follows the scroll.
|
|
728
790
|
|
|
791
|
+
**The search size.** `header: { size: 'search', search: { placeholder: 'Search projects' } }`
|
|
792
|
+
puts the search field at the bar's centre. A route that sets a `handle.title`
|
|
793
|
+
still gets its `h1`, visually hidden but in the accessibility tree and
|
|
794
|
+
labelling `<main>`; without a title the screen's own `ActivityContent` title is
|
|
795
|
+
the heading, as for any small bar. See [The app bar's search](#the-app-bars-search)
|
|
796
|
+
for the field's props.
|
|
797
|
+
|
|
798
|
+
**Phone and desktop.**
|
|
799
|
+
|
|
800
|
+
- On a phone the menu button is a ghost icon button leading the bar, with no
|
|
801
|
+
brand or logo; the bar keeps one free icon action, the rest go to the account
|
|
802
|
+
menu as inline sections. `headerPrimaryAction` is a floating button above the
|
|
803
|
+
bottom navigation. `headerContext` is hidden (the sheet's `context` covers it).
|
|
804
|
+
- From 768 px two icon actions fit, `headerPrimaryAction` is a `Button` in the
|
|
805
|
+
bar, and `headerContext` shows under the title.
|
|
806
|
+
- Heights: the headline row of a medium bar is 3 rem and a large bar's 6.5 rem
|
|
807
|
+
before it is measured, then follows the title's real height.
|
|
808
|
+
|
|
809
|
+
**Reduced motion.** Under `prefers-reduced-motion: reduce` the collapse snaps
|
|
810
|
+
between the two states at the halfway point, with no morph, no slide for
|
|
811
|
+
`hideOnScroll` and no transition on the bar's tint.
|
|
812
|
+
|
|
729
813
|
The scroll is the shell's ([Scroll direction](#scroll-direction)): the window,
|
|
730
814
|
or the content region with `scroll="container"` (a hidden bar then gives its
|
|
731
815
|
room back). Once per animation frame the bar sets one CSS variable on itself,
|
|
732
|
-
`--nxgt-header-progress` (0 expanded, 1 collapsed), through `setProperty`,
|
|
733
|
-
no inline style reaches the markup
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
816
|
+
`--nxgt-header-progress` (0 expanded, 1 collapsed), through `setProperty`, and
|
|
817
|
+
`data-scrolled` once the page has moved, so no inline style reaches the markup
|
|
818
|
+
and a frame of scrolling does not re-render. A plain shell, with no collapsing
|
|
819
|
+
or hiding bar, tracks no scroll at all.
|
|
820
|
+
|
|
821
|
+
**Deprecated spellings.** `'center'`, `'medium'`, `'large'` and `variant` in the
|
|
822
|
+
options still work and log a one-time development warning (see
|
|
823
|
+
[troubleshooting](../troubleshooting.md#activitylayout-header-center-medium-or-large-is-deprecated)):
|
|
824
|
+
`'center'` is `{ size: 'small', align: 'center' }`, `'medium'` is
|
|
825
|
+
`'medium-flexible'`, `'large'` is `'large-flexible'`. See
|
|
826
|
+
[Moving to TopAppBar](./migrating-to-top-app-bar.md).
|
|
827
|
+
|
|
828
|
+
`TopAppBar` takes the same as props (`size`, `align`, `collapse`, `hideOnScroll`,
|
|
829
|
+
`title`, `subtitle`, `tabs`, `search`) for a bar of your own; `AppHeader` is its
|
|
830
|
+
deprecated wrapper (see [Using the parts](#using-the-parts)). Known limits: a
|
|
831
|
+
hidden bar in a `scroll="container"` shell that is barely taller than its
|
|
832
|
+
container can flicker at the very bottom (the region grows, so the scroll
|
|
833
|
+
clamps); the scroll-driven CSS animation enhancement is not used, the JavaScript
|
|
834
|
+
path drives every browser.
|
|
744
835
|
|
|
745
836
|
### The app bar's search
|
|
746
837
|
|
|
@@ -755,13 +846,13 @@ import { ActivityLayout } from '@nxgt/material/components';
|
|
|
755
846
|
<ActivityLayout
|
|
756
847
|
items={items}
|
|
757
848
|
header={{
|
|
758
|
-
|
|
849
|
+
size: 'small',
|
|
759
850
|
search: { placeholder: 'Search projects', shortcut: '/', onSubmit: (q) => navigate(`/search?q=${q}`) },
|
|
760
851
|
}}
|
|
761
852
|
/>
|
|
762
853
|
|
|
763
854
|
// a route turns it off, or changes it, like the other options
|
|
764
|
-
export const handle = { title: 'Settings', header: {
|
|
855
|
+
export const handle = { title: 'Settings', header: { size: 'small', search: false } };
|
|
765
856
|
```
|
|
766
857
|
|
|
767
858
|
The search never changes the shape of the page: the content stays mounted when
|
|
@@ -792,7 +883,7 @@ const tabs = (
|
|
|
792
883
|
);
|
|
793
884
|
|
|
794
885
|
export function Layout({ items }: { items: MenuItem[] }) {
|
|
795
|
-
return <ActivityLayout items={items} header={{
|
|
886
|
+
return <ActivityLayout items={items} header={{ size: 'small', tabs }} />;
|
|
796
887
|
}
|
|
797
888
|
```
|
|
798
889
|
|
|
@@ -809,13 +900,13 @@ const projectTabs = (
|
|
|
809
900
|
|
|
810
901
|
export const handle = {
|
|
811
902
|
title: 'Atlas',
|
|
812
|
-
header: {
|
|
903
|
+
header: { size: 'small', tabs: projectTabs }, // tabs: null drops the layout's
|
|
813
904
|
} satisfies AppShellHandle;
|
|
814
905
|
```
|
|
815
906
|
|
|
816
907
|
The option is `header.tabs` (there is no `handle.headerTabs`): a route's `tabs`
|
|
817
908
|
replaces the layout's whole, `tabs: null` drops them for that route, and a route
|
|
818
|
-
that only names a
|
|
909
|
+
that only names a size keeps the layout's. The row's height is one CSS
|
|
819
910
|
variable, `--nxgt-header-tabs` (3rem, in `app-header.css`). The bar's whole
|
|
820
911
|
height (the row, a headline row and the tabs) is `--nxgt-header-total` on the
|
|
821
912
|
`ActivityLayout` root, measured with a `ResizeObserver` (worked out in CSS from
|
|
@@ -1045,14 +1136,14 @@ A multi-tenant app keeps the current tenant visible on a desktop screen with
|
|
|
1045
1136
|
```
|
|
1046
1137
|
|
|
1047
1138
|
- **It is outside the `h1`** (`[data-slot=app-header-context]`), so the
|
|
1048
|
-
heading's name stays the page's title; it
|
|
1049
|
-
its full text is the `title` tooltip once it is cut off (#629).
|
|
1139
|
+
heading's name stays the page's title; it sits under the title (the bar's
|
|
1140
|
+
subtitle), is truncated to the title's width, and its full text is the `title` tooltip once it is cut off (#629).
|
|
1050
1141
|
- **From `md` up only.** On a phone it is hidden: the menu sheet's `context`
|
|
1051
1142
|
line covers it. The two props are independent, so setting `context` alone
|
|
1052
1143
|
adds nothing to the bar, and setting both never shows the name twice on one
|
|
1053
1144
|
screen.
|
|
1054
1145
|
- **The title truncates first**: with a long title, the slot and the line
|
|
1055
|
-
together, the title gives way (two lines on a phone, then an ellipsis); the slot stays whole and the line
|
|
1146
|
+
together, the title gives way (two lines on a phone, then an ellipsis); the slot stays whole and the line stays under the title.
|
|
1056
1147
|
- **It needs a page title**: while the bar shows none (no `handle.title`),
|
|
1057
1148
|
`headerTitle` is the context line and `headerContext` is ignored.
|
|
1058
1149
|
|
|
@@ -1793,8 +1884,8 @@ export function InvoiceTrail() {
|
|
|
1793
1884
|
|
|
1794
1885
|
## Using the parts
|
|
1795
1886
|
|
|
1796
|
-
`AppSidebar`, `AppHeader` and `AppBreadcrumb` are
|
|
1797
|
-
own. They take the same `items`; `AppHeader` takes `actions`, `avatar`,
|
|
1887
|
+
`AppSidebar`, `AppHeader` (deprecated, use `TopAppBar`) and `AppBreadcrumb` are
|
|
1888
|
+
exported for a layout of your own. They take the same `items`; `AppHeader` takes `actions`, `avatar`,
|
|
1798
1889
|
`showMenuIcon` (default `true`), and `menuOpen` / `onMenuOpenChange` to control
|
|
1799
1890
|
its phone menu sheet, `tabs` (a node, default none: a `TabsNav` drawn as a row
|
|
1800
1891
|
at the foot of the bar) and `back` (a `ShellBack`, default none: the back arrow,
|
|
@@ -1802,6 +1893,10 @@ before the menu button). The lower-level `Sidebar`, `TopAppBar` and
|
|
|
1802
1893
|
`Breadcrumb` primitives are on the
|
|
1803
1894
|
[navigation & layout](../components/navigation-and-layout.md) page.
|
|
1804
1895
|
|
|
1896
|
+
The shell draws its bar with `TopAppBar`, as the page's `<header>`. `AppHeader`
|
|
1897
|
+
is deprecated: it stays as a wrapper over `TopAppBar` with the same props, and
|
|
1898
|
+
warns once in development.
|
|
1899
|
+
|
|
1805
1900
|
`AppHeader` needs a React Router context even on its own: its menu sheet reads
|
|
1806
1901
|
the location (`useLocation`) to close when it changes, and outside a router
|
|
1807
1902
|
that hook throws. Render it under your `RouterProvider` — or, in a test, inside
|
package/docs/guides/drawing.md
CHANGED
|
@@ -187,6 +187,8 @@ A fill, a stroke or a gradient stop is a **role**, a **tone** or a free colour.
|
|
|
187
187
|
`outline-variant`, `success`, `info`, `warning`, `neutral`. `ROLES` lists them
|
|
188
188
|
and `ROLE_VARS` gives each one's CSS variable (`on-primary-container` is
|
|
189
189
|
`--primary-text`, `outline` is `--muted-foreground`).
|
|
190
|
+
The drawing role `surface-container` resolves to `--card`; it is not the
|
|
191
|
+
`--surface-container` theme token (`bg-surface-container`).
|
|
190
192
|
They follow light and dark, scoped themes and a retheme with no re-render.
|
|
191
193
|
- **Tones**: `tone('success')`, `tone('success', 'container')` (variants `base`,
|
|
192
194
|
`text`, `on`, `container`) name a theme tone or an app tone of your own, the
|
package/docs/guides/layouts.md
CHANGED
|
@@ -75,7 +75,7 @@ layout of your own. Every preset, its entries (`bar`, `priority`, `group`,
|
|
|
75
75
|
<ActivityLayout
|
|
76
76
|
items={items}
|
|
77
77
|
header={{
|
|
78
|
-
|
|
78
|
+
size: 'large-flexible',
|
|
79
79
|
hideOnScroll: true,
|
|
80
80
|
search: { placeholder: 'Search projects', shortcut: '/' },
|
|
81
81
|
tabs: (
|
|
@@ -95,13 +95,13 @@ A route changes its own bar with a handle, and draws a back arrow:
|
|
|
95
95
|
```tsx
|
|
96
96
|
export const handle = {
|
|
97
97
|
title: 'Atlas redesign',
|
|
98
|
-
header: {
|
|
98
|
+
header: { size: 'medium-flexible' },
|
|
99
99
|
back: { to: '/projects', label: 'Projects' },
|
|
100
100
|
} satisfies AppShellHandle;
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
The search is a pill with a docked results panel from 768px and a full-screen
|
|
104
|
-
view on a phone. See [
|
|
104
|
+
view on a phone. See [Top app bar sizes](app-shell.md#top-app-bar-sizes),
|
|
105
105
|
[the search](app-shell.md#the-app-bars-search),
|
|
106
106
|
[the tabs](app-shell.md#tabs-under-the-app-bar) and
|
|
107
107
|
[the back arrow](app-shell.md#the-back-arrow).
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Moving to TopAppBar
|
|
2
|
+
|
|
3
|
+
`ActivityLayout` draws its app bar with `TopAppBar`, and `TopAppBar` has new
|
|
4
|
+
sizes, a title that is the page's `h1`, free icon actions and a main action. This
|
|
5
|
+
is a minor release: every old spelling keeps working, logs a one-time development
|
|
6
|
+
warning, and is removed no earlier than the next major. This page lists each one
|
|
7
|
+
with what replaces it, what looks different, and which slots the next major renames.
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [`AppHeader` becomes `TopAppBar`](#appheader-becomes-topappbar)
|
|
12
|
+
- [`header` values and `handle.header`](#header-values-and-handleheader)
|
|
13
|
+
- [`TopAppBar` `variant` and `headline`](#topappbar-variant-and-headline)
|
|
14
|
+
- [Actions, the account menu and a main action](#actions-the-account-menu-and-a-main-action)
|
|
15
|
+
- [What looks different](#what-looks-different)
|
|
16
|
+
- [The `data-slot` rename in the next major](#the-data-slot-rename-in-the-next-major)
|
|
17
|
+
|
|
18
|
+
## `AppHeader` becomes `TopAppBar`
|
|
19
|
+
|
|
20
|
+
**Search**: `AppHeader`.
|
|
21
|
+
|
|
22
|
+
`AppHeader` is a thin wrapper over `TopAppBar` with the props it always had; it
|
|
23
|
+
logs `AppHeader: is deprecated, use TopAppBar` once in development. Inside
|
|
24
|
+
`ActivityLayout` there is nothing to do: the layout does not use the wrapper.
|
|
25
|
+
In a layout of your own, draw the bar with `TopAppBar`; the menu button and back
|
|
26
|
+
arrow go in `leading`, the avatar in `trailing`.
|
|
27
|
+
|
|
28
|
+
**Replace**:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// before
|
|
32
|
+
<AppHeader items={items} variant="large" headline={<h1>Orders</h1>} avatar={<Avatar />} />
|
|
33
|
+
|
|
34
|
+
// after
|
|
35
|
+
<TopAppBar
|
|
36
|
+
as="header"
|
|
37
|
+
size="large-flexible"
|
|
38
|
+
title="Orders"
|
|
39
|
+
leading={<MenuButton />}
|
|
40
|
+
trailing={<Avatar />}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`TopAppBar` does not draw the phone's menu sheet or read the router: the shell
|
|
45
|
+
does. A bar of your own passes its own `leading` and `actions`. `AppHeader` also
|
|
46
|
+
renders a `div`, where `as="header"` makes the bar the page's banner.
|
|
47
|
+
|
|
48
|
+
## `header` values and `handle.header`
|
|
49
|
+
|
|
50
|
+
**Search**: `header="center"`, `header="medium"`, `header="large"`,
|
|
51
|
+
`header: 'center'` (and `'medium'`, `'large'`), `variant:` inside a `header` object
|
|
52
|
+
or a route's `handle.header`.
|
|
53
|
+
|
|
54
|
+
| Before | After |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `'small'` | `'small'` (unchanged) |
|
|
57
|
+
| `'center'` | `{ size: 'small', align: 'center' }` |
|
|
58
|
+
| `'medium'` | `'medium-flexible'` |
|
|
59
|
+
| `'large'` | `'large-flexible'` |
|
|
60
|
+
| `'none'` | `'none'` (unchanged) |
|
|
61
|
+
| `{ variant: 'large', hideOnScroll: true }` | `{ size: 'large-flexible', hideOnScroll: true }` |
|
|
62
|
+
| (none) | `'search'`: the search field is the bar's centre |
|
|
63
|
+
|
|
64
|
+
A string in the new spelling sets the size only, so the layout's `align` stays.
|
|
65
|
+
A route's header in one spelling overrides the layout's in the other. The warning
|
|
66
|
+
is `ActivityLayout: header `medium` is deprecated; use 'medium-flexible'.`
|
|
67
|
+
([troubleshooting](../troubleshooting.md#activitylayout-header-center-medium-or-large-is-deprecated)).
|
|
68
|
+
|
|
69
|
+
`resolveHeader` and `ResolvedHeader` gain `size` and `align`; `variant` stays
|
|
70
|
+
filled with the old equivalent. `ShellHeaderVariant` is widened with the new
|
|
71
|
+
values: an exhaustive `switch` over it needs them.
|
|
72
|
+
|
|
73
|
+
## `TopAppBar` `variant` and `headline`
|
|
74
|
+
|
|
75
|
+
**Search**: `<TopAppBar variant=`, `headline=`.
|
|
76
|
+
|
|
77
|
+
| Before | After |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `variant="center"` | `size="small" align="center"` |
|
|
80
|
+
| `variant="medium"` | `size="medium-flexible"` |
|
|
81
|
+
| `variant="large"` | `size="large-flexible"` |
|
|
82
|
+
| `headline={<h1>Projects</h1>}` | `title="Projects"` (the bar renders the `<h1>`) |
|
|
83
|
+
|
|
84
|
+
`headline` rendered in a non-heading element with display type; it still does, now
|
|
85
|
+
with the bar's title styling. `data-variant` is still set (`"search"` is new), and
|
|
86
|
+
`data-size` and `data-align` are added.
|
|
87
|
+
|
|
88
|
+
## Actions, the account menu and a main action
|
|
89
|
+
|
|
90
|
+
All additive. `headerActions` (and `TopAppBar`'s `actions`) takes a
|
|
91
|
+
`TopAppBarAction[]` as well as a node: free ghost icon buttons, with the rest in
|
|
92
|
+
the account menu on the avatar. `headerPrimaryAction` (`primaryAction`) is a
|
|
93
|
+
`Button` from 768 px and a floating button on a phone. `headerContext` is now the
|
|
94
|
+
bar's subtitle, under the title. An `actions` that is a node, an array of elements
|
|
95
|
+
included, and `trailing` draw as before. See
|
|
96
|
+
[Top app bar sizes](./app-shell.md#top-app-bar-sizes) and
|
|
97
|
+
[the `TopAppBar` props](../components/navigation-and-layout.md#topappbar).
|
|
98
|
+
|
|
99
|
+
An avatar used as `trailing` next to an `actions` array of data becomes the menu's
|
|
100
|
+
trigger (a `<button>`): it must hold no link or button.
|
|
101
|
+
|
|
102
|
+
## What looks different
|
|
103
|
+
|
|
104
|
+
No code change, but snapshots of an app that renders the bar change:
|
|
105
|
+
|
|
106
|
+
- **Heights.** The headline row of a medium bar is 3 rem and a large bar's 6.5 rem
|
|
107
|
+
before it is measured (it was 5 rem and 8 rem), then follows the title's real
|
|
108
|
+
height. Medium titles are 28 px, large ones 40 px (36 px on a phone).
|
|
109
|
+
- **A flat bar.** It sits on the page ground with no shadow, border or surface
|
|
110
|
+
background (it was a translucent card). Once scrolled it takes the
|
|
111
|
+
`--surface-container` tint and a 1 px `--border` hairline (the `data-scrolled`
|
|
112
|
+
attribute). A `className` background, radius or shadow wins at rest (the
|
|
113
|
+
bar's own look is in `@layer components`); once scrolled the tint replaces a
|
|
114
|
+
`className` background, as the scrolled state's look.
|
|
115
|
+
- **A ghost menu button on a phone**, leading the bar, with no logo or brand.
|
|
116
|
+
Desktop is unchanged.
|
|
117
|
+
- **Vertical padding** sits on the bar itself, so `className="py-1"` still works.
|
|
118
|
+
- **`position`.** A `TopAppBar` is no longer `position: relative` except
|
|
119
|
+
`size="search"`, so a `sticky` class works.
|
|
120
|
+
- **The root is a column.** A standalone `TopAppBar` used to be one flex row on
|
|
121
|
+
the root; the root is now `flex-col` and its children sit in a
|
|
122
|
+
`[data-slot="top-app-bar-row"]` (a headline row and the tabs follow it). A
|
|
123
|
+
layout utility in the root's `className` (`justify-between`, `gap-*`,
|
|
124
|
+
`items-*`, a horizontal `px-*`) no longer reaches the children; aim it at the
|
|
125
|
+
row, for example `className="[&_[data-slot=top-app-bar-row]]:justify-between"`.
|
|
126
|
+
A vertical `py-*` on the root still works.
|
|
127
|
+
- **`title` is the page's heading.** On the old `TopAppBar`, `title` was the HTML
|
|
128
|
+
`title` attribute (a native tooltip). It is now the bar's own title and renders
|
|
129
|
+
an `<h1>`. To keep a tooltip, put `title` on an element you pass as a child.
|
|
130
|
+
- **The shell's bar** is the page's `<header>` (a banner landmark) instead of a
|
|
131
|
+
`<div>`. It keeps its `data-slot` names; `app-header-page-title-row` is now the
|
|
132
|
+
title block, always present around the title and the context line. A small
|
|
133
|
+
bar with `hideOnScroll` or tabs still carries `data-variant="small"`. The
|
|
134
|
+
internal `--nxgt-header-h` custom property (never documented) is gone;
|
|
135
|
+
`--nxgt-header-height` still sets the bar's height, and the first-paint total
|
|
136
|
+
`--nxgt-header-total` follows it.
|
|
137
|
+
|
|
138
|
+
## The `data-slot` rename in the next major
|
|
139
|
+
|
|
140
|
+
The shell keeps its `app-header*` `data-slot` names in this minor, so selectors
|
|
141
|
+
and tests written against them keep working; `TopAppBar`'s CSS styles both
|
|
142
|
+
families. The next major renames the slots in the table below. Update selectors then, or now with the new
|
|
143
|
+
names on a `TopAppBar` of your own:
|
|
144
|
+
|
|
145
|
+
| Today (shell) | Next major |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| `app-header` | `top-app-bar` |
|
|
148
|
+
| `app-header-page-title` | `top-app-bar-title` |
|
|
149
|
+
| `app-header-headline` | `top-app-bar-headline` |
|
|
150
|
+
| `app-header-collapsed-title` | `top-app-bar-collapsed-title` |
|
|
151
|
+
| `app-header-context` | `top-app-bar-subtitle` |
|
|
152
|
+
| `app-header-tabs` | `top-app-bar-tabs` |
|
|
153
|
+
|
|
154
|
+
The other `app-header*` slots (`app-header-title`, `-title-after`, `-back`, `-menu`) are not in this table: their next-major names are not decided yet, so do not rely on a `top-app-bar-*` equivalent.
|
|
155
|
+
|
|
156
|
+
**Search**: `app-header` in tests, CSS and `data-slot=` selectors.
|
package/docs/guides/theming.md
CHANGED
|
@@ -73,6 +73,7 @@ at the top are needed is in [getting started](../getting-started.md#styles).
|
|
|
73
73
|
| `--error-text` | `text-error-text` | error drawn as text: field messages, `HelperText` in its error state, form and dialog errors, `variant="error"` menu items |
|
|
74
74
|
| `--destructive` | `bg-destructive`, `text-destructive` | deprecated alias of `--error`: the light theme sets it to `var(--error)`, the dark theme keeps its own value; use `--error` |
|
|
75
75
|
| `--ground` | `bg-ground` | the page's ground under `ActivityLayout`: the tinted colour the cards stand on (see [Page ground](#page-ground)) |
|
|
76
|
+
| `--surface-container`, `--surface-container-high` | `bg-surface-container`, `bg-surface-container-high` | tinted chrome: `--surface-container` is the scrolled top app bar (draw it with a 1px `--border` hairline), the primary at 12 % over `--ground` in light (less for a very dark primary, solved per seed) and 26 % in dark; `--surface-container-high` is raised chrome such as a search field, the primary at 16 % over `--background` in light (+4 points over the solved share) and 34 % over `--ground` in dark. Foreground, muted foreground and primary text keep 4.5:1 or more on both, in every preset |
|
|
76
77
|
| `--card`, `--popover`, `--tooltip` (+ `-foreground`) | `bg-card`, `bg-popover`, `bg-tooltip` | surfaces |
|
|
77
78
|
| `--card-edge` | `border-card-edge` | the edge of a `Card`, a `Popover` and a `Dialog`: `var(--border)` in light, `color-mix(in oklab, white 8%, var(--card))` in dark, a hairline lighter than the surface so it lifts off `--ground` |
|
|
78
79
|
| `--border`, `--input`, `--ring` | `border-border`, `border-input`, `ring-ring` | outlines |
|
|
@@ -83,6 +84,10 @@ at the top are needed is in [getting started](../getting-started.md#styles).
|
|
|
83
84
|
| `--nxgt-cards-min`, `--nxgt-cards-gap` | set on the list or an ancestor | the narrowest a `DataTable`/`ServerTable` card is (default `15rem`) with `cardDensity="compact"`, and the gap between cards (`0.75rem`, `0.5rem` when compact): see [Cards and tiles](./cards-and-tiles.md#columns) |
|
|
84
85
|
| `--nxgt-field-radius`, `--nxgt-field-inner-radius` | `rounded-field` (and its sides, `rounded-s-field`…), `rounded-field-inner` | every field's corners, and the corner a field meets its open list with: see [The field box](#the-field-box) |
|
|
85
86
|
|
|
87
|
+
```tsx
|
|
88
|
+
<header className="bg-surface-container border-b border-border" />
|
|
89
|
+
```
|
|
90
|
+
|
|
86
91
|
Some colours are derived rather than tokens of their own:
|
|
87
92
|
`bg-background-paper` (5 % primary), `bg-paper` (0.5 % primary),
|
|
88
93
|
`bg-primary-container`, `bg-secondary-container`, `bg-tertiary-container`,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -6,12 +6,6 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
6
6
|
|
|
7
7
|
## Now
|
|
8
8
|
|
|
9
|
-
- **App shell header refresh** — `AppHeader` and the look `TopAppBar`
|
|
10
|
-
shares sit flat on the page ground and tint when content scrolls under
|
|
11
|
-
them; the actions are grouped in a pill, the search is a pill field (an
|
|
12
|
-
icon on a phone), and the menu button is a ghost icon button. The new look
|
|
13
|
-
is the default in a minor, with no API change; an A/B preview comes first
|
|
14
|
-
([#2503](https://github.com/softistx/nxgt-material/issues/2503)).
|
|
15
9
|
- **Calculator** — `@nxgt/material/calculator` is an exact-decimal calculator
|
|
16
10
|
(Standard, Scientific, point of sale, Financial, Conversion, Programmer;
|
|
17
11
|
every variant but Standard loads on demand)
|
|
@@ -386,6 +380,23 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
386
380
|
|
|
387
381
|
## Shipped
|
|
388
382
|
|
|
383
|
+
- **App shell header refresh: the TopAppBar family (next minor)** — `TopAppBar`
|
|
384
|
+
takes four sizes (`small`, `medium-flexible`, `large-flexible`, `search`), an
|
|
385
|
+
`align`, a `title` that is the page's `h1` with a `subtitle`, and a collapse
|
|
386
|
+
from large to small on scroll with a morph (snapped under reduced motion).
|
|
387
|
+
It sits flat on the page ground and tints when content scrolls under it,
|
|
388
|
+
with new surface-container tokens. Actions are data (`TopAppBarAction`):
|
|
389
|
+
free icon buttons plus an account menu on the avatar, and a `primaryAction`
|
|
390
|
+
that is a floating button on a phone. `ActivityLayout` draws its bar with it
|
|
391
|
+
(`header` / `handle.header` take the new sizes, `headerActions` takes data,
|
|
392
|
+
`headerPrimaryAction` is new, `headerContext` is the subtitle) and the
|
|
393
|
+
phone's menu button is a ghost icon leading the bar. `AppHeader` and the old
|
|
394
|
+
`variant`, `headline` and `'center'` / `'medium'` / `'large'` values are
|
|
395
|
+
deprecated, and some `app-header*` slots are renamed in the next major (see the guide)
|
|
396
|
+
([#2503](https://github.com/softistx/nxgt-material/issues/2503),
|
|
397
|
+
[guide](guides/app-shell.md#top-app-bar-sizes),
|
|
398
|
+
[moving to `TopAppBar`](guides/migrating-to-top-app-bar.md)).
|
|
399
|
+
|
|
389
400
|
- **Seven more layout recipes (next minor)** — whole screens to start from under Guides/Recipes, each a tested Storybook story with its code in the plugin's `screen-recipes` skill: a team feed, a gallery of pictures by day, sign-in, sign-up and forgotten-password screens, a messages thread, settings with sections, an overview of rearrangeable widgets and a document editor, on the layouts the shell ships ([#2413](https://github.com/softistx/nxgt-material/issues/2413)).
|
|
390
401
|
|
|
391
402
|
- **Search dialog and results page recipe (next patch)** — a command dialog (Ctrl/Cmd+K and a header button), debounced grouped suggestions, type chips, a conditional filter and highlighted result cards, with its code in the plugin's `screen-recipes` skill ([#2333](https://github.com/softistx/nxgt-material/issues/2333)).
|