@nextlyhq/ui 0.0.2-alpha.35 → 0.0.2-alpha.37

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/dist/index.cjs CHANGED
@@ -66,9 +66,15 @@ var buttonVariants = classVarianceAuthority.cva(
66
66
  variant: {
67
67
  default: "bg-primary text-primary-foreground border border-transparent hover:opacity-90",
68
68
  primary: "bg-primary text-primary-foreground border border-transparent hover:opacity-90",
69
- destructive: "bg-destructive text-destructive-foreground border border-transparent hover:opacity-90",
70
- outline: "border border-primary/10 text-foreground hover-unified bg-background",
71
- secondary: "bg-background border border-primary/10 text-foreground hover:bg-primary/5",
69
+ // Solid fill uses the emphasis token so white on-color text stays AA in
70
+ // dark mode (the base token is the readable text color, too light here).
71
+ // Hover darkens to a deeper shade instead of opacity-90, which would
72
+ // composite the fill toward the page and drop white text under 4.5:1.
73
+ destructive: "bg-destructive-solid text-destructive-foreground border border-transparent hover:bg-destructive-700",
74
+ // border-border (not a faint primary alpha) so the outline is a visible
75
+ // boundary at the 3:1 UI minimum.
76
+ outline: "border border-border text-foreground hover-unified bg-background",
77
+ secondary: "bg-background border border-border text-foreground hover:bg-primary/5",
72
78
  ghost: "text-foreground border border-transparent hover-unified",
73
79
  link: "text-primary border border-transparent underline-offset-4 hover:underline"
74
80
  },
@@ -151,7 +157,9 @@ var Textarea = React6.forwardRef(({ className, ...props }, ref) => {
151
157
  {
152
158
  "data-slot": "textarea",
153
159
  className: cn(
154
- "flex min-h-[80px] w-full rounded-none border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground placeholder:opacity-50 transition-all duration-200 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary/30 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 resize-y",
160
+ // hover:border-primary (full strength) keeps the hover boundary more
161
+ // visible than the resting border-input, not a fainter alpha of it.
162
+ "flex min-h-[80px] w-full rounded-none border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground placeholder:opacity-50 transition-all duration-200 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 resize-y",
155
163
  "aria-invalid:border-destructive aria-invalid:focus:border-destructive!",
156
164
  className
157
165
  ),
@@ -404,15 +412,71 @@ var CardFooter = React6.forwardRef(
404
412
  }
405
413
  );
406
414
  CardFooter.displayName = "CardFooter";
415
+ var GAP = {
416
+ 0: "gap-0",
417
+ 1: "gap-1",
418
+ 2: "gap-2",
419
+ 3: "gap-3",
420
+ 4: "gap-4",
421
+ 6: "gap-6",
422
+ 8: "gap-8"
423
+ };
424
+ var COLS = {
425
+ 1: "grid-cols-1",
426
+ 2: "grid-cols-2",
427
+ 3: "grid-cols-3",
428
+ 4: "grid-cols-4",
429
+ 6: "grid-cols-6"
430
+ };
431
+ var Stack = React6.forwardRef(
432
+ ({ direction = "col", gap = 4, className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
433
+ "div",
434
+ {
435
+ ref,
436
+ className: cn(
437
+ "flex",
438
+ direction === "col" ? "flex-col" : "flex-row",
439
+ GAP[gap],
440
+ className
441
+ ),
442
+ ...props
443
+ }
444
+ )
445
+ );
446
+ Stack.displayName = "Stack";
447
+ var Grid = React6.forwardRef(
448
+ ({ cols = 2, gap = 4, className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
449
+ "div",
450
+ {
451
+ ref,
452
+ className: cn("grid", COLS[cols], GAP[gap], className),
453
+ ...props
454
+ }
455
+ )
456
+ );
457
+ Grid.displayName = "Grid";
458
+ var Stat = React6.forwardRef(
459
+ ({ label, value, className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("flex flex-col gap-1", className), ...props, children: [
460
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: label }),
461
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl font-semibold text-foreground", children: value })
462
+ ] })
463
+ );
464
+ Stat.displayName = "Stat";
407
465
  var alertVariants = classVarianceAuthority.cva(
408
466
  "relative flex items-start gap-3 rounded-none border border-border p-4 text-sm transition-colors duration-150",
409
467
  {
410
468
  variants: {
411
469
  variant: {
412
- info: "border-border bg-primary/5 text-primary dark:border-primary/30 dark:bg-primary/5 dark:text-primary-foreground/90",
413
- success: "border-success-200 bg-success-50 text-success-900 border-l-4 border-l-success dark:border-success-900 dark:bg-success-950 dark:text-success-100",
414
- warning: "border-warning-200 bg-warning-50 text-warning-900 border-l-4 border-l-warning dark:border-warning-900 dark:bg-warning-950 dark:text-warning-100",
415
- destructive: "border-destructive-200 bg-destructive-50 text-destructive-900 border-l-4 border-l-destructive dark:border-destructive-900 dark:bg-destructive-950 dark:text-destructive-100"
470
+ // text-primary is mode-correct (dark ink on light in light mode, light
471
+ // ink on dark in dark mode); the previous dark text override rendered
472
+ // dark slate on the dark tint at about 1:1.
473
+ info: "bg-primary/5 text-primary",
474
+ // dark:border-l-* re-asserts the strong base accent on the left after
475
+ // the dark:border-*-900 all-sides rule, so the meaningful accent stays
476
+ // visible in dark mode instead of collapsing to the faint -900 shade.
477
+ success: "border-success-200 bg-success-50 text-success-900 border-l-4 border-l-success dark:border-success-900 dark:border-l-success dark:bg-success-950 dark:text-success-100",
478
+ warning: "border-warning-200 bg-warning-50 text-warning-900 border-l-4 border-l-warning dark:border-warning-900 dark:border-l-warning dark:bg-warning-950 dark:text-warning-100",
479
+ destructive: "border-destructive-200 bg-destructive-50 text-destructive-900 border-l-4 border-l-destructive dark:border-destructive-900 dark:border-l-destructive dark:bg-destructive-950 dark:text-destructive-100"
416
480
  }
417
481
  },
418
482
  defaultVariants: {
@@ -562,22 +626,9 @@ var Checkbox = React6.forwardRef(({ className, indeterminate, ...props }, ref) =
562
626
  ref,
563
627
  "data-slot": "checkbox",
564
628
  className: cn(
565
- // Unchecked outline uses primary/50: measured 3.95:1 on the light row and
566
- // 5.32:1 on the dark one. WCAG 1.4.11 asks 3:1 of a control's boundary and
567
- // the earlier values did not reach it primary/40 came out at 2.85, close
568
- // enough to look deliberate and still short. Callers must not override the
569
- // border: passing `border-border` puts the divider token here, which
570
- // measured 1.35:1 and 1.14:1, and a divider is meant to go unnoticed.
571
- // Checked and indeterminate share the filled appearance; declaring both
572
- // here keeps the control self-sufficient without host overrides.
573
- //
574
- // The box stays 16px and the target does not: `before` stretches an
575
- // invisible 24px square from the centre, which is WCAG 2.5.8's floor.
576
- // The exemption for a bare browser checkbox does not cover a styled one,
577
- // and this is styled. Growing the box instead would make every dense
578
- // table heavier for a rule about pointers, so the box and the thing you
579
- // can hit are allowed to differ.
580
- "peer relative h-4 w-4 shrink-0 rounded-none border border-primary/50 ring-offset-background before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary transition-all duration-200",
629
+ // Resting border uses border-input (a visible 3:1 boundary); the checked
630
+ // state switches to border-primary below, keeping the two states distinct.
631
+ "peer relative h-4 w-4 shrink-0 rounded-none border border-input ring-offset-background before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary transition-all duration-200",
581
632
  className
582
633
  ),
583
634
  ...props,
@@ -612,7 +663,9 @@ var RadioGroupItem = React6.forwardRef(({ className, ...props }, ref) => {
612
663
  className: cn(
613
664
  // Unchecked outline uses primary/40 (clearly visible) instead of primary/5
614
665
  // (~5% opacity, effectively invisible); hover strengthens above the resting state.
615
- "peer h-4 w-4 shrink-0 rounded-none border border-primary/40 bg-background cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 hover:border-primary/70 data-[state=checked]:border-primary data-[state=checked]:border-[5px]",
666
+ // Resting border uses border-input (a visible 3:1 boundary); the checked
667
+ // state switches to border-primary below, keeping the two states distinct.
668
+ "peer h-4 w-4 shrink-0 rounded-none border border-input bg-background cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none focus-visible:outline-none aria-invalid:border-destructive aria-invalid:focus:border-destructive! aria-invalid:focus-visible:border-destructive! disabled:cursor-not-allowed disabled:opacity-50 hover:border-primary/70 data-[state=checked]:border-primary data-[state=checked]:border-[5px]",
616
669
  className
617
670
  ),
618
671
  ...props,
@@ -795,7 +848,7 @@ var TabsTrigger = React6.forwardRef(
795
848
  ref,
796
849
  "data-slot": "tabs-trigger",
797
850
  className: cn(
798
- "inline-flex items-center justify-center whitespace-nowrap rounded-none bg-transparent px-4 py-2 text-sm font-medium cursor-pointer transition-all duration-200 border-b-2 relative -mb-0.5 data-[state=active]:border-b-primary! data-[state=active]:text-primary data-[state=inactive]:border-transparent data-[state=inactive]:text-muted-foreground hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed",
851
+ "inline-flex items-center justify-center whitespace-nowrap rounded-none bg-transparent px-4 py-2 text-sm font-medium cursor-pointer transition-all duration-200 border-b-2 relative -mb-0.5 data-[state=active]:border-b-primary! data-[state=active]:text-primary data-[state=inactive]:border-transparent data-[state=inactive]:text-muted-foreground hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed",
799
852
  className
800
853
  ),
801
854
  ...props
@@ -810,7 +863,7 @@ var TabsContent = React6.forwardRef(
810
863
  ref,
811
864
  "data-slot": "tabs-content",
812
865
  className: cn(
813
- "mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20 focus-visible:ring-offset-2",
866
+ "mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
814
867
  className
815
868
  ),
816
869
  ...props
@@ -1208,7 +1261,9 @@ function SelectValue({
1208
1261
  return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Value, { "data-slot": "select-value", ...props });
1209
1262
  }
1210
1263
  var selectTriggerVariants = classVarianceAuthority.cva(
1211
- "flex w-full items-center justify-between gap-2 rounded-none border border-input bg-background px-3 text-sm text-foreground cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary/30 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 data-[placeholder]:text-muted-foreground aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:border-destructive! [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
1264
+ // hover:border-primary (full strength) keeps the hover boundary more visible
1265
+ // than the resting border-input, not a fainter alpha of it.
1266
+ "flex w-full items-center justify-between gap-2 rounded-none border border-input bg-background px-3 text-sm text-foreground cursor-pointer transition-all duration-150 focus:border-primary! focus-visible:border-primary! focus:outline-none hover:border-primary disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-primary/5 data-[placeholder]:text-muted-foreground aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:border-destructive! [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
1212
1267
  {
1213
1268
  variants: {
1214
1269
  size: {
@@ -1819,7 +1874,7 @@ function TableSearch({
1819
1874
  {
1820
1875
  type: "button",
1821
1876
  onClick: onClear,
1822
- className: "text-muted-foreground/60 hover:text-foreground transition-colors p-0.5 rounded-none hover:bg-primary/5",
1877
+ className: "text-muted-foreground hover:text-foreground transition-colors p-0.5 rounded-none hover:bg-primary/5",
1823
1878
  "aria-label": "Clear search",
1824
1879
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
1825
1880
  }
@@ -1891,6 +1946,19 @@ var TableSkeleton = ({
1891
1946
  TableSkeleton.displayName = "TableSkeleton";
1892
1947
 
1893
1948
  // src/tailwind-preset.ts
1949
+ var statusScale = (base) => ({
1950
+ 50: `color-mix(in srgb, var(${base}), white 95%)`,
1951
+ 100: `color-mix(in srgb, var(${base}), white 90%)`,
1952
+ 200: `color-mix(in srgb, var(${base}), white 70%)`,
1953
+ 300: `color-mix(in srgb, var(${base}), white 50%)`,
1954
+ 400: `color-mix(in srgb, var(${base}), white 30%)`,
1955
+ 500: `var(${base})`,
1956
+ 600: `color-mix(in srgb, var(${base}), black 10%)`,
1957
+ 700: `color-mix(in srgb, var(${base}), black 30%)`,
1958
+ 800: `color-mix(in srgb, var(${base}), black 50%)`,
1959
+ 900: `color-mix(in srgb, var(${base}), black 70%)`,
1960
+ 950: `color-mix(in srgb, var(${base}), black 85%)`
1961
+ });
1894
1962
  var uiPreset = {
1895
1963
  theme: {
1896
1964
  extend: {
@@ -1910,15 +1978,21 @@ var uiPreset = {
1910
1978
  },
1911
1979
  destructive: {
1912
1980
  DEFAULT: "var(--nx-destructive)",
1913
- foreground: "var(--nx-destructive-foreground)"
1981
+ // Saturated fill for solid buttons, distinct from the text-tuned base.
1982
+ solid: "var(--nx-destructive-solid)",
1983
+ foreground: "var(--nx-destructive-foreground)",
1984
+ ...statusScale("--nx-destructive")
1914
1985
  },
1915
1986
  success: {
1916
1987
  DEFAULT: "var(--nx-success)",
1917
- foreground: "var(--nx-success-foreground)"
1988
+ solid: "var(--nx-success-solid)",
1989
+ foreground: "var(--nx-success-foreground)",
1990
+ ...statusScale("--nx-success")
1918
1991
  },
1919
1992
  warning: {
1920
1993
  DEFAULT: "var(--nx-warning)",
1921
- foreground: "var(--nx-warning-foreground)"
1994
+ foreground: "var(--nx-warning-foreground)",
1995
+ ...statusScale("--nx-warning")
1922
1996
  },
1923
1997
  muted: {
1924
1998
  DEFAULT: "var(--nx-muted)",
@@ -2034,6 +2108,7 @@ exports.DropdownMenuSubContent = DropdownMenuSubContent;
2034
2108
  exports.DropdownMenuSubTrigger = DropdownMenuSubTrigger;
2035
2109
  exports.DropdownMenuTrigger = DropdownMenuTrigger;
2036
2110
  exports.FormLabelWithTooltip = FormLabelWithTooltip;
2111
+ exports.Grid = Grid;
2037
2112
  exports.Input = Input;
2038
2113
  exports.Label = Label;
2039
2114
  exports.Popover = Popover;
@@ -2067,6 +2142,8 @@ exports.SheetTitle = SheetTitle;
2067
2142
  exports.SheetTrigger = SheetTrigger;
2068
2143
  exports.Skeleton = Skeleton;
2069
2144
  exports.Spinner = Spinner;
2145
+ exports.Stack = Stack;
2146
+ exports.Stat = Stat;
2070
2147
  exports.Switch = Switch;
2071
2148
  exports.Table = Table;
2072
2149
  exports.TableBody = TableBody;