@nxgt/material 3.10.2 → 3.11.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 +70 -0
- package/README.md +4 -4
- package/dist/{async-slice-DDjaJY_F.js → async-slice-4qbER86I.js} +1 -1
- package/dist/button-BNjw-pnE.js +327 -0
- package/dist/button-group-context-CaP0X5p_.js +5 -0
- package/dist/{button-tones-BgZJ1tkD.js → button-tones-BwuVvAmd.js} +9 -1
- package/dist/{callout-view-DdJPdFrP.js → callout-view-C6voDS00.js} +1 -1
- package/dist/charts.js +5 -5
- package/dist/{chip-DpySRqCy.js → chip-DLgQTJBZ.js} +4 -4
- package/dist/{code-editor-BiA14xua.js → code-editor-BZbaYLvo.js} +8 -8
- package/dist/code-editor.js +7 -7
- package/dist/{code-language-items-C_dJ6GVs.js → code-language-items-BT5BO5w6.js} +2 -2
- package/dist/components/base.css +21 -6
- package/dist/components/components.css +5 -2
- package/dist/components/type-scale.css +194 -0
- package/dist/components/ui/actions/button/button.css +156 -0
- package/dist/components/ui/actions/button-group/button-group-standard.css +131 -0
- package/dist/components/ui/actions/button-group/button-group.css +4 -1
- package/dist/components/ui/actions/icon-button/icon-button.css +115 -0
- package/dist/components/ui/actions/morph-fill.css +62 -0
- package/dist/{components-BkF9N-Yx.js → components-1GK7YIhY.js} +14685 -14688
- package/dist/components.js +23 -23
- package/dist/{dialog-CkIYpJXk.js → dialog-BQp5IdFl.js} +147 -147
- package/dist/dnd.js +1 -1
- package/dist/{dropdown-menu-BC5Tbhb9.js → dropdown-menu-BsH9W_3C.js} +3 -3
- package/dist/editor-viewer.js +1 -1
- package/dist/editor.js +13 -13
- package/dist/{empty-state-SeAg2TOX.js → empty-state-WaU4-T2c.js} +5 -5
- package/dist/escape-owner-C4W_sOAU.js +116 -0
- package/dist/{field-blur-DPLsMufs.js → field-blur-CJHzVSh9.js} +1 -1
- package/dist/{field-blur-context-1ZwJgsHE.js → field-blur-context-Cft9s7Hg.js} +2 -2
- package/dist/{hover-card-Cox-tPDz.js → hover-card-C0fw2kLK.js} +72 -71
- package/dist/i18n.js +12 -12
- package/dist/{icon-badge-q3Ve8gra.js → icon-badge-DUAq9f7H.js} +4 -4
- package/dist/icon-button-ifTpXt0A.js +355 -0
- package/dist/{illustration-BfHRpVzM.js → illustration-BmQmvW_4.js} +1 -1
- package/dist/illustrations.js +2 -2
- package/dist/lib/components/ui/actions/button/button-tones.d.ts +16 -0
- package/dist/lib/components/ui/actions/button/button.d.ts +13 -0
- package/dist/lib/components/ui/actions/button/button.variants.d.ts +4 -3
- package/dist/lib/components/ui/actions/button-group/button-group-context.d.ts +16 -0
- package/dist/lib/components/ui/actions/button-group/button-group-reset.d.ts +13 -0
- package/dist/lib/components/ui/actions/button-group/button-group.d.ts +19 -2
- package/dist/lib/components/ui/actions/icon-button/icon-button-shape.d.ts +3 -2
- package/dist/lib/components/ui/actions/icon-button/icon-button.d.ts +18 -4
- package/dist/lib/components/ui/actions/icon-button/icon-button.variants.d.ts +34 -4
- package/dist/lib/components/ui/feedback/typing-indicator/typing-indicator.d.ts +1 -1
- package/dist/lib/components/ui/fields/slider/split-slider-props.d.ts +1 -1
- package/dist/lib/components/ui/fields/slider/use-slider-control.d.ts +1 -1
- package/dist/lib/components/ui/overlays/dialog/dialog-variants.d.ts +1 -1
- package/dist/lib/components/ui/primitives/toggle/toggle.d.ts +1 -1
- package/dist/lib/components/ui/primitives/typography/typography.d.ts +17 -7
- package/dist/lib/components/ui/primitives/typography/typography.variants.d.ts +55 -0
- package/dist/lib/components/ui/selection/choice-group/use-choice-group-field.d.ts +2 -2
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib.js +2 -2
- package/dist/{line-path-BQeLQZ-P.js → line-path-C5pZGC49.js} +1 -1
- package/dist/main.js +29 -29
- package/dist/map.js +9 -9
- package/dist/material.css +1 -1
- package/dist/pdf-reader.js +1 -1
- package/dist/print.js +1 -1
- package/dist/{public-CtpsxV4I.js → public-B0Nq_yYV.js} +524 -524
- package/dist/{render-json-DyFYFIkZ.js → render-json-BOhvPnSv.js} +1 -1
- package/dist/{rich-code-block-C2Fp_FDU.js → rich-code-block-v7WmeZp9.js} +5 -5
- package/dist/{rich-text-viewer-LO1IZCWs.js → rich-text-viewer-W15XIwah.js} +2 -2
- package/dist/{skeleton-Bmp4gWAH.js → skeleton-DSdtr2qc.js} +1 -1
- package/dist/{sortable-provider-pVaEZzty.js → sortable-provider-CgDTolQR.js} +3 -3
- package/dist/{spinner-CsHcmcpF.js → spinner-BtSIYVrC.js} +3 -3
- package/dist/{state-scenes-SGNyZjTz.js → state-scenes-BX03WmSu.js} +1 -1
- package/dist/styles.css +2 -0
- package/dist/theme-picker.js +3 -3
- package/dist/{theme-toggle-oU-fh6WE.js → theme-toggle-B2Pehdhn.js} +2 -2
- package/dist/{toggle-group-j8zaxEg1.js → toggle-group-BMJNcFAC.js} +1 -1
- package/dist/{toolbar-items-CqHvlTU8.js → toolbar-items-rUHdVqAq.js} +399 -398
- package/dist/{tooltip-rhbqNmr3.js → tooltip-CkttDIab.js} +1 -1
- package/dist/{translate-material-CGZljjp1.js → translate-material-Bd_KgfB8.js} +1 -1
- package/dist/{translator-DCYO4Ij3.js → translator-Dje8HrNz.js} +5 -5
- package/dist/{use-chat-composer-nWWfVyrK.js → use-chat-composer-Bt2ULsv6.js} +4172 -4172
- package/dist/{use-material-translation-DkxcLbLM.js → use-material-translation-B3V_bz-5.js} +1 -1
- package/dist/{utils-Bcd2Z3ea.js → utils-BLfntITJ.js} +14 -1
- package/docs/components/buttons-and-actions.md +64 -15
- package/docs/components/navigation-and-layout.md +1 -1
- package/docs/components/primitives.md +52 -10
- package/docs/guides/theming.md +51 -0
- package/docs/previews/buttons-actions-button.webp +0 -0
- package/docs/previews/buttons-actions-iconbutton.webp +0 -0
- package/docs/previews/primitives-typography.webp +0 -0
- package/docs/roadmap.md +35 -4
- package/docs/troubleshooting.md +58 -2
- package/lib/components/base.css +21 -6
- package/lib/components/components.css +5 -2
- package/lib/components/type-scale.css +194 -0
- package/lib/components/ui/actions/button/button.css +156 -0
- package/lib/components/ui/actions/button-group/button-group-standard.css +131 -0
- package/lib/components/ui/actions/button-group/button-group.css +4 -1
- package/lib/components/ui/actions/icon-button/icon-button.css +115 -0
- package/lib/components/ui/actions/morph-fill.css +62 -0
- package/lib/styles.css +2 -0
- package/package.json +1 -1
- package/dist/button-DbfdITBB.js +0 -322
- package/dist/components/ui/actions/icon-button/icon-button-morph-media.css +0 -65
- package/dist/components/ui/actions/icon-button/icon-button-morph.css +0 -152
- package/dist/escape-owner-CripBce_.js +0 -57
- package/dist/icon-button-DJcWpIhu.js +0 -319
- package/lib/components/ui/actions/icon-button/icon-button-morph-media.css +0 -65
- package/lib/components/ui/actions/icon-button/icon-button-morph.css +0 -152
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as e } from "./i18n-provider-C6HhBw34.js";
|
|
2
|
-
import { t } from "./translate-material-
|
|
2
|
+
import { t } from "./translate-material-Bd_KgfB8.js";
|
|
3
3
|
import { useCallback as n } from "react";
|
|
4
4
|
//#region lib/i18n/use-material-translation.ts
|
|
5
5
|
function r() {
|
|
@@ -1733,7 +1733,20 @@ var n = (e, t) => {
|
|
|
1733
1733
|
}, Pe = (e, t, n) => {
|
|
1734
1734
|
let r = t[n];
|
|
1735
1735
|
r !== void 0 && (e[n] = e[n] ? e[n].concat(r) : r);
|
|
1736
|
-
}, Fe = ((e, ...t) => typeof e == "function" ? k(Ae, e, ...t) : k(() => je(Ae(), e), ...t))({ extend: { theme: {
|
|
1736
|
+
}, Fe = ((e, ...t) => typeof e == "function" ? k(Ae, e, ...t) : k(() => je(Ae(), e), ...t))({ extend: { theme: {
|
|
1737
|
+
radius: ["field", "field-inner"],
|
|
1738
|
+
text: [
|
|
1739
|
+
"display",
|
|
1740
|
+
"headline",
|
|
1741
|
+
"title",
|
|
1742
|
+
"body",
|
|
1743
|
+
"label"
|
|
1744
|
+
].flatMap((e) => [
|
|
1745
|
+
"lg",
|
|
1746
|
+
"md",
|
|
1747
|
+
"sm"
|
|
1748
|
+
].flatMap((t) => [`${e}-${t}`, `${e}-${t}-em`]))
|
|
1749
|
+
} } });
|
|
1737
1750
|
function Ie(...e) {
|
|
1738
1751
|
return Fe(t(e));
|
|
1739
1752
|
}
|
|
@@ -6,9 +6,9 @@ and language switches. Everything is imported from `@nxgt/material/components`.
|
|
|
6
6
|
|
|
7
7
|
| | Component | What it does |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| <img src="../previews/buttons-actions-button.webp" width="96" alt=""> | [Button](#button) | Five variants in seven colours and
|
|
10
|
-
| <img src="../previews/buttons-actions-iconbutton.webp" width="96" alt=""> | [IconButton](#iconbutton) | Icon-only button with an optional tooltip |
|
|
11
|
-
| <img src="../previews/buttons-actions-buttongroup.webp" width="96" alt=""> | [ButtonGroup](#buttongroup) | Joins adjacent buttons into one control |
|
|
9
|
+
| <img src="../previews/buttons-actions-button.webp" width="96" alt=""> | [Button](#button) | Five variants in seven colours, six sizes, a round or square shape and a selected state, with a loading state |
|
|
10
|
+
| <img src="../previews/buttons-actions-iconbutton.webp" width="96" alt=""> | [IconButton](#iconbutton) | Icon-only button in five sizes and three widths, with an optional tooltip |
|
|
11
|
+
| <img src="../previews/buttons-actions-buttongroup.webp" width="96" alt=""> | [ButtonGroup](#buttongroup) | Joins adjacent buttons into one control; the expressive look widens the pressed one |
|
|
12
12
|
| <img src="../previews/buttons-actions-splitbutton.webp" width="96" alt=""> | [SplitButton](#splitbutton) | Main action plus a menu of related ones, Material 3 Expressive |
|
|
13
13
|
| <img src="../previews/buttons-actions-fab.webp" width="96" alt=""> | [Fab](#fab) | The screen's main action, floating; extended with its label, folds on scroll |
|
|
14
14
|
| <img src="../previews/buttons-actions-fabmenu.webp" width="96" alt=""> | [FabMenu](#fabmenu) | A FAB that opens a few related actions as pills |
|
|
@@ -28,7 +28,7 @@ and language switches. Everything is imported from `@nxgt/material/components`.
|
|
|
28
28
|
|
|
29
29
|

|
|
30
30
|
|
|
31
|
-
Filled, tonal, outlined, ghost or link button in seven colours,
|
|
31
|
+
Filled, tonal, outlined, ghost or link button in seven colours, six sizes (24 to 96 px) and four square icon sizes, round or square, with a selected state and a loading state.
|
|
32
32
|
|
|
33
33
|
```tsx
|
|
34
34
|
import { Button } from '@nxgt/material/components';
|
|
@@ -43,6 +43,7 @@ import { Mail } from 'lucide-react';
|
|
|
43
43
|
</Button>
|
|
44
44
|
<Button loading>Saving</Button>
|
|
45
45
|
<Button size="sm">Small</Button>
|
|
46
|
+
<Button size="xl" shape="square">Big and square</Button>
|
|
46
47
|
<Button size="icon" aria-label="Email">
|
|
47
48
|
<Mail />
|
|
48
49
|
</Button>
|
|
@@ -52,8 +53,10 @@ import { Mail } from 'lucide-react';
|
|
|
52
53
|
| Prop | Type | Default | Effect |
|
|
53
54
|
| --- | --- | --- | --- |
|
|
54
55
|
| `variant` | `'filled' \| 'tonal' \| 'outlined' \| 'ghost' \| 'link'` | `'filled'` | the style |
|
|
55
|
-
| `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'default'` | `'primary'` | the colour; `default` is the foreground colour. A `ghost` button in `secondary`, `success`, `info`, `warning` or `error` takes that colour's text and a tint of it on hover, at 4.5:1 on the page and on a card in both themes;
|
|
56
|
-
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'icon-xs' \| 'icon-sm' \| 'icon' \| 'icon-lg'` | — | height: 24, 32, 36 and
|
|
56
|
+
| `color` | `'primary' \| 'secondary' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'default'` | `'primary'` | the colour; `default` is the foreground colour. A `ghost` button in `secondary`, `success`, `info`, `warning` or `error` takes that colour's text and a tint of it on hover, at 4.5:1 on the page and on a card in both themes; without a `color` (or with `default`) it keeps the foreground text, neutral; `color="primary"` set on a ghost button is tinted and takes the primary text |
|
|
57
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl' \| '2xl' \| 'icon-xs' \| 'icon-sm' \| 'icon' \| 'icon-lg'` | — | height: 24, 32, 36, 40, 56 and 96 px, with a label from the type scale (`label-md` to `headline-lg`, heavier as the size grows) and an icon that follows (14, 16, 18, 20, 28 and 44 px); the `icon*` sizes are square, for a button holding only an icon (give it an `aria-label`). Unset, the button keeps its content's height and its 16 px padding, as before sizes existed |
|
|
58
|
+
| `shape` | `'round' \| 'square'` | `'round'` | `round` is a pill (radius half the height); `square` has a corner of 6 px at `xs` to 28 px at `2xl`. A press springs to the other shape and scales to .97 (.985 at `2xl`); reduced motion keeps the colour change only |
|
|
59
|
+
| `selected` | `boolean` | — | makes it a toggle: `aria-pressed` and `data-selected`, the other shape and a solid fill of its `color` (a `ghost` toggle without a `color` is a neutral tint of the text colour). Unset: a plain button. Ignored with `asChild` (a warning in development): set `aria-pressed` on the child |
|
|
57
60
|
| `loading` | `boolean` | — | busy: a spinner, `aria-busy="true"` and `aria-disabled="true"`, and every click cancelled — a submit button submits neither on a click nor on Enter in a field. It stays focusable (no native `disabled`), so focus is not lost |
|
|
58
61
|
| `lockOnClick` | `boolean` | — | a click makes the button busy at once, until `loading` has turned true and back (or for one second when it never does): for a `loading` that turns true only after an `await` |
|
|
59
62
|
| `spinnerVariant` | `SpinnerProps['variant']` | `'2'` | which spinner `loading` shows |
|
|
@@ -62,7 +65,19 @@ import { Mail } from 'lucide-react';
|
|
|
62
65
|
| `asChild` | `boolean` | `false` | styles its only child instead of rendering a `<button>` |
|
|
63
66
|
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | not `submit` by default — pass it inside a form |
|
|
64
67
|
|
|
65
|
-
The classes are exported as `buttonVariants` for styling your own element.
|
|
68
|
+
The classes are exported as `buttonVariants` for styling your own element (Pagination, AlertDialog and the calendar's date picker use them).
|
|
69
|
+
|
|
70
|
+
**The look.** The label is set in the type scale and is heavier than before (weights 560 at `xs` to 700 at `2xl`). The focus is a 2 px outline in the button's colour, 2 px off the button (the error colour with `aria-invalid`). A disabled button has neutral text (40 % of the text colour) and a neutral 12 % fill, none on `ghost` and `link`. `outlined` is a 1.5 px line inside the box at 55 % of the colour, and keeps a `ButtonText` outline in forced colours, where the inset shadow is removed. A `ghost` button is neutral without a `color`, and takes the tone of one it is given. On a coarse pointer every size has a 44 px hit area.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
const [on, setOn] = useState(false);
|
|
74
|
+
|
|
75
|
+
<Button selected={on} onClick={() => setOn(!on)}>
|
|
76
|
+
<Star />
|
|
77
|
+
Favourite
|
|
78
|
+
</Button>;
|
|
79
|
+
<Button size="2xl" shape="square" variant="tonal">Start</Button>;
|
|
80
|
+
```
|
|
66
81
|
|
|
67
82
|
**On a phone.** A button is never wider than its container, and keeps its
|
|
68
83
|
content's width in a column: a label too
|
|
@@ -71,7 +86,7 @@ accessible name — and a `title` you give it — keep the whole text. Give a
|
|
|
71
86
|
label that must be read in full `wrap`, or a width of your own (`w-full`).
|
|
72
87
|
The text is put in a `<span data-slot="button-label">` (one per run of
|
|
73
88
|
text) that shrinks and ends in the ellipsis; it needs the text to be the button's own child; with `asChild`,
|
|
74
|
-
put the label in a `<span>` inside the child element.
|
|
89
|
+
put the label in a `<span>` inside the child element. On a touch screen in Safari (no `overflow-clip-margin`) an `asChild` host does not clip, to keep its 44 px hit area, so it has no ellipsis at all: a label that needs one goes in a `<span>` with `truncate`.
|
|
75
90
|
|
|
76
91
|
```tsx
|
|
77
92
|
<Button title="Continue to the payment details">Continue to the payment details</Button>;
|
|
@@ -110,7 +125,7 @@ A test finds a busy button by its state, not by `disabled`:
|
|
|
110
125
|
`expect(button).toHaveAttribute('aria-busy', 'true')` (`toBeDisabled()` is
|
|
111
126
|
false: it is still focusable).
|
|
112
127
|
|
|
113
|
-
**Storybook:** `Buttons & actions/Button` (`Submits Once`, `Lock On Click`), `Buttons & actions/Button/Phone` · **Vue:** `Button`
|
|
128
|
+
**Storybook:** `Buttons & actions/Button` (`Submits Once`, `Lock On Click`), `Buttons & actions/Button/Expressive` (`SizesLadder`, `Shape`, `Selected`), `Buttons & actions/Button/Press and motion` (`PressMorph`, `ReducedMotion`), `Buttons & actions/Button/States` (`FocusOutline`, `Disabled`, `GhostSelectedNeutral`, `SelectedForcedColours`, `OutlinedForcedColours`, `PhoneBigSizes`), `Buttons & actions/Button/Phone`, `Guides/Buttons expressive` · **Vue:** `Button` (no `xl`, `2xl`, `shape` or `selected`)
|
|
114
129
|
|
|
115
130
|
---
|
|
116
131
|
|
|
@@ -136,14 +151,16 @@ import { Pencil, Trash2 } from 'lucide-react';
|
|
|
136
151
|
|
|
137
152
|
| Prop | Type | Default | Effect |
|
|
138
153
|
| --- | --- | --- | --- |
|
|
139
|
-
| `variant` | `'filled' \| 'tonal' \| 'outlined' \| 'ghost' \| 'link'` | `'filled'` | the style; a round
|
|
154
|
+
| `variant` | `'filled' \| 'tonal' \| 'outlined' \| 'ghost' \| 'link'` | `'filled'` | the style; a round button |
|
|
140
155
|
| `color` | as `Button` | `'primary'` | the colour; a `ghost` one in a colour other than `primary` or `default` draws its icon in it, as `Button` does |
|
|
156
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl'` | — | 24, 32, 36, 40 or 56 px, icons of 14, 16, 18, 20 or 28 px (for a glyph without its own `size-*` class; an `Icon` is 16 px unless sized). Unset: the 36 px button with a 16 px icon it always was, so an explicit `default` has an 18 px icon |
|
|
157
|
+
| `width` | `'narrow' \| 'default' \| 'wide'` | `'default'` | 0.78, 1 or 1.45 times the height, always a pill. Ignored with `shape` (a warning in development) |
|
|
141
158
|
| `tooltip` | `ReactNode` | — | wraps it in a `Tooltip`; a string tooltip also becomes the `aria-label` |
|
|
142
159
|
| `aria-label` | `string` | the tooltip, if a string | give one when there is no string tooltip |
|
|
143
160
|
| `shape` | `ShapeName` | — | draws the button as one of the expressive shapes (`cookie-9`, `sunny`, `squircle`…) instead of a circle; changing it morphs. Unset: the round button, unchanged |
|
|
144
161
|
| `morph` | `'round' \| 'pill' \| 'none'` | `'pill'` | what a **toggle** (`aria-pressed` set) does when pressed: `pill` fills with its colour and widens by 14 px into a pill, `round` fills and stays a circle, `none` keeps the look your classes give it. Not set on a button without `aria-pressed`, one with a `shape`, or a Toolbar item (the Toolbar's own look) |
|
|
145
162
|
|
|
146
|
-
**A toggle button**
|
|
163
|
+
**A toggle button** fills with the button's `color` (`primary` by default) through `data-selected` and the fill `Button` shares, and a pointer down squeezes the corners; `pill` widens the button itself by 14 px (its neighbours move by the 14 px), at any `size` (give the button a `size`, not a `size-*` class: the pressed width follows the `size`, see [troubleshooting](../troubleshooting.md#a-pill-iconbutton-toggle-is-the-wrong-width-with-a-size--class)). Below 600 px wide only the colour changes, so a phone row never reflows; `prefers-reduced-motion` keeps the colour change only; in forced colours the pressed fill is `SelectedItem`. The pressed fill and corners are the button's own (a `bg-*` or `rounded-*` class on a pressed toggle does not apply); a ghost toggle without a `color` is neutral when selected (a tint of the text colour), and primary only with a `color`. The focus is a 2 px outline 2 px off the button, a disabled button has a neutral 12 % fill (none on `ghost` and `link`), and on a coarse pointer every size has a 44 px hit area. The morph works with a `tooltip` too (the styles match `data-icon-button`, which the tooltip trigger does not replace). The date picker's input-mode switch uses `morph="round"`; `PasswordField`'s eye, which sits inside its field, and `RichChatComposer`'s format toggle, which draws its own pressed look, use `morph="none"`; the mini player's move button and the Gallery viewer's repeat are pills too, white with a black icon on their dark chrome. `CodeEditor`'s word-wrap pill takes the editor theme's tint.
|
|
147
164
|
|
|
148
165
|
```tsx
|
|
149
166
|
import { IconButton } from '@nxgt/material/components';
|
|
@@ -214,7 +231,9 @@ built this way. A `Contacts` badge is `role="img"`, named by the contact type.
|
|
|
214
231
|
|
|
215
232
|
The classes are exported as `iconButtonVariants`.
|
|
216
233
|
|
|
217
|
-
**
|
|
234
|
+
**Forced colours.** An `outlined` button keeps a `ButtonText` outline and a pressed toggle, `Button` or `IconButton`, fills with `SelectedItem` (its text and icon in `SelectedItemText`); the focus outline follows the system colours.
|
|
235
|
+
|
|
236
|
+
**Storybook:** `Buttons & actions/IconButton` (`Shapes`, `ShapeToggle`), `Buttons & actions/IconButton/Sizes and widths` (`SizesLadder`, `Widths`, `Colours`), `Buttons & actions/IconButton/States` (`FocusOutline`, `Disabled`, `GhostToggleNeutral`, `SelectedForcedColours`), `Buttons & actions/IconButton/Toggle and motion` (`SizedToggle`, `ReducedMotion`, `PressMorph`), `Buttons & actions/IconButton/Morph` (`Frozen`, `WidensOrStaysRound`, `Contrast`), `Buttons & actions/IconButton/Morph unaffected` (`Unaffected`, `WithTooltip`), `Buttons & actions/IconButton/Shapes` (`InsideAGroup`) · **Vue:** `IconButton` (no `shape`)
|
|
218
237
|
|
|
219
238
|
---
|
|
220
239
|
|
|
@@ -222,7 +241,7 @@ The classes are exported as `iconButtonVariants`.
|
|
|
222
241
|
|
|
223
242
|

|
|
224
243
|
|
|
225
|
-
Joins adjacent buttons into one control.
|
|
244
|
+
Joins adjacent buttons into one control; `look="standard"` is the Material 3 Expressive action group.
|
|
226
245
|
|
|
227
246
|
```tsx
|
|
228
247
|
import { Button, ButtonGroup } from '@nxgt/material/components';
|
|
@@ -236,12 +255,42 @@ import { Button, ButtonGroup } from '@nxgt/material/components';
|
|
|
236
255
|
</ButtonGroup>;
|
|
237
256
|
```
|
|
238
257
|
|
|
239
|
-
|
|
258
|
+
| Prop | Type | Default | Effect |
|
|
259
|
+
| --- | --- | --- | --- |
|
|
260
|
+
| `look` | `'standard'` | — | the Material 3 Expressive group (see below). Unset: the original group, which becomes the `standard` one by default in the next major, with `look="legacy"` to keep it |
|
|
261
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl'` | — | the `size` every `Button` and `IconButton` in the group takes through a context; a child's own `size` wins. Works with either look |
|
|
262
|
+
| `...div` | `ComponentProps<'div'>` | — | the host's props; `data-slot="button-group"`, `data-look` and `data-size` are set on it |
|
|
263
|
+
|
|
264
|
+
A `<div>` taking its props. Without `look` it stretches to its container (`w-full`); mark the
|
|
240
265
|
current button with `data-state="active"`: it fills with the primary colour and
|
|
241
266
|
its label and icons switch to the primary foreground, so every button can stay
|
|
242
267
|
`tonal` and only the attribute moves.
|
|
243
268
|
|
|
244
|
-
|
|
269
|
+
`look="standard"` is the Material 3 Expressive group: the buttons keep their own
|
|
270
|
+
look, 8px apart, and a pressed one widens by 14px on each side while its
|
|
271
|
+
neighbours give the width back, so the group's width never changes (7, 10 and
|
|
272
|
+
11px at `xs`, `sm` and `default`, which have less padding to give; none with
|
|
273
|
+
reduced motion; an icon-only neighbour at the end of the group keeps its icon and may give back less). `size` is shared by every `Button` and `IconButton` in the group
|
|
274
|
+
(a child's own `size` wins) and works with either look. It sets
|
|
275
|
+
`data-look` and `data-size` on the host; mark the group with `role="group"` and a
|
|
276
|
+
name when it is one control.
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
<ButtonGroup look="standard" size="lg" role="group" aria-label="Actions">
|
|
280
|
+
<Button variant="tonal">Save</Button>
|
|
281
|
+
<Button variant="tonal">Share</Button>
|
|
282
|
+
<IconButton variant="tonal" aria-label="More">
|
|
283
|
+
<MoreHorizontal />
|
|
284
|
+
</IconButton>
|
|
285
|
+
</ButtonGroup>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
On a coarse pointer the standard group's gap is `max(8px, 44px - the height of its size)`
|
|
289
|
+
(20px at `xs`, 12px at `sm`, 8px from `default`), so every button, in a row or
|
|
290
|
+
across wrapped rows, keeps a 44px hit area that touches no neighbour's. A child with its own smaller `size` in a standard group keeps the group's gap, so its coarse 44px hit area can overlap a neighbour's: give the group the smallest `size` instead. Without
|
|
291
|
+
`look` the group is unchanged.
|
|
292
|
+
|
|
293
|
+
**Storybook:** `Buttons & actions/ButtonGroup`, `Buttons & actions/ButtonGroup/Standard`, `Buttons & actions/ButtonGroup/Standard toggles`, `Buttons & actions/ButtonGroup/Standard phone and motion`, `Guides/Buttons expressive` · **Vue:** `ButtonGroup` (no `look` or `size`)
|
|
245
294
|
|
|
246
295
|
---
|
|
247
296
|
|
|
@@ -295,7 +295,7 @@ import { BottomAppBar, IconButton, TopAppBar, Typography } from '@nxgt/material/
|
|
|
295
295
|
|
|
296
296
|
<TopAppBar>
|
|
297
297
|
<IconButton variant="ghost" aria-label="Open menu"><Menu /></IconButton>
|
|
298
|
-
<Typography variant="title-
|
|
298
|
+
<Typography variant="title-md" emphasized className="flex-1">Inbox</Typography>
|
|
299
299
|
<IconButton variant="ghost" aria-label="Search"><Search /></IconButton>
|
|
300
300
|
</TopAppBar>
|
|
301
301
|
|
|
@@ -10,7 +10,7 @@ other pages are built from these.
|
|
|
10
10
|
| <img src="../previews/primitives-accordion.webp" width="96" alt=""> | [Accordion](#accordion) | Collapsible sections with a rotating chevron and animated content |
|
|
11
11
|
| <img src="../previews/primitives-collapsible.webp" width="96" alt=""> | [Collapsible](#collapsible) | A single show / hide region and its trigger |
|
|
12
12
|
| <img src="../previews/primitives-card.webp" width="96" alt=""> | [Card](#card) | Card surface with header, action slot, content and footer |
|
|
13
|
-
| <img src="../previews/primitives-typography.webp" width="96" alt=""> | [Typography](#typography) | Text in the Material type scale |
|
|
13
|
+
| <img src="../previews/primitives-typography.webp" width="96" alt=""> | [Typography](#typography) | Text in the Material 3 type scale, with an emphasized weight |
|
|
14
14
|
| <img src="../previews/primitives-anchorheading.webp" width="96" alt=""> | [AnchorHeading](#anchorheading) | Heading with a hover copy-link |
|
|
15
15
|
| <img src="../previews/primitives-label.webp" width="96" alt=""> | [Label](#label) | Form label with an optional required asterisk |
|
|
16
16
|
| <img src="../previews/primitives-helpertext.webp" width="96" alt=""> | [HelperText](#helpertext) | Hint or error message under a field |
|
|
@@ -171,36 +171,78 @@ with `as` (`<CardTitle as="h2">`), so `getByRole('heading', { name })` finds it.
|
|
|
171
171
|
|
|
172
172
|

|
|
173
173
|
|
|
174
|
-
Text in the Material type scale
|
|
174
|
+
Text in the Material 3 type scale: five roles, three sizes each, and an emphasized weight.
|
|
175
175
|
|
|
176
176
|
```tsx
|
|
177
177
|
import { Typography } from '@nxgt/material/components';
|
|
178
178
|
|
|
179
179
|
<>
|
|
180
|
-
<Typography variant="headline-
|
|
181
|
-
<Typography
|
|
182
|
-
<Typography variant="
|
|
180
|
+
<Typography variant="headline-sm">Orders</Typography>
|
|
181
|
+
<Typography>12 orders are waiting to ship.</Typography>
|
|
182
|
+
<Typography variant="label-sm" tone="muted">Updated a minute ago</Typography>
|
|
183
|
+
<Typography variant="title-md" emphasized>Next delivery</Typography>
|
|
183
184
|
</>;
|
|
184
185
|
```
|
|
185
186
|
|
|
186
187
|
| Prop | Type | Default | Effect |
|
|
187
188
|
| --- | --- | --- | --- |
|
|
188
|
-
| `variant` |
|
|
189
|
+
| `variant` | `` `${'display' \| 'headline' \| 'title' \| 'body' \| 'label'}-${'lg' \| 'md' \| 'sm'}` `` | `'body-md'` | the step of the scale: size, line height, tracking and weight together. The fifteen former names still work, deprecated (see below) |
|
|
190
|
+
| `emphasized` | `boolean` | `false` | the heavier weight of the same step (`text-<step>-em`); same size, line height and tracking. No effect on a deprecated alias that is emphasized already |
|
|
189
191
|
| `tone` | `'default' \| 'muted' \| 'primary' \| 'error'` | `'default'` | text colour: `muted` is `text-muted-foreground`, `primary` is `text-primary-text` (primary lightened in dark), `error` is `text-error-text`; `default` inherits (a `className` colour still wins) |
|
|
190
192
|
| `as` | an intrinsic tag name (`keyof JSX.IntrinsicElements`) | `'div'` | the element to render, keeping the variant, e.g. `as="h2"` or `as="span"` |
|
|
191
193
|
| `asChild` | `boolean` | `false` | merge the classes onto the single child instead of rendering an element |
|
|
192
194
|
|
|
195
|
+
**The scale.** Sizes are in px, then line height; the weight is 400 except `title-md`, `title-sm` and the three `label` steps (500).
|
|
196
|
+
|
|
197
|
+
| Role | `lg` | `md` | `sm` |
|
|
198
|
+
| --- | --- | --- | --- |
|
|
199
|
+
| `display` | 57 / 64 | 45 / 52 | 36 / 44 |
|
|
200
|
+
| `headline` | 32 / 40 | 28 / 36 | 24 / 32 |
|
|
201
|
+
| `title` | 22 / 28 | 16 / 24 | 14 / 20 |
|
|
202
|
+
| `body` | 16 / 24 | 14 / 20 | 12 / 16 |
|
|
203
|
+
| `label` | 14 / 20 | 12 / 16 | 11 / 16 |
|
|
204
|
+
|
|
205
|
+
`emphasized` weights: `display` 540, `headline` 560, `title-lg` 580, `title-md` and `title-sm` 680, `body` 520, `label` 700. A variable font such as Inter reads them on its `wght` axis; any other font rounds to the nearest weight it has.
|
|
206
|
+
|
|
207
|
+
**The tokens.** The scale is Tailwind 4 tokens in `styles.css` (`--text-<role>-<size>` with `--line-height`, `--letter-spacing`, `--font-weight` and `--font-weight-em`), so `text-title-md` and `text-title-md-em` are utilities for your own markup, and an app or a zone retunes a step with CSS variables alone (no `defineTheme` key). The [theming guide](../guides/theming.md#type-scale) has the details.
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
<Typography variant="title-md" emphasized className="[--text-title-md:1.5rem] [--text-title-md--line-height:2rem]">
|
|
211
|
+
Larger inside this element
|
|
212
|
+
</Typography>
|
|
213
|
+
```
|
|
214
|
+
|
|
193
215
|
It renders a `<div>` unless `as` or `asChild` says otherwise. Use `as="span"` inside a `<button>` or a link, where a `<div>` is invalid HTML. It sets no `overflow`, so it is never a scroll region: text with break points wraps, while an unbreakable string can overflow its box (add `wrap-anywhere` or `min-w-0`; put your own wrapper with `overflow-auto` and `tabIndex={0}` around it to scroll):
|
|
194
216
|
|
|
195
217
|
```tsx
|
|
196
|
-
<Typography as="span" variant="title-
|
|
197
|
-
<Typography asChild
|
|
198
|
-
<Typography tone="muted"
|
|
218
|
+
<Typography as="span" variant="title-sm" emphasized>Inline</Typography>
|
|
219
|
+
<Typography asChild><a href="/docs">Docs</a></Typography>
|
|
220
|
+
<Typography tone="muted">Jan 3 to Jan 9</Typography>
|
|
199
221
|
```
|
|
200
222
|
|
|
223
|
+
**Deprecated names.** The fifteen former variants are aliases of the scale by name, removed in 4.0. Their **sizes changed** in 3.11 (the weights and line heights follow the scale too):
|
|
224
|
+
|
|
225
|
+
| Former variant | Use | Size before → after |
|
|
226
|
+
| --- | --- | --- |
|
|
227
|
+
| `normal`, `body-medium` | `body-md` | 14 → 14 px (weight 400, which `Typography` now sets itself instead of inheriting its parent's) |
|
|
228
|
+
| `body-small` | `body-sm` | 12 → 12 px |
|
|
229
|
+
| `caption` | `label-sm` with `tone="muted"` | 10 → 11 px |
|
|
230
|
+
| `title-small` | `title-sm` emphasized | 16 → 14 px |
|
|
231
|
+
| `title-medium` | `title-md` emphasized | 18 → 16 px |
|
|
232
|
+
| `title-large` | `title-lg` emphasized | 20 → 22 px |
|
|
233
|
+
| `headline-small` | `headline-sm` emphasized | 24 → 24 px |
|
|
234
|
+
| `headline-medium` | `headline-md` emphasized | 30 → 28 px |
|
|
235
|
+
| `headline-large` | `headline-lg` emphasized | 36 → 32 px |
|
|
236
|
+
| `headline-larger` | `display-sm` emphasized | 48 → 36 px |
|
|
237
|
+
| `huge-small` | `display-sm` emphasized | 60 → 36 px |
|
|
238
|
+
| `huge-medium` | `display-md` emphasized | 72 → 45 px |
|
|
239
|
+
| `huge-large`, `huge-larger` | `display-lg` emphasized | 96 → 57 px |
|
|
240
|
+
|
|
241
|
+
The bare `h1` to `h6` elements follow the scale too: `headline-md`, `headline-sm`, `title-lg`, `title-md`, `title-sm` and `label-md`, at weight 500.
|
|
242
|
+
|
|
201
243
|
The variants are also exported as `typographyVariants` for use on your own elements.
|
|
202
244
|
|
|
203
|
-
**Storybook:** `Primitives/Typography` · **Vue:** `Typography`
|
|
245
|
+
**Storybook:** `Primitives/Typography` (`Scale`), `Primitives/Typography/Type scale` (`Emphasized`, `Aliases`, `ZoneOverride`) · **Vue:** `Typography` (no scale)
|
|
204
246
|
|
|
205
247
|
---
|
|
206
248
|
|
package/docs/guides/theming.md
CHANGED
|
@@ -35,6 +35,8 @@ at the top are needed is in [getting started](../getting-started.md#styles).
|
|
|
35
35
|
`AttributeForm` and `AttributeValuesForm`, and the required-field mark drawn
|
|
36
36
|
after a `Label` (the first three are dependencies, the rest ship in
|
|
37
37
|
`lib/components/`);
|
|
38
|
+
- the **type scale**: `--text-<role>-<size>` tokens and the `text-title-md` and
|
|
39
|
+
`text-title-md-em` utilities ([Type scale](#type-scale));
|
|
38
40
|
- the **tokens**: CSS variables on `:root`, and their dark values on `.dark`
|
|
39
41
|
and `[data-theme="dark"]`;
|
|
40
42
|
- an `@theme inline` block that maps each token to a Tailwind colour, so
|
|
@@ -664,6 +666,55 @@ does not set it: without it the title uses the body face. Set it on `:root`
|
|
|
664
666
|
}
|
|
665
667
|
```
|
|
666
668
|
|
|
669
|
+
## Type scale
|
|
670
|
+
|
|
671
|
+
The text sizes are the Material 3 type scale: five roles (`display`, `headline`,
|
|
672
|
+
`title`, `body`, `label`) in three sizes (`lg`, `md`, `sm`), as Tailwind 4
|
|
673
|
+
tokens in `styles.css`. Each step has a size, a line height, a tracking and a
|
|
674
|
+
weight, and an emphasized (heavier) weight:
|
|
675
|
+
|
|
676
|
+
```css
|
|
677
|
+
--text-title-md: 1rem;
|
|
678
|
+
--text-title-md--line-height: 1.5rem;
|
|
679
|
+
--text-title-md--letter-spacing: 0.0094em;
|
|
680
|
+
--text-title-md--font-weight: 500;
|
|
681
|
+
--text-title-md--font-weight-em: 680;
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
They are real Tailwind utilities, so your own markup uses the same steps as
|
|
685
|
+
`Typography`, `Button` and the bare headings:
|
|
686
|
+
|
|
687
|
+
```tsx
|
|
688
|
+
<h2 className="text-headline-sm">Orders</h2>
|
|
689
|
+
<p className="text-body-md">12 orders are waiting.</p>
|
|
690
|
+
<span className="text-title-md-em">Next delivery</span>
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
`text-title-md` sets size, line height, tracking and weight; `text-title-md-em`
|
|
694
|
+
keeps the first three and takes the emphasized weight. `font-bold`,
|
|
695
|
+
`leading-*` and `tracking-*` still win over them. Retune a step with CSS
|
|
696
|
+
variables, on `:root` for the app or on a zone for one part of the page; there
|
|
697
|
+
is no `defineTheme` key:
|
|
698
|
+
|
|
699
|
+
```css
|
|
700
|
+
:root {
|
|
701
|
+
--text-body-md: 0.9375rem;
|
|
702
|
+
--text-body-md--line-height: 1.4rem;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.dense-table {
|
|
706
|
+
--text-title-md--font-weight-em: 600;
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
Weights are numeric and read on a variable font's `wght` axis (Inter Variable
|
|
711
|
+
covers 100 to 900); the library sets no `font-variation-settings`, and
|
|
712
|
+
`font-optical-sizing` stays at the browser's `auto`. The bare `h1` to `h6` are
|
|
713
|
+
`headline-md`, `headline-sm`, `title-lg`, `title-md`, `title-sm` and
|
|
714
|
+
`label-md` at weight 500, so a retuned step retunes them too. The
|
|
715
|
+
[Typography component](../components/primitives.md#typography) has the table of
|
|
716
|
+
values and the deprecated names.
|
|
717
|
+
|
|
667
718
|
## Overriding tokens
|
|
668
719
|
|
|
669
720
|
Redefine the variables **after** the import, for light and dark separately:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -123,6 +123,18 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
123
123
|
|
|
124
124
|
## Next
|
|
125
125
|
|
|
126
|
+
- **`ButtonGroup` standard look by default, and the old `Typography` names
|
|
127
|
+
removed (4.0)** — `ButtonGroup`'s Material 3 Expressive look (`look="standard"`)
|
|
128
|
+
becomes the default, with `look="legacy"` to keep the original group. The
|
|
129
|
+
fifteen deprecated `Typography` variants (`huge-*`, `headline-larger`,
|
|
130
|
+
`headline-large`... `caption`) are removed in favour of the type scale's
|
|
131
|
+
names, once the other component families read the scale
|
|
132
|
+
([Typography](components/primitives.md#typography)).
|
|
133
|
+
|
|
134
|
+
- **IconButton: `round` or `square` like Button** — a `shape` of `round` or
|
|
135
|
+
`square` on `IconButton`, with the same press morph, beside the expressive
|
|
136
|
+
shape names it takes today.
|
|
137
|
+
|
|
126
138
|
- **DataGrid: row selection on phones** — the phone list gets the selection
|
|
127
139
|
control the grid has with `enableRowSelection`: a checkbox per item and a
|
|
128
140
|
select-all, with the same `rowSelection` state.
|
|
@@ -220,10 +232,11 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
220
232
|
- **`CircularProgress` at Material 3's size** — the default `size` becomes
|
|
221
233
|
Material 3's 40 px (48 px when `wavy`) instead of 100 px. Pass `size` today
|
|
222
234
|
to keep a size across the change.
|
|
223
|
-
- **`Button` on the
|
|
224
|
-
24
|
|
225
|
-
|
|
226
|
-
up
|
|
235
|
+
- **`Button` `xs` and `lg` on the `SplitButton` scale** — 3.11 keeps `Button`
|
|
236
|
+
at 24, 32, 36 and 40 px (and adds `xl` 56 and `2xl` 96); `xs` becoming 28 px
|
|
237
|
+
and `lg` 44 px, the scale `SplitButton` and `ToggleGroup` follow, so a
|
|
238
|
+
`Button` and a `SplitButton` of the same size line up, stays a possible
|
|
239
|
+
change for a major.
|
|
227
240
|
- **A CSP without `style-src-attr 'unsafe-inline'`** — the four form controls'
|
|
228
241
|
hidden inputs and the `Checkbox` indicator no longer need it;
|
|
229
242
|
`SelectValue`, the `RadioGroup` root, `Slider` and popper positioning still
|
|
@@ -295,6 +308,24 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
295
308
|
|
|
296
309
|
## Shipped
|
|
297
310
|
|
|
311
|
+
- **Buttons and the type scale in Material 3 Expressive** — `Typography` takes
|
|
312
|
+
the Material 3 scale (`display`, `headline`, `title`, `body`, `label`, each
|
|
313
|
+
`lg`, `md` and `sm`, plus `emphasized`) as Tailwind tokens: `text-title-md`
|
|
314
|
+
and `text-title-md-em` are utilities, and an app or a zone retunes a step
|
|
315
|
+
with CSS variables. The former variants are deprecated aliases (their sizes
|
|
316
|
+
changed) and the bare `h1` to `h6` read the scale. `Button` gains the `xl`
|
|
317
|
+
(56 px) and `2xl` (96 px) sizes, `shape` `round` or `square` with a spring
|
|
318
|
+
press morph, and `selected` (a toggle with an inverted shape and a solid
|
|
319
|
+
fill); every button has a 2 px focus outline, a neutral disabled look and a
|
|
320
|
+
44 px hit area on a coarse pointer. `IconButton` gets `size` `xs` to `xl`
|
|
321
|
+
and `width` `narrow`, `default` or `wide`, on Button's look and the shared
|
|
322
|
+
toggle fill. `ButtonGroup` gets `look="standard"` (the pressed button widens,
|
|
323
|
+
its neighbours give the width back) and a `size` its buttons share. Nothing
|
|
324
|
+
changes in core. React only; the Vue port is a `vue` issue. 3.11.0.
|
|
325
|
+
([Buttons & actions](components/buttons-and-actions.md),
|
|
326
|
+
[Typography](components/primitives.md#typography),
|
|
327
|
+
[Type scale](guides/theming.md#type-scale))
|
|
328
|
+
|
|
298
329
|
- **Icon backgrounds, celestial presets and illustrations** — `Background
|
|
299
330
|
preset="icons"` draws a pattern of icons from the packs, `iconStyle` taking
|
|
300
331
|
one style or a list and `iconMotif` choosing the layout.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -86,6 +86,10 @@ words in your error.
|
|
|
86
86
|
- [A test of the editor's More panel finds nothing (`[data-editor-more]`)](#a-test-of-the-editors-more-panel-finds-nothing-data-editor-more)
|
|
87
87
|
- [An editor, a composer or `PdfReader` looks different after upgrading, and fewer tools fit before More](#an-editor-a-composer-or-pdfreader-looks-different-after-upgrading-and-fewer-tools-fit-before-more)
|
|
88
88
|
- [An `IconButton` with `aria-pressed` now widens and fills when pressed](#an-iconbutton-with-aria-pressed-now-widens-and-fills-when-pressed)
|
|
89
|
+
- [Text got bigger or smaller after upgrading to 3.11 (`Typography` `huge-*`, `headline-*`, `title-*`, `caption`)](#text-got-bigger-or-smaller-after-upgrading-to-311-typography-huge--headline--title--caption)
|
|
90
|
+
- [`Type '"icon"' is not assignable to type '"xs" | "sm" | "default" | "lg" | "xl"'` when spreading Button props into an `IconButton`](#type-icon-is-not-assignable-to-type-xs--sm--default--lg--xl-when-spreading-button-props-into-an-iconbutton)
|
|
91
|
+
- [A pill `IconButton` toggle is the wrong width with a `size-*` class](#a-pill-iconbutton-toggle-is-the-wrong-width-with-a-size--class)
|
|
92
|
+
- [A `Button` with a height class of your own has the wrong corner radius](#a-button-with-a-height-class-of-your-own-has-the-wrong-corner-radius)
|
|
89
93
|
|
|
90
94
|
**Feedback**
|
|
91
95
|
|
|
@@ -1242,7 +1246,7 @@ inside the child element is clipped without one.
|
|
|
1242
1246
|
**Fix:** update. Then pick, for each long label: leave the ellipsis (give a
|
|
1243
1247
|
`title` so a sighted user can read it whole; the accessible name already
|
|
1244
1248
|
is), let it break onto lines with `wrap`, or give the button a width of
|
|
1245
|
-
your own through `className`. With `asChild`, put the label in a `<span
|
|
1249
|
+
your own through `className`. With `asChild`, put the label in a `<span>` (on a touch screen in Safari an `asChild` host is not clipped, to keep its 44 px hit area, so only a span gets the ellipsis):
|
|
1246
1250
|
|
|
1247
1251
|
```tsx
|
|
1248
1252
|
<Button title="Continue to the payment details">Continue to the payment details</Button>
|
|
@@ -1631,7 +1635,7 @@ screen.getByRole('button', { name: 'Bold', pressed: true });
|
|
|
1631
1635
|
### An `IconButton` with `aria-pressed` now widens and fills when pressed
|
|
1632
1636
|
|
|
1633
1637
|
**When:** after upgrading, an icon toggle (an `IconButton` with `aria-pressed`) grows into a filled pill when pressed and pushes its neighbours by 14 px.
|
|
1634
|
-
**Fix:** `morph="round"` keeps a filled circle that does not widen. A test that read the quiet pressed item's `::after` bar should read its background instead, or query the state: `getByRole('button', { name: 'Favourite', pressed: true })`.
|
|
1638
|
+
**Fix:** `morph="round"` keeps a filled circle that does not widen (a pill toggle's width follows its `size`: see [the wrong width with a `size-*` class](#a-pill-iconbutton-toggle-is-the-wrong-width-with-a-size--class)). A test that read the quiet pressed item's `::after` bar should read its background instead, or query the state: `getByRole('button', { name: 'Favourite', pressed: true })`.
|
|
1635
1639
|
|
|
1636
1640
|
```tsx
|
|
1637
1641
|
<IconButton morph="round" aria-label="Favourite" aria-pressed={on} onClick={toggle}>
|
|
@@ -1658,6 +1662,58 @@ A dialog opened from a bar button that is showing returns the focus to that butt
|
|
|
1658
1662
|
|
|
1659
1663
|
A tool that toggles is a `menuitemcheckbox`, a plain action or a dialog a `menuitem` (a dialog's has `aria-haspopup="dialog"`), the text colour, the highlight and the emoji a `menuitem` that opens their popover at More (a `dialog` named as the tool). The block type, the font, the callout types and the image's upload are submenus; the block type and the font list `menuitemradio` rows, and the submenu's row shows the current one after its name. A folded group of two or more rows is a `group` named by its label; a group of one row lists that row alone, with no group around it; a single-choice group stays a named radio group, even with one row. The alignments are a radio group named "Alignment" of `menuitemradio` rows, the current one checked (`getByRole('menuitemradio', { name: 'Align left' })`), while the bar keeps them as `aria-pressed` buttons. The text and highlight colour pickers are now a `dialog` (the library `Popover`, named as the tool), not a `menu`, in the bar too; a test of `[data-group-id="…"]` waits for its `hidden` attribute, not for it to leave. In the rail the groups are `data-slot="toolbar-group"` (they were `editor-toolbar-group`, which only `layout="wrap"` keeps) and the separators `data-slot="toolbar-separator"`: select a group by `data-group` or `data-group-id`.
|
|
1660
1664
|
|
|
1665
|
+
### Text got bigger or smaller after upgrading to 3.11 (`Typography` `huge-*`, `headline-*`, `title-*`, `caption`)
|
|
1666
|
+
|
|
1667
|
+
**When:** after the upgrade, a heading, a stat or a caption set with a `Typography` `variant` such as `title-medium` (18 to 16 px), `title-large` (20 to 22 px), `headline-large` (36 to 32 px), `huge-large` (96 to 57 px) or `caption` (10 to 11 px) has another size, line height and weight, and so do the bare `h1` to `h6` (`h1` 24 to 28 px, `h2` 20 to 24, `h3` 18 to 22).
|
|
1668
|
+
**Why:** `Typography` moved to the Material 3 type scale. The fifteen former variants are kept, deprecated, as aliases of the scale by name, so the sizes follow the scale; the headings read it too.
|
|
1669
|
+
**Fix:** pick the step you want by its scale name, which also silences the deprecation. The table of former names and sizes is in [Typography](components/primitives.md#typography); to keep an old size in one place, retune the step with CSS variables:
|
|
1670
|
+
|
|
1671
|
+
```tsx
|
|
1672
|
+
// before
|
|
1673
|
+
<Typography variant="title-medium">Next delivery</Typography>
|
|
1674
|
+
// after: the same step, written in the scale
|
|
1675
|
+
<Typography variant="title-md" emphasized>Next delivery</Typography>
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
```css
|
|
1679
|
+
/* or keep 18 px for one zone */
|
|
1680
|
+
.invoice { --text-title-md: 1.125rem; --text-title-md--line-height: 1.75rem; }
|
|
1681
|
+
```
|
|
1682
|
+
|
|
1683
|
+
### `Type '"icon"' is not assignable to type '"xs" | "sm" | "default" | "lg" | "xl"'` when spreading Button props into an `IconButton`
|
|
1684
|
+
|
|
1685
|
+
**When:** a wrapper spreads a `Button`'s props (`ComponentProps<typeof Button>`, `ButtonProps`) into an `IconButton` or `IconLinkButton`, and the compiler rejects `size` after the upgrade, or `shape`.
|
|
1686
|
+
**Why:** `IconButton` has its own typed `size` (`xs` to `xl`), which the `Button`'s `icon`, `icon-xs`, `icon-sm`, `icon-lg` and `2xl` are not; and `Button`'s `shape` is `round` or `square` where `IconButton`'s is an expressive shape name.
|
|
1687
|
+
**Fix:** drop `size` and `shape` before spreading, or pass the ones `IconButton` takes:
|
|
1688
|
+
|
|
1689
|
+
```tsx
|
|
1690
|
+
const { size, shape, ...rest } = props;
|
|
1691
|
+
return <IconButton size="lg" {...rest} />;
|
|
1692
|
+
```
|
|
1693
|
+
|
|
1694
|
+
### A pill `IconButton` toggle is the wrong width with a `size-*` class
|
|
1695
|
+
|
|
1696
|
+
**When:** an `IconButton` toggle (`aria-pressed`, `morph="pill"`) given a `size-*` class of your own (`size-12`) is as wide as its `size` says, not as your class does, when pressed.
|
|
1697
|
+
**Why:** the pill's pressed width follows the button's `size` (24 to 56 px, 36 px unset), so it is the same at every size without the old `::before`.
|
|
1698
|
+
**Fix:** give the button a `size` instead of a `size-*` class; use `width="wide"` for a longer resting button.
|
|
1699
|
+
|
|
1700
|
+
```tsx
|
|
1701
|
+
<IconButton size="xl" aria-pressed={on} aria-label="Favourite">
|
|
1702
|
+
<Star />
|
|
1703
|
+
</IconButton>
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
### A `Button` with a height class of your own has the wrong corner radius
|
|
1707
|
+
|
|
1708
|
+
**When:** a `Button` given a height of its own (`className="h-11"`) is a pill whose corners are those of its `size`: a 44 px button with the 18 px radius of a 36 px one, or a squarer pill than expected, and the corners spring toward the wrong size when pressed.
|
|
1709
|
+
**Why:** a round button's radius is half of `--btn-h`, which its `size` sets (36 px without one); a height class changes the box and not that variable.
|
|
1710
|
+
**Fix:** set `--btn-h` with your height class, or use `size`:
|
|
1711
|
+
|
|
1712
|
+
```tsx
|
|
1713
|
+
<Button className="[--btn-h:44px] h-(--btn-h)">Save</Button>
|
|
1714
|
+
<Button size="xl">Save</Button>
|
|
1715
|
+
```
|
|
1716
|
+
|
|
1661
1717
|
## Feedback
|
|
1662
1718
|
|
|
1663
1719
|
### An `EmptyState` with no `kind` shows "No Data Found" where it showed "Something Went Wrong"
|
package/lib/components/base.css
CHANGED
|
@@ -31,28 +31,43 @@
|
|
|
31
31
|
@apply dark:fill-foreground;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/* h1 to h6 read the type scale (type-scale.css); the fallbacks keep the
|
|
35
|
+
old sizes where the scale is not loaded (this file is shared with
|
|
36
|
+
@nxgt/material-vue, which has no scale yet). */
|
|
34
37
|
h1 {
|
|
35
|
-
font-size: var(--text-2xl);
|
|
38
|
+
font-size: var(--text-headline-md, var(--text-2xl));
|
|
39
|
+
line-height: var(--text-headline-md--line-height, inherit);
|
|
40
|
+
letter-spacing: var(--text-headline-md--letter-spacing, inherit);
|
|
36
41
|
font-weight: var(--font-weight-medium);
|
|
37
42
|
}
|
|
38
43
|
h2 {
|
|
39
|
-
font-size: var(--text-xl);
|
|
44
|
+
font-size: var(--text-headline-sm, var(--text-xl));
|
|
45
|
+
line-height: var(--text-headline-sm--line-height, inherit);
|
|
46
|
+
letter-spacing: var(--text-headline-sm--letter-spacing, inherit);
|
|
40
47
|
font-weight: var(--font-weight-medium);
|
|
41
48
|
}
|
|
42
49
|
h3 {
|
|
43
|
-
font-size: var(--text-lg);
|
|
50
|
+
font-size: var(--text-title-lg, var(--text-lg));
|
|
51
|
+
line-height: var(--text-title-lg--line-height, inherit);
|
|
52
|
+
letter-spacing: var(--text-title-lg--letter-spacing, inherit);
|
|
44
53
|
font-weight: var(--font-weight-medium);
|
|
45
54
|
}
|
|
46
55
|
h4 {
|
|
47
|
-
font-size: var(--text-base);
|
|
56
|
+
font-size: var(--text-title-md, var(--text-base));
|
|
57
|
+
line-height: var(--text-title-md--line-height, inherit);
|
|
58
|
+
letter-spacing: var(--text-title-md--letter-spacing, inherit);
|
|
48
59
|
font-weight: var(--font-weight-medium);
|
|
49
60
|
}
|
|
50
61
|
h5 {
|
|
51
|
-
font-size: var(--text-sm);
|
|
62
|
+
font-size: var(--text-title-sm, var(--text-sm));
|
|
63
|
+
line-height: var(--text-title-sm--line-height, inherit);
|
|
64
|
+
letter-spacing: var(--text-title-sm--letter-spacing, inherit);
|
|
52
65
|
font-weight: var(--font-weight-medium);
|
|
53
66
|
}
|
|
54
67
|
h6 {
|
|
55
|
-
font-size: var(--text-xs);
|
|
68
|
+
font-size: var(--text-label-md, var(--text-xs));
|
|
69
|
+
line-height: var(--text-label-md--line-height, inherit);
|
|
70
|
+
letter-spacing: var(--text-label-md--letter-spacing, inherit);
|
|
56
71
|
font-weight: var(--font-weight-medium);
|
|
57
72
|
}
|
|
58
73
|
/* A sidebar entry is a link styled as a menu entry: the prose link style
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
@import "./ui/widgets/editor/extensions/code/code-block.css";
|
|
52
52
|
@import "./ui/widgets/editor/extensions/code/code-block-head.css";
|
|
53
53
|
@import "./ui/actions/button-group/button-group.css";
|
|
54
|
+
@import "./ui/actions/button-group/button-group-standard.css";
|
|
54
55
|
/* ActivityLayout: the route transition (cross-fade, none under reduced motion). */
|
|
55
56
|
@import "./ui/layout/app-shell/route-transition.css";
|
|
56
57
|
@import "./ui/layout/app-shell/activity-backdrop.css";
|
|
@@ -79,8 +80,10 @@
|
|
|
79
80
|
@import "./ui/actions/split-button/split-button-sizes.css";
|
|
80
81
|
@import "./ui/actions/split-button/split-button-colors.css";
|
|
81
82
|
@import "./ui/actions/split-button/split-button-states.css";
|
|
82
|
-
|
|
83
|
-
@import "./ui/actions/
|
|
83
|
+
/* Button (sizes, shape morph, selected), the selected fill it shares with IconButton, and IconButton's own rules. */
|
|
84
|
+
@import "./ui/actions/morph-fill.css";
|
|
85
|
+
@import "./ui/actions/button/button.css";
|
|
86
|
+
@import "./ui/actions/icon-button/icon-button.css";
|
|
84
87
|
@import "./ui/actions/fab/fab.css";
|
|
85
88
|
@import "./ui/actions/fab/fab-tones.css";
|
|
86
89
|
@import "./ui/actions/fab/fab-menu.css";
|