@neoptocom/neopto-ui 1.6.3 → 1.6.6

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
@@ -195,7 +195,7 @@ The library uses a comprehensive design token system:
195
195
 
196
196
  ## 📚 Documentation
197
197
 
198
- Visit our [Storybook documentation](https://neoptocom.github.io/neopto-ui/) for:
198
+ Visit our [Storybook documentation](https://neoptocom.github.io/neopto-ui/storybook-static) for:
199
199
 
200
200
  - Interactive component playground
201
201
  - Design system guidelines
package/dist/index.cjs CHANGED
@@ -1179,13 +1179,64 @@ var Button = React11__namespace.forwardRef(
1179
1179
  }
1180
1180
  );
1181
1181
  Button.displayName = "Button";
1182
+ function getTextColorForBackground(bgClassName) {
1183
+ if (!bgClassName) return "";
1184
+ const lightColors = [
1185
+ "white",
1186
+ "gray-50",
1187
+ "gray-100",
1188
+ "slate-50",
1189
+ "slate-100",
1190
+ "zinc-50",
1191
+ "zinc-100",
1192
+ "neutral-50",
1193
+ "neutral-100",
1194
+ "stone-50",
1195
+ "stone-100"
1196
+ ];
1197
+ const darkColors = [
1198
+ "black",
1199
+ "gray-900",
1200
+ "gray-950",
1201
+ "slate-900",
1202
+ "slate-950",
1203
+ "zinc-900",
1204
+ "zinc-950",
1205
+ "neutral-900",
1206
+ "neutral-950",
1207
+ "stone-900",
1208
+ "stone-950"
1209
+ ];
1210
+ for (const lightColor of lightColors) {
1211
+ if (bgClassName.includes(lightColor)) {
1212
+ return "text-gray-900";
1213
+ }
1214
+ }
1215
+ for (const darkColor of darkColors) {
1216
+ if (bgClassName.includes(darkColor)) {
1217
+ return "text-white";
1218
+ }
1219
+ }
1220
+ const shadeMatch = bgClassName.match(/-(\d{2,3})/);
1221
+ if (shadeMatch) {
1222
+ const shade = parseInt(shadeMatch[1], 10);
1223
+ if (shade >= 100 && shade <= 400) {
1224
+ return "text-gray-900";
1225
+ }
1226
+ if (shade >= 500) {
1227
+ return "text-white";
1228
+ }
1229
+ }
1230
+ return "text-white";
1231
+ }
1182
1232
  function Chip({
1183
1233
  variant = "success",
1184
1234
  icon,
1185
1235
  className = "",
1186
1236
  label,
1187
- backgroundColor,
1188
1237
  textColor,
1238
+ bgClassName,
1239
+ title,
1189
1240
  style,
1190
1241
  onDelete,
1191
1242
  ...props
@@ -1198,28 +1249,30 @@ function Chip({
1198
1249
  light: "bg-[var(--muted)] text-[var(--fg)]",
1199
1250
  dark: "bg-[var(--surface)] text-[var(--fg)]"
1200
1251
  };
1201
- const hasCustomColors = backgroundColor || textColor;
1202
- const colorClasses = hasCustomColors ? "" : variantCls[variant];
1252
+ const hasCustomTextColor = !!textColor;
1253
+ const hasBgClassName = !!bgClassName;
1254
+ const colorClasses = hasBgClassName ? "" : hasCustomTextColor ? "" : variantCls[variant];
1255
+ const autoTextColor = hasBgClassName && !textColor ? getTextColorForBackground(bgClassName) : "";
1203
1256
  const mergedStyle = {
1204
1257
  ...style,
1205
- ...backgroundColor && { backgroundColor },
1206
1258
  ...textColor && { color: textColor }
1207
1259
  };
1208
1260
  return /* @__PURE__ */ jsxRuntime.jsxs(
1209
1261
  "div",
1210
1262
  {
1211
- className: [base, colorClasses, className].join(" "),
1263
+ className: [base, colorClasses, bgClassName, autoTextColor, className].join(" "),
1212
1264
  style: mergedStyle,
1265
+ title,
1213
1266
  ...props,
1214
1267
  children: [
1215
- icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
1216
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
1268
+ icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm", className: "mr-0.5 flex-shrink-0" }) : null,
1269
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }),
1217
1270
  onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
1218
1271
  "button",
1219
1272
  {
1220
1273
  type: "button",
1221
1274
  onClick: onDelete,
1222
- className: "ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30",
1275
+ className: "ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30 flex-shrink-0",
1223
1276
  "aria-label": "Remove",
1224
1277
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "close", size: "sm" })
1225
1278
  }
@@ -1628,7 +1681,7 @@ function Calendar({
1628
1681
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
1629
1682
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
1630
1683
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1631
- /* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "title-md", bold: "medium", className: "text-[var(--fg)]", children: MONTHS[currentMonth.getMonth()] }),
1684
+ /* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "title-md", className: "text-[var(--fg)]", children: MONTHS[currentMonth.getMonth()] }),
1632
1685
  /* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "title-md", bold: "medium", className: "text-cyan-500", children: currentMonth.getFullYear() })
1633
1686
  ] }),
1634
1687
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
package/dist/index.d.cts CHANGED
@@ -292,14 +292,16 @@ type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
292
292
  variant?: "warning" | "success" | "error" | "light" | "dark";
293
293
  icon?: string;
294
294
  label?: string;
295
- /** Custom background color (overrides variant) */
296
- backgroundColor?: string;
297
295
  /** Custom text color (overrides variant) */
298
296
  textColor?: string;
297
+ /** Tailwind class for background color (overrides variant) */
298
+ bgClassName?: string;
299
+ /** Title attribute for tooltip */
300
+ title?: string;
299
301
  /** Optional handler to render a delete affordance */
300
302
  onDelete?: React.MouseEventHandler<HTMLButtonElement>;
301
303
  };
302
- declare function Chip({ variant, icon, className, label, backgroundColor, textColor, style, onDelete, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
304
+ declare function Chip({ variant, icon, className, label, textColor, bgClassName, title, style, onDelete, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
303
305
 
304
306
  type CounterProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
305
307
  value?: number;
package/dist/index.d.ts CHANGED
@@ -292,14 +292,16 @@ type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
292
292
  variant?: "warning" | "success" | "error" | "light" | "dark";
293
293
  icon?: string;
294
294
  label?: string;
295
- /** Custom background color (overrides variant) */
296
- backgroundColor?: string;
297
295
  /** Custom text color (overrides variant) */
298
296
  textColor?: string;
297
+ /** Tailwind class for background color (overrides variant) */
298
+ bgClassName?: string;
299
+ /** Title attribute for tooltip */
300
+ title?: string;
299
301
  /** Optional handler to render a delete affordance */
300
302
  onDelete?: React.MouseEventHandler<HTMLButtonElement>;
301
303
  };
302
- declare function Chip({ variant, icon, className, label, backgroundColor, textColor, style, onDelete, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
304
+ declare function Chip({ variant, icon, className, label, textColor, bgClassName, title, style, onDelete, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
303
305
 
304
306
  type CounterProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
305
307
  value?: number;
package/dist/index.js CHANGED
@@ -1158,13 +1158,64 @@ var Button = React11.forwardRef(
1158
1158
  }
1159
1159
  );
1160
1160
  Button.displayName = "Button";
1161
+ function getTextColorForBackground(bgClassName) {
1162
+ if (!bgClassName) return "";
1163
+ const lightColors = [
1164
+ "white",
1165
+ "gray-50",
1166
+ "gray-100",
1167
+ "slate-50",
1168
+ "slate-100",
1169
+ "zinc-50",
1170
+ "zinc-100",
1171
+ "neutral-50",
1172
+ "neutral-100",
1173
+ "stone-50",
1174
+ "stone-100"
1175
+ ];
1176
+ const darkColors = [
1177
+ "black",
1178
+ "gray-900",
1179
+ "gray-950",
1180
+ "slate-900",
1181
+ "slate-950",
1182
+ "zinc-900",
1183
+ "zinc-950",
1184
+ "neutral-900",
1185
+ "neutral-950",
1186
+ "stone-900",
1187
+ "stone-950"
1188
+ ];
1189
+ for (const lightColor of lightColors) {
1190
+ if (bgClassName.includes(lightColor)) {
1191
+ return "text-gray-900";
1192
+ }
1193
+ }
1194
+ for (const darkColor of darkColors) {
1195
+ if (bgClassName.includes(darkColor)) {
1196
+ return "text-white";
1197
+ }
1198
+ }
1199
+ const shadeMatch = bgClassName.match(/-(\d{2,3})/);
1200
+ if (shadeMatch) {
1201
+ const shade = parseInt(shadeMatch[1], 10);
1202
+ if (shade >= 100 && shade <= 400) {
1203
+ return "text-gray-900";
1204
+ }
1205
+ if (shade >= 500) {
1206
+ return "text-white";
1207
+ }
1208
+ }
1209
+ return "text-white";
1210
+ }
1161
1211
  function Chip({
1162
1212
  variant = "success",
1163
1213
  icon,
1164
1214
  className = "",
1165
1215
  label,
1166
- backgroundColor,
1167
1216
  textColor,
1217
+ bgClassName,
1218
+ title,
1168
1219
  style,
1169
1220
  onDelete,
1170
1221
  ...props
@@ -1177,28 +1228,30 @@ function Chip({
1177
1228
  light: "bg-[var(--muted)] text-[var(--fg)]",
1178
1229
  dark: "bg-[var(--surface)] text-[var(--fg)]"
1179
1230
  };
1180
- const hasCustomColors = backgroundColor || textColor;
1181
- const colorClasses = hasCustomColors ? "" : variantCls[variant];
1231
+ const hasCustomTextColor = !!textColor;
1232
+ const hasBgClassName = !!bgClassName;
1233
+ const colorClasses = hasBgClassName ? "" : hasCustomTextColor ? "" : variantCls[variant];
1234
+ const autoTextColor = hasBgClassName && !textColor ? getTextColorForBackground(bgClassName) : "";
1182
1235
  const mergedStyle = {
1183
1236
  ...style,
1184
- ...backgroundColor && { backgroundColor },
1185
1237
  ...textColor && { color: textColor }
1186
1238
  };
1187
1239
  return /* @__PURE__ */ jsxs(
1188
1240
  "div",
1189
1241
  {
1190
- className: [base, colorClasses, className].join(" "),
1242
+ className: [base, colorClasses, bgClassName, autoTextColor, className].join(" "),
1191
1243
  style: mergedStyle,
1244
+ title,
1192
1245
  ...props,
1193
1246
  children: [
1194
- icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
1195
- /* @__PURE__ */ jsx("span", { children: label }),
1247
+ icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm", className: "mr-0.5 flex-shrink-0" }) : null,
1248
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: label }),
1196
1249
  onDelete ? /* @__PURE__ */ jsx(
1197
1250
  "button",
1198
1251
  {
1199
1252
  type: "button",
1200
1253
  onClick: onDelete,
1201
- className: "ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30",
1254
+ className: "ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30 flex-shrink-0",
1202
1255
  "aria-label": "Remove",
1203
1256
  children: /* @__PURE__ */ jsx(Icon, { name: "close", size: "sm" })
1204
1257
  }
@@ -1607,7 +1660,7 @@ function Calendar({
1607
1660
  return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
1608
1661
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
1609
1662
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1610
- /* @__PURE__ */ jsx(Typo, { variant: "title-md", bold: "medium", className: "text-[var(--fg)]", children: MONTHS[currentMonth.getMonth()] }),
1663
+ /* @__PURE__ */ jsx(Typo, { variant: "title-md", className: "text-[var(--fg)]", children: MONTHS[currentMonth.getMonth()] }),
1611
1664
  /* @__PURE__ */ jsx(Typo, { variant: "title-md", bold: "medium", className: "text-cyan-500", children: currentMonth.getFullYear() })
1612
1665
  ] }),
1613
1666
  /* @__PURE__ */ jsxs("div", { children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoptocom/neopto-ui",
3
- "version": "1.6.3",
3
+ "version": "1.6.6",
4
4
  "private": false,
5
5
  "description": "A modern React component library built with Tailwind CSS v4 and TypeScript. Features dark mode, design tokens, and comprehensive Storybook documentation. Requires Tailwind v4+.",
6
6
  "keywords": [
@@ -62,3 +62,9 @@ page load. The interactive example demonstrates an in-app documents flow.
62
62
 
63
63
 
64
64
 
65
+
66
+
67
+
68
+
69
+
70
+
@@ -80,3 +80,9 @@ export const InteractiveNavigation: Story = {
80
80
 
81
81
 
82
82
 
83
+
84
+
85
+
86
+
87
+
88
+
@@ -58,3 +58,9 @@ Use variants to communicate hierarchy:
58
58
 
59
59
 
60
60
 
61
+
62
+
63
+
64
+
65
+
66
+
@@ -112,3 +112,9 @@ export const FullWidthCallToAction: Story = {
112
112
 
113
113
 
114
114
 
115
+
116
+
117
+
118
+
119
+
120
+
@@ -119,7 +119,7 @@ export default function Calendar({
119
119
  {/* Header */}
120
120
  <div className="flex items-center justify-between mb-4">
121
121
  <div className="flex items-center gap-2">
122
- <Typo variant="title-md" bold="medium" className="text-[var(--fg)]">
122
+ <Typo variant="title-md" className="text-[var(--fg)]">
123
123
  {MONTHS[currentMonth.getMonth()]}
124
124
  </Typo>
125
125
  <Typo variant="title-md" bold="medium" className="text-cyan-500">
@@ -58,3 +58,9 @@ attaching click handlers to the card root.
58
58
 
59
59
 
60
60
 
61
+
62
+
63
+
64
+
65
+
66
+
@@ -5,21 +5,92 @@ export type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
5
5
  variant?: "warning" | "success" | "error" | "light" | "dark";
6
6
  icon?: string;
7
7
  label?: string;
8
- /** Custom background color (overrides variant) */
9
- backgroundColor?: string;
10
8
  /** Custom text color (overrides variant) */
11
9
  textColor?: string;
10
+ /** Tailwind class for background color (overrides variant) */
11
+ bgClassName?: string;
12
+ /** Title attribute for tooltip */
13
+ title?: string;
12
14
  /** Optional handler to render a delete affordance */
13
15
  onDelete?: React.MouseEventHandler<HTMLButtonElement>;
14
16
  };
15
17
 
18
+ /**
19
+ * Detects if a Tailwind background class represents a light or dark background
20
+ * and returns the appropriate text color class for optimal contrast.
21
+ */
22
+ function getTextColorForBackground(bgClassName: string | undefined): string {
23
+ if (!bgClassName) return "";
24
+
25
+ // Named light colors - use dark text
26
+ const lightColors = [
27
+ "white",
28
+ "gray-50",
29
+ "gray-100",
30
+ "slate-50",
31
+ "slate-100",
32
+ "zinc-50",
33
+ "zinc-100",
34
+ "neutral-50",
35
+ "neutral-100",
36
+ "stone-50",
37
+ "stone-100"
38
+ ];
39
+
40
+ // Named dark colors - use white text
41
+ const darkColors = [
42
+ "black",
43
+ "gray-900",
44
+ "gray-950",
45
+ "slate-900",
46
+ "slate-950",
47
+ "zinc-900",
48
+ "zinc-950",
49
+ "neutral-900",
50
+ "neutral-950",
51
+ "stone-900",
52
+ "stone-950"
53
+ ];
54
+
55
+ // Check for named colors
56
+ for (const lightColor of lightColors) {
57
+ if (bgClassName.includes(lightColor)) {
58
+ return "text-gray-900";
59
+ }
60
+ }
61
+
62
+ for (const darkColor of darkColors) {
63
+ if (bgClassName.includes(darkColor)) {
64
+ return "text-white";
65
+ }
66
+ }
67
+
68
+ // Extract shade number from patterns like bg-blue-500, bg-purple-200, etc.
69
+ const shadeMatch = bgClassName.match(/-(\d{2,3})/);
70
+ if (shadeMatch) {
71
+ const shade = parseInt(shadeMatch[1], 10);
72
+ // Shades 100-400 are typically light, use dark text
73
+ if (shade >= 100 && shade <= 400) {
74
+ return "text-gray-900";
75
+ }
76
+ // Shades 500-950 are typically dark, use white text
77
+ if (shade >= 500) {
78
+ return "text-white";
79
+ }
80
+ }
81
+
82
+ // Default to white text if pattern is unclear (safer for most backgrounds)
83
+ return "text-white";
84
+ }
85
+
16
86
  export default function Chip({
17
87
  variant = "success",
18
88
  icon,
19
89
  className = "",
20
90
  label,
21
- backgroundColor,
22
91
  textColor,
92
+ bgClassName,
93
+ title,
23
94
  style,
24
95
  onDelete,
25
96
  ...props
@@ -37,30 +108,34 @@ export default function Chip({
37
108
  dark: "bg-[var(--surface)] text-[var(--fg)]"
38
109
  };
39
110
 
40
- // Use custom colors if provided, otherwise use variant styles
41
- const hasCustomColors = backgroundColor || textColor;
42
- const colorClasses = hasCustomColors ? "" : variantCls[variant];
111
+ // Use bgClassName if provided, otherwise use custom text color, otherwise use variant styles
112
+ const hasCustomTextColor = !!textColor;
113
+ const hasBgClassName = !!bgClassName;
114
+ const colorClasses = hasBgClassName ? "" : hasCustomTextColor ? "" : variantCls[variant];
115
+
116
+ // Automatically detect text color for custom background classes
117
+ const autoTextColor = hasBgClassName && !textColor ? getTextColorForBackground(bgClassName) : "";
43
118
 
44
- // Merge custom colors into style prop
119
+ // Merge custom text color into style prop
45
120
  const mergedStyle: React.CSSProperties = {
46
121
  ...style,
47
- ...(backgroundColor && { backgroundColor }),
48
122
  ...(textColor && { color: textColor })
49
123
  };
50
124
 
51
125
  return (
52
126
  <div
53
- className={[base, colorClasses, className].join(" ")}
127
+ className={[base, colorClasses, bgClassName, autoTextColor, className].join(" ")}
54
128
  style={mergedStyle}
129
+ title={title}
55
130
  {...props}
56
131
  >
57
- {icon ? <Icon name={icon} size="sm" className="mr-0.5" /> : null}
58
- <span>{label}</span>
132
+ {icon ? <Icon name={icon} size="sm" className="mr-0.5 flex-shrink-0" /> : null}
133
+ <span className="truncate">{label}</span>
59
134
  {onDelete ? (
60
135
  <button
61
136
  type="button"
62
137
  onClick={onDelete}
63
- className="ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30"
138
+ className="ml-1 flex h-4 w-4 items-center justify-center rounded-full transition-colors hover:bg-black/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-black/30 flex-shrink-0"
64
139
  aria-label="Remove"
65
140
  >
66
141
  <Icon name="close" size="sm" />
@@ -48,4 +48,51 @@ export const Deletable: Story = {
48
48
  )
49
49
  };
50
50
 
51
+ export const CustomBackgroundColor: Story = {
52
+ render: () => (
53
+ <div className="space-y-4">
54
+ <div>
55
+ <p className="text-sm text-gray-600 mb-2">Dark backgrounds (auto white text):</p>
56
+ <div className="flex flex-wrap items-center gap-3">
57
+ <Chip bgClassName="bg-blue-500" label="Blue 500" title="Custom blue background" />
58
+ <Chip bgClassName="bg-purple-500" label="Purple 500" title="Custom purple background" />
59
+ <Chip bgClassName="bg-pink-500" label="Pink 500" title="Custom pink background" />
60
+ <Chip bgClassName="bg-indigo-500" label="Indigo 500" title="Custom indigo background" />
61
+ <Chip bgClassName="bg-teal-500" label="Teal 500" title="Custom teal background" />
62
+ <Chip bgClassName="bg-orange-500" label="Orange 500" title="Custom orange background" />
63
+ <Chip bgClassName="bg-cyan-500" label="Cyan 500" title="Custom cyan background" />
64
+ <Chip bgClassName="bg-emerald-500" label="Emerald 500" title="Custom emerald background" />
65
+ <Chip bgClassName="bg-red-600" label="Red 600" title="Custom red background" />
66
+ <Chip bgClassName="bg-gray-900" label="Gray 900" title="Custom gray background" />
67
+ </div>
68
+ </div>
69
+ <div>
70
+ <p className="text-sm text-gray-600 mb-2">Light backgrounds (auto dark text):</p>
71
+ <div className="flex flex-wrap items-center gap-3">
72
+ <Chip bgClassName="bg-blue-200" label="Blue 200" title="Light blue background" />
73
+ <Chip bgClassName="bg-purple-200" label="Purple 200" title="Light purple background" />
74
+ <Chip bgClassName="bg-pink-200" label="Pink 200" title="Light pink background" />
75
+ <Chip bgClassName="bg-indigo-200" label="Indigo 200" title="Light indigo background" />
76
+ <Chip bgClassName="bg-teal-200" label="Teal 200" title="Light teal background" />
77
+ <Chip bgClassName="bg-orange-200" label="Orange 200" title="Light orange background" />
78
+ <Chip bgClassName="bg-cyan-200" label="Cyan 200" title="Light cyan background" />
79
+ <Chip bgClassName="bg-emerald-200" label="Emerald 200" title="Light emerald background" />
80
+ <Chip bgClassName="bg-yellow-300" label="Yellow 300" title="Light yellow background" />
81
+ <Chip bgClassName="bg-white" label="White" title="White background" />
82
+ </div>
83
+ </div>
84
+ </div>
85
+ )
86
+ };
87
+
88
+ export const CustomBackgroundWithIcon: Story = {
89
+ render: () => (
90
+ <div className="flex flex-wrap items-center gap-3">
91
+ <Chip bgClassName="bg-blue-500" icon="check" label="Completed" title="Task completed" />
92
+ <Chip bgClassName="bg-purple-500" icon="star" label="Featured" title="Featured item" />
93
+ <Chip bgClassName="bg-pink-500" icon="favorite" label="Favorite" title="Marked as favorite" />
94
+ <Chip bgClassName="bg-indigo-500" icon="schedule" label="Scheduled" title="Scheduled for later" />
95
+ </div>
96
+ )
97
+ };
51
98
 
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { DateInput } from "../components/DateInput";
4
+ import * as assets from "../assets";
4
5
 
5
6
  const meta: Meta<typeof DateInput> = {
6
7
  title: "Components/DateInput",
@@ -134,3 +135,23 @@ export const Multiple: Story = {
134
135
  }
135
136
  };
136
137
 
138
+ export const WithBackgroundImages: Story = {
139
+ render: () => {
140
+ const [date, setDate] = React.useState<Date | null>(null);
141
+ return (
142
+ <div className="flex flex-col gap-4 w-96">
143
+ <DateInput
144
+ label="Select date"
145
+ value={date}
146
+ onChange={(d) => setDate(d)}
147
+ lightBackgroundImage={assets.bgLight}
148
+ darkBackgroundImage={assets.bgDark}
149
+ />
150
+ <p className="text-xs text-[var(--muted-fg)]">
151
+ Calendar popup uses background images that adapt to light/dark mode.
152
+ </p>
153
+ </div>
154
+ );
155
+ }
156
+ };
157
+
@@ -31,7 +31,6 @@
31
31
  vertical-align: middle;
32
32
  white-space: nowrap;
33
33
  -webkit-font-smoothing: antialiased;
34
- color: inherit;
35
34
  }
36
35
 
37
36
  .btn { @apply inline-flex items-center justify-center gap-2 rounded-[--radius-lg] px-4 py-2 text-sm font-medium transition; }
@@ -34,7 +34,6 @@
34
34
  vertical-align: middle;
35
35
  white-space: nowrap;
36
36
  -webkit-font-smoothing: antialiased;
37
- color: inherit;
38
37
  }
39
38
 
40
39
  /* Optional shared utility classes used by some components */