@tanishqkancharla/maui 0.0.39 → 0.0.41

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 (40) hide show
  1. package/dist/components/Button.js +9 -8
  2. package/dist/components/Checkbox.js +5 -2
  3. package/dist/components/Code.d.ts +5 -1
  4. package/dist/components/Code.js +5 -2
  5. package/dist/components/Input.js +11 -12
  6. package/dist/components/Radio.js +5 -2
  7. package/dist/components/Select.js +1 -1
  8. package/dist/components/Switch.js +8 -6
  9. package/dist/components/Table.js +4 -1
  10. package/dist/components/Tooltip.js +1 -1
  11. package/dist/maui.d.ts +1 -1
  12. package/dist/tokens/background.d.ts +2 -5
  13. package/dist/tokens/background.js +4 -4
  14. package/dist/tokens/shadow.d.ts +4 -1
  15. package/dist/tokens/shadow.js +4 -1
  16. package/package.json +3 -1
  17. package/src/apps/AiChat/AiChat.tsx +6 -7
  18. package/src/apps/Calendar/Calendar.tsx +196 -81
  19. package/src/apps/JsxEditor/lint.test.ts +4 -13
  20. package/src/components/Button.tsx +28 -29
  21. package/src/components/Checkbox.tsx +21 -14
  22. package/src/components/Code.tsx +19 -2
  23. package/src/components/Input.tsx +22 -19
  24. package/src/components/Radio.tsx +29 -30
  25. package/src/components/Select.tsx +12 -7
  26. package/src/components/Switch.tsx +32 -30
  27. package/src/components/Table.tsx +26 -9
  28. package/src/components/Tooltip.tsx +1 -1
  29. package/src/index.tsx +4 -2
  30. package/src/maui.ts +1 -1
  31. package/src/pages/ButtonsPage.tsx +20 -18
  32. package/src/pages/CrossfadePage.tsx +11 -11
  33. package/src/pages/DrawerPage.tsx +7 -7
  34. package/src/pages/GalleryDeferredPages.dev.tsx +29 -0
  35. package/src/pages/GalleryDeferredPages.ts +7 -0
  36. package/src/pages/Maui.tsx +39 -35
  37. package/src/pages/SidebarPage.tsx +42 -29
  38. package/src/pages/TooltipPage.tsx +20 -11
  39. package/src/tokens/background.ts +8 -4
  40. package/src/tokens/shadow.ts +4 -1
@@ -6,10 +6,9 @@ import { style, useStyles } from "purse-styles";
6
6
  import { useFocus } from "../hooks/useFocus";
7
7
  import { useRefCurrent } from "../hooks/useRefCurrent";
8
8
  import { backgroundColor, surfaceMixPercent, surfaceWash, } from "../tokens/background";
9
- import { colors, } from "../tokens/colors";
9
+ import { colors } from "../tokens/colors";
10
10
  import { focusRing } from "../tokens/focusRing";
11
11
  import { radius } from "../tokens/radius";
12
- import { motion } from "../tokens/motion";
13
12
  import { shadowVars } from "../tokens/shadow";
14
13
  import { controlSize } from "../tokens/sizing";
15
14
  import { spacing } from "../tokens/spacing";
@@ -30,7 +29,7 @@ const disabledQuiet = {
30
29
  backgroundColor: "transparent",
31
30
  boxShadow: "none",
32
31
  };
33
- const buttonBaseClass = style(text({ size: "xs", fontWeight: 400, color: "highContrast" }), focusRing("&:focus-visible", buttonShadow), motion.standard("box-shadow", "background-color", "color"), spacing.padding({ x: 6, y: 4 }), radius.sm, {
32
+ const buttonBaseClass = style(text({ size: "xs", fontWeight: 400, color: "highContrast" }), focusRing("&:focus-visible", buttonShadow), spacing.padding({ x: 6, y: 4 }), radius.sm, {
34
33
  display: "inline-flex",
35
34
  alignItems: "center",
36
35
  justifyContent: "center",
@@ -88,7 +87,7 @@ const buttonClass = style(buttonBaseClass, {
88
87
  function paletteAlpha(name) {
89
88
  return colors[`${name}Alpha`];
90
89
  }
91
- const quietClass = memoize((color, hoverColor, wash) => style(buttonBaseClass, focusRing("&:focus-visible"), motion.standard("box-shadow", "color"), {
90
+ const quietClass = memoize((color, hoverColor, wash) => style(buttonBaseClass, focusRing("&:focus-visible"), {
92
91
  color,
93
92
  backgroundColor: "transparent",
94
93
  boxShadow: "none",
@@ -120,7 +119,7 @@ function paletteFill(name) {
120
119
  function opaqueColor(color) {
121
120
  return `oklch(from ${color} l c h / 1)`;
122
121
  }
123
- /** Hover/active of a one-off fill: same hue, a step darker. */
122
+ /** Pressed state of a one-off fill: same hue, a step darker. */
124
123
  function darkerFill(color) {
125
124
  return `oklch(from ${color} calc(l - 0.04) c h)`;
126
125
  }
@@ -138,7 +137,8 @@ const coloredButtonClass = memoize((variant, color) => {
138
137
  if (isCssColor(color)) {
139
138
  const fill = opaqueColor(color);
140
139
  if (variant === "primary") {
141
- const hover = darkerFill(fill);
140
+ const hover = surfaceWash(colors.gray[12], surfaceMixPercent.hover, fill);
141
+ const pressed = darkerFill(fill);
142
142
  const primaryShadow = primaryButtonShadow(fill);
143
143
  return style(buttonBaseClass, focusRing("&:focus-visible", primaryShadow), {
144
144
  color: onSolidText(fill),
@@ -148,7 +148,7 @@ const coloredButtonClass = memoize((variant, color) => {
148
148
  backgroundColor: hover,
149
149
  },
150
150
  ...pressedOrExpanded({
151
- backgroundColor: hover,
151
+ backgroundColor: pressed,
152
152
  }),
153
153
  "&:disabled": disabledRaised,
154
154
  });
@@ -158,12 +158,13 @@ const coloredButtonClass = memoize((variant, color) => {
158
158
  const scale = paletteFill(color);
159
159
  if (variant === "primary") {
160
160
  const primaryShadow = primaryButtonShadow(scale[9]);
161
+ const hover = surfaceWash(colors.gray[12], surfaceMixPercent.hover, scale[9]);
161
162
  return style(buttonBaseClass, focusRing("&:focus-visible", primaryShadow), {
162
163
  color: darkTextOnSolid.has(color) ? scale[12] : "white",
163
164
  backgroundColor: scale[9],
164
165
  boxShadow: primaryShadow,
165
166
  "&:hover:not(:disabled)": {
166
- backgroundColor: scale[10],
167
+ backgroundColor: hover,
167
168
  },
168
169
  ...pressedOrExpanded({
169
170
  backgroundColor: scale[10],
@@ -4,7 +4,7 @@ import { useCheckbox } from "react-aria";
4
4
  import { useToggleState } from "react-stately";
5
5
  import { defineVars, style, useStyles } from "purse-styles";
6
6
  import { LARGE_SCALE } from "../theme/dataScale";
7
- import { backgroundColor } from "../tokens/background";
7
+ import { backgroundColor, surfaceMixPercent, surfaceWash, } from "../tokens/background";
8
8
  import { colors } from "../tokens/colors";
9
9
  import { focusRing } from "../tokens/focusRing";
10
10
  import { flex } from "../tokens/layout";
@@ -29,12 +29,15 @@ const checkboxClass = style(flex({ alignItems: "center", gap: 3 }), focusRing("&
29
29
  "& .checkbox-input:checked + .checkbox-toggle": {
30
30
  backgroundColor: colors.accent[9],
31
31
  },
32
+ "&:hover .checkbox-input:checked + .checkbox-toggle": {
33
+ backgroundColor: surfaceWash(colors.gray[12], surfaceMixPercent.hover, colors.accent[9]),
34
+ },
32
35
  "& .checkbox-input:checked + .checkbox-toggle .checkbox-icon": {
33
36
  opacity: 1,
34
37
  transform: "scale(1)",
35
38
  },
36
39
  });
37
- const checkboxToggleClass = style(flex({ alignItems: "center", justifyContent: "center" }), radius["2xs"], motion.standard("background-color"), shadow.control, {
40
+ const checkboxToggleClass = style(flex({ alignItems: "center", justifyContent: "center" }), radius["2xs"], shadow.control, {
38
41
  pointerEvents: "none",
39
42
  flexShrink: 0,
40
43
  width: checkboxSize.box,
@@ -1,5 +1,9 @@
1
1
  import type React from "react";
2
2
  type CodeProps = React.HTMLAttributes<HTMLElement>;
3
+ export type KbdVariant = "default" | "quiet";
4
+ export type KbdProps = CodeProps & {
5
+ variant?: KbdVariant;
6
+ };
3
7
  export declare function Code({ className, children, ...props }: CodeProps): React.JSX.Element;
4
- export declare function Kbd({ className, children, ...props }: CodeProps): React.JSX.Element;
8
+ export declare function Kbd({ className, children, variant, ...props }: KbdProps): React.JSX.Element;
5
9
  export {};
@@ -22,12 +22,15 @@ const kbdClass = style(text({ size: "xs", fontWeight: 400, color: "lowContrast"
22
22
  paddingBlock: 0,
23
23
  whiteSpace: "nowrap",
24
24
  });
25
+ const quietKbdClass = style(kbdClass, {
26
+ backgroundColor: "transparent",
27
+ });
25
28
  export function Code({ className, children, ...props }) {
26
29
  const codeClassName = useStyles(codeClass);
27
30
  return (_jsx("code", { ...props, className: joinClassNames(codeClassName, className), children: children }));
28
31
  }
29
- export function Kbd({ className, children, ...props }) {
30
- const kbdClassName = useStyles(kbdClass);
32
+ export function Kbd({ className, children, variant = "default", ...props }) {
33
+ const kbdClassName = useStyles(variant === "quiet" ? quietKbdClass : kbdClass);
31
34
  return (_jsx("kbd", { ...props, className: joinClassNames(kbdClassName, className), children: children }));
32
35
  }
33
36
  function joinClassNames(...classNames) {
@@ -4,20 +4,19 @@ import { mergeProps, useButton, useLocale, useNumberField, useSearchField, useTe
4
4
  import { useNumberFieldState, useSearchFieldState } from "react-stately";
5
5
  import { defineVars, style, useStyles } from "purse-styles";
6
6
  import { LARGE_SCALE } from "../theme/dataScale";
7
- import { backgroundColor } from "../tokens/background";
7
+ import { backgroundColor, surfaceMixPercent, surfaceWash, } from "../tokens/background";
8
8
  import { colors } from "../tokens/colors";
9
9
  import { focusRing } from "../tokens/focusRing";
10
- import { motion } from "../tokens/motion";
11
10
  import { radius } from "../tokens/radius";
12
11
  import { shadow, shadowVars } from "../tokens/shadow";
13
12
  import { controlSize, iconSizeValues } from "../tokens/sizing";
14
13
  import { spacing } from "../tokens/spacing";
15
- import { text } from "../tokens/text";
14
+ import { monospace, text } from "../tokens/text";
15
+ import { CircleX, Minus, Plus } from "../icons";
16
16
  import { Kbd } from "./Code";
17
- import { Icons } from "./Icons";
18
17
  const inputText = text({ size: "sm", fontWeight: 400, color: "highContrast" });
19
18
  const numberFieldDivider = `color-mix(in oklch, ${colors.gray[12]} 5%, ${backgroundColor.element})`;
20
- const inputClass = style(inputText, focusRing("&:focus-visible", shadowVars.control), motion.standard("background", "border-color"), radius.sm, spacing.padding({ x: 4, y: 2 }), shadow.control, {
19
+ const inputClass = style(inputText, focusRing("&:focus-visible", shadowVars.control), radius.sm, spacing.padding({ x: 4, y: 2 }), shadow.control, {
21
20
  width: "100%",
22
21
  minWidth: 0,
23
22
  height: controlSize.height,
@@ -46,7 +45,7 @@ const inputFrameClass = style({
46
45
  const inputWithHintClass = style({
47
46
  paddingRight: "28px",
48
47
  });
49
- const keyboardHintClass = style({
48
+ const keyboardHintClass = style(monospace, {
50
49
  position: "absolute",
51
50
  top: "50%",
52
51
  right: spacing.value(4),
@@ -65,7 +64,7 @@ function useKeyboardHint() {
65
64
  }
66
65
  function KeyboardHint(props) {
67
66
  const className = useStyles(keyboardHintClass);
68
- return (_jsx(Kbd, { className: className, "aria-hidden": "true", children: props.children }));
67
+ return (_jsx(Kbd, { variant: "quiet", className: className, "aria-hidden": "true", children: props.children }));
69
68
  }
70
69
  export function TextField(props) {
71
70
  const { keyboardHint, ...fieldProps } = props;
@@ -127,12 +126,12 @@ export function SearchField(props) {
127
126
  const { isFocused, focusProps } = useKeyboardHint();
128
127
  const inputClassName = useStyles(inputClass);
129
128
  const searchClassName = useStyles(searchFieldClass);
130
- return (_jsxs("div", { className: searchClassName, children: [_jsx("input", { className: inputClassName, ref: ref, ...mergeProps(inputProps, focusProps), "aria-keyshortcuts": ariaKeyShortcuts }), keyboardHint && !isFocused && state.value === "" ? (_jsx(KeyboardHint, { children: keyboardHint })) : null, state.value !== "" && (_jsx("button", { "aria-label": "Clear search", type: "button", onMouseDown: (event) => event.preventDefault(), onClick: () => state.setValue(""), children: _jsx(Icons.CircleX, {}) }))] }));
129
+ return (_jsxs("div", { className: searchClassName, children: [_jsx("input", { className: inputClassName, ref: ref, ...mergeProps(inputProps, focusProps), "aria-keyshortcuts": ariaKeyShortcuts }), keyboardHint && !isFocused && state.value === "" ? (_jsx(KeyboardHint, { children: keyboardHint })) : null, state.value !== "" && (_jsx("button", { "aria-label": "Clear search", type: "button", onMouseDown: (event) => event.preventDefault(), onClick: () => state.setValue(""), children: _jsx(CircleX, {}) }))] }));
131
130
  }
132
131
  const numberFieldSize = defineVars({
133
132
  stepperWidth: { default: "24px", [LARGE_SCALE]: "40px" },
134
133
  });
135
- const numberFieldClass = style(focusRing("&:has(:focus-visible)", shadowVars.control), motion.standard("background", "border-color"), radius.sm, shadow.control, {
134
+ const numberFieldClass = style(focusRing("&:has(:focus-visible)", shadowVars.control), radius.sm, shadow.control, {
136
135
  display: "flex",
137
136
  alignItems: "center",
138
137
  width: "100%",
@@ -207,9 +206,9 @@ export function NumberField(props) {
207
206
  const { buttonProps: decrementProps } = useButton(decrementButtonProps, decrementRef);
208
207
  const inputClassName = useStyles(numberInputClass);
209
208
  const numberClassName = useStyles(numberFieldClass);
210
- return (_jsxs("div", { className: numberClassName, ...groupProps, children: [_jsx("input", { className: inputClassName, ref: ref, ...inputProps }), _jsxs("div", { className: "number-stepper", children: [_jsx("button", { ...decrementProps, ref: decrementRef, type: "button", children: _jsx(Icons.Minus, {}) }), _jsx("button", { ...incrementProps, ref: incrementRef, type: "button", children: _jsx(Icons.Plus, {}) })] })] }));
209
+ return (_jsxs("div", { className: numberClassName, ...groupProps, children: [_jsx("input", { className: inputClassName, ref: ref, ...inputProps }), _jsxs("div", { className: "number-stepper", children: [_jsx("button", { ...decrementProps, ref: decrementRef, type: "button", children: _jsx(Minus, {}) }), _jsx("button", { ...incrementProps, ref: incrementRef, type: "button", children: _jsx(Plus, {}) })] })] }));
211
210
  }
212
- const quietInputClass = style(inputText, focusRing(), motion.standard("background", "border-color"), radius.sm, spacing.padding({ x: 4, y: 2 }), {
211
+ const quietInputClass = style(inputText, focusRing(), radius.sm, spacing.padding({ x: 4, y: 2 }), {
213
212
  width: "100%",
214
213
  minWidth: 0,
215
214
  height: controlSize.height,
@@ -217,7 +216,7 @@ const quietInputClass = style(inputText, focusRing(), motion.standard("backgroun
217
216
  background: "transparent",
218
217
  border: "none",
219
218
  "&:hover:not(:disabled)": {
220
- background: backgroundColor.elementHover,
219
+ background: surfaceWash(colors.gray[12], surfaceMixPercent.hover),
221
220
  },
222
221
  "&:disabled": {
223
222
  color: colors.gray[8],
@@ -3,7 +3,7 @@ import { createContext, useContext, useRef } from "react";
3
3
  import { useRadio, useRadioGroup } from "react-aria";
4
4
  import { useRadioGroupState } from "react-stately";
5
5
  import { style, useStyles } from "purse-styles";
6
- import { backgroundColor } from "../tokens/background";
6
+ import { backgroundColor, surfaceMixPercent, surfaceWash, } from "../tokens/background";
7
7
  import { colors } from "../tokens/colors";
8
8
  import { focusRing } from "../tokens/focusRing";
9
9
  import { flex } from "../tokens/layout";
@@ -30,11 +30,14 @@ const radioClass = style(flex({ alignItems: "center", gap: 3 }), focusRing("& .r
30
30
  "& .radio-input:checked + .radio-toggle": {
31
31
  backgroundColor: colors.accent[9],
32
32
  },
33
+ "&:hover .radio-input:checked + .radio-toggle": {
34
+ backgroundColor: surfaceWash(colors.gray[12], surfaceMixPercent.hover, colors.accent[9]),
35
+ },
33
36
  "& .radio-input:checked + .radio-toggle .radio-dot": {
34
37
  transform: "scale(1)",
35
38
  },
36
39
  });
37
- const radioToggleClass = style(radius.circle, motion.standard("background-color"), shadow.control, {
40
+ const radioToggleClass = style(radius.circle, shadow.control, {
38
41
  pointerEvents: "none",
39
42
  position: "relative",
40
43
  width: "14px",
@@ -19,7 +19,7 @@ const selectClass = style({
19
19
  gap: spacing.value(3),
20
20
  width: "100%",
21
21
  });
22
- const triggerClass = style(text({ size: "sm", fontWeight: 400, color: "highContrast" }), focusRing("&:focus-visible", shadowVars.control), motion.standard("background", "border-color"), radius.sm, spacing.padding({ x: 4, y: 2 }), shadow.control, {
22
+ const triggerClass = style(text({ size: "sm", fontWeight: 400, color: "highContrast" }), focusRing("&:focus-visible", shadowVars.control), radius.sm, spacing.padding({ x: 4, y: 2 }), shadow.control, {
23
23
  display: "flex",
24
24
  alignItems: "center",
25
25
  height: controlSize.height,
@@ -5,6 +5,7 @@ import { useToggleState } from "react-stately";
5
5
  import { defineVars, style, useStyles } from "purse-styles";
6
6
  import { DARK_THEME } from "../theme/dataTheme";
7
7
  import { LARGE_SCALE } from "../theme/dataScale";
8
+ import { surfaceMixPercent, surfaceWash } from "../tokens/background";
8
9
  import { colors } from "../tokens/colors";
9
10
  import { focusRing } from "../tokens/focusRing";
10
11
  import { flex } from "../tokens/layout";
@@ -25,26 +26,27 @@ const switchOff = defineVars({
25
26
  default: colors.gray[2],
26
27
  [DARK_THEME]: colors.gray[1],
27
28
  },
28
- trackHover: {
29
- default: colors.gray[3],
30
- [DARK_THEME]: colors.gray[2],
31
- },
32
29
  });
30
+ const switchOffHover = surfaceWash(colors.gray[12], surfaceMixPercent.hover, switchOff.track);
31
+ const switchOnHover = surfaceWash(colors.gray[12], surfaceMixPercent.hover, colors.accent[9]);
33
32
  const switchClass = style(flex({ alignItems: "center", gap: 3 }), focusRing("& .switch-input:focus-visible + .switch-toggle", shadowVars.control), {
34
33
  position: "relative",
35
34
  width: "fit-content",
36
35
  minHeight: controlSize.minTarget,
37
36
  "&:hover .switch-toggle": {
38
- backgroundColor: switchOff.trackHover,
37
+ backgroundColor: switchOffHover,
39
38
  },
40
39
  "& .switch-input:checked + .switch-toggle": {
41
40
  backgroundColor: colors.accent[9],
42
41
  },
42
+ "&:hover .switch-input:checked + .switch-toggle": {
43
+ backgroundColor: switchOnHover,
44
+ },
43
45
  "& .switch-input:checked + .switch-toggle .switch-thumb": {
44
46
  transform: `translateX(calc(${switchSize.width} - ${switchSize.thumb} - 4px))`,
45
47
  },
46
48
  });
47
- const switchToggleClass = style(radius.pill, motion.standard("background-color"), shadow.control, {
49
+ const switchToggleClass = style(radius.pill, shadow.control, {
48
50
  position: "relative",
49
51
  flexShrink: 0,
50
52
  width: switchSize.width,
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Cell as AriaCell, Checkbox as AriaCheckbox, Collection, Column as AriaColumn, Row as AriaRow, Table as AriaTable, TableBody as AriaTableBody, TableFooter as AriaTableFooter, TableHeader as AriaTableHeader, useTableOptions, } from "react-aria-components";
3
3
  import { style, useStyles } from "purse-styles";
4
- import { backgroundColor } from "../tokens/background";
4
+ import { backgroundColor, surfaceMixPercent, surfaceWash, } from "../tokens/background";
5
5
  import { border, borderColor } from "../tokens/borders";
6
6
  import { colors } from "../tokens/colors";
7
7
  import { focusRing } from "../tokens/focusRing";
@@ -103,6 +103,9 @@ const tableSelectionCheckboxClass = style(flex({ alignItems: "center", justifyCo
103
103
  "&[data-selected] .checkbox-toggle, &[data-indeterminate] .checkbox-toggle": {
104
104
  backgroundColor: colors.accent[9],
105
105
  },
106
+ "&[data-hovered][data-selected] .checkbox-toggle, &[data-hovered][data-indeterminate] .checkbox-toggle": {
107
+ backgroundColor: surfaceWash(colors.gray[12], surfaceMixPercent.hover, colors.accent[9]),
108
+ },
106
109
  "&[data-selected] .checkbox-icon, &[data-indeterminate] .checkbox-icon": {
107
110
  opacity: 1,
108
111
  transform: "scale(1)",
@@ -5,11 +5,11 @@ import ReactDOM from "react-dom";
5
5
  import { mergeProps, useOverlayPosition, useTooltip, useTooltipTrigger, } from "react-aria";
6
6
  import { useTooltipTriggerState } from "react-stately";
7
7
  import { style, useStyles } from "purse-styles";
8
+ import { background } from "../tokens/background";
8
9
  import { radius } from "../tokens/radius";
9
10
  import { shadow } from "../tokens/shadow";
10
11
  import { spacing } from "../tokens/spacing";
11
12
  import { text } from "../tokens/text";
12
- import { background } from "../maui";
13
13
  export function Tooltip(props) {
14
14
  const { content, children, placement = "top", delay = 500, isDisabled, } = props;
15
15
  const state = useTooltipTriggerState({ delay, isDisabled });
package/dist/maui.d.ts CHANGED
@@ -45,6 +45,6 @@ export { Flex, Gap, Spacer, Divider, type FlexShadow, type FlexRadius, type Flex
45
45
  export { Text, type TextProps } from "./components/Text";
46
46
  export { H1, H2, H3, H4, P, Label, labelText, Blockquote, Ul, Ol, Li, Link, } from "./components/Typography";
47
47
  export { CodeBlock } from "./components/CodeBlock";
48
- export { Code, Kbd } from "./components/Code";
48
+ export { Code, Kbd, type KbdProps, type KbdVariant } from "./components/Code";
49
49
  export { CollectionPopover, type CollectionPopoverProps, } from "./components/CollectionPopover";
50
50
  export { navigationItem } from "./components/navigationItem";
@@ -1,9 +1,6 @@
1
- /** Transparent-wash percents (press is 2× hover). */
1
+ /** Shared interactive surface washes. */
2
2
  export declare const surfaceMixPercent: {
3
- readonly hover: {
4
- readonly light: 6;
5
- readonly dark: 9;
6
- };
3
+ readonly hover: 3.5;
7
4
  readonly active: {
8
5
  readonly light: 12;
9
6
  readonly dark: 18;
@@ -4,7 +4,7 @@ import { memoize } from "../utils/memoize";
4
4
  import { colors } from "./colors";
5
5
  const appSurface = defineVars({
6
6
  app: {
7
- default: "#ffffff",
7
+ default: colors.gray[1],
8
8
  [DARK_THEME]: colors.gray[1],
9
9
  },
10
10
  });
@@ -14,9 +14,9 @@ const elementSurface = defineVars({
14
14
  [DARK_THEME]: colors.gray[2],
15
15
  },
16
16
  });
17
- /** Transparent-wash percents (press is 2× hover). */
17
+ /** Shared interactive surface washes. */
18
18
  export const surfaceMixPercent = {
19
- hover: { light: 6, dark: 9 },
19
+ hover: 3.5,
20
20
  active: { light: 12, dark: 18 },
21
21
  };
22
22
  /** `color-mix` of a foreground into `base` (transparent by default). */
@@ -34,7 +34,7 @@ const themeWash = memoize((foreground, percent, base) => defineVars({
34
34
  }).wash);
35
35
  // Craft-style foreground wash over the element's own surface.
36
36
  const elementStates = defineVars({
37
- elementHover: surfaceWash(colors.gray[12], 3.5, elementSurface.element),
37
+ elementHover: surfaceWash(colors.gray[12], surfaceMixPercent.hover, elementSurface.element),
38
38
  elementActive: surfaceWash(colors.gray[12], 7, elementSurface.element),
39
39
  });
40
40
  export const backgroundColor = {
@@ -1,5 +1,8 @@
1
1
  export declare const shadowVars: import("purse-styles").VariableGroup<{
2
- readonly control: "inset 0 1px #ffffff08, inset 0 0 1px .5px #fff1, 0 1px .5px #00000018, 0 0 3px -1px #000a";
2
+ readonly control: {
3
+ readonly default: "inset 0 1px #fff8, inset 0 0 1px 1px #fff8, 0 .5px 1px #00000018, 0 0 1px #0001, 0 0 4px -1px #0001";
4
+ readonly ":root[data-theme=\"dark\"]": "inset 0 1px #ffffff08, inset 0 0 1px .5px #fff1, 0 1px .5px #00000018, 0 0 3px -1px #000a";
5
+ };
3
6
  readonly subtle: `rgba(var(--${string}), 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, var(--${string})) 0px 1px 1px -0.5px, rgba(0, 0, 0, var(--${string})) 0px 3px 3px -1.5px`;
4
7
  readonly medium: `rgba(var(--${string}), 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, var(--${string})) 0px 1px 1px -0.5px, rgba(0, 0, 0, var(--${string})) 0px 3px 3px -1.5px, rgba(0, 0, 0, var(--${string})) 0px 6px 6px -3px`;
5
8
  readonly strong: `rgba(var(--${string}), 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, var(--${string})) 0px 1px 1px -0.5px, rgba(0, 0, 0, var(--${string})) 0px 3px 3px -1.5px, rgba(0, 0, 0, var(--${string})) 0px 6px 6px -3px, rgba(0, 0, 0, calc(var(--${string}) * 0.67)) 0px 12px 12px -6px, rgba(0, 0, 0, calc(var(--${string}) * 0.67)) 0px 24px 24px -12px`;
@@ -13,7 +13,10 @@ const shadowParams = defineVars({
13
13
  const rgb = shadowParams.foregroundRgb;
14
14
  const blur = shadowParams.blurOpacity;
15
15
  export const shadowVars = defineVars({
16
- control: `inset 0 1px #ffffff08, inset 0 0 1px .5px #fff1, 0 1px .5px #00000018, 0 0 3px -1px #000a`,
16
+ control: {
17
+ default: `inset 0 1px #fff8, inset 0 0 1px 1px #fff8, 0 .5px 1px #00000018, 0 0 1px #0001, 0 0 4px -1px #0001`,
18
+ [DARK_THEME]: `inset 0 1px #ffffff08, inset 0 0 1px .5px #fff1, 0 1px .5px #00000018, 0 0 3px -1px #000a`,
19
+ },
17
20
  subtle: `rgba(${rgb}, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, ${blur}) 0px 1px 1px -0.5px, rgba(0, 0, 0, ${blur}) 0px 3px 3px -1.5px`,
18
21
  medium: `rgba(${rgb}, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, ${blur}) 0px 1px 1px -0.5px, rgba(0, 0, 0, ${blur}) 0px 3px 3px -1.5px, rgba(0, 0, 0, ${blur}) 0px 6px 6px -3px`,
19
22
  strong: `rgba(${rgb}, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, ${blur}) 0px 1px 1px -0.5px, rgba(0, 0, 0, ${blur}) 0px 3px 3px -1.5px, rgba(0, 0, 0, ${blur}) 0px 6px 6px -3px, rgba(0, 0, 0, calc(${blur} * 0.67)) 0px 12px 12px -6px, rgba(0, 0, 0, calc(${blur} * 0.67)) 0px 24px 24px -12px`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanishqkancharla/maui",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "Maui design system",
5
5
  "type": "module",
6
6
  "main": "./dist/maui.js",
@@ -63,11 +63,13 @@
63
63
  "clear": "mkdir -p dist && rm -rf dist/*",
64
64
  "dev": "vite",
65
65
  "build": "npm run og && vite build",
66
+ "build:review": "vite build --mode review --outDir ../website-review",
66
67
  "build:lib": "tsc -p tsconfig.lib.json",
67
68
  "prepack": "npm run build:lib",
68
69
  "verify-package": "node scripts/verify-package.mjs",
69
70
  "og": "node scripts/generate-og-image.mjs",
70
71
  "serve": "vite preview",
72
+ "serve:review": "serve -s website-review",
71
73
  "deploy": "npx vercel deploy",
72
74
  "test": "vitest",
73
75
  "mcp:browser": "node .cursor/libretto-browser-mcp.mjs",
@@ -3,9 +3,9 @@ import type { Editor as TiptapEditor } from "@tiptap/react"
3
3
  import { style, useStyles } from "purse-styles"
4
4
  import { Button } from "../../components/Button"
5
5
  import { MarkdownEditor } from "../../components/MarkdownEditor"
6
- import { Icons } from "../../components/Icons"
7
6
  import { Thinking } from "../../components/Thinking"
8
7
  import { AssistantMessage } from "../../patterns/AssistantMessage"
8
+ import { ArrowUp } from "../../icons"
9
9
  import { backgroundColor } from "../../tokens/background"
10
10
  import { border } from "../../tokens/borders"
11
11
  import { colors } from "../../tokens/colors"
@@ -105,10 +105,7 @@ function streamAssistantTurn(
105
105
  onDone()
106
106
  return
107
107
  }
108
- timeoutId = window.setTimeout(
109
- tickText,
110
- 16 + Math.floor(Math.random() * 28),
111
- )
108
+ timeoutId = window.setTimeout(tickText, 16 + Math.floor(Math.random() * 28))
112
109
  }
113
110
 
114
111
  const tickTools = () => {
@@ -313,7 +310,7 @@ export function AiChat() {
313
310
  isDisabled={streaming || !draft.trim()}
314
311
  onClick={send}
315
312
  >
316
- <Icons.ArrowUp size="sm" />
313
+ <ArrowUp size="sm" />
317
314
  </Button>
318
315
  </div>
319
316
  </div>
@@ -398,7 +395,9 @@ const composerShellClass = style(
398
395
  },
399
396
  )
400
397
 
401
- const composerActionsClass = style(flex({ alignItems: "center", justifyContent: "end", gap: 3 }))
398
+ const composerActionsClass = style(
399
+ flex({ alignItems: "center", justifyContent: "end", gap: 3 }),
400
+ )
402
401
 
403
402
  /** Filled circular send control — icon-only Button without the default shadow. */
404
403
  const sendButtonClass = style(radius.circle, {