@saasflare/ui 3.1.0 → 3.1.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.
@@ -19,11 +19,11 @@ var buttonVariants = cva(
19
19
  variants: {
20
20
  variant: {
21
21
  solid: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-xs hover:brightness-110 dark:hover:brightness-125",
22
- soft: "bg-[var(--intent)]/15 text-[var(--intent)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
23
- outline: "border border-[var(--intent)]/30 text-[var(--intent)] shadow-xs hover:bg-[var(--intent)]/10 dark:border-[var(--intent)]/40 dark:hover:bg-[var(--intent)]/15",
24
- ghost: "text-[var(--intent)] hover:bg-[var(--intent)]/10 dark:hover:bg-[var(--intent)]/15",
25
- link: "text-[var(--intent)] underline-offset-4 hover:underline",
26
- glass: "bg-[var(--glass-bg)] text-[var(--intent)] border border-[var(--glass-border)] backdrop-blur-lg shadow-[var(--glass-shadow)] hover:bg-[var(--glass-bg-hover)] hover:border-[var(--glass-border-hover)]",
22
+ soft: "bg-[var(--intent)]/15 text-[var(--intent-text)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
23
+ outline: "border border-[var(--intent-text)]/30 text-[var(--intent-text)] shadow-xs hover:bg-[var(--intent-text)]/10 dark:border-[var(--intent-text)]/40 dark:hover:bg-[var(--intent-text)]/15",
24
+ ghost: "text-[var(--intent-text)] hover:bg-[var(--intent-text)]/10 dark:hover:bg-[var(--intent-text)]/15",
25
+ link: "text-[var(--intent-text)] underline-offset-4 hover:underline",
26
+ glass: "bg-[var(--glass-bg)] text-[var(--intent-text)] border border-[var(--glass-border)] backdrop-blur-lg shadow-[var(--glass-shadow)] hover:bg-[var(--glass-bg-hover)] hover:border-[var(--glass-border-hover)]",
27
27
  shadow: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-[var(--btn-shadow)] hover:shadow-[var(--btn-shadow-hover)] hover:brightness-110 dark:hover:brightness-125"
28
28
  },
29
29
  size: {
@@ -41,11 +41,11 @@ var buttonVariants = classVarianceAuthority.cva(
41
41
  variants: {
42
42
  variant: {
43
43
  solid: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-xs hover:brightness-110 dark:hover:brightness-125",
44
- soft: "bg-[var(--intent)]/15 text-[var(--intent)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
45
- outline: "border border-[var(--intent)]/30 text-[var(--intent)] shadow-xs hover:bg-[var(--intent)]/10 dark:border-[var(--intent)]/40 dark:hover:bg-[var(--intent)]/15",
46
- ghost: "text-[var(--intent)] hover:bg-[var(--intent)]/10 dark:hover:bg-[var(--intent)]/15",
47
- link: "text-[var(--intent)] underline-offset-4 hover:underline",
48
- glass: "bg-[var(--glass-bg)] text-[var(--intent)] border border-[var(--glass-border)] backdrop-blur-lg shadow-[var(--glass-shadow)] hover:bg-[var(--glass-bg-hover)] hover:border-[var(--glass-border-hover)]",
44
+ soft: "bg-[var(--intent)]/15 text-[var(--intent-text)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
45
+ outline: "border border-[var(--intent-text)]/30 text-[var(--intent-text)] shadow-xs hover:bg-[var(--intent-text)]/10 dark:border-[var(--intent-text)]/40 dark:hover:bg-[var(--intent-text)]/15",
46
+ ghost: "text-[var(--intent-text)] hover:bg-[var(--intent-text)]/10 dark:hover:bg-[var(--intent-text)]/15",
47
+ link: "text-[var(--intent-text)] underline-offset-4 hover:underline",
48
+ glass: "bg-[var(--glass-bg)] text-[var(--intent-text)] border border-[var(--glass-border)] backdrop-blur-lg shadow-[var(--glass-shadow)] hover:bg-[var(--glass-bg-hover)] hover:border-[var(--glass-border-hover)]",
49
49
  shadow: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-[var(--btn-shadow)] hover:shadow-[var(--btn-shadow-hover)] hover:brightness-110 dark:hover:brightness-125"
50
50
  },
51
51
  size: {
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkDNLCSV5M_js = require('../chunk-DNLCSV5M.js');
4
+ var chunkNPNSPYTX_js = require('../chunk-NPNSPYTX.js');
5
5
  require('../chunk-FT66KYRN.js');
6
6
  var chunkD5LKWKG7_js = require('../chunk-D5LKWKG7.js');
7
7
  var React = require('react');
@@ -75,12 +75,12 @@ function Calendar({
75
75
  defaultClassNames.nav
76
76
  ),
77
77
  button_previous: chunkD5LKWKG7_js.cn(
78
- chunkDNLCSV5M_js.buttonVariants({ variant: buttonVariant }),
78
+ chunkNPNSPYTX_js.buttonVariants({ variant: buttonVariant }),
79
79
  "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
80
80
  defaultClassNames.button_previous
81
81
  ),
82
82
  button_next: chunkD5LKWKG7_js.cn(
83
- chunkDNLCSV5M_js.buttonVariants({ variant: buttonVariant }),
83
+ chunkNPNSPYTX_js.buttonVariants({ variant: buttonVariant }),
84
84
  "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
85
85
  defaultClassNames.button_next
86
86
  ),
@@ -195,7 +195,7 @@ function CalendarDayButton({
195
195
  if (modifiers.focused) ref.current?.focus();
196
196
  }, [modifiers.focused]);
197
197
  return /* @__PURE__ */ jsxRuntime.jsx(
198
- chunkDNLCSV5M_js.Button,
198
+ chunkNPNSPYTX_js.Button,
199
199
  {
200
200
  ref,
201
201
  variant: "ghost",
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { buttonVariants, Button } from '../chunk-WPOOC2FX.mjs';
2
+ import { buttonVariants, Button } from '../chunk-56PMDC5F.mjs';
3
3
  import '../chunk-EJHYM2HP.mjs';
4
4
  import { useSaasflareProps, cn } from '../chunk-WRONFPRI.mjs';
5
5
  import * as React from 'react';
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkDNLCSV5M_js = require('../chunk-DNLCSV5M.js');
4
+ var chunkNPNSPYTX_js = require('../chunk-NPNSPYTX.js');
5
5
  require('../chunk-FT66KYRN.js');
6
6
  var chunkD5LKWKG7_js = require('../chunk-D5LKWKG7.js');
7
7
  var React = require('react');
@@ -176,7 +176,7 @@ function CarouselPrevious({
176
176
  }) {
177
177
  const { orientation, scrollPrev, canScrollPrev } = useCarousel();
178
178
  return /* @__PURE__ */ jsxRuntime.jsxs(
179
- chunkDNLCSV5M_js.Button,
179
+ chunkNPNSPYTX_js.Button,
180
180
  {
181
181
  "data-slot": "carousel-previous",
182
182
  variant,
@@ -204,7 +204,7 @@ function CarouselNext({
204
204
  }) {
205
205
  const { orientation, scrollNext, canScrollNext } = useCarousel();
206
206
  return /* @__PURE__ */ jsxRuntime.jsxs(
207
- chunkDNLCSV5M_js.Button,
207
+ chunkNPNSPYTX_js.Button,
208
208
  {
209
209
  "data-slot": "carousel-next",
210
210
  variant,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { Button } from '../chunk-WPOOC2FX.mjs';
2
+ import { Button } from '../chunk-56PMDC5F.mjs';
3
3
  import '../chunk-EJHYM2HP.mjs';
4
4
  import { useSaasflareProps, cn } from '../chunk-WRONFPRI.mjs';
5
5
  import * as React from 'react';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkDNLCSV5M_js = require('./chunk-DNLCSV5M.js');
4
+ var chunkNPNSPYTX_js = require('./chunk-NPNSPYTX.js');
5
5
  var chunk4BOMMZEY_js = require('./chunk-4BOMMZEY.js');
6
6
  var chunkFT66KYRN_js = require('./chunk-FT66KYRN.js');
7
7
  var chunkD5LKWKG7_js = require('./chunk-D5LKWKG7.js');
@@ -436,7 +436,7 @@ function AlertDialogAction({
436
436
  AlertDialogPrimitive__namespace.Action,
437
437
  {
438
438
  "data-intent": "primary",
439
- className: chunkD5LKWKG7_js.cn(chunkDNLCSV5M_js.buttonVariants({ variant: "solid" }), className),
439
+ className: chunkD5LKWKG7_js.cn(chunkNPNSPYTX_js.buttonVariants({ variant: "solid" }), className),
440
440
  ...props
441
441
  }
442
442
  );
@@ -449,7 +449,7 @@ function AlertDialogCancel({
449
449
  AlertDialogPrimitive__namespace.Cancel,
450
450
  {
451
451
  "data-intent": "neutral",
452
- className: chunkD5LKWKG7_js.cn(chunkDNLCSV5M_js.buttonVariants({ variant: "outline" }), className),
452
+ className: chunkD5LKWKG7_js.cn(chunkNPNSPYTX_js.buttonVariants({ variant: "outline" }), className),
453
453
  ...props
454
454
  }
455
455
  );
@@ -861,8 +861,8 @@ var badgeVariants = classVarianceAuthority.cva(
861
861
  variants: {
862
862
  variant: {
863
863
  solid: "bg-[var(--intent)] text-[var(--intent-fg)] [a&]:hover:brightness-110",
864
- soft: "bg-[var(--intent)]/15 text-[var(--intent)] [a&]:hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
865
- outline: "border-[var(--intent)]/30 text-[var(--intent)] [a&]:hover:bg-[var(--intent)]/10"
864
+ soft: "bg-[var(--intent)]/15 text-[var(--intent-text)] [a&]:hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
865
+ outline: "border-[var(--intent-text)]/30 text-[var(--intent-text)] [a&]:hover:bg-[var(--intent-text)]/10"
866
866
  },
867
867
  size: {
868
868
  sm: "px-1.5 py-px text-[10px]",
@@ -4807,7 +4807,7 @@ function InputGroupButton({
4807
4807
  ...props
4808
4808
  }) {
4809
4809
  return /* @__PURE__ */ jsxRuntime.jsx(
4810
- chunkDNLCSV5M_js.Button,
4810
+ chunkNPNSPYTX_js.Button,
4811
4811
  {
4812
4812
  type,
4813
4813
  "data-size": size,
@@ -5161,7 +5161,7 @@ function PaginationLink({
5161
5161
  "data-slot": "pagination-link",
5162
5162
  "data-active": isActive,
5163
5163
  className: chunkD5LKWKG7_js.cn(
5164
- chunkDNLCSV5M_js.buttonVariants({
5164
+ chunkNPNSPYTX_js.buttonVariants({
5165
5165
  variant: isActive ? "outline" : "ghost",
5166
5166
  size
5167
5167
  }),
@@ -5560,7 +5560,7 @@ function SidebarTrigger({
5560
5560
  }) {
5561
5561
  const { toggleSidebar } = useSidebar();
5562
5562
  return /* @__PURE__ */ jsxRuntime.jsxs(
5563
- chunkDNLCSV5M_js.Button,
5563
+ chunkNPNSPYTX_js.Button,
5564
5564
  {
5565
5565
  "data-sidebar": "trigger",
5566
5566
  "data-slot": "sidebar-trigger",
@@ -6529,9 +6529,10 @@ function ThemeModeToggle({
6529
6529
  setTheme(theme === "dark" ? "light" : "dark");
6530
6530
  };
6531
6531
  return /* @__PURE__ */ jsxRuntime.jsxs(
6532
- chunkDNLCSV5M_js.Button,
6532
+ chunkNPNSPYTX_js.Button,
6533
6533
  {
6534
6534
  variant: "ghost",
6535
+ intent: "neutral",
6535
6536
  size: showText ? "sm" : "icon",
6536
6537
  className: chunkD5LKWKG7_js.cn("cursor-pointer", className),
6537
6538
  onClick: toggleTheme,
@@ -6684,11 +6685,11 @@ function UserAvatar({ src, name, initials, size = "md", className }) {
6684
6685
 
6685
6686
  Object.defineProperty(exports, "Button", {
6686
6687
  enumerable: true,
6687
- get: function () { return chunkDNLCSV5M_js.Button; }
6688
+ get: function () { return chunkNPNSPYTX_js.Button; }
6688
6689
  });
6689
6690
  Object.defineProperty(exports, "buttonVariants", {
6690
6691
  enumerable: true,
6691
- get: function () { return chunkDNLCSV5M_js.buttonVariants; }
6692
+ get: function () { return chunkNPNSPYTX_js.buttonVariants; }
6692
6693
  });
6693
6694
  Object.defineProperty(exports, "Dialog", {
6694
6695
  enumerable: true,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { buttonVariants, Button } from './chunk-WPOOC2FX.mjs';
3
- export { Button, buttonVariants } from './chunk-WPOOC2FX.mjs';
2
+ import { buttonVariants, Button } from './chunk-56PMDC5F.mjs';
3
+ export { Button, buttonVariants } from './chunk-56PMDC5F.mjs';
4
4
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './chunk-RW2S3KNB.mjs';
5
5
  import { useSaasflareMotion, springGentle, springBouncy, spring } from './chunk-EJHYM2HP.mjs';
6
6
  export { fadeIn, noMotion, scaleIn, slideDown, slideUp, spring, springBouncy, springGentle, springStiff, useSaasflareMotion } from './chunk-EJHYM2HP.mjs';
@@ -812,8 +812,8 @@ var badgeVariants = cva(
812
812
  variants: {
813
813
  variant: {
814
814
  solid: "bg-[var(--intent)] text-[var(--intent-fg)] [a&]:hover:brightness-110",
815
- soft: "bg-[var(--intent)]/15 text-[var(--intent)] [a&]:hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
816
- outline: "border-[var(--intent)]/30 text-[var(--intent)] [a&]:hover:bg-[var(--intent)]/10"
815
+ soft: "bg-[var(--intent)]/15 text-[var(--intent-text)] [a&]:hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
816
+ outline: "border-[var(--intent-text)]/30 text-[var(--intent-text)] [a&]:hover:bg-[var(--intent-text)]/10"
817
817
  },
818
818
  size: {
819
819
  sm: "px-1.5 py-px text-[10px]",
@@ -6483,6 +6483,7 @@ function ThemeModeToggle({
6483
6483
  Button,
6484
6484
  {
6485
6485
  variant: "ghost",
6486
+ intent: "neutral",
6486
6487
  size: showText ? "sm" : "icon",
6487
6488
  className: cn("cursor-pointer", className),
6488
6489
  onClick: toggleTheme,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasflare/ui",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "The Next.js UI library — App Router-aware Radix primitives with Tailwind v4 and Motion, animated by default.",
@@ -122,6 +122,10 @@
122
122
  :root[data-palette="teal"] { --primary-h: 185; --primary-c: 0.15; --primary-l: 0.60; }
123
123
  :root[data-palette="teal"].dark { --primary-l: 0.70; }
124
124
 
125
+ /* ─── Sage (dusty teal, Saasflare alt-brand) ────── */
126
+ :root[data-palette="sage"] { --primary-h: 169.28; --primary-c: 0.082; --primary-l: 0.586; }
127
+ :root[data-palette="sage"].dark { --primary-l: 0.70; }
128
+
125
129
  /* ─── Iris ──────────────────────────────────────── */
126
130
  :root[data-palette="iris"] { --primary-h: 255; --primary-c: 0.16; --primary-l: 0.60; }
127
131
  :root[data-palette="iris"].dark { --primary-l: 0.70; }
package/styles/theme.css CHANGED
@@ -70,7 +70,7 @@
70
70
  --primary-foreground: oklch(1 0 0);
71
71
 
72
72
  /* ── Secondary / Accent / Muted (from neutral axis) ── */
73
- --secondary: oklch(0.965 var(--neutral-c) var(--neutral-h));
73
+ --secondary: oklch(0.92 calc(var(--neutral-c) * 1.5) var(--neutral-h));
74
74
  --secondary-foreground: oklch(0.24 calc(var(--neutral-c) * 2) var(--neutral-h));
75
75
 
76
76
  --accent: oklch(0.95 calc(var(--neutral-c) * 1.6) var(--neutral-h));
@@ -91,13 +91,13 @@
91
91
  --ring: oklch(var(--primary-l) var(--primary-c) var(--primary-h));
92
92
 
93
93
  /* ── Semantic (fixed hues, brand-independent) ── */
94
- --destructive: oklch(0.577 0.245 27.325);
94
+ --destructive: oklch(0.583 0.239 28.476);
95
95
  --destructive-foreground: oklch(1 0 0);
96
- --success: oklch(0.59 0.17 149);
97
- --success-foreground: oklch(1 0 0);
98
- --warning: oklch(0.75 0.17 65);
99
- --warning-foreground: oklch(0.22 0.05 65);
100
- --info: oklch(0.68 0.15 230);
96
+ --success: oklch(0.750 0.146 161.279);
97
+ --success-foreground: oklch(0.22 0.05 161);
98
+ --warning: oklch(0.849 0.144 93.533);
99
+ --warning-foreground: oklch(0.22 0.05 93);
100
+ --info: oklch(0.590 0.133 254.001);
101
101
  --info-foreground: oklch(1 0 0);
102
102
 
103
103
  /* ── Charts (offsets from primary hue) ── */
@@ -149,14 +149,14 @@
149
149
  --input: oklch(1 0 0 / 0.15);
150
150
  --ring: oklch(var(--primary-l) var(--primary-c) var(--primary-h));
151
151
 
152
- --destructive: oklch(0.704 0.191 22.216);
153
- --destructive-foreground: oklch(0.15 0.03 27);
154
- --success: oklch(0.68 0.19 149);
155
- --success-foreground: oklch(0.15 0.03 149);
156
- --warning: oklch(0.8 0.17 65);
157
- --warning-foreground: oklch(0.2 0.04 65);
158
- --info: oklch(0.72 0.15 230);
159
- --info-foreground: oklch(0.15 0.03 230);
152
+ --destructive: oklch(0.700 0.200 28.476);
153
+ --destructive-foreground: oklch(1 0 0);
154
+ --success: oklch(0.770 0.146 161.279);
155
+ --success-foreground: oklch(0.22 0.05 161);
156
+ --warning: oklch(0.830 0.150 93.533);
157
+ --warning-foreground: oklch(0.22 0.05 93);
158
+ --info: oklch(0.680 0.140 254.001);
159
+ --info-foreground: oklch(1 0 0);
160
160
 
161
161
  --chart-1: oklch(var(--primary-l) var(--primary-c) var(--primary-h));
162
162
  --chart-2: oklch(0.68 0.19 calc(var(--primary-h) - 110));
@@ -341,7 +341,7 @@ textarea,
341
341
  * and wins by specificity — intentional escape hatch.
342
342
  * ============================================ */
343
343
  :root[data-radius="sharp"] { --radius: 0; }
344
- :root[data-radius="soft"] { --radius: 0.25rem; }
344
+ :root[data-radius="soft"] { --radius: 0.35rem; }
345
345
  :root[data-radius="rounded"] { --radius: 0.625rem; }
346
346
  :root[data-radius="pill"] {
347
347
  --radius: 9999px;
@@ -355,33 +355,49 @@ textarea,
355
355
  * Intent color system — components set
356
356
  * data-intent="primary|success|warning|…" to
357
357
  * activate intent-aware coloring via --intent.
358
+ *
359
+ * Three tokens per intent:
360
+ * --intent fill color (used as background in solid/shadow variants)
361
+ * --intent-fg paired text color readable on top of --intent
362
+ * --intent-text text color when rendered without a fill (transparent bg)
363
+ *
364
+ * For colored intents --intent-text === --intent (the saturated brand color
365
+ * is itself readable as text on a page background). For neutral, --intent
366
+ * is a light surface, so --intent-text falls back to --secondary-foreground
367
+ * (dark gray) so soft/outline/ghost/link/glass variants stay legible.
358
368
  * ============================================ */
359
369
  [data-intent="primary"] {
360
370
  --intent: var(--primary);
361
371
  --intent-fg: var(--primary-foreground);
372
+ --intent-text: var(--primary);
362
373
  }
363
374
 
364
375
  [data-intent="neutral"] {
365
376
  --intent: var(--secondary);
366
377
  --intent-fg: var(--secondary-foreground);
378
+ --intent-text: var(--secondary-foreground);
367
379
  }
368
380
 
369
381
  [data-intent="success"] {
370
382
  --intent: var(--success);
371
383
  --intent-fg: var(--success-foreground);
384
+ --intent-text: var(--success);
372
385
  }
373
386
 
374
387
  [data-intent="warning"] {
375
388
  --intent: var(--warning);
376
389
  --intent-fg: var(--warning-foreground);
390
+ --intent-text: var(--warning);
377
391
  }
378
392
 
379
393
  [data-intent="danger"] {
380
394
  --intent: var(--destructive);
381
395
  --intent-fg: var(--destructive-foreground);
396
+ --intent-text: var(--destructive);
382
397
  }
383
398
 
384
399
  [data-intent="info"] {
385
400
  --intent: var(--info);
386
401
  --intent-fg: var(--info-foreground);
402
+ --intent-text: var(--info);
387
403
  }