jfs-components 0.1.49 → 0.1.51

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 (61) hide show
  1. package/.cursor/D2C-FLOW.md +94 -0
  2. package/.cursor/D2C-SCREEN.md +119 -0
  3. package/.cursor/commands/D2C.md +101 -0
  4. package/CHANGELOG.md +14 -0
  5. package/lib/commonjs/components/CardCTA/CardCTA.js +7 -4
  6. package/lib/commonjs/components/CardFeedback/CardFeedback.js +1 -1
  7. package/lib/commonjs/components/CategoryCard/CategoryCard.js +4 -4
  8. package/lib/commonjs/components/Checkbox/Checkbox.js +4 -6
  9. package/lib/commonjs/components/CircularProgressBarDoted/CircularProgressBarDoted.js +12 -9
  10. package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +7 -2
  11. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +3 -1
  12. package/lib/commonjs/components/ProductOverview/ProductOverview.js +2 -2
  13. package/lib/commonjs/components/Radio/Radio.js +5 -3
  14. package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +2 -2
  15. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +1 -1
  16. package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +1 -1
  17. package/lib/commonjs/components/Slider/Slider.js +3 -2
  18. package/lib/commonjs/components/StatusHero/StatusHero.js +1 -1
  19. package/lib/commonjs/components/Tooltip/Tooltip.js +4 -2
  20. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  21. package/lib/commonjs/design-tokens/figma-modes.generated.js +31 -28
  22. package/lib/commonjs/icons/registry.js +1 -1
  23. package/lib/module/components/CardCTA/CardCTA.js +7 -4
  24. package/lib/module/components/CardFeedback/CardFeedback.js +1 -1
  25. package/lib/module/components/CategoryCard/CategoryCard.js +4 -4
  26. package/lib/module/components/Checkbox/Checkbox.js +4 -6
  27. package/lib/module/components/CircularProgressBarDoted/CircularProgressBarDoted.js +12 -9
  28. package/lib/module/components/DonutChartSummary/DonutChartSummary.js +7 -2
  29. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +3 -1
  30. package/lib/module/components/ProductOverview/ProductOverview.js +2 -2
  31. package/lib/module/components/Radio/Radio.js +5 -3
  32. package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +2 -2
  33. package/lib/module/components/SegmentedControl/SegmentedControl.js +1 -1
  34. package/lib/module/components/SegmentedTrack/SegmentedTrack.js +1 -1
  35. package/lib/module/components/Slider/Slider.js +3 -2
  36. package/lib/module/components/StatusHero/StatusHero.js +1 -1
  37. package/lib/module/components/Tooltip/Tooltip.js +4 -2
  38. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  39. package/lib/module/design-tokens/figma-modes.generated.js +31 -28
  40. package/lib/module/icons/registry.js +1 -1
  41. package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +4 -1
  42. package/lib/typescript/src/icons/registry.d.ts +1 -1
  43. package/package.json +4 -2
  44. package/src/components/CardCTA/CardCTA.tsx +7 -4
  45. package/src/components/CardFeedback/CardFeedback.tsx +1 -1
  46. package/src/components/CategoryCard/CategoryCard.tsx +4 -4
  47. package/src/components/Checkbox/Checkbox.tsx +4 -6
  48. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +12 -9
  49. package/src/components/DonutChartSummary/DonutChartSummary.tsx +6 -6
  50. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +3 -1
  51. package/src/components/ProductOverview/ProductOverview.tsx +2 -2
  52. package/src/components/Radio/Radio.tsx +8 -3
  53. package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +3 -3
  54. package/src/components/SegmentedControl/SegmentedControl.tsx +1 -1
  55. package/src/components/SegmentedTrack/SegmentedTrack.tsx +1 -2
  56. package/src/components/Slider/Slider.tsx +3 -2
  57. package/src/components/StatusHero/StatusHero.tsx +1 -1
  58. package/src/components/Tooltip/Tooltip.tsx +4 -2
  59. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  60. package/src/design-tokens/figma-modes.generated.ts +31 -28
  61. package/src/icons/registry.ts +1 -1
@@ -9,6 +9,7 @@ export declare const FIGMA_MODES: {
9
9
  readonly "AccordionGroup / Output": readonly ["Default"];
10
10
  readonly "AccountCard / Output": readonly ["Default"];
11
11
  readonly Action: readonly ["True", "False"];
12
+ readonly "Action Footer Radius": readonly ["False", "True"];
12
13
  readonly "ActionFooter / Output": readonly ["Default"];
13
14
  readonly "ActionNumpad / Output": readonly ["Default"];
14
15
  readonly "ActionTile / Output": readonly ["Default"];
@@ -42,6 +43,8 @@ export declare const FIGMA_MODES: {
42
43
  readonly "Button / Output": readonly ["Default"];
43
44
  readonly "Button / Size": readonly ["M", "S", "XS"];
44
45
  readonly "Button / State": readonly ["Idle", "Hover", "Pressed", "Disabled"];
46
+ readonly "Button Glass State": readonly ["Idle", "Hover", "Pressed", "Disabled"];
47
+ readonly "Button type": readonly ["default", "glass"];
45
48
  readonly "ButtonGroup / Output": readonly ["Default"];
46
49
  readonly "Calendar Glyph / Output": readonly ["Default"];
47
50
  readonly "Calendar Glyph State": readonly ["Idle", "notSaved", "saved"];
@@ -90,7 +93,7 @@ export declare const FIGMA_MODES: {
90
93
  readonly Context2: readonly ["Default", "AppBar"];
91
94
  readonly Context3: readonly ["Default", "Transaction Bubble", "Balance & Cards", "Amount Input"];
92
95
  readonly Context4: readonly ["Default", "Chip", "Button", "Badge", "Badge/glass"];
93
- readonly context5: readonly ["Default", "Fullscreen Modal"];
96
+ readonly context5: readonly ["Default", "Fullscreen Modal", "Mode 1"];
94
97
  readonly context7: readonly ["Default", "Card", "Page Hero"];
95
98
  readonly "Contrast Context": readonly ["on dark", "on light"];
96
99
  readonly "Control Toggle ": readonly ["Default"];
@@ -4,7 +4,7 @@
4
4
  * Auto-generated from SVG files in src/icons/
5
5
  * DO NOT EDIT MANUALLY - Run "npm run icons:generate" to regenerate
6
6
  *
7
- * Generated: 2026-07-25T08:19:21.865Z
7
+ * Generated: 2026-07-26T08:49:43.170Z
8
8
  */
9
9
  export declare const iconRegistry: Record<string, {
10
10
  path: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jfs-components",
3
- "version": "0.1.49",
3
+ "version": "0.1.51",
4
4
  "description": "React Native Jio Finance Components Library",
5
5
  "author": "sunshuaiqi@gmail.com",
6
6
  "license": "MIT",
@@ -17,7 +17,9 @@
17
17
  "src",
18
18
  "lib",
19
19
  "scripts/extract-figma-modes.js",
20
- "D2C.md",
20
+ ".cursor/commands/D2C.md",
21
+ ".cursor/D2C-FLOW.md",
22
+ ".cursor/D2C-SCREEN.md",
21
23
  "CHANGELOG.md",
22
24
  "!**/__tests__",
23
25
  "!**/*.stories.*",
@@ -126,7 +126,8 @@ function CardCTA({
126
126
  const borderSize = getVariableByName('cardCTA/border/size', modes)
127
127
  const borderColor = getVariableByName('cardCTA/border/color', modes)
128
128
 
129
- const leftPaddingH = getVariableByName('cardCTA/left-wrap/padding/horizontal', modes)
129
+ const leftPaddingLeft = getVariableByName('cardCTA/left-wrap/padding/left', modes)
130
+ const leftPaddingRight = getVariableByName('cardCTA/left-wrap/padding/right', modes)
130
131
  const leftPaddingV = getVariableByName('cardCTA/left-wrap/padding/vertical', modes)
131
132
  const leftGap = getVariableByName('cardCTA/left-wrap/gap', modes)
132
133
 
@@ -272,7 +273,8 @@ function CardCTA({
272
273
  flexShrink: 1,
273
274
  flexBasis: 0,
274
275
  minWidth: 0,
275
- paddingHorizontal: leftPaddingH,
276
+ paddingLeft: leftPaddingLeft,
277
+ paddingRight: leftPaddingRight,
276
278
  paddingVertical: leftPaddingV,
277
279
  gap: leftGap,
278
280
  alignItems: 'flex-start',
@@ -302,7 +304,7 @@ function CardCTA({
302
304
  // an explicit computed floor — the resolved IconCapsule size plus the
303
305
  // wrapper's own horizontal padding. The column is exactly 2fr whenever
304
306
  // space allows and can never collapse below its content.
305
- const iconCapsuleModes = { ...modes, 'IconCapsule / Size': 'M', Emphasis: 'Medium', AppearanceBrand: 'Secondary' }
307
+ const iconCapsuleModes = { ...modes, 'Icon Capsule Size': 'M', Emphasis: 'Medium', AppearanceBrand: 'Secondary' }
306
308
  const rightWrapMinWidth =
307
309
  ((getVariableByName('iconCapsule/size', iconCapsuleModes) as number) || 0) +
308
310
  ((rightPaddingH as number) || 0) * 2
@@ -364,7 +366,8 @@ function CardCTA({
364
366
 
365
367
  const sipWrapStyle: ViewStyle = {
366
368
  width: '100%',
367
- paddingHorizontal: leftPaddingH,
369
+ paddingLeft: leftPaddingLeft,
370
+ paddingRight: leftPaddingRight,
368
371
  paddingVertical: leftPaddingV,
369
372
  gap: leftGap,
370
373
  alignItems: 'flex-start',
@@ -47,7 +47,7 @@ export function CardFeedback({
47
47
  accessibilityLabel,
48
48
  }: CardFeedbackProps) {
49
49
  const modes = {
50
- 'Appearance.System': 'positive',
50
+ 'AppearanceSystem': 'positive',
51
51
  'Context': 'Nudge&Alert',
52
52
  'Semantic Intent': 'System',
53
53
  ...propModes,
@@ -162,18 +162,18 @@ function resolveCategoryCardTokens(
162
162
  )
163
163
 
164
164
  const fontFamily =
165
- (getVariableByName('cardTab/label/fontFamily', resolvedModes) as string | null) ??
165
+ (getVariableByName('label/fontFamily', resolvedModes) as string | null) ??
166
166
  'JioType Var'
167
167
  const fontSize = toNumber(
168
- getVariableByName('cardTab/label/fontSize', resolvedModes),
168
+ getVariableByName('label/fontSize', resolvedModes),
169
169
  12
170
170
  )
171
171
  const lineHeight = toNumber(
172
- getVariableByName('cardTab/label/lineHeight', resolvedModes),
172
+ getVariableByName('label/lineHeight', resolvedModes),
173
173
  Math.round(fontSize * 1.3)
174
174
  )
175
175
  const fontWeight = toFontWeight(
176
- getVariableByName('cardTab/label/fontWeight', resolvedModes),
176
+ getVariableByName('label/fontWeight', resolvedModes),
177
177
  '500'
178
178
  )
179
179
  const labelColor =
@@ -122,8 +122,8 @@ const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox({
122
122
  const idleStroke = getVariableByName('checkbox/idle/stroke/color', modes) ?? '#666666'
123
123
  const hoverFill = getVariableByName('checkbox/hover/fill/color', modes) ?? 'rgba(0,0,0,0.1)'
124
124
  const hoverStroke = getVariableByName('checkbox/hover/stroke/color', modes) ?? '#666666'
125
- const hoverRing = getVariableByName('checkbox/hoverRing', modes) ?? 4
126
- const hoverShadow = getVariableByName('hover/boxShadow', modes) ?? 'rgba(0,0,0,0.1)'
125
+ const hoverSpread = getVariableByName('checkbox/hover/spread/effect1', modes) ?? 4
126
+ const hoverShadow = getVariableByName('checkbox/hover/shadow/color', modes) ?? 'rgba(0,0,0,0.1)'
127
127
  const selectedFill = getVariableByName('checkbox/selected/fill/color', modes) ?? '#cea15a'
128
128
  const selectedStroke = getVariableByName('checkbox/selected/stroke/color', modes) ?? '#0d0d0d'
129
129
  const selectedMarkColor = getVariableByName('checkbox/selected/mark/color', modes) ?? '#0f0d0a'
@@ -135,8 +135,6 @@ const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox({
135
135
  const disabledActiveBg = getVariableByName('checkbox/disabledActive/background/color', modes) ?? '#f6d19a'
136
136
  const disabledActiveBorder = getVariableByName('checkbox/disabledActive/border/color', modes) ?? '#f6d19a'
137
137
  const disabledActiveMark = getVariableByName('checkbox/disabledActive/mark/color', modes) ?? '#474d54'
138
- const selectedHoverShadow = getVariableByName('selected/hover/boxShadow', modes) ?? 'rgba(0,0,0,0.1)'
139
- const hoverShadowSize = getVariableByName('hover/boxShadow/size', modes) ?? 4
140
138
 
141
139
  const handlePress = useCallback(() => {
142
140
  if (disabled) return
@@ -187,7 +185,7 @@ const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox({
187
185
  ...base,
188
186
  backgroundColor: selectedFill as string,
189
187
  borderColor: selectedStroke as string,
190
- ...boxShadow(`0px 0px 0px ${hoverShadowSize}px ${selectedHoverShadow}`),
188
+ ...boxShadow(`0px 0px 0px ${hoverSpread}px ${hoverShadow}`),
191
189
  }
192
190
  }
193
191
 
@@ -213,7 +211,7 @@ const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox({
213
211
  ...base,
214
212
  backgroundColor: hoverFill as string,
215
213
  borderColor: hoverStroke as string,
216
- ...boxShadow(`0px 0px 0px ${hoverRing}px ${hoverShadow}`),
214
+ ...boxShadow(`0px 0px 0px ${hoverSpread}px ${hoverShadow}`),
217
215
  }
218
216
  }
219
217
 
@@ -160,10 +160,11 @@ function CircularProgressBarDoted({
160
160
  const scoreTrendGap = toNumber(getVariableByName('circularProgressBarDoted/scoreTrend/gap', modes), 2)
161
161
  const scoreTrendHeight = toNumber(getVariableByName('circularProgressBarDoted/scoreTrend/height', modes), 24)
162
162
 
163
- const typographyFontFamily = getVariableByName('Typography/Font Family', modes)
164
163
  const labelColor = getVariableByName('circularProgressBarDoted/label/color', modes)
165
- const labelFontSize = toNumber(getVariableByName('Typography/Size/Body/XS', modes), 12)
166
- const labelFontWeight = toFontWeight(getVariableByName('Typography/Font Weight/Body Low (Regular)', modes), '400')
164
+ const labelFontSize = toNumber(getVariableByName('circularProgressBarDoted/label/fontSize', modes), 12)
165
+ const labelFontFamily = getVariableByName('circularProgressBarDoted/label/fontFamily', modes)
166
+ const labelLineHeight = toNumber(getVariableByName('circularProgressBarDoted/label/lineHeight', modes), 15.6)
167
+ const labelFontWeight = toFontWeight(getVariableByName('circularProgressBarDoted/label/fontWeight', modes), '400')
167
168
 
168
169
  const scoreColor = getVariableByName('circularProgressBarDoted/scoreLabel/color', modes)
169
170
  const scoreFontSize = toNumber(getVariableByName('circularProgressBarDoted/scoreLabel/fontSize', modes), 56)
@@ -172,8 +173,10 @@ function CircularProgressBarDoted({
172
173
  const scoreFontWeight = toFontWeight(getVariableByName('circularProgressBarDoted/scoreLabel/fontWeight', modes), '900')
173
174
 
174
175
  const tierColor = getVariableByName('circularProgressBarDoted/tierLabel/color', modes)
175
- const tierFontSize = toNumber(getVariableByName('Typography/Size/Body/M', modes), 16)
176
- const tierFontWeight = toFontWeight(getVariableByName('Typography/Font Weight/Body High', modes), '700')
176
+ const tierFontSize = toNumber(getVariableByName('circularProgressBarDoted/tierLabel/fontSize', modes), 16)
177
+ const tierFontFamily = getVariableByName('circularProgressBarDoted/tierLabel/fontFamily', modes)
178
+ const tierLineHeight = toNumber(getVariableByName('circularProgressBarDoted/tierLabel/lineHeight', modes), 20.8)
179
+ const tierFontWeight = toFontWeight(getVariableByName('circularProgressBarDoted/tierLabel/fontWeight', modes), '700')
177
180
  const iconColor = getVariableByName('circularProgressBarDoted/icon/color', modes)
178
181
  const iconSize = toNumber(getVariableByName('circularProgressBarDoted/icon/size', modes), 24)
179
182
 
@@ -245,10 +248,10 @@ function CircularProgressBarDoted({
245
248
 
246
249
  const computedLabelStyle: TextStyle = {
247
250
  color: labelColor,
248
- fontFamily: typographyFontFamily,
251
+ fontFamily: labelFontFamily,
249
252
  fontSize: labelFontSize,
250
253
  fontWeight: labelFontWeight,
251
- lineHeight: labelFontSize * 1.3,
254
+ lineHeight: labelLineHeight,
252
255
  textAlign: 'center',
253
256
  }
254
257
 
@@ -263,10 +266,10 @@ function CircularProgressBarDoted({
263
266
 
264
267
  const computedTierLabelStyle: TextStyle = {
265
268
  color: tierColor,
266
- fontFamily: typographyFontFamily,
269
+ fontFamily: tierFontFamily,
267
270
  fontSize: tierFontSize,
268
271
  fontWeight: tierFontWeight,
269
- lineHeight: tierFontSize * 1.3,
272
+ lineHeight: tierLineHeight,
270
273
  textAlign: 'center',
271
274
  }
272
275
 
@@ -164,12 +164,12 @@ function DonutChartSummary({
164
164
  const { modes: globalModes } = useTokens()
165
165
  const modes = { ...globalModes, ...propModes }
166
166
 
167
- const gap =
168
- (getVariableByName('donutChartSummary/gap', modes) as number | null) ?? 16
169
- const legendGap =
170
- (getVariableByName('donutChartSummary/legend/gap', modes) as
171
- | number
172
- | null) ?? 8
167
+ // Figma DonutChartSummary (4203:51713) does not expose component-level
168
+ // gap variables layout uses unbound 16px (donut→legend) and 8px
169
+ // (legend rows). Nested `textWrap/gap` / `metricLegendItem/gap` belong
170
+ // to child components and are not substitutes.
171
+ const gap = 16
172
+ const legendGap = 8
173
173
 
174
174
  const resolvedItems = items && items.length > 0 ? items : DEFAULT_ITEMS
175
175
 
@@ -430,7 +430,9 @@ function resolveTokens(modes: Modes): ResolvedTokens {
430
430
  const titleColor = asStr(getVariableByName('productMerchandisingcard/footer/title/font/color', modes), '#ffffff')
431
431
  const titleSize = asNum(getVariableByName('productMerchandisingcard/footer/title/fontsize', modes), 14)
432
432
  const titleFamily = asStr(getVariableByName('productMerchandisingcard/footer/title/fontfamily', modes), 'JioType Var')
433
- const titleWeight = asStr(getVariableByName('productMerchandisingcard/footer/title/fontweight', modes), '700')
433
+ // No `productMerchandisingcard/footer/title/fontweight` in Coin Variables (Figma
434
+ // binds 700). `typography/title/fontWeight/high` is 800; use body/high (=700).
435
+ const titleWeight = asStr(getVariableByName('typography/body/fontWeight/high', modes), '700')
434
436
 
435
437
  const subtitleColor = asStr(getVariableByName('productMerchandisingcard/footer/subtitle/font/color', modes), '#c5bcb5')
436
438
  const subtitleSize = asNum(getVariableByName('productMerchandisingcard/footer/subtitle/fontsize', modes), 12)
@@ -79,7 +79,7 @@ const ProductOverview = ({
79
79
  (getVariableByName('productOverview/background', modes) as string | null) ?? '#ffffff'
80
80
 
81
81
  const productNameColor =
82
- (getVariableByName('productOverview/productName/color', modes) as string | null) ??
82
+ (getVariableByName('text/appearance/high/color', modes) as string | null) ??
83
83
  '#0d0d0f'
84
84
  const productNameFontFamily =
85
85
  (getVariableByName('productOverview/productName/fontFamily', modes) as string | null) ??
@@ -92,7 +92,7 @@ const ProductOverview = ({
92
92
  (getVariableByName('productOverview/productName/lineHeight', modes) as number | null) ?? 26
93
93
 
94
94
  const descriptionColor =
95
- (getVariableByName('productOverview/description/color', modes) as string | null) ??
95
+ (getVariableByName('text/appearance/medium/color', modes) as string | null) ??
96
96
  '#1a1c1f'
97
97
  const descriptionFontFamily =
98
98
  (getVariableByName('productOverview/description/fontFamily', modes) as string | null) ??
@@ -115,7 +115,12 @@ export const Radio = forwardRef<View, RadioProps>(function Radio({
115
115
  }
116
116
 
117
117
  // Border Color
118
- let borderColorVar = `${prefix}/border/color`
118
+ // Coin Variables has no `radio/focus/border/color` — focus indication is
119
+ // the yellow boxShadow ring; stroke reuses the published idle border.
120
+ let borderColorVar =
121
+ visualState === 'focus' && !selected
122
+ ? 'radio/idle/border/color'
123
+ : `${prefix}/border/color`
119
124
 
120
125
  // Border Width
121
126
  let borderWidthVar = `${prefix}/border/size`
@@ -174,7 +179,6 @@ export const Radio = forwardRef<View, RadioProps>(function Radio({
174
179
  getVariableByName('radio/selector/size')
175
180
  getVariableByName('radio/width')
176
181
  getVariableByName('radio/height')
177
- getVariableByName('radio/background/color')
178
182
  getVariableByName('radio/hover/background/color')
179
183
  getVariableByName('radio/hover/border/color')
180
184
  getVariableByName('radio/hover/boxShadow/size')
@@ -188,13 +192,14 @@ export const Radio = forwardRef<View, RadioProps>(function Radio({
188
192
  getVariableByName('radio/hoverSelected/shadow/color')
189
193
  getVariableByName('radio/hoverSelected/selector/background/color')
190
194
  getVariableByName('radio/focus/background/color')
191
- getVariableByName('radio/focus/border/color')
192
195
  getVariableByName('radio/focus/border/size')
193
196
  getVariableByName('radio/focus/boxShadow/size')
194
197
  getVariableByName('radio/focus/shadow/color')
195
198
  getVariableByName('radio/focusSelected/background/color')
199
+ getVariableByName('radio/focusSelected/border/color')
196
200
  getVariableByName('radio/focusSelected/selector/background/color')
197
201
  getVariableByName('radio/focusSelected/border/size')
202
+ getVariableByName('radio/focusSelected/shadow/color')
198
203
  getVariableByName('radio/disabled/radio/disabled/border/size')
199
204
  getVariableByName('radio/disabled/background/color')
200
205
  getVariableByName('radio/disabled/border/color')
@@ -211,7 +211,7 @@ function SavingsGoalSummary({
211
211
  getVariableByName('savingsGoalSummary/value/fontWeight', mergedModes) ?? 900,
212
212
  ) as TextStyle['fontWeight']
213
213
  const valueColor =
214
- (getVariableByName('savingsGoalSummary/value/color', mergedModes) as string | null) ??
214
+ (getVariableByName('text/appearance/high/color', mergedModes) as string | null) ??
215
215
  '#0d0d0f'
216
216
 
217
217
  // Caption ("Credit usage") typography — `savingsGoalSummary/label/*`
@@ -227,8 +227,8 @@ function SavingsGoalSummary({
227
227
  getVariableByName('savingsGoalSummary/label/fontWeight', mergedModes) ?? 400,
228
228
  ) as TextStyle['fontWeight']
229
229
  const labelColor =
230
- (getVariableByName('savingsGoalSummary/label/color', mergedModes) as string | null) ??
231
- '#0d0d0f'
230
+ (getVariableByName('text/appearance/medium/color', mergedModes) as string | null) ??
231
+ '#1a1c1f'
232
232
 
233
233
  const labelNode =
234
234
  label == null || label === false ? null : typeof label === 'string' ? (
@@ -141,7 +141,7 @@ function SegmentedControl({
141
141
 
142
142
  const gap = (getVariableByName('segmentedControl/gap', modes) ?? 8) as number
143
143
  const background = (getVariableByName('segmentedControl/background', modes) ?? '#f6f3ff') as string
144
- const radius = (getVariableByName('segmentedControl/radius', modes) ?? 24) as number
144
+ const radius = (getVariableByName('segment/radius', modes) ?? 20) as number
145
145
 
146
146
  const containerStyle: ViewStyle = {
147
147
  flexDirection: 'row',
@@ -171,8 +171,7 @@ function SegmentedTrack({
171
171
 
172
172
  const trackHeight =
173
173
  (getVariableByName('segmentedTrack/height', modes) as number | null) ?? 24
174
- const trackRadius =
175
- (getVariableByName('segmentedTrack/radius', modes) as number | null) ?? 999
174
+ const trackRadius = trackHeight / 2
176
175
 
177
176
  const renderedSegments = renderSegments({
178
177
  segments,
@@ -547,8 +547,9 @@ function resolveTokens(modes: Modes): ResolvedTokens {
547
547
  const tooltipBackground = asStr(getVariableByName('tooltip/background', modes), '#0f0d0a')
548
548
  const tooltipPaddingH = asNum(getVariableByName('tooltip/padding/horizontal', modes), 12)
549
549
  const tooltipPaddingV = asNum(getVariableByName('tooltip/padding/vertical', modes), 8)
550
- const tooltipRadius = asNum(getVariableByName('radius', modes), 8)
551
- const tooltipMaxWidth = asNum(getVariableByName('maxWidth', modes), 280)
550
+ // Not yet in Coin Variables export (Figma still binds bare local radius/maxWidth).
551
+ const tooltipRadius = asNum(getVariableByName('tooltip/radius', modes), 8)
552
+ const tooltipMaxWidth = asNum(getVariableByName('tooltip/maxWidth', modes), 280)
552
553
  const tipWidth = asNum(getVariableByName('tooltip/tipItem/width', modes), 16)
553
554
  const tipHeight = asNum(getVariableByName('tooltip/tipItem/height', modes), 8)
554
555
 
@@ -141,7 +141,7 @@ export default function StatusHero({
141
141
  <MoneyValue
142
142
  value={value}
143
143
  currency={currency}
144
- modes={{ ...modes, Context3: 'Balance' }}
144
+ modes={{ ...modes, Context3: 'Balance & Cards' }}
145
145
  />
146
146
  </View>
147
147
  )
@@ -266,8 +266,10 @@ export function TooltipContent({
266
266
  const bgColor = (getVariableByName('tooltip/background', modes) as string)
267
267
  const paddingH = Number(getVariableByName('tooltip/padding/horizontal', modes))
268
268
  const paddingV = Number(getVariableByName('tooltip/padding/vertical', modes))
269
- const radius = Number(getVariableByName('radius', modes))
270
- const maxWidthToken = Number(getVariableByName('maxWidth', modes))
269
+ // Figma still binds bare local radius/maxWidth; published names are tooltip/*.
270
+ // Not yet in Coin Variables export — fall back to Figma values (8 / 280).
271
+ const radius = Number(getVariableByName('tooltip/radius', modes) ?? 8)
272
+ const maxWidthToken = Number(getVariableByName('tooltip/maxWidth', modes) ?? 280)
271
273
  const arrowWidth = Number(getVariableByName('tooltip/tipItem/width', modes))
272
274
  const arrowHeight = Number(getVariableByName('tooltip/tipItem/height', modes))
273
275
  const labelColor = (getVariableByName('tooltip/label/color', modes) as string)