@trading-game/design-intelligence-layer 0.17.1 → 0.17.2

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.
package/README.md CHANGED
@@ -186,11 +186,13 @@ See [`AGENTS.md`](./AGENTS.md#blocks) for full usage examples per block.
186
186
  ## Button variants and sizes
187
187
 
188
188
  ```tsx
189
- <Button variant="primary" /> // Blue filled — main CTA (light surfaces)
190
- <Button variant="primary-inverse" /> // White filled + blue text — main CTA on dark/coloured surfaces
191
- <Button variant="secondary" /> // Black outline — secondary actions (light surfaces)
192
- <Button variant="secondary-inverse" /> // White outline + white text — secondary actions on dark/coloured surfaces
193
- <Button variant="tertiary" /> // Text only — minimal (light surfaces)
189
+ <Button variant="primary" /> // Blue filled — main CTA (light surfaces)
190
+ <Button variant="primary-inverse" /> // White filled + blue text — main CTA on dark/coloured surfaces
191
+ <Button variant="primary-shimmer" /> // Same as `primary` + sweeping diagonal shimmer (headline CTAs that need to draw the eye)
192
+ <Button variant="primary-inverse-shimmer" /> // Same as `primary-inverse` + brand-blue shimmer over the white surface
193
+ <Button variant="secondary" /> // Black outline — secondary actions (light surfaces)
194
+ <Button variant="secondary-inverse" /> // White outline + white text — secondary actions on dark/coloured surfaces
195
+ <Button variant="tertiary" /> // Text only — minimal (light surfaces)
194
196
 
195
197
  // Sizes
196
198
  <Button size="lg" /> // 48px height (default)
@@ -236,7 +238,7 @@ States: hover (`bg-secondary-hover`), focus (3px `ring-ring/50`), active (`opaci
236
238
  <Badge variant="fill-success" /> // Green tint
237
239
  <Badge variant="fill-fail" /> // Red tint
238
240
  <Badge variant="fill-warning" /> // Yellow tint — status/warning
239
- <Badge variant="fill-credit" /> // Deep peach (#FDCA8A) + bold deep-amber (#521900) text — Welcome credit / bonus labels
241
+ <Badge variant="fill-credit" /> // Frosted-glass surface (`--semantic-boost-surface` = `oklch(1 0 0 / 0.22)`) + white text + `backdrop-blur-md` — Welcome credit / bonus chip. Only readable on coloured surfaces (e.g. a brand-blue hero card); blends into white surfaces by design.
240
242
  <Badge variant="fill-demo" /> // Peach surface + red-orange text — demo/test-mode flags
241
243
 
242
244
  // Outline (black border, secondary-hover on hover)
@@ -712,6 +714,10 @@ Design tokens are managed in Figma and exported as CSS variables. To update:
712
714
  ## Changelog
713
715
 
714
716
  ### Unreleased
717
+ - **Button — two new shimmer variants for headline CTAs:** `primary-shimmer` and `primary-inverse-shimmer`. Same surface tokens as their non-shimmer cousins, plus `relative overflow-hidden` to anchor an absolutely-positioned shimmer overlay. The overlay sweeps a diagonal (`110deg`) gradient driven by a new `button-shimmer` keyframe — two quick back-to-back sweeps every cycle, then a ~3 s pause off-screen, so it reads as an occasional glint rather than a continuous loader. Peak opacity is tuned per-surface (white at 32 % over brand blue; brand-blue at 22 % over white) and falls off into transparent edges. Suppressed automatically when the button is `loading` or `disabled`.
718
+ - **Button — `button-shimmer` keyframe:** new `@keyframes button-shimmer` in both `src/styles.css` and `app/globals.css`. Pattern: `0%, 10% → 30%, 100%` translateX, with an opacity fade at the seam between the two sweeps so the reset between flashes is invisible.
719
+ - **Badge — `fill-credit` is now a frosted glass chip:** `bg-semantic-boost-surface` was repurposed from the old peach (`#FDCA8A`) to `oklch(1 0 0 / 0.22)` — a translucent white surface that composes over whatever sits behind it. Paired with `backdrop-blur-md` and `text-on-primary` (white). Custom `!font-bold` / `!text-xs` overrides removed — the variant now only sets surface tokens, so font weight / size match every other badge (`font-semibold`, `text-xs` from the base). Border override removed too. The variant is intentionally invisible on white surfaces — designed to live on coloured surfaces (e.g. a brand-blue hero card / wallet card), matching the wallet mock's `.c-hero-wc`.
720
+ - **Item — auto-divider in `ItemGroup`:** new `divider` prop (default `true`) adds a 1 px `bg-border-subtle` divider between consecutive default-variant `Item`s. The line is drawn via `::after` (not a border on the item itself), sitting in a 4 px `gap-1` between items with `inset-x-4` so it aligns with the item content padding. The last item's `::after` is suppressed; non-default variants (`outline`, `muted`) are untouched. Pass `divider={false}` to opt out for flush items or manual `<ItemSeparator />` usage.
715
721
  - **Tooltip — black surface by default:** `variant="default"` switched from brand-blue to black (`bg-prominent-inverse` + `text-on-prominent-inverse`). The arrow follows. `variant="inverse"` (white) is unchanged. Default primitive now bakes in `max-w-xs whitespace-normal`, so consumers no longer pass these classes.
716
722
  - **Tooltip — keyboard-shortcut breathing room:** when the tooltip contains a `Kbd` (detected via `:has([data-slot=kbd])`), padding bumps to `px-3.5 py-2` and child elements get `space-y-1.5` so the title / kbd-row pair doesn't crowd.
717
723
  - **Switch — pill + white circle knob:** track switched from `rounded-[6px]` to `rounded-full`, thumb from `rounded-[3px]` to `rounded-full`. Thumb is always `bg-prominent` (white) in both states. Checked track: `bg-primary`. Unchecked track: `bg-input`. No API change.
package/dist/index.cjs CHANGED
@@ -530,6 +530,14 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
530
530
  primary: "bg-primary text-on-primary hover:bg-primary-hover",
531
531
  // Primary Inverse — white bg + blue text; for use on dark/coloured surfaces
532
532
  "primary-inverse": "bg-primary-inverse text-on-primary-inverse hover:bg-primary-inverse/80",
533
+ // Primary Shimmer — same surface as `primary` plus a sweeping
534
+ // white shimmer overlay (same animation as the TicketCard deposit
535
+ // stub). Use for headline CTAs that need to draw the eye.
536
+ "primary-shimmer": "relative overflow-hidden bg-primary text-on-primary hover:bg-primary-hover",
537
+ // Primary Inverse Shimmer — same surface as `primary-inverse` plus
538
+ // a sweeping brand-blue shimmer (white shimmer would be invisible
539
+ // on the white surface). For headline CTAs on dark/coloured pages.
540
+ "primary-inverse-shimmer": "relative overflow-hidden bg-primary-inverse text-on-primary-inverse hover:bg-primary-inverse/80",
533
541
  secondary: "bg-transparent border-[1.5px] border-border-prominent text-on-prominent hover:bg-secondary-hover",
534
542
  // Secondary Inverse — white border + white text; for use on dark/coloured surfaces
535
543
  "secondary-inverse": "bg-transparent border-[1.5px] border-primary-inverse text-on-prominent-inverse hover:bg-primary-inverse/10",
@@ -564,6 +572,13 @@ var spinnerSizeMap = {
564
572
  "icon-sm": "size-3.5",
565
573
  "icon-xs": "size-3"
566
574
  };
575
+ var shimmerGradients = {
576
+ // 110° tilts the bright band forward so the sweep reads as a diagonal
577
+ // shine. Three stops around 50% (soft → mid → soft) shape the highlight
578
+ // like a polished-metal gleam without going too bright at the peak.
579
+ "primary-shimmer": "linear-gradient(110deg, transparent 20%, rgba(255,255,255,0.10) 40%, rgba(255,255,255,0.20) 50%, rgba(255,255,255,0.10) 60%, transparent 80%)",
580
+ "primary-inverse-shimmer": "linear-gradient(110deg, transparent 20%, rgba(35,35,255,0.07) 40%, rgba(35,35,255,0.14) 50%, rgba(35,35,255,0.07) 60%, transparent 80%)"
581
+ };
567
582
  function Button(_a) {
568
583
  var _b = _a, {
569
584
  className,
@@ -581,7 +596,7 @@ function Button(_a) {
581
596
  "children"
582
597
  ]);
583
598
  const Comp = asChild ? import_radix_ui2.Slot.Root : "button";
584
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
599
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
585
600
  Comp,
586
601
  __spreadProps(__spreadValues({
587
602
  "data-slot": "button",
@@ -594,10 +609,20 @@ function Button(_a) {
594
609
  ),
595
610
  "aria-busy": loading || void 0
596
611
  }, props), {
597
- children: loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
598
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "invisible inline-flex items-center gap-[inherit]", "aria-hidden": true, children }),
599
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { className: spinnerSizeMap[size != null ? size : "lg"] }) })
600
- ] }) : children
612
+ children: [
613
+ variant && shimmerGradients[variant] && !loading && !props.disabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
614
+ "span",
615
+ {
616
+ "aria-hidden": true,
617
+ className: "pointer-events-none absolute inset-0 [animation:button-shimmer_4s_linear_infinite]",
618
+ style: { background: shimmerGradients[variant] }
619
+ }
620
+ ) : null,
621
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
622
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "invisible inline-flex items-center gap-[inherit]", "aria-hidden": true, children }),
623
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { className: spinnerSizeMap[size != null ? size : "lg"] }) })
624
+ ] }) : children
625
+ ]
601
626
  })
602
627
  );
603
628
  }
@@ -1128,7 +1153,7 @@ var badgeVariants = (0, import_class_variance_authority3.cva)(
1128
1153
  "fill-success": "bg-semantic-win/10 border-transparent text-semantic-win",
1129
1154
  "fill-fail": "bg-semantic-loss/10 border-transparent text-semantic-loss",
1130
1155
  "fill-warning": "bg-semantic-warning/10 border-transparent text-semantic-warning",
1131
- "fill-credit": "bg-semantic-boost-surface border-transparent text-on-semantic-boost !text-xs !font-bold",
1156
+ "fill-credit": "bg-semantic-boost-surface backdrop-blur-md text-on-primary",
1132
1157
  // Demo / test-mode flag — opaque light-peach surface + red-orange text.
1133
1158
  // Uses --semantic-demo-surface (a solid color-mix of demo @ 10% with white)
1134
1159
  // so the badge looks identical on any background.
@@ -4311,13 +4336,37 @@ var import_class_variance_authority9 = require("class-variance-authority");
4311
4336
  var import_radix_ui18 = require("radix-ui");
4312
4337
  var import_jsx_runtime35 = require("react/jsx-runtime");
4313
4338
  function ItemGroup(_a) {
4314
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
4339
+ var _b = _a, {
4340
+ className,
4341
+ divider = true
4342
+ } = _b, props = __objRest(_b, [
4343
+ "className",
4344
+ "divider"
4345
+ ]);
4315
4346
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4316
4347
  "div",
4317
4348
  __spreadValues({
4318
4349
  role: "list",
4319
4350
  "data-slot": "item-group",
4320
- className: cn("group/item-group flex flex-col", className)
4351
+ "data-divider": divider ? "true" : void 0,
4352
+ className: cn(
4353
+ "group/item-group flex flex-col",
4354
+ // Divider mode: 4 px gap between items + a 1 px line drawn via
4355
+ // ::after on each non-last default item, sitting in that gap.
4356
+ // Item itself stays border-free — the line is a separate visual
4357
+ // element rather than an outline on the item.
4358
+ divider && [
4359
+ "gap-1",
4360
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:relative",
4361
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:content-['']",
4362
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:absolute",
4363
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:-bottom-0.5",
4364
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:inset-x-4",
4365
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:h-px",
4366
+ "[&>[data-slot=item][data-variant=default]:not(:last-child)]:after:bg-border-subtle"
4367
+ ],
4368
+ className
4369
+ )
4321
4370
  }, props)
4322
4371
  );
4323
4372
  }