react-material-expressive 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/LICENSE +21 -0
  3. package/README.md +286 -0
  4. package/dist/index.cjs +7014 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +2068 -0
  7. package/dist/index.d.ts +2068 -0
  8. package/dist/index.js +6941 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/styles.css +2 -0
  11. package/dist/theme.css +187 -0
  12. package/docs/components/Amount.md +48 -0
  13. package/docs/components/Avatar.md +69 -0
  14. package/docs/components/AvatarStack.md +50 -0
  15. package/docs/components/Badge.md +50 -0
  16. package/docs/components/Blob.md +44 -0
  17. package/docs/components/Button.md +79 -0
  18. package/docs/components/ButtonGroup.md +46 -0
  19. package/docs/components/ButtonGroupConnected.md +62 -0
  20. package/docs/components/Card.md +52 -0
  21. package/docs/components/Checkbox.md +45 -0
  22. package/docs/components/Chips.md +77 -0
  23. package/docs/components/DatePicker.md +112 -0
  24. package/docs/components/Dialog.md +83 -0
  25. package/docs/components/Divider.md +48 -0
  26. package/docs/components/Dropdown.md +79 -0
  27. package/docs/components/FAB.md +63 -0
  28. package/docs/components/FABMenu.md +76 -0
  29. package/docs/components/Gallery.md +35 -0
  30. package/docs/components/Icon.md +36 -0
  31. package/docs/components/IconButton.md +69 -0
  32. package/docs/components/Img.md +52 -0
  33. package/docs/components/Layers.md +43 -0
  34. package/docs/components/Link.md +43 -0
  35. package/docs/components/List.md +87 -0
  36. package/docs/components/Loading.md +67 -0
  37. package/docs/components/LoadingIndicator.md +64 -0
  38. package/docs/components/MaterialSymbol.md +48 -0
  39. package/docs/components/MediaFrame.md +46 -0
  40. package/docs/components/Menu.md +149 -0
  41. package/docs/components/NavigationBar.md +78 -0
  42. package/docs/components/NavigationRail.md +105 -0
  43. package/docs/components/OverflowMenu.md +65 -0
  44. package/docs/components/Perspective.md +45 -0
  45. package/docs/components/Progress.md +83 -0
  46. package/docs/components/Radio.md +39 -0
  47. package/docs/components/Search.md +100 -0
  48. package/docs/components/Select.md +76 -0
  49. package/docs/components/Sheets.md +62 -0
  50. package/docs/components/Slider.md +89 -0
  51. package/docs/components/Snackbar.md +73 -0
  52. package/docs/components/SplitButton.md +75 -0
  53. package/docs/components/Stories.md +71 -0
  54. package/docs/components/Switch.md +40 -0
  55. package/docs/components/Table.md +67 -0
  56. package/docs/components/Tabs.md +67 -0
  57. package/docs/components/TextElement.md +37 -0
  58. package/docs/components/TextField.md +70 -0
  59. package/docs/components/TimePicker.md +83 -0
  60. package/docs/components/ToggleTheme.md +71 -0
  61. package/docs/components/Toolbar.md +102 -0
  62. package/docs/components/Tooltip.md +63 -0
  63. package/docs/components/TopAppBar.md +84 -0
  64. package/docs/components/Video.md +35 -0
  65. package/llms.txt +90 -0
  66. package/package.json +101 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ All notable changes to `react-material-expressive` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
+ and the project follows [Semantic Versioning](https://semver.org/).
7
+
8
+ Each breaking entry includes a **Migration** note so consumers know exactly
9
+ what to adjust when upgrading.
10
+
11
+ ## [Unreleased]
12
+
13
+ ## [1.0.0] - 2026-06-17
14
+
15
+ Initial public release — the first complete implementation of **Material 3
16
+ Expressive** for the web (the official Material Web library only ships the
17
+ baseline).
18
+
19
+ ### Added
20
+
21
+ - **Components, elements and layers** covering the M3
22
+ Expressive surface: buttons (incl. FAB, split, button groups), cards,
23
+ dialogs, sheets, navigation (bar/rail/tabs/top app bar/toolbars), menus,
24
+ selection and input (text fields, select, chips, sliders, checkbox, radio,
25
+ switch, date and time pickers), communication (snackbar, tooltip, badges,
26
+ progress, loading indicator) and more.
27
+ - **Precompiled CSS** — import one stylesheet; no Tailwind setup required.
28
+ - **Runtime theming** through the official `--md-sys-*` tokens, with built-in
29
+ light/dark and any scoped or custom Material Theme Builder export.
30
+ - **Framework-agnostic** — native `<img>`/`<a>` with media/link injection, no
31
+ `next/*`; RSC/SSR friendly with `"use client"` embedded in every entry.
32
+ - **i18n** via a per-component `labels` prop (English defaults).
33
+ - **Accessibility** hardened across the interactive components: focus
34
+ management and trapping, ARIA names/roles/states, and full keyboard support.
35
+ - React 19+, **ESM + CJS** builds and **TypeScript** types, plus
36
+ machine-readable per-component docs and an LLM index.
37
+
38
+ [Unreleased]: https://github.com/gersilva96/react-material-expressive/compare/v1.0.0...HEAD
39
+ [1.0.0]: https://github.com/gersilva96/react-material-expressive/releases/tag/v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Germán Silva
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # react-material-expressive
2
+
3
+ [![npm version](https://img.shields.io/npm/v/react-material-expressive.svg)](https://www.npmjs.com/package/react-material-expressive)
4
+ [![CI](https://github.com/gersilva96/react-material-expressive/actions/workflows/ci.yml/badge.svg)](https://github.com/gersilva96/react-material-expressive/actions/workflows/ci.yml)
5
+ [![license: MIT](https://img.shields.io/npm/l/react-material-expressive.svg)](LICENSE)
6
+
7
+ React component system implementing **Material 3 Expressive**: official M3
8
+ design tokens, state layers, the full type/shape/elevation scales and
9
+ motion — framework-agnostic (no `next/*`), RSC/SSR friendly, with
10
+ **precompiled CSS** (you don't set up Tailwind) and runtime theming via CSS
11
+ variables.
12
+
13
+ - React `>= 19` (peer dependency). ESM + CJS + TypeScript types.
14
+ - Pure UI kit: presentational, controllable components. No business logic,
15
+ no data fetching, no app state.
16
+ - Machine-readable docs per component in [`docs/components/`](docs/components)
17
+ and an LLM index in [`llms.txt`](llms.txt).
18
+ - **Live demo**: [ger-material-expressive.vercel.app](https://ger-material-expressive.vercel.app)
19
+ (the Storybook, redeployed on every push).
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install react-material-expressive react react-dom
25
+ ```
26
+
27
+ React 19+ is a peer dependency. The package ships precompiled CSS, ESM + CJS
28
+ builds and TypeScript types — there is nothing else to configure.
29
+
30
+ ## Quickstart
31
+
32
+ ```tsx
33
+ // 1. Import the precompiled stylesheet ONCE (global CSS / root layout).
34
+ import "react-material-expressive/styles.css";
35
+
36
+ // 2. Use the components.
37
+ import {Button, Card, Dialog, Switch} from "react-material-expressive";
38
+
39
+ export function Example() {
40
+ return (
41
+ <Card variant="elevated">
42
+ <Card.Body>
43
+ <Switch defaultChecked label="Notifications" />
44
+ </Card.Body>
45
+ <Card.Footer className="justify-end">
46
+ <Button variant="text">Dismiss</Button>
47
+ <Button>Accept</Button>
48
+ </Card.Footer>
49
+ </Card>
50
+ );
51
+ }
52
+ ```
53
+
54
+ No Tailwind, no ThemeProvider, no configuration. Components are client
55
+ components (`"use client"` is embedded in every entry), so they can be
56
+ imported directly from React Server Components.
57
+
58
+ ### Exports
59
+
60
+ The package has a single JavaScript entry, the precompiled stylesheet and an
61
+ optional Tailwind partial:
62
+
63
+ | Import | Contents |
64
+ | ------------------------------------------- | ---------------------------------------------------- |
65
+ | `react-material-expressive` | all components, elements and layers |
66
+ | `react-material-expressive/styles.css` | precompiled stylesheet (import once) |
67
+ | `react-material-expressive/theme.css` | raw Tailwind v4 partial — only to extend (see below) |
68
+
69
+ ## Theming
70
+
71
+ Everything resolves through **official M3 tokens** at runtime:
72
+ `--md-sys-color-*` (full 49-role scheme), `--md-sys-shape-corner-*`,
73
+ `--md-sys-elevation-level1..5`, `--md-ref-typeface-brand/plain`.
74
+
75
+ - `:root` ships the light scheme and `.dark, [data-theme="dark"]` the dark
76
+ one — both verbatim Material Theme Builder exports.
77
+
78
+ Theme switching uses the prebuilt `ToggleTheme` / `ToggleThemeMenu`
79
+ components (there is no ThemeProvider): they read/write `data-theme` on
80
+ `<html>` (SSR-safe, synced across instances and tabs) and persist to
81
+ `localStorage`.
82
+
83
+ ```tsx
84
+ import {ToggleTheme} from "react-material-expressive";
85
+
86
+ <ToggleTheme />;
87
+ ```
88
+
89
+ There is no public JavaScript theming API — customization is done purely
90
+ through CSS token overrides (see below).
91
+
92
+ ### Custom themes (cascade override)
93
+
94
+ The CSS is precompiled and only reads variables, so a custom theme is just
95
+ a token override. Paste a [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/)
96
+ export verbatim:
97
+
98
+ ```css
99
+ /* my-brand.css — loaded after styles.css */
100
+ :root {
101
+ --md-sys-color-primary: #006a60;
102
+ --md-sys-color-on-primary: #ffffff;
103
+ /* ...rest of the export... */
104
+ }
105
+ ```
106
+
107
+ Scoped themes work the same way on any element: any class or
108
+ `data-theme` scope that overrides the tokens re-themes its subtree.
109
+
110
+ ### Typography
111
+
112
+ The type scale ships as utilities (`text-display-large` …
113
+ `text-label-small`) that inherit two typeface tokens. Fonts are **named but
114
+ never bundled** — load yours and point the tokens at it:
115
+
116
+ ```css
117
+ :root {
118
+ --md-ref-typeface-brand: "Google Sans", system-ui, sans-serif;
119
+ --md-ref-typeface-plain: "Google Sans Text", system-ui, sans-serif;
120
+ }
121
+ ```
122
+
123
+ ### Extending with your own Tailwind (optional)
124
+
125
+ Most apps only import `styles.css`. If you run **your own Tailwind v4** and want
126
+ to write markup with the same M3 utilities the library uses — `bg-primary`,
127
+ `text-on-surface`, `rounded-extra-large`, `shadow-mm-1`, `text-headline-small`,
128
+ even token roles the precompiled CSS never emitted — import the raw partial into
129
+ your Tailwind entry:
130
+
131
+ ```css
132
+ @import "tailwindcss";
133
+ @import "react-material-expressive/theme.css";
134
+ ```
135
+
136
+ That's all you need: the mappings are `@theme inline`, so the utilities
137
+ re-resolve per element and switch light/dark automatically by following the
138
+ tokens (their **values** come from the `styles.css` you already import for the
139
+ components — or a Material Theme Builder paste). `theme.css` also registers the
140
+ `dark:` variant against the library's `.dark`/`[data-theme]` toggle, so explicit
141
+ `dark:` utilities in your code match the components.
142
+
143
+ ## Icons
144
+
145
+ Components take icons as `ReactNode` (`icon`, `iconLeft`, `iconRight`,
146
+ `leftElement`…) — the library bundles **no icon font or icon package**.
147
+ Recommended: [Material Symbols](https://fonts.google.com/icons) (variable
148
+ font). Load it yourself, e.g.:
149
+
150
+ ```html
151
+ <link
152
+ href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block"
153
+ rel="stylesheet" />
154
+ ```
155
+
156
+ and use the zero-dependency helper:
157
+
158
+ ```tsx
159
+ import {MaterialSymbol} from "react-material-expressive";
160
+
161
+ <Button iconLeft={<MaterialSymbol name="add" size={18} />}>New</Button>;
162
+ ```
163
+
164
+ ## Images and links (framework-agnostic)
165
+
166
+ There are no proprietary `Image`/`Link` components. Image-like components
167
+ (`Avatar`, `Img`, `Stories.User`…) accept `src: string | StaticImageData`
168
+ and render a native `<img>` (object-fit + hide-on-error), or let you inject
169
+ your framework's component with priority **render > image > children**:
170
+
171
+ ```tsx
172
+ import Image from "next/image"; // in YOUR app, not in the library
173
+
174
+ <Avatar
175
+ src={photo}
176
+ render={({src, alt, className, style}) => (
177
+ <Image alt={alt} className={className} fill src={src!} style={style} />
178
+ )}
179
+ />;
180
+ ```
181
+
182
+ Navigation components render native `<a href>` and derive their active
183
+ state from `active` or `currentPath` (`resolveActive`); client-side routing
184
+ plugs in via `onClick` or a wrapper.
185
+
186
+ ## State layers, disabled, motion
187
+
188
+ - Interaction states follow M3 **state layers** (hover 8%, focus 10%,
189
+ pressed 10%) — exposed as the `.state-layer` class for custom items.
190
+ - Disabled follows M3: container 12% / content 38% of `on-surface`.
191
+ - Entrances use emphasized-decelerate (400ms), exits emphasized-accelerate
192
+ (200ms); overlays stay mounted during their exit animation.
193
+
194
+ ## Internationalization (i18n)
195
+
196
+ Every component with user-facing text accepts a **`labels` prop** — an object
197
+ of optional strings (a few are `ReactNode`) merged over the built-in English
198
+ defaults. Override one instance, or pass the same object everywhere to localize
199
+ the whole app. The library ships **English defaults only**; the translations
200
+ are yours to provide (like the fonts and icons, named but not bundled).
201
+
202
+ ```tsx
203
+ <Snackbar text="Foto archivada" labels={{dismiss: "Descartar"}} showClose />
204
+ <Chips onRemove={remove} labels={{remove: "Quitar"}}>Etiqueta</Chips>
205
+ <SearchInput labels={{placeholder: "Buscar"}} />
206
+ ```
207
+
208
+ `labels` covers chrome and accessible names only. Date/number formatting is
209
+ driven by a separate **`locale`** prop on the pickers (native `Intl`), and the
210
+ date/time pickers expose their full label sets too (`DatePickerLabels`,
211
+ `TimePickerLabels`, …). Each component's `*Labels` type is exported from the
212
+ barrel.
213
+
214
+ Consolidating every string under `labels` renamed a few single-purpose text
215
+ props (breaking):
216
+
217
+ | Component | Old prop | New |
218
+ | ------------------------------------ | ------------- | ------------------------ |
219
+ | FABMenu | `label` | `labels={{open}}` |
220
+ | SplitButton | `menuLabel` | `labels={{menu}}` |
221
+ | SearchInput | `placeholder` | `labels={{placeholder}}` |
222
+ | Slider / SliderDual | `aria-label` | `labels={{label}}` |
223
+ | Progress / Circle / LoadingIndicator | `aria-label` | `labels={{label}}` |
224
+ | Amount | `aria-label` | `labels={{label}}` |
225
+ | Loading | `label` | `labels={{label}}` |
226
+
227
+ The theme-name strings of `ToggleThemeMenu` stay in its `themes` list (an
228
+ `{id, label}` array), not in `labels`.
229
+
230
+ ## Component catalog
231
+
232
+ | Family | Docs |
233
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
234
+ | Buttons | [Button](docs/components/Button.md) · [ButtonGroup](docs/components/ButtonGroup.md) · [ButtonGroupConnected](docs/components/ButtonGroupConnected.md) · [IconButton](docs/components/IconButton.md) · [FAB / ExtendedFAB](docs/components/FAB.md) · [FABMenu](docs/components/FABMenu.md) · [SplitButton](docs/components/SplitButton.md) |
235
+ | Communication | [Badge](docs/components/Badge.md) · [Progress / Circle](docs/components/Progress.md) · [LoadingIndicator](docs/components/LoadingIndicator.md) · [Snackbar](docs/components/Snackbar.md) · [Tooltip](docs/components/Tooltip.md) · [Loading](docs/components/Loading.md) |
236
+ | Containment | [Card](docs/components/Card.md) · [Dialog](docs/components/Dialog.md) · [Sheets](docs/components/Sheets.md) · [Divider](docs/components/Divider.md) · [List](docs/components/List.md) · [Table](docs/components/Table.md) |
237
+ | Selection & input | [Checkbox](docs/components/Checkbox.md) · [Radio](docs/components/Radio.md) · [Switch](docs/components/Switch.md) · [Chips](docs/components/Chips.md) · [Slider / SliderDual](docs/components/Slider.md) · [TextField](docs/components/TextField.md) · [Select](docs/components/Select.md) · [Amount](docs/components/Amount.md) · [DatePicker](docs/components/DatePicker.md) · [TimePicker](docs/components/TimePicker.md) |
238
+ | Navigation | [NavigationBar](docs/components/NavigationBar.md) · [NavigationRail](docs/components/NavigationRail.md) · [TopAppBar](docs/components/TopAppBar.md) · [Toolbars](docs/components/Toolbar.md) · [Tabs](docs/components/Tabs.md) · [Link](docs/components/Link.md) · [Search](docs/components/Search.md) |
239
+ | Menus | [Menu](docs/components/Menu.md) · [Dropdown](docs/components/Dropdown.md) · [OverflowMenu](docs/components/OverflowMenu.md) · [ToggleTheme](docs/components/ToggleTheme.md) |
240
+ | Media & showcase | [Avatar](docs/components/Avatar.md) · [AvatarStack](docs/components/AvatarStack.md) · [Img](docs/components/Img.md) · [MediaFrame](docs/components/MediaFrame.md) · [Gallery](docs/components/Gallery.md) · [Stories](docs/components/Stories.md) · [Video](docs/components/Video.md) · [Perspective](docs/components/Perspective.md) · [Blob](docs/components/Blob.md) |
241
+ | Text & icons | [TextElement](docs/components/TextElement.md) · [Icon](docs/components/Icon.md) · [MaterialSymbol](docs/components/MaterialSymbol.md) |
242
+ | Layout | [Layers](docs/components/Layers.md) |
243
+
244
+ ### Expressive-only
245
+
246
+ This kit is **Material 3 Expressive only**. Components and variants that the
247
+ M3 Expressive spec marks "no longer recommended" are not shipped: the
248
+ NavigationDrawer (→ expanded [NavigationRail](docs/components/NavigationRail.md)),
249
+ BottomAppBar (→ [DockedToolbar](docs/components/Toolbar.md)) and SegmentedButtons
250
+ (→ [ButtonGroupConnected](docs/components/ButtonGroupConnected.md) with toggles)
251
+ components were removed, as were the FAB `surface` color / small (40dp) size,
252
+ the Slider `classic` prop, the TopAppBar `Medium`/`Large` `baseline` prop and
253
+ the NavigationBar `tall` height. The expressive default is the only path.
254
+
255
+ Where the spec keeps more than one valid style, the **recommended** one is the
256
+ default and the alternative stays available:
257
+
258
+ | Component | Default (recommended) | Still-available alternative |
259
+ | ------------------------------------------------ | ------------------------------ | --------------------------- |
260
+ | [List](docs/components/List.md) | `variant="expressive"` (tiles) | `variant="plain"` |
261
+ | [Search](docs/components/Search.md) | contained (gapped card) | `divided` prop |
262
+ | [Progress / Circle](docs/components/Progress.md) | flat indicator | `wavy` prop |
263
+
264
+ ## Versioning
265
+
266
+ This project follows [Semantic Versioning](https://semver.org/): breaking
267
+ changes bump the _major_ version, new features the _minor_, and fixes the
268
+ _patch_. See the [CHANGELOG](CHANGELOG.md) for every release, with a
269
+ **migration note** on each breaking change so you know exactly what to adjust
270
+ when upgrading.
271
+
272
+ ## Development (this repo)
273
+
274
+ ```bash
275
+ npm install
276
+ npm run build # dist/: css + esm + cjs + dts + themes
277
+ npm run typecheck && npm run lint && npm test
278
+ ```
279
+
280
+ See [AGENTS.md](AGENTS.md) for architecture and conventions, and
281
+ [CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute. The interactive
282
+ component workbench (Storybook) lives in a separate repository.
283
+
284
+ ## License
285
+
286
+ MIT