@nxgt/material 3.3.0 → 3.4.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +3 -3
  3. package/dist/backgrounds/backgrounds.css +30 -1
  4. package/dist/backgrounds/css-react/blobs.css +65 -0
  5. package/dist/backgrounds/css-react/bubbles.css +41 -0
  6. package/dist/backgrounds/css-react/checker.css +47 -0
  7. package/dist/backgrounds/css-react/chevrons.css +46 -0
  8. package/dist/backgrounds/css-react/circuit.css +111 -0
  9. package/dist/backgrounds/css-react/concrete.css +41 -0
  10. package/dist/backgrounds/css-react/diagonal-checker.css +48 -0
  11. package/dist/backgrounds/css-react/glass.css +99 -0
  12. package/dist/backgrounds/css-react/graph-paper.css +74 -0
  13. package/dist/backgrounds/css-react/halo.css +66 -0
  14. package/dist/backgrounds/css-react/hexagons.css +79 -0
  15. package/dist/backgrounds/css-react/illustrated.css +164 -0
  16. package/dist/backgrounds/css-react/leaves.css +41 -0
  17. package/dist/backgrounds/css-react/linen.css +44 -0
  18. package/dist/backgrounds/css-react/marble.css +55 -0
  19. package/dist/backgrounds/css-react/music.css +2 -0
  20. package/dist/backgrounds/css-react/night-sky.css +41 -0
  21. package/dist/backgrounds/css-react/paper.css +49 -0
  22. package/dist/backgrounds/css-react/plasma.css +53 -0
  23. package/dist/backgrounds/css-react/rays.css +67 -0
  24. package/dist/backgrounds/css-react/ripples.css +68 -0
  25. package/dist/backgrounds/css-react/school.css +2 -0
  26. package/dist/backgrounds/css-react/science.css +2 -0
  27. package/dist/backgrounds/css-react/sport.css +2 -0
  28. package/dist/backgrounds/css-react/travel.css +2 -0
  29. package/dist/backgrounds.js +57 -33
  30. package/dist/lib/backgrounds/background/available.d.ts +3 -3
  31. package/dist/lib/backgrounds/background/background.d.ts +2 -2
  32. package/dist/lib/backgrounds/index.d.ts +1 -1
  33. package/dist/material.css +1 -1
  34. package/docs/components/navigation-and-layout.md +1 -1
  35. package/docs/getting-started.md +1 -1
  36. package/docs/guides/backgrounds.md +94 -16
  37. package/docs/previews/backgrounds-geometry-more.webp +0 -0
  38. package/docs/previews/backgrounds-illustrated-scenes.webp +0 -0
  39. package/docs/previews/backgrounds-light-more.webp +0 -0
  40. package/docs/previews/backgrounds-material-more.webp +0 -0
  41. package/docs/previews/backgrounds-matrix.webp +0 -0
  42. package/docs/previews/backgrounds-motif-shapes.webp +0 -0
  43. package/docs/roadmap.md +16 -4
  44. package/docs/troubleshooting.md +2 -2
  45. package/lib/backgrounds/backgrounds.css +30 -1
  46. package/lib/backgrounds/css-react/blobs.css +65 -0
  47. package/lib/backgrounds/css-react/bubbles.css +41 -0
  48. package/lib/backgrounds/css-react/checker.css +47 -0
  49. package/lib/backgrounds/css-react/chevrons.css +46 -0
  50. package/lib/backgrounds/css-react/circuit.css +111 -0
  51. package/lib/backgrounds/css-react/concrete.css +41 -0
  52. package/lib/backgrounds/css-react/diagonal-checker.css +48 -0
  53. package/lib/backgrounds/css-react/glass.css +99 -0
  54. package/lib/backgrounds/css-react/graph-paper.css +74 -0
  55. package/lib/backgrounds/css-react/halo.css +66 -0
  56. package/lib/backgrounds/css-react/hexagons.css +79 -0
  57. package/lib/backgrounds/css-react/illustrated.css +164 -0
  58. package/lib/backgrounds/css-react/leaves.css +41 -0
  59. package/lib/backgrounds/css-react/linen.css +44 -0
  60. package/lib/backgrounds/css-react/marble.css +55 -0
  61. package/lib/backgrounds/css-react/music.css +2 -0
  62. package/lib/backgrounds/css-react/night-sky.css +41 -0
  63. package/lib/backgrounds/css-react/paper.css +49 -0
  64. package/lib/backgrounds/css-react/plasma.css +53 -0
  65. package/lib/backgrounds/css-react/rays.css +67 -0
  66. package/lib/backgrounds/css-react/ripples.css +68 -0
  67. package/lib/backgrounds/css-react/school.css +2 -0
  68. package/lib/backgrounds/css-react/science.css +2 -0
  69. package/lib/backgrounds/css-react/sport.css +2 -0
  70. package/lib/backgrounds/css-react/travel.css +2 -0
  71. package/package.json +103 -2
@@ -741,7 +741,7 @@ import { Background, Card } from '@nxgt/material/components';
741
741
  It fills the viewport; pass a `className` such as `h-96 w-full` to use it as a band.
742
742
  It is plain CSS from `styles.css`, with no inline `style`, and its colours lift
743
743
  in dark. `ActivityLayout` and `ThreadLayout` sit on it. The superset with `grain`,
744
- `seed`, `fill`, `motif` and the other presets (light, geometry and motif families) is `Background` from `/backgrounds`; see the [backgrounds guide](../guides/backgrounds.md). Light presets there: `mesh`, `aurora`, `spotlight`, `bokeh`, `grain`; geometry: `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`; motifs: `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons`.
744
+ `seed`, `fill`, `motif` and the other presets (light, geometry and motif families) is `Background` from `/backgrounds`; see the [backgrounds guide](../guides/backgrounds.md). Light presets there: `mesh`, `aurora`, `spotlight`, `bokeh`, `rays`, `halo`, `plasma`, `glass`, `ripples`, `blobs`, `paper`, `linen`, `concrete`, `marble`, `grain`; geometry: `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`, `hexagons`, `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`; motifs: `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons`, `school`, `night-sky`, `bubbles`, `leaves`, `science`, `music`, `travel`, `sport`.
745
745
 
746
746
  **Storybook:** `Navigation & layout/Background` · **Vue:** `Background`
747
747
 
@@ -139,7 +139,7 @@ and need nothing.
139
139
  | `@nxgt/material/editor/viewer` | `RichTextViewer`: shows a saved document (HTML, JSON or Markdown) read-only. **Server-safe**: no editor instance, no `'use client'` ([RichTextViewer](components/rich-widgets.md#richtextviewer)) |
140
140
  | `@nxgt/material/editor/collab` | `collaboration()`: several people editing one `DocumentEditor` through a Yjs document and provider your app supplies. Needs `yjs` and `y-protocols` ([Collaboration](components/rich-widgets.md#collaboration)) |
141
141
  | `@nxgt/material/editor/pm` | The editor's own tiptap and ProseMirror classes (`Extension`, `Node`, `Plugin`, `PluginKey`, `TextSelection`, `ProseMirrorNode`, `Fragment`, `DecorationSet`, …) for a custom feature's extensions, so `instanceof` agrees with the editor. Shares the editor's code; **server-safe** ([A custom feature](components/rich-widgets.md#a-custom-feature)) |
142
- | `@nxgt/material/backgrounds` | Background presets: `Background` (a superset of the `/components` one: `preset` (twenty ids, `AVAILABLE_BACKGROUND_PRESETS`), `tone`, `intensity`, `animated`, `grain`, `seed`, `fill` and `motif` (`shapes`, `density`, `size`, `rotate`, `shapeFill`, `opacitySpread`)), and the types and tables re-exported from `@nxgt/material-core/backgrounds`. **Its own entry**, with an opt-in stylesheet ([backgrounds](guides/backgrounds.md)) |
142
+ | `@nxgt/material/backgrounds` | Background presets: `Background` (a superset of the `/components` one: `preset` (44 ids, `AVAILABLE_BACKGROUND_PRESETS`), `tone`, `intensity`, `animated`, `grain`, `seed`, `fill` and `motif` (`shapes`, `density`, `size`, `rotate`, `shapeFill`, `opacitySpread`)), and the types and tables re-exported from `@nxgt/material-core/backgrounds`. **Its own entry**, with an opt-in stylesheet ([backgrounds](guides/backgrounds.md)) |
143
143
  | `@nxgt/material/media-hls` | `hlsStreaming()`: the HLS adapter for `MediaPlayer`, `hls.js` loaded lazily ([streaming](guides/media-streaming.md)) |
144
144
  | `@nxgt/material/vite` | Build-time helper for consumers: `pdfkitStandardFonts()` ([printing](guides/printing.md#bundling-print-into-an-ssr-server)) |
145
145
  | `@nxgt/material/hooks` | `useTheme`, `useIsClient`, `useIsMobile`, `useLocalizedDate`, … ([helpers](guides/helpers.md#nxgtmaterialhooks)) |
@@ -7,7 +7,7 @@ preset family and shares its tones, its intensities and its CSS with
7
7
  that gradient. There, `Background` is a superset of the `/components` one under
8
8
  the same name (same props, plus the preset ones); it draws every preset: the
9
9
  gradient and the grain, the light family (`mesh`, `aurora`, `spotlight`,
10
- `bokeh`), the [geometry family](#geometry-presets) and the
10
+ `bokeh`, `rays`, `halo`, `plasma`, `glass`, `ripples`, `blobs`, then the textures `paper`, `linen`, `concrete`, `marble`), the [geometry family](#geometry-presets) and the
11
11
  [motif presets](#motif-presets).
12
12
 
13
13
  ## Tone and intensity
@@ -45,7 +45,7 @@ import '@nxgt/material/backgrounds.css';
45
45
 
46
46
  | Prop | Values | Default |
47
47
  | --- | --- | --- |
48
- | `preset` | `gradient`, `grain`, `mesh`, `aurora`, `spotlight`, `bokeh`, `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`, `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons` (`AVAILABLE_BACKGROUND_PRESETS`, the ids this library draws); any other id draws the gradient and warns outside production | `gradient` |
48
+ | `preset` | `gradient`, `grain`, `mesh`, `aurora`, `spotlight`, `bokeh`, `rays`, `halo`, `plasma`, `glass`, `ripples`, `blobs`, `paper`, `linen`, `concrete`, `marble`, `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`, `hexagons`, `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`, `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons`, `school`, `night-sky`, `bubbles`, `leaves`, `science`, `music`, `travel`, `sport` (`AVAILABLE_BACKGROUND_PRESETS`, the ids this library draws); any other id draws the gradient and warns outside production | `gradient` |
49
49
  | `tone`, `intensity` | as above | `primary`, `default` |
50
50
  | `animated` | `boolean`: drifts the layers, see Motion | `false` |
51
51
  | `grain` | `boolean`: film noise over the preset; needs `grain.css` | `false` |
@@ -53,11 +53,11 @@ import '@nxgt/material/backgrounds.css';
53
53
  | `motif` | a `MotifOptions` object (`shapes`, `density`, `size`, `rotate`, `shapeFill`, `opacitySpread`), see [Motif presets](#motif-presets) | all fields optional |
54
54
  | `fill` | `viewport` (the viewport's size) or `container` (its parent's size: the parent needs a definite height) | `viewport` |
55
55
 
56
- `BACKGROUND_PRESETS` is the table of all twenty presets with their family and
56
+ `BACKGROUND_PRESETS` is the table of all 44 presets with their family and
57
57
  kind; `AVAILABLE_BACKGROUND_PRESETS` lists the ids this library draws (all
58
- twenty; `SHIPPED_BACKGROUND_PRESETS` is the common floor every library draws).
58
+ 44; `SHIPPED_BACKGROUND_PRESETS` is the common floor every library draws).
59
59
 
60
- <img src="../previews/backgrounds-matrix.webp" width="640" alt="The twenty presets, each in a card with its name">
60
+ <img src="../previews/backgrounds-matrix.webp" width="640" alt="The 44 presets, each in a card with its name">
61
61
 
62
62
  The root states `preset`, `tone`, `intensity`, `animated`, `grain` and `fill` as
63
63
  `data-*` attributes (`data-animated` and `data-grain` are empty attributes), and
@@ -78,10 +78,12 @@ markup, and nothing is random or measured.
78
78
 
79
79
  <img src="../previews/backgrounds-light.webp" width="480" alt="The mesh preset behind a card">
80
80
 
81
- Soft colour, no geometry. All four read the tone's three colours, so they follow
81
+ Soft colour, no geometry. All of them read the tone's three colours, so they follow
82
82
  `tone`, `intensity` and the theme; `animated` is opt-in and never runs under
83
83
  reduced motion. Their CSS is `mesh.css`, `aurora.css`, `spotlight.css` and
84
- `bokeh.css`.
84
+ `bokeh.css`; the six after `bokeh` (`rays`, `halo`, `plasma`, `glass`, `ripples`,
85
+ `blobs`) are drawn by `@nxgt/material` only, from `@nxgt/material/backgrounds.css` or
86
+ one file such as `@nxgt/material/backgrounds/plasma.css`.
85
87
 
86
88
  | `preset` | What it draws | Notes |
87
89
  | --- | --- | --- |
@@ -89,18 +91,51 @@ reduced motion. Their CSS is `mesh.css`, `aurora.css`, `spotlight.css` and
89
91
  | `aurora` | four blurred, wavy veils with thin vertical rays | SVG scene; fixed geometry; adds light (`screen`) in dark; `animated` sways the veils |
90
92
  | `spotlight` | a cone of light from the top with six beams and a glow | SVG scene; fixed geometry; `animated` swings the beams |
91
93
  | `bokeh` | 26 blurred discs with a brighter rim | SVG scene; `seed` moves the discs; `animated` makes them bob |
94
+ | `rays` | a sunburst: alternating rays from the top centre, faded with distance | CSS only (a conic gradient); adds light in dark; `animated` turns the burst slowly |
95
+ | `halo` | a ring of light through the tone's three colours | CSS only (a conic gradient cut to a ring); adds light in dark; `animated` turns the colours round the ring |
96
+ | `plasma` | a soft colour field: blurred discs whose tone and strength follow two value-noise fields | SVG scene; `seed` redraws the field; `animated` drifts it |
97
+ | `glass` | frosted panes over blurred colour blobs | SVG scene; a background has no backdrop to blur, so the frost is faked (blurred blobs under pale panes with a bright edge); `seed` moves the blobs and the panes' edges; `animated` drifts the blobs behind the panes |
98
+ | `ripples` | rings spreading from three seeded centres, one tone colour each, fading outward | SVG scene; `seed` moves the centres; `animated` makes each set of rings breathe |
99
+ | `blobs` | seven soft organic blobs in the tone's colours | SVG scene (smooth seeded paths, slightly blurred); `--nxgt-bg-blob-1..3` recolour the blobs (unset, the tone's colours); `seed` redraws them; `animated` drifts each at its own pace |
92
100
 
93
101
  ```tsx
94
- <Background preset="aurora" tone="mixed" intensity="subtle" className="h-96 w-full">
102
+ import '@nxgt/material/backgrounds/plasma.css'; // or backgrounds.css for every preset
103
+
104
+ <Background preset="plasma" tone="mixed" intensity="subtle" seed={3} className="h-96 w-full">
95
105
  ...
96
106
  </Background>
97
107
  ```
98
108
 
109
+
110
+ ### The textures
111
+
112
+ <img src="../previews/backgrounds-material-more.webp" width="480" alt="The paper, linen, concrete and marble textures behind a card">
113
+
114
+ `paper`, `linen`, `concrete` and `marble` are discreet page textures: a wash of the
115
+ tone (a warm cream for `paper`, a cool grey for `concrete`) under a fine pattern of
116
+ specks that is black in light and white in dark (like the grain). They are made to sit
117
+ under body text: the specks stay faint. `subtle` softens them, and `vivid` is capped:
118
+ it draws as the default (`intensity` never goes above normal for these four), so body
119
+ text keeps at least 6:1 over the darkest pixel and 8:1 over the darkest 1% in light and dark. They are still:
120
+ `animated` adds nothing. Seeded: `seed` moves the fibres,
121
+ the mottle, the slubs and the veins. React only, like the six before them
122
+ (`@nxgt/material/backgrounds/paper.css`, `linen.css`, `concrete.css`, `marble.css`).
123
+
124
+ | `preset` | What it draws | Notes |
125
+ | --- | --- | --- |
126
+ | `paper` | fibre grain on a warm tint that the tone cools or warms | SVG scene in screen pixels, a 400 px seamless tile of `feTurbulence`; the cream goes in dark |
127
+ | `linen` | a plain weave: 1 px threads every 4 px, with faint slubs | the weave sits on whole pixels, so it is crisp at 1x and has no moire; the slubs are a 960 px `feTurbulence` tile (large, so no grid of blocks shows) |
128
+ | `concrete` | a soft mottle and small pores on a cool grey | a 640 px `feTurbulence` tile of three layers (mottle, pores, tooth); a little fainter in dark |
129
+ | `marble` | a cloudy body and soft veins, very low in contrast | a faint 960 px cloud tile, and smooth seeded vein curves with a halo (geometry, not cut noise, so it never bands) |
130
+
131
+ The noise runs once per tile and the browser repeats it, so the cost does not grow with
132
+ the page (a full-page filter would).
133
+
99
134
  ## Geometry presets
100
135
 
101
136
  <img src="../previews/backgrounds-geometry.webp" width="480" alt="The isometric preset behind a card">
102
137
 
103
- Seven presets draw regular patterns and structures. All of them take `tone`,
138
+ Thirteen presets draw regular patterns and structures. The six after `waves` (`hexagons`, `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`) are drawn by `@nxgt/material` only: their CSS sits in `css-react/`, which `@nxgt/material-vue` does not have (it draws `gradient` and `grain`). All of them take `tone`,
104
139
  `intensity` and `animated`; the CSS is the one file per preset (or
105
140
  `backgrounds.css`).
106
141
 
@@ -122,13 +157,19 @@ import '@nxgt/material/backgrounds/isometric.css';
122
157
  | `low-poly` | SVG mosaic of 208 triangular facets lit by a raking light | yes | the facets breathe | `low-poly.css` |
123
158
  | `topography` | SVG contour lines (marching squares) of a seeded height field, every fifth curve heavier | yes | the map floats | `topography.css` |
124
159
  | `waves` | SVG: five stacked wavy bands along the bottom, each with a bright crest | no | the bands slide, each at its own speed | `waves.css` |
160
+ | `hexagons` | SVG: a honeycomb (one `<pattern>` of cell edges, each edge drawn once) with a seeded tenth of its cells tinted in the tone's three colours | yes (which cells light up) | the tinted cells pulse, out of step | `hexagons.css` |
161
+ | `circuit` | SVG: a printed circuit board, with chips, pins, traces that bend by 45 degrees and end in a pad, all on a 20 unit grid and never crossing | yes (chips and traces) | a bright dash runs along a dozen of the traces | `circuit.css` |
162
+ | `graph-paper` | CSS soft squared grid in the tone's colour: thin pale lines every 20 px, every fifth (100 px) barely stronger, fading out toward the edges, with fine line doodles (set square, compass, ruler, plotted curve, arrow, star) drawn in an SVG near the edges | yes (the doodles) | the grid pans by one major cell | `graph-paper.css` |
163
+ | `checker` | SVG: a fine checkerboard in two close tints of the tone, with no tint layer over it, fading out toward the edges; about one cell in eight near the edges carries a small motif shape | yes (which cells carry a motif) | the board and its motifs drift slowly | `checker.css` |
164
+ | `diagonal-checker` | SVG: the fine checkerboard turned 45 degrees (its size follows the viewport), one `<pattern>` of a diamond and its corner triangles, fading out toward the edges, with the same motifs on some cells | yes (which cells carry a motif) | the field and its motifs drift slowly | `diagonal-checker.css` |
165
+ | `chevrons` | SVG: four large, very pale chevron bands leaning across the frame, sized by the viewport, with small motif shapes along them | yes (where the motifs sit) | the bands drift slowly down and back (the motifs with them) | `chevrons.css` |
125
166
 
126
167
  The SVG ones are drawn by `@nxgt/material-core/backgrounds`
127
168
  (`buildBackgroundScene`; the CSS-only ones have no scene). Their colours are classes of the stylesheet, never a
128
169
  `style` attribute: `low-poly` colours each facet with two classes (`lp-t0..8`,
129
170
  the base colour, and `lp-s0..6`, its shade) that the stylesheet resolves in the
130
171
  tone's colours. At the defaults the heaviest geometry scene is `topography`, about 80 KB
131
- of path data; `low-poly` is about 20 KB (210 nodes).
172
+ of path data; `low-poly` is about 20 KB (210 nodes); `circuit` about 9 KB (90 nodes), `hexagons` about 6 KB, `graph-paper` about 7 KB, `chevrons` about 16 KB, `checker` about 20 KB (91 nodes) and `diagonal-checker` about 23 KB (125 nodes); `dots` and `stripes` are under 1 KB.
132
173
 
133
174
  ## Motif presets
134
175
 
@@ -154,13 +195,21 @@ browser, and a new `seed` redraws it.
154
195
 
155
196
  | Field | Values | Default | Read by |
156
197
  | --- | --- | --- | --- |
157
- | `shapes` | any of `MOTIF_SHAPES`: `circle`, `ring`, `square`, `triangle`, `plus`, `line`, `arc`; none chosen draws circles | all of them | `shapes`, `confetti-grid`, `halftone`, `truchet`, `floating` (`halftone` takes `circle`, else the first of `square`, `ring`, `plus`; `truchet` draws diagonals for `line` without `arc`; `floating` turns `circle`/`triangle` into blobs, `ring`/`arc` into rings, `square` into squircles and ignores `plus`/`line`) |
158
- | `density` | `low`, `default`, `high`: how many items | `default` | all seven |
159
- | `size` | `small`, `mixed`, `large` | `mixed` | all seven |
160
- | `rotate` | `boolean`: turns the items | `false` | `shapes`, `confetti-grid`, `scatter-icons` (tilts up to 35 degrees) |
198
+ | `shapes` | any of `MOTIF_SHAPES_ALL`: `circle`, `ring`, `square`, `triangle`, `plus`, `line`, `arc`, then `star`, `heart`, `hexagon`, `diamond`, `wave`, `zigzag`, `spiral`, then the Material 3 Expressive ones `m3-cookie-6`, `m3-cookie-9`, `m3-flower`, `m3-clover-4`, `m3-soft-burst`, `m3-sunny`, `m3-gem`, `m3-puffy`; none chosen draws circles | `MOTIF_SHAPES`: the first seven | `shapes`, `confetti-grid`, `halftone`, `truchet`, `floating` (`halftone` takes `circle`, else the first of `square`, `ring`, `plus`; `truchet` draws diagonals for `line` without `arc`; `floating` turns `circle`/`triangle` into blobs, `ring`/`arc` into rings, `square` into squircles and ignores `plus`/`line`; `shapes` and `confetti-grid` are the only presets that draw the added shapes, the others ignore them) |
199
+ | `density` | `low`, `default`, `high`: how many items | `default` | all fifteen |
200
+ | `size` | `small`, `mixed`, `large` | `mixed` | all fifteen |
201
+ | `rotate` | `boolean`: turns the items | `false` | `shapes`, `confetti-grid`, `scatter-icons` (tilts up to 35 degrees), the illustrated scenes (up to 35 degrees instead of 8) |
161
202
  | `shapeFill` | `filled`, `outline`, `mixed` | `mixed` | `shapes`, `confetti-grid`, `halftone`, `floating` |
162
203
  | `opacitySpread` | `uniform`, `varied` | `varied` | all but `halftone` |
163
204
 
205
+ `MOTIF_SHAPES` (the default) stays the first seven; pass `shapes: MOTIF_SHAPES_ALL`, or a hand-picked list such as `['star', 'm3-flower', 'wave']`, for the rest. In `shapes` and `confetti-grid` the 15 added shapes are drawn once per scene as a repeated pattern, so their tone, fill and (in `confetti-grid`) turn and size are fixed per shape; the first seven behave as before, item by item. The Storybook story `Backgrounds/Motif shapes/ShapeCatalogue` draws every shape filled and outlined.
206
+
207
+ <img src="../previews/backgrounds-motif-shapes.webp" width="480" alt="The 22 motif shapes, each filled and outlined">
208
+
209
+ ```tsx
210
+ <Background preset="shapes" motif={{ shapes: ['star', 'm3-flower', 'wave'] }} />
211
+ ```
212
+
164
213
  A field a preset does not read is ignored. `rotate` defaults to `false`: motifs stay upright
165
214
  unless you turn them on. A new `motif` object with the same values redraws nothing.
166
215
 
@@ -181,6 +230,35 @@ stops under `prefers-reduced-motion` or while the page is hidden. The drift is c
181
230
  CSS: `backgrounds/motifs.css` (shared by the seven) plus `shapes.css`, `confetti-grid.css`,
182
231
  `halftone.css`, `truchet.css`, `constellation.css`, `floating.css` and `scatter-icons.css` (the last two share `drift.css`); each preset's file imports `motifs.css`, so one alone works. `constellation` is about 34 KB of markup at the defaults and 59 KB at `motif.density: 'high'`, `scatter-icons` 18 and 31 KB (438 elements), `floating` under 8 KB.
183
232
 
233
+ ### Illustrated scenes
234
+
235
+ <img src="../previews/backgrounds-illustrated-scenes.webp" width="480" alt="An illustrated scene behind a card">
236
+
237
+ `school`, `night-sky`, `bubbles`, `leaves`, `science`, `music`, `travel` and `sport` are the motif family's
238
+ themed line art: fine strokes (round caps, about 1.5 px at 1440 px wide) of one theme each, drawn in the tone's
239
+ three colours, seeded so the placement never tiles. They are thicker with drawings toward the edges and calm
240
+ around the content: the drawings thin out and fade toward the middle of the frame, which a mask keeps nearly empty
241
+ for your content. They follow `tone`, `intensity` (the stroke opacity, with `vivid` capped at the default so body text stays readable) and the theme, and read `density`, `size`,
242
+ `opacitySpread` and `rotate` from `motif`: a drawing is tilted up to 8 degrees, up to 35 with `rotate`. They are still
243
+ by default.
244
+
245
+ | Preset | Draws | With `animated` |
246
+ | --- | --- | --- |
247
+ | `school` | pencils, open books, rulers, a graduation cap, notebooks, set squares, a magnifier, an apple | still |
248
+ | `night-sky` | a crescent moon, stars, clouds, a ringed planet, shooting stars, constellations | the stars twinkle (14 to 24 s) |
249
+ | `bubbles` | soap bubbles with a glint, drops, ripples | the bubbles rise and sink back (14 to 24 s a leg) |
250
+ | `leaves` | leaves, a fern, an acorn | the leaves sway (14 to 24 s a leg) |
251
+ | `science` | flasks, an atom, a bulb, a test tube, a molecule, a graph | still |
252
+ | `music` | notes, a treble clef, a staff, a drum, a metronome, headphones, a record | still |
253
+ | `travel` | a paper plane, a pin, a suitcase, a globe, mountains, a sun, a balloon, a camera, a compass | still |
254
+ | `sport` | balls, a racket, a trophy, a dumbbell, a medal, a stopwatch, a flag, a target | still |
255
+
256
+ Each is about 14 to 16 KB of markup at the defaults and 24 to 28 KB at `density: 'high'`. The motion is
257
+ classes (a pace `p1..p3`, a delay `l1..l4`), so it needs no inline style under a strict CSP, and it stops under
258
+ `prefers-reduced-motion` or while the page is hidden. CSS: `backgrounds/illustrated.css` (shared, imported by each
259
+ preset's file) plus `school.css`, `night-sky.css`, `bubbles.css`, `leaves.css`, `science.css`, `music.css`,
260
+ `travel.css` and `sport.css`; one alone works. React only: `@nxgt/material-vue` does not draw them.
261
+
184
262
  ## Dark mode
185
263
 
186
264
  In dark the drawn colours are lifted to a lightness floor: the dark `--primary` is as dim as the light one, which made the
@@ -222,7 +300,7 @@ The gradient ends on `--nxgt-bg-cp`, not `--nxgt-bg-c2`: to recolour it, set
222
300
 
223
301
  The gradient's three blobs have a public API: `--nxgt-bg-blob-1`, `--nxgt-bg-blob-2` and `--nxgt-bg-blob-3`.
224
302
  Each takes any colour. Unset, a blob keeps the tone's gradient, so adding the
225
- variables changes nothing until you set one. `ActivityLayout` draws the same
303
+ variables changes nothing until you set one. The `blobs` preset reads the same variables. `ActivityLayout` draws the same
226
304
  blobs, so set them on `[data-slot="activity-layout"]`:
227
305
 
228
306
  ```css
@@ -249,7 +327,7 @@ else is opt-in, because CSS cannot be tree-shaken. `animated` on the
249
327
  ```css
250
328
  @import "@nxgt/material/backgrounds.css"; /* every opt-in file */
251
329
  /* or just the one you use: */
252
- @import "@nxgt/material/backgrounds/aurora.css"; /* a preset file, named after the preset (aurora.css, low-poly.css, scatter-icons.css…) */
330
+ @import "@nxgt/material/backgrounds/aurora.css"; /* a preset file, named after the preset (aurora.css, low-poly.css, hexagons.css, scatter-icons.css…) */
253
331
  @import "@nxgt/material/backgrounds/grain.css"; /* the grain overlay, over any preset */
254
332
  @import "@nxgt/material/backgrounds/halftone.css"; /* a motif preset (brings motifs.css) */
255
333
  @import "@nxgt/material/backgrounds/floating.css"; /* brings motifs.css and drift.css */
package/docs/roadmap.md CHANGED
@@ -185,10 +185,6 @@ version they shipped in, and planned entries may name the major they target.
185
185
  it. Needs a spike first: sonner pauses its own timer on hover and focus and
186
186
  does not expose the time left, so the bar would run beside it.
187
187
 
188
- - **`Background` blobs in a tone's colour** — the background presets drawing
189
- their blobs from the tone channel, so an app tone colours them. Not
190
- decided yet.
191
-
192
188
  - **`CountryField` single mode takes only the field's own props** —
193
189
  `CountryFieldProps` narrows to what single mode reads (`label`,
194
190
  `helperText`, `error`, `required`, `disabled`, `name`, `id`, `className`,
@@ -274,6 +270,22 @@ version they shipped in, and planned entries may name the major they target.
274
270
 
275
271
  ## Shipped
276
272
 
273
+ - **44 `Background` presets, and 22 motif shapes** — `Background` from
274
+ `@nxgt/material/backgrounds` draws six light presets (`rays`, `halo`,
275
+ `plasma`, `glass`, `ripples`, `blobs`), six geometry presets (`hexagons`,
276
+ `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`), four
277
+ textures discreet enough under body text (`paper`, `linen`, `concrete`,
278
+ `marble`) and eight illustrated line-art scenes (`school`, `night-sky`,
279
+ `bubbles`, `leaves`, `science`, `music`, `travel`, `sport`), beside the
280
+ existing ones. The motif shapes grow from seven to 22 (`MOTIF_SHAPES_ALL`:
281
+ `star`, `heart`, `hexagon`, `diamond`, `wave`, `zigzag`, `spiral` and eight
282
+ Material 3 Expressive shapes such as `m3-flower`); the default stays the
283
+ first seven, so existing backgrounds draw as before. The textures and the
284
+ scenes cap `vivid` at the default intensity so body text stays readable.
285
+ Every preset follows `tone`, `intensity` and the theme, is seeded where
286
+ random, and moves only with `animated`. React only. 3.4.0.
287
+ ([Backgrounds guide](guides/backgrounds.md))
288
+
277
289
  - **Tailwind 4 animation API** — `animate-*` classes in `styles.css`, pure CSS
278
290
  and completed by Tailwind IntelliSense, with the Material 3 Expressive
279
291
  springs and durations by default: entrances and exits (fade, slide, scale,
@@ -6702,13 +6702,13 @@ How the presets work is in the [Backgrounds guide](guides/backgrounds.md).
6702
6702
  ### `Background: preset "<id>" is not available in this library yet; drawing "gradient".`
6703
6703
 
6704
6704
  **When:** in development (not when `NODE_ENV` is `production`), the first time a `Background` from `@nxgt/material/backgrounds` gets a `preset` that this library does not draw yet, or a typo from JavaScript. It is printed once per id.
6705
- **Why:** `BACKGROUND_PRESETS` lists the twenty presets; this library draws the ones in `AVAILABLE_BACKGROUND_PRESETS`. Any other id draws the gradient.
6705
+ **Why:** `BACKGROUND_PRESETS` lists the 44 presets; this library draws the ones in `AVAILABLE_BACKGROUND_PRESETS`. Any other id draws the gradient.
6706
6706
  **Fix:** use an available preset:
6707
6707
 
6708
6708
  ```ts
6709
6709
  import { AVAILABLE_BACKGROUND_PRESETS } from '@nxgt/material/backgrounds';
6710
6710
 
6711
- console.log(AVAILABLE_BACKGROUND_PRESETS); // all twenty ids: 'gradient', 'grain', 'mesh', 'aurora', …, 'scatter-icons'
6711
+ console.log(AVAILABLE_BACKGROUND_PRESETS); // all 44 ids: 'gradient', 'grain', 'mesh', 'aurora', …, 'sport'
6712
6712
  ```
6713
6713
 
6714
6714
  ### A preset `Background` looks bare, with no error
@@ -1,5 +1,6 @@
1
1
  /* Every background preset's CSS, opt-in: `import "@nxgt/material/backgrounds.css"`
2
- * (the same file in @nxgt/material-vue). Not part of styles.css, which carries
2
+ * (Vue's copy imports only the shared `css/` presets; `css-react/` is React
3
+ * only). Not part of styles.css, which carries
3
4
  * only the base, the gradient and the motion `Background` (from /components)
4
5
  * needs. One preset alone: `@nxgt/material/backgrounds/<preset>.css`. */
5
6
  @import "./css/base.css";
@@ -20,6 +21,34 @@
20
21
  @import "./css/low-poly.css";
21
22
  @import "./css/topography.css";
22
23
  @import "./css/waves.css";
24
+ /* geometry, React only (css-react/: not in scripts/shared-paths.ts, so no Vue copy) */
25
+ @import "./css-react/hexagons.css";
26
+ @import "./css-react/circuit.css";
27
+ @import "./css-react/graph-paper.css";
28
+ @import "./css-react/checker.css";
29
+ @import "./css-react/diagonal-checker.css";
30
+ @import "./css-react/chevrons.css";
31
+ /* light, more (React only) */
32
+ @import "./css-react/rays.css";
33
+ @import "./css-react/halo.css";
34
+ @import "./css-react/plasma.css";
35
+ @import "./css-react/glass.css";
36
+ @import "./css-react/ripples.css";
37
+ @import "./css-react/blobs.css";
38
+ /* textures (React only) */
39
+ @import "./css-react/paper.css";
40
+ @import "./css-react/linen.css";
41
+ @import "./css-react/concrete.css";
42
+ @import "./css-react/marble.css";
43
+ /* illustrated scenes (React only) */
44
+ @import "./css-react/school.css";
45
+ @import "./css-react/night-sky.css";
46
+ @import "./css-react/bubbles.css";
47
+ @import "./css-react/leaves.css";
48
+ @import "./css-react/science.css";
49
+ @import "./css-react/music.css";
50
+ @import "./css-react/travel.css";
51
+ @import "./css-react/sport.css";
23
52
  /* motifs */
24
53
  @import "./css/motifs.css";
25
54
  @import "./css/shapes.css";
@@ -0,0 +1,65 @@
1
+ /* The `blobs` preset: soft organic blobs in the tone's colours. A seeded SVG
2
+ * of smooth shapes in c1, c2 and c3 (`bl1..3`), slightly blurred, over a tint
3
+ * (`wash`). Blended with the page: it adds light in dark. Motion (opt-in,
4
+ * `animated`): each blob drifts at its own pace (`bd1..3`). React only:
5
+ * nothing in the shared `css/` folder. `--nxgt-bg-blob-1..3` recolour the blobs
6
+ * as they do the gradient's; unset, a blob keeps `--nxgt-bg-c1..c3`. */
7
+ @import "../css/scene.css";
8
+
9
+ @layer components {
10
+ [data-background="blobs"] {
11
+ isolation: isolate;
12
+ }
13
+ [data-background="blobs"] > [data-layer="wash"] {
14
+ position: absolute;
15
+ inset: 0;
16
+ background-image: linear-gradient(
17
+ 200deg,
18
+ color-mix(in oklab, var(--nxgt-bg-c2) var(--nxgt-bg-a1), transparent),
19
+ transparent 70%
20
+ );
21
+ }
22
+ [data-background="blobs"] > [data-scene] > svg {
23
+ mix-blend-mode: var(--nxgt-bg-glow-blend);
24
+ }
25
+ [data-background="blobs"] > [data-scene] .bl {
26
+ fill-opacity: calc(var(--nxgt-bg-op) * 0.42);
27
+ }
28
+ [data-background="blobs"] > [data-scene] .bl1 {
29
+ fill: var(--nxgt-bg-blob-1, var(--nxgt-bg-c1));
30
+ }
31
+ [data-background="blobs"] > [data-scene] .bl2 {
32
+ fill: var(--nxgt-bg-blob-2, var(--nxgt-bg-c2));
33
+ }
34
+ [data-background="blobs"] > [data-scene] .bl3 {
35
+ fill: var(--nxgt-bg-blob-3, var(--nxgt-bg-c3));
36
+ }
37
+ }
38
+
39
+ @media (prefers-reduced-motion: no-preference) {
40
+ @keyframes nxgt-bg-blobs-drift {
41
+ from {
42
+ transform: translate(-30px, 18px);
43
+ }
44
+ to {
45
+ transform: translate(34px, -26px);
46
+ }
47
+ }
48
+
49
+ @layer components {
50
+ [data-background="blobs"][data-animated] > [data-scene] .bl-g {
51
+ animation: nxgt-bg-blobs-drift 19s ease-in-out infinite alternate
52
+ var(--nxgt-bg-play, running);
53
+ }
54
+ [data-background="blobs"][data-animated] > [data-scene] .bd1 {
55
+ animation-direction: alternate;
56
+ }
57
+ [data-background="blobs"][data-animated] > [data-scene] .bd2 {
58
+ animation-duration: 26s;
59
+ animation-direction: alternate-reverse;
60
+ }
61
+ [data-background="blobs"][data-animated] > [data-scene] .bd3 {
62
+ animation-duration: 33s;
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,41 @@
1
+ /* The `bubbles` preset: line drawings of one theme (see illustrated.css).
2
+ * Motion (opt-in, `animated`): a bubble rises and sinks back, 14 to 24 s a leg. The builder sets
3
+ * the pace (`p1..p3`) and the delay (`l1..l4`) as classes, so the markup holds
4
+ * no inline style. */
5
+ @import "./illustrated.css";
6
+
7
+ @media (prefers-reduced-motion: no-preference) {
8
+ @keyframes nxgt-bg-bubbles-up {
9
+ to {
10
+ translate: 0 -46px;
11
+ }
12
+ }
13
+
14
+ @layer components {
15
+ [data-background="bubbles"][data-animated] > [data-scene] .up {
16
+ animation: nxgt-bg-bubbles-up 14s ease-in-out infinite alternate
17
+ var(--nxgt-bg-play, running);
18
+ }
19
+ [data-background="bubbles"][data-animated] > [data-scene] .p1 {
20
+ animation-duration: 14s;
21
+ }
22
+ [data-background="bubbles"][data-animated] > [data-scene] .p2 {
23
+ animation-duration: 19s;
24
+ }
25
+ [data-background="bubbles"][data-animated] > [data-scene] .p3 {
26
+ animation-duration: 24s;
27
+ }
28
+ [data-background="bubbles"][data-animated] > [data-scene] .l1 {
29
+ animation-delay: 0s;
30
+ }
31
+ [data-background="bubbles"][data-animated] > [data-scene] .l2 {
32
+ animation-delay: -3s;
33
+ }
34
+ [data-background="bubbles"][data-animated] > [data-scene] .l3 {
35
+ animation-delay: -7s;
36
+ }
37
+ [data-background="bubbles"][data-animated] > [data-scene] .l4 {
38
+ animation-delay: -11s;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,47 @@
1
+ /* The `checker` preset: a fine checkerboard of 24 unit cells in two tints of
2
+ * the tone that sit close together, fading out toward the edges (stronger in
3
+ * dark, as the isometric: `--nxgt-bg-iso-k`), with a seeded eighth of the cells
4
+ * near the edges carrying a small tonal motif. One layer, the SVG scene
5
+ * (`ck-a`, `ck-b` the cells, `ck-m` the motifs), with nothing over it; the
6
+ * scene covers the background, so the cells follow the viewport. For the
7
+ * diagonal one, see `diagonal-checker.css`. React only: nothing in the shared
8
+ * `css/` folder. */
9
+ @import "../css/scene.css";
10
+
11
+ @layer components {
12
+ [data-background="checker"] > [data-scene] .fade-1 {
13
+ stop-color: white;
14
+ }
15
+ [data-background="checker"] > [data-scene] .fade-0 {
16
+ stop-color: black;
17
+ }
18
+ [data-background="checker"] > [data-scene] .ck-a {
19
+ fill: var(--nxgt-bg-c1);
20
+ fill-opacity: calc(var(--nxgt-bg-op) * 0.14 * var(--nxgt-bg-iso-k));
21
+ }
22
+ [data-background="checker"] > [data-scene] .ck-b {
23
+ fill: var(--nxgt-bg-c2);
24
+ fill-opacity: calc(var(--nxgt-bg-op) * 0.07 * var(--nxgt-bg-iso-k));
25
+ }
26
+ [data-background="checker"] > [data-scene] .ck-m,
27
+ [data-background="checker"] > [data-scene] .ck-p {
28
+ color: var(--nxgt-bg-c1);
29
+ stroke-opacity: 0.85;
30
+ fill-opacity: calc(0.4 * var(--nxgt-bg-iso-k));
31
+ }
32
+ }
33
+
34
+ @media (prefers-reduced-motion: no-preference) {
35
+ @keyframes nxgt-bg-checker-drift {
36
+ to {
37
+ transform: translate(24px, 24px);
38
+ }
39
+ }
40
+
41
+ @layer components {
42
+ [data-background="checker"][data-animated] > [data-scene] .ck-drift {
43
+ animation: nxgt-bg-checker-drift 22s ease-in-out infinite alternate
44
+ var(--nxgt-bg-play, running);
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,46 @@
1
+ /* The `chevrons` preset: a few large, very pale chevron bands leaning across
2
+ * the frame, c1 and c2 in turn, over a faint tint. Layers: `wash` (a tint) and
3
+ * the SVG scene (`ch-a`, `ch-b` the bands, in the group `ch-field`). The SVG
4
+ * covers the background, so the bands are sized by the viewport. `animated`
5
+ * drifts the group slowly down and back. `ch-m`: small motifs along the bands. React only: nothing in the shared
6
+ * `css/` folder. */
7
+ @import "../css/scene.css";
8
+
9
+ @layer components {
10
+ [data-background="chevrons"] > [data-layer="wash"] {
11
+ position: absolute;
12
+ inset: 0;
13
+ background-image: linear-gradient(
14
+ 0deg,
15
+ color-mix(in oklab, var(--nxgt-bg-c1) var(--nxgt-bg-a1), transparent),
16
+ transparent 65%
17
+ );
18
+ }
19
+ [data-background="chevrons"] > [data-scene] .ch-a {
20
+ fill: var(--nxgt-bg-c1);
21
+ fill-opacity: calc(var(--nxgt-bg-op) * 0.16);
22
+ }
23
+ [data-background="chevrons"] > [data-scene] .ch-b {
24
+ fill: var(--nxgt-bg-c2);
25
+ fill-opacity: calc(var(--nxgt-bg-op) * 0.12);
26
+ }
27
+ [data-background="chevrons"] > [data-scene] .ch-m {
28
+ color: var(--nxgt-bg-c1);
29
+ fill-opacity: 0.55;
30
+ }
31
+ }
32
+
33
+ @media (prefers-reduced-motion: no-preference) {
34
+ @keyframes nxgt-bg-chevrons-drift {
35
+ to {
36
+ transform: translateY(40px);
37
+ }
38
+ }
39
+
40
+ @layer components {
41
+ [data-background="chevrons"][data-animated] > [data-scene] .ch-field {
42
+ animation: nxgt-bg-chevrons-drift 18s ease-in-out infinite alternate
43
+ var(--nxgt-bg-play, running);
44
+ }
45
+ }
46
+ }