@luxfi/ui 7.4.12 → 7.4.13

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.
@@ -1,12 +1,8 @@
1
1
  "use client";
2
+ import { YStack, XStack, Text, View } from '@hanzo/gui';
2
3
  import * as React from 'react';
3
- import { clsx } from 'clsx';
4
- import { twMerge } from 'tailwind-merge';
5
4
  import { jsxs, jsx } from 'react/jsx-runtime';
6
5
 
7
- function cn(...inputs) {
8
- return twMerge(clsx(inputs));
9
- }
10
6
  function findATM(strikes, spot) {
11
7
  if (strikes.length === 0) return spot;
12
8
  return strikes.reduce(
@@ -115,84 +111,145 @@ var STRATEGY_PRESETS = [
115
111
  ]
116
112
  }
117
113
  ];
114
+ var MONO = "monospace";
115
+ var CONTROL_BOX = {
116
+ backgroundColor: "var(--color-input-bg)",
117
+ borderWidth: 1,
118
+ borderColor: "var(--color-input-border)",
119
+ outlineWidth: 0,
120
+ focusStyle: { borderColor: "var(--color-input-border-focus)" }
121
+ };
122
+ var CONTROL_INK = { color: "var(--color-input-fg)" };
118
123
  function LegRow({ leg, index, strikes, expirations, removable, onChange, onRemove }) {
119
124
  const update = (patch) => {
120
125
  onChange(index, { ...leg, ...patch });
121
126
  };
122
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-md bg-zinc-800/50 px-2 py-1.5", children: [
123
- /* @__PURE__ */ jsx("span", { className: "text-[10px] font-mono text-zinc-500 w-4 shrink-0", children: index + 1 }),
124
- /* @__PURE__ */ jsx(
125
- "button",
126
- {
127
- type: "button",
128
- className: cn(
129
- "px-2 py-0.5 rounded text-xs font-semibold transition-colors",
130
- leg.action === "buy" ? "bg-emerald-900/60 text-emerald-400" : "bg-red-900/60 text-red-400"
127
+ return /* @__PURE__ */ jsxs(
128
+ XStack,
129
+ {
130
+ alignItems: "center",
131
+ gap: 8,
132
+ borderRadius: 6,
133
+ backgroundColor: "var(--color-tag-subtle-bg)",
134
+ paddingHorizontal: 8,
135
+ paddingVertical: 6,
136
+ children: [
137
+ /* @__PURE__ */ jsx(Text, { fontSize: 10, style: { fontFamily: MONO }, flexShrink: 0, width: 16, color: "var(--color-text-secondary)", children: index + 1 }),
138
+ /* @__PURE__ */ jsx(
139
+ XStack,
140
+ {
141
+ unstyled: true,
142
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
143
+ onClick: () => update({ action: leg.action === "buy" ? "sell" : "buy" }),
144
+ paddingHorizontal: 8,
145
+ paddingVertical: 2,
146
+ borderRadius: 4,
147
+ borderWidth: 0,
148
+ cursor: "pointer",
149
+ transition: "quick",
150
+ backgroundColor: leg.action === "buy" ? "color-mix(in srgb, var(--color-status-good) 20%, transparent)" : "color-mix(in srgb, var(--color-status-bad) 20%, transparent)",
151
+ children: /* @__PURE__ */ jsx(Text, { fontSize: 12, fontWeight: "600", color: leg.action === "buy" ? "var(--color-status-good)" : "var(--color-status-bad)", children: leg.action === "buy" ? "BUY" : "SELL" })
152
+ }
131
153
  ),
132
- onClick: () => update({ action: leg.action === "buy" ? "sell" : "buy" }),
133
- children: leg.action === "buy" ? "BUY" : "SELL"
134
- }
135
- ),
136
- /* @__PURE__ */ jsx(
137
- "button",
138
- {
139
- type: "button",
140
- className: cn(
141
- "px-2 py-0.5 rounded text-xs font-medium transition-colors",
142
- // Call vs put is a rank difference, not a hue difference.
143
- leg.type === "call" ? "bg-[var(--secondary)] text-[var(--foreground)]" : "bg-[var(--muted)] text-[var(--muted-foreground)]"
154
+ /* @__PURE__ */ jsx(
155
+ XStack,
156
+ {
157
+ unstyled: true,
158
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
159
+ onClick: () => update({ type: leg.type === "call" ? "put" : "call" }),
160
+ paddingHorizontal: 8,
161
+ paddingVertical: 2,
162
+ borderRadius: 4,
163
+ borderWidth: 0,
164
+ cursor: "pointer",
165
+ transition: "quick",
166
+ backgroundColor: leg.type === "call" ? "var(--secondary)" : "var(--muted)",
167
+ children: /* @__PURE__ */ jsx(Text, { fontSize: 12, fontWeight: "500", color: leg.type === "call" ? "var(--foreground)" : "var(--muted-foreground)", children: leg.type === "call" ? "CALL" : "PUT" })
168
+ }
144
169
  ),
145
- onClick: () => update({ type: leg.type === "call" ? "put" : "call" }),
146
- children: leg.type === "call" ? "CALL" : "PUT"
147
- }
148
- ),
149
- /* @__PURE__ */ jsx(
150
- "select",
151
- {
152
- value: leg.strike,
153
- onChange: (e) => update({ strike: Number(e.target.value) }),
154
- className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs font-mono text-zinc-200 outline-none focus:border-zinc-500 min-w-[72px]",
155
- children: strikes.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: s.toFixed(2) }, s))
156
- }
157
- ),
158
- /* @__PURE__ */ jsx(
159
- "select",
160
- {
161
- value: leg.expiration,
162
- onChange: (e) => update({ expiration: e.target.value }),
163
- className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs text-zinc-200 outline-none focus:border-zinc-500 min-w-[80px]",
164
- children: expirations.map((exp) => /* @__PURE__ */ jsx("option", { value: exp, children: exp }, exp))
165
- }
166
- ),
167
- /* @__PURE__ */ jsx(
168
- "input",
169
- {
170
- type: "number",
171
- min: 1,
172
- max: 999,
173
- value: leg.quantity,
174
- onChange: (e) => update({ quantity: Math.max(1, parseInt(e.target.value, 10) || 1) }),
175
- className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs font-mono text-zinc-200 outline-none focus:border-zinc-500 w-[48px] text-center"
176
- }
177
- ),
178
- leg.premium !== void 0 && /* @__PURE__ */ jsxs("span", { className: cn(
179
- "font-mono tabular-nums text-xs ml-auto",
180
- leg.premium >= 0 ? "text-emerald-400" : "text-red-400"
181
- ), children: [
182
- leg.premium >= 0 ? "+" : "",
183
- leg.premium.toFixed(2)
184
- ] }),
185
- removable && /* @__PURE__ */ jsx(
186
- "button",
187
- {
188
- type: "button",
189
- onClick: () => onRemove(index),
190
- className: "ml-auto p-0.5 text-zinc-500 hover:text-red-400 transition-colors",
191
- "aria-label": "Remove leg",
192
- children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
193
- }
194
- )
195
- ] });
170
+ /* @__PURE__ */ jsx(
171
+ View,
172
+ {
173
+ unstyled: true,
174
+ render: /* @__PURE__ */ jsx("select", { value: leg.strike, onChange: (e) => update({ strike: Number(e.target.value) }) }),
175
+ ...CONTROL_BOX,
176
+ borderRadius: 4,
177
+ paddingHorizontal: 6,
178
+ paddingVertical: 2,
179
+ minWidth: 72,
180
+ style: { ...CONTROL_INK, fontFamily: MONO, fontSize: 12 },
181
+ children: strikes.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: s.toFixed(2) }, s))
182
+ }
183
+ ),
184
+ /* @__PURE__ */ jsx(
185
+ View,
186
+ {
187
+ unstyled: true,
188
+ render: /* @__PURE__ */ jsx("select", { value: leg.expiration, onChange: (e) => update({ expiration: e.target.value }) }),
189
+ ...CONTROL_BOX,
190
+ borderRadius: 4,
191
+ paddingHorizontal: 6,
192
+ paddingVertical: 2,
193
+ minWidth: 80,
194
+ style: { ...CONTROL_INK, fontSize: 12 },
195
+ children: expirations.map((exp) => /* @__PURE__ */ jsx("option", { value: exp, children: exp }, exp))
196
+ }
197
+ ),
198
+ /* @__PURE__ */ jsx(
199
+ View,
200
+ {
201
+ unstyled: true,
202
+ render: /* @__PURE__ */ jsx(
203
+ "input",
204
+ {
205
+ type: "number",
206
+ min: 1,
207
+ max: 999,
208
+ value: leg.quantity,
209
+ onChange: (e) => update({ quantity: Math.max(1, parseInt(e.target.value, 10) || 1) })
210
+ }
211
+ ),
212
+ ...CONTROL_BOX,
213
+ borderRadius: 4,
214
+ paddingHorizontal: 6,
215
+ paddingVertical: 2,
216
+ width: 48,
217
+ style: { ...CONTROL_INK, fontFamily: MONO, fontSize: 12, textAlign: "center" }
218
+ }
219
+ ),
220
+ leg.premium !== void 0 && /* @__PURE__ */ jsxs(
221
+ Text,
222
+ {
223
+ fontSize: 12,
224
+ style: { fontFamily: MONO },
225
+ fontVariant: ["tabular-nums"],
226
+ marginLeft: "auto",
227
+ color: leg.premium >= 0 ? "var(--color-status-good)" : "var(--color-status-bad)",
228
+ children: [
229
+ leg.premium >= 0 ? "+" : "",
230
+ leg.premium.toFixed(2)
231
+ ]
232
+ }
233
+ ),
234
+ removable && /* @__PURE__ */ jsx(
235
+ XStack,
236
+ {
237
+ unstyled: true,
238
+ render: /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Remove leg" }),
239
+ onClick: () => onRemove(index),
240
+ marginLeft: "auto",
241
+ padding: 2,
242
+ borderWidth: 0,
243
+ cursor: "pointer",
244
+ transition: "quick",
245
+ style: { color: "var(--color-text-secondary)" },
246
+ hoverStyle: { opacity: 0.7 },
247
+ children: /* @__PURE__ */ jsx("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
248
+ }
249
+ )
250
+ ]
251
+ }
252
+ );
196
253
  }
197
254
  var StrategyBuilder = React.forwardRef(
198
255
  function StrategyBuilder2(props, ref) {
@@ -262,37 +319,46 @@ var StrategyBuilder = React.forwardRef(
262
319
  });
263
320
  }, [onSubmit, strategyType, legs, netPremium]);
264
321
  const currentPreset = STRATEGY_PRESETS.find((p) => p.value === strategyType);
322
+ const netColor = netPremium > 0 ? "var(--color-status-good)" : netPremium < 0 ? "var(--color-status-bad)" : "var(--color-text-secondary)";
265
323
  return /* @__PURE__ */ jsxs(
266
- "div",
324
+ YStack,
267
325
  {
268
326
  ref,
269
- className: cn(
270
- "flex flex-col gap-3 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3",
271
- className
272
- ),
327
+ gap: 12,
328
+ borderRadius: 8,
329
+ borderWidth: 1,
330
+ borderColor: "var(--color-border-divider)",
331
+ backgroundColor: "var(--card)",
332
+ padding: 12,
333
+ className,
273
334
  ...rest,
274
335
  children: [
275
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
276
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
277
- /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-zinc-500", children: "Strategy" }),
278
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-zinc-200", children: underlying })
336
+ /* @__PURE__ */ jsxs(XStack, { alignItems: "center", justifyContent: "space-between", gap: 12, children: [
337
+ /* @__PURE__ */ jsxs(XStack, { alignItems: "center", gap: 8, children: [
338
+ /* @__PURE__ */ jsx(Text, { fontSize: 12, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.6, color: "var(--color-text-secondary)", children: "Strategy" }),
339
+ /* @__PURE__ */ jsx(Text, { fontSize: 14, fontWeight: "500", color: "var(--color-text-primary)", children: underlying })
279
340
  ] }),
280
- /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-zinc-500", children: [
341
+ /* @__PURE__ */ jsxs(Text, { fontSize: 10, color: "var(--color-text-secondary)", children: [
281
342
  "Spot: ",
282
- /* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums text-zinc-300", children: spotPrice.toFixed(2) })
343
+ /* @__PURE__ */ jsx(Text, { style: { fontFamily: MONO }, fontVariant: ["tabular-nums"], color: "var(--color-text-primary)", children: spotPrice.toFixed(2) })
283
344
  ] })
284
345
  ] }),
285
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
286
- "select",
346
+ /* @__PURE__ */ jsx(XStack, { alignItems: "center", gap: 8, children: /* @__PURE__ */ jsx(
347
+ View,
287
348
  {
288
- value: strategyType,
289
- onChange: handleStrategyChange,
290
- className: "flex-1 bg-zinc-900 border border-zinc-700 rounded-md px-2.5 py-1.5 text-sm text-zinc-200 outline-none focus:border-zinc-500",
349
+ unstyled: true,
350
+ render: /* @__PURE__ */ jsx("select", { value: strategyType, onChange: handleStrategyChange }),
351
+ flex: 1,
352
+ ...CONTROL_BOX,
353
+ borderRadius: 6,
354
+ paddingHorizontal: 10,
355
+ paddingVertical: 6,
356
+ style: { ...CONTROL_INK, fontSize: 14 },
291
357
  children: STRATEGY_PRESETS.map((preset) => /* @__PURE__ */ jsx("option", { value: preset.value, children: preset.label }, preset.value))
292
358
  }
293
359
  ) }),
294
- currentPreset && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-zinc-500 -mt-1", children: currentPreset.description }),
295
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children: legs.map((leg, i) => /* @__PURE__ */ jsx(
360
+ currentPreset && /* @__PURE__ */ jsx(Text, { fontSize: 11, marginTop: -4, color: "var(--color-text-secondary)", children: currentPreset.description }),
361
+ /* @__PURE__ */ jsx(YStack, { gap: 6, children: legs.map((leg, i) => /* @__PURE__ */ jsx(
296
362
  LegRow,
297
363
  {
298
364
  leg,
@@ -306,40 +372,53 @@ var StrategyBuilder = React.forwardRef(
306
372
  i
307
373
  )) }),
308
374
  strategyType === "custom" && legs.length < 4 && /* @__PURE__ */ jsxs(
309
- "button",
375
+ XStack,
310
376
  {
311
- type: "button",
377
+ unstyled: true,
378
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
312
379
  onClick: handleAddLeg,
313
- className: "flex items-center justify-center gap-1 rounded-md border border-dashed border-zinc-700 py-1 text-xs text-zinc-500 hover:text-zinc-300 hover:border-zinc-500 transition-colors",
380
+ alignItems: "center",
381
+ justifyContent: "center",
382
+ gap: 4,
383
+ borderRadius: 6,
384
+ borderWidth: 1,
385
+ paddingVertical: 4,
386
+ cursor: "pointer",
387
+ transition: "quick",
388
+ borderColor: "var(--color-border-divider)",
389
+ hoverStyle: { borderColor: "var(--color-hover)" },
390
+ style: { color: "var(--color-text-secondary)", borderStyle: "dashed" },
314
391
  children: [
315
- /* @__PURE__ */ jsx("svg", { className: "h-3 w-3", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
316
- "Add Leg"
392
+ /* @__PURE__ */ jsx("svg", { width: 12, height: 12, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
393
+ /* @__PURE__ */ jsx(Text, { fontSize: 12, color: "var(--color-text-secondary)", children: "Add Leg" })
317
394
  ]
318
395
  }
319
396
  ),
320
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-1 border-t border-zinc-800", children: [
321
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
322
- /* @__PURE__ */ jsx("span", { className: "text-xs text-zinc-500", children: "Net:" }),
323
- /* @__PURE__ */ jsxs("span", { className: cn(
324
- "font-mono tabular-nums text-sm font-semibold",
325
- netPremium > 0 ? "text-emerald-400" : netPremium < 0 ? "text-red-400" : "text-zinc-400"
326
- ), children: [
397
+ /* @__PURE__ */ jsxs(XStack, { alignItems: "center", justifyContent: "space-between", paddingTop: 4, borderTopWidth: 1, borderColor: "var(--color-border-divider)", children: [
398
+ /* @__PURE__ */ jsxs(XStack, { alignItems: "center", gap: 8, children: [
399
+ /* @__PURE__ */ jsx(Text, { fontSize: 12, color: "var(--color-text-secondary)", children: "Net:" }),
400
+ /* @__PURE__ */ jsxs(Text, { fontSize: 14, fontWeight: "600", style: { fontFamily: MONO }, fontVariant: ["tabular-nums"], color: netColor, children: [
327
401
  netPremium > 0 ? "Credit " : netPremium < 0 ? "Debit " : "",
328
402
  netPremium !== 0 ? `$${Math.abs(netPremium).toFixed(2)}` : "-"
329
403
  ] })
330
404
  ] }),
331
405
  /* @__PURE__ */ jsx(
332
- "button",
406
+ XStack,
333
407
  {
334
- type: "button",
408
+ unstyled: true,
409
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
335
410
  onClick: handleSubmit,
336
411
  disabled: legs.length === 0,
337
- className: cn(
338
- "px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
339
- "bg-blue-600 text-white hover:bg-blue-500",
340
- "disabled:opacity-40 disabled:cursor-not-allowed"
341
- ),
342
- children: "Review Order"
412
+ paddingHorizontal: 16,
413
+ paddingVertical: 6,
414
+ borderRadius: 6,
415
+ borderWidth: 0,
416
+ cursor: "pointer",
417
+ transition: "quick",
418
+ backgroundColor: "var(--color-button-solid-bg)",
419
+ hoverStyle: { backgroundColor: "var(--color-hover)" },
420
+ disabledStyle: { opacity: 0.4, cursor: "not-allowed" },
421
+ children: /* @__PURE__ */ jsx(Text, { fontSize: 12, fontWeight: "600", color: "var(--color-button-solid-text)", children: "Review Order" })
343
422
  }
344
423
  )
345
424
  ] })
package/dist/tag.cjs CHANGED
@@ -476,21 +476,24 @@ var Tag = React4__namespace.forwardRef(
476
476
  ":",
477
477
  nbsp
478
478
  ] }) : null;
479
- const labelSpan = /* @__PURE__ */ jsxRuntime.jsxs(
480
- gui.Text,
481
- {
482
- overflow: "hidden",
483
- textOverflow: "ellipsis",
484
- whiteSpace: "nowrap",
485
- fontWeight: "500",
486
- fontSize: TAG_SIZE_FONT[resolvedSize],
487
- color,
488
- hoverStyle: textHoverColor ? { color: textHoverColor } : void 0,
489
- children: [
490
- labelElement,
491
- children
492
- ]
493
- }
479
+ const labelSpan = (
480
+ // `ellipsis` is Text's own built-in single-line-truncation variant —
481
+ // the same rule Tailwind's `line-clamp-1`/`text-ellipsis` drew, through
482
+ // the component's variants rather than three separate style props.
483
+ /* @__PURE__ */ jsxRuntime.jsxs(
484
+ gui.Text,
485
+ {
486
+ ellipsis: true,
487
+ fontWeight: "500",
488
+ fontSize: TAG_SIZE_FONT[resolvedSize],
489
+ color,
490
+ hoverStyle: textHoverColor ? { color: textHoverColor } : void 0,
491
+ children: [
492
+ labelElement,
493
+ children
494
+ ]
495
+ }
496
+ )
494
497
  );
495
498
  const contentElement = truncated ? /* @__PURE__ */ jsxRuntime.jsx(TruncatedTextTooltip, { label: children, children: labelSpan }) : labelSpan;
496
499
  return /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { loading, asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
package/dist/tag.js CHANGED
@@ -455,21 +455,24 @@ var Tag = React4.forwardRef(
455
455
  ":",
456
456
  nbsp
457
457
  ] }) : null;
458
- const labelSpan = /* @__PURE__ */ jsxs(
459
- Text,
460
- {
461
- overflow: "hidden",
462
- textOverflow: "ellipsis",
463
- whiteSpace: "nowrap",
464
- fontWeight: "500",
465
- fontSize: TAG_SIZE_FONT[resolvedSize],
466
- color,
467
- hoverStyle: textHoverColor ? { color: textHoverColor } : void 0,
468
- children: [
469
- labelElement,
470
- children
471
- ]
472
- }
458
+ const labelSpan = (
459
+ // `ellipsis` is Text's own built-in single-line-truncation variant —
460
+ // the same rule Tailwind's `line-clamp-1`/`text-ellipsis` drew, through
461
+ // the component's variants rather than three separate style props.
462
+ /* @__PURE__ */ jsxs(
463
+ Text,
464
+ {
465
+ ellipsis: true,
466
+ fontWeight: "500",
467
+ fontSize: TAG_SIZE_FONT[resolvedSize],
468
+ color,
469
+ hoverStyle: textHoverColor ? { color: textHoverColor } : void 0,
470
+ children: [
471
+ labelElement,
472
+ children
473
+ ]
474
+ }
475
+ )
473
476
  );
474
477
  const contentElement = truncated ? /* @__PURE__ */ jsx(TruncatedTextTooltip, { label: children, children: labelSpan }) : labelSpan;
475
478
  return /* @__PURE__ */ jsx(Skeleton, { loading, asChild: true, children: /* @__PURE__ */ jsxs(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxfi/ui",
3
- "version": "7.4.12",
3
+ "version": "7.4.13",
4
4
  "description": "Cross-platform UI components on @hanzo/gui. Native mobile + web.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/avatar.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { Avatar as GuiAvatar, View, XStack } from '@hanzo/gui';
3
+ import { Avatar as GuiAvatar, XStack } from '@hanzo/gui';
4
4
  import * as React from 'react';
5
5
 
6
6
  import { ink } from './ink';
@@ -94,7 +94,6 @@ export const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
94
94
  return (
95
95
  <GuiAvatar
96
96
  ref={ ref as never }
97
- unstyled
98
97
  position="relative"
99
98
  display="inline-flex"
100
99
  flexShrink={ 0 }
@@ -49,24 +49,24 @@ interface ExpirationPillProps {
49
49
 
50
50
  // Resting and selected are the same two states every selectable pill in this
51
51
  // package uses (tabs, menu rows): a solid fill when selected, a bordered card
52
- // otherwise. The date label sets no colour of its own it inherits the
53
- // button's, so `hoverStyle` here is what brightens it on hover, in one place.
52
+ // otherwise. Stacks carry no `color` of their own (only Text does — same
53
+ // reason they carry no `fontSize`), so ink is computed per-state below and
54
+ // set directly on each Text rather than left to cascade from the button.
54
55
  const SHAPE = {
55
56
  selected: {
56
57
  borderColor: 'transparent',
57
58
  backgroundColor: 'var(--color-selected-control-bg)',
58
- color: 'var(--color-selected-control-text)',
59
59
  },
60
60
  resting: {
61
61
  borderColor: 'var(--color-border-divider)',
62
62
  backgroundColor: 'var(--card)',
63
- color: 'var(--color-text-secondary)',
64
- hoverStyle: { borderColor: 'var(--color-hover)', color: 'var(--color-hover)' },
63
+ hoverStyle: { borderColor: 'var(--color-hover)' },
65
64
  },
66
65
  } as const;
67
66
 
68
67
  function ExpirationPill({ exp, isSelected, onClick }: ExpirationPillProps) {
69
68
  const shape = isSelected ? SHAPE.selected : SHAPE.resting;
69
+ const dateColor = isSelected ? 'var(--color-selected-control-text)' : 'var(--color-text-secondary)';
70
70
 
71
71
  // Near-expiry is a notice, and a notice in Lux is the loudest neutral — it
72
72
  // only shows while resting; a selected pill's own fill already carries the
@@ -91,7 +91,7 @@ function ExpirationPill({ exp, isSelected, onClick }: ExpirationPillProps) {
91
91
  cursor="pointer"
92
92
  { ...(shape as object) }
93
93
  >
94
- <Text unstyled fontSize={ 12 } fontWeight="500" style={ { whiteSpace: 'nowrap' } as never }>
94
+ <Text fontSize={ 12 } fontWeight="500" style={ { whiteSpace: 'nowrap' } as never } color={ dateColor as never }>
95
95
  { formatExpDate(exp.date) }
96
96
  </Text>
97
97
  <Text
@@ -129,7 +129,7 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
129
129
  zIndex={ 1 }
130
130
  alignItems="center"
131
131
  pointerEvents="none"
132
- color={ 'var(--color-icon-secondary)' as never }
132
+ style={{ color: 'var(--color-icon-secondary)' }}
133
133
  className={ startClassName }
134
134
  { ...(startRest as object) }
135
135
  >
@@ -167,7 +167,7 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
167
167
  zIndex={ 1 }
168
168
  alignItems="center"
169
169
  pointerEvents="none"
170
- color={ 'var(--color-icon-secondary)' as never }
170
+ style={{ color: 'var(--color-icon-secondary)' }}
171
171
  className={ endClassName }
172
172
  { ...(endRest as object) }
173
173
  >
@@ -189,9 +189,16 @@ function ActionButton({ onClick, children }: ActionButtonProps) {
189
189
  paddingVertical={ 4 }
190
190
  backgroundColor={ 'var(--color-button-subtle-bg)' as never }
191
191
  cursor="pointer"
192
- hoverStyle={ { color: 'var(--color-hover)' } as never }
193
192
  >
194
- <Text fontSize={ 12 } fontWeight="500" color={ 'var(--color-button-subtle-fg)' as never }>
193
+ {/* `hoverStyle` lives on the Text, not the button frame Stacks carry
194
+ no `color` (same reason they carry no `fontSize`), so the hover
195
+ re-tint has to be the text's own state, not the button's. */}
196
+ <Text
197
+ fontSize={ 12 }
198
+ fontWeight="500"
199
+ color={ 'var(--color-button-subtle-fg)' as never }
200
+ hoverStyle={ { color: 'var(--color-hover)' } as never }
201
+ >
195
202
  { children }
196
203
  </Text>
197
204
  </XStack>