@nxgt/material 3.79.1 → 3.80.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 +48 -0
- package/README.md +45 -6
- package/dist/{alert-dialog-653apk3f.js → alert-dialog-DgHtXZuB.js} +1 -1
- package/dist/{async-slice-CXLbQuOc.js → async-slice-YBQsGtQT.js} +1 -1
- package/dist/{button-3op3rtZh.js → button-_vm-xSBU.js} +1 -1
- package/dist/{calculator-KqIMBXSh.js → calculator-CTd_S23A.js} +10 -10
- package/dist/calculator-field.js +6 -6
- package/dist/{calculator-segment-BlJE1LaS.js → calculator-segment-OI1BT3bA.js} +1 -1
- package/dist/calculator.js +1 -1
- package/dist/charts.js +3 -3
- package/dist/{chip-MuKDwtkG.js → chip-DumcVzUO.js} +2 -2
- package/dist/{code-editor-Bp2RrdNx.js → code-editor-CiwgfSOK.js} +4 -4
- package/dist/code-editor.js +4 -4
- package/dist/{code-language-items-B7WR5ua_.js → code-language-items-Dip0xnmc.js} +2 -2
- package/dist/components/components.css +3 -0
- package/dist/components/ui/actions/fab/fab-dock.css +19 -6
- package/dist/components/ui/layout/app-search/app-search.css +62 -0
- package/dist/components/ui/layout/app-shell/activity-backdrop.css +10 -2
- package/dist/components/ui/layout/app-shell/app-header.css +108 -0
- package/dist/components/ui/layout/navigation-toolbar/navigation-toolbar.css +43 -0
- package/dist/{components-CTyNC_zW.js → components-CJFHhkZv.js} +21798 -17784
- package/dist/components.js +37 -37
- package/dist/{conversion-variant-BDFAxqe9.js → conversion-variant-CqrPwPjC.js} +3 -3
- package/dist/{currency-field-DWHB5oms.js → currency-field-CMFvctye.js} +4 -4
- package/dist/{dialog-Bm5LvVlB.js → dialog-B0iU3fmh.js} +3 -3
- package/dist/dnd.js +2 -2
- package/dist/{dropdown-menu-xlZ6NYUA.js → dropdown-menu-CPOgcajv.js} +1 -1
- package/dist/editor.js +7 -7
- package/dist/{empty-state-C0kviQdW.js → empty-state-D3Jggupu.js} +1 -1
- package/dist/{financial-variant-CggTpad2.js → financial-variant-BdyfYhnp.js} +5 -5
- package/dist/{hooks-Dg94jPRq.js → hooks-Z7KKbv4G.js} +2 -2
- package/dist/hooks.js +2 -2
- package/dist/{hover-card-B1g55Hi6.js → hover-card-CFGIX6kg.js} +1 -1
- package/dist/i18n.js +3 -3
- package/dist/{icon-badge-BcW66bRk.js → icon-badge-kxGWUvcO.js} +1 -1
- package/dist/{icon-button-Cogxy1cy.js → icon-button-BamxMwZs.js} +1 -1
- package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
- package/dist/lib/components/ui/layout/app-bar/top-app-bar.d.ts +18 -3
- package/dist/lib/components/ui/layout/app-search/app-search-bar.d.ts +11 -0
- package/dist/lib/components/ui/layout/app-search/app-search.types.d.ts +47 -0
- package/dist/lib/components/ui/layout/app-search/index.d.ts +3 -0
- package/dist/lib/components/ui/layout/app-search/partials/on-phone.d.ts +2 -0
- package/dist/lib/components/ui/layout/app-search/partials/phone-search.d.ts +3 -0
- package/dist/lib/components/ui/layout/app-search/partials/pill-search.d.ts +3 -0
- package/dist/lib/components/ui/layout/app-search/pill-form.d.ts +18 -0
- package/dist/lib/components/ui/layout/app-search/search-panel.d.ts +24 -0
- package/dist/lib/components/ui/layout/app-search/search-results.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-search/search-shortcut.d.ts +15 -0
- package/dist/lib/components/ui/layout/app-search/search-view.d.ts +22 -0
- package/dist/lib/components/ui/layout/app-search/use-pill-panel.d.ts +22 -0
- package/dist/lib/components/ui/layout/app-search/use-search-text.d.ts +8 -0
- package/dist/lib/components/ui/layout/app-shell/activity-app-bar.d.ts +35 -0
- package/dist/lib/components/ui/layout/app-shell/activity-chrome.d.ts +26 -3
- package/dist/lib/components/ui/layout/app-shell/activity-column-props.d.ts +22 -0
- package/dist/lib/components/ui/layout/app-shell/activity-column.d.ts +10 -2
- package/dist/lib/components/ui/layout/app-shell/activity-layout-navigation.types.d.ts +94 -0
- package/dist/lib/components/ui/layout/app-shell/activity-layout.d.ts +8 -1
- package/dist/lib/components/ui/layout/app-shell/activity-layout.types.d.ts +2 -1
- package/dist/lib/components/ui/layout/app-shell/activity-rails.d.ts +16 -0
- package/dist/lib/components/ui/layout/app-shell/activity-sidebar-lane.d.ts +22 -0
- package/dist/lib/components/ui/layout/app-shell/activity-top-nav.d.ts +11 -0
- package/dist/lib/components/ui/layout/app-shell/activity-two-level-lane.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-shell/app-back.d.ts +22 -0
- package/dist/lib/components/ui/layout/app-shell/app-header-row.d.ts +3 -0
- package/dist/lib/components/ui/layout/app-shell/app-header.d.ts +33 -1
- package/dist/lib/components/ui/layout/app-shell/app-shell.utils.d.ts +8 -0
- package/dist/lib/components/ui/layout/app-shell/app-sidebar-entries.d.ts +13 -0
- package/dist/lib/components/ui/layout/app-shell/app-sidebar-label-item.d.ts +3 -1
- package/dist/lib/components/ui/layout/app-shell/bottom-chrome.d.ts +13 -0
- package/dist/lib/components/ui/layout/app-shell/header-title.d.ts +18 -2
- package/dist/lib/components/ui/layout/app-shell/header.utils.d.ts +37 -0
- package/dist/lib/components/ui/layout/app-shell/index.d.ts +3 -0
- package/dist/lib/components/ui/layout/app-shell/navigation-parts.d.ts +38 -0
- package/dist/lib/components/ui/layout/app-shell/navigation.utils.d.ts +36 -0
- package/dist/lib/components/ui/layout/app-shell/page-title-scope.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-shell/page-title.d.ts +12 -1
- package/dist/lib/components/ui/layout/app-shell/shell-scroll.d.ts +32 -0
- package/dist/lib/components/ui/layout/app-shell/sticky-offset.d.ts +8 -0
- package/dist/lib/components/ui/layout/app-shell/types.d.ts +14 -0
- package/dist/lib/components/ui/layout/app-shell/use-focus-while-hidden.d.ts +9 -0
- package/dist/lib/components/ui/layout/app-shell/use-header-height.d.ts +12 -0
- package/dist/lib/components/ui/layout/app-shell/use-header-scroll.d.ts +19 -0
- package/dist/lib/components/ui/layout/app-shell/use-shell-header.d.ts +20 -0
- package/dist/lib/components/ui/layout/auth-card/auth-card-split.d.ts +14 -0
- package/dist/lib/components/ui/layout/auth-card/auth-card.d.ts +13 -1
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid-context.d.ts +21 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid.d.ts +9 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid.state.d.ts +30 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid.tiles.d.ts +8 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid.types.d.ts +50 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-grid.utils.d.ts +70 -0
- package/dist/lib/components/ui/layout/dashboard-grid/dashboard-tile.d.ts +7 -0
- package/dist/lib/components/ui/layout/dashboard-grid/index.d.ts +4 -0
- package/dist/lib/components/ui/layout/dashboard-grid/partials/dashboard-announcer.d.ts +6 -0
- package/dist/lib/components/ui/layout/dashboard-grid/partials/dashboard-edit-bar.d.ts +11 -0
- package/dist/lib/components/ui/layout/dashboard-grid/partials/dashboard-move-buttons.d.ts +9 -0
- package/dist/lib/components/ui/layout/dashboard-grid/partials/dashboard-toolbar.d.ts +7 -0
- package/dist/lib/components/ui/layout/dashboard-grid/use-dashboard-grid.d.ts +21 -0
- package/dist/lib/components/ui/layout/dashboard-grid/use-dashboard-moves.d.ts +22 -0
- package/dist/lib/components/ui/layout/doc/doc-context.d.ts +2 -0
- package/dist/lib/components/ui/layout/doc/doc.d.ts +5 -0
- package/dist/lib/components/ui/layout/doc/index.d.ts +1 -1
- package/dist/lib/components/ui/layout/doc/partials/doc-embedded-bar.d.ts +9 -0
- package/dist/lib/components/ui/layout/doc/partials/doc-embedded.d.ts +8 -0
- package/dist/lib/components/ui/layout/doc/use-doc.d.ts +9 -1
- package/dist/lib/components/ui/layout/editor-layout/editor-layout.d.ts +14 -0
- package/dist/lib/components/ui/layout/editor-layout/editor-layout.types.d.ts +31 -0
- package/dist/lib/components/ui/layout/editor-layout/index.d.ts +4 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/editor-layout-body.d.ts +11 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/editor-layout-canvas.d.ts +8 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/editor-layout-context.d.ts +12 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/editor-layout-start.d.ts +8 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/editor-layout-triggers.d.ts +10 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/use-editor-layout-names.d.ts +8 -0
- package/dist/lib/components/ui/layout/editor-layout/partials/use-editor-layout-state.d.ts +21 -0
- package/dist/lib/components/ui/layout/index.d.ts +9 -0
- package/dist/lib/components/ui/layout/landing/index.d.ts +6 -0
- package/dist/lib/components/ui/layout/landing/landing-layout.d.ts +15 -0
- package/dist/lib/components/ui/layout/landing/landing-layout.types.d.ts +27 -0
- package/dist/lib/components/ui/layout/landing/landing-section.d.ts +12 -0
- package/dist/lib/components/ui/layout/landing/landing-section.types.d.ts +32 -0
- package/dist/lib/components/ui/layout/landing/landing.classes.d.ts +20 -0
- package/dist/lib/components/ui/layout/landing/partials/landing-header.d.ts +11 -0
- package/dist/lib/components/ui/layout/landing/partials/landing-section-intro.d.ts +13 -0
- package/dist/lib/components/ui/layout/landing/partials/site-footer-group.d.ts +8 -0
- package/dist/lib/components/ui/layout/landing/site-footer.d.ts +13 -0
- package/dist/lib/components/ui/layout/landing/site-footer.types.d.ts +29 -0
- package/dist/lib/components/ui/layout/list-details-layout/internal.d.ts +2 -0
- package/dist/lib/components/ui/layout/list-details-layout/list-details-layout.d.ts +9 -17
- package/dist/lib/components/ui/layout/list-details-layout/partials/history-mark.d.ts +2 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-context.d.ts +17 -1
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-history.d.ts +8 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-inspector.d.ts +21 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-layout.types.d.ts +47 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-resizer.d.ts +9 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-root.d.ts +3 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/list-details-trigger.d.ts +13 -4
- package/dist/lib/components/ui/layout/list-details-layout/partials/use-inspector-focus.d.ts +8 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/use-list-details-param.d.ts +26 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/use-list-details-state.d.ts +15 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/use-list-width.d.ts +16 -0
- package/dist/lib/components/ui/layout/list-details-layout/partials/use-pane-focus.d.ts +6 -4
- package/dist/lib/components/ui/layout/navigation-bar/index.d.ts +3 -0
- package/dist/lib/components/ui/layout/navigation-bar/internal.d.ts +4 -0
- package/dist/lib/components/ui/layout/navigation-bar/navigation-bar.classes.d.ts +14 -0
- package/dist/lib/components/ui/layout/navigation-bar/navigation-bar.d.ts +35 -0
- package/dist/lib/components/ui/layout/navigation-bar/navigation-bar.utils.d.ts +19 -0
- package/dist/lib/components/ui/layout/navigation-bar/partials/bar-badge.d.ts +5 -0
- package/dist/lib/components/ui/layout/navigation-bar/partials/bar-entry.d.ts +12 -0
- package/dist/lib/components/ui/layout/navigation-bar/partials/navigation-bar-item.d.ts +22 -0
- package/dist/lib/components/ui/layout/navigation-bar/partials/navigation-bar-more.d.ts +24 -0
- package/dist/lib/components/ui/layout/navigation-bar/use-nav-bar-inset.d.ts +12 -0
- package/dist/lib/components/ui/layout/navigation-drawer/index.d.ts +5 -0
- package/dist/lib/components/ui/layout/navigation-drawer/navigation-drawer.classes.d.ts +9 -0
- package/dist/lib/components/ui/layout/navigation-drawer/navigation-drawer.d.ts +45 -0
- package/dist/lib/components/ui/layout/navigation-drawer/navigation-drawer.utils.d.ts +14 -0
- package/dist/lib/components/ui/layout/navigation-drawer/partials/navigation-drawer-body.d.ts +3 -0
- package/dist/lib/components/ui/layout/navigation-drawer/partials/navigation-drawer-item.d.ts +20 -0
- package/dist/lib/components/ui/layout/navigation-drawer/partials/navigation-drawer-modal.d.ts +17 -0
- package/dist/lib/components/ui/layout/navigation-drawer/partials/navigation-drawer-section.d.ts +15 -0
- package/dist/lib/components/ui/layout/navigation-rail/index.d.ts +3 -0
- package/dist/lib/components/ui/layout/navigation-rail/navigation-rail-panel.d.ts +26 -0
- package/dist/lib/components/ui/layout/navigation-rail/navigation-rail.classes.d.ts +23 -0
- package/dist/lib/components/ui/layout/navigation-rail/navigation-rail.d.ts +42 -1
- package/dist/lib/components/ui/layout/navigation-rail/navigation-rail.utils.d.ts +4 -0
- package/dist/lib/components/ui/layout/navigation-rail/partials/navigation-rail-body.d.ts +3 -0
- package/dist/lib/components/ui/layout/navigation-rail/partials/navigation-rail-item.d.ts +20 -0
- package/dist/lib/components/ui/layout/navigation-rail/partials/navigation-rail-panel-item.d.ts +7 -0
- package/dist/lib/components/ui/layout/navigation-rail/partials/navigation-rail-toggle.d.ts +7 -0
- package/dist/lib/components/ui/layout/navigation-rail/use-rail-expanded.d.ts +13 -0
- package/dist/lib/components/ui/layout/navigation-toolbar/index.d.ts +2 -0
- package/dist/lib/components/ui/layout/navigation-toolbar/navigation-toolbar.classes.d.ts +20 -0
- package/dist/lib/components/ui/layout/navigation-toolbar/navigation-toolbar.d.ts +51 -0
- package/dist/lib/components/ui/layout/navigation-toolbar/partials/navigation-toolbar-item.d.ts +25 -0
- package/dist/lib/components/ui/layout/navigation-toolbar/partials/navigation-toolbar-more.d.ts +3 -0
- package/dist/lib/components/ui/layout/pane-layout/internal.d.ts +3 -0
- package/dist/lib/components/ui/layout/pane-layout/pane-layout.d.ts +16 -2
- package/dist/lib/components/ui/layout/pane-layout/partials/pane-layout-classes.d.ts +7 -0
- package/dist/lib/components/ui/layout/pane-layout/partials/pane-layout-context.d.ts +13 -0
- package/dist/lib/components/ui/layout/pane-layout/partials/use-pane-layout-state.d.ts +16 -0
- package/dist/lib/components/ui/layout/pane-layout/partials/use-pane-narrow.d.ts +6 -0
- package/dist/lib/components/ui/layout/responsive-grid/index.d.ts +4 -1
- package/dist/lib/components/ui/layout/responsive-grid/responsive-grid-item.d.ts +19 -0
- package/dist/lib/components/ui/layout/responsive-grid/responsive-grid-spans.d.ts +19 -0
- package/dist/lib/components/ui/layout/responsive-grid/responsive-grid.d.ts +24 -2
- package/dist/lib/components/ui/layout/responsive-grid/responsive-grid.utils.d.ts +12 -0
- package/dist/lib/components/ui/layout/settings-layout/index.d.ts +2 -0
- package/dist/lib/components/ui/layout/settings-layout/partials/settings-link.d.ts +7 -0
- package/dist/lib/components/ui/layout/settings-layout/partials/settings-list.d.ts +11 -0
- package/dist/lib/components/ui/layout/settings-layout/partials/settings-page.d.ts +5 -0
- package/dist/lib/components/ui/layout/settings-layout/settings-layout.d.ts +10 -0
- package/dist/lib/components/ui/layout/settings-layout/settings-layout.types.d.ts +33 -0
- package/dist/lib/components/ui/layout/settings-layout/settings-layout.utils.d.ts +13 -0
- package/dist/lib/components/ui/layout/thread-layout/thread-layout-classes.d.ts +17 -0
- package/dist/lib/components/ui/layout/thread-layout/thread-layout-parts.d.ts +14 -0
- package/dist/lib/components/ui/layout/thread-layout/thread-layout-stepper.d.ts +11 -0
- package/dist/lib/components/ui/layout/thread-layout/thread-layout.d.ts +30 -3
- package/dist/lib/components/ui/layout/top-nav/index.d.ts +5 -0
- package/dist/lib/components/ui/layout/top-nav/partials/top-nav-item.d.ts +23 -0
- package/dist/lib/components/ui/layout/top-nav/partials/top-nav-menu.d.ts +22 -0
- package/dist/lib/components/ui/layout/top-nav/top-nav.classes.d.ts +10 -0
- package/dist/lib/components/ui/layout/top-nav/top-nav.d.ts +34 -0
- package/dist/lib/components/ui/layout/top-nav/top-nav.utils.d.ts +10 -0
- package/dist/lib/components/ui/widgets/kanban/index.d.ts +1 -1
- package/dist/lib/components/ui/widgets/kanban/kanban-context.d.ts +5 -2
- package/dist/lib/components/ui/widgets/kanban/kanban.d.ts +11 -2
- package/dist/lib/components/ui/widgets/kanban/kanban.slice.d.ts +32 -0
- package/dist/lib/components/ui/widgets/kanban/kanban.utils.d.ts +9 -0
- package/dist/lib/components/ui/widgets/kanban/partials/kanban-card-preview.d.ts +3 -1
- package/dist/lib/components/ui/widgets/kanban/partials/kanban-column.d.ts +6 -0
- package/dist/lib/components/ui/widgets/kanban/partials/kanban-move-to.d.ts +13 -0
- package/dist/lib/components/ui/widgets/kanban/partials/kanban-phone-tabs.d.ts +10 -0
- package/dist/lib/components/ui/widgets/kanban/types.d.ts +7 -0
- package/dist/lib/components/ui/widgets/kanban/use-kanban-board-keys.d.ts +7 -0
- package/dist/lib/components/ui/widgets/kanban/use-kanban-item-actions.d.ts +5 -0
- package/dist/lib/components/ui/widgets/kanban/use-kanban-phone-column.d.ts +18 -0
- package/dist/lib/components/ui/widgets/kanban/use-kanban.d.ts +6 -1
- package/dist/lib/i18n/resources/en/en.d.ts +50 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +52 -2
- package/dist/lib/i18n/resources/fr/fr.d.ts +50 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +52 -2
- package/dist/lib/i18n/resources/resources.d.ts +100 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/dist/main.js +52 -52
- package/dist/map.js +7 -7
- package/dist/material.css +1 -1
- package/dist/pdf-reader.js +1 -1
- package/dist/{percent-field--WIXV5dX.js → percent-field-C2LNr8NA.js} +1 -1
- package/dist/{picker-surface-CV09H7Nb.js → picker-surface-BUCFMoAZ.js} +4 -4
- package/dist/{popover-Cd7DkND4.js → popover-DFRwQF12.js} +1 -1
- package/dist/{pos-types-DKCkOTYy.js → pos-types-CXnEdjdy.js} +1 -1
- package/dist/{pos-variant-GrUfbTTP.js → pos-variant-DMwn_7is.js} +4 -4
- package/dist/print.js +1 -1
- package/dist/{programmer-variant-eKJNKENL.js → programmer-variant-Bo4eiDFi.js} +2 -2
- package/dist/{public-y6g4ddxd.js → public-CyQPkkSR.js} +9 -9
- package/dist/{rich-code-block-CRQ0iyLb.js → rich-code-block-iK7UcZdc.js} +5 -5
- package/dist/{scientific-variant-2y3UxAAU.js → scientific-variant-B9ScTgfx.js} +2 -2
- package/dist/{sortable-provider-DdiI3Fwk.js → sortable-provider-BZwVjSVU.js} +3 -3
- package/dist/{spinner-C1QIewWv.js → spinner-RITOxvpH.js} +2 -2
- package/dist/{tabs-KGKvve3y.js → tabs-DSo4eCUn.js} +1 -1
- package/dist/theme-picker.js +2 -2
- package/dist/{theme-toggle-C_VeiiCm.js → theme-toggle-3gbzQX0x.js} +1 -1
- package/dist/{toolbar-items-D310xDuM.js → toolbar-items-Bt5RK-Nx.js} +4 -4
- package/dist/{translate-material-BypJJ1l5.js → translate-material-CZTGqgen.js} +1 -1
- package/dist/{translator-DJkf4J7t.js → translator-DTlOlIoq.js} +108 -4
- package/dist/{use-chat-composer-BFhRMHcX.js → use-chat-composer-DBY01IpX.js} +16 -16
- package/dist/{use-heading-spy-DJR8YYm6.js → use-heading-spy-Dt48bBts.js} +4 -4
- package/dist/{use-material-translation-CD6QoVal.js → use-material-translation-BJucC_xe.js} +1 -1
- package/dist/{use-return-focus-Cevw_6yq.js → use-return-focus-BS1JLcnq.js} +1 -1
- package/docs/README.md +1 -0
- package/docs/components/data-display.md +4 -0
- package/docs/components/navigation-and-layout.md +944 -27
- package/docs/components/rich-widgets.md +26 -0
- package/docs/guides/app-shell.md +641 -2
- package/docs/guides/i18n.md +13 -1
- package/docs/guides/layouts.md +215 -0
- package/docs/guides/ssr.md +1 -1
- package/docs/previews/navigation-layout-appshell-page-ground.webp +0 -0
- package/docs/previews/navigation-layout-appshell.webp +0 -0
- package/docs/previews/navigation-layout-authcard-split.webp +0 -0
- package/docs/previews/navigation-layout-authcard.webp +0 -0
- package/docs/previews/navigation-layout-dashboardgrid.webp +0 -0
- package/docs/previews/navigation-layout-editorlayout.webp +0 -0
- package/docs/previews/navigation-layout-landinglayout.webp +0 -0
- package/docs/previews/navigation-layout-panelayout.webp +0 -0
- package/docs/previews/navigation-layout-settingslayout.webp +0 -0
- package/docs/previews/navigation-layout-threadlayout-pages.webp +0 -0
- package/docs/previews/navigation-layout-threadlayout.webp +0 -0
- package/docs/roadmap.md +10 -2
- package/lib/components/components.css +3 -0
- package/lib/components/ui/actions/fab/fab-dock.css +19 -6
- package/lib/components/ui/layout/app-search/app-search.css +62 -0
- package/lib/components/ui/layout/app-shell/activity-backdrop.css +10 -2
- package/lib/components/ui/layout/app-shell/app-header.css +108 -0
- package/lib/components/ui/layout/navigation-toolbar/navigation-toolbar.css +43 -0
- package/package.json +1 -1
package/docs/guides/app-shell.md
CHANGED
|
@@ -211,6 +211,8 @@ partitionMenu(items); // { content, footer }
|
|
|
211
211
|
| `align` | `'start' \| 'center'` | `'start'` | Where the collapsed rail's entries sit: right under the brand, or centred in the height below it |
|
|
212
212
|
| `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
213
|
| `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
|
+
| `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' \| 'center' \| 'medium' \| 'large' \| 'none' \| { variant, collapse?, hideOnScroll?, tabs?, search? }` | `'small'` | The app bar's size, overridable per route with `handle.header`; see [The app bar variants](#the-app-bar-variants) |
|
|
214
216
|
| `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 |
|
|
215
217
|
| `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) |
|
|
216
218
|
|
|
@@ -311,9 +313,573 @@ confirmation inside the menu) is the top layer: it takes the first Escape alone,
|
|
|
311
313
|
and the second closes the sheet. A leave confirmation raised by a followed link
|
|
312
314
|
comes after the sheet has closed: the sheet stays closed, "Stay" included.
|
|
313
315
|
|
|
316
|
+
### `navigation` and `header`
|
|
317
|
+
|
|
318
|
+
`ActivityLayout` takes two props that choose how the shell's navigation and
|
|
319
|
+
header are drawn. Both are optional, and unset they are what the shell draws
|
|
320
|
+
today: the menu sheet on a phone, the rail from `md`, a small header.
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
<ActivityLayout items={items} navigation="rail" header="small">
|
|
324
|
+
<Outlet />
|
|
325
|
+
</ActivityLayout>
|
|
326
|
+
|
|
327
|
+
// one preset per window size
|
|
328
|
+
<ActivityLayout
|
|
329
|
+
items={items}
|
|
330
|
+
navigation={{ phone: 'modal-drawer', tablet: 'rail', desktop: 'rail' }}
|
|
331
|
+
header={{ variant: 'small' }}
|
|
332
|
+
>
|
|
333
|
+
<Outlet />
|
|
334
|
+
</ActivityLayout>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
- `navigation`: a `ShellNavigation` name for every size, or an object
|
|
338
|
+
`{ phone, tablet, desktop, hideOnScroll, persistKey }`; `persistKey` is a
|
|
339
|
+
field of that object (it keeps the `'rail-expanded'` rail's, the
|
|
340
|
+
`'sidebar'`'s and the `'two-level'` panel's state); `hideOnScroll` is another
|
|
341
|
+
(`false` by default; it slides the `'floating'` toolbar away on scroll). The sizes are a phone below `md` (768px), a tablet from
|
|
342
|
+
768px to 1279px and a desktop from `xl` (1280px). A name alone applies to
|
|
343
|
+
every size, except `'sidebar'`, `'drawer'`, `'top'` and `'two-level'`, which it draws from the
|
|
344
|
+
tablet size only: the phone keeps its default navigation unless the object asks for
|
|
345
|
+
it (`{ phone: 'sidebar' }`). `'bar'` and `'floating'` are phone navigations: a
|
|
346
|
+
name alone draws them at every size, the phone included. Every name is drawn:
|
|
347
|
+
`'modal-drawer'`, `'rail'`, `'rail-expanded'`, `'drawer'`, `'sidebar'`, `'top'`,
|
|
348
|
+
`'two-level'`, `'floating'`, `'bar'` and `'none'`.
|
|
349
|
+
- `header`: `'small'`, `'center'`, `'medium'`, `'large'` or `'none'`, or
|
|
350
|
+
`{ variant, collapse, hideOnScroll, tabs, search }`. The five variants and
|
|
351
|
+
`hideOnScroll` are drawn (see [The app bar variants](#the-app-bar-variants));
|
|
352
|
+
`search` and `tabs` are drawn (see [The app bar's search](#the-app-bars-search) and
|
|
353
|
+
[Tabs under the app bar](#tabs-under-the-app-bar)). A route's `handle.back` draws a
|
|
354
|
+
back arrow ([The back arrow](#the-back-arrow)).
|
|
355
|
+
|
|
356
|
+
An object's `phone` that names a preset never drawn on a phone (`rail`, `rail-expanded`, `top`, `two-level`) resolves to the default, as a name alone does.
|
|
357
|
+
|
|
358
|
+
`resolveNavigation()` and `resolveHeader()` return the full settings for a
|
|
359
|
+
value (what the props resolve to), and `navigationClasses()` the classes that
|
|
360
|
+
show each preset only at the sizes it is configured for. `DEFAULT_NAVIGATION` is
|
|
361
|
+
the default value (`modal-drawer`, `rail`, `rail`).
|
|
362
|
+
|
|
363
|
+
`MenuItem` also accepts `children`, `group`, `bar` and `priority`. Each is read
|
|
364
|
+
by the presets that use it, and ignored by the others: `bar` and `priority`
|
|
365
|
+
choose the entries of the bottom bar **and** of the floating toolbar (the rest go
|
|
366
|
+
under « More »), `group` is read by the drawer, and `children` by the top
|
|
367
|
+
navigation, the two-level panel, the sidebar and the phone's menu sheet.
|
|
368
|
+
`footer` is read by the rail, the sidebar and the drawer (its footer), `display`
|
|
369
|
+
by the rail, the sidebar and the phone's menu sheet, and `badge` and `badgeLabel`
|
|
370
|
+
by every preset that draws entries, except on a `display: 'icon'` entry.
|
|
371
|
+
|
|
372
|
+
### The bottom bar (`navigation="bar"`)
|
|
373
|
+
|
|
374
|
+
`navigation="bar"` alone is phone-only: the bar is hidden from 768px, where the
|
|
375
|
+
default rail shows (`{ tablet: 'bar' }` keeps it there).
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
// a bar on the phone, the rail from 768px
|
|
379
|
+
<ActivityLayout
|
|
380
|
+
items={[
|
|
381
|
+
{ label: 'Home', url: '/', icon: 'house' },
|
|
382
|
+
{ label: 'Inbox', url: '/inbox', icon: 'envelope', badge: 3 },
|
|
383
|
+
{ label: 'Tasks', url: '/tasks', icon: 'check', badge: true },
|
|
384
|
+
{ label: 'Files', url: '/files', icon: 'folder' },
|
|
385
|
+
{ label: 'Settings', url: '/settings', icon: 'gear', priority: -1 },
|
|
386
|
+
]}
|
|
387
|
+
navigation={{ phone: 'bar' }}
|
|
388
|
+
>
|
|
389
|
+
<Outlet />
|
|
390
|
+
</ActivityLayout>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
The bar is a `nav` named "Navigation" (`material.app-shell.navigation`) pinned
|
|
394
|
+
to the bottom edge, clear of the home indicator. It shows 3 to 5 destinations,
|
|
395
|
+
each an icon in an indicator pill with its label always visible, `aria-current="page"`
|
|
396
|
+
on the current one and a target of 48px or more. A `badge` shows as a dot or a
|
|
397
|
+
count on the icon and is read in the link's name ("Inbox, 3 new").
|
|
398
|
+
|
|
399
|
+
- **Which entries.** Up to five fit when they all do; with more, the bar keeps
|
|
400
|
+
four and "More" takes the fifth slot. `bar: true` on some entries limits the bar to
|
|
401
|
+
them, `bar: false` keeps one off it, and `priority` (higher stays, unset is 0)
|
|
402
|
+
chooses among the rest; ties keep the menu's order. `splitBarItems(items, max)`
|
|
403
|
+
returns `{ bar, more }`.
|
|
404
|
+
- **More.** A button that opens a sheet from the bottom with the other entries
|
|
405
|
+
(`material.navigation.more`, closed by Escape, the "Close" button
|
|
406
|
+
(`material.navigation.close`) or a followed link). Focus returns to the button;
|
|
407
|
+
after a followed link it goes to the page's title as for the menu sheet. It
|
|
408
|
+
lights up when the current page is one of its entries.
|
|
409
|
+
- **Breakpoints.** The bar and the rail are both in the markup and CSS classes
|
|
410
|
+
show one per size, so a server render matches the client. A hidden bar is
|
|
411
|
+
`display: none`: out of the tab order and the accessibility tree. With the
|
|
412
|
+
bar on the phone the app bar has no menu button.
|
|
413
|
+
- **Room.** While it shows, the bar sets `--nxgt-nav-bar` (`calc(4rem + env(safe-area-inset-bottom))`,
|
|
414
|
+
the safe area included) on the document root as long as any bar shows (it stays while a second
|
|
415
|
+
bar remains), and the shell's frame clears
|
|
416
|
+
`--nxgt-bottom-chrome`; with no bar the shell's markup is unchanged.
|
|
417
|
+
|
|
418
|
+
Use it by hand with `<NavigationBar items={items} />` (needs a router context)
|
|
419
|
+
and hide it with a breakpoint class such as `md:hidden`; compose entries with
|
|
420
|
+
`<NavigationBar.Item href icon badge>Label</NavigationBar.Item>`. The variable
|
|
421
|
+
is set after mount: a server render and the first paint get the room from the
|
|
422
|
+
layout root's breakpoint class, and portals (the toaster) read the variable on
|
|
423
|
+
the document root once the effect has run. A layout without `items` draws no bar.
|
|
424
|
+
|
|
425
|
+
### The wide rail (`navigation="rail-expanded"`)
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
import { ActivityLayout, Fab, Icon } from '@nxgt/material/components';
|
|
429
|
+
|
|
430
|
+
// the wide rail from 768px, a bar on the phone
|
|
431
|
+
<ActivityLayout
|
|
432
|
+
items={items}
|
|
433
|
+
navigation={{ phone: 'bar', tablet: 'rail-expanded', persistKey: 'app-rail' }}
|
|
434
|
+
navigationFab={({ expanded }) => (
|
|
435
|
+
<Fab extended collapsed={!expanded} icon={<Icon name="plus" />} label="Compose" />
|
|
436
|
+
)}
|
|
437
|
+
>
|
|
438
|
+
<Outlet />
|
|
439
|
+
</ActivityLayout>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
`'rail'` stays the collapsed sidebar rail the shell has always drawn (it is
|
|
443
|
+
the default, so its markup does not change). `'rail-expanded'` draws
|
|
444
|
+
[`NavigationRail`](../components/navigation-and-layout.md#navigationrail)
|
|
445
|
+
instead: a `nav` named "Navigation" with the menu button, the optional FAB, a
|
|
446
|
+
link per entry (icon in an indicator pill, label, badge read in the link's
|
|
447
|
+
name) and the `footer` entries at the bottom. It starts expanded (15rem) and the
|
|
448
|
+
menu button narrows it to 5rem, labels under the icons.
|
|
449
|
+
|
|
450
|
+
- **FAB.** `navigationFab` is the screen's primary action, a node or a function
|
|
451
|
+
of `{ expanded }` to pass an extended `Fab` that folds to its icon. The other
|
|
452
|
+
presets do not draw it. `navigationFab` is drawn only by `'rail-expanded'`; the other presets ignore it.
|
|
453
|
+
- **Remembering the choice.** With `navigation.persistKey` the state is kept in
|
|
454
|
+
the browser's local storage and read after hydration, so a server render and
|
|
455
|
+
the first client render agree; without it the rail starts expanded each time.
|
|
456
|
+
- **On a phone.** A phone never draws `'rail-expanded'` (or `'rail'`): it keeps
|
|
457
|
+
its menu sheet, or `'bar'`.
|
|
458
|
+
- **Breakpoints.** Both rails and the bar are in the markup and CSS classes show
|
|
459
|
+
one per size (`display: none` elsewhere, so a hidden rail is out of the tab order
|
|
460
|
+
and the accessibility tree). A layout without `items` draws no wide rail.
|
|
461
|
+
- **Motion.** The width and the indicator ease unless the user prefers reduced
|
|
462
|
+
motion.
|
|
463
|
+
|
|
464
|
+
### The drawer and the collapsible sidebar
|
|
465
|
+
|
|
466
|
+
```tsx
|
|
467
|
+
// the phone's menu sheet, the collapsible sidebar from 768px, remembered
|
|
468
|
+
<ActivityLayout
|
|
469
|
+
items={items}
|
|
470
|
+
navigation={{ tablet: 'sidebar', desktop: 'sidebar', persistKey: 'app-nav' }}
|
|
471
|
+
>
|
|
472
|
+
<Outlet />
|
|
473
|
+
</ActivityLayout>
|
|
474
|
+
|
|
475
|
+
// the permanent drawer on a wide desktop
|
|
476
|
+
<ActivityLayout items={items} navigation={{ desktop: 'drawer' }}>
|
|
477
|
+
<Outlet />
|
|
478
|
+
</ActivityLayout>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
- **`'drawer'`** draws the standard (permanent) drawer,
|
|
482
|
+
[`NavigationDrawer`](../components/navigation-and-layout.md#navigationdrawer),
|
|
483
|
+
20rem wide, instead of the rail at that size: a `nav` named "Navigation"
|
|
484
|
+
with the entries in sections by their `group`, the `footer` entries at the
|
|
485
|
+
bottom, the brand above. The modal variant is the phone's menu sheet
|
|
486
|
+
(`'modal-drawer'`, unchanged).
|
|
487
|
+
- **`'sidebar'`** draws the shell's sidebar, collapsed to the rail of icons at
|
|
488
|
+
first. A small chevron button on its end edge, level with the brand and with
|
|
489
|
+
no row of its own, expands it (logo and name, labels beside the icons) and
|
|
490
|
+
collapses it again; it is named "Toggle sidebar", carries `aria-expanded` and
|
|
491
|
+
`aria-controls`, has a 48px hit area, and the chevron turns (unless the user
|
|
492
|
+
prefers reduced motion). The state is `sidebarExpanded` (controlled) or
|
|
493
|
+
`defaultSidebarExpanded` (`false`), reported by `onSidebarExpandedChange`.
|
|
494
|
+
With `navigation.persistKey` the user's last choice is kept in the browser's
|
|
495
|
+
local storage and read after hydration, so a server render and the first
|
|
496
|
+
client render agree; a blocked storage is ignored.
|
|
497
|
+
- Both are in the markup with the other presets and CSS classes show one per
|
|
498
|
+
size (`display: none` elsewhere, out of the tab order and the accessibility
|
|
499
|
+
tree). They need `items`; a layout without any draws no drawer. The unset
|
|
500
|
+
`navigation` still draws the collapsed rail, so existing apps are unchanged.
|
|
501
|
+
On a phone they are drawn only when asked by size (`{ phone: 'drawer' }`),
|
|
502
|
+
taking 16 to 20rem beside the content: keep the menu sheet or a bar there.
|
|
503
|
+
|
|
504
|
+
### The top navigation
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
// the brand and a bar of destinations in the app header from 768px;
|
|
508
|
+
// the phone keeps its menu sheet, with the children nested
|
|
509
|
+
<ActivityLayout
|
|
510
|
+
items={[
|
|
511
|
+
{ label: 'Home', url: '/', icon: 'house' },
|
|
512
|
+
{
|
|
513
|
+
label: 'Projects',
|
|
514
|
+
url: '/projects',
|
|
515
|
+
icon: 'folder',
|
|
516
|
+
children: [
|
|
517
|
+
{ label: 'All projects', url: '/projects/all', icon: 'folder' },
|
|
518
|
+
{ label: 'Archived', url: '/projects/archived', icon: 'box-archive' },
|
|
519
|
+
],
|
|
520
|
+
},
|
|
521
|
+
]}
|
|
522
|
+
name="Acme"
|
|
523
|
+
navigation="top"
|
|
524
|
+
>
|
|
525
|
+
<Outlet />
|
|
526
|
+
</ActivityLayout>
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
- **`'top'`** draws [`TopNav`](../components/navigation-and-layout.md#topnav)
|
|
530
|
+
in the app header, after the brand (`brand`, else `logo` and `name`: no rail
|
|
531
|
+
carries it then): a `nav` named "Navigation" of 48px pills, the current one
|
|
532
|
+
tinted with `aria-current="page"`. An entry with `children` is a button that
|
|
533
|
+
opens a dropdown of its child links; when the current page is one of them,
|
|
534
|
+
the button reads as active and the child carries `aria-current`. Arrow keys,
|
|
535
|
+
Escape and focus return follow Radix's navigation menu, and the dropdown's
|
|
536
|
+
motion is off for users who prefer reduced motion. A badge is read in the
|
|
537
|
+
link's name.
|
|
538
|
+
- On a phone the bar is not drawn, whatever the object says
|
|
539
|
+
(`{ phone: 'top' }` keeps the menu sheet): the sheet lists the entries and
|
|
540
|
+
nests each entry's `children` under it, indented. The expanded sidebar nests
|
|
541
|
+
them the same way.
|
|
542
|
+
- An entry with `children` is only a trigger: its `url` is never a link, so put an "all" link as the first child. (The phone's menu sheet and the expanded sidebar do list the
|
|
543
|
+
parent's own `url` as a link, with its children nested under it.)
|
|
544
|
+
- Past about 5 entries the bar does not fit at 768px beside the brand and the title and pushes the header's actions out; it does not scroll (that would clip the dropdowns). Use `{ tablet: 'rail', desktop: 'top' }` for a longer menu.
|
|
545
|
+
- It shows per size with CSS classes like the other presets, so the server and
|
|
546
|
+
the browser agree. It needs `items`; the `footer`, `group` and `display`
|
|
547
|
+
options are not used. The unset `navigation` is unchanged.
|
|
548
|
+
|
|
549
|
+
### The two-level navigation
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
// a rail of the top-level entries and, beside it, a panel of the current
|
|
553
|
+
// entry's children, from 768px; the phone keeps its menu sheet
|
|
554
|
+
<ActivityLayout
|
|
555
|
+
items={[
|
|
556
|
+
{ label: 'Home', url: '/', icon: 'house' },
|
|
557
|
+
{
|
|
558
|
+
label: 'Projects',
|
|
559
|
+
url: '/projects',
|
|
560
|
+
icon: 'folder',
|
|
561
|
+
children: [
|
|
562
|
+
{ label: 'Overview', url: '/projects', icon: 'folder' },
|
|
563
|
+
{ label: 'Active', url: '/projects/active', icon: 'folder' },
|
|
564
|
+
{ label: 'Archived', url: '/projects/archived', icon: 'box-archive' },
|
|
565
|
+
],
|
|
566
|
+
},
|
|
567
|
+
]}
|
|
568
|
+
navigation={{ tablet: 'two-level', desktop: 'two-level', persistKey: 'app-nav' }}
|
|
569
|
+
>
|
|
570
|
+
<Outlet />
|
|
571
|
+
</ActivityLayout>
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
- **`'two-level'`** draws [`NavigationRail`](../components/navigation-and-layout.md#navigationrail)
|
|
575
|
+
(the top-level entries, 5rem wide, no menu button of its own) and
|
|
576
|
+
[`NavigationRailPanel`](../components/navigation-and-layout.md#navigationrailpanel)
|
|
577
|
+
(14rem) side by side in one lane, bled to the frame's edges like the other
|
|
578
|
+
lanes. The app's brand tops the rail's column: `brand`, else `logo` alone (named by
|
|
579
|
+
`name`).
|
|
580
|
+
- **A rail entry always links to its own `url`**, with or without `children`:
|
|
581
|
+
following it navigates there, and the panel shows that entry's children
|
|
582
|
+
(an entry is the section the location belongs to when its `url` or one of its
|
|
583
|
+
children's matches; the most specific match wins, so a child outside the
|
|
584
|
+
parent's `url` still lights its parent). Put the section's overview at the
|
|
585
|
+
parent's `url`, and as a first child with the same `url` if you want it listed:
|
|
586
|
+
that child is marked current there.
|
|
587
|
+
- **The panel is open by default and collapsible.** Its button folds it to a
|
|
588
|
+
narrow strip and back; nothing opens it on hover, and a rail entry does not
|
|
589
|
+
reopen it. With `navigation.persistKey` the choice is remembered under
|
|
590
|
+
`nxgt-panel:<persistKey>` (the rail's `'rail-expanded'` state and the sidebar's
|
|
591
|
+
keep their own prefixes), read after hydration: the server render and the first
|
|
592
|
+
client render are open.
|
|
593
|
+
- **An entry without `children`** just navigates; the panel is hidden by CSS for
|
|
594
|
+
it (its markup stays, so the tree does not change between routes). Only one
|
|
595
|
+
level of `children` is listed.
|
|
596
|
+
- **On a phone** neither is drawn, whatever the object says
|
|
597
|
+
(`{ phone: 'two-level' }` keeps the menu sheet, as `'top'` does): the sheet lists
|
|
598
|
+
the entries and nests each one's `children`. A name alone leaves the phone its
|
|
599
|
+
default.
|
|
600
|
+
- At 768px the rail and the open panel take 19rem beside the content; fold the
|
|
601
|
+
panel or use `{ tablet: 'rail', desktop: 'two-level' }` when that is too much.
|
|
602
|
+
It needs `items` (none draws nothing); `footer` entries sit at the rail's
|
|
603
|
+
bottom, `group` and `display` are not used. The unset `navigation` is unchanged.
|
|
604
|
+
|
|
605
|
+
### The floating navigation toolbar
|
|
606
|
+
|
|
607
|
+
```tsx
|
|
608
|
+
import { ActivityLayout } from '@nxgt/material/components';
|
|
609
|
+
import { Outlet } from 'react-router';
|
|
610
|
+
|
|
611
|
+
// a floating pill on the phone, the rail from 768px, hiding while the page scrolls down
|
|
612
|
+
<ActivityLayout
|
|
613
|
+
items={[
|
|
614
|
+
{ label: 'Home', url: '/', icon: 'house' },
|
|
615
|
+
{ label: 'Inbox', url: '/inbox', icon: 'envelope', badge: 3 },
|
|
616
|
+
{ label: 'Tasks', url: '/tasks', icon: 'check' },
|
|
617
|
+
{ label: 'Files', url: '/files', icon: 'folder' },
|
|
618
|
+
{ label: 'Settings', url: '/settings', icon: 'gear', priority: -1 },
|
|
619
|
+
]}
|
|
620
|
+
navigation={{ phone: 'floating', hideOnScroll: true }}
|
|
621
|
+
>
|
|
622
|
+
<Outlet />
|
|
623
|
+
</ActivityLayout>
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
[`NavigationToolbar`](../components/navigation-and-layout.md#navigationtoolbar) is
|
|
627
|
+
a pill of round icon links at the bottom centre, over the content. It is a `nav`
|
|
628
|
+
named "Navigation" (`material.app-shell.navigation`) of links, each named by a
|
|
629
|
+
visually hidden label (and a tooltip), with `aria-current="page"` on the
|
|
630
|
+
current one: it is not a `role="toolbar"`, which is for actions (use
|
|
631
|
+
`Toolbar variant="floating"` for those). It wears the same pill as that toolbar
|
|
632
|
+
(its tokens, shadow and slide away), so a themed toolbar gives a themed pill.
|
|
633
|
+
|
|
634
|
+
- **Where it shows.** A name alone (`navigation="floating"`) draws it at every
|
|
635
|
+
size, the phone included, like `'bar'`: the pill is a bar-like phone
|
|
636
|
+
navigation, and on a phone it replaces the menu sheet, so the app bar has no
|
|
637
|
+
menu button. `{ phone: 'floating' }` limits it to the phone, `{ desktop: 'floating' }`
|
|
638
|
+
to the desktop. Pill and rail are both in the markup and breakpoint classes show
|
|
639
|
+
one per size, so a server render matches the client.
|
|
640
|
+
- **Which entries.** The same rules as the bottom bar: 3 to 5 destinations,
|
|
641
|
+
`bar`, `priority` and `splitBarItems` choose them, and with more the last slot
|
|
642
|
+
is « More » (the bar's bottom sheet, lit when the current page is under it).
|
|
643
|
+
Keep to 3-5 destinations; without a fifth slot to spare, mark the secondary
|
|
644
|
+
ones `priority: -1` so they live under « More ». No entry is lost: nothing is
|
|
645
|
+
reachable only from a hidden place.
|
|
646
|
+
- **Hide on scroll is off by default.** `navigation.hideOnScroll: true` slides the
|
|
647
|
+
pill away on the way down (past 64px, after 8px of movement) and back on the
|
|
648
|
+
way up, reading the shell's scroll ([Scroll direction](#scroll-direction)). While away it is
|
|
649
|
+
`inert` (out of the tab order and the accessibility tree), and a focus inside
|
|
650
|
+
it moves to the content region and returns to its link when the pill is back,
|
|
651
|
+
unless the user went elsewhere meanwhile. With reduced motion it snaps instead
|
|
652
|
+
of sliding. `hideOnScroll` reads no other preset; the header's own
|
|
653
|
+
`hideOnScroll` is separate. The server draws it shown.
|
|
654
|
+
- **Room.** The pill is `1rem` above the safe area; a docked media bar sits above it (the dock rests at `var(--nxgt-nav-bar)`). While
|
|
655
|
+
it shows it sets `--nxgt-nav-bar` to `calc(5rem + env(safe-area-inset-bottom))` (4rem of pill, the gap and the safe area), also
|
|
656
|
+
while slid away, so `FabDock`, the toaster, the mini player and a sticky
|
|
657
|
+
`StickyActionBar` stay above it and nothing jumps when it returns; the shell's
|
|
658
|
+
frame clears `--nxgt-bottom-chrome` as for the bar. The first paint gets the
|
|
659
|
+
value from a class on the layout root, as the bar does. The pill does not rise
|
|
660
|
+
with the on-screen keyboard: it stays at the bottom of the layout viewport.
|
|
661
|
+
- It needs `items` (none draws nothing) and a router context. Use it by hand with
|
|
662
|
+
`<NavigationToolbar items={items} />` (hide it with a breakpoint class such as
|
|
663
|
+
`md:hidden`) or compose entries with `<NavigationToolbar.Item href icon>Label</NavigationToolbar.Item>`.
|
|
664
|
+
|
|
665
|
+
### Scroll direction
|
|
666
|
+
|
|
667
|
+
`useShellScroll()` returns `{ direction, offset, reducedMotion }` for a bar
|
|
668
|
+
that hides while scrolling down: `direction` is `'down'`, `'up'` or `'none'`
|
|
669
|
+
(at the top), and flips only after 8px of movement the other way. Wrap the part
|
|
670
|
+
that reads it in `ShellScrollProvider` (it is `useScrollTracker()`, the hook
|
|
671
|
+
behind it, in a context; use `ShellScrollContext` to provide your own state); give it `container` (a ref to the
|
|
672
|
+
scrolling box) when the content region scrolls (`scroll="container"`), none for
|
|
673
|
+
the window. Outside a provider the hook is idle. `reducedMotion` is true when
|
|
674
|
+
the user asked for less motion: skip the slide and snap. The header
|
|
675
|
+
(`header.hideOnScroll`) and the floating navigation toolbar
|
|
676
|
+
(`navigation.hideOnScroll`) read it; the shell tracks the scroll only when one of
|
|
677
|
+
them asks, and `NavigationToolbar` reads it by hand too.
|
|
678
|
+
|
|
679
|
+
### The app bar variants
|
|
680
|
+
|
|
681
|
+
`header` chooses the bar's size, the way Material 3 does. Unset is `'small'`:
|
|
682
|
+
today's one row, byte for byte.
|
|
683
|
+
|
|
684
|
+
```tsx
|
|
685
|
+
import { ActivityLayout, type AppShellHandle } from '@nxgt/material/components';
|
|
686
|
+
|
|
687
|
+
<ActivityLayout items={items} header="large">
|
|
688
|
+
<Outlet />
|
|
689
|
+
</ActivityLayout>
|
|
690
|
+
|
|
691
|
+
// a route opts in, whatever the layout says
|
|
692
|
+
export const handle = { title: 'Projects', header: 'large' } satisfies AppShellHandle;
|
|
693
|
+
|
|
694
|
+
// a bar that goes away on the way down
|
|
695
|
+
<ActivityLayout items={items} header={{ variant: 'small', hideOnScroll: true }} />
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
Defaults: `variant` is `'small'`; `collapse` is `true` for `'medium'` and
|
|
699
|
+
`'large'`; `hideOnScroll` is `false`. Nothing to import beyond `styles.css`: the
|
|
700
|
+
bar's CSS ships with it.
|
|
701
|
+
|
|
702
|
+
- `'small'`: one row, the title beside the actions.
|
|
703
|
+
- `'center'`: the title centred in the room between the menu button and the
|
|
704
|
+
actions.
|
|
705
|
+
- `'medium'` and `'large'`: the page's title on a second row, in display type
|
|
706
|
+
(`large` is taller and bigger, up to two lines), under the small row. As the
|
|
707
|
+
page scrolls the headline fades and the bar shrinks into the small row, which
|
|
708
|
+
then shows the title (a copy hidden from assistive technology). `collapse:
|
|
709
|
+
false` keeps the headline however far the page scrolls.
|
|
710
|
+
- `'none'`: no bar. The screen's own `ActivityContent` title is then the page's
|
|
711
|
+
`h1`; the phone's menu button goes with the bar, so pair it with a navigation
|
|
712
|
+
that has one on its own (`navigation="bar"`).
|
|
713
|
+
- `hideOnScroll`: the bar slides away while the page scrolls down (past 64px) and
|
|
714
|
+
comes back on the way up. While away it is `inert` and out of the tab order; if
|
|
715
|
+
the focus was inside it, the focus moves to the content region.
|
|
716
|
+
|
|
717
|
+
A route gives its own through `handle.header` (a variant or the options, like
|
|
718
|
+
the prop). The deepest route that declares one wins, and its options win over
|
|
719
|
+
the layout's one by one: a route that only names a variant keeps the layout's
|
|
720
|
+
`hideOnScroll`. It is read from the matched routes, so the server and the
|
|
721
|
+
browser draw the same bar.
|
|
722
|
+
|
|
723
|
+
The headline **is** the page's one `h1` (the small row's copy is `aria-hidden`).
|
|
724
|
+
A medium or large header needs a title in the bar, a route's `handle.title`;
|
|
725
|
+
without one the bar stays small, so nothing changes for a screen that titles
|
|
726
|
+
itself with `ActivityContent`. The server always renders the bar expanded and
|
|
727
|
+
shown; the browser then follows the scroll.
|
|
728
|
+
|
|
729
|
+
The scroll is the shell's ([Scroll direction](#scroll-direction)): the window,
|
|
730
|
+
or the content region with `scroll="container"` (a hidden bar then gives its
|
|
731
|
+
room back). Once per animation frame the bar sets one CSS variable on itself,
|
|
732
|
+
`--nxgt-header-progress` (0 expanded, 1 collapsed), through `setProperty`, so
|
|
733
|
+
no inline style reaches the markup; the sizes are CSS in `app-header.css`.
|
|
734
|
+
Under reduced motion the bar snaps between the two states halfway, with no slide.
|
|
735
|
+
A plain shell, with no collapsing or hiding bar, tracks no scroll at all.
|
|
736
|
+
|
|
737
|
+
`AppHeader` takes the same as props (`variant`, `collapse`, `hideOnScroll`, the
|
|
738
|
+
`headline` node, `tabs` (a node, default none) and `back` (a `ShellBack`,
|
|
739
|
+
default none); see [Using the parts](#using-the-parts)), and so does `TopAppBar` (`variant`, `headline`) for a bar
|
|
740
|
+
of your own. Known limits: a hidden bar in a `scroll="container"` shell that is
|
|
741
|
+
barely taller than its container can flicker at the very bottom (the region
|
|
742
|
+
grows, so the scroll clamps); the scroll-driven CSS animation enhancement is not
|
|
743
|
+
used, the JavaScript path drives every browser.
|
|
744
|
+
|
|
745
|
+
### The app bar's search
|
|
746
|
+
|
|
747
|
+
`header.search` puts an `AppSearchBar` after the title: `true` for a bare one,
|
|
748
|
+
or its props. From 768px it is a pill with the results in a docked panel; on a
|
|
749
|
+
phone a search button opens a full-screen dialog (`SearchView`). Unset (the
|
|
750
|
+
default) there is no search, and the bar is the same markup as before.
|
|
751
|
+
|
|
752
|
+
```tsx
|
|
753
|
+
import { ActivityLayout } from '@nxgt/material/components';
|
|
754
|
+
|
|
755
|
+
<ActivityLayout
|
|
756
|
+
items={items}
|
|
757
|
+
header={{
|
|
758
|
+
variant: 'small',
|
|
759
|
+
search: { placeholder: 'Search projects', shortcut: '/', onSubmit: (q) => navigate(`/search?q=${q}`) },
|
|
760
|
+
}}
|
|
761
|
+
/>
|
|
762
|
+
|
|
763
|
+
// a route turns it off, or changes it, like the other options
|
|
764
|
+
export const handle = { title: 'Settings', header: { variant: 'small', search: false } };
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
The search never changes the shape of the page: the content stays mounted when
|
|
768
|
+
a route adds or drops it. A route's `search` replaces the layout's whole object
|
|
769
|
+
(its props are not merged). The props, the keyboard and the focus rules are in
|
|
770
|
+
[`AppSearchBar`](../components/navigation-and-layout.md#appsearchbar).
|
|
771
|
+
|
|
772
|
+
### Tabs under the app bar
|
|
773
|
+
|
|
774
|
+
`header.tabs` is a node, normally a `TabsNav` (route links), drawn as a 48px row
|
|
775
|
+
at the foot of the bar. It is part of the bar: under a `medium` or `large` header
|
|
776
|
+
it stays under the small row as the headline collapses, and with `hideOnScroll`
|
|
777
|
+
the bar slides away **but the tabs stay pinned at the top of the window**
|
|
778
|
+
(Material 3's behaviour for a bar with tabs: the title row goes, the tabs stay
|
|
779
|
+
within reach). Only the bar's rows are `inert` while they are away; the tabs keep
|
|
780
|
+
the focus if they had it. The default is none: no row, and the bar is the same
|
|
781
|
+
markup as before. A `'none'` header draws none.
|
|
782
|
+
|
|
783
|
+
```tsx
|
|
784
|
+
// layout.tsx: tabs on every route
|
|
785
|
+
import { ActivityLayout, type MenuItem, TabsNav, TabsNavLink } from '@nxgt/material/components';
|
|
786
|
+
|
|
787
|
+
const tabs = (
|
|
788
|
+
<TabsNav aria-label="Project sections" value="activity">
|
|
789
|
+
<TabsNavLink to="/projects/overview" value="overview">Overview</TabsNavLink>
|
|
790
|
+
<TabsNavLink to="/projects/activity" value="activity">Activity</TabsNavLink>
|
|
791
|
+
</TabsNav>
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
export function Layout({ items }: { items: MenuItem[] }) {
|
|
795
|
+
return <ActivityLayout items={items} header={{ variant: 'small', tabs }} />;
|
|
796
|
+
}
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
```tsx
|
|
800
|
+
// routes/project.tsx: tabs on this route only, or none
|
|
801
|
+
import { type AppShellHandle, TabsNav, TabsNavLink } from '@nxgt/material/components';
|
|
802
|
+
|
|
803
|
+
const projectTabs = (
|
|
804
|
+
<TabsNav aria-label="Atlas sections" value="board">
|
|
805
|
+
<TabsNavLink to="/projects/atlas/board" value="board">Board</TabsNavLink>
|
|
806
|
+
<TabsNavLink to="/projects/atlas/files" value="files">Files</TabsNavLink>
|
|
807
|
+
</TabsNav>
|
|
808
|
+
);
|
|
809
|
+
|
|
810
|
+
export const handle = {
|
|
811
|
+
title: 'Atlas',
|
|
812
|
+
header: { variant: 'small', tabs: projectTabs }, // tabs: null drops the layout's
|
|
813
|
+
} satisfies AppShellHandle;
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
The option is `header.tabs` (there is no `handle.headerTabs`): a route's `tabs`
|
|
817
|
+
replaces the layout's whole, `tabs: null` drops them for that route, and a route
|
|
818
|
+
that only names a variant keeps the layout's. The row's height is one CSS
|
|
819
|
+
variable, `--nxgt-header-tabs` (3rem, in `app-header.css`). The bar's whole
|
|
820
|
+
height (the row, a headline row and the tabs) is `--nxgt-header-total` on the
|
|
821
|
+
`ActivityLayout` root, measured with a `ResizeObserver` (worked out in CSS from
|
|
822
|
+
the variant and tabs before script runs, from `data-header="medium|large"`, set only when the bar has a headline, and `data-header-tabs` on that root); the sticky aside and `Doc` stick below it. Give the `TabsNav` an
|
|
823
|
+
`aria-label` and its `value`, as it asks; a long list scrolls sideways in its
|
|
824
|
+
own row, never the page. The content stays mounted when a route adds or drops
|
|
825
|
+
the tabs; the bar's own row is drawn again then (as it is when a route moves to or
|
|
826
|
+
from a `medium` or `large` header), so an uncontrolled search loses its text.
|
|
827
|
+
|
|
828
|
+
### The back arrow
|
|
829
|
+
|
|
830
|
+
A route's `handle.back` draws an arrow at the start of the app bar, 48px, named
|
|
831
|
+
`Back` or `Back to <label>` (`material.app-header.back`, default text "Back", and
|
|
832
|
+
`back-to`, default "Back to {label}"). It is read from the matched routes like
|
|
833
|
+
`handle.header`: the deepest route that declares one wins, and a route without it
|
|
834
|
+
has none. The type is `ShellBack`, which `AppShellHandle['back']` uses:
|
|
835
|
+
`import type { ShellBack } from '@nxgt/material/components'`.
|
|
836
|
+
|
|
837
|
+
```tsx
|
|
838
|
+
// routes/project.tsx
|
|
839
|
+
import type { AppShellHandle } from '@nxgt/material/components';
|
|
840
|
+
|
|
841
|
+
export const handle = {
|
|
842
|
+
title: 'Atlas redesign',
|
|
843
|
+
back: { to: '/projects', label: 'Projects' },
|
|
844
|
+
} satisfies AppShellHandle;
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
```tsx
|
|
848
|
+
// routes/file.tsx: history back; the page above when the visit started here
|
|
849
|
+
import type { AppShellHandle } from '@nxgt/material/components';
|
|
850
|
+
|
|
851
|
+
export const handle = { title: 'File', back: true } satisfies AppShellHandle;
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
- `{ to, label? }` is a link drawn with the shell's `linkComponent` (React
|
|
855
|
+
Router's `Link` by default), so it opens in a new tab and shows its address.
|
|
856
|
+
- `true` is a button: it goes back in the history when the visit has a previous
|
|
857
|
+
entry, and otherwise (a deep link, a reload) goes up one level of the URL, so the
|
|
858
|
+
arrow never leaves the app. It works under a router `basename`.
|
|
859
|
+
- The arrow comes first in the bar, before the top navigation and the title. On a
|
|
860
|
+
phone that has the menu sheet (the default) the menu button follows the arrow,
|
|
861
|
+
so the route is never a dead end; a phone with the bottom bar
|
|
862
|
+
(`navigation={{ phone: 'bar' }}`) has no menu button, so the arrow is first
|
|
863
|
+
and the bar navigates. From 768px the rail or sidebar stays.
|
|
864
|
+
- The arrow mirrors in right-to-left. The content stays mounted when a route adds
|
|
865
|
+
or drops it, and so does the bar's row (the menu button and the search keep their
|
|
866
|
+
state).
|
|
867
|
+
|
|
868
|
+
### Room at the bottom
|
|
869
|
+
|
|
870
|
+
`--nxgt-nav-bar` is the room of a bottom navigation bar (4rem plus the bottom
|
|
871
|
+
safe-area inset) or of the floating navigation toolbar with its gap (5rem plus
|
|
872
|
+
the inset); 0 when there is none. It already holds the safe area: a consumer
|
|
873
|
+
clears `max(env(safe-area-inset-bottom), var(--nxgt-nav-bar, 0px))` once and
|
|
874
|
+
never adds the inset again. `--nxgt-media-dock` is that of a `MediaPlayerHost`'s
|
|
875
|
+
docked bar, and `--nxgt-bottom-chrome` is the two added together (it falls back to that sum
|
|
876
|
+
when unset). `FabDock`, `Toaster`, the mini player and a sticky
|
|
877
|
+
`StickyActionBar` keep clear of them, so a bar added at the bottom never
|
|
878
|
+
covers a button.
|
|
879
|
+
|
|
314
880
|
### The app bar: a title, the actions, the account
|
|
315
881
|
|
|
316
|
-
The header reads, from the start: the phone's menu button, `headerTitle`
|
|
882
|
+
The header reads, from the start: a route's back arrow (`handle.back`), the phone's menu button, `headerTitle`
|
|
317
883
|
(the context the app is in, the active school or organisation), then
|
|
318
884
|
`headerActions` (language, notifications) and `avatar` at the end. The title
|
|
319
885
|
takes the room left and ends in an ellipsis when it does not fit, so the
|
|
@@ -1037,6 +1603,44 @@ import { ActivityContent, Alert } from '@nxgt/material/components';
|
|
|
1037
1603
|
- **Width token.** `--nxgt-aside-width` changes `asideWidth="md"` (20rem) app-wide;
|
|
1038
1604
|
any CSS length goes in `asideWidth` for one screen.
|
|
1039
1605
|
|
|
1606
|
+
## A docs page inside the shell
|
|
1607
|
+
|
|
1608
|
+
A documentation section of an app (the help, the API reference) is a `Doc`
|
|
1609
|
+
under a route of the shell, not a second page with its own top bar. Pass
|
|
1610
|
+
`chrome="embedded"`:
|
|
1611
|
+
|
|
1612
|
+
```tsx
|
|
1613
|
+
import { ActivityLayout, Doc, DocPage } from '@nxgt/material/components';
|
|
1614
|
+
|
|
1615
|
+
<ActivityLayout items={items} navigation={{ phone: 'bar' }}>
|
|
1616
|
+
<Doc chrome="embedded" items={docItems} pathname={pathname} toc={toc}>
|
|
1617
|
+
<DocPage title="Install">…</DocPage>
|
|
1618
|
+
</Doc>
|
|
1619
|
+
</ActivityLayout>
|
|
1620
|
+
```
|
|
1621
|
+
|
|
1622
|
+
- The shell's header stays the page's only bar: `Doc` draws no top bar and no
|
|
1623
|
+
reading bar, and does not take the viewport's height.
|
|
1624
|
+
- The page tree (from `md`) and the outline (from `xl`) stick under the header,
|
|
1625
|
+
at the offset `ActivityContent`'s `aside` uses, and scroll with the shell:
|
|
1626
|
+
its window, or the region of a `scroll="container"` shell.
|
|
1627
|
+
- On a phone the tree is a sheet, opened by « Browse docs » under the header
|
|
1628
|
+
(not the shell's « Menu »), together with the search and `actions`. Its list
|
|
1629
|
+
and the page clear a bottom bar or the floating toolbar (`--nxgt-bottom-chrome`).
|
|
1630
|
+
- Without `chrome` (or `chrome="standalone"`) `Doc` is what it was: it owns the
|
|
1631
|
+
page.
|
|
1632
|
+
|
|
1633
|
+
See [Doc](../components/navigation-and-layout.md#doc).
|
|
1634
|
+
|
|
1635
|
+
## A public page outside the shell
|
|
1636
|
+
|
|
1637
|
+
A landing or marketing page is not inside the app shell: it has no rail or
|
|
1638
|
+
sidebar and is read by people who are not signed in. `LandingLayout` is its
|
|
1639
|
+
frame (a top bar on `TopNav`, a drawer on a phone, `LandingSection` bands, a
|
|
1640
|
+
`SiteFooter`), and it takes the same `items` as the shell, so the links are
|
|
1641
|
+
declared once. See
|
|
1642
|
+
[LandingLayout](../components/navigation-and-layout.md#landinglayout).
|
|
1643
|
+
|
|
1040
1644
|
## Dense pages on large screens
|
|
1041
1645
|
|
|
1042
1646
|
On a 1440 or 1920 px screen a page should show more, not stretch the same four
|
|
@@ -1192,7 +1796,9 @@ export function InvoiceTrail() {
|
|
|
1192
1796
|
`AppSidebar`, `AppHeader` and `AppBreadcrumb` are exported for a layout of your
|
|
1193
1797
|
own. They take the same `items`; `AppHeader` takes `actions`, `avatar`,
|
|
1194
1798
|
`showMenuIcon` (default `true`), and `menuOpen` / `onMenuOpenChange` to control
|
|
1195
|
-
its phone menu sheet
|
|
1799
|
+
its phone menu sheet, `tabs` (a node, default none: a `TabsNav` drawn as a row
|
|
1800
|
+
at the foot of the bar) and `back` (a `ShellBack`, default none: the back arrow,
|
|
1801
|
+
before the menu button). The lower-level `Sidebar`, `TopAppBar` and
|
|
1196
1802
|
`Breadcrumb` primitives are on the
|
|
1197
1803
|
[navigation & layout](../components/navigation-and-layout.md) page.
|
|
1198
1804
|
|
|
@@ -1211,3 +1817,36 @@ render(
|
|
|
1211
1817
|
</MemoryRouter>,
|
|
1212
1818
|
);
|
|
1213
1819
|
```
|
|
1820
|
+
|
|
1821
|
+
A bar of your own with a back arrow and tabs, complete:
|
|
1822
|
+
|
|
1823
|
+
```tsx
|
|
1824
|
+
import { MemoryRouter } from 'react-router';
|
|
1825
|
+
import {
|
|
1826
|
+
AppHeader,
|
|
1827
|
+
TabsNav,
|
|
1828
|
+
TabsNavLink,
|
|
1829
|
+
type MenuItem,
|
|
1830
|
+
} from '@nxgt/material/components';
|
|
1831
|
+
|
|
1832
|
+
const items: MenuItem[] = [{ label: 'Home', url: '/', icon: 'house' }];
|
|
1833
|
+
|
|
1834
|
+
export function ProjectBar() {
|
|
1835
|
+
return (
|
|
1836
|
+
<MemoryRouter initialEntries={['/projects/activity']}>
|
|
1837
|
+
<AppHeader
|
|
1838
|
+
items={items}
|
|
1839
|
+
back={{ to: '/projects', label: 'Projects' }}
|
|
1840
|
+
tabs={
|
|
1841
|
+
<TabsNav aria-label="Project sections" value="activity">
|
|
1842
|
+
<TabsNavLink to="/projects/overview" value="overview">Overview</TabsNavLink>
|
|
1843
|
+
<TabsNavLink to="/projects/activity" value="activity">Activity</TabsNavLink>
|
|
1844
|
+
</TabsNav>
|
|
1845
|
+
}
|
|
1846
|
+
>
|
|
1847
|
+
<h1>Atlas redesign</h1>
|
|
1848
|
+
</AppHeader>
|
|
1849
|
+
</MemoryRouter>
|
|
1850
|
+
);
|
|
1851
|
+
}
|
|
1852
|
+
```
|