@nxgt/material 3.105.0 → 3.107.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 +18 -0
- package/README.md +1 -1
- package/dist/components/ui/collections/data-table/data-table-items-tiles.css +14 -0
- package/dist/components/ui/collections/data-table/data-table-items.css +22 -0
- package/dist/{components-Cn14BksP.js → components-xpdWhhI5.js} +51 -45
- package/dist/components.js +1 -1
- package/dist/keypad.js +224 -207
- package/dist/lib/components/ui/actions/product-tile/product-tile-parts.d.ts +12 -0
- package/dist/lib/components/ui/actions/product-tile/product-tile.d.ts +7 -1
- package/dist/lib/components/ui/collections/data-table/layout-types.d.ts +14 -0
- package/dist/lib/components/ui/collections/data-table/types.d.ts +2 -3
- package/dist/lib/components/ui/widgets/keypad/keypad-above.d.ts +14 -0
- package/dist/lib/components/ui/widgets/keypad/keypad-display.d.ts +3 -1
- package/dist/lib/components/ui/widgets/keypad/keypad.types.d.ts +9 -2
- package/dist/main.js +1 -1
- package/dist/material.css +1 -1
- package/docs/components/buttons-and-actions.md +8 -1
- package/docs/components/data-table-filter-and-lists.md +1 -0
- package/docs/guides/cards-and-tiles.md +20 -0
- package/docs/guides/keypad.md +20 -6
- package/lib/components/ui/collections/data-table/data-table-items-tiles.css +14 -0
- package/lib/components/ui/collections/data-table/data-table-items.css +22 -0
- package/lib/components/ui/widgets/calculator/calculator.css +71 -6
- package/package.json +1 -1
|
@@ -1370,14 +1370,21 @@ import { Badge, ProductTile, ResponsiveGrid } from '@nxgt/material/components';
|
|
|
1370
1370
|
| `status` | `ReactNode` | none | The stock state, on its own line under the price (a `Badge`) |
|
|
1371
1371
|
| `image` | `string` | none | The photo's URL (a square one fits best), in a tinted 4:3 well, lazy loaded, with an empty `alt` (the title names the tile). If it fails to load, the toned `icon` shape takes its place |
|
|
1372
1372
|
| `imageFit` | `'contain' \| 'cover'` | `contain` | `contain` for a cut-out PNG or a packshot on white, `cover` for a full-bleed photo |
|
|
1373
|
-
| `icon`, `tone`, `shape` | `IconName`, `Tone`, `ShapeName` | `primary`, `squircle` | Without an `image` (or when it fails), a toned shape with this icon, in the same 4:3 well, so tiles with and without a photo share one height |
|
|
1373
|
+
| `icon`, `tone`, `shape` | `IconName`, `Tone`, `ShapeName` | `primary`, `squircle` | Without an `image` (or when it fails), a toned shape with this icon, in the same 4:3 well (3:2 with `size="sm"`), so tiles with and without a photo share one height |
|
|
1374
1374
|
| `media` | `ReactNode` | none | Your own media in place of the box; replaces `image` and `icon` |
|
|
1375
|
+
| `size` | `'md' \| 'sm'` | `md` | `sm` is the compact tile for a dense grid (`minItem` near 7.5 to 9rem, 6 to 7 columns on a desktop, 2 at 360 px): a 3:2 media box instead of 4:3, `p-1.5` instead of `p-2`, smaller name and price type, a smaller icon shape. It keeps the 44 px target and the accessible name |
|
|
1375
1376
|
| `selected` | `boolean` | `false` | `aria-pressed`, a tint and a bar at the start (the item is in the basket) |
|
|
1376
1377
|
| `disabled` | `boolean` | `false` | Dimmed and not tappable; its text, status included, is still read |
|
|
1377
1378
|
| `asChild` | `boolean` | `false` | Render inside the one child (a router `Link`): `<ProductTile asChild title="…"><Link to="…" /></ProductTile>`. `selected` is then `aria-current`, `disabled` is `aria-disabled`, `tabIndex={-1}` and a cancelled click, so a link leaves the Tab order and Enter does not follow it; `onClick` is not called |
|
|
1378
1379
|
|
|
1379
1380
|
The tile is one `button` named by its text: `getByRole('button', { name: /Orange juice.*1,500/ })`. It is a hairline card, at least 44 px high under a coarse pointer, and fills its grid cell (`h-full`): the name takes two lines and the status line is always reserved, so tiles of a row share one height. `minItem="9rem"` gives two columns at 360 px. It has a pressed state, a focus ring and a dark mode. It takes the `button`'s props, so `className` adds to it.
|
|
1380
1381
|
|
|
1382
|
+
```tsx
|
|
1383
|
+
<ResponsiveGrid minItem="7.5rem" gap="sm">
|
|
1384
|
+
<ProductTile size="sm" title="Orange juice 1 L" price="1,500" icon="bottle-water" />
|
|
1385
|
+
</ResponsiveGrid>
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1381
1388
|
**Storybook:** `Buttons & actions/ProductTile` · **Vue:** later
|
|
1382
1389
|
|
|
1383
1390
|
---
|
|
@@ -97,6 +97,7 @@ table enables, for typing your own column defs.
|
|
|
97
97
|
| `data` | `T[]` | — | rows; sorting, filtering and pagination run client-side |
|
|
98
98
|
| `layout` | `'table' \| 'cards' \| 'tiles' \| { phone, wide }` | `'table'` | `'cards'` lays the rows out as a list of cards, `'tiles'` as one column in a single surface ([Cards and tiles](../guides/cards-and-tiles.md)); both ignore `virtual`, `renderExpandedRow` and `showViewOptions` |
|
|
99
99
|
| `cardDensity` | `'comfortable' \| 'compact'` | `'comfortable'` | `compact` fits cards of at least `--nxgt-cards-min` (15rem), up to four a row, with a tighter padding; `layout="cards"` only ([Cards and tiles](../guides/cards-and-tiles.md#columns)) |
|
|
100
|
+
| `surface` | `'card' \| 'none'` | `'card'` | `'none'` drops the surface of a `cards` or `tiles` list so it sits on a card that already has one (no card in a card): the table's fill and padding go, tiles lose the list's border and corners (rows stay split by hairlines), cards lose their border and fill (one column stays split by hairlines) ([Cards and tiles](../guides/cards-and-tiles.md#inside-a-card)); the `table` layout ignores it |
|
|
100
101
|
| `renderCard` | `(row, { Title, Actions, Row, selected, locked, reason }) => ReactNode` | — | a card's content, required with `layout="cards"`; `Title` is the card's one link and its name; `Actions` is the trailing action slot (outside the link, at least 44px); `Row` (the compact record row) is also passed, laid out inside the card's own padding, with no height of its own |
|
|
101
102
|
| `renderTile` | `(row, { Title, Actions, Row, selected, locked, reason }) => ReactNode` | — | a tile's content, required with `layout="tiles"`; same `Title` as a card, or `Row`, the compact record row (title, subtitle, chips, trailing facts; see the cards and tiles guide) |
|
|
102
103
|
| `renderExpandedRow` | `(row) => ReactNode` | — | makes rows expandable; pair with the `expand` column |
|
|
@@ -302,6 +302,26 @@ on the list or an ancestor to tune it. The default `comfortable` keeps the one,
|
|
|
302
302
|
two, three columns above, whatever the token; tiles ignore `cardDensity`. It is
|
|
303
303
|
independent of `density`, which also tightens a card's padding and gap.
|
|
304
304
|
|
|
305
|
+
## Inside a card
|
|
306
|
+
|
|
307
|
+
A list draws its own surface: tiles are one bordered, filled box, cards each have
|
|
308
|
+
a border and a fill. Inside a page card or a `PanelCard` that is a card in a card.
|
|
309
|
+
`surface="none"` leaves it out:
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
<PanelCard title="Team">
|
|
313
|
+
<DataTable layout="tiles" surface="none" renderTile={…} … />
|
|
314
|
+
</PanelCard>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The table's own fill and padding go, tiles lose the list's border and rounded
|
|
318
|
+
corners (the rows stay split by hairlines), and cards lose their border and fill (in
|
|
319
|
+
one column they are split by hairlines). Hover and selected tints, the padding and
|
|
320
|
+
the focus ring are unchanged, so the rows sit directly on the parent card. The
|
|
321
|
+
default (`'card'`) is unchanged, and the `table` layout ignores it. `ServerTable`
|
|
322
|
+
has its own `surface` (for its root, with the tiles keeping their border) and does
|
|
323
|
+
not pass this one on.
|
|
324
|
+
|
|
305
325
|
## States
|
|
306
326
|
|
|
307
327
|
- **First load** (`loading` with no row): placeholder cards (or tiles), hidden from
|
package/docs/guides/keypad.md
CHANGED
|
@@ -173,6 +173,8 @@ written at `=`.
|
|
|
173
173
|
- The settlement row carries a tone: **success** while the payment covers the
|
|
174
174
|
total (change may be `0`), **warning** while an amount is still due, with the
|
|
175
175
|
figure emphasised (AA text on a tinted band, light and dark).
|
|
176
|
+
- The chips have a visible edge in the theme's AA primary text tone: 3:1
|
|
177
|
+
against the surface and 4.5:1 for the label, in light and dark.
|
|
176
178
|
- The keys follow one scheme: digits neutral, the editing keys (C, backspace)
|
|
177
179
|
one tone, the commit key filled primary, the quick amounts tonal chips in a
|
|
178
180
|
two-column grid (an odd last chip takes the full row; amounts never
|
|
@@ -182,7 +184,12 @@ written at `=`.
|
|
|
182
184
|
without one the commit key does nothing.
|
|
183
185
|
|
|
184
186
|
Use `entry="minor"` for a till that types cents, and `size="large"` for a
|
|
185
|
-
counter's touch screen.
|
|
187
|
+
counter's touch screen. A keypad docked permanently in a narrow column (a
|
|
188
|
+
till's quantity and cash pad beside the ticket) takes `size="compact"`:
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
<Keypad variant="cash" size="compact" total={17.35} currency="EUR" onTender={tender} />
|
|
192
|
+
```
|
|
186
193
|
|
|
187
194
|
## Props
|
|
188
195
|
|
|
@@ -198,10 +205,11 @@ counter's touch screen.
|
|
|
198
205
|
| `fractionDigits` | the currency's, else any | Decimals kept |
|
|
199
206
|
| `min`, `max` | none | See [Limits](#limits) |
|
|
200
207
|
| `keyboard` | `'focus'` | `'focus'`, `'global'` or `false` |
|
|
201
|
-
| `size` | `'comfortable'` | `'comfortable'` or `'
|
|
208
|
+
| `size` | `'comfortable'` | `'comfortable'`, `'large'` or `'compact'` (docked use) |
|
|
202
209
|
| `display` | `true`, `false` with a `binding` and no `operations` | Shows the amount above the keys |
|
|
203
210
|
| `commitLabel` | translated "Enter" ("Tender" in cash) | The commit key's name and text |
|
|
204
211
|
| `disabled` | `false` | Keys do nothing and say so (`aria-disabled`) |
|
|
212
|
+
| `placeholder` | none | Muted hint while the entry is empty, also with a `currency` (visual only, `aria-hidden`; not shown on an error) |
|
|
205
213
|
| `label` | "Keypad" | The group's accessible name |
|
|
206
214
|
| `variant`, `total`, `denominations`, `onTender` | `'standard'` | See [Cash](#cash) |
|
|
207
215
|
| `className` | | On the root |
|
|
@@ -210,10 +218,16 @@ Types: `KeypadProps`, `KeypadEntry`, `KeypadOperation`, `KeypadVariant`, `Keypad
|
|
|
210
218
|
|
|
211
219
|
## Sizing and styles
|
|
212
220
|
|
|
213
|
-
The keypad sizes by its own width with the calculator's bands (
|
|
214
|
-
360px, wider keys from 600px) and is at most 24rem wide.
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
The keypad sizes by its own width with the calculator's bands (a narrow band
|
|
222
|
+
under 360px, wider keys from 600px, automatic) and is at most 24rem wide. The
|
|
223
|
+
`size` prop is separate: `size="large"` gives
|
|
224
|
+
taller keys. `size="compact"` is for a keypad docked beside other content: 36px
|
|
225
|
+
keys, tighter gaps, a smaller display, and in cash a denser total and change
|
|
226
|
+
and the quick amounts (four at most) on one row, so a 4-row pad with its display fits about
|
|
227
|
+
320px of height (the cash variant a little more). On a coarse pointer the keys
|
|
228
|
+
and the quick amounts stay at 44px, so a touch till gets the tighter gaps and
|
|
229
|
+
display but not shorter keys. Colours and shapes follow the theme and dark mode
|
|
230
|
+
through `styles.css`; the key rules are shared with the calculator in `calculator.css`.
|
|
217
231
|
|
|
218
232
|
## Accessibility
|
|
219
233
|
|
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
border: 1px solid var(--item-border);
|
|
14
14
|
border-radius: var(--item-radius);
|
|
15
15
|
}
|
|
16
|
+
/* `surface="none"`: no surface of its own, for a list inside a card. The
|
|
17
|
+
* rows keep their hairlines; the tints still mix over the parent. */
|
|
18
|
+
[data-slot="data-table-tiles"][data-surface="none"] {
|
|
19
|
+
--item-surface: transparent;
|
|
20
|
+
margin: 0;
|
|
21
|
+
background: none;
|
|
22
|
+
border: 0;
|
|
23
|
+
border-radius: 0;
|
|
24
|
+
}
|
|
16
25
|
/* A ServerTable on a phone has no panel of its own: the tile list sits at
|
|
17
26
|
* the page gutter, in line with the heading (#2292). */
|
|
18
27
|
@media (max-width: 767.98px) {
|
|
@@ -52,6 +61,11 @@
|
|
|
52
61
|
border-end-start-radius: calc(var(--item-radius) - 1px);
|
|
53
62
|
border-end-end-radius: calc(var(--item-radius) - 1px);
|
|
54
63
|
}
|
|
64
|
+
/* `surface="none"`: no rounded first and last row either. */
|
|
65
|
+
[data-slot="data-table-tiles"][data-surface="none"]
|
|
66
|
+
> [data-slot="data-table-item"] {
|
|
67
|
+
border-radius: 0;
|
|
68
|
+
}
|
|
55
69
|
[data-slot="data-table-tiles"][data-selectable]
|
|
56
70
|
> [data-slot="data-table-item"] {
|
|
57
71
|
padding-inline-start: 3.25rem;
|
|
@@ -73,6 +73,12 @@
|
|
|
73
73
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
/* `surface="none"`: the list sits on its parent, with no padding of the
|
|
77
|
+
* table's own to take the ring room's 4px back from. */
|
|
78
|
+
[data-slot="table-wrapper"]:has(> [data-surface="none"]) {
|
|
79
|
+
margin-inline: 0;
|
|
80
|
+
width: 100% !important;
|
|
81
|
+
}
|
|
76
82
|
[data-slot="data-table-cards"][data-density="compact"] {
|
|
77
83
|
gap: var(--nxgt-cards-gap, 0.5rem);
|
|
78
84
|
}
|
|
@@ -120,6 +126,22 @@
|
|
|
120
126
|
> [data-slot="data-table-item"] {
|
|
121
127
|
padding: 0.75rem;
|
|
122
128
|
}
|
|
129
|
+
/* `surface="none"`: a card draws no border or fill of its own, for a list
|
|
130
|
+
* inside a card. In one column the cards are split by hairlines. */
|
|
131
|
+
[data-slot="data-table-cards"][data-surface="none"] {
|
|
132
|
+
--item-surface: transparent;
|
|
133
|
+
}
|
|
134
|
+
[data-slot="data-table-cards"][data-surface="none"]
|
|
135
|
+
> [data-slot="data-table-item"] {
|
|
136
|
+
border-color: transparent;
|
|
137
|
+
}
|
|
138
|
+
@container (max-width: 35.999rem) {
|
|
139
|
+
[data-slot="data-table-cards"][data-surface="none"]
|
|
140
|
+
> [data-slot="data-table-item"]
|
|
141
|
+
+ [data-slot="data-table-item"] {
|
|
142
|
+
border-top-color: var(--item-border);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
123
145
|
[data-slot="data-table-item"] a[data-slot="data-table-item-link"],
|
|
124
146
|
[data-slot="data-table-item"] button[data-slot="data-table-item-link"] {
|
|
125
147
|
color: inherit;
|
|
@@ -110,6 +110,24 @@
|
|
|
110
110
|
--calc-key: 4.5rem;
|
|
111
111
|
--calc-gap: 0.625rem;
|
|
112
112
|
}
|
|
113
|
+
/* Compact: a keypad docked beside other content. Shorter keys, tighter gaps,
|
|
114
|
+
* display and cash rows. A coarse pointer keeps 44px keys (the Touch rule in
|
|
115
|
+
* calculator-bands.css) and chips (the block after the cash rules). */
|
|
116
|
+
.nxgt-keypad[data-size="compact"] .nxgt-calc-body {
|
|
117
|
+
--calc-key: 2.25rem;
|
|
118
|
+
--calc-gap: 0.25rem;
|
|
119
|
+
--calc-radius: 1rem;
|
|
120
|
+
--calc-result: 1.75rem;
|
|
121
|
+
gap: 0.375rem;
|
|
122
|
+
}
|
|
123
|
+
.nxgt-keypad[data-size="compact"] .nxgt-calc-key {
|
|
124
|
+
border-radius: 1rem;
|
|
125
|
+
font-size: 1.125rem;
|
|
126
|
+
}
|
|
127
|
+
.nxgt-keypad[data-size="compact"] .nxgt-calc-key[data-role="operator"],
|
|
128
|
+
.nxgt-keypad[data-size="compact"] .nxgt-calc-key[data-role="equals"] {
|
|
129
|
+
border-radius: 9999px;
|
|
130
|
+
}
|
|
113
131
|
.nxgt-keypad-display {
|
|
114
132
|
display: block;
|
|
115
133
|
min-width: 0;
|
|
@@ -124,6 +142,15 @@
|
|
|
124
142
|
direction: ltr;
|
|
125
143
|
overflow-wrap: anywhere;
|
|
126
144
|
}
|
|
145
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-display {
|
|
146
|
+
padding: 0.375rem 0.875rem;
|
|
147
|
+
}
|
|
148
|
+
.nxgt-keypad-display [data-placeholder] {
|
|
149
|
+
color: var(--muted-foreground);
|
|
150
|
+
font-size: 0.5em;
|
|
151
|
+
vertical-align: middle;
|
|
152
|
+
font-weight: 400;
|
|
153
|
+
}
|
|
127
154
|
.nxgt-keypad-display[data-kind="error"] {
|
|
128
155
|
color: var(--destructive);
|
|
129
156
|
}
|
|
@@ -192,13 +219,14 @@
|
|
|
192
219
|
padding-inline: 0.875rem;
|
|
193
220
|
white-space: nowrap;
|
|
194
221
|
min-height: max(calc(var(--calc-key) * 0.8), 2.75rem);
|
|
195
|
-
border: 0;
|
|
196
222
|
border-radius: 9999px;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
223
|
+
/* --primary is dark navy in dark mode, so a mix of it vanishes into the
|
|
224
|
+
* surface. --primary-text is the theme's AA primary for text, light in
|
|
225
|
+
* dark: 28 % of it tints the chip, 60 % draws its 1px edge (3:1 against the
|
|
226
|
+
* surface in light and dark, text at 8:1 and more). */
|
|
227
|
+
border: 1px solid
|
|
228
|
+
color-mix(in oklab, var(--primary-text) 60%, var(--background));
|
|
229
|
+
background: color-mix(in oklab, var(--primary-text) 28%, var(--background));
|
|
202
230
|
color: var(--foreground);
|
|
203
231
|
font: inherit;
|
|
204
232
|
font-weight: 500;
|
|
@@ -213,3 +241,40 @@
|
|
|
213
241
|
outline: 2px solid var(--ring);
|
|
214
242
|
outline-offset: 2px;
|
|
215
243
|
}
|
|
244
|
+
|
|
245
|
+
/* Keypad, compact: the cash rows and the quick amounts take less height; the
|
|
246
|
+
* four amounts sit on one row. A coarse pointer keeps 44px chips. */
|
|
247
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-cash {
|
|
248
|
+
gap: 0.125rem;
|
|
249
|
+
}
|
|
250
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-cash > div {
|
|
251
|
+
padding-inline: 0.875rem;
|
|
252
|
+
}
|
|
253
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-cash dd {
|
|
254
|
+
font-size: 1rem;
|
|
255
|
+
}
|
|
256
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-cash [data-status] {
|
|
257
|
+
padding-block: 0.125rem;
|
|
258
|
+
border-radius: 0.75rem;
|
|
259
|
+
}
|
|
260
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-cash [data-status] dd {
|
|
261
|
+
font-size: 1.25rem;
|
|
262
|
+
}
|
|
263
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-shortcuts {
|
|
264
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
265
|
+
}
|
|
266
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-shortcuts button {
|
|
267
|
+
min-height: 2rem;
|
|
268
|
+
padding-inline: 0.25rem;
|
|
269
|
+
font-size: 0.875rem;
|
|
270
|
+
}
|
|
271
|
+
.nxgt-keypad[data-size="compact"]
|
|
272
|
+
.nxgt-keypad-shortcuts
|
|
273
|
+
button:last-child:nth-child(odd) {
|
|
274
|
+
grid-column: auto;
|
|
275
|
+
}
|
|
276
|
+
@media (pointer: coarse) {
|
|
277
|
+
.nxgt-keypad[data-size="compact"] .nxgt-keypad-shortcuts button {
|
|
278
|
+
min-height: 2.75rem;
|
|
279
|
+
}
|
|
280
|
+
}
|