@nxgt/material 3.4.0 → 3.5.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.
@@ -81,6 +81,7 @@ phone's menu sheet pad clear of `env(safe-area-inset-*)`, as classes; see the
81
81
  | `titleAs` | `'h1'` … `'h6'` \| `'div'` | `'h1'` | `ActivityContent`: the title's heading level |
82
82
  | `inset` | `boolean` | `false` | `ActivityContent`: pads the content 1rem on each side. Off, it lines up with the app bar and the cards |
83
83
  | `align` | `'start' \| 'center'` | `'start'` | `ActivityLayout`, `AppSidebar`: the collapsed rail's entries sit right under the brand, or `'center'` for centred in the height below it |
84
+ | `backdrop` | `ReactNode` | — | `ActivityLayout`: a decorative background behind the frame, in place of the gradient and its blobs: a `Background` preset from `@nxgt/material/backgrounds`. Rendered in an `inert`, `aria-hidden` layer that fills the layout. See [Use a background preset behind the shell](../guides/app-shell.md#use-a-background-preset-behind-the-shell) |
84
85
  | `routeTransition` | `boolean \| Omit<ViewTransitionProps, 'children' \| 'ref'>` | `true` | `ActivityLayout`: React's `<ViewTransition>` around the content region, so a navigation cross-fades it. `false` renders none (your app has its own boundary); an object passes `default` / `update` classes, `name`, callbacks through. See [Route transitions](../guides/app-shell.md#route-transitions) |
85
86
 
86
87
  The active entry is the longest match across the whole menu, segment-aware.
@@ -191,6 +191,7 @@ partitionMenu(items); // { content, footer }
191
191
  | `align` | `'start' \| 'center'` | `'start'` | Where the collapsed rail's entries sit: right under the brand, or centred in the height below it |
192
192
  | `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 |
193
193
  | `onMenuOpenChange` | `(open: boolean) => void` | — | Called for every change of the sheet: the menu button, Escape, the close button, a followed link, a new location |
194
+ | `backdrop` | `ReactNode` | — | A decorative background drawn behind the frame in place of the built-in gradient and blobs: usually a `Background` preset from `@nxgt/material/backgrounds` (see [Use a background preset behind the shell](#use-a-background-preset-behind-the-shell)) |
194
195
 
195
196
  On a page with `viewport-fit=cover` (an installed PWA drawing under a
196
197
  notch and the home indicator), the shell pads clear of
@@ -483,6 +484,52 @@ while the sheet is open, so leave ids out of it. A link in `brand` (a home
483
484
  link around the logo) is the sheet's first focusable element, so it takes
484
485
  the focus when the sheet opens.
485
486
 
487
+ ## Use a background preset behind the shell
488
+
489
+ The shell draws the gradient with three blurred blobs behind its frame. To use
490
+ one of the 44 presets of `@nxgt/material/backgrounds` instead, pass it as
491
+ `backdrop`:
492
+
493
+ ```tsx
494
+ import { Outlet } from 'react-router';
495
+ import { ActivityLayout, type MenuItem } from '@nxgt/material/components';
496
+ import { Background, MOTIF_SHAPES_ALL } from '@nxgt/material/backgrounds';
497
+ import '@nxgt/material/backgrounds.css'; // or one preset's backgrounds/<preset>.css
498
+
499
+ export function Shell({ items }: { items: MenuItem[] }) {
500
+ return (
501
+ <ActivityLayout
502
+ items={items}
503
+ backdrop={<Background preset="shapes" motif={{ shapes: MOTIF_SHAPES_ALL }} />}
504
+ >
505
+ <Outlet />
506
+ </ActivityLayout>
507
+ );
508
+ }
509
+ ```
510
+
511
+ - **It replaces the gradient.** While `backdrop` is given the layout's root
512
+ carries `data-backdrop`, and the built-in gradient (its tint and three blobs) is not drawn (plain
513
+ CSS, no inline `style`). Without it the markup and the look are what they
514
+ were; `null`, `undefined` and `false` count as none.
515
+ - **It sits behind everything.** The node is wrapped in a layer
516
+ (`[data-slot="activity-layout-backdrop"]`) that fills the layout, under the
517
+ sidebar, the header and the content. The layer is `inert`, `aria-hidden="true"`
518
+ and takes no pointer, so the preset is decoration only: put nothing
519
+ interactive in it.
520
+ - **It fills the layout.** A `Background` in the layer is sized to the layer,
521
+ not to `100lvw × 100lvh`, so you need no `className` or `fill`. In
522
+ `scroll="document"` the layout grows with the content, and so does the preset.
523
+ - **Readable by design.** The frame keeps `bg-background-paper` and the sidebar
524
+ and header their `bg-background/40`, so the content reads over a busy preset.
525
+ Tone it down with the preset's `intensity` (`subtle`) rather than by
526
+ restyling the frame.
527
+ - **The stylesheet is yours to import.** `@nxgt/material/backgrounds` is a
528
+ separate entry, so `ActivityLayout` never pulls it in: import it where you
529
+ build the `backdrop`, and its `backgrounds.css` once.
530
+ - The `--nxgt-bg-blob-1..3` variables recolour the built-in blobs only; the
531
+ `blobs` preset reads them too.
532
+
486
533
  ## Route transitions
487
534
 
488
535
  `ActivityLayout` wraps its content region (`data-slot="activity-content-region"`)
@@ -296,12 +296,18 @@ you can select on:
296
296
  The gradient ends on `--nxgt-bg-cp`, not `--nxgt-bg-c2`: to recolour it, set
297
297
  `--nxgt-bg-cp` too.
298
298
 
299
+ ## Behind the app shell
300
+
301
+ `ActivityLayout` takes a preset as its `backdrop`, replacing the gradient and
302
+ its blobs: `backdrop={<Background preset="shapes" motif={{ shapes: MOTIF_SHAPES_ALL }} />}`.
303
+ See [Use a background preset behind the shell](./app-shell.md#use-a-background-preset-behind-the-shell).
304
+
299
305
  ## Recolour the blobs
300
306
 
301
307
  The gradient's three blobs have a public API: `--nxgt-bg-blob-1`, `--nxgt-bg-blob-2` and `--nxgt-bg-blob-3`.
302
308
  Each takes any colour. Unset, a blob keeps the tone's gradient, so adding the
303
309
  variables changes nothing until you set one. The `blobs` preset reads the same variables. `ActivityLayout` draws the same
304
- blobs, so set them on `[data-slot="activity-layout"]`:
310
+ blobs (unless it has a `backdrop`), so set them on `[data-slot="activity-layout"]`:
305
311
 
306
312
  ```css
307
313
  [data-slot="activity-layout"] {
@@ -58,6 +58,7 @@ words in your error.
58
58
  - [My activity content lost its side padding, or the rail's entries moved up](#my-activity-content-lost-its-side-padding-or-the-rails-entries-moved-up)
59
59
  - [axe reports `target-size` on a control under a form's sticky actions](#axe-reports-target-size-on-a-control-under-a-forms-sticky-actions)
60
60
  - [`color-contrast` fails over the background blobs on phone](#color-contrast-fails-over-the-background-blobs-on-phone)
61
+ - [`ActivityLayout`'s `backdrop` shows nothing, or the blobs are still there](#activitylayouts-backdrop-shows-nothing-or-the-blobs-are-still-there)
61
62
  - [Shaped Gallery tiles are plain rounded squares](#shaped-gallery-tiles-are-plain-rounded-squares)
62
63
  - [A component with my own tone (Shape, Fab, Avatar, StatCard, a metric card) shows no colour, or `tone` is a type error](#a-component-with-my-own-tone-shape-fab-avatar-statcard-a-metric-card-shows-no-colour-or-tone-is-a-type-error)
63
64
  - [A test expects the old `bg-muted` Avatar fallback, or a filled fallback shows a grey ring](#a-test-expects-the-old-bg-muted-avatar-fallback-or-a-filled-fallback-shows-a-grey-ring)
@@ -1254,6 +1255,23 @@ reports "needs review", not a failure), and delete the `[data-layer]` rules:
1254
1255
  }
1255
1256
  ```
1256
1257
 
1258
+ ### `ActivityLayout`'s `backdrop` shows nothing, or the blobs are still there
1259
+
1260
+ **When:** `<ActivityLayout backdrop={<Background preset="shapes" />}>` draws
1261
+ no shapes, or draws the gradient's blobs behind them.
1262
+ **Why:** the presets' CSS is not in `styles.css`, it is its own opt-in file, so
1263
+ without it the preset's layers have no look. The blobs are hidden by CSS keyed
1264
+ on `data-backdrop` in `styles.css`; they stay when the `Background` you pass
1265
+ comes from `@nxgt/material/components` (the gradient alone) and so draws its own
1266
+ blobs, or when the page loads a copy of `styles.css` older than 3.5.
1267
+ **Fix:** import `Background` from `@nxgt/material/backgrounds`, import
1268
+ `@nxgt/material/backgrounds.css` once, and keep `@nxgt/material` current.
1269
+
1270
+ ```tsx
1271
+ import { Background } from '@nxgt/material/backgrounds';
1272
+ import '@nxgt/material/backgrounds.css';
1273
+ ```
1274
+
1257
1275
  ### A ResponsiveButton no longer shows its tooltip next to its visible label
1258
1276
 
1259
1277
  **When:** a `ResponsiveButton` with a `tooltip` on a desktop width (768 px and up, or `expanded`), where the tooltip used to appear beside the label.
@@ -56,6 +56,7 @@
56
56
  @import "./ui/actions/button-group/button-group.css";
57
57
  /* ActivityLayout: the route transition (cross-fade, none under reduced motion). */
58
58
  @import "./ui/layout/app-shell/route-transition.css";
59
+ @import "./ui/layout/app-shell/activity-backdrop.css";
59
60
  /* DataTable cards and tiles: the item shell (hairline, tint, start bar, columns by the list's width). */
60
61
  @import "./ui/collections/data-table/data-table-items.css";
61
62
  @import "./ui/collections/data-table/data-table-items-compact.css";
@@ -0,0 +1,24 @@
1
+ /* ActivityLayout's `backdrop` prop: a node (a `Background` preset from
2
+ * `@nxgt/material/backgrounds`) drawn behind the frame instead of the built-in
3
+ * gradient. `data-backdrop` is on the layout's root only while one is given, so
4
+ * without it nothing here matches and the gradient is unchanged.
5
+ *
6
+ * Plain CSS, no inline `style`, in `@layer components` like the rest: an app's
7
+ * utilities still win. The layer itself (`data-slot="activity-layout-backdrop"`)
8
+ * is positioned by classes in activity-layout.tsx. */
9
+ @layer components {
10
+ /* The gradient's own tint and blobs give way to the backdrop. */
11
+ [data-slot="activity-layout"][data-backdrop] {
12
+ background-image: none;
13
+ }
14
+ [data-slot="activity-layout"][data-backdrop] > [data-layer] {
15
+ display: none;
16
+ }
17
+
18
+ /* A preset fills the layer: the layer's size, not `100lvw x 100lvh`, which
19
+ * counts the scrollbar and a phone's toolbar. */
20
+ [data-slot="activity-layout-backdrop"] > [data-background] {
21
+ width: 100%;
22
+ height: 100%;
23
+ }
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/material",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"