jfs-components 0.1.51 → 0.1.55

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 (95) hide show
  1. package/.cursor/D2C-SCREEN.md +2 -1
  2. package/.cursor/commands/D2C.md +2 -1
  3. package/CHANGELOG.md +17 -0
  4. package/lib/commonjs/components/ActionFooter/ActionFooter.js +319 -135
  5. package/lib/commonjs/components/Badge/Badge.js +20 -1
  6. package/lib/commonjs/components/Button/Button.js +139 -47
  7. package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +1 -1
  8. package/lib/commonjs/components/Card/Card.js +151 -112
  9. package/lib/commonjs/components/Card/assets/gold-logo-mark.png +0 -0
  10. package/lib/commonjs/components/CategoryCard/CategoryCard.js +97 -63
  11. package/lib/commonjs/components/CategoryCard/assets/sample.png +0 -0
  12. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +59 -10
  13. package/lib/commonjs/components/CircularProgressBarDoted/CircularProgressBarDoted.js +1 -1
  14. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +132 -49
  15. package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +56 -14
  16. package/lib/commonjs/components/IconCapsule/IconCapsule.js +1 -1
  17. package/lib/commonjs/components/MetricData/MetricData.js +26 -13
  18. package/lib/commonjs/components/MoneyValue/MoneyValue.js +1 -1
  19. package/lib/commonjs/components/Nudge/Nudge.js +1 -1
  20. package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +47 -91
  21. package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +52 -45
  22. package/lib/commonjs/components/PortfolioHero/PortfolioHero.js +1 -1
  23. package/lib/commonjs/components/Slider/Slider.js +3 -3
  24. package/lib/commonjs/components/TextInput/TextInput.js +26 -8
  25. package/lib/commonjs/components/Tooltip/Tooltip.js +3 -5
  26. package/lib/commonjs/components/index.js +7 -1
  27. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  28. package/lib/commonjs/design-tokens/figma-modes.generated.js +13 -13
  29. package/lib/commonjs/icons/registry.js +1 -1
  30. package/lib/module/components/ActionFooter/ActionFooter.js +322 -138
  31. package/lib/module/components/Badge/Badge.js +20 -1
  32. package/lib/module/components/Button/Button.js +140 -48
  33. package/lib/module/components/ButtonGroup/ButtonGroup.js +1 -1
  34. package/lib/module/components/Card/Card.js +152 -114
  35. package/lib/module/components/Card/assets/gold-logo-mark.png +0 -0
  36. package/lib/module/components/CategoryCard/CategoryCard.js +97 -63
  37. package/lib/module/components/CategoryCard/assets/sample.png +0 -0
  38. package/lib/module/components/CheckboxItem/CheckboxItem.js +59 -10
  39. package/lib/module/components/CircularProgressBarDoted/CircularProgressBarDoted.js +1 -1
  40. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +135 -52
  41. package/lib/module/components/HelloJioInput/HelloJioInput.js +56 -14
  42. package/lib/module/components/IconCapsule/IconCapsule.js +1 -1
  43. package/lib/module/components/MetricData/MetricData.js +26 -14
  44. package/lib/module/components/MoneyValue/MoneyValue.js +1 -1
  45. package/lib/module/components/Nudge/Nudge.js +1 -1
  46. package/lib/module/components/PdpCcCard/PdpCcCard.js +48 -92
  47. package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +52 -45
  48. package/lib/module/components/PortfolioHero/PortfolioHero.js +1 -1
  49. package/lib/module/components/Slider/Slider.js +3 -3
  50. package/lib/module/components/TextInput/TextInput.js +27 -9
  51. package/lib/module/components/Tooltip/Tooltip.js +3 -5
  52. package/lib/module/components/index.js +1 -1
  53. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  54. package/lib/module/design-tokens/figma-modes.generated.js +13 -13
  55. package/lib/module/icons/registry.js +1 -1
  56. package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +50 -21
  57. package/lib/typescript/src/components/Button/Button.d.ts +24 -1
  58. package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +2 -2
  59. package/lib/typescript/src/components/Card/Card.d.ts +54 -25
  60. package/lib/typescript/src/components/CategoryCard/CategoryCard.d.ts +29 -12
  61. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +27 -9
  62. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +37 -12
  63. package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +1 -1
  64. package/lib/typescript/src/components/MetricData/MetricData.d.ts +7 -5
  65. package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +16 -6
  66. package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +9 -2
  67. package/lib/typescript/src/components/index.d.ts +2 -2
  68. package/lib/typescript/src/icons/registry.d.ts +1 -1
  69. package/package.json +1 -1
  70. package/src/components/ActionFooter/ActionFooter.tsx +375 -141
  71. package/src/components/Badge/Badge.tsx +21 -1
  72. package/src/components/Button/Button.tsx +192 -44
  73. package/src/components/ButtonGroup/ButtonGroup.tsx +2 -2
  74. package/src/components/Card/Card.tsx +370 -212
  75. package/src/components/Card/assets/gold-logo-mark.png +0 -0
  76. package/src/components/CategoryCard/CategoryCard.tsx +130 -84
  77. package/src/components/CategoryCard/assets/sample.png +0 -0
  78. package/src/components/CheckboxItem/CheckboxItem.tsx +72 -12
  79. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +1 -1
  80. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +186 -67
  81. package/src/components/HelloJioInput/HelloJioInput.tsx +58 -17
  82. package/src/components/IconCapsule/IconCapsule.tsx +1 -1
  83. package/src/components/MetricData/MetricData.tsx +39 -22
  84. package/src/components/MoneyValue/MoneyValue.tsx +1 -1
  85. package/src/components/Nudge/Nudge.tsx +1 -1
  86. package/src/components/PdpCcCard/PdpCcCard.tsx +41 -92
  87. package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +73 -58
  88. package/src/components/PortfolioHero/PortfolioHero.tsx +1 -1
  89. package/src/components/Slider/Slider.tsx +3 -3
  90. package/src/components/TextInput/TextInput.tsx +26 -9
  91. package/src/components/Tooltip/Tooltip.tsx +3 -5
  92. package/src/components/index.ts +9 -2
  93. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  94. package/src/design-tokens/figma-modes.generated.ts +13 -13
  95. package/src/icons/registry.ts +1 -1
@@ -15,6 +15,26 @@ import GlassFill from '../../utils/GlassFill/GlassFill'
15
15
 
16
16
  export type BadgeType = 'default' | 'glass'
17
17
 
18
+ /**
19
+ * Figma still binds `badge/color/label`, but that alias is broken for
20
+ * `Semantic Intent=System` + `Emphasis=High` (missing VariableID:2811:2401).
21
+ * Use the published tokens that the chain is supposed to land on:
22
+ * - Brand → `Emphasis/badge/brand/fg`
23
+ * - System + High → `Emphasis/badge/high/fg Copy` (AppearanceSystem)
24
+ * - System + Medium/Low → `Emphasis/badge/system/fg`
25
+ */
26
+ function badgeLabelColorToken(modes: Modes): string {
27
+ const intent = modes['Semantic Intent'] ?? 'Brand'
28
+ const emphasis = modes.Emphasis ?? 'High'
29
+ if (intent === 'System' && emphasis === 'High') {
30
+ return 'Emphasis/badge/high/fg Copy'
31
+ }
32
+ if (intent === 'System') {
33
+ return 'Emphasis/badge/system/fg'
34
+ }
35
+ return 'Emphasis/badge/brand/fg'
36
+ }
37
+
18
38
  export type BadgeProps = {
19
39
  /** Visible label text shown inside the badge */
20
40
  label?: string
@@ -91,7 +111,7 @@ function Badge({
91
111
  (getVariableByName('badge/glass/color/label', modes) as string)
92
112
  const labelColor = isGlass
93
113
  ? glassLabelColor
94
- : (getVariableByName('badge/color/label', modes) as string)
114
+ : (getVariableByName(badgeLabelColorToken(modes), modes) as string)
95
115
  const fontSize =
96
116
  Number(getVariableByName('badge/label/fontSize', modes) as unknown)
97
117
  const fontFamily =
@@ -13,11 +13,20 @@ import {
13
13
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
14
  import { usePressableWebSupport, type SafePressableProps, type WebAccessibilityProps } from '../../utils/web-platform-utils'
15
15
  import { EMPTY_MODES } from '../../utils/react-utils'
16
+ import GlassFill from '../../utils/GlassFill/GlassFill'
16
17
  import Icon from '../../icons/Icon'
17
18
  import Skeleton from '../../skeleton/Skeleton'
18
19
  import { useSkeleton } from '../../skeleton/SkeletonGroup'
19
20
  import type { Modes } from '../../design-tokens'
20
21
 
22
+ /**
23
+ * Figma `Type` property on Button.
24
+ * - `'default'` — solid token-colored pill (hugs content)
25
+ * - `'glass'` — frosted translucent pill backed by {@link GlassFill}
26
+ * - `'fixed'` — solid pill constrained by `button/maxWidth`
27
+ */
28
+ export type ButtonType = 'default' | 'glass' | 'fixed'
29
+
21
30
  export type ButtonProps = SafePressableProps & {
22
31
  label?: string;
23
32
  children?: React.ReactNode;
@@ -45,6 +54,22 @@ export type ButtonProps = SafePressableProps & {
45
54
  * Takes precedence over `trailing` if both are provided.
46
55
  */
47
56
  icon?: string;
57
+ /**
58
+ * Visual/layout type matching the Figma `Type` property. Defaults to
59
+ * `'default'`. `'glass'` also activates when `modes['Button type'] === 'glass'`.
60
+ */
61
+ type?: ButtonType;
62
+ /**
63
+ * Glass-only override for the translucent overlay color painted over the live
64
+ * blur. Defaults to the resolved `button/background` token under
65
+ * `Button type=glass`. Ignored for non-glass types.
66
+ */
67
+ glassOverlayColor?: string;
68
+ /**
69
+ * Glass-only override for blur intensity on the 0–100 scale. Defaults to the
70
+ * `blur/minimal` token. Ignored for non-glass types.
71
+ */
72
+ glassIntensity?: number;
48
73
  modes?: Modes;
49
74
  onPress?: () => void;
50
75
  disabled?: boolean;
@@ -115,6 +140,8 @@ const NO_WRAP_LABEL_STYLE: TextStyle = {
115
140
  // ---------------------------------------------------------------------------
116
141
 
117
142
  interface ButtonTokens {
143
+ isGlass: boolean;
144
+ isFixed: boolean;
118
145
  container: ViewStyle;
119
146
  baseLabel: TextStyle;
120
147
  hoverContainer: ViewStyle | null;
@@ -126,28 +153,101 @@ interface ButtonTokens {
126
153
  pressedIconColor: string;
127
154
  iconSize: number;
128
155
  accessoryOffset: number;
156
+ /** Idle glass overlay (token `button/background` under Button type=glass). */
157
+ glassOverlayIdle: string;
158
+ glassOverlayHover: string | null;
159
+ glassOverlayPressed: string;
160
+ /** `blur/minimal` mapped to GlassFill's 0–100 intensity scale. */
161
+ glassBlurIntensity: number;
162
+ }
163
+
164
+ type ButtonInteractiveState = 'Idle' | 'Hover' | 'Pressed' | 'Disabled'
165
+
166
+ const BUTTON_STATE_VALUES = new Set<string>(['Idle', 'Hover', 'Pressed', 'Disabled'])
167
+ const SOLID_STATE_COLLECTION = 'Button / State'
168
+ const GLASS_STATE_COLLECTION = 'Button Glass State'
169
+
170
+ function resolveIsGlass(type: ButtonType, modes: Modes): boolean {
171
+ return type === 'glass' || modes['Button type'] === 'glass'
172
+ }
173
+
174
+ /**
175
+ * Pick Idle/Hover/Pressed/Disabled from the active state collection, falling
176
+ * back to the sibling collection when callers pass the other key (e.g. glass
177
+ * buttons that still send `Button / State`). Never treats a collection name
178
+ * as a mode value.
179
+ */
180
+ function pickButtonInteractiveState(
181
+ modes: Modes,
182
+ isGlass: boolean,
183
+ ): ButtonInteractiveState {
184
+ const primary = isGlass ? GLASS_STATE_COLLECTION : SOLID_STATE_COLLECTION
185
+ const sibling = isGlass ? SOLID_STATE_COLLECTION : GLASS_STATE_COLLECTION
186
+ const candidate = modes[primary] ?? modes[sibling]
187
+ if (typeof candidate === 'string' && BUTTON_STATE_VALUES.has(candidate)) {
188
+ return candidate as ButtonInteractiveState
189
+ }
190
+ return 'Idle'
129
191
  }
130
192
 
131
- function resolveButtonTokens(modes: Modes, disabled: boolean): ButtonTokens {
132
- const backgroundColor = getVariableByName('button/background', modes)
133
- const borderColor = getVariableByName('button/border/color', modes)
134
- const borderWidth = getVariableByName('button/border/size', modes)
135
- const radius = getVariableByName('button/radius', modes)
136
- const paddingHorizontal = getVariableByName('button/padding/horizontal', modes)
137
- const paddingVertical = getVariableByName('button/padding/vertical', modes)
138
- const gap = getVariableByName('button/gap', modes)
139
-
140
- const fontFamily = getVariableByName('button/fontFamily', modes)
141
- const fontWeightValue = getVariableByName('button/fontWeight', modes)
193
+ /** Write a valid interactive state onto the correct collection for glass/solid. */
194
+ function withButtonInteractiveState(
195
+ modes: Modes,
196
+ isGlass: boolean,
197
+ state: ButtonInteractiveState,
198
+ ): Modes {
199
+ const collection = isGlass ? GLASS_STATE_COLLECTION : SOLID_STATE_COLLECTION
200
+ const sibling = isGlass ? SOLID_STATE_COLLECTION : GLASS_STATE_COLLECTION
201
+ const { [sibling]: _dropSibling, ...rest } = modes
202
+ return { ...rest, [collection]: state }
203
+ }
204
+
205
+ function resolveButtonTokens(
206
+ modes: Modes,
207
+ disabled: boolean,
208
+ type: ButtonType,
209
+ ): ButtonTokens {
210
+ const isGlass = resolveIsGlass(type, modes)
211
+ const isFixed = type === 'fixed'
212
+
213
+ // Inject the Button type mode so token aliases (background/foreground) resolve
214
+ // to the glass palette. Callers can also drive glass solely via modes.
215
+ const effectiveModes: Modes = isGlass
216
+ ? { ...modes, 'Button type': 'glass' }
217
+ : modes
218
+
219
+ // Glass interactive states live on `Button Glass State`; solid on `Button / State`.
220
+ // Map Idle/Hover/Pressed/Disabled values through — never assign a collection name.
221
+ const idleState: ButtonInteractiveState =
222
+ disabled && isGlass ? 'Disabled' : pickButtonInteractiveState(effectiveModes, isGlass)
223
+ const idleModes = withButtonInteractiveState(effectiveModes, isGlass, idleState)
224
+
225
+ const backgroundColor = getVariableByName('button/background', idleModes)
226
+ const borderColor = getVariableByName('button/border/color', idleModes)
227
+ const borderWidth = getVariableByName('button/border/size', idleModes)
228
+ const radius = getVariableByName('button/radius', idleModes)
229
+ const paddingHorizontal = getVariableByName('button/padding/horizontal', idleModes)
230
+ const paddingVertical = getVariableByName('button/padding/vertical', idleModes)
231
+ const gap = getVariableByName('button/gap', idleModes)
232
+ const maxWidth = getVariableByName('button/maxWidth', idleModes)
233
+
234
+ const fontFamily = getVariableByName('button/fontFamily', idleModes)
235
+ const fontWeightValue = getVariableByName('button/fontWeight', idleModes)
142
236
  const fontWeight = typeof fontWeightValue === 'number' ? fontWeightValue.toString() : fontWeightValue
143
- const lineHeight = getVariableByName('button/lineHeight', modes)
144
- const fontSize = getVariableByName('button/fontSize', modes)
145
- const textColor = getVariableByName('button/foreground', modes)
146
- const iconSize = (getVariableByName('button/icon/size', modes) ?? 18) as number
147
-
148
- // Pressed tokens are always resolved so the Pressable `style` callback can
149
- // apply the pressed visual without scheduling a React render.
150
- const pressedModes = { ...modes, 'Button / State': 'Pressed' }
237
+ const lineHeight = getVariableByName('button/lineHeight', idleModes)
238
+ const fontSize = getVariableByName('button/fontSize', idleModes)
239
+ const textColor = getVariableByName('button/foreground', idleModes)
240
+ const iconSize = (getVariableByName('button/icon/size', idleModes) ?? 18) as number
241
+
242
+ // Figma `blur/minimal` (px radius) -> GlassFill's 0–100 intensity scale.
243
+ const glassBlurIntensity = Math.max(
244
+ 0,
245
+ Math.min(100, Math.round(Number(getVariableByName('blur/minimal', idleModes) ?? 29))),
246
+ )
247
+
248
+ // Pressed tokens are always resolved so the Pressable `style` callback /
249
+ // glass overlay can apply the pressed visual without a modes recompute.
250
+ const pressedModes = withButtonInteractiveState(effectiveModes, isGlass, 'Pressed')
151
251
  const pressedBg = getVariableByName('button/background', pressedModes)
152
252
  const pressedBorderColor = getVariableByName('button/border/color', pressedModes)
153
253
  const pressedTextColor = (getVariableByName('button/foreground', pressedModes)) as string
@@ -156,15 +256,22 @@ function resolveButtonTokens(modes: Modes, disabled: boolean): ButtonTokens {
156
256
  // ~3 token lookups + an object spread per render on every Button.
157
257
  let hoverContainer: ViewStyle | null = null
158
258
  let hoverTextColor: string | null = null
259
+ let glassOverlayHover: string | null = null
159
260
  if (IS_WEB) {
160
- const hoverModes = { ...modes, 'Button / State': 'Hover' }
261
+ const hoverModes = withButtonInteractiveState(effectiveModes, isGlass, 'Hover')
161
262
  const hoverBg = getVariableByName('button/background', hoverModes)
162
263
  const hoverBorderColor = getVariableByName('button/border/color', hoverModes)
163
264
  hoverTextColor = (getVariableByName('button/foreground', hoverModes)) as string
164
- hoverContainer = { backgroundColor: hoverBg as string, borderColor: hoverBorderColor as string }
265
+ glassOverlayHover = hoverBg as string
266
+ // Glass keeps the host transparent; hover only retints the GlassFill overlay.
267
+ hoverContainer = isGlass
268
+ ? null
269
+ : { backgroundColor: hoverBg as string, borderColor: hoverBorderColor as string }
165
270
  }
166
271
 
167
272
  return {
273
+ isGlass,
274
+ isFixed,
168
275
  container: {
169
276
  ...containerLayoutStyle,
170
277
  paddingHorizontal: paddingHorizontal as number,
@@ -172,9 +279,14 @@ function resolveButtonTokens(modes: Modes, disabled: boolean): ButtonTokens {
172
279
  borderRadius: radius as number,
173
280
  borderWidth: (borderWidth ?? 1) as number,
174
281
  borderColor: borderColor as string,
175
- backgroundColor: backgroundColor as string,
282
+ // Glass: transparent host so GlassFill shows through. Fixed: clamp width.
283
+ backgroundColor: isGlass ? 'transparent' : (backgroundColor as string),
176
284
  gap: gap as number,
177
- opacity: disabled ? 0.5 : 1,
285
+ // Glass disabled uses Button Glass State=Disabled foreground tokens —
286
+ // don't also apply the solid-button opacity fade.
287
+ opacity: disabled && !isGlass ? 0.5 : 1,
288
+ ...(isGlass ? { overflow: 'hidden' as const } : null),
289
+ ...(isFixed && maxWidth != null ? { maxWidth: maxWidth as number } : null),
178
290
  },
179
291
  baseLabel: {
180
292
  color: textColor as string,
@@ -184,10 +296,12 @@ function resolveButtonTokens(modes: Modes, disabled: boolean): ButtonTokens {
184
296
  lineHeight: lineHeight as number,
185
297
  },
186
298
  hoverContainer,
187
- pressedContainer: {
188
- backgroundColor: pressedBg as string,
189
- borderColor: pressedBorderColor as string,
190
- },
299
+ pressedContainer: isGlass
300
+ ? {}
301
+ : {
302
+ backgroundColor: pressedBg as string,
303
+ borderColor: pressedBorderColor as string,
304
+ },
191
305
  hoverTextColor,
192
306
  pressedTextColor,
193
307
  baseIconColor: textColor as string,
@@ -195,6 +309,10 @@ function resolveButtonTokens(modes: Modes, disabled: boolean): ButtonTokens {
195
309
  pressedIconColor: pressedTextColor,
196
310
  iconSize,
197
311
  accessoryOffset: (gap as number) / 2,
312
+ glassOverlayIdle: backgroundColor as string,
313
+ glassOverlayHover,
314
+ glassOverlayPressed: pressedBg as string,
315
+ glassBlurIntensity,
198
316
  }
199
317
  }
200
318
 
@@ -240,6 +358,9 @@ function ButtonImpl({
240
358
  leading,
241
359
  trailing,
242
360
  icon,
361
+ type = 'default',
362
+ glassOverlayColor,
363
+ glassIntensity,
243
364
  modes = EMPTY_MODES,
244
365
  onPress,
245
366
  disabled = false,
@@ -271,8 +392,8 @@ function ButtonImpl({
271
392
  userHandlersRef.current.onHoverOut = (rest as any)?.onHoverOut
272
393
 
273
394
  const tokens = useMemo(
274
- () => resolveButtonTokens(modes, disabled),
275
- [modes, disabled]
395
+ () => resolveButtonTokens(modes, disabled, type),
396
+ [modes, disabled, type]
276
397
  )
277
398
 
278
399
  // Skeleton context — read unconditionally so React's hook order stays
@@ -412,6 +533,26 @@ function ButtonImpl({
412
533
  )
413
534
  }
414
535
 
536
+ const body = (
537
+ <>
538
+ {leading ? (
539
+ <View style={leadingAccessoryStyle}>
540
+ {leading}
541
+ </View>
542
+ ) : null}
543
+ {content}
544
+ {icon ? (
545
+ <View style={trailingAccessoryStyle}>
546
+ <Icon name={icon} size={tokens.iconSize} color={activeIconColor} accessibilityElementsHidden={true} importantForAccessibility="no" />
547
+ </View>
548
+ ) : trailing ? (
549
+ <View style={trailingAccessoryStyle}>
550
+ {trailing}
551
+ </View>
552
+ ) : null}
553
+ </>
554
+ )
555
+
415
556
  return (
416
557
  <Pressable
417
558
  accessibilityRole="button"
@@ -431,21 +572,28 @@ function ButtonImpl({
431
572
  style={styleCallback}
432
573
  {...webProps}
433
574
  >
434
- {leading ? (
435
- <View style={leadingAccessoryStyle}>
436
- {leading}
437
- </View>
438
- ) : null}
439
- {content}
440
- {icon ? (
441
- <View style={trailingAccessoryStyle}>
442
- <Icon name={icon} size={tokens.iconSize} color={activeIconColor} accessibilityElementsHidden={true} importantForAccessibility="no" />
443
- </View>
444
- ) : trailing ? (
445
- <View style={trailingAccessoryStyle}>
446
- {trailing}
447
- </View>
448
- ) : null}
575
+ {tokens.isGlass
576
+ ? ({ pressed }: PressableStateCallbackType) => {
577
+ const overlayColor =
578
+ glassOverlayColor ??
579
+ (pressed && !disabled
580
+ ? tokens.glassOverlayPressed
581
+ : isHovered && !disabled && tokens.glassOverlayHover
582
+ ? tokens.glassOverlayHover
583
+ : tokens.glassOverlayIdle)
584
+ return (
585
+ <>
586
+ <GlassFill
587
+ tint="light"
588
+ intensity={glassIntensity ?? tokens.glassBlurIntensity}
589
+ overlayColor={overlayColor}
590
+ androidTintWash={false}
591
+ />
592
+ {body}
593
+ </>
594
+ )
595
+ }
596
+ : body}
449
597
  </Pressable>
450
598
  )
451
599
  }
@@ -16,7 +16,7 @@ export type ButtonGroupProps = {
16
16
  */
17
17
  children?: React.ReactNode;
18
18
  /**
19
- * Mode configuration for design tokens (e.g., {"Button / Size": "M", "Appearance": "high"})
19
+ * Mode configuration for design tokens (e.g., {"Button / Size": "M", "Emphasis": "High"})
20
20
  * These modes are passed down to all child components.
21
21
  */
22
22
  modes?: Modes;
@@ -37,7 +37,7 @@ export type ButtonGroupProps = {
37
37
  * @component
38
38
  * @example
39
39
  * ```jsx
40
- * <ButtonGroup modes={{"Appearance": "light"}}>
40
+ * <ButtonGroup modes={{"Color Mode": "Light"}}>
41
41
  * <IconButton iconName="ic_qr_code" />
42
42
  * <Button label="Pay" />
43
43
  * </ButtonGroup>