@maxsteinwender/sort-ui 1.4.0 → 1.4.1

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
@@ -67,10 +67,10 @@ Sort UI supports 4 themes built on two color schemes:
67
67
 
68
68
  | Theme | Base | Accent | Mode |
69
69
  |-------|------|--------|------|
70
- | Theme 1 Light | Zinc | Blue | `light` |
71
- | Theme 1 Dark | Zinc | Blue | `dark` |
72
- | Theme 2 Light | Neutral | Orange | `theme-2` |
73
- | Theme 2 Dark | Neutral | Orange | `theme-2-dark` |
70
+ | Default Blue Light | Zinc | Blue | `light` |
71
+ | Default Blue Dark | Zinc | Blue | `dark` |
72
+ | Neutral Violet Light | Neutral | Violet | `theme-2` |
73
+ | Neutral Violet Dark | Neutral | Violet | `theme-2-dark` |
74
74
 
75
75
  Themes are applied via CSS classes on the root element. Switch between them in Storybook using the theme toolbar.
76
76
 
package/dist/index.js CHANGED
@@ -294,7 +294,7 @@ var buttonVariants = classVarianceAuthority.cva(
294
294
  variants: {
295
295
  variant: {
296
296
  // Primary — Sort UI: bg/state/primary, text/on-primary, icon/on-primary
297
- // (on-primary is theme-aware: white everywhere except Theme 2 Dark, where the button inverts to near-white and needs dark text)
297
+ // (on-primary is theme-aware: white everywhere except Neutral Violet Dark, where the button inverts to near-white and needs dark text)
298
298
  default: "bg-sui-bg-state-primary text-sui-text-on-primary [text-shadow:var(--shadow-text)] [&_i]:text-icon-on-primary [&_i]:[text-shadow:none] [&_svg]:text-icon-on-primary [&_svg]:[text-shadow:none] shadow-button-default active:shadow-button-press [@media(hover:hover)]:hover:bg-sui-bg-state-primary-hover active:bg-sui-bg-state-primary-press disabled:bg-sui-bg-state-disabled disabled:[text-shadow:none]",
299
299
  // Soft — Sort UI: bg/state/soft, text/subtle, icon/default-muted
300
300
  secondary: "bg-sui-bg-state-soft text-sui-text-subtle [&_i]:text-icon-default-muted [&_svg]:text-icon-default-muted [@media(hover:hover)]:hover:bg-sui-bg-state-soft-hover active:bg-sui-bg-state-soft-press disabled:bg-sui-bg-state-disabled",
@@ -351,7 +351,7 @@ var buttonBadgeVariants = classVarianceAuthority.cva(
351
351
  color: {
352
352
  inverse: "bg-[rgba(255,255,255,0.1)] border-[rgba(255,255,255,0.2)] text-sui-text-white-default group-disabled:bg-transparent group-disabled:border-transparent group-disabled:text-sui-text-hint",
353
353
  // Same visual treatment as `inverse`, but theme-aware — used on the Primary
354
- // (default) button only, since that's the one that inverts in Theme 2 Dark.
354
+ // (default) button only, since that's the one that inverts in Neutral Violet Dark.
355
355
  // Destructive keeps `inverse` because its red background never inverts.
356
356
  "on-primary": "bg-[var(--overlay-on-primary)] border-[var(--overlay-on-primary-border)] text-sui-text-on-primary group-disabled:bg-transparent group-disabled:border-transparent group-disabled:text-sui-text-hint",
357
357
  neutral: "bg-transparent border-sui-border-default text-sui-text-muted group-disabled:text-sui-text-hint"
@@ -2285,6 +2285,19 @@ var LinkButton = React80__namespace.forwardRef(
2285
2285
  );
2286
2286
  const iconColor = disabled ? "text-icon-default-disabled" : variant === "informative" ? "text-icon-informative" : "text-icon-default-muted";
2287
2287
  const underlineColor = disabled ? "var(--border-darker)" : variant === "informative" ? "var(--border-informative)" : "var(--border-darker)";
2288
+ const underlineClassName = cn(
2289
+ "relative",
2290
+ "after:content-[''] after:absolute after:inset-x-0 after:h-px",
2291
+ "after:bg-[repeating-linear-gradient(90deg,var(--link-ul)_0_2px,transparent_2px_4px)]",
2292
+ underlineOffsetMap[resolvedSize]
2293
+ );
2294
+ const underlineStyle = { "--link-ul": underlineColor };
2295
+ const asChildTarget = asChild && React80__namespace.isValidElement(children) ? children : null;
2296
+ const content = asChildTarget ? /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slottable, { children: React80__namespace.cloneElement(
2297
+ asChildTarget,
2298
+ void 0,
2299
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: underlineClassName, style: underlineStyle, children: asChildTarget.props.children })
2300
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: underlineClassName, style: underlineStyle, children });
2288
2301
  return /* @__PURE__ */ jsxRuntime.jsxs(
2289
2302
  Comp,
2290
2303
  __spreadProps(__spreadValues({
@@ -2304,19 +2317,7 @@ var LinkButton = React80__namespace.forwardRef(
2304
2317
  }, props), {
2305
2318
  children: [
2306
2319
  leadIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: cn("shrink-0 text-md leading-none [&_svg]:size-4", iconColor), children: leadIcon }),
2307
- /* @__PURE__ */ jsxRuntime.jsx(
2308
- "span",
2309
- {
2310
- className: cn(
2311
- "relative",
2312
- "after:content-[''] after:absolute after:inset-x-0 after:h-px",
2313
- "after:bg-[repeating-linear-gradient(90deg,var(--link-ul)_0_2px,transparent_2px_4px)]",
2314
- underlineOffsetMap[resolvedSize]
2315
- ),
2316
- style: { "--link-ul": underlineColor },
2317
- children
2318
- }
2319
- ),
2320
+ content,
2320
2321
  tailIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: cn("shrink-0 text-md leading-none [&_svg]:size-4", iconColor), children: tailIcon })
2321
2322
  ]
2322
2323
  })
@@ -3176,7 +3177,7 @@ var CheckboxCard = React80__namespace.forwardRef(
3176
3177
  selected || isDefault ? "bg-sui-bg-card" : "bg-sui-bg-state-soft",
3177
3178
  // Border — always 1px border, use inset ring for selected highlight (no layout shift)
3178
3179
  "border",
3179
- selected ? "border-primary ring-1 ring-inset ring-primary" : disabled ? isDefault ? "border-sui-border-default" : "border-transparent" : isDefault ? "border-sui-border-darker" : "border-transparent",
3180
+ selected ? "border-informative ring-1 ring-inset ring-informative" : disabled ? isDefault ? "border-sui-border-default" : "border-transparent" : isDefault ? "border-sui-border-darker" : "border-transparent",
3180
3181
  // Shadow (only for default or selected)
3181
3182
  selected || isDefault ? disabled ? "" : "shadow-card-base" : "",
3182
3183
  // Disabled
@@ -3392,7 +3393,7 @@ var unselectedStyles = {
3392
3393
  ].join(" ")
3393
3394
  };
3394
3395
  var selectedStyles = {
3395
- // default, soft, ghost → informative accent selected (shifts blue → orange in Theme 2; bg-badge-blue has no theme-adaptive equivalent yet)
3396
+ // default, soft, ghost → informative accent selected (shifts blue → orange in Neutral Violet; bg-badge-blue has no theme-adaptive equivalent yet)
3396
3397
  default: "bg-sui-bg-badge-blue border-sui-border-blue text-sui-text-informative [&_i]:text-sui-text-informative",
3397
3398
  soft: "bg-sui-bg-badge-blue text-sui-text-informative [&_i]:text-sui-text-informative",
3398
3399
  ghost: "bg-sui-bg-badge-blue text-sui-text-informative [&_i]:text-sui-text-informative",
@@ -4430,7 +4431,7 @@ var DataRangeSlider = React80__namespace.forwardRef(
4430
4431
  /* @__PURE__ */ jsxRuntime.jsx(
4431
4432
  "div",
4432
4433
  {
4433
- className: "absolute top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
4434
+ className: "absolute top-1/2 h-1 -translate-y-1/2 bg-informative",
4434
4435
  style: { left: `${pctMin}%`, right: `${100 - pctMax}%` }
4435
4436
  }
4436
4437
  ),
@@ -6611,7 +6612,7 @@ var FileUploadArea = React80__namespace.forwardRef(
6611
6612
  "span",
6612
6613
  {
6613
6614
  className: cn(
6614
- disabled ? "text-sui-text-hint" : "text-primary"
6615
+ disabled ? "text-sui-text-hint" : "text-sui-text-informative"
6615
6616
  ),
6616
6617
  children: linkText
6617
6618
  }
@@ -6711,7 +6712,7 @@ var ProgressBar = React80__namespace.forwardRef(
6711
6712
  {
6712
6713
  className: cn(
6713
6714
  "h-1 min-h-px min-w-px flex-[1_0_0] rounded-full",
6714
- i < filledSegments ? "bg-sui-bg-basic-gray-accent" : "bg-sui-bg-basic-gray-alpha-10"
6715
+ i < filledSegments ? "bg-informative" : "bg-sui-bg-basic-gray-alpha-10"
6715
6716
  )
6716
6717
  },
6717
6718
  i
@@ -6731,7 +6732,7 @@ var ProgressBar = React80__namespace.forwardRef(
6731
6732
  children: /* @__PURE__ */ jsxRuntime.jsx(
6732
6733
  ProgressPrimitive2__namespace.Indicator,
6733
6734
  {
6734
- className: "h-full rounded-full bg-sui-bg-basic-gray-accent transition-all duration-300 ease-out",
6735
+ className: "h-full rounded-full bg-informative transition-all duration-300 ease-out",
6735
6736
  style: { width: `${clampedValue}%` }
6736
6737
  }
6737
6738
  )
@@ -7741,17 +7742,23 @@ var textBlockVariants = classVarianceAuthority.cva("flex w-full flex-col gap-1",
7741
7742
  align: "left"
7742
7743
  }
7743
7744
  });
7744
- var horizontalStepperItemVariants = classVarianceAuthority.cva("flex w-full flex-col gap-4", {
7745
- variants: {
7746
- position: {
7747
- top: "",
7748
- bottom: ""
7745
+ var horizontalStepperItemVariants = classVarianceAuthority.cva(
7746
+ [
7747
+ "flex w-full flex-col gap-4",
7748
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sui-border-highlight focus-visible:ring-offset-2 focus-visible:ring-offset-sui-bg-default focus-visible:rounded-sm"
7749
+ ].join(" "),
7750
+ {
7751
+ variants: {
7752
+ position: {
7753
+ top: "",
7754
+ bottom: ""
7755
+ }
7756
+ },
7757
+ defaultVariants: {
7758
+ position: "top"
7749
7759
  }
7750
- },
7751
- defaultVariants: {
7752
- position: "top"
7753
7760
  }
7754
- });
7761
+ );
7755
7762
  function ConnectorLine({ success }) {
7756
7763
  return /* @__PURE__ */ jsxRuntime.jsx(
7757
7764
  "div",
@@ -8397,7 +8404,7 @@ var pageItemVariants = classVarianceAuthority.cva(
8397
8404
  );
8398
8405
  var activeDefaultClasses = [
8399
8406
  "bg-sui-bg-state-ghost",
8400
- // Semantic accent tokens — shift blue → orange in Theme 2, matching the theme's accent color
8407
+ // Semantic accent tokens — shift blue → orange in Neutral Violet, matching the theme's accent color
8401
8408
  "text-sui-text-informative",
8402
8409
  "border border-sui-border-informative",
8403
8410
  "[@media(hover:hover)]:hover:bg-sui-bg-state-ghost [@media(hover:hover)]:hover:text-sui-text-informative"
@@ -8996,7 +9003,7 @@ var Progress = React80__namespace.forwardRef((_a, ref) => {
8996
9003
  children: /* @__PURE__ */ jsxRuntime.jsx(
8997
9004
  ProgressPrimitive2__namespace.Indicator,
8998
9005
  {
8999
- className: "h-full w-full flex-1 bg-primary transition-all",
9006
+ className: "h-full w-full flex-1 bg-informative transition-all",
9000
9007
  style: { transform: `translateX(-${100 - (value || 0)}%)` }
9001
9008
  }
9002
9009
  )
@@ -9022,13 +9029,13 @@ var radialProgressBarVariants = classVarianceAuthority.cva("relative inline-flex
9022
9029
  }
9023
9030
  });
9024
9031
  var textVariantMap = {
9025
- default: "text-sui-text-default",
9032
+ default: "text-sui-text-informative",
9026
9033
  success: "text-sui-text-success",
9027
9034
  failed: "text-sui-text-destructive"
9028
9035
  };
9029
9036
  var trackStrokeVar = "var(--border-default)";
9030
9037
  var arcStrokeVarMap = {
9031
- default: "var(--text-subtle)",
9038
+ default: "hsl(var(--informative))",
9032
9039
  success: "var(--text-success)",
9033
9040
  failed: "var(--text-destructive)"
9034
9041
  };
@@ -9281,7 +9288,7 @@ var radioButtonCardVariants = classVarianceAuthority.cva(
9281
9288
  // Shadow
9282
9289
  "shadow-card-base",
9283
9290
  // Selected: highlight border + ring
9284
- "data-[state=checked]:border-primary data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-primary",
9291
+ "data-[state=checked]:border-informative data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-informative",
9285
9292
  // Disabled
9286
9293
  "disabled:border-sui-border-default disabled:shadow-none"
9287
9294
  ],
@@ -9289,7 +9296,7 @@ var radioButtonCardVariants = classVarianceAuthority.cva(
9289
9296
  // Background — soft bg when unchecked, card bg when selected
9290
9297
  "bg-sui-bg-state-soft border border-transparent",
9291
9298
  // Selected: card bg + highlight border + ring
9292
- "data-[state=checked]:bg-sui-bg-card data-[state=checked]:border-primary data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-primary",
9299
+ "data-[state=checked]:bg-sui-bg-card data-[state=checked]:border-informative data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-informative",
9293
9300
  "data-[state=checked]:shadow-card-base",
9294
9301
  // Disabled
9295
9302
  "disabled:border-transparent disabled:shadow-none"
@@ -11812,7 +11819,7 @@ var Slider = React80__namespace.forwardRef(
11812
11819
  /* @__PURE__ */ jsxRuntime.jsx(
11813
11820
  "div",
11814
11821
  {
11815
- className: "absolute left-0 top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
11822
+ className: "absolute left-0 top-1/2 h-1 -translate-y-1/2 bg-informative",
11816
11823
  style: { width: `${pct}%` }
11817
11824
  }
11818
11825
  ),
@@ -12159,7 +12166,7 @@ var SliderRange = React80__namespace.forwardRef(
12159
12166
  /* @__PURE__ */ jsxRuntime.jsx(
12160
12167
  "div",
12161
12168
  {
12162
- className: "absolute top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
12169
+ className: "absolute top-1/2 h-1 -translate-y-1/2 bg-informative",
12163
12170
  style: { left: `${pctMin}%`, right: `${100 - pctMax}%` }
12164
12171
  }
12165
12172
  ),
@@ -14005,7 +14012,7 @@ var ToggleGroupItem = React80__namespace.forwardRef(
14005
14012
  "bg-sui-bg-state-ghost text-sui-text-muted [&_svg]:text-icon-default-muted",
14006
14013
  "[@media(hover:hover)]:hover:bg-sui-bg-state-ghost-hover [@media(hover:hover)]:hover:text-sui-text-subtle [@media(hover:hover)]:hover:[&_svg]:text-icon-default-subtle",
14007
14014
  "active:bg-sui-bg-state-ghost-press",
14008
- // Selected state — bg-badge-blue has no theme-adaptive equivalent yet (stays a light-blue tint in Theme 2); text/icon use the semantic informative token so they shift blue → orange
14015
+ // Selected state — bg-badge-blue has no theme-adaptive equivalent yet (stays a light-blue tint in Neutral Violet); text/icon use the semantic informative token so they shift blue → orange
14009
14016
  active && "bg-sui-bg-badge-blue text-sui-text-informative [&_svg]:text-sui-text-informative",
14010
14017
  // Disabled
14011
14018
  disabled && "opacity-50 cursor-not-allowed pointer-events-none",
@@ -14373,7 +14380,10 @@ var VerticalStepper = React80__namespace.forwardRef(
14373
14380
  "li",
14374
14381
  {
14375
14382
  "aria-current": state === "current" ? "step" : void 0,
14376
- className: onStepClick ? "cursor-pointer" : void 0,
14383
+ className: cn(
14384
+ onStepClick && "cursor-pointer",
14385
+ onStepClick && "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sui-border-highlight focus-visible:ring-offset-2 focus-visible:ring-offset-sui-bg-default focus-visible:rounded-sm"
14386
+ ),
14377
14387
  onClick: onStepClick ? () => onStepClick(index) : void 0,
14378
14388
  onKeyDown: onStepClick ? (e) => {
14379
14389
  if (e.key === "Enter" || e.key === " ") {
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
9
- import { Slot } from '@radix-ui/react-slot';
9
+ import { Slot, Slottable } from '@radix-ui/react-slot';
10
10
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
11
11
  import { getDefaultClassNames, DayPicker } from 'react-day-picker';
12
12
  import * as RechartsPrimitive from 'recharts';
@@ -251,7 +251,7 @@ var buttonVariants = cva(
251
251
  variants: {
252
252
  variant: {
253
253
  // Primary — Sort UI: bg/state/primary, text/on-primary, icon/on-primary
254
- // (on-primary is theme-aware: white everywhere except Theme 2 Dark, where the button inverts to near-white and needs dark text)
254
+ // (on-primary is theme-aware: white everywhere except Neutral Violet Dark, where the button inverts to near-white and needs dark text)
255
255
  default: "bg-sui-bg-state-primary text-sui-text-on-primary [text-shadow:var(--shadow-text)] [&_i]:text-icon-on-primary [&_i]:[text-shadow:none] [&_svg]:text-icon-on-primary [&_svg]:[text-shadow:none] shadow-button-default active:shadow-button-press [@media(hover:hover)]:hover:bg-sui-bg-state-primary-hover active:bg-sui-bg-state-primary-press disabled:bg-sui-bg-state-disabled disabled:[text-shadow:none]",
256
256
  // Soft — Sort UI: bg/state/soft, text/subtle, icon/default-muted
257
257
  secondary: "bg-sui-bg-state-soft text-sui-text-subtle [&_i]:text-icon-default-muted [&_svg]:text-icon-default-muted [@media(hover:hover)]:hover:bg-sui-bg-state-soft-hover active:bg-sui-bg-state-soft-press disabled:bg-sui-bg-state-disabled",
@@ -308,7 +308,7 @@ var buttonBadgeVariants = cva(
308
308
  color: {
309
309
  inverse: "bg-[rgba(255,255,255,0.1)] border-[rgba(255,255,255,0.2)] text-sui-text-white-default group-disabled:bg-transparent group-disabled:border-transparent group-disabled:text-sui-text-hint",
310
310
  // Same visual treatment as `inverse`, but theme-aware — used on the Primary
311
- // (default) button only, since that's the one that inverts in Theme 2 Dark.
311
+ // (default) button only, since that's the one that inverts in Neutral Violet Dark.
312
312
  // Destructive keeps `inverse` because its red background never inverts.
313
313
  "on-primary": "bg-[var(--overlay-on-primary)] border-[var(--overlay-on-primary-border)] text-sui-text-on-primary group-disabled:bg-transparent group-disabled:border-transparent group-disabled:text-sui-text-hint",
314
314
  neutral: "bg-transparent border-sui-border-default text-sui-text-muted group-disabled:text-sui-text-hint"
@@ -2242,6 +2242,19 @@ var LinkButton = React80.forwardRef(
2242
2242
  );
2243
2243
  const iconColor = disabled ? "text-icon-default-disabled" : variant === "informative" ? "text-icon-informative" : "text-icon-default-muted";
2244
2244
  const underlineColor = disabled ? "var(--border-darker)" : variant === "informative" ? "var(--border-informative)" : "var(--border-darker)";
2245
+ const underlineClassName = cn(
2246
+ "relative",
2247
+ "after:content-[''] after:absolute after:inset-x-0 after:h-px",
2248
+ "after:bg-[repeating-linear-gradient(90deg,var(--link-ul)_0_2px,transparent_2px_4px)]",
2249
+ underlineOffsetMap[resolvedSize]
2250
+ );
2251
+ const underlineStyle = { "--link-ul": underlineColor };
2252
+ const asChildTarget = asChild && React80.isValidElement(children) ? children : null;
2253
+ const content = asChildTarget ? /* @__PURE__ */ jsx(Slottable, { children: React80.cloneElement(
2254
+ asChildTarget,
2255
+ void 0,
2256
+ /* @__PURE__ */ jsx("span", { className: underlineClassName, style: underlineStyle, children: asChildTarget.props.children })
2257
+ ) }) : /* @__PURE__ */ jsx("span", { className: underlineClassName, style: underlineStyle, children });
2245
2258
  return /* @__PURE__ */ jsxs(
2246
2259
  Comp,
2247
2260
  __spreadProps(__spreadValues({
@@ -2261,19 +2274,7 @@ var LinkButton = React80.forwardRef(
2261
2274
  }, props), {
2262
2275
  children: [
2263
2276
  leadIcon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0 text-md leading-none [&_svg]:size-4", iconColor), children: leadIcon }),
2264
- /* @__PURE__ */ jsx(
2265
- "span",
2266
- {
2267
- className: cn(
2268
- "relative",
2269
- "after:content-[''] after:absolute after:inset-x-0 after:h-px",
2270
- "after:bg-[repeating-linear-gradient(90deg,var(--link-ul)_0_2px,transparent_2px_4px)]",
2271
- underlineOffsetMap[resolvedSize]
2272
- ),
2273
- style: { "--link-ul": underlineColor },
2274
- children
2275
- }
2276
- ),
2277
+ content,
2277
2278
  tailIcon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0 text-md leading-none [&_svg]:size-4", iconColor), children: tailIcon })
2278
2279
  ]
2279
2280
  })
@@ -3133,7 +3134,7 @@ var CheckboxCard = React80.forwardRef(
3133
3134
  selected || isDefault ? "bg-sui-bg-card" : "bg-sui-bg-state-soft",
3134
3135
  // Border — always 1px border, use inset ring for selected highlight (no layout shift)
3135
3136
  "border",
3136
- selected ? "border-primary ring-1 ring-inset ring-primary" : disabled ? isDefault ? "border-sui-border-default" : "border-transparent" : isDefault ? "border-sui-border-darker" : "border-transparent",
3137
+ selected ? "border-informative ring-1 ring-inset ring-informative" : disabled ? isDefault ? "border-sui-border-default" : "border-transparent" : isDefault ? "border-sui-border-darker" : "border-transparent",
3137
3138
  // Shadow (only for default or selected)
3138
3139
  selected || isDefault ? disabled ? "" : "shadow-card-base" : "",
3139
3140
  // Disabled
@@ -3349,7 +3350,7 @@ var unselectedStyles = {
3349
3350
  ].join(" ")
3350
3351
  };
3351
3352
  var selectedStyles = {
3352
- // default, soft, ghost → informative accent selected (shifts blue → orange in Theme 2; bg-badge-blue has no theme-adaptive equivalent yet)
3353
+ // default, soft, ghost → informative accent selected (shifts blue → orange in Neutral Violet; bg-badge-blue has no theme-adaptive equivalent yet)
3353
3354
  default: "bg-sui-bg-badge-blue border-sui-border-blue text-sui-text-informative [&_i]:text-sui-text-informative",
3354
3355
  soft: "bg-sui-bg-badge-blue text-sui-text-informative [&_i]:text-sui-text-informative",
3355
3356
  ghost: "bg-sui-bg-badge-blue text-sui-text-informative [&_i]:text-sui-text-informative",
@@ -4387,7 +4388,7 @@ var DataRangeSlider = React80.forwardRef(
4387
4388
  /* @__PURE__ */ jsx(
4388
4389
  "div",
4389
4390
  {
4390
- className: "absolute top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
4391
+ className: "absolute top-1/2 h-1 -translate-y-1/2 bg-informative",
4391
4392
  style: { left: `${pctMin}%`, right: `${100 - pctMax}%` }
4392
4393
  }
4393
4394
  ),
@@ -6568,7 +6569,7 @@ var FileUploadArea = React80.forwardRef(
6568
6569
  "span",
6569
6570
  {
6570
6571
  className: cn(
6571
- disabled ? "text-sui-text-hint" : "text-primary"
6572
+ disabled ? "text-sui-text-hint" : "text-sui-text-informative"
6572
6573
  ),
6573
6574
  children: linkText
6574
6575
  }
@@ -6668,7 +6669,7 @@ var ProgressBar = React80.forwardRef(
6668
6669
  {
6669
6670
  className: cn(
6670
6671
  "h-1 min-h-px min-w-px flex-[1_0_0] rounded-full",
6671
- i < filledSegments ? "bg-sui-bg-basic-gray-accent" : "bg-sui-bg-basic-gray-alpha-10"
6672
+ i < filledSegments ? "bg-informative" : "bg-sui-bg-basic-gray-alpha-10"
6672
6673
  )
6673
6674
  },
6674
6675
  i
@@ -6688,7 +6689,7 @@ var ProgressBar = React80.forwardRef(
6688
6689
  children: /* @__PURE__ */ jsx(
6689
6690
  ProgressPrimitive2.Indicator,
6690
6691
  {
6691
- className: "h-full rounded-full bg-sui-bg-basic-gray-accent transition-all duration-300 ease-out",
6692
+ className: "h-full rounded-full bg-informative transition-all duration-300 ease-out",
6692
6693
  style: { width: `${clampedValue}%` }
6693
6694
  }
6694
6695
  )
@@ -7698,17 +7699,23 @@ var textBlockVariants = cva("flex w-full flex-col gap-1", {
7698
7699
  align: "left"
7699
7700
  }
7700
7701
  });
7701
- var horizontalStepperItemVariants = cva("flex w-full flex-col gap-4", {
7702
- variants: {
7703
- position: {
7704
- top: "",
7705
- bottom: ""
7702
+ var horizontalStepperItemVariants = cva(
7703
+ [
7704
+ "flex w-full flex-col gap-4",
7705
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sui-border-highlight focus-visible:ring-offset-2 focus-visible:ring-offset-sui-bg-default focus-visible:rounded-sm"
7706
+ ].join(" "),
7707
+ {
7708
+ variants: {
7709
+ position: {
7710
+ top: "",
7711
+ bottom: ""
7712
+ }
7713
+ },
7714
+ defaultVariants: {
7715
+ position: "top"
7706
7716
  }
7707
- },
7708
- defaultVariants: {
7709
- position: "top"
7710
7717
  }
7711
- });
7718
+ );
7712
7719
  function ConnectorLine({ success }) {
7713
7720
  return /* @__PURE__ */ jsx(
7714
7721
  "div",
@@ -8354,7 +8361,7 @@ var pageItemVariants = cva(
8354
8361
  );
8355
8362
  var activeDefaultClasses = [
8356
8363
  "bg-sui-bg-state-ghost",
8357
- // Semantic accent tokens — shift blue → orange in Theme 2, matching the theme's accent color
8364
+ // Semantic accent tokens — shift blue → orange in Neutral Violet, matching the theme's accent color
8358
8365
  "text-sui-text-informative",
8359
8366
  "border border-sui-border-informative",
8360
8367
  "[@media(hover:hover)]:hover:bg-sui-bg-state-ghost [@media(hover:hover)]:hover:text-sui-text-informative"
@@ -8953,7 +8960,7 @@ var Progress = React80.forwardRef((_a, ref) => {
8953
8960
  children: /* @__PURE__ */ jsx(
8954
8961
  ProgressPrimitive2.Indicator,
8955
8962
  {
8956
- className: "h-full w-full flex-1 bg-primary transition-all",
8963
+ className: "h-full w-full flex-1 bg-informative transition-all",
8957
8964
  style: { transform: `translateX(-${100 - (value || 0)}%)` }
8958
8965
  }
8959
8966
  )
@@ -8979,13 +8986,13 @@ var radialProgressBarVariants = cva("relative inline-flex items-center justify-c
8979
8986
  }
8980
8987
  });
8981
8988
  var textVariantMap = {
8982
- default: "text-sui-text-default",
8989
+ default: "text-sui-text-informative",
8983
8990
  success: "text-sui-text-success",
8984
8991
  failed: "text-sui-text-destructive"
8985
8992
  };
8986
8993
  var trackStrokeVar = "var(--border-default)";
8987
8994
  var arcStrokeVarMap = {
8988
- default: "var(--text-subtle)",
8995
+ default: "hsl(var(--informative))",
8989
8996
  success: "var(--text-success)",
8990
8997
  failed: "var(--text-destructive)"
8991
8998
  };
@@ -9238,7 +9245,7 @@ var radioButtonCardVariants = cva(
9238
9245
  // Shadow
9239
9246
  "shadow-card-base",
9240
9247
  // Selected: highlight border + ring
9241
- "data-[state=checked]:border-primary data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-primary",
9248
+ "data-[state=checked]:border-informative data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-informative",
9242
9249
  // Disabled
9243
9250
  "disabled:border-sui-border-default disabled:shadow-none"
9244
9251
  ],
@@ -9246,7 +9253,7 @@ var radioButtonCardVariants = cva(
9246
9253
  // Background — soft bg when unchecked, card bg when selected
9247
9254
  "bg-sui-bg-state-soft border border-transparent",
9248
9255
  // Selected: card bg + highlight border + ring
9249
- "data-[state=checked]:bg-sui-bg-card data-[state=checked]:border-primary data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-primary",
9256
+ "data-[state=checked]:bg-sui-bg-card data-[state=checked]:border-informative data-[state=checked]:ring-1 data-[state=checked]:ring-inset data-[state=checked]:ring-informative",
9250
9257
  "data-[state=checked]:shadow-card-base",
9251
9258
  // Disabled
9252
9259
  "disabled:border-transparent disabled:shadow-none"
@@ -11769,7 +11776,7 @@ var Slider = React80.forwardRef(
11769
11776
  /* @__PURE__ */ jsx(
11770
11777
  "div",
11771
11778
  {
11772
- className: "absolute left-0 top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
11779
+ className: "absolute left-0 top-1/2 h-1 -translate-y-1/2 bg-informative",
11773
11780
  style: { width: `${pct}%` }
11774
11781
  }
11775
11782
  ),
@@ -12116,7 +12123,7 @@ var SliderRange = React80.forwardRef(
12116
12123
  /* @__PURE__ */ jsx(
12117
12124
  "div",
12118
12125
  {
12119
- className: "absolute top-1/2 h-1 -translate-y-1/2 bg-sui-bg-basic-gray-accent",
12126
+ className: "absolute top-1/2 h-1 -translate-y-1/2 bg-informative",
12120
12127
  style: { left: `${pctMin}%`, right: `${100 - pctMax}%` }
12121
12128
  }
12122
12129
  ),
@@ -13962,7 +13969,7 @@ var ToggleGroupItem = React80.forwardRef(
13962
13969
  "bg-sui-bg-state-ghost text-sui-text-muted [&_svg]:text-icon-default-muted",
13963
13970
  "[@media(hover:hover)]:hover:bg-sui-bg-state-ghost-hover [@media(hover:hover)]:hover:text-sui-text-subtle [@media(hover:hover)]:hover:[&_svg]:text-icon-default-subtle",
13964
13971
  "active:bg-sui-bg-state-ghost-press",
13965
- // Selected state — bg-badge-blue has no theme-adaptive equivalent yet (stays a light-blue tint in Theme 2); text/icon use the semantic informative token so they shift blue → orange
13972
+ // Selected state — bg-badge-blue has no theme-adaptive equivalent yet (stays a light-blue tint in Neutral Violet); text/icon use the semantic informative token so they shift blue → orange
13966
13973
  active && "bg-sui-bg-badge-blue text-sui-text-informative [&_svg]:text-sui-text-informative",
13967
13974
  // Disabled
13968
13975
  disabled && "opacity-50 cursor-not-allowed pointer-events-none",
@@ -14330,7 +14337,10 @@ var VerticalStepper = React80.forwardRef(
14330
14337
  "li",
14331
14338
  {
14332
14339
  "aria-current": state === "current" ? "step" : void 0,
14333
- className: onStepClick ? "cursor-pointer" : void 0,
14340
+ className: cn(
14341
+ onStepClick && "cursor-pointer",
14342
+ onStepClick && "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sui-border-highlight focus-visible:ring-offset-2 focus-visible:ring-offset-sui-bg-default focus-visible:rounded-sm"
14343
+ ),
14334
14344
  onClick: onStepClick ? () => onStepClick(index) : void 0,
14335
14345
  onKeyDown: onStepClick ? (e) => {
14336
14346
  if (e.key === "Enter" || e.key === " ") {
package/dist/styles.css CHANGED
@@ -13621,7 +13621,7 @@ video {
13621
13621
  display: none;
13622
13622
  }
13623
13623
 
13624
- /* ===== Sort UI Theme 1 — Light ===== */
13624
+ /* ===== Sort UI Default Blue — Light ===== */
13625
13625
 
13626
13626
  :root {
13627
13627
  --background: 0 0% 100%;
@@ -13930,7 +13930,7 @@ video {
13930
13930
  --sidebar-accent-foreground: 240 10.5% 7.5%;
13931
13931
  --sidebar-border: 240 5.9% 90%;
13932
13932
  --sidebar-ring: 221 96.9% 62.5%;
13933
- /* === GENERATED TOKENS START === Theme-1-Light */
13933
+ /* === GENERATED TOKENS START === Default-Blue-Light */
13934
13934
  /* icon tokens */
13935
13935
  --icon-default: #111115;
13936
13936
  --icon-default-subtle: #4e4e55;
@@ -14191,7 +14191,7 @@ video {
14191
14191
  --focus-ring-offset: 1px;
14192
14192
  }
14193
14193
 
14194
- /* ===== Sort UI Theme 1 — Dark ===== */
14194
+ /* ===== Sort UI Default Blue — Dark ===== */
14195
14195
 
14196
14196
  .dark {
14197
14197
  --background: 240 5.9% 10%;
@@ -14246,7 +14246,7 @@ video {
14246
14246
  --sidebar-accent-foreground: 0 0% 100%;
14247
14247
  --sidebar-border: 240 3.7% 20%;
14248
14248
  --sidebar-ring: 225 89.3% 56.1%;
14249
- /* === GENERATED TOKENS START === Theme-1-Dark */
14249
+ /* === GENERATED TOKENS START === Default-Blue-Dark */
14250
14250
  /* icon tokens */
14251
14251
  --icon-default: #ffffff;
14252
14252
  --icon-default-subtle: rgba(255, 255, 255, 0.7);
@@ -14488,9 +14488,9 @@ video {
14488
14488
  /* === GENERATED TOKENS END === */
14489
14489
  }
14490
14490
 
14491
- /* ===== Sort UI Theme 2 — Light ===== */
14491
+ /* ===== Sort UI Neutral Violet — Light ===== */
14492
14492
 
14493
- /* Structurally identical to Theme 1 Light — see docs/superpowers/specs/2026-07-06-theme-2-neutral-violet-redesign-design.md.
14493
+ /* Structurally identical to Default Blue Light — see docs/superpowers/specs/2026-07-06-theme-2-neutral-violet-redesign-design.md.
14494
14494
  Only two deviations: Primary Button is zinc/black (Group A), accent is violet instead of blue (Group B). */
14495
14495
 
14496
14496
  .theme-2 {
@@ -14533,7 +14533,7 @@ video {
14533
14533
  --text-subtle: 240 4.2% 26%;
14534
14534
  --text-muted: 240 3.5% 45.1%;
14535
14535
  --text-hint: 240 2.5% 62%;
14536
- /* Chart Colors — same palette as Theme 1, chart-1 swapped to violet */
14536
+ /* Chart Colors — same palette as Default Blue, chart-1 swapped to violet */
14537
14537
  --chart-1: 258 90% 66%;
14538
14538
  --chart-2: 129 51.1% 54.3%;
14539
14539
  --chart-3: 26 89.6% 51.2%;
@@ -14548,7 +14548,7 @@ video {
14548
14548
  --sidebar-accent-foreground: 240 10.5% 7.5%;
14549
14549
  --sidebar-border: 240 5.9% 90%;
14550
14550
  --sidebar-ring: 258 90% 66%;
14551
- /* === GENERATED TOKENS START === Theme-2-Light */
14551
+ /* === GENERATED TOKENS START === Neutral-Violet-Light */
14552
14552
  /* icon tokens */
14553
14553
  --icon-default: #111115;
14554
14554
  --icon-default-subtle: #4e4e55;
@@ -14788,9 +14788,9 @@ video {
14788
14788
  /* === GENERATED TOKENS END === */
14789
14789
  }
14790
14790
 
14791
- /* ===== Sort UI Theme 2 — Dark ===== */
14791
+ /* ===== Sort UI Neutral Violet — Dark ===== */
14792
14792
 
14793
- /* Structurally identical to Theme 1 Dark — see docs/superpowers/specs/2026-07-06-theme-2-neutral-violet-redesign-design.md.
14793
+ /* Structurally identical to Default Blue Dark — see docs/superpowers/specs/2026-07-06-theme-2-neutral-violet-redesign-design.md.
14794
14794
  Group A — Primary Button is INVERTED (near-white bg, dark text via --text-on-primary/--icon-on-primary).
14795
14795
  Group B — accent is violet instead of orange. */
14796
14796
 
@@ -14832,7 +14832,7 @@ video {
14832
14832
  --text-subtle: 240 3% 75%;
14833
14833
  --text-muted: 240 5% 64.9%;
14834
14834
  --text-hint: 240 3% 50%;
14835
- /* Chart Colors — same palette as Theme 1, chart-1 swapped to violet */
14835
+ /* Chart Colors — same palette as Default Blue, chart-1 swapped to violet */
14836
14836
  --chart-1: 252 89% 71%;
14837
14837
  --chart-2: 132 62.8% 63.1%;
14838
14838
  --chart-3: 28 88.7% 58.2%;
@@ -14847,7 +14847,7 @@ video {
14847
14847
  --sidebar-accent-foreground: 0 0% 100%;
14848
14848
  --sidebar-border: 240 3.7% 20%;
14849
14849
  --sidebar-ring: 252 89% 71%;
14850
- /* === GENERATED TOKENS START === Theme-2-Dark */
14850
+ /* === GENERATED TOKENS START === Neutral-Violet-Dark */
14851
14851
  /* icon tokens */
14852
14852
  --icon-default: #ffffff;
14853
14853
  --icon-default-subtle: rgba(255, 255, 255, 0.7);
@@ -15089,7 +15089,7 @@ video {
15089
15089
 
15090
15090
  /* ===== Sort UI Font Family Mode — Font B ===== */
15091
15091
 
15092
- /* Independent of color theme — combine freely with Theme-1 or Theme-2 */
15092
+ /* Independent of color theme — combine freely with Default Blue or Neutral Violet */
15093
15093
 
15094
15094
  .font-b {
15095
15095
  --font-headline: var(--font-geist-sans);
@@ -17542,8 +17542,8 @@ button,
17542
17542
  border-color: hsl(var(--destructive) / 0.5);
17543
17543
  }
17544
17544
 
17545
- .border-primary {
17546
- border-color: hsl(var(--primary));
17545
+ .border-informative {
17546
+ border-color: hsl(var(--informative));
17547
17547
  }
17548
17548
 
17549
17549
  .border-sidebar-border {
@@ -19621,6 +19621,10 @@ button,
19621
19621
  --tw-ring-inset: inset;
19622
19622
  }
19623
19623
 
19624
+ .ring-informative {
19625
+ --tw-ring-color: hsl(var(--informative));
19626
+ }
19627
+
19624
19628
  .ring-primary {
19625
19629
  --tw-ring-color: hsl(var(--primary));
19626
19630
  }
@@ -21226,8 +21230,8 @@ button,
21226
21230
  border-color: var(--border-accent);
21227
21231
  }
21228
21232
 
21229
- .data-\[state\=checked\]\:border-primary[data-state="checked"] {
21230
- border-color: hsl(var(--primary));
21233
+ .data-\[state\=checked\]\:border-informative[data-state="checked"] {
21234
+ border-color: hsl(var(--informative));
21231
21235
  }
21232
21236
 
21233
21237
  .data-\[state\=checked\]\:border-sui-bg-checkbox-active[data-state="checked"] {
@@ -21473,8 +21477,8 @@ button,
21473
21477
  --tw-ring-inset: inset;
21474
21478
  }
21475
21479
 
21476
- .data-\[state\=checked\]\:ring-primary[data-state="checked"] {
21477
- --tw-ring-color: hsl(var(--primary));
21480
+ .data-\[state\=checked\]\:ring-informative[data-state="checked"] {
21481
+ --tw-ring-color: hsl(var(--informative));
21478
21482
  }
21479
21483
 
21480
21484
  .data-\[swipe\=move\]\:transition-none[data-swipe="move"] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxsteinwender/sort-ui",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "A coded design system based on Sort UI Kit — Figma components as production-ready Next.js/Tailwind components",
5
5
  "author": "Max Steinwender",
6
6
  "license": "UNLICENSED",