@maggioli-design-system/magma-react 2.2.0 → 2.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.
- package/AGENTS.md +25 -10
- package/CHANGELOG.md +715 -0
- package/agents/anti-patterns.md +7 -4
- package/agents/assets.md +231 -28
- package/agents/color.md +7 -5
- package/agents/components.md +5 -4
- package/agents/conventions.md +16 -0
- package/agents/install.md +11 -5
- package/agents/reporting.md +11 -2
- package/agents/theming.md +15 -0
- package/dist/components.js +1 -0
- package/dist/components.server.js +1 -0
- package/dist/mds-input-date-range.server.js +1 -0
- package/dist/mds-input-date.server.js +1 -0
- package/dist/mds-input-select.server.js +1 -0
- package/dist/mds-input.server.js +1 -0
- package/dist/mds-table-footer.server.js +1 -1
- package/dist/mds-table-header-cell.js +1 -1
- package/dist/mds-table-header-cell.server.js +1 -0
- package/dist/mds-table.server.js +2 -1
- package/dist/mds-toast-region.js +12 -0
- package/dist/mds-toast-region.server.js +15 -0
- package/dist/mds-toast.server.js +2 -1
- package/dist/mds-tooltip.server.js +1 -0
- package/dist/mds-usage.server.js +2 -1
- package/dist/types/components.d.ts +1 -0
- package/dist/types/components.server.d.ts +1 -0
- package/dist/types/mds-table-header-cell.d.ts +5 -2
- package/dist/types/mds-table-header-cell.server.d.ts +5 -2
- package/dist/types/mds-toast-region.d.ts +9 -0
- package/dist/types/mds-toast-region.server.d.ts +11 -0
- package/dist/types/mds-toast.d.ts +2 -2
- package/dist/types/mds-toast.server.d.ts +2 -2
- package/package.json +6 -4
package/agents/anti-patterns.md
CHANGED
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
properties and, for a deep customisation, the parts listed in the component's
|
|
20
20
|
`AGENTS.md` (see [`conventions.md`](conventions.md)).
|
|
21
21
|
- Setting boolean attributes to the string `"false"` (e.g. `disabled="false"`,
|
|
22
|
-
`await="false"`).
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
the attribute
|
|
22
|
+
`await="false"`). On a form-associated component (`mds-button`, `mds-button-dropdown`
|
|
23
|
+
and the form inputs, listed in [`conventions.md`](conventions.md)) it turns the prop
|
|
24
|
+
**on**, as on a native control. On the others Stencil reads `"false"` as `false`, but
|
|
25
|
+
the attribute stays in the DOM on a prop that is not reflected (and until the first
|
|
26
|
+
render on one that is), so `[disabled]` selectors and scripts reading the attribute
|
|
27
|
+
still see it set. **Remove the attribute** to turn it off; from React or Angular, pass
|
|
28
|
+
`false` to the property, as [`conventions.md`](conventions.md) shows.
|
|
26
29
|
- Embedding nested HTML in a default slot when the component documents a `label` prop.
|
|
27
30
|
- Using raw Tailwind colour utilities (`bg-white`, `text-gray-700`) on or inside Magma
|
|
28
31
|
components - use the semantic role classes (`bg-surface-default`, `text-fg-muted`),
|
package/agents/assets.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
## Purpose
|
|
9
9
|
|
|
10
10
|
Canonical setup for the assets every Magma consumer needs, **identical for all three
|
|
11
|
-
targets** (web components, React, Angular): styles, fonts, icons
|
|
12
|
-
identity. The per-target tracks ([`install.md`](install.md)) link here instead of repeating
|
|
11
|
+
targets** (web components, React, Angular): styles, fonts, icons, optional brand
|
|
12
|
+
identity and editor autocomplete. The per-target tracks ([`install.md`](install.md)) link here instead of repeating
|
|
13
13
|
this. If something about styles/fonts/icons setup is unclear, this file wins.
|
|
14
14
|
|
|
15
15
|
This file is the minimum to get a consumer running. Once it runs: coloring your own UI
|
|
@@ -72,10 +72,10 @@ What each file provides:
|
|
|
72
72
|
| `colors-rgb.css` | RGB color tokens (`--tone-*`, `--status-*`, ...). Required by components and Tailwind. Also redefines tokens for dark / high-contrast |
|
|
73
73
|
| `typography.css` | The non-color tokens as CSS vars: fonts, type sizes, spacing, radius, shadows (`--shadow-md-sharp`, ...). Components carry their own fallbacks; your CSS needs this file for `var(--shadow-*)`, `var(--radius-*)` and the `--magma-radius-*` corner scale |
|
|
74
74
|
| `reset.css` | Opinionated CSS reset |
|
|
75
|
-
| `hydrated.css` | Anti-FOUC for Stencil - hides components until hydrated |
|
|
75
|
+
| `hydrated.css` | Anti-FOUC for Stencil - hides components until hydrated, then keeps the margin, padding and border they give themselves against a page reset such as Tailwind's preflight. Import it into `base`, as above |
|
|
76
76
|
| `transitions.css`, `animations.css` | Shared motion |
|
|
77
77
|
| `globals.css` | Global `--magma-*` design decisions |
|
|
78
|
-
| `semantic.css` | The semantic color roles (`--magma-surface-*`, `--magma-text-*`, ..., see [`color.md`](color.md)). Required: without it the page `body` has no colour, the Tailwind role utilities
|
|
78
|
+
| `semantic.css` | The semantic color roles (`--magma-surface-*`, `--magma-text-*`, ..., see [`color.md`](color.md)). Required: without it the page `body` has no colour, the Tailwind role utilities are stuck on their light default (the fallback that gives editors a swatch), and components lose dark mode, named themes and high contrast |
|
|
79
79
|
| `themes.css` | The named themes (`data-theme-name`): retint the semantic roles. Import it after `semantic.css` |
|
|
80
80
|
| `base.css` | Base element styles (sets `--font-info` body font, etc.) |
|
|
81
81
|
|
|
@@ -129,40 +129,173 @@ the `vendor` cascade layer and ship offline.
|
|
|
129
129
|
## 3. Icons
|
|
130
130
|
|
|
131
131
|
Icons are consumed at runtime by `mds-icon`, which fetches each icon as an SVG file from
|
|
132
|
-
a path the host app configures.
|
|
133
|
-
|
|
134
|
-
`<mdsIconSvgPath><slug>.svg`: with the path `/svg/`, `mi/baseline/email` is fetched from
|
|
135
|
-
`/svg/mi/baseline/email.svg`.
|
|
132
|
+
a path the host app configures. The components' own icons are inlined, so what needs
|
|
133
|
+
serving is the icons the app names.
|
|
136
134
|
|
|
137
|
-
###
|
|
135
|
+
### The contract
|
|
136
|
+
|
|
137
|
+
Every slug the app uses must be served at `<mdsIconSvgPath><slug>.svg`: with the path
|
|
138
|
+
`/svg/`, `mi/baseline/email` is fetched from `/svg/mi/baseline/email.svg`. A slug starts
|
|
139
|
+
with its icon set, and each set comes from its own package, with its own layout:
|
|
140
|
+
|
|
141
|
+
| Slug | Set | Package | File in the package |
|
|
142
|
+
| ---- | --- | ------- | ------------------- |
|
|
143
|
+
| `mi/<variant>/<name>` | Material Icons | `@material-icons/svg` | `svg/<name>/<variant>.svg` |
|
|
144
|
+
| `mdi/<name>` | Material Design Icons | `@mdi/svg` | `svg/<name>.svg` |
|
|
145
|
+
| `mgg/<name>` | Maggioli | `@maggioli-design-system/svg-icons` | `dist/svg/<name>.svg` |
|
|
146
|
+
|
|
147
|
+
Magma ships only the `mgg/` set, and none of these packages is a dependency of `magma`,
|
|
148
|
+
`magma-react` or `magma-angular`: the route you pick installs what it needs. Copying the
|
|
149
|
+
`svg-icons` folder as it is does NOT follow the contract: its files sit directly in
|
|
150
|
+
`dist/svg/`, while `mds-icon` asks for them under `mgg/`.
|
|
151
|
+
|
|
152
|
+
`mds-usage` still fetches `mi/baseline/info` for its header: serve it too if the app
|
|
153
|
+
uses that component.
|
|
154
|
+
|
|
155
|
+
Any setup that follows the contract works. Two tested routes, both run before every dev
|
|
156
|
+
start and build, with the output folder kept out of git:
|
|
157
|
+
|
|
158
|
+
### Route 1: iconsauce (what Magma uses)
|
|
159
|
+
|
|
160
|
+
iconsauce reads the sources the way Tailwind reads class names and writes only the icons
|
|
161
|
+
they use, one SVG file per slug, in the folders `mds-icon` expects. Its plugins know the
|
|
162
|
+
three sets and bring their packages along.
|
|
138
163
|
|
|
139
164
|
```bash
|
|
140
|
-
npm i @
|
|
165
|
+
npm i -D @iconsauce/core @iconsauce/material-icons @iconsauce/mdi-svg @iconsauce/mgg-icons
|
|
141
166
|
```
|
|
142
167
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
168
|
+
```js
|
|
169
|
+
// iconsauce.config.mjs
|
|
170
|
+
import mi from '@iconsauce/material-icons';
|
|
171
|
+
import mdi from '@iconsauce/mdi-svg';
|
|
172
|
+
import mgg from '@iconsauce/mgg-icons';
|
|
146
173
|
|
|
147
|
-
|
|
174
|
+
export default {
|
|
175
|
+
content: ['./index.html', './src/**/*.{html,js,jsx,ts,tsx}'], // every file where icon slugs are written
|
|
176
|
+
plugin: [mi, mdi, mgg],
|
|
177
|
+
};
|
|
178
|
+
```
|
|
148
179
|
|
|
149
|
-
|
|
150
|
-
|
|
180
|
+
```json
|
|
181
|
+
"scripts": {
|
|
182
|
+
"icons": "iconsauce --config ./iconsauce.config.mjs --output-svg ./public/svg",
|
|
183
|
+
"predev": "npm run icons",
|
|
184
|
+
"prebuild": "npm run icons"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
151
187
|
|
|
152
|
-
|
|
153
|
-
|
|
188
|
+
A slug built at runtime (`'mi/baseline/' + name`) is invisible to iconsauce: write slugs
|
|
189
|
+
in full, or list the computed ones in a file that `content` reads.
|
|
190
|
+
|
|
191
|
+
### Route 2: serve the files yourself
|
|
192
|
+
|
|
193
|
+
One renaming step: `@material-icons/svg` stores `<name>/<variant>.svg`, while the slug
|
|
194
|
+
wants `mi/<variant>/<name>`. `mdi/` and `mgg/` are plain folder copies. This script covers
|
|
195
|
+
the three sets with Node built-ins only, so it fits any bundler:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npm i -D @maggioli-design-system/svg-icons @material-icons/svg @mdi/svg
|
|
154
199
|
```
|
|
155
200
|
|
|
156
|
-
|
|
157
|
-
|
|
201
|
+
```js
|
|
202
|
+
// scripts/copy-icons.mjs
|
|
203
|
+
// Copies Magma's icon sets where mds-icon fetches them: <OUT>/<slug>.svg.
|
|
204
|
+
// node scripts/copy-icons.mjs icons.json only the slugs listed in icons.json
|
|
205
|
+
// node scripts/copy-icons.mjs every icon of the three sets (18,720 files, 73 MB)
|
|
206
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync } from 'node:fs';
|
|
207
|
+
import { createRequire } from 'node:module';
|
|
208
|
+
import { dirname, join } from 'node:path';
|
|
209
|
+
|
|
210
|
+
const OUT = 'public/svg'; // served at /svg/ by Vite, Next.js and the Angular CLI
|
|
211
|
+
const require = createRequire(import.meta.url);
|
|
212
|
+
const root = (pkg) => dirname(require.resolve(`${pkg}/package.json`));
|
|
213
|
+
const MI = join(root('@material-icons/svg'), 'svg'); // <name>/<variant>.svg
|
|
214
|
+
const MDI = join(root('@mdi/svg'), 'svg'); // <name>.svg
|
|
215
|
+
const MGG = join(root('@maggioli-design-system/svg-icons'), 'dist/svg'); // <name>.svg
|
|
216
|
+
|
|
217
|
+
// Source file of a slug: mi/<variant>/<name>, mdi/<name>, mgg/<name>.
|
|
218
|
+
function source(slug) {
|
|
219
|
+
const [set, ...rest] = slug.split('/');
|
|
220
|
+
if (set === 'mi' && rest.length === 2) return join(MI, rest[1], `${rest[0]}.svg`);
|
|
221
|
+
if (set === 'mdi' && rest.length === 1) return join(MDI, `${rest[0]}.svg`);
|
|
222
|
+
if (set === 'mgg' && rest.length === 1) return join(MGG, `${rest[0]}.svg`);
|
|
223
|
+
throw new Error(`Not a Magma icon slug: ${slug}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function allSlugs() {
|
|
227
|
+
const names = (dir) => readdirSync(dir).map((file) => file.replace(/\.svg$/, ''));
|
|
228
|
+
return [
|
|
229
|
+
...readdirSync(MI).flatMap((name) => names(join(MI, name)).map((variant) => `mi/${variant}/${name}`)),
|
|
230
|
+
...names(MDI).map((name) => `mdi/${name}`),
|
|
231
|
+
...names(MGG).map((name) => `mgg/${name}`),
|
|
232
|
+
];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const slugs = process.argv[2] ? JSON.parse(readFileSync(process.argv[2], 'utf8')) : allSlugs();
|
|
236
|
+
for (const slug of slugs) {
|
|
237
|
+
const file = source(slug);
|
|
238
|
+
if (!existsSync(file)) throw new Error(`No such icon: ${slug} (${file})`);
|
|
239
|
+
const target = join(OUT, `${slug}.svg`);
|
|
240
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
241
|
+
copyFileSync(file, target);
|
|
242
|
+
}
|
|
243
|
+
console.log(`${slugs.length} icons in ${OUT}/`);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`icons.json` lists the slugs the app uses:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
["mi/baseline/email", "mi/baseline/send", "mdi/github", "mgg/abitazione-principale"]
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
"scripts": {
|
|
254
|
+
"icons": "node scripts/copy-icons.mjs icons.json",
|
|
255
|
+
"predev": "npm run icons",
|
|
256
|
+
"prebuild": "npm run icons"
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
A slug that does not exist stops the script with an error. A slug used in the code but
|
|
261
|
+
missing from `icons.json` gives a 404 at runtime: iconsauce avoids that by reading the
|
|
262
|
+
sources. Without `icons.json` the script copies every icon of the three sets, all of
|
|
263
|
+
them deployed: 18,720 files and 73 MB (`mi` 43 MB in five variants, `mdi` 29 MB, `mgg`
|
|
264
|
+
1.3 MB).
|
|
265
|
+
|
|
266
|
+
### Only the `mgg/` set
|
|
267
|
+
|
|
268
|
+
An app that uses only Maggioli icons can copy the `svg-icons` folder, into `mgg/` under
|
|
269
|
+
the served path: `@maggioli-design-system/svg-icons/dist/svg/` to `public/svg/mgg/`. With
|
|
270
|
+
the Angular CLI that is an `assets` entry in `angular.json`:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{ "glob": "**/*.svg", "input": "node_modules/@maggioli-design-system/svg-icons/dist/svg", "output": "/svg/mgg" }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Tell mds-icon where the icons are
|
|
277
|
+
|
|
278
|
+
Set the public URL of the folder the icons are served from, before the first `mds-icon`
|
|
279
|
+
renders. Two ways:
|
|
158
280
|
|
|
159
281
|
- `IconsSetService.setSvgPath('/svg/')`, imported from
|
|
160
|
-
`@maggioli-design-system/magma/services
|
|
161
|
-
`sessionStorage`, and reloads the icons already mounted
|
|
162
|
-
- `
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
282
|
+
`@maggioli-design-system/magma/services` (recommended): sets the path in code, without
|
|
283
|
+
`sessionStorage`, and reloads the icons already mounted.
|
|
284
|
+
- the `mdsIconSvgPath` key in `sessionStorage`, a one-liner the install tracks use. Some
|
|
285
|
+
browsers block storage (private windows, sandboxed iframes, storage partitioning): there
|
|
286
|
+
only `IconsSetService` works.
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
import { IconsSetService } from '@maggioli-design-system/magma/services';
|
|
290
|
+
|
|
291
|
+
IconsSetService.setSvgPath('/svg/');
|
|
292
|
+
// or: window.sessionStorage.setItem('mdsIconSvgPath', '/svg/');
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Icons mounted before a path set through `sessionStorage` reload on
|
|
296
|
+
`window.dispatchEvent(new CustomEvent('mdsIconSvgPathUpdate'))`. Every option, with its
|
|
297
|
+
snippet, is in the
|
|
298
|
+
[`mds-icon` pattern](../../magma/dist/collection/components/mds-icon/pattern.md).
|
|
166
299
|
|
|
167
300
|
Reference an icon by slug, never inline SVG and never import from an icon-set package:
|
|
168
301
|
|
|
@@ -190,14 +323,84 @@ Assets live under `@maggioli-design-system/identity/dist/`:
|
|
|
190
323
|
- `dist/illustrations/`, `dist/products/` - additional brand imagery
|
|
191
324
|
|
|
192
325
|
These are static read-only files - serve them like any other asset, do not modify
|
|
193
|
-
them in the consumer project.
|
|
326
|
+
them in the consumer project. `dist/identity.json` describes them: one entry per family of
|
|
327
|
+
artworks, with its name as the artwork writes it, its owner and kind, and every variant with
|
|
328
|
+
its path, form, colour, the background it is drawn for and its size. Read names and alt texts
|
|
329
|
+
from it instead of from the file names, which lose accents and punctuation.
|
|
330
|
+
|
|
331
|
+
## 5. Editor autocomplete
|
|
332
|
+
|
|
333
|
+
Two halves, one extension each. Set them up in VS Code; for another editor, point its CSS
|
|
334
|
+
custom property completion at the same `tokens.editor.css` and leave the rest to the user.
|
|
335
|
+
|
|
336
|
+
| Completes | Extension | Fed by |
|
|
337
|
+
| --------- | --------- | ------ |
|
|
338
|
+
| Magma tokens inside `var(--...)`, in scale order, with a swatch on colors | CSS Var Complete (`phoenisx.cssvar`) | `@maggioli-design-system/styles/dist/css/tokens.editor.css`, every public token once |
|
|
339
|
+
| Tailwind classes (`bg-surface-default`, `p-600`), with their value | Tailwind CSS IntelliSense (`bradlc.vscode-tailwindcss`), only if the app uses Tailwind | the CSS entry that imports Tailwind and Magma's theme (section 1) |
|
|
340
|
+
|
|
341
|
+
MERGE these keys into `.vscode/settings.json` and `.vscode/extensions.json`: never overwrite
|
|
342
|
+
a file that exists, the user's own settings stay.
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"cssvar.files": ["node_modules/@maggioli-design-system/styles/dist/css/tokens.editor.css"],
|
|
347
|
+
"cssvar.ignore": [],
|
|
348
|
+
"cssvar.disableSort": true
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"recommendations": ["phoenisx.cssvar", "bradlc.vscode-tailwindcss"],
|
|
355
|
+
"unwantedRecommendations": ["vunguyentuan.vscode-css-variables"]
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Leave `bradlc.vscode-tailwindcss` out of `recommendations` when the app has no Tailwind.
|
|
360
|
+
|
|
361
|
+
The traps, all measured:
|
|
362
|
+
|
|
363
|
+
- `cssvar.ignore` must be `[]`: its default, `["**/node_modules/**"]`, is applied over
|
|
364
|
+
`cssvar.files`, so the path above is dropped and nothing completes.
|
|
365
|
+
- `cssvar.disableSort: true` keeps the order of the file (a scale from its smallest step
|
|
366
|
+
up); without it the list is alphabetical.
|
|
367
|
+
- `vunguyentuan.vscode-css-variables` goes in `unwantedRecommendations`: it sorts
|
|
368
|
+
alphabetically, never opens the list by itself and duplicates every entry next to CSS
|
|
369
|
+
Var Complete.
|
|
370
|
+
- Never import `tokens.editor.css` in the app: it is for editors only, and holds light
|
|
371
|
+
defaults that would freeze theming (it is wrapped in a query that never matches, so an
|
|
372
|
+
import does nothing at best).
|
|
373
|
+
|
|
374
|
+
Tailwind IntelliSense finds the CSS entry on its own, the split imports of section 1
|
|
375
|
+
included. Only if hovering a class shows nothing, add
|
|
376
|
+
`"tailwindCSS.experimental.configFile": "<path of that CSS file>"`. If the app builds class
|
|
377
|
+
names through functions (`clsx`, `cva`, `cn`), list the ones it uses in
|
|
378
|
+
`"tailwindCSS.classFunctions"`, so the classes inside their calls complete too.
|
|
379
|
+
|
|
380
|
+
Verify, after reloading the window:
|
|
381
|
+
|
|
382
|
+
- in a CSS file, `var(--magma-surface` lists the surface roles, in order, with swatches;
|
|
383
|
+
- with Tailwind, in markup: hovering `p-600` shows `1.5rem = 24px`, and `bg-surface-default`
|
|
384
|
+
shows a swatch in the completion list. No swatch on the semantic classes means an older
|
|
385
|
+
`@maggioli-design-system/styles`: update it.
|
|
386
|
+
|
|
387
|
+
Known limits, nothing to configure:
|
|
388
|
+
|
|
389
|
+
- Tailwind IntelliSense lists the utilities alphabetically, whatever the order of the
|
|
390
|
+
theme: `bg-surface-bisque-*` comes before `bg-surface-default`. Type the role name.
|
|
391
|
+
- The class list offers Tailwind's stock spacing steps (`p-1` ... `p-96`), not Magma's:
|
|
392
|
+
with Magma's theme `p-1` is 0.04px. Write the Magma steps in full (`p-600`, `gap-400`):
|
|
393
|
+
they work and hover with their value, they are just not suggested.
|
|
194
394
|
|
|
195
395
|
## Checklist
|
|
196
396
|
|
|
197
397
|
- [ ] `styles` + `design-tokens` installed on the matching version row
|
|
198
398
|
- [ ] Global CSS imports in the exact cascade-layer order above
|
|
199
399
|
- [ ] `@fontsource` fonts installed and imported in the `vendor` layer
|
|
200
|
-
- [ ]
|
|
400
|
+
- [ ] Every icon slug the app uses served at `<mdsIconSvgPath><slug>.svg` (iconsauce or
|
|
401
|
+
the copy script, run before dev and build, output folder out of git)
|
|
201
402
|
- [ ] `mdsIconSvgPath` set to that public path before hydration
|
|
202
403
|
- [ ] (optional) `identity` installed if brand assets are used
|
|
203
404
|
- [ ] Components registered per your target track
|
|
405
|
+
- [ ] (VS Code) the editor keys merged into `.vscode/settings.json` and `extensions.json`;
|
|
406
|
+
`var(--magma-` completes, and with Tailwind `bg-surface-default` shows a swatch
|
package/agents/color.md
CHANGED
|
@@ -55,9 +55,11 @@ Tailwind names the TEXT roles `fg-*`, so a utility never reads `text-text-*`:
|
|
|
55
55
|
`border-border-default`, `bg-accent-emphasis`, `bg-danger-wash-base`.
|
|
56
56
|
|
|
57
57
|
Both faces need the setup in [`assets.md`](assets.md): the values come from
|
|
58
|
-
`styles/dist/css/semantic.css
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
`styles/dist/css/semantic.css`, the Tailwind utilities from `styles/dist/tailwind/theme.css`.
|
|
59
|
+
Without `semantic.css` a `var(--magma-*)` paints nothing, and a Tailwind utility paints the
|
|
60
|
+
light default of its role, the fallback its bridge carries so editors can show a swatch: in
|
|
61
|
+
dark mode, with a named theme or with more contrast it stays wrong, so the file is still
|
|
62
|
+
required. A Tailwind modifier works as usual (`bg-surface-raised/80`).
|
|
61
63
|
|
|
62
64
|
## The roles
|
|
63
65
|
|
|
@@ -70,10 +72,10 @@ named theme retints all of it at once.
|
|
|
70
72
|
| --- | --- | --- |
|
|
71
73
|
| `surface-default` | `bg-surface-default` | the page canvas (the `body` already has it) |
|
|
72
74
|
| `surface-raised` | `bg-surface-raised` | cards, panels, sticky headers |
|
|
73
|
-
| `surface-overlay` | `bg-surface-overlay` | modal, dropdown, popover, sheet |
|
|
75
|
+
| `surface-overlay` | `bg-surface-overlay` | modal, dropdown, popover, sheet, and anything lifted with a shadow |
|
|
74
76
|
| `surface-sunken` | `bg-surface-sunken` | wells, insets, code blocks, tracks |
|
|
75
77
|
| `surface-muted` | `bg-surface-muted` | same-plane grouping: zebra rows, a subtle section |
|
|
76
|
-
| `wash-soft` / `wash-base` / `wash-strong` | `bg-wash-*` | a neutral pill or chip, by how marked it is |
|
|
78
|
+
| `wash-soft` / `wash-base` / `wash-strong` | `bg-wash-*` | a flat neutral pill or chip (no shadow), by how marked it is |
|
|
77
79
|
| `surface-inverse` / `surface-inverse-muted` | `bg-surface-inverse*` | the chip that flips with the mode (dark on a light UI) |
|
|
78
80
|
| `on-inverse` | `text-on-inverse` | text and icons on either inverse level |
|
|
79
81
|
| `text-default` | `text-fg-default` | body text, titles, primary data |
|
package/agents/components.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Source of truth: docs/agents/ in the magma monorepo.
|
|
4
4
|
Regenerate with: npm run sync.agent-docs (from the stencil package).
|
|
5
5
|
-->
|
|
6
|
-
# Magma components catalogue (
|
|
6
|
+
# Magma components catalogue (115 components)
|
|
7
7
|
|
|
8
8
|
> Generated from each component's usage description. Each tag links the component's
|
|
9
9
|
> own `AGENTS.md` (its API, with `pattern.md` and `antipattern.md` beside it) in
|
|
@@ -83,10 +83,10 @@
|
|
|
83
83
|
| [`mds-pref-animation`](../../magma/dist/collection/components/mds-pref-animation/AGENTS.md) | The `<mds-pref-animation>` web component is a preference control that lets users choose how animations are presented (reduced, system-driven, or fully enabled) |
|
|
84
84
|
| [`mds-pref-consumption`](../../magma/dist/collection/components/mds-pref-consumption/AGENTS.md) | The `<mds-pref-consumption>` web component is a preference control of the Magma Design System that lets the user pick an energy-consumption mode (`low`, `medium`, `high`); it is usually a child of `<mds-pref>` and renders as a tab group with one option per mode, so it has no native HTML primitive equivalent. |
|
|
85
85
|
| [`mds-pref-contrast`](../../magma/dist/collection/components/mds-pref-contrast/AGENTS.md) | The `<mds-pref-contrast>` web component is a preference control that lets users switch the application's contrast mode (`more`, `system`, or `no-preference`) |
|
|
86
|
-
| [`mds-pref-language`](../../magma/dist/collection/components/mds-pref-language/AGENTS.md) | The `<mds-pref-language>` web component is the language-preference control of the Magma Design System,
|
|
86
|
+
| [`mds-pref-language`](../../magma/dist/collection/components/mds-pref-language/AGENTS.md) | The `<mds-pref-language>` web component is the language-preference control of the Magma Design System, usually slotted inside the `<mds-pref>` panel alongside the other preference children |
|
|
87
87
|
| [`mds-pref-language-item`](../../magma/dist/collection/components/mds-pref-language-item/AGENTS.md) | The `<mds-pref-language-item>` web component represents a single selectable language option inside the language-preference picker `<mds-pref-language>` |
|
|
88
|
-
| [`mds-pref-mode`](../../magma/dist/collection/components/mds-pref-mode/AGENTS.md) | The `<mds-pref-mode>` web component is the mode preference control of the Magma Design System,
|
|
89
|
-
| [`mds-pref-theme`](../../magma/dist/collection/components/mds-pref-theme/AGENTS.md) | The `<mds-pref-theme>` web component is the theme-switcher segment of the Magma accessibility preferences panel,
|
|
88
|
+
| [`mds-pref-mode`](../../magma/dist/collection/components/mds-pref-mode/AGENTS.md) | The `<mds-pref-mode>` web component is the mode preference control of the Magma Design System, usually a direct child of the `<mds-pref>` panel |
|
|
89
|
+
| [`mds-pref-theme`](../../magma/dist/collection/components/mds-pref-theme/AGENTS.md) | The `<mds-pref-theme>` web component is the theme-switcher segment of the Magma accessibility preferences panel, usually a direct child of `<mds-pref>` |
|
|
90
90
|
| [`mds-pref-theme-item`](../../magma/dist/collection/components/mds-pref-theme-item/AGENTS.md) | The `<mds-pref-theme-item>` web component is a single selectable theme entry inside the `<mds-pref-theme>` preference picker |
|
|
91
91
|
| [`mds-price-table`](../../magma/dist/collection/components/mds-price-table/AGENTS.md) | The `<mds-price-table>` web component is the layout container of the Magma Design System pricing-table family |
|
|
92
92
|
| [`mds-price-table-features`](../../magma/dist/collection/components/mds-price-table-features/AGENTS.md) | The `<mds-price-table-features>` web component is the feature-matrix block of the Magma Design System pricing-table family |
|
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
| [`mds-table-row`](../../magma/dist/collection/components/mds-table-row/AGENTS.md) | The `<mds-table-row>` web component represents a single data row inside a `<mds-table>` (slotted through `mds-table-body`; `mds-table-header` and `mds-table-footer` are rows themselves) |
|
|
121
121
|
| [`mds-text`](../../magma/dist/collection/components/mds-text/AGENTS.md) | The `<mds-text>` web component is the foundational typography primitive of the Magma Design System |
|
|
122
122
|
| [`mds-toast`](../../magma/dist/collection/components/mds-toast/AGENTS.md) | The `<mds-toast>` web component is the transient notification surface of the Magma Design System, used to surface brief, non-blocking feedback messages that appear over the viewport and auto-dismiss after a timeout |
|
|
123
|
+
| [`mds-toast-region`](../../magma/dist/collection/components/mds-toast-region/AGENTS.md) | The `<mds-toast-region>` web component is the place where an application shows its toasts: placed once in the application shell, at an edge of the viewport, it lines up the `<mds-toast>` elements visible at the same time, each one readable, and announces them to assistive technologies |
|
|
123
124
|
| [`mds-tooltip`](../../magma/dist/collection/components/mds-tooltip/AGENTS.md) | The `<mds-tooltip>` web component is the floating contextual hint of the Magma Design System |
|
|
124
125
|
| [`mds-tree`](../../magma/dist/collection/components/mds-tree/AGENTS.md) | The `<mds-tree>` web component is the root container of the Magma Design System tree view, organizing a hierarchy of slotted `<mds-tree-item>` nodes into an expandable/collapsible structure |
|
|
125
126
|
| [`mds-tree-item`](../../magma/dist/collection/components/mds-tree-item/AGENTS.md) | The `<mds-tree-item>` web component is the node primitive of the Magma Design System tree view: it represents a single labeled, expandable/collapsible entry inside an `<mds-tree>` and is also the recursive container for its own descendants |
|
package/agents/conventions.md
CHANGED
|
@@ -28,11 +28,27 @@
|
|
|
28
28
|
|
|
29
29
|
- Boolean props default to `false`/`undefined`. Prefer removing the attribute over
|
|
30
30
|
setting it to `false`.
|
|
31
|
+
- A boolean attribute turns its prop on by being present. On the form-associated
|
|
32
|
+
components (`mds-button`, `mds-button-dropdown`, `mds-input`, `mds-input-date`,
|
|
33
|
+
`mds-input-date-range`, `mds-input-field`, `mds-input-otp`, `mds-input-range`,
|
|
34
|
+
`mds-input-select`, `mds-input-switch`, `mds-input-upload`) any value turns it on,
|
|
35
|
+
`"false"` included, as on a native control.
|
|
31
36
|
- Disabled: `<mds-button disabled>`. Never `disabled="false"` - remove it instead. Set
|
|
32
37
|
`disabled` on the component, not on a wrapper: disabled components are removed from
|
|
33
38
|
the tab order automatically.
|
|
34
39
|
- Async: `<mds-button await>` shows a spinner and blocks interaction; remove `await`
|
|
35
40
|
(set `undefined`) when done.
|
|
41
|
+
- From a framework, pass a real boolean to the property, not a string to the attribute:
|
|
42
|
+
- React with `magma-react`: `<MdsButton disabled={isDisabled} />` sets the property,
|
|
43
|
+
so `false` turns the prop off; the `.server` variants leave a `false` out of the
|
|
44
|
+
markup. A bare `mds-*` tag in React 18 JSX is different: React 18 writes
|
|
45
|
+
`disabled={false}` as the attribute `"false"`, which turns a form-associated component
|
|
46
|
+
on, so pass `undefined` there. React 19 sets the property and turns it off.
|
|
47
|
+
- Angular with `magma-angular`: bind the input, `[disabled]="isDisabled"`. The proxy
|
|
48
|
+
sets the property, so `false` turns the prop off. A static `disabled="false"` or an
|
|
49
|
+
attribute binding (`[attr.disabled]="false"`) writes the attribute instead, and turns
|
|
50
|
+
a form-associated component on; `[attr.disabled]="null"` removes it. Reactive Forms
|
|
51
|
+
`disable()` / `enable()` set the property through the value accessor.
|
|
36
52
|
|
|
37
53
|
## Sizing
|
|
38
54
|
|
package/agents/install.md
CHANGED
|
@@ -24,7 +24,7 @@ npm i @maggioli-design-system/magma-react @maggioli-design-system/magma
|
|
|
24
24
|
matrix). Then install the assets from [`assets.md`](assets.md):
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
npm i @maggioli-design-system/styles @maggioli-design-system/design-tokens
|
|
27
|
+
npm i @maggioli-design-system/styles @maggioli-design-system/design-tokens
|
|
28
28
|
npm i @fontsource/karla @fontsource/merriweather @fontsource/roboto @fontsource/roboto-mono
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -116,9 +116,10 @@ export default function RootLayout({
|
|
|
116
116
|
|
|
117
117
|
## 4. Serve the icon SVGs and styles
|
|
118
118
|
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
- Write the icons into the static folder served at `/svg/` (Vite and Next.js:
|
|
120
|
+
`public/svg/`) with one of the routes of [`assets.md`](assets.md) section 3
|
|
121
|
+
(iconsauce or the copy script, run from `predev` and `prebuild`). Match the path you
|
|
122
|
+
pass to `mdsIconSvgPath`.
|
|
122
123
|
- Import the global CSS block from [`assets.md`](assets.md) in your global stylesheet
|
|
123
124
|
(`app/globals.css`, `src/index.css`, ...) so the cascade-layer order is preserved.
|
|
124
125
|
|
|
@@ -164,7 +165,7 @@ SSR notes:
|
|
|
164
165
|
- Icons render empty server-side (the box is reserved, no layout shift) and the
|
|
165
166
|
default theme is rendered - see the SSR section in
|
|
166
167
|
[`install.md`](install.md).
|
|
167
|
-
- The hydrate module (`magma/hydrate`) bundles all
|
|
168
|
+
- The hydrate module (`magma/hydrate`) bundles all 115 components (~3 MB,
|
|
168
169
|
server-only). It is imported lazily behind a `typeof window` check and must
|
|
169
170
|
never end up in a client bundle.
|
|
170
171
|
|
|
@@ -208,6 +209,11 @@ With React Router the handler is `(href) => navigate(href)` from `useNavigate()`
|
|
|
208
209
|
on the client - use the `.server` variants (section 5) to get real SSR markup.
|
|
209
210
|
- Keep `magma` and `magma-react` on the exact same version; the wrapper is generated
|
|
210
211
|
against a specific `magma` build.
|
|
212
|
+
- Pass booleans as booleans: `<MdsButton disabled={false} />` sets the property and turns
|
|
213
|
+
the prop off, and the `.server` variants leave a `false` out of the markup. Render the
|
|
214
|
+
wrapper, not the bare `mds-*` tag: in React 18 JSX `<mds-button disabled={false}>`
|
|
215
|
+
writes the attribute `"false"`, which turns a form-associated component on (see
|
|
216
|
+
[`conventions.md`](conventions.md)).
|
|
211
217
|
|
|
212
218
|
## See also
|
|
213
219
|
|
package/agents/reporting.md
CHANGED
|
@@ -56,8 +56,11 @@ gh label list --repo magma-design-system/magma --search prd-
|
|
|
56
56
|
|
|
57
57
|
Match it against this project's repository name (the `origin` remote, or the `name` in
|
|
58
58
|
`package.json`). If none matches, do not create one: the Magma maintainers manage the
|
|
59
|
-
labels of their repository
|
|
60
|
-
|
|
59
|
+
labels of their repository, and a label missing from their configuration is deleted by
|
|
60
|
+
the next sync. Open the issue without it, and propose its name in the body, so the
|
|
61
|
+
maintainers add it as it is: `prd-` and the project's short name, lowercase, in
|
|
62
|
+
kebab-case (`prd-mindy` for `mindy-webapp`, `prd-docs` for the docs site). Leave out
|
|
63
|
+
generic words such as `app`, `webapp`, `frontend` or the organization's name.
|
|
61
64
|
|
|
62
65
|
GitHub sets labels on a new issue only for users with write access to the repository,
|
|
63
66
|
and drops them for everyone else, often without an error. After creating the issue,
|
|
@@ -98,6 +101,12 @@ What the project does meanwhile, if anything.
|
|
|
98
101
|
Found in <project> (<repository>): <where in the app>.
|
|
99
102
|
```
|
|
100
103
|
|
|
104
|
+
When step 4 found no origin label, end the body with the one you propose:
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
No origin label for this project yet: proposed `prd-<name>`.
|
|
108
|
+
```
|
|
109
|
+
|
|
101
110
|
Read the installed versions from the lockfile or `npm ls`, not from the ranges in
|
|
102
111
|
`package.json`.
|
|
103
112
|
|
package/agents/theming.md
CHANGED
|
@@ -138,3 +138,18 @@ by itself changes the shape WITHOUT the scale.
|
|
|
138
138
|
In your own CSS take radii from the `--magma-radius-*` scale (`none`, `3xs` ... `5xl`,
|
|
139
139
|
`full`), which follows the axis: `border-radius: var(--magma-radius-lg)`. A raw
|
|
140
140
|
`--radius-*` token or a pixel value stays the same under every shape.
|
|
141
|
+
|
|
142
|
+
A browser without `corner-shape` (Firefox, Safari) gets round corners and the round
|
|
143
|
+
scale on its own. A control of your own whose radius is past half its height
|
|
144
|
+
(Chromium clamps it to half the height) needs one more step to keep its look there:
|
|
145
|
+
cap the radius at a part of its height, as Magma's buttons and fields do.
|
|
146
|
+
|
|
147
|
+
```css
|
|
148
|
+
.my-control {
|
|
149
|
+
--my-control-height: 2.25rem;
|
|
150
|
+
|
|
151
|
+
border-radius: min(var(--magma-radius-2xl), var(--magma-corner-cap) * var(--my-control-height));
|
|
152
|
+
corner-shape: var(--magma-corner-shape);
|
|
153
|
+
min-height: var(--my-control-height);
|
|
154
|
+
}
|
|
155
|
+
```
|
package/dist/components.js
CHANGED
|
@@ -109,6 +109,7 @@ export { MdsTableHeader } from "./mds-table-header.js";
|
|
|
109
109
|
export { MdsTableRow } from "./mds-table-row.js";
|
|
110
110
|
export { MdsTable } from "./mds-table.js";
|
|
111
111
|
export { MdsText } from "./mds-text.js";
|
|
112
|
+
export { MdsToastRegion } from "./mds-toast-region.js";
|
|
112
113
|
export { MdsToast } from "./mds-toast.js";
|
|
113
114
|
export { MdsTooltip } from "./mds-tooltip.js";
|
|
114
115
|
export { MdsTreeItem } from "./mds-tree-item.js";
|
|
@@ -109,6 +109,7 @@ export { MdsTableHeader } from "./mds-table-header.server.js";
|
|
|
109
109
|
export { MdsTableRow } from "./mds-table-row.server.js";
|
|
110
110
|
export { MdsTable } from "./mds-table.server.js";
|
|
111
111
|
export { MdsText } from "./mds-text.server.js";
|
|
112
|
+
export { MdsToastRegion } from "./mds-toast-region.server.js";
|
|
112
113
|
export { MdsToast } from "./mds-toast.server.js";
|
|
113
114
|
export { MdsTooltip } from "./mds-tooltip.server.js";
|
|
114
115
|
export { MdsTreeItem } from "./mds-tree-item.server.js";
|
package/dist/mds-input.server.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as clientComponents from "@maggioli-design-system/magma-react";
|
|
|
5
5
|
export const serializeShadowRoot = "declarative-shadow-dom";
|
|
6
6
|
export const MdsTableFooter = /*@__PURE__*/ createComponent({
|
|
7
7
|
tagName: 'mds-table-footer',
|
|
8
|
-
properties: {},
|
|
8
|
+
properties: { selectable: 'selectable' },
|
|
9
9
|
hydrateModule: typeof window === 'undefined' ? import('@maggioli-design-system/magma/hydrate') : undefined,
|
|
10
10
|
clientModule: clientComponents.MdsTableFooter,
|
|
11
11
|
serializeShadowRoot
|
|
@@ -7,6 +7,6 @@ export const MdsTableHeaderCell = /*@__PURE__*/ createComponent({
|
|
|
7
7
|
elementClass: MdsTableHeaderCellElement,
|
|
8
8
|
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
|
|
9
9
|
react: React,
|
|
10
|
-
events: {},
|
|
10
|
+
events: { onMdsTableHeaderCellSort: 'mdsTableHeaderCellSort' },
|
|
11
11
|
defineCustomElement: defineMdsTableHeaderCell
|
|
12
12
|
});
|
|
@@ -8,6 +8,7 @@ export const MdsTableHeaderCell = /*@__PURE__*/ createComponent({
|
|
|
8
8
|
properties: {
|
|
9
9
|
sortable: 'sortable',
|
|
10
10
|
label: 'label',
|
|
11
|
+
sortKey: 'sort-key',
|
|
11
12
|
direction: 'direction'
|
|
12
13
|
},
|
|
13
14
|
hydrateModule: typeof window === 'undefined' ? import('@maggioli-design-system/magma/hydrate') : undefined,
|
package/dist/mds-table.server.js
CHANGED
|
@@ -8,7 +8,8 @@ export const MdsTable = /*@__PURE__*/ createComponent({
|
|
|
8
8
|
properties: {
|
|
9
9
|
interactive: 'interactive',
|
|
10
10
|
selectable: 'selectable',
|
|
11
|
-
selection: 'selection'
|
|
11
|
+
selection: 'selection',
|
|
12
|
+
sorting: 'sorting'
|
|
12
13
|
},
|
|
13
14
|
hydrateModule: typeof window === 'undefined' ? import('@maggioli-design-system/magma/hydrate') : undefined,
|
|
14
15
|
clientModule: clientComponents.MdsTable,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createComponent } from '@stencil/react-output-target/runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { MdsToastRegion as MdsToastRegionElement, defineCustomElement as defineMdsToastRegion } from "@maggioli-design-system/magma/dist/components/mds-toast-region.js";
|
|
5
|
+
export const MdsToastRegion = /*@__PURE__*/ createComponent({
|
|
6
|
+
tagName: 'mds-toast-region',
|
|
7
|
+
elementClass: MdsToastRegionElement,
|
|
8
|
+
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
|
|
9
|
+
react: React,
|
|
10
|
+
events: {},
|
|
11
|
+
defineCustomElement: defineMdsToastRegion
|
|
12
|
+
});
|