@bug-on/m3-expressive 1.3.4 → 1.3.6

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 (76) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +31 -7
  3. package/dist/assets/material-symbols-cdn.css +17 -23
  4. package/dist/buttons.js +129 -35
  5. package/dist/buttons.js.map +1 -1
  6. package/dist/buttons.mjs +129 -35
  7. package/dist/buttons.mjs.map +1 -1
  8. package/dist/{core-COvZHQ_k.d.ts → core-Cckt8qEm.d.ts} +10 -4
  9. package/dist/{core-CRkixy1y.d.mts → core-DDfG4pym.d.mts} +10 -4
  10. package/dist/core.d.mts +2 -2
  11. package/dist/core.d.ts +2 -2
  12. package/dist/core.js +6 -5
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +6 -5
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/fading-blur-mask--uZbBKLj.d.mts +77 -0
  17. package/dist/fading-blur-mask--uZbBKLj.d.ts +77 -0
  18. package/dist/feedback.js +1 -1
  19. package/dist/feedback.js.map +1 -1
  20. package/dist/feedback.mjs +1 -1
  21. package/dist/feedback.mjs.map +1 -1
  22. package/dist/forms.d.mts +2 -2
  23. package/dist/forms.d.ts +2 -2
  24. package/dist/forms.js +17 -7
  25. package/dist/forms.js.map +1 -1
  26. package/dist/forms.mjs +17 -7
  27. package/dist/forms.mjs.map +1 -1
  28. package/dist/index.d.mts +9 -8
  29. package/dist/index.d.ts +9 -8
  30. package/dist/index.js +988 -309
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +984 -310
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/layout.d.mts +5 -3
  35. package/dist/layout.d.ts +5 -3
  36. package/dist/layout.js +61 -6
  37. package/dist/layout.js.map +1 -1
  38. package/dist/layout.mjs +61 -7
  39. package/dist/layout.mjs.map +1 -1
  40. package/dist/material-symbols-cdn.css +17 -23
  41. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.mts → md3-expressive-shapes-wk_98LJh.d.mts} +20 -1
  42. package/dist/{md3-expressive-shapes-CPcfl_Hf.d.ts → md3-expressive-shapes-wk_98LJh.d.ts} +20 -1
  43. package/dist/navigation.d.mts +26 -84
  44. package/dist/navigation.d.ts +26 -84
  45. package/dist/navigation.js +95 -29
  46. package/dist/navigation.js.map +1 -1
  47. package/dist/navigation.mjs +95 -29
  48. package/dist/navigation.mjs.map +1 -1
  49. package/dist/overlays.d.mts +4 -2
  50. package/dist/overlays.d.ts +4 -2
  51. package/dist/overlays.js +85 -44
  52. package/dist/overlays.js.map +1 -1
  53. package/dist/overlays.mjs +85 -44
  54. package/dist/overlays.mjs.map +1 -1
  55. package/dist/pickers.d.mts +12 -0
  56. package/dist/pickers.d.ts +12 -0
  57. package/dist/pickers.js +186 -120
  58. package/dist/pickers.js.map +1 -1
  59. package/dist/pickers.mjs +186 -120
  60. package/dist/pickers.mjs.map +1 -1
  61. package/dist/shapes.d.mts +141 -15
  62. package/dist/shapes.d.ts +141 -15
  63. package/dist/shapes.js +618 -126
  64. package/dist/shapes.js.map +1 -1
  65. package/dist/shapes.mjs +614 -127
  66. package/dist/shapes.mjs.map +1 -1
  67. package/dist/{side-sheet-modal-64FGhDxL.d.mts → side-sheet-modal-BycxrabB.d.mts} +70 -0
  68. package/dist/{side-sheet-modal-Bd5Qqvp9.d.ts → side-sheet-modal-Cw4vemKx.d.ts} +70 -0
  69. package/dist/{text-field-4OlT9o8s.d.mts → text-field-B1fLh5Sh.d.mts} +22 -3
  70. package/dist/{text-field-DARNdj14.d.ts → text-field-C0VQLp8Y.d.ts} +22 -3
  71. package/dist/{typography-339RV6v7.d.mts → typography-CKTjvlZ4.d.mts} +25 -0
  72. package/dist/{typography-339RV6v7.d.ts → typography-CKTjvlZ4.d.ts} +25 -0
  73. package/dist/typography.css +1 -1
  74. package/llms-full.txt +24 -13
  75. package/llms.txt +11 -6
  76. package/package.json +3 -3
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as RadixDialog from '@radix-ui/react-dialog';
3
3
  import * as React$1 from 'react';
4
+ import { B as BaseIconButtonProps } from './icon-button-CxyJv7UV.mjs';
4
5
  import { MotionStyle, useMotionValue, useTransform } from 'motion/react';
5
6
  import { b as ScrollAreaProps } from './scroll-area-CVS6HyLl.mjs';
6
7
 
@@ -43,6 +44,49 @@ interface DialogProps {
43
44
  interface DialogContentProps extends React$1.ComponentPropsWithoutRef<typeof RadixDialog.Content> {
44
45
  /** Hides the top-right close (X) button. @default false */
45
46
  hideCloseButton?: boolean;
47
+ /**
48
+ * Override any `IconButton` prop on the default close button.
49
+ *
50
+ * Common use cases:
51
+ * - `disabled` — prevent closing during form submission.
52
+ * - `aria-label` — i18n label (e.g. `"Đóng"`).
53
+ * - `colorStyle` — change visual style (`"filled"` restores original look).
54
+ * - `className` — reposition or override the default `absolute right-4 top-4`.
55
+ *
56
+ * These props are **merged** with the library defaults — you only need to specify overrides.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * // Disable during form submission
61
+ * <DialogContent closeButtonProps={{ disabled: isSubmitting, "aria-label": "Đóng" }}>
62
+ *
63
+ * // Restore the original filled style
64
+ * <DialogContent closeButtonProps={{ colorStyle: "filled" }}>
65
+ * ```
66
+ */
67
+ closeButtonProps?: Partial<BaseIconButtonProps>;
68
+ /**
69
+ * Fully replace the close button with a custom React node.
70
+ * The node is automatically wrapped in `RadixDialog.Close asChild`.
71
+ *
72
+ * When provided, `hideCloseButton` and `closeButtonProps` are ignored —
73
+ * this slot takes full ownership of the close action.
74
+ *
75
+ * Use when `closeButtonProps` is insufficient (e.g. completely different element
76
+ * or button placed inside a custom flex header).
77
+ *
78
+ * @example
79
+ * ```tsx
80
+ * <DialogContent
81
+ * closeButton={
82
+ * <IconButton disabled={isSubmitting} aria-label="Đóng" className="absolute right-4 top-4">
83
+ * <Icon name="close" />
84
+ * </IconButton>
85
+ * }
86
+ * >
87
+ * ```
88
+ */
89
+ closeButton?: React$1.ReactNode;
46
90
  className?: string;
47
91
  }
48
92
  /**
@@ -62,6 +106,32 @@ interface DialogFullScreenContentProps extends React$1.ComponentPropsWithoutRef<
62
106
  actionLabel?: string;
63
107
  /** Handler invoked when pressing the primary action button. */
64
108
  onAction?: () => void;
109
+ /**
110
+ * Override any native `<button>` attribute on the top-bar action button.
111
+ *
112
+ * Common use case: `disabled` during form submission.
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * <DialogFullScreenContent
117
+ * actionLabel="Lưu"
118
+ * onAction={handleSave}
119
+ * actionButtonProps={{ disabled: isSubmitting }}
120
+ * >
121
+ * ```
122
+ */
123
+ actionButtonProps?: React$1.ButtonHTMLAttributes<HTMLButtonElement>;
124
+ /**
125
+ * Override any `IconButton` prop on the top-bar close button.
126
+ *
127
+ * Common use cases: `disabled` during submission, `aria-label` for i18n.
128
+ *
129
+ * @example
130
+ * ```tsx
131
+ * <DialogFullScreenContent closeButtonProps={{ disabled: isSubmitting, "aria-label": "Đóng" }}>
132
+ * ```
133
+ */
134
+ closeButtonProps?: Partial<BaseIconButtonProps>;
65
135
  /** Renders a divider separating Top App Bar from scrollable body content. @default false */
66
136
  showDivider?: boolean;
67
137
  className?: string;
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as RadixDialog from '@radix-ui/react-dialog';
3
3
  import * as React$1 from 'react';
4
+ import { B as BaseIconButtonProps } from './icon-button-Di8VX6ou.js';
4
5
  import { MotionStyle, useMotionValue, useTransform } from 'motion/react';
5
6
  import { b as ScrollAreaProps } from './scroll-area-CVS6HyLl.js';
6
7
 
@@ -43,6 +44,49 @@ interface DialogProps {
43
44
  interface DialogContentProps extends React$1.ComponentPropsWithoutRef<typeof RadixDialog.Content> {
44
45
  /** Hides the top-right close (X) button. @default false */
45
46
  hideCloseButton?: boolean;
47
+ /**
48
+ * Override any `IconButton` prop on the default close button.
49
+ *
50
+ * Common use cases:
51
+ * - `disabled` — prevent closing during form submission.
52
+ * - `aria-label` — i18n label (e.g. `"Đóng"`).
53
+ * - `colorStyle` — change visual style (`"filled"` restores original look).
54
+ * - `className` — reposition or override the default `absolute right-4 top-4`.
55
+ *
56
+ * These props are **merged** with the library defaults — you only need to specify overrides.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * // Disable during form submission
61
+ * <DialogContent closeButtonProps={{ disabled: isSubmitting, "aria-label": "Đóng" }}>
62
+ *
63
+ * // Restore the original filled style
64
+ * <DialogContent closeButtonProps={{ colorStyle: "filled" }}>
65
+ * ```
66
+ */
67
+ closeButtonProps?: Partial<BaseIconButtonProps>;
68
+ /**
69
+ * Fully replace the close button with a custom React node.
70
+ * The node is automatically wrapped in `RadixDialog.Close asChild`.
71
+ *
72
+ * When provided, `hideCloseButton` and `closeButtonProps` are ignored —
73
+ * this slot takes full ownership of the close action.
74
+ *
75
+ * Use when `closeButtonProps` is insufficient (e.g. completely different element
76
+ * or button placed inside a custom flex header).
77
+ *
78
+ * @example
79
+ * ```tsx
80
+ * <DialogContent
81
+ * closeButton={
82
+ * <IconButton disabled={isSubmitting} aria-label="Đóng" className="absolute right-4 top-4">
83
+ * <Icon name="close" />
84
+ * </IconButton>
85
+ * }
86
+ * >
87
+ * ```
88
+ */
89
+ closeButton?: React$1.ReactNode;
46
90
  className?: string;
47
91
  }
48
92
  /**
@@ -62,6 +106,32 @@ interface DialogFullScreenContentProps extends React$1.ComponentPropsWithoutRef<
62
106
  actionLabel?: string;
63
107
  /** Handler invoked when pressing the primary action button. */
64
108
  onAction?: () => void;
109
+ /**
110
+ * Override any native `<button>` attribute on the top-bar action button.
111
+ *
112
+ * Common use case: `disabled` during form submission.
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * <DialogFullScreenContent
117
+ * actionLabel="Lưu"
118
+ * onAction={handleSave}
119
+ * actionButtonProps={{ disabled: isSubmitting }}
120
+ * >
121
+ * ```
122
+ */
123
+ actionButtonProps?: React$1.ButtonHTMLAttributes<HTMLButtonElement>;
124
+ /**
125
+ * Override any `IconButton` prop on the top-bar close button.
126
+ *
127
+ * Common use cases: `disabled` during submission, `aria-label` for i18n.
128
+ *
129
+ * @example
130
+ * ```tsx
131
+ * <DialogFullScreenContent closeButtonProps={{ disabled: isSubmitting, "aria-label": "Đóng" }}>
132
+ * ```
133
+ */
134
+ closeButtonProps?: Partial<BaseIconButtonProps>;
65
135
  /** Renders a divider separating Top App Bar from scrollable body content. @default false */
66
136
  showDivider?: boolean;
67
137
  className?: string;
@@ -473,11 +473,30 @@ interface SelectProps extends Omit<TextFieldProps, "value" | "onChange" | "defau
473
473
  /** Callback fired when selection changes */
474
474
  onChange?: (value: string, option?: SelectOption) => void;
475
475
  /**
476
- * Callback fired when search query changes in searchable mode.
477
- * When provided, INTERNAL filtering is disabled — pass filtered `options` from outside (for server-side/async search).
476
+ * Callback fired when the search query changes.
477
+ *
478
+ * ⚠️ **Requires `searchable={true}`** — without it, typing is disabled and this callback is never called.
479
+ *
480
+ * When provided, INTERNAL filtering is disabled — you control `options` externally
481
+ * (ideal for server-side / async search with large datasets).
482
+ *
483
+ * @example
484
+ * // Server-side search: fetch results as user types
485
+ * <Select
486
+ * searchable
487
+ * loading={isLoading}
488
+ * options={serverResults}
489
+ * onSearchChange={(query) => fetchOptions(query)}
490
+ * onChange={(val) => setSelected(val)}
491
+ * />
478
492
  */
479
493
  onSearchChange?: (query: string) => void;
480
- /** Enable autocomplete mode (input filtering real-time search) */
494
+ /**
495
+ * Enable autocomplete/search mode — renders the trigger as an editable text input.
496
+ *
497
+ * - When `false` (default): read-only dropdown, no typing allowed.
498
+ * - When `true`: user can type to filter options. Combine with `onSearchChange` for server-side search.
499
+ */
481
500
  searchable?: boolean;
482
501
  /** Whether data is loading (displays a spinner inside the dropdown) */
483
502
  loading?: boolean;
@@ -473,11 +473,30 @@ interface SelectProps extends Omit<TextFieldProps, "value" | "onChange" | "defau
473
473
  /** Callback fired when selection changes */
474
474
  onChange?: (value: string, option?: SelectOption) => void;
475
475
  /**
476
- * Callback fired when search query changes in searchable mode.
477
- * When provided, INTERNAL filtering is disabled — pass filtered `options` from outside (for server-side/async search).
476
+ * Callback fired when the search query changes.
477
+ *
478
+ * ⚠️ **Requires `searchable={true}`** — without it, typing is disabled and this callback is never called.
479
+ *
480
+ * When provided, INTERNAL filtering is disabled — you control `options` externally
481
+ * (ideal for server-side / async search with large datasets).
482
+ *
483
+ * @example
484
+ * // Server-side search: fetch results as user types
485
+ * <Select
486
+ * searchable
487
+ * loading={isLoading}
488
+ * options={serverResults}
489
+ * onSearchChange={(query) => fetchOptions(query)}
490
+ * onChange={(val) => setSelected(val)}
491
+ * />
478
492
  */
479
493
  onSearchChange?: (query: string) => void;
480
- /** Enable autocomplete mode (input filtering real-time search) */
494
+ /**
495
+ * Enable autocomplete/search mode — renders the trigger as an editable text input.
496
+ *
497
+ * - When `false` (default): read-only dropdown, no typing allowed.
498
+ * - When `true`: user can type to filter options. Combine with `onSearchChange` for server-side search.
499
+ */
481
500
  searchable?: boolean;
482
501
  /** Whether data is loading (displays a spinner inside the dropdown) */
483
502
  loading?: boolean;
@@ -97,14 +97,39 @@ interface FontVariationAxes {
97
97
  ROND?: number;
98
98
  /**
99
99
  * Weight axis. Overrides `font-weight` via variation settings.
100
+ * Range: `100` (thin) – `1000` (extra black).
100
101
  * @default font default
101
102
  */
102
103
  wght?: number;
103
104
  /**
104
105
  * Width axis. Controls glyph condensation/expansion.
106
+ * Range: `75` (condensed) – `125` (expanded).
105
107
  * @default font default
106
108
  */
107
109
  wdth?: number;
110
+ /**
111
+ * Optical Size axis. Adjusts stroke thickness, proportions, and spacing
112
+ * for optimal readability at different text sizes.
113
+ * Range: `6` (caption/fine print) – `144` (display/banner).
114
+ *
115
+ * Note: Browsers normally handle optical sizing automatically via `font-optical-sizing: auto`.
116
+ * When manually overriding `opsz` in CSS, set `font-optical-sizing: none` to prevent conflicts.
117
+ * @default font default
118
+ */
119
+ opsz?: number;
120
+ /**
121
+ * Grade axis. Modifies stroke weight/density without changing layout, line wrapping, or glyph advance widths.
122
+ * Ideal for dark mode adjustments or subtle hover/emphasis states.
123
+ * Range: `-200` (light grade) – `150` (heavy grade).
124
+ * @default 0
125
+ */
126
+ GRAD?: number;
127
+ /**
128
+ * Slant axis. Applies font-designed slant angle in degrees.
129
+ * Range: `-15` (15-degree forward slant) – `0` (upright).
130
+ * @default 0
131
+ */
132
+ slnt?: number;
108
133
  /** Any additional named variation axis supported by the font. */
109
134
  [axis: string]: number | undefined;
110
135
  }
@@ -97,14 +97,39 @@ interface FontVariationAxes {
97
97
  ROND?: number;
98
98
  /**
99
99
  * Weight axis. Overrides `font-weight` via variation settings.
100
+ * Range: `100` (thin) – `1000` (extra black).
100
101
  * @default font default
101
102
  */
102
103
  wght?: number;
103
104
  /**
104
105
  * Width axis. Controls glyph condensation/expansion.
106
+ * Range: `75` (condensed) – `125` (expanded).
105
107
  * @default font default
106
108
  */
107
109
  wdth?: number;
110
+ /**
111
+ * Optical Size axis. Adjusts stroke thickness, proportions, and spacing
112
+ * for optimal readability at different text sizes.
113
+ * Range: `6` (caption/fine print) – `144` (display/banner).
114
+ *
115
+ * Note: Browsers normally handle optical sizing automatically via `font-optical-sizing: auto`.
116
+ * When manually overriding `opsz` in CSS, set `font-optical-sizing: none` to prevent conflicts.
117
+ * @default font default
118
+ */
119
+ opsz?: number;
120
+ /**
121
+ * Grade axis. Modifies stroke weight/density without changing layout, line wrapping, or glyph advance widths.
122
+ * Ideal for dark mode adjustments or subtle hover/emphasis states.
123
+ * Range: `-200` (light grade) – `150` (heavy grade).
124
+ * @default 0
125
+ */
126
+ GRAD?: number;
127
+ /**
128
+ * Slant axis. Applies font-designed slant angle in degrees.
129
+ * Range: `-15` (15-degree forward slant) – `0` (upright).
130
+ * @default 0
131
+ */
132
+ slnt?: number;
108
133
  /** Any additional named variation axis supported by the font. */
109
134
  [axis: string]: number | undefined;
110
135
  }
@@ -5,7 +5,7 @@
5
5
  src: url('./assets/fonts/GoogleSansFlex-VariableFont.woff2')
6
6
  format("woff2");
7
7
  font-weight: 100 1000;
8
- font-style: normal;
8
+ font-style: oblique -15deg 0deg;
9
9
  font-display: swap;
10
10
  }
11
11
 
package/llms-full.txt CHANGED
@@ -1,6 +1,6 @@
1
- # @bug-on/m3-expressive — Full AI Documentation (v1.1.1)
1
+ # @bug-on/m3-expressive — Full AI Documentation & API Specification (Latest Stable Release)
2
2
 
3
- This file contains the complete context for the `@bug-on/m3-expressive` library (version 1.1.1), including core principles, multi-package architecture, styling guides, component references, and AI gotchas.
3
+ This document provides complete, canonical context for the `@bug-on/m3-expressive` ecosystem (React 19 + Tailwind CSS v4 + Motion for React), including core principles, multi-package architecture, styling guides, component references, subpath exports, and AI gotchas.
4
4
 
5
5
  ---
6
6
 
@@ -113,7 +113,10 @@ Icons use **Material Symbols** (Variable Font).
113
113
  <Icon name="search" weight={500} size={24} />
114
114
  ```
115
115
 
116
- - Standard CDN imports: `@import "@bug-on/m3-expressive/typography.css";` and `@import "@bug-on/m3-expressive/material-symbols-cdn.css";`
116
+ - Standard CDN setup:
117
+ - Base styles: `@import "@bug-on/m3-expressive/material-symbols-cdn.css";` and `@import "@bug-on/m3-expressive/typography.css";` in root CSS.
118
+ - React + Vite: Add `<link rel="preconnect" ...>` and `<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block" />` to `index.html` inside `<head>`.
119
+ - Next.js (App Router): Add `<MaterialSymbolsPreconnect variants={["rounded"]} display="block" />` in `app/layout.tsx` inside `<head>`.
117
120
  - Offline / Self-hosted imports: `pnpm add @bug-on/m3-fonts`, then `@import "@bug-on/m3-fonts/typography.css";` and `@import "@bug-on/m3-fonts/material-symbols.css";`
118
121
 
119
122
  ---
@@ -123,6 +126,8 @@ Icons use **Material Symbols** (Variable Font).
123
126
  ### 7.1 Compound Components & Responsive Layout Groups
124
127
  Complex components use a structured compound pattern:
125
128
  - **Dialog & Drawer**: `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogBody`, `DialogFooter`, `DialogClose`.
129
+ - `DialogContent` has `closeButtonProps?: Partial<IconButtonProps>` to override the default close button (use `disabled`, `aria-label`, `colorStyle`, `className`) and `closeButton?: React.ReactNode` for full slot replacement (auto-wrapped in `DialogClose`).
130
+ - `DialogFullScreenContent` has `closeButtonProps?: Partial<IconButtonProps>` and `actionButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>` to disable/label close and action buttons during form submission.
126
131
  - **Tabs**: `Tabs`, `TabsList`, `Tab`, `TabsContent`.
127
132
  - **SplitButton**: `SplitButtonLayout`, `SplitButtonLeading`, `SplitButtonTrailing` (or `SplitButtonTrailingUncheckable`).
128
133
  - **ButtonDistribute**: `ButtonDistribute` (`mode="dynamic" | "fixed" | "mixed"`), spring-animated button layout container for responsive action bars.
@@ -222,16 +227,17 @@ import {
222
227
 
223
228
  ## Subpath Exports Map
224
229
 
225
- - `@bug-on/m3-expressive` — complete package exports
226
- - `@bug-on/m3-expressive/index.css` — **REQUIRED**: bundled tokens + Tailwind `@theme` + resets
227
- - `@bug-on/m3-expressive/core` — base providers, hooks, motion tokens
228
- - `@bug-on/m3-expressive/buttons` — Button, IconButton, ButtonDistribute, FAB, ExtendedFAB, FABMenu, SplitButton, ButtonGroup
229
- - `@bug-on/m3-expressive/forms` — Select, TextField, Checkbox, RadioButton, Switch, Slider, Search
230
- - `@bug-on/m3-expressive/feedback` — Dialog, Menu, ContextMenu, VerticalMenu, Tooltip, SnackbarProvider, ProgressIndicator
231
- - `@bug-on/m3-expressive/navigation` — NavigationBar, NavigationRail, Drawer, Tabs
232
- - `@bug-on/m3-expressive/overlays` — BottomSheet, SideSheet
233
- - `@bug-on/m3-expressive/pickers` — DatePicker, DateRangePicker, TimePicker, state hooks
234
- - `@bug-on/m3-expressive/shapes` — ShapeMedia, ShapeSvg
230
+ - `@bug-on/m3-expressive` — Complete package root exports
231
+ - `@bug-on/m3-expressive/index.css` — **REQUIRED**: Bundled tokens + Tailwind v4 `@theme` + resets
232
+ - `@bug-on/m3-expressive/core` — Base providers (`MD3ThemeProvider`), theme utilities (`createMd3ExpressiveTheme`, `generateM3Theme`, `applyTheme`, `resolveMode`), hooks (`useMediaQuery`, `useDOMRipple`, `useTheme`, `useThemeMode`, `useSnackbar`), `Icon`, `Ripple`, `MaterialSymbolsPreconnect`
233
+ - `@bug-on/m3-expressive/buttons` — `Button`, `IconButton`, `ButtonDistribute`, `FAB`, `ExtendedFAB`, `FABMenu`, `SplitButton`, `ButtonGroup`
234
+ - `@bug-on/m3-expressive/forms` — `TextField`, `Select`, `Chip`, `Checkbox`, `TriStateCheckbox`, `RadioButton`, `RadioGroup`, `Switch`, `Slider`, `RangeSlider`
235
+ - `@bug-on/m3-expressive/navigation` — `NavigationBar`, `NavigationBarItem`, `NavigationRail`, `NavigationRailItem`, `NavigationDrawer`, `Tabs`, `Tab`, `TabsList`, `TabsContent`, `SmallAppBar`, `MediumFlexibleAppBar`, `LargeFlexibleAppBar`, `BottomAppBar`, `DockedToolbar`, `HorizontalFloatingToolbar`, `VerticalFloatingToolbar`, `ToolbarIconButton`, `ToolbarToggleButton`, `Menu`, `ContextMenu`, `VerticalMenu`, `Search`, `SearchBar`, `SearchView`
236
+ - `@bug-on/m3-expressive/overlays` — `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogBody`, `DialogFooter`, `DialogClose`, `DialogFullScreenContent`, `Drawer`, `BottomSheet`, `BottomSheetModal`, `SideSheet`, `SideSheetModal`
237
+ - `@bug-on/m3-expressive/feedback` — `Badge`, `BadgedBox`, `LoadingIndicator`, `ProgressIndicator`, `Snackbar`, `SnackbarProvider`, `useSnackbar`, `PlainTooltip`, `RichTooltip`
238
+ - `@bug-on/m3-expressive/layout` — `Card`, `Carousel`, `Divider`, `List`, `ListItem`, `ListDivider`, `ScrollArea`, `CodeBlock`, `TableOfContents`, `Text`, `Typography`, `FadingBlurMask`
239
+ - `@bug-on/m3-expressive/pickers` — `DatePicker`, `DatePickerDialog`, `DatePickerInput`, `DateRangePicker`, `TimePicker`, `TimePickerDialog`, `TimeInput`, `useDatePickerState`, `useDateRangePickerState`, `useTimePickerState`
240
+ - `@bug-on/m3-expressive/shapes` — `ShapeMedia`, `ShapeSvg`, `ShapeIcon`, `useShapeMorph`
235
241
 
236
242
  ---
237
243
 
@@ -253,3 +259,8 @@ import {
253
259
  | `<ProgressIndicator max={100} />` | ProgressIndicator does not support `max` prop. Progress is mapped strictly from 0 to 100 on the `value` prop |
254
260
  | `<ProgressIndicator>` without `aria-label` | `aria-label` is required on all progress indicators for accessibility |
255
261
  | `<ProgressIndicator value={0} />` for indeterminate mode | Omit `value` prop entirely (or pass `undefined`) to trigger indeterminate loading. Setting `value={0}` indicates 0% determinate progress |
262
+ | `<DialogContent>` close button during form submission | Use `closeButtonProps={{ disabled: isSubmitting }}` — do not build a custom close button just for `disabled` support |
263
+ | `<DialogContent>` close button i18n label | Use `closeButtonProps={{ "aria-label": "Đóng" }}` — the `aria-label` prop is forwarded to the `IconButton` |
264
+ | `<DialogContent>` needing full custom close button | Use `closeButton={<YourNode />}` — library auto-wraps in `DialogClose asChild`. When provided, `hideCloseButton` and `closeButtonProps` are ignored |
265
+ | `<DialogFullScreenContent>` action/close disabled during submit | Use `actionButtonProps={{ disabled: isSubmitting }}` and `closeButtonProps={{ disabled: isSubmitting }}` |
266
+ | Building a custom header with `DialogContent` just to control close button style | Use `closeButtonProps={{ colorStyle: "standard" }}` (default) or `"filled"` to override. Only use `hideCloseButton` + custom header when layout positioning is the actual requirement |
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bug-on/m3-expressive
2
2
 
3
- > MD3 Expressive Design System for React + Tailwind v4 + Framer Motion. Version: 1.3.1
3
+ > MD3 Expressive Design System for React 19 + Tailwind CSS v4 + Motion for React (Current Stable Release).
4
4
 
5
5
  > [!WARNING]
6
6
  > Bug On MD3 Expressive only supports **Tailwind CSS v4** (peer dependency `tailwindcss: ">=4.0.0"`). **Tailwind CSS v3 is no longer supported**.
@@ -23,14 +23,19 @@ pnpm add @bug-on/m3-expressive motion
23
23
  ```
24
24
 
25
25
  ```css
26
- /* globals.css — Zero Config Tailwind v4 setup */
26
+ /* globals.css / index.css — Zero Config Tailwind v4 setup */
27
27
  @import "tailwindcss";
28
28
  @import "@bug-on/m3-expressive/index.css"; /* tokens + @theme + resets (REQUIRED) */
29
29
  @import "@bug-on/m3-tailwind"; /* optional: MD3 utilities & elevation */
30
30
  @import "@bug-on/m3-expressive/typography.css"; /* optional: typography preset classes */
31
- @import "@bug-on/m3-expressive/material-symbols-cdn.css"; /* optional: Material Symbols (CDN) */
31
+ @import "@bug-on/m3-expressive/material-symbols-cdn.css"; /* base styles for .md-icon */
32
32
  ```
33
33
 
34
+ Material Symbols CDN Font Loading:
35
+ - **React + Vite**: Add font link tags to `index.html` inside `<head>` (use `display=block` to prevent ligature text flashing):
36
+ `<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block" />`
37
+ - **Next.js (App Router)**: Add `<MaterialSymbolsPreconnect variants={["rounded"]} display="block" />` in `app/layout.tsx` inside `<head>`.
38
+
34
39
  For offline or self-hosted fonts:
35
40
  ```bash
36
41
  pnpm add @bug-on/m3-fonts
@@ -83,13 +88,13 @@ function Root({ children }: { children: React.ReactNode }) {
83
88
 
84
89
  - `@bug-on/m3-expressive` — complete package exports
85
90
  - `@bug-on/m3-expressive/index.css` — **REQUIRED**: bundled tokens + Tailwind `@theme` + resets
86
- - `@bug-on/m3-expressive/core` — base providers (`MD3ThemeProvider`), hooks (`useTheme`, `useThemeMode`, `useSnackbar`), `Icon`, `Ripple`
91
+ - `@bug-on/m3-expressive/core` — base providers (`MD3ThemeProvider`), theme utilities (`createMd3ExpressiveTheme`, `generateM3Theme`, `applyTheme`, `resolveMode`), hooks (`useTheme`, `useThemeMode`, `useSnackbar`, `useMediaQuery`, `useDOMRipple`), `Icon`, `Ripple`, `MaterialSymbolsPreconnect`
87
92
  - `@bug-on/m3-expressive/buttons` — Button, IconButton, ButtonDistribute, FAB, ExtendedFAB, FABMenu, SplitButton, ButtonGroup
88
- - `@bug-on/m3-expressive/forms` — TextField, Chip, Checkbox, TriStateCheckbox, RadioButton, RadioGroup, Switch, Slider, RangeSlider, Select, Search
93
+ - `@bug-on/m3-expressive/forms` — TextField, Chip, Checkbox, TriStateCheckbox, RadioButton, RadioGroup, Switch, Slider, RangeSlider, Select
89
94
  - `@bug-on/m3-expressive/feedback` — Snackbar, SnackbarProvider, useSnackbar, ProgressIndicator (linear, circular, wavy), LoadingIndicator, Badge, BadgedBox, PlainTooltip, RichTooltip
90
95
  - `@bug-on/m3-expressive/navigation` — NavigationBar, NavigationRail, NavigationDrawer, Tabs, Tab, SmallAppBar, MediumFlexibleAppBar, LargeFlexibleAppBar, BottomAppBar, DockedToolbar, HorizontalFloatingToolbar, VerticalFloatingToolbar, Menu, ContextMenu, VerticalMenu, Search
91
96
  - `@bug-on/m3-expressive/overlays` — Dialog, DialogFullScreenContent, Drawer, BottomSheet, BottomSheetModal, SideSheet, SideSheetModal
92
- - `@bug-on/m3-expressive/layout` — Card, Carousel, Divider, List, ListItem, ListDivider, ScrollArea, CodeBlock, TableOfContents, Text, Typography
97
+ - `@bug-on/m3-expressive/layout` — Card, Carousel, Divider, List, ListItem, ListDivider, ScrollArea, CodeBlock, TableOfContents, Text, Typography, FadingBlurMask
93
98
  - `@bug-on/m3-expressive/pickers` — DatePicker, DatePickerDialog, DatePickerInput, DateRangePicker, TimePicker, TimePickerDialog, TimeInput, state hooks
94
99
  - `@bug-on/m3-expressive/shapes` — ShapeMedia, ShapeSvg, ShapeIcon, useShapeMorph
95
100
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bug-on/m3-expressive",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "Material Design 3 Expressive React components",
5
5
  "author": "Bug On",
6
6
  "license": "MIT",
@@ -183,8 +183,8 @@
183
183
  "class-variance-authority": "^0.7.1",
184
184
  "clsx": "^2.1.1",
185
185
  "tailwind-merge": "^3.6.0",
186
- "@bug-on/m3-tokens": "1.2.2",
187
- "@bug-on/m3-tailwind": "1.2.2"
186
+ "@bug-on/m3-tailwind": "1.2.3",
187
+ "@bug-on/m3-tokens": "1.2.2"
188
188
  },
189
189
  "devDependencies": {
190
190
  "@testing-library/jest-dom": "^6.9.1",