@jasonshimmy/cer-material 0.1.2
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/README.md +989 -0
- package/dist/components/md-app-bar.d.ts +1 -0
- package/dist/components/md-badge.d.ts +1 -0
- package/dist/components/md-bottom-sheet.d.ts +1 -0
- package/dist/components/md-button-group.d.ts +1 -0
- package/dist/components/md-button.d.ts +1 -0
- package/dist/components/md-card.d.ts +1 -0
- package/dist/components/md-carousel.d.ts +1 -0
- package/dist/components/md-checkbox.d.ts +1 -0
- package/dist/components/md-chip.d.ts +1 -0
- package/dist/components/md-date-picker.d.ts +1 -0
- package/dist/components/md-dialog.d.ts +1 -0
- package/dist/components/md-divider.d.ts +1 -0
- package/dist/components/md-fab-menu.d.ts +1 -0
- package/dist/components/md-fab.d.ts +1 -0
- package/dist/components/md-icon-button.d.ts +1 -0
- package/dist/components/md-list.d.ts +1 -0
- package/dist/components/md-loading-indicator.d.ts +1 -0
- package/dist/components/md-menu.d.ts +1 -0
- package/dist/components/md-navigation-bar.d.ts +1 -0
- package/dist/components/md-navigation-drawer.d.ts +1 -0
- package/dist/components/md-navigation-rail.d.ts +1 -0
- package/dist/components/md-progress.d.ts +1 -0
- package/dist/components/md-radio.d.ts +1 -0
- package/dist/components/md-search.d.ts +1 -0
- package/dist/components/md-segmented-button.d.ts +1 -0
- package/dist/components/md-side-sheet.d.ts +1 -0
- package/dist/components/md-slider.d.ts +1 -0
- package/dist/components/md-snackbar.d.ts +1 -0
- package/dist/components/md-split-button.d.ts +1 -0
- package/dist/components/md-switch.d.ts +1 -0
- package/dist/components/md-tabs.d.ts +1 -0
- package/dist/components/md-text-field.d.ts +1 -0
- package/dist/components/md-time-picker.d.ts +1 -0
- package/dist/components/md-tooltip.d.ts +1 -0
- package/dist/composables/useControlledValue.d.ts +14 -0
- package/dist/composables/useEscapeKey.d.ts +16 -0
- package/dist/composables/useFocusReturn.d.ts +18 -0
- package/dist/composables/useFocusTrap.d.ts +31 -0
- package/dist/composables/useListKeyNav.d.ts +42 -0
- package/dist/composables/useScrollLock.d.ts +4 -0
- package/dist/index.cjs +5030 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6250 -0
- package/dist/index.js.map +1 -0
- package/dist/theme.cjs +137 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.ts +14 -0
- package/dist/theme.js +148 -0
- package/dist/theme.js.map +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
# @jasonshimmy/cer-material
|
|
2
|
+
|
|
3
|
+
Material Design 3 web components built on [`@jasonshimmy/custom-elements-runtime`](https://github.com/jshimkoski/custom-elements).
|
|
4
|
+
|
|
5
|
+
All components are standard custom elements — framework-agnostic and usable in plain HTML, React, Vue, Angular, Svelte, or any other environment.
|
|
6
|
+
|
|
7
|
+
Learn more about the author at [jasonshimmy.com](https://jasonshimmy.com) and check out the [changelog](./CHANGELOG.md) for recent updates.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @jasonshimmy/cer-material @jasonshimmy/custom-elements-runtime
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`@jasonshimmy/custom-elements-runtime` is a **peer dependency** and must be installed alongside this package.
|
|
18
|
+
|
|
19
|
+
### Font setup
|
|
20
|
+
|
|
21
|
+
Components use Material Symbols and Roboto. Add both to your HTML `<head>`:
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
25
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
26
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet" />
|
|
27
|
+
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20,400,0,0&display=swap" rel="stylesheet" />
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// Registers all components and applies the MD3 design token theme
|
|
36
|
+
import '@jasonshimmy/cer-material';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then use any component tag directly in your HTML or templates:
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<md-button variant="filled" label="Save"></md-button>
|
|
43
|
+
<md-text-field label="Email" type="email"></md-text-field>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Theme only
|
|
47
|
+
|
|
48
|
+
If you need the MD3 CSS custom properties without registering components:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import '@jasonshimmy/cer-material/theme';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or call it lazily:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { applyTheme } from '@jasonshimmy/cer-material/theme';
|
|
58
|
+
applyTheme();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Two-way bindings (`:model`)
|
|
64
|
+
|
|
65
|
+
All stateful components emit `update:*` events enabling concise two-way data binding with `:model` — no need to manually pair a `:prop` setter with a `@event` handler.
|
|
66
|
+
|
|
67
|
+
| Syntax | Syncs | Components |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `:model="${ref}"` | `value` | `md-text-field`, `md-slider`, `md-search`, `md-date-picker`, `md-time-picker` |
|
|
70
|
+
| `:model:checked="${ref}"` | `checked` | `md-checkbox` |
|
|
71
|
+
| `:model:selected="${ref}"` | `selected` | `md-switch`, `md-chip` (filter), `md-icon-button` (toggle), `md-segmented-button` |
|
|
72
|
+
| `:model:activeTab="${ref}"` | active tab id | `md-tabs` |
|
|
73
|
+
| `:model:active="${ref}"` | active item id | `md-navigation-bar`, `md-navigation-rail`, `md-navigation-drawer` |
|
|
74
|
+
| `:model:open="${ref}"` | open / visible | `md-dialog`, `md-menu`, `md-snackbar`, `md-bottom-sheet`, `md-side-sheet`, `md-fab-menu`, `md-navigation-drawer`, `md-date-picker`, `md-time-picker` |
|
|
75
|
+
|
|
76
|
+
All original `change`, `close`, `tab-change`, and other events still fire for backward compatibility — `:model` is additive.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// Verbose (still works)
|
|
80
|
+
<md-text-field :value="${email}" @change="${e => email = e.detail}"></md-text-field>
|
|
81
|
+
|
|
82
|
+
// Concise with :model
|
|
83
|
+
<md-text-field :model="${email}"></md-text-field>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **Radio groups**: `:model:checked` writes the radio's `value` string to the ref when selected, but does not derive the `checked` boolean. Use `:checked="${selected === radio.value}"` for the display state alongside `@change` for radio groups.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Design tokens
|
|
91
|
+
|
|
92
|
+
The theme is injected as `document.adoptedStyleSheets` and exposes every MD3 system token as a CSS custom property. Override them on `:root` to customise the palette:
|
|
93
|
+
|
|
94
|
+
```css
|
|
95
|
+
:root {
|
|
96
|
+
--md-sys-color-primary: #0057b8;
|
|
97
|
+
--md-sys-color-on-primary: #ffffff;
|
|
98
|
+
--md-sys-color-primary-container: #d6e4ff;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Dark mode is handled automatically via `@media (prefers-color-scheme: dark)`.
|
|
103
|
+
|
|
104
|
+
**Available token groups:**
|
|
105
|
+
|
|
106
|
+
| Group | Example properties |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Primary | `--md-sys-color-primary`, `--md-sys-color-on-primary`, `--md-sys-color-primary-container` |
|
|
109
|
+
| Secondary | `--md-sys-color-secondary`, `--md-sys-color-secondary-container` |
|
|
110
|
+
| Tertiary | `--md-sys-color-tertiary`, `--md-sys-color-tertiary-container` |
|
|
111
|
+
| Error | `--md-sys-color-error`, `--md-sys-color-error-container` |
|
|
112
|
+
| Surface | `--md-sys-color-surface`, `--md-sys-color-surface-variant`, `--md-sys-color-surface-container` |
|
|
113
|
+
| Outline | `--md-sys-color-outline`, `--md-sys-color-outline-variant` |
|
|
114
|
+
| Elevation | `--md-sys-elevation-1` … `--md-sys-elevation-4` |
|
|
115
|
+
| Typography | `--md-sys-typescale-font` |
|
|
116
|
+
| Shape | `--md-sys-shape-corner-none` … `--md-sys-shape-corner-full` |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Components
|
|
121
|
+
|
|
122
|
+
### `<md-app-bar>`
|
|
123
|
+
|
|
124
|
+
MD3 top app bar with four layout variants, a leading navigation icon, title area, and trailing action icons.
|
|
125
|
+
|
|
126
|
+
| Prop | Type | Default | Description |
|
|
127
|
+
|---|---|---|---|
|
|
128
|
+
| `variant` | `'small' \| 'medium' \| 'large' \| 'center'` | `'small'` | Layout and title size |
|
|
129
|
+
| `title` | `string` | `''` | Title text |
|
|
130
|
+
| `leading-icon` | `string` | `'menu'` | Material Symbol for the leading nav button |
|
|
131
|
+
| `trailing-icons` | `string[]` | `[]` | Array of Material Symbol names for trailing action buttons |
|
|
132
|
+
| `scrolled` | `boolean` | `false` | Applies elevated/tinted scroll state |
|
|
133
|
+
|
|
134
|
+
**Slots:** `title` — custom title content; `trailing` — completely custom trailing area.
|
|
135
|
+
|
|
136
|
+
**Events:** `nav` — leading icon clicked; `action` `(detail: string)` — the clicked icon name.
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<md-app-bar
|
|
140
|
+
variant="small"
|
|
141
|
+
title="Inbox"
|
|
142
|
+
leading-icon="menu"
|
|
143
|
+
:bind="${{ trailingIcons: ['search', 'more_vert'] }}"
|
|
144
|
+
@nav="${openDrawer}"
|
|
145
|
+
@action="${handleAction}"
|
|
146
|
+
></md-app-bar>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### `<md-badge>`
|
|
152
|
+
|
|
153
|
+
Overlays a numeric label or a small dot indicator on top of slotted content.
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Default | Description |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| `value` | `string \| number` | `''` | Badge text; empty renders a small dot |
|
|
158
|
+
| `small` | `boolean` | `false` | Forces the small dot style regardless of `value` |
|
|
159
|
+
|
|
160
|
+
**Slots:** default — the element the badge attaches to.
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<md-badge value="3">
|
|
164
|
+
<md-icon-button icon="notifications"></md-icon-button>
|
|
165
|
+
</md-badge>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### `<md-bottom-sheet>`
|
|
171
|
+
|
|
172
|
+
Slide-up bottom sheet with optional drag-to-dismiss, focus trap, and scroll lock.
|
|
173
|
+
|
|
174
|
+
| Prop | Type | Default | Description |
|
|
175
|
+
|---|---|---|---|
|
|
176
|
+
| `open` | `boolean` | `false` | Shows/hides the sheet |
|
|
177
|
+
| `headline` | `string` | `''` | Sheet header text |
|
|
178
|
+
| `show-handle` | `boolean` | `true` | Renders the drag handle pill |
|
|
179
|
+
| `variant` | `'standard' \| 'modal'` | `'standard'` | `modal` adds a scrim overlay |
|
|
180
|
+
|
|
181
|
+
**Slots:** default — sheet body content.
|
|
182
|
+
|
|
183
|
+
**Events:** `close` — sheet dismissed.
|
|
184
|
+
|
|
185
|
+
```html
|
|
186
|
+
<md-bottom-sheet
|
|
187
|
+
:model:open="${isOpen}"
|
|
188
|
+
headline="Options"
|
|
189
|
+
variant="modal"
|
|
190
|
+
>
|
|
191
|
+
<p>Your content here</p>
|
|
192
|
+
</md-bottom-sheet>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### `<md-button>`
|
|
198
|
+
|
|
199
|
+
MD3 button in five style variants with optional leading icon.
|
|
200
|
+
|
|
201
|
+
| Prop | Type | Default | Description |
|
|
202
|
+
|---|---|---|---|
|
|
203
|
+
| `variant` | `'filled' \| 'outlined' \| 'text' \| 'elevated' \| 'tonal'` | `'filled'` | Visual style |
|
|
204
|
+
| `label` | `string` | `''` | Button text |
|
|
205
|
+
| `icon` | `string` | `''` | Leading Material Symbol name |
|
|
206
|
+
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type |
|
|
207
|
+
| `disabled` | `boolean` | `false` | Disables the button |
|
|
208
|
+
|
|
209
|
+
```html
|
|
210
|
+
<md-button variant="filled" label="Save" icon="save"></md-button>
|
|
211
|
+
<md-button variant="outlined" label="Cancel"></md-button>
|
|
212
|
+
<md-button variant="text" label="Learn more"></md-button>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### `<md-button-group>`
|
|
218
|
+
|
|
219
|
+
Horizontally connected group of buttons sharing a unified variant style.
|
|
220
|
+
|
|
221
|
+
| Prop | Type | Default | Description |
|
|
222
|
+
|---|---|---|---|
|
|
223
|
+
| `variant` | `'filled' \| 'outlined' \| 'tonal' \| 'text' \| 'elevated'` | `'outlined'` | Shared style for all items |
|
|
224
|
+
| `disabled` | `boolean` | `false` | Disables all buttons |
|
|
225
|
+
| `items` | `{ id: string; label: string; icon?: string; disabled?: boolean }[]` | `[]` | Button definitions |
|
|
226
|
+
|
|
227
|
+
**Events:** `click` `(detail: { id: string; index: number })` — a button was clicked.
|
|
228
|
+
|
|
229
|
+
```html
|
|
230
|
+
<md-button-group
|
|
231
|
+
variant="outlined"
|
|
232
|
+
:bind="${{ items: [
|
|
233
|
+
{ id: 'day', label: 'Day' },
|
|
234
|
+
{ id: 'week', label: 'Week' },
|
|
235
|
+
{ id: 'month', label: 'Month' },
|
|
236
|
+
] }}"
|
|
237
|
+
@click="${handleGroupClick}"
|
|
238
|
+
></md-button-group>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### `<md-card>`
|
|
244
|
+
|
|
245
|
+
MD3 card container that optionally becomes an interactive button with a ripple state layer.
|
|
246
|
+
|
|
247
|
+
| Prop | Type | Default | Description |
|
|
248
|
+
|---|---|---|---|
|
|
249
|
+
| `variant` | `'elevated' \| 'filled' \| 'outlined'` | `'elevated'` | Visual style |
|
|
250
|
+
| `clickable` | `boolean` | `false` | Makes the whole card an accessible button |
|
|
251
|
+
|
|
252
|
+
**Slots:** default — card content.
|
|
253
|
+
|
|
254
|
+
**Events:** `click` — emitted when `clickable` is `true`.
|
|
255
|
+
|
|
256
|
+
```html
|
|
257
|
+
<md-card variant="outlined" clickable @click="${openDetail}">
|
|
258
|
+
<h3>Card Title</h3>
|
|
259
|
+
<p>Supporting text goes here.</p>
|
|
260
|
+
</md-card>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### `<md-carousel>`
|
|
266
|
+
|
|
267
|
+
Horizontal snap-scroll carousel rendering image or color-placeholder cards with overlay text.
|
|
268
|
+
|
|
269
|
+
| Prop | Type | Default | Description |
|
|
270
|
+
|---|---|---|---|
|
|
271
|
+
| `items` | `{ id: string; headline?: string; supportingText?: string; image?: string; color?: string }[]` | `[]` | Carousel item data |
|
|
272
|
+
| `variant` | `'multi-browse' \| 'uncontained' \| 'full-screen'` | `'multi-browse'` | Layout density |
|
|
273
|
+
|
|
274
|
+
**Events:** `select` `(detail: string)` — the `id` of the clicked card.
|
|
275
|
+
|
|
276
|
+
```html
|
|
277
|
+
<md-carousel
|
|
278
|
+
variant="multi-browse"
|
|
279
|
+
:bind="${{ items: [
|
|
280
|
+
{ id: '1', headline: 'Mountains', image: '/img/mountains.jpg' },
|
|
281
|
+
{ id: '2', headline: 'Ocean', color: '#0077b6' },
|
|
282
|
+
] }}"
|
|
283
|
+
@select="${handleSelect}"
|
|
284
|
+
></md-carousel>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### `<md-checkbox>`
|
|
290
|
+
|
|
291
|
+
MD3 checkbox with animated check/dash icon and an optional inline text label.
|
|
292
|
+
|
|
293
|
+
| Prop | Type | Default | Description |
|
|
294
|
+
|---|---|---|---|
|
|
295
|
+
| `checked` | `boolean` | `false` | Checked state |
|
|
296
|
+
| `indeterminate` | `boolean` | `false` | Indeterminate (dash) state |
|
|
297
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
298
|
+
| `label` | `string` | `''` | Inline label text |
|
|
299
|
+
|
|
300
|
+
**Events:** `change` `(detail: boolean)` — new checked state.
|
|
301
|
+
|
|
302
|
+
```html
|
|
303
|
+
<md-checkbox
|
|
304
|
+
label="Accept terms"
|
|
305
|
+
:model:checked="${accepted}"
|
|
306
|
+
></md-checkbox>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### `<md-chip>`
|
|
312
|
+
|
|
313
|
+
MD3 chip in four variants — assist, filter (toggle), input (removable), and suggestion.
|
|
314
|
+
|
|
315
|
+
| Prop | Type | Default | Description |
|
|
316
|
+
|---|---|---|---|
|
|
317
|
+
| `variant` | `'assist' \| 'filter' \| 'input' \| 'suggestion'` | `'assist'` | Chip type |
|
|
318
|
+
| `label` | `string` | `''` | Chip text |
|
|
319
|
+
| `icon` | `string` | `''` | Leading Material Symbol |
|
|
320
|
+
| `selected` | `boolean` | `false` | Active state (filter variant) |
|
|
321
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
322
|
+
|
|
323
|
+
**Events:** `click`; `remove` — the × button was tapped (input variant only).
|
|
324
|
+
|
|
325
|
+
```html
|
|
326
|
+
<md-chip variant="filter" label="Unread" :model:selected="${filterUnread}"></md-chip>
|
|
327
|
+
<md-chip variant="input" label="jason@example.com" @remove="${removeChip}"></md-chip>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
### `<md-date-picker>`
|
|
333
|
+
|
|
334
|
+
Full MD3 date picker with calendar grid, month/year navigation, optional date range, and min/max constraints.
|
|
335
|
+
|
|
336
|
+
| Prop | Type | Default | Description |
|
|
337
|
+
|---|---|---|---|
|
|
338
|
+
| `variant` | `'dialog' \| 'docked'` | `'dialog'` | Modal dialog or inline docked layout |
|
|
339
|
+
| `value` | `string` | `''` | Selected date (`YYYY-MM-DD`) |
|
|
340
|
+
| `range-start` | `string` | `''` | Range start date (`YYYY-MM-DD`) |
|
|
341
|
+
| `range-end` | `string` | `''` | Range end date (`YYYY-MM-DD`) |
|
|
342
|
+
| `min` | `string` | `''` | Minimum selectable date |
|
|
343
|
+
| `max` | `string` | `''` | Maximum selectable date |
|
|
344
|
+
| `open` | `boolean` | `false` | Controls visibility |
|
|
345
|
+
| `label` | `string` | `'Select date'` | Trigger field label |
|
|
346
|
+
| `aria-label` | `string` | `'Date picker'` | Accessible label |
|
|
347
|
+
|
|
348
|
+
**Events:** `change` `(detail: string)` — selected date in `YYYY-MM-DD` format; `close`.
|
|
349
|
+
|
|
350
|
+
```html
|
|
351
|
+
<md-date-picker
|
|
352
|
+
label="Start date"
|
|
353
|
+
:model="${startDate}"
|
|
354
|
+
min="2024-01-01"
|
|
355
|
+
:model:open="${pickerOpen}"
|
|
356
|
+
></md-date-picker>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
### `<md-dialog>`
|
|
362
|
+
|
|
363
|
+
MD3 modal dialog with scale-in animation, optional icon/headline, scrollable body, and an actions slot.
|
|
364
|
+
|
|
365
|
+
| Prop | Type | Default | Description |
|
|
366
|
+
|---|---|---|---|
|
|
367
|
+
| `open` | `boolean` | `false` | Shows/hides the dialog |
|
|
368
|
+
| `headline` | `string` | `''` | Dialog title |
|
|
369
|
+
| `icon` | `string` | `''` | Leading Material Symbol in the header |
|
|
370
|
+
|
|
371
|
+
**Slots:** default — scrollable body content; `actions` — action buttons row.
|
|
372
|
+
|
|
373
|
+
**Events:** `close` — dialog dismissed.
|
|
374
|
+
|
|
375
|
+
```html
|
|
376
|
+
<md-dialog :model:open="${dialogOpen}" headline="Delete item?">
|
|
377
|
+
<p>This action cannot be undone.</p>
|
|
378
|
+
<div slot="actions">
|
|
379
|
+
<md-button variant="text" label="Cancel" @click="${() => dialogOpen = false}"></md-button>
|
|
380
|
+
<md-button variant="filled" label="Delete" @click="${confirmDelete}"></md-button>
|
|
381
|
+
</div>
|
|
382
|
+
</md-dialog>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
### `<md-divider>`
|
|
388
|
+
|
|
389
|
+
Thin horizontal or vertical separator rule with inset variants for list and layout use.
|
|
390
|
+
|
|
391
|
+
| Prop | Type | Default | Description |
|
|
392
|
+
|---|---|---|---|
|
|
393
|
+
| `inset` | `boolean` | `false` | Insets both ends |
|
|
394
|
+
| `inset-start` | `boolean` | `false` | Insets the leading end only |
|
|
395
|
+
| `inset-end` | `boolean` | `false` | Insets the trailing end only |
|
|
396
|
+
| `vertical` | `boolean` | `false` | Renders as a vertical rule |
|
|
397
|
+
|
|
398
|
+
```html
|
|
399
|
+
<md-divider></md-divider>
|
|
400
|
+
<md-divider inset-start></md-divider>
|
|
401
|
+
<md-divider vertical></md-divider>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
### `<md-fab>`
|
|
407
|
+
|
|
408
|
+
MD3 Floating Action Button in four color variants, four sizes, and an extended (icon + label) pill form.
|
|
409
|
+
|
|
410
|
+
| Prop | Type | Default | Description |
|
|
411
|
+
|---|---|---|---|
|
|
412
|
+
| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'surface'` | `'primary'` | Background color role |
|
|
413
|
+
| `size` | `'small' \| 'regular' \| 'medium' \| 'large'` | `'regular'` | Button size |
|
|
414
|
+
| `icon` | `string` | `'add'` | Material Symbol |
|
|
415
|
+
| `label` | `string` | `''` | Non-empty value makes it an extended FAB |
|
|
416
|
+
| `lowered` | `boolean` | `false` | Reduces elevation |
|
|
417
|
+
| `aria-label` | `string` | `''` | Accessible label |
|
|
418
|
+
|
|
419
|
+
**Events:** `click`
|
|
420
|
+
|
|
421
|
+
```html
|
|
422
|
+
<md-fab icon="edit" variant="primary"></md-fab>
|
|
423
|
+
<md-fab icon="add" label="Compose" variant="secondary" size="regular"></md-fab>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
### `<md-fab-menu>`
|
|
429
|
+
|
|
430
|
+
FAB speed dial that expands upward to reveal labeled action items. Only one instance can be open at a time.
|
|
431
|
+
|
|
432
|
+
| Prop | Type | Default | Description |
|
|
433
|
+
|---|---|---|---|
|
|
434
|
+
| `icon` | `string` | `'add'` | Material Symbol for the collapsed state |
|
|
435
|
+
| `close-icon` | `string` | `'close'` | Material Symbol for the expanded state |
|
|
436
|
+
| `variant` | `'primary' \| 'secondary' \| 'tertiary'` | `'primary'` | FAB color role |
|
|
437
|
+
| `open` | `boolean` | `false` | Expanded state |
|
|
438
|
+
| `items` | `{ id: string; icon: string; label: string; disabled?: boolean }[]` | `[]` | Action item definitions |
|
|
439
|
+
| `aria-label` | `string` | `'Speed dial'` | Accessible label |
|
|
440
|
+
|
|
441
|
+
**Events:** `open`; `close`; `select` `(detail: { id: string })` — an item was chosen.
|
|
442
|
+
|
|
443
|
+
```html
|
|
444
|
+
<md-fab-menu
|
|
445
|
+
:model:open="${fabOpen}"
|
|
446
|
+
:bind="${{ items: [
|
|
447
|
+
{ id: 'share', icon: 'share', label: 'Share' },
|
|
448
|
+
{ id: 'copy', icon: 'content_copy', label: 'Copy link' },
|
|
449
|
+
] }}"
|
|
450
|
+
@select="${handleFabSelect}"
|
|
451
|
+
></md-fab-menu>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
### `<md-icon-button>`
|
|
457
|
+
|
|
458
|
+
MD3 icon button with four style variants and optional toggle (pressed/selected) behaviour.
|
|
459
|
+
|
|
460
|
+
| Prop | Type | Default | Description |
|
|
461
|
+
|---|---|---|---|
|
|
462
|
+
| `variant` | `'standard' \| 'filled' \| 'tonal' \| 'outlined'` | `'standard'` | Visual style |
|
|
463
|
+
| `icon` | `string` | `'more_vert'` | Material Symbol |
|
|
464
|
+
| `selected` | `boolean` | `false` | Pressed/selected state (toggle mode) |
|
|
465
|
+
| `selected-icon` | `string` | `''` | Alternate symbol shown when selected |
|
|
466
|
+
| `toggle` | `boolean` | `false` | Enables toggle behaviour |
|
|
467
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
468
|
+
| `aria-label` | `string` | `''` | Accessible label |
|
|
469
|
+
|
|
470
|
+
**Events:** `click`; `change` `(detail: boolean)` — new selected state (toggle mode).
|
|
471
|
+
|
|
472
|
+
```html
|
|
473
|
+
<md-icon-button icon="favorite_border" selected-icon="favorite" toggle :model:selected="${isFav}"></md-icon-button>
|
|
474
|
+
<md-icon-button icon="delete" variant="outlined" @click="${onDelete}"></md-icon-button>
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### `<md-list>` / `<md-list-item>`
|
|
480
|
+
|
|
481
|
+
MD3 list container and individual list items with leading/trailing content, headlines, supporting text, and selected/disabled states.
|
|
482
|
+
|
|
483
|
+
#### `<md-list>`
|
|
484
|
+
|
|
485
|
+
| Prop | Type | Default | Description |
|
|
486
|
+
|---|---|---|---|
|
|
487
|
+
| `role` | `string` | `'list'` | ARIA role |
|
|
488
|
+
|
|
489
|
+
**Slots:** default — `<md-list-item>` children.
|
|
490
|
+
|
|
491
|
+
#### `<md-list-item>`
|
|
492
|
+
|
|
493
|
+
| Prop | Type | Default | Description |
|
|
494
|
+
|---|---|---|---|
|
|
495
|
+
| `headline` | `string` | `''` | Primary text |
|
|
496
|
+
| `supporting-text` | `string` | `''` | Secondary text |
|
|
497
|
+
| `leading-icon` | `string` | `''` | Leading Material Symbol |
|
|
498
|
+
| `trailing-icon` | `string` | `''` | Trailing Material Symbol |
|
|
499
|
+
| `trailing-supporting-text` | `string` | `''` | Trailing metadata text |
|
|
500
|
+
| `disabled` | `boolean` | `false` | Disables the item |
|
|
501
|
+
| `selected` | `boolean` | `false` | Highlights the item as active |
|
|
502
|
+
| `type` | `'text' \| 'link' \| 'checkbox' \| 'radio'` | `'text'` | Item interaction type |
|
|
503
|
+
|
|
504
|
+
**Slots:** `leading` — custom leading content; default — inline content after headline; `trailing` — custom trailing content.
|
|
505
|
+
|
|
506
|
+
**Events:** `click`
|
|
507
|
+
|
|
508
|
+
```html
|
|
509
|
+
<md-list>
|
|
510
|
+
<md-list-item headline="Inbox" leading-icon="inbox" trailing-supporting-text="24"></md-list-item>
|
|
511
|
+
<md-list-item headline="Sent" leading-icon="send" selected></md-list-item>
|
|
512
|
+
<md-list-item headline="Trash" leading-icon="delete" disabled></md-list-item>
|
|
513
|
+
</md-list>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
### `<md-loading-indicator>`
|
|
519
|
+
|
|
520
|
+
MD3 four-color indeterminate circular spinner.
|
|
521
|
+
|
|
522
|
+
| Prop | Type | Default | Description |
|
|
523
|
+
|---|---|---|---|
|
|
524
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Spinner size |
|
|
525
|
+
| `aria-label` | `string` | `'Loading'` | Accessible announcement text |
|
|
526
|
+
|
|
527
|
+
```html
|
|
528
|
+
<md-loading-indicator size="large"></md-loading-indicator>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
### `<md-menu>`
|
|
534
|
+
|
|
535
|
+
Contextual dropdown menu with four anchor positions, keyboard navigation, and divider support.
|
|
536
|
+
|
|
537
|
+
| Prop | Type | Default | Description |
|
|
538
|
+
|---|---|---|---|
|
|
539
|
+
| `open` | `boolean` | `false` | Shows/hides the menu |
|
|
540
|
+
| `items` | `{ id: string; label: string; icon?: string; disabled?: boolean; divider?: boolean }[]` | `[]` | Menu item definitions |
|
|
541
|
+
| `anchor` | `'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end'` | `'bottom-start'` | Popup position relative to the trigger |
|
|
542
|
+
|
|
543
|
+
**Slots:** `trigger` — the element that opens the menu.
|
|
544
|
+
|
|
545
|
+
**Events:** `select` `(detail: string)` — the `id` of the chosen item; `close`.
|
|
546
|
+
|
|
547
|
+
```html
|
|
548
|
+
<md-menu
|
|
549
|
+
:model:open="${menuOpen}"
|
|
550
|
+
:bind="${{ items: [
|
|
551
|
+
{ id: 'edit', label: 'Edit', icon: 'edit' },
|
|
552
|
+
{ id: 'dup', label: 'Duplicate', icon: 'content_copy' },
|
|
553
|
+
{ id: 'del', label: 'Delete', icon: 'delete', divider: true },
|
|
554
|
+
] }}"
|
|
555
|
+
@select="${handleMenuSelect}"
|
|
556
|
+
>
|
|
557
|
+
<md-icon-button slot="trigger" icon="more_vert" @click="${() => menuOpen = !menuOpen}"></md-icon-button>
|
|
558
|
+
</md-menu>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
### `<md-navigation-bar>`
|
|
564
|
+
|
|
565
|
+
MD3 bottom navigation bar for mobile with active pill indicator, filled icon for the active item, and badge support.
|
|
566
|
+
|
|
567
|
+
| Prop | Type | Default | Description |
|
|
568
|
+
|---|---|---|---|
|
|
569
|
+
| `items` | `{ id: string; label: string; icon: string; badge?: string }[]` | `[]` | Destination definitions |
|
|
570
|
+
| `active` | `string` | `''` | `id` of the active destination |
|
|
571
|
+
|
|
572
|
+
**Events:** `change` `(detail: string)` — the `id` of the selected destination.
|
|
573
|
+
|
|
574
|
+
```html
|
|
575
|
+
<md-navigation-bar
|
|
576
|
+
:model:active="${activeTab}"
|
|
577
|
+
:bind="${{ items: [
|
|
578
|
+
{ id: 'home', label: 'Home', icon: 'home' },
|
|
579
|
+
{ id: 'search', label: 'Search', icon: 'search' },
|
|
580
|
+
{ id: 'profile', label: 'Profile', icon: 'person', badge: '2' },
|
|
581
|
+
] }}"
|
|
582
|
+
></md-navigation-bar>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### `<md-navigation-drawer>`
|
|
588
|
+
|
|
589
|
+
MD3 navigation drawer in standard (in-layout, width-animated) or modal (slide-in overlay) form with section headers and dividers.
|
|
590
|
+
|
|
591
|
+
| Prop | Type | Default | Description |
|
|
592
|
+
|---|---|---|---|
|
|
593
|
+
| `open` | `boolean` | `false` | Shows/hides the drawer |
|
|
594
|
+
| `headline` | `string` | `''` | Header text |
|
|
595
|
+
| `variant` | `'standard' \| 'modal'` | `'standard'` | `modal` adds a scrim |
|
|
596
|
+
| `items` | `{ id?: string; label?: string; icon?: string; section?: string; divider?: boolean; disabled?: boolean }[]` | `[]` | Navigation item definitions |
|
|
597
|
+
| `active` | `string` | `''` | `id` of the active item |
|
|
598
|
+
|
|
599
|
+
**Slots:** default — extra content below the item list.
|
|
600
|
+
|
|
601
|
+
**Events:** `close`; `change` `(detail: string)` — the `id` of the selected item.
|
|
602
|
+
|
|
603
|
+
```html
|
|
604
|
+
<md-navigation-drawer
|
|
605
|
+
variant="modal"
|
|
606
|
+
headline="Mail"
|
|
607
|
+
:model:open="${drawerOpen}"
|
|
608
|
+
:model:active="${currentRoute}"
|
|
609
|
+
:bind="${{ items: navItems }}"
|
|
610
|
+
@change="${e => navigate(e.detail)}"
|
|
611
|
+
></md-navigation-drawer>
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
### `<md-navigation-rail>`
|
|
617
|
+
|
|
618
|
+
MD3 vertical navigation rail for tablet/desktop with optional top FAB and hamburger menu icon.
|
|
619
|
+
|
|
620
|
+
| Prop | Type | Default | Description |
|
|
621
|
+
|---|---|---|---|
|
|
622
|
+
| `items` | `{ id: string; label: string; icon: string; badge?: string }[]` | `[]` | Destination definitions |
|
|
623
|
+
| `active` | `string` | `''` | `id` of the active destination |
|
|
624
|
+
| `fab` | `boolean` | `false` | Shows a FAB at the top |
|
|
625
|
+
| `fab-icon` | `string` | `'add'` | FAB Material Symbol |
|
|
626
|
+
| `menu-icon` | `boolean` | `false` | Shows a hamburger menu icon |
|
|
627
|
+
|
|
628
|
+
**Events:** `change` `(detail: string)` — the `id` of the selected destination; `fab-click`; `menu-click`.
|
|
629
|
+
|
|
630
|
+
```html
|
|
631
|
+
<md-navigation-rail
|
|
632
|
+
:model:active="${activeRoute}"
|
|
633
|
+
menu-icon
|
|
634
|
+
:bind="${{ items: [
|
|
635
|
+
{ id: 'inbox', label: 'Inbox', icon: 'inbox' },
|
|
636
|
+
{ id: 'sent', label: 'Sent', icon: 'send' },
|
|
637
|
+
] }}"
|
|
638
|
+
@change="${e => navigate(e.detail)}"
|
|
639
|
+
></md-navigation-rail>
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
### `<md-progress>`
|
|
645
|
+
|
|
646
|
+
MD3 progress indicator — linear (with buffer track) or circular — in determinate or indeterminate mode.
|
|
647
|
+
|
|
648
|
+
| Prop | Type | Default | Description |
|
|
649
|
+
|---|---|---|---|
|
|
650
|
+
| `variant` | `'linear' \| 'circular'` | `'linear'` | Indicator shape |
|
|
651
|
+
| `value` | `number` | `0` | Progress value (0–100) |
|
|
652
|
+
| `indeterminate` | `boolean` | `false` | Animated looping mode |
|
|
653
|
+
| `buffer` | `number` | `100` | Buffer track value 0–100 (linear only) |
|
|
654
|
+
| `aria-label` | `string` | `'Loading'` | Accessible label |
|
|
655
|
+
|
|
656
|
+
```html
|
|
657
|
+
<md-progress variant="linear" value="65"></md-progress>
|
|
658
|
+
<md-progress variant="circular" indeterminate></md-progress>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
---
|
|
662
|
+
|
|
663
|
+
### `<md-radio>`
|
|
664
|
+
|
|
665
|
+
MD3 radio button with animated inner circle, `name`/`value` for grouping, and an optional inline label.
|
|
666
|
+
|
|
667
|
+
| Prop | Type | Default | Description |
|
|
668
|
+
|---|---|---|---|
|
|
669
|
+
| `checked` | `boolean` | `false` | Selected state |
|
|
670
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
671
|
+
| `name` | `string` | `''` | Radio group name |
|
|
672
|
+
| `value` | `string` | `''` | Form value |
|
|
673
|
+
| `label` | `string` | `''` | Inline label text |
|
|
674
|
+
|
|
675
|
+
**Events:** `change` `(detail: string)` — the `value` of the selected radio.
|
|
676
|
+
|
|
677
|
+
```html
|
|
678
|
+
<md-radio name="size" value="s" label="Small"></md-radio>
|
|
679
|
+
<md-radio name="size" value="m" label="Medium" checked></md-radio>
|
|
680
|
+
<md-radio name="size" value="l" label="Large"></md-radio>
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
### `<md-search>`
|
|
686
|
+
|
|
687
|
+
MD3 search bar with a leading icon, animated clear button, and optional avatar.
|
|
688
|
+
|
|
689
|
+
| Prop | Type | Default | Description |
|
|
690
|
+
|---|---|---|---|
|
|
691
|
+
| `value` | `string` | `''` | Current input value |
|
|
692
|
+
| `placeholder` | `string` | `'Search'` | Placeholder text |
|
|
693
|
+
| `leading-icon` | `string` | `'search'` | Material Symbol for the leading icon |
|
|
694
|
+
| `show-avatar` | `boolean` | `false` | Renders an avatar button on the trailing end |
|
|
695
|
+
|
|
696
|
+
**Events:** `clear`; `search` `(detail: string)` — the search query when Enter is pressed.
|
|
697
|
+
|
|
698
|
+
```html
|
|
699
|
+
<md-search
|
|
700
|
+
placeholder="Search contacts"
|
|
701
|
+
:model="${query}"
|
|
702
|
+
@search="${e => runSearch(e.detail)}"
|
|
703
|
+
></md-search>
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
### `<md-segmented-button>`
|
|
709
|
+
|
|
710
|
+
MD3 segmented button group for single-select or multi-select toggle behaviour.
|
|
711
|
+
|
|
712
|
+
| Prop | Type | Default | Description |
|
|
713
|
+
|---|---|---|---|
|
|
714
|
+
| `segments` | `{ id: string; label?: string; icon?: string; disabled?: boolean }[]` | `[]` | Segment definitions |
|
|
715
|
+
| `selected` | `string \| string[]` | `''` | Selected segment `id` (or array for multi-select) |
|
|
716
|
+
| `multiselect` | `boolean` | `false` | Allows multiple selections |
|
|
717
|
+
| `aria-label` | `string` | `''` | Accessible group label |
|
|
718
|
+
|
|
719
|
+
**Events:** `change` `(detail: string | string[])` — selected segment `id` or array of `id`s (multiselect).
|
|
720
|
+
|
|
721
|
+
```html
|
|
722
|
+
<md-segmented-button
|
|
723
|
+
:bind="${{ segments: [
|
|
724
|
+
{ id: 'day', label: 'Day' },
|
|
725
|
+
{ id: 'week', label: 'Week' },
|
|
726
|
+
{ id: 'month', label: 'Month' },
|
|
727
|
+
] }}"
|
|
728
|
+
:model:selected="${view}"
|
|
729
|
+
></md-segmented-button>
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
### `<md-side-sheet>`
|
|
735
|
+
|
|
736
|
+
MD3 side sheet — standard (in-layout, right-side panel) or modal (slide-in from the right with scrim).
|
|
737
|
+
|
|
738
|
+
| Prop | Type | Default | Description |
|
|
739
|
+
|---|---|---|---|
|
|
740
|
+
| `open` | `boolean` | `false` | Shows/hides the sheet |
|
|
741
|
+
| `headline` | `string` | `''` | Header title text |
|
|
742
|
+
| `variant` | `'standard' \| 'modal'` | `'standard'` | Layout mode |
|
|
743
|
+
| `divider` | `boolean` | `true` | Renders a left-edge border |
|
|
744
|
+
|
|
745
|
+
**Slots:** default — sheet body content.
|
|
746
|
+
|
|
747
|
+
**Events:** `close`; `back` — header back button clicked (modal variant).
|
|
748
|
+
|
|
749
|
+
```html
|
|
750
|
+
<md-side-sheet variant="modal" headline="Details" :model:open="${sheetOpen}">
|
|
751
|
+
<p>Side panel content</p>
|
|
752
|
+
</md-side-sheet>
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
---
|
|
756
|
+
|
|
757
|
+
### `<md-slider>`
|
|
758
|
+
|
|
759
|
+
MD3 range slider with a custom-styled track, optional floating value label, and optional tick marks.
|
|
760
|
+
|
|
761
|
+
| Prop | Type | Default | Description |
|
|
762
|
+
|---|---|---|---|
|
|
763
|
+
| `min` | `number` | `0` | Minimum value |
|
|
764
|
+
| `max` | `number` | `100` | Maximum value |
|
|
765
|
+
| `value` | `number` | `50` | Current value |
|
|
766
|
+
| `step` | `number` | `1` | Step increment |
|
|
767
|
+
| `disabled` | `boolean` | `false` | Disables the slider |
|
|
768
|
+
| `labeled` | `boolean` | `false` | Shows a floating value bubble on drag |
|
|
769
|
+
| `ticks` | `boolean` | `false` | Renders tick marks at each step |
|
|
770
|
+
| `aria-label` | `string` | `''` | Accessible label |
|
|
771
|
+
|
|
772
|
+
```html
|
|
773
|
+
<md-slider min="0" max="50" step="5" labeled :model="${vol}"></md-slider>
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
---
|
|
777
|
+
|
|
778
|
+
### `<md-snackbar>`
|
|
779
|
+
|
|
780
|
+
MD3 snackbar that slides up from the bottom with an optional action button.
|
|
781
|
+
|
|
782
|
+
| Prop | Type | Default | Description |
|
|
783
|
+
|---|---|---|---|
|
|
784
|
+
| `open` | `boolean` | `false` | Shows/hides the snackbar |
|
|
785
|
+
| `message` | `string` | `''` | Message text |
|
|
786
|
+
| `action-label` | `string` | `''` | Label for the optional action button; empty hides it |
|
|
787
|
+
|
|
788
|
+
**Events:** `action` — action button clicked; `close` — dismiss button clicked.
|
|
789
|
+
|
|
790
|
+
```html
|
|
791
|
+
<md-snackbar
|
|
792
|
+
:model:open="${showSnack}"
|
|
793
|
+
message="Item deleted"
|
|
794
|
+
action-label="Undo"
|
|
795
|
+
@action="${undoDelete}"
|
|
796
|
+
></md-snackbar>
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
### `<md-split-button>`
|
|
802
|
+
|
|
803
|
+
MD3 split button combining a primary action and an arrow-toggle dropdown for secondary actions.
|
|
804
|
+
|
|
805
|
+
| Prop | Type | Default | Description |
|
|
806
|
+
|---|---|---|---|
|
|
807
|
+
| `label` | `string` | `'Action'` | Primary button label |
|
|
808
|
+
| `icon` | `string` | `''` | Leading Material Symbol on the primary button |
|
|
809
|
+
| `variant` | `'filled' \| 'outlined' \| 'tonal'` | `'filled'` | Visual style |
|
|
810
|
+
| `disabled` | `boolean` | `false` | Disables both sections |
|
|
811
|
+
| `items` | `{ id: string; label: string; icon?: string; disabled?: boolean }[]` | `[]` | Dropdown action definitions |
|
|
812
|
+
|
|
813
|
+
**Events:** `click` — primary button pressed; `select` `(detail: { id: string })` — dropdown item chosen.
|
|
814
|
+
|
|
815
|
+
```html
|
|
816
|
+
<md-split-button
|
|
817
|
+
label="Save"
|
|
818
|
+
icon="save"
|
|
819
|
+
:bind="${{ items: [
|
|
820
|
+
{ id: 'save-draft', label: 'Save as draft' },
|
|
821
|
+
{ id: 'save-copy', label: 'Save a copy' },
|
|
822
|
+
] }}"
|
|
823
|
+
@click="${save}"
|
|
824
|
+
@select="${handleSplitSelect}"
|
|
825
|
+
></md-split-button>
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
---
|
|
829
|
+
|
|
830
|
+
### `<md-switch>`
|
|
831
|
+
|
|
832
|
+
MD3 toggle switch with animated thumb, state-layer ripple, and optional check/close thumb icons.
|
|
833
|
+
|
|
834
|
+
| Prop | Type | Default | Description |
|
|
835
|
+
|---|---|---|---|
|
|
836
|
+
| `selected` | `boolean` | `false` | On/off state |
|
|
837
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
838
|
+
| `icons` | `boolean` | `false` | Renders a check icon when on and a close icon when off |
|
|
839
|
+
|
|
840
|
+
**Events:** `change` `(detail: boolean)` — new selected state.
|
|
841
|
+
|
|
842
|
+
```html
|
|
843
|
+
<md-switch :model:selected="${darkMode}" icons></md-switch>
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
---
|
|
847
|
+
|
|
848
|
+
### `<md-tabs>`
|
|
849
|
+
|
|
850
|
+
MD3 tabbed navigation with an active indicator bar, icon and badge support, keyboard navigation, and a single panel slot.
|
|
851
|
+
|
|
852
|
+
| Prop | Type | Default | Description |
|
|
853
|
+
|---|---|---|---|
|
|
854
|
+
| `variant` | `'primary' \| 'secondary'` | `'primary'` | Tab style (`primary` has icons above labels; `secondary` is text-only) |
|
|
855
|
+
| `tabs` | `{ id: string; label: string; icon?: string; badge?: string }[]` | `[]` | Tab definitions |
|
|
856
|
+
| `active-tab` | `string` | `''` | `id` of the active tab |
|
|
857
|
+
|
|
858
|
+
**Slots:** default — the active tab panel content.
|
|
859
|
+
|
|
860
|
+
**Events:** `tab-change` `(detail: string)` — the `id` of the newly active tab.
|
|
861
|
+
|
|
862
|
+
```html
|
|
863
|
+
<md-tabs
|
|
864
|
+
variant="primary"
|
|
865
|
+
:model:activeTab="${activeTab}"
|
|
866
|
+
:bind="${{ tabs: [
|
|
867
|
+
{ id: 'flights', label: 'Flights', icon: 'flight' },
|
|
868
|
+
{ id: 'hotels', label: 'Hotels', icon: 'hotel' },
|
|
869
|
+
] }}"
|
|
870
|
+
>
|
|
871
|
+
<!-- render panel based on activeTab -->
|
|
872
|
+
</md-tabs>
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
---
|
|
876
|
+
|
|
877
|
+
### `<md-text-field>`
|
|
878
|
+
|
|
879
|
+
MD3 text field (filled or outlined) with animated floating label, leading/trailing icons, error state, and supporting text.
|
|
880
|
+
|
|
881
|
+
| Prop | Type | Default | Description |
|
|
882
|
+
|---|---|---|---|
|
|
883
|
+
| `variant` | `'filled' \| 'outlined'` | `'filled'` | Visual style |
|
|
884
|
+
| `label` | `string` | `'Label'` | Floating label text |
|
|
885
|
+
| `value` | `string` | `''` | Input value |
|
|
886
|
+
| `type` | `string` | `'text'` | Native input type |
|
|
887
|
+
| `placeholder` | `string` | `''` | Placeholder text (shown when no label floats) |
|
|
888
|
+
| `disabled` | `boolean` | `false` | Disables the field |
|
|
889
|
+
| `error` | `boolean` | `false` | Applies error styling |
|
|
890
|
+
| `error-text` | `string` | `''` | Error helper text beneath the field |
|
|
891
|
+
| `supporting-text` | `string` | `''` | Helper text beneath the field (non-error) |
|
|
892
|
+
| `leading-icon` | `string` | `''` | Leading Material Symbol |
|
|
893
|
+
| `trailing-icon` | `string` | `''` | Trailing Material Symbol |
|
|
894
|
+
| `required` | `boolean` | `false` | Marks the field as required |
|
|
895
|
+
| `readonly` | `boolean` | `false` | Makes the field read-only |
|
|
896
|
+
|
|
897
|
+
```html
|
|
898
|
+
<md-text-field
|
|
899
|
+
variant="outlined"
|
|
900
|
+
label="Email"
|
|
901
|
+
type="email"
|
|
902
|
+
leading-icon="mail"
|
|
903
|
+
:model="${email}"
|
|
904
|
+
:error="${!!emailError}"
|
|
905
|
+
:error-text="${emailError}"
|
|
906
|
+
></md-text-field>
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
---
|
|
910
|
+
|
|
911
|
+
### `<md-time-picker>`
|
|
912
|
+
|
|
913
|
+
MD3 time picker modal with an interactive clock dial or keyboard input mode, AM/PM toggle, and 12/24-hour support.
|
|
914
|
+
|
|
915
|
+
| Prop | Type | Default | Description |
|
|
916
|
+
|---|---|---|---|
|
|
917
|
+
| `variant` | `'dial' \| 'input'` | `'dial'` | Clock dial or text input mode |
|
|
918
|
+
| `value` | `string` | `''` | Selected time (`HH:MM` 24-hour) |
|
|
919
|
+
| `open` | `boolean` | `false` | Controls visibility |
|
|
920
|
+
| `hour24` | `boolean` | `false` | Uses 24-hour format (no AM/PM) |
|
|
921
|
+
| `aria-label` | `string` | `'Time picker'` | Accessible label |
|
|
922
|
+
|
|
923
|
+
**Events:** `change` `(detail: string)` — selected time in `HH:MM` 24-hour format; `close`.
|
|
924
|
+
|
|
925
|
+
```html
|
|
926
|
+
<md-time-picker
|
|
927
|
+
:model="${meetingTime}"
|
|
928
|
+
:model:open="${pickerOpen}"
|
|
929
|
+
></md-time-picker>
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
---
|
|
933
|
+
|
|
934
|
+
### `<md-tooltip>`
|
|
935
|
+
|
|
936
|
+
MD3 tooltip shown on hover/focus — plain (small floating label) or rich (card with title, body, and optional action).
|
|
937
|
+
|
|
938
|
+
| Prop | Type | Default | Description |
|
|
939
|
+
|---|---|---|---|
|
|
940
|
+
| `text` | `string` | `''` | Tooltip body text |
|
|
941
|
+
| `variant` | `'plain' \| 'rich'` | `'plain'` | Plain label or rich card |
|
|
942
|
+
| `title` | `string` | `''` | Rich tooltip title |
|
|
943
|
+
| `action` | `string` | `''` | Rich tooltip action button label |
|
|
944
|
+
|
|
945
|
+
**Slots:** default — the anchor element that triggers the tooltip.
|
|
946
|
+
|
|
947
|
+
**Events:** `action` — rich tooltip action button clicked.
|
|
948
|
+
|
|
949
|
+
```html
|
|
950
|
+
<!-- Plain tooltip -->
|
|
951
|
+
<md-tooltip text="Delete permanently">
|
|
952
|
+
<md-icon-button icon="delete"></md-icon-button>
|
|
953
|
+
</md-tooltip>
|
|
954
|
+
|
|
955
|
+
<!-- Rich tooltip -->
|
|
956
|
+
<md-tooltip variant="rich" title="Formatting" text="Adjust text size, weight, and alignment." action="Learn more" @action="${openDocs}">
|
|
957
|
+
<md-icon-button icon="format_size"></md-icon-button>
|
|
958
|
+
</md-tooltip>
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
---
|
|
962
|
+
|
|
963
|
+
## Composables
|
|
964
|
+
|
|
965
|
+
Advanced consumers can re-use the internal composable utilities directly. All are exported from `cer-material`:
|
|
966
|
+
|
|
967
|
+
| Export | Description |
|
|
968
|
+
|---|---|
|
|
969
|
+
| `useControlledValue(getProp)` | Syncs an internal reactive value to a prop, returning a `ReactiveState`. |
|
|
970
|
+
| `useEscapeKey(guard, onEscape)` | Registers a global Escape key listener with an active-guard callback. Cleans up automatically. |
|
|
971
|
+
| `createFocusReturn()` | Captures the current focus target and restores it when `.return()` is called. |
|
|
972
|
+
| `createFocusTrap()` | Traps keyboard focus within a DOM element; call `.activate(el)` and `.deactivate()`. |
|
|
973
|
+
| `useListKeyNav(options)` | Adds keyboard arrow-key navigation for a list of DOM items. |
|
|
974
|
+
| `useScrollLock()` | Returns `{ lock(), unlock() }` to prevent `<body>` scrolling while an overlay is open. |
|
|
975
|
+
|
|
976
|
+
---
|
|
977
|
+
|
|
978
|
+
## Browser support
|
|
979
|
+
|
|
980
|
+
All evergreen browsers supporting:
|
|
981
|
+
- [Custom Elements v1](https://caniuse.com/custom-elementsv1)
|
|
982
|
+
- [Shadow DOM v1](https://caniuse.com/shadowdomv1)
|
|
983
|
+
- [`CSSStyleSheet.replaceSync`](https://caniuse.com/mdn-api_cssstylesheet_replacesync) (for theme tokens)
|
|
984
|
+
|
|
985
|
+
---
|
|
986
|
+
|
|
987
|
+
## License
|
|
988
|
+
|
|
989
|
+
MIT
|