@tanishqkancharla/maui 0.0.41 → 0.0.43

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.
@@ -64,25 +64,11 @@ const buttonTextClass = style({
64
64
  minWidth: 0,
65
65
  textBox: "trim-both cap alphabetic",
66
66
  });
67
- /**
68
- * RAC `data-pressed` is true while the pointer is down. MenuTrigger’s
69
- * PressResponder also keeps it while the menu is open. `aria-expanded`
70
- * covers Select / ComboBox / DatePicker / DialogTrigger overlays.
71
- */
72
- function pressedOrExpanded(styles) {
73
- return {
74
- "&:active:not(:disabled), &[data-pressed]:not(:disabled)": styles,
75
- "&[aria-expanded='true']:not(:disabled)": styles,
76
- };
77
- }
78
67
  const buttonClass = style(buttonBaseClass, {
79
68
  backgroundColor: backgroundColor.element,
80
69
  "&:hover:not(:disabled)": {
81
70
  backgroundColor: backgroundColor.elementHover,
82
71
  },
83
- ...pressedOrExpanded({
84
- backgroundColor: backgroundColor.elementActive,
85
- }),
86
72
  });
87
73
  function paletteAlpha(name) {
88
74
  return colors[`${name}Alpha`];
@@ -95,10 +81,6 @@ const quietClass = memoize((color, hoverColor, wash) => style(buttonBaseClass, f
95
81
  color: hoverColor,
96
82
  backgroundColor: surfaceWash(wash, surfaceMixPercent.hover),
97
83
  },
98
- ...pressedOrExpanded({
99
- color: hoverColor,
100
- backgroundColor: surfaceWash(wash, surfaceMixPercent.active),
101
- }),
102
84
  "&:disabled": disabledQuiet,
103
85
  }));
104
86
  const quietButtonClass = quietClass(colors.gray[11], colors.gray[12], colors.grayAlpha[9]);
@@ -119,7 +101,7 @@ function paletteFill(name) {
119
101
  function opaqueColor(color) {
120
102
  return `oklch(from ${color} l c h / 1)`;
121
103
  }
122
- /** Pressed state of a one-off fill: same hue, a step darker. */
104
+ /** Darken a one-off fill while preserving its hue. */
123
105
  function darkerFill(color) {
124
106
  return `oklch(from ${color} calc(l - 0.04) c h)`;
125
107
  }
@@ -138,7 +120,6 @@ const coloredButtonClass = memoize((variant, color) => {
138
120
  const fill = opaqueColor(color);
139
121
  if (variant === "primary") {
140
122
  const hover = surfaceWash(colors.gray[12], surfaceMixPercent.hover, fill);
141
- const pressed = darkerFill(fill);
142
123
  const primaryShadow = primaryButtonShadow(fill);
143
124
  return style(buttonBaseClass, focusRing("&:focus-visible", primaryShadow), {
144
125
  color: onSolidText(fill),
@@ -147,9 +128,6 @@ const coloredButtonClass = memoize((variant, color) => {
147
128
  "&:hover:not(:disabled)": {
148
129
  backgroundColor: hover,
149
130
  },
150
- ...pressedOrExpanded({
151
- backgroundColor: pressed,
152
- }),
153
131
  "&:disabled": disabledRaised,
154
132
  });
155
133
  }
@@ -166,9 +144,6 @@ const coloredButtonClass = memoize((variant, color) => {
166
144
  "&:hover:not(:disabled)": {
167
145
  backgroundColor: hover,
168
146
  },
169
- ...pressedOrExpanded({
170
- backgroundColor: scale[10],
171
- }),
172
147
  "&:disabled": disabledRaised,
173
148
  });
174
149
  }
@@ -8,6 +8,11 @@
8
8
  * (https://github.com/tailwindlabs/tailwindcss-typography): `sm` -> 14px base,
9
9
  * `md` -> Tailwind's `base` (16px), `lg` -> 18px. Tailwind's em-relative values
10
10
  * are resolved to px here so they compose with Maui's px-based tokens.
11
+ *
12
+ * On the Large platform scale (coarse pointers) block font sizes and line
13
+ * heights step up ~1.2x — the same idea as the `text` tokens — so reading
14
+ * content grows with the rest of the UI on touch devices. Block gaps tighten
15
+ * separately (see `blockGaps`).
11
16
  */
12
17
  export type ProseSize = "sm" | "md" | "lg";
13
18
  export declare const prose: (size: ProseSize) => {
@@ -4,36 +4,100 @@ import { memoize } from "../utils/memoize";
4
4
  import { colors } from "./colors";
5
5
  import { motionEasing, motionStreamDurationMs } from "./motion";
6
6
  import { fontFamily, monoFontStyle } from "./text";
7
+ /** A block size that steps up with the platform data scale. */
8
+ const scaledPx = (normal, large) => defineVars({
9
+ px: { default: `${normal}px`, [LARGE_SCALE]: `${large}px` },
10
+ }).px;
7
11
  const metrics = {
8
12
  sm: {
9
13
  blockGap: 16,
10
- paragraph: { fontSize: 14, lineHeight: 24 },
11
- h1: { fontSize: 30, lineHeight: 36, marginTop: 32, marginBottom: 24 },
12
- h2: { fontSize: 20, lineHeight: 28, marginTop: 32, marginBottom: 16 },
13
- h3: { fontSize: 18, lineHeight: 28, marginTop: 28, marginBottom: 8 },
14
- h4: { fontSize: 14, lineHeight: 20, marginTop: 20, marginBottom: 8 },
14
+ paragraph: { fontSize: scaledPx(14, 17), lineHeight: scaledPx(24, 29) },
15
+ h1: {
16
+ fontSize: scaledPx(30, 36),
17
+ lineHeight: scaledPx(36, 43),
18
+ marginTop: 32,
19
+ marginBottom: 24,
20
+ },
21
+ h2: {
22
+ fontSize: scaledPx(20, 24),
23
+ lineHeight: scaledPx(28, 34),
24
+ marginTop: 32,
25
+ marginBottom: 16,
26
+ },
27
+ h3: {
28
+ fontSize: scaledPx(18, 22),
29
+ lineHeight: scaledPx(28, 34),
30
+ marginTop: 28,
31
+ marginBottom: 8,
32
+ },
33
+ h4: {
34
+ fontSize: scaledPx(14, 17),
35
+ lineHeight: scaledPx(20, 24),
36
+ marginTop: 20,
37
+ marginBottom: 8,
38
+ },
15
39
  listPadding: 22,
16
40
  listItemGap: 4,
17
41
  listNestedGap: 8,
18
42
  },
19
43
  md: {
20
44
  blockGap: 20,
21
- paragraph: { fontSize: 16, lineHeight: 28 },
22
- h1: { fontSize: 36, lineHeight: 40, marginTop: 48, marginBottom: 32 },
23
- h2: { fontSize: 24, lineHeight: 32, marginTop: 48, marginBottom: 24 },
24
- h3: { fontSize: 20, lineHeight: 32, marginTop: 32, marginBottom: 12 },
25
- h4: { fontSize: 16, lineHeight: 24, marginTop: 24, marginBottom: 8 },
45
+ paragraph: { fontSize: scaledPx(16, 19), lineHeight: scaledPx(28, 34) },
46
+ h1: {
47
+ fontSize: scaledPx(36, 43),
48
+ lineHeight: scaledPx(40, 48),
49
+ marginTop: 48,
50
+ marginBottom: 32,
51
+ },
52
+ h2: {
53
+ fontSize: scaledPx(24, 29),
54
+ lineHeight: scaledPx(32, 38),
55
+ marginTop: 48,
56
+ marginBottom: 24,
57
+ },
58
+ h3: {
59
+ fontSize: scaledPx(20, 24),
60
+ lineHeight: scaledPx(32, 38),
61
+ marginTop: 32,
62
+ marginBottom: 12,
63
+ },
64
+ h4: {
65
+ fontSize: scaledPx(16, 19),
66
+ lineHeight: scaledPx(24, 29),
67
+ marginTop: 24,
68
+ marginBottom: 8,
69
+ },
26
70
  listPadding: 26,
27
71
  listItemGap: 8,
28
72
  listNestedGap: 12,
29
73
  },
30
74
  lg: {
31
75
  blockGap: 24,
32
- paragraph: { fontSize: 18, lineHeight: 32 },
33
- h1: { fontSize: 48, lineHeight: 48, marginTop: 56, marginBottom: 40 },
34
- h2: { fontSize: 30, lineHeight: 40, marginTop: 56, marginBottom: 32 },
35
- h3: { fontSize: 24, lineHeight: 36, marginTop: 40, marginBottom: 16 },
36
- h4: { fontSize: 18, lineHeight: 28, marginTop: 32, marginBottom: 8 },
76
+ paragraph: { fontSize: scaledPx(18, 22), lineHeight: scaledPx(32, 38) },
77
+ h1: {
78
+ fontSize: scaledPx(48, 58),
79
+ lineHeight: scaledPx(48, 58),
80
+ marginTop: 56,
81
+ marginBottom: 40,
82
+ },
83
+ h2: {
84
+ fontSize: scaledPx(30, 36),
85
+ lineHeight: scaledPx(40, 48),
86
+ marginTop: 56,
87
+ marginBottom: 32,
88
+ },
89
+ h3: {
90
+ fontSize: scaledPx(24, 29),
91
+ lineHeight: scaledPx(36, 43),
92
+ marginTop: 40,
93
+ marginBottom: 16,
94
+ },
95
+ h4: {
96
+ fontSize: scaledPx(18, 22),
97
+ lineHeight: scaledPx(28, 34),
98
+ marginTop: 32,
99
+ marginBottom: 8,
100
+ },
37
101
  listPadding: 28,
38
102
  listItemGap: 12,
39
103
  listNestedGap: 16,
@@ -52,8 +116,8 @@ const bodyColor = colors.gray[12];
52
116
  const quoteColor = colors.gray[11];
53
117
  const px = (value) => `${value}px`;
54
118
  const block = (metric) => ({
55
- fontSize: px(metric.fontSize),
56
- lineHeight: px(metric.lineHeight),
119
+ fontSize: metric.fontSize,
120
+ lineHeight: metric.lineHeight,
57
121
  fontFamily,
58
122
  });
59
123
  export const prose = memoize((size) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanishqkancharla/maui",
3
- "version": "0.0.41",
3
+ "version": "0.0.43",
4
4
  "description": "Maui design system",
5
5
  "type": "module",
6
6
  "main": "./dist/maui.js",
@@ -113,11 +113,13 @@ text({
113
113
  | `lg` | 16px | 24px |
114
114
  | `xl` | 22px | 30px |
115
115
 
116
+ Sizes step up on the **Large platform scale** (`:root[data-scale="large"]`, driven by `(pointer: coarse)` under the system preference): `md` is 14px/22px on desktop and 17px/26px on coarse pointers. See `useScale` / `ScaleProvider`.
117
+
116
118
  - `lowContrast` → `gray[11]`, `highContrast` → `gray[12]`, `accent` → `accent[11]`, `onAccent` → white.
117
119
  - UI sans: `fontFamily` (system ui-sans-serif stack). Mono: Commit Mono with `ss05` smart kerning (`monoFontStyle` / `monospace`).
118
120
  - `tabular: true` → `font-variant-numeric: tabular-nums`. NumberField, TableHead, and TableCell turn this on by default. Body copy and Prose stay off.
119
121
  - `baseTextStyle` is md / 400 / highContrast — already on `html, body`.
120
- - Inside `Prose`, `H1`–`H4` / `P` / lists switch to the **prose** scale (`sm` 14px, `md` 16px, `lg` 18px), which is larger and has reading rhythm. Do not put app chrome inside `Prose`.
122
+ - Inside `Prose`, `H1`–`H4` / `P` / lists switch to the **prose** scale (`sm` 14px, `md` 16px, `lg` 18px), which is larger and has reading rhythm. Prose block sizes and line heights also step up ~1.2x on the Large platform scale. Do not put app chrome inside `Prose`.
121
123
 
122
124
  `proseContainerStyle` is the composable column (`maxWidth: proseMaxWidth`, `"80ch"`). `sizing.contentWidth` is that same style. `sizing.fullWidth` is `width: 100%`.
123
125
 
@@ -84,26 +84,11 @@ const buttonTextClass = style({
84
84
  textBox: "trim-both cap alphabetic",
85
85
  })
86
86
 
87
- /**
88
- * RAC `data-pressed` is true while the pointer is down. MenuTrigger’s
89
- * PressResponder also keeps it while the menu is open. `aria-expanded`
90
- * covers Select / ComboBox / DatePicker / DialogTrigger overlays.
91
- */
92
- function pressedOrExpanded(styles: Record<string, string>) {
93
- return {
94
- "&:active:not(:disabled), &[data-pressed]:not(:disabled)": styles,
95
- "&[aria-expanded='true']:not(:disabled)": styles,
96
- }
97
- }
98
-
99
87
  const buttonClass = style(buttonBaseClass, {
100
88
  backgroundColor: backgroundColor.element,
101
89
  "&:hover:not(:disabled)": {
102
90
  backgroundColor: backgroundColor.elementHover,
103
91
  },
104
- ...pressedOrExpanded({
105
- backgroundColor: backgroundColor.elementActive,
106
- }),
107
92
  })
108
93
 
109
94
  function paletteAlpha(name: ColorName): ColorScale {
@@ -119,10 +104,6 @@ const quietClass = memoize((color: string, hoverColor: string, wash: string) =>
119
104
  color: hoverColor,
120
105
  backgroundColor: surfaceWash(wash, surfaceMixPercent.hover),
121
106
  },
122
- ...pressedOrExpanded({
123
- color: hoverColor,
124
- backgroundColor: surfaceWash(wash, surfaceMixPercent.active),
125
- }),
126
107
  "&:disabled": disabledQuiet,
127
108
  }),
128
109
  )
@@ -158,7 +139,7 @@ function opaqueColor(color: string) {
158
139
  return `oklch(from ${color} l c h / 1)`
159
140
  }
160
141
 
161
- /** Pressed state of a one-off fill: same hue, a step darker. */
142
+ /** Darken a one-off fill while preserving its hue. */
162
143
  function darkerFill(color: string) {
163
144
  return `oklch(from ${color} calc(l - 0.04) c h)`
164
145
  }
@@ -185,7 +166,6 @@ const coloredButtonClass = memoize(
185
166
  surfaceMixPercent.hover,
186
167
  fill,
187
168
  )
188
- const pressed = darkerFill(fill)
189
169
  const primaryShadow = primaryButtonShadow(fill)
190
170
  return style(
191
171
  buttonBaseClass,
@@ -197,9 +177,6 @@ const coloredButtonClass = memoize(
197
177
  "&:hover:not(:disabled)": {
198
178
  backgroundColor: hover,
199
179
  },
200
- ...pressedOrExpanded({
201
- backgroundColor: pressed,
202
- }),
203
180
  "&:disabled": disabledRaised,
204
181
  },
205
182
  )
@@ -226,9 +203,6 @@ const coloredButtonClass = memoize(
226
203
  "&:hover:not(:disabled)": {
227
204
  backgroundColor: hover,
228
205
  },
229
- ...pressedOrExpanded({
230
- backgroundColor: scale[10],
231
- }),
232
206
  "&:disabled": disabledRaised,
233
207
  },
234
208
  )
@@ -29,7 +29,7 @@ export function ButtonsPage() {
29
29
  <P>
30
30
  <Code>isDisabled</Code> is React Aria’s disabled prop. It sets the
31
31
  native <Code>disabled</Code> attribute — there is no parallel{" "}
32
- <Code>disabled</Code> React prop. Hover and press fills do not apply.
32
+ <Code>disabled</Code> React prop. The hover fill does not apply.
33
33
  </P>
34
34
  <Flex row alignItems="center" gap={4} style={{ flexWrap: "wrap" }}>
35
35
  <Button isDisabled>Button</Button>
@@ -110,9 +110,9 @@ export function ButtonsPage() {
110
110
  <H3>Quiet</H3>
111
111
  <P>
112
112
  <Code>variant="quiet"</Code> has no fill. <Code>variantColor</Code>{" "}
113
- tints the label and icon. Hover and press mix <Code>grayAlpha[9]</Code>{" "}
114
- (or that color’s alpha 9) into transparent. Hover uses the shared 3.5%
115
- control wash; press remains stronger.
113
+ tints the label and icon. Hover mixes <Code>grayAlpha[9]</Code> (or
114
+ that color’s alpha 9) into transparent using the shared 3.5% control
115
+ wash.
116
116
  </P>
117
117
  <Flex row alignItems="center" gap={4} style={{ flexWrap: "wrap" }}>
118
118
  <Button variant="quiet">Button</Button>
@@ -15,12 +15,17 @@ import { fontFamily, monoFontStyle } from "./text"
15
15
  * (https://github.com/tailwindlabs/tailwindcss-typography): `sm` -> 14px base,
16
16
  * `md` -> Tailwind's `base` (16px), `lg` -> 18px. Tailwind's em-relative values
17
17
  * are resolved to px here so they compose with Maui's px-based tokens.
18
+ *
19
+ * On the Large platform scale (coarse pointers) block font sizes and line
20
+ * heights step up ~1.2x — the same idea as the `text` tokens — so reading
21
+ * content grows with the rest of the UI on touch devices. Block gaps tighten
22
+ * separately (see `blockGaps`).
18
23
  */
19
24
  export type ProseSize = "sm" | "md" | "lg"
20
25
 
21
26
  type BlockMetric = {
22
- fontSize: number
23
- lineHeight: number
27
+ fontSize: string
28
+ lineHeight: string
24
29
  }
25
30
 
26
31
  type HeadingMetric = BlockMetric & {
@@ -43,36 +48,102 @@ type ProseMetric = {
43
48
  listNestedGap: number
44
49
  }
45
50
 
51
+ /** A block size that steps up with the platform data scale. */
52
+ const scaledPx = (normal: number, large: number) =>
53
+ defineVars({
54
+ px: { default: `${normal}px`, [LARGE_SCALE]: `${large}px` },
55
+ }).px
56
+
46
57
  const metrics: Record<ProseSize, ProseMetric> = {
47
58
  sm: {
48
59
  blockGap: 16,
49
- paragraph: { fontSize: 14, lineHeight: 24 },
50
- h1: { fontSize: 30, lineHeight: 36, marginTop: 32, marginBottom: 24 },
51
- h2: { fontSize: 20, lineHeight: 28, marginTop: 32, marginBottom: 16 },
52
- h3: { fontSize: 18, lineHeight: 28, marginTop: 28, marginBottom: 8 },
53
- h4: { fontSize: 14, lineHeight: 20, marginTop: 20, marginBottom: 8 },
60
+ paragraph: { fontSize: scaledPx(14, 17), lineHeight: scaledPx(24, 29) },
61
+ h1: {
62
+ fontSize: scaledPx(30, 36),
63
+ lineHeight: scaledPx(36, 43),
64
+ marginTop: 32,
65
+ marginBottom: 24,
66
+ },
67
+ h2: {
68
+ fontSize: scaledPx(20, 24),
69
+ lineHeight: scaledPx(28, 34),
70
+ marginTop: 32,
71
+ marginBottom: 16,
72
+ },
73
+ h3: {
74
+ fontSize: scaledPx(18, 22),
75
+ lineHeight: scaledPx(28, 34),
76
+ marginTop: 28,
77
+ marginBottom: 8,
78
+ },
79
+ h4: {
80
+ fontSize: scaledPx(14, 17),
81
+ lineHeight: scaledPx(20, 24),
82
+ marginTop: 20,
83
+ marginBottom: 8,
84
+ },
54
85
  listPadding: 22,
55
86
  listItemGap: 4,
56
87
  listNestedGap: 8,
57
88
  },
58
89
  md: {
59
90
  blockGap: 20,
60
- paragraph: { fontSize: 16, lineHeight: 28 },
61
- h1: { fontSize: 36, lineHeight: 40, marginTop: 48, marginBottom: 32 },
62
- h2: { fontSize: 24, lineHeight: 32, marginTop: 48, marginBottom: 24 },
63
- h3: { fontSize: 20, lineHeight: 32, marginTop: 32, marginBottom: 12 },
64
- h4: { fontSize: 16, lineHeight: 24, marginTop: 24, marginBottom: 8 },
91
+ paragraph: { fontSize: scaledPx(16, 19), lineHeight: scaledPx(28, 34) },
92
+ h1: {
93
+ fontSize: scaledPx(36, 43),
94
+ lineHeight: scaledPx(40, 48),
95
+ marginTop: 48,
96
+ marginBottom: 32,
97
+ },
98
+ h2: {
99
+ fontSize: scaledPx(24, 29),
100
+ lineHeight: scaledPx(32, 38),
101
+ marginTop: 48,
102
+ marginBottom: 24,
103
+ },
104
+ h3: {
105
+ fontSize: scaledPx(20, 24),
106
+ lineHeight: scaledPx(32, 38),
107
+ marginTop: 32,
108
+ marginBottom: 12,
109
+ },
110
+ h4: {
111
+ fontSize: scaledPx(16, 19),
112
+ lineHeight: scaledPx(24, 29),
113
+ marginTop: 24,
114
+ marginBottom: 8,
115
+ },
65
116
  listPadding: 26,
66
117
  listItemGap: 8,
67
118
  listNestedGap: 12,
68
119
  },
69
120
  lg: {
70
121
  blockGap: 24,
71
- paragraph: { fontSize: 18, lineHeight: 32 },
72
- h1: { fontSize: 48, lineHeight: 48, marginTop: 56, marginBottom: 40 },
73
- h2: { fontSize: 30, lineHeight: 40, marginTop: 56, marginBottom: 32 },
74
- h3: { fontSize: 24, lineHeight: 36, marginTop: 40, marginBottom: 16 },
75
- h4: { fontSize: 18, lineHeight: 28, marginTop: 32, marginBottom: 8 },
122
+ paragraph: { fontSize: scaledPx(18, 22), lineHeight: scaledPx(32, 38) },
123
+ h1: {
124
+ fontSize: scaledPx(48, 58),
125
+ lineHeight: scaledPx(48, 58),
126
+ marginTop: 56,
127
+ marginBottom: 40,
128
+ },
129
+ h2: {
130
+ fontSize: scaledPx(30, 36),
131
+ lineHeight: scaledPx(40, 48),
132
+ marginTop: 56,
133
+ marginBottom: 32,
134
+ },
135
+ h3: {
136
+ fontSize: scaledPx(24, 29),
137
+ lineHeight: scaledPx(36, 43),
138
+ marginTop: 40,
139
+ marginBottom: 16,
140
+ },
141
+ h4: {
142
+ fontSize: scaledPx(18, 22),
143
+ lineHeight: scaledPx(28, 34),
144
+ marginTop: 32,
145
+ marginBottom: 8,
146
+ },
76
147
  listPadding: 28,
77
148
  listItemGap: 12,
78
149
  listNestedGap: 16,
@@ -95,8 +166,8 @@ const quoteColor = colors.gray[11]
95
166
  const px = (value: number) => `${value}px`
96
167
 
97
168
  const block = (metric: BlockMetric) => ({
98
- fontSize: px(metric.fontSize),
99
- lineHeight: px(metric.lineHeight),
169
+ fontSize: metric.fontSize,
170
+ lineHeight: metric.lineHeight,
100
171
  fontFamily,
101
172
  })
102
173