aplance-ui 1.1.0 → 1.2.0

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.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/registry/components/primitives/infinite-scroll/infinite-scroll-context.ts +32 -0
  3. package/registry/components/primitives/infinite-scroll/infinite-scroll.module.css +118 -0
  4. package/registry/components/primitives/infinite-scroll/infinite-scroll.tsx +386 -0
  5. package/registry/components/primitives/popover/popover.module.css +16 -21
  6. package/registry/components/primitives/slider/slider-context.ts +50 -0
  7. package/registry/components/primitives/slider/slider.module.css +300 -0
  8. package/registry/components/primitives/slider/slider.tsx +1174 -0
  9. package/registry/components/primitives/slider/types.ts +140 -0
  10. package/registry/components/primitives/slider/utils.ts +88 -0
  11. package/registry/components/ui/breadcrumbs/breadcrumbs.module.css +144 -0
  12. package/registry/components/ui/breadcrumbs/breadcrumbs.tsx +236 -0
  13. package/registry/components/ui/button/button.module.css +3 -9
  14. package/registry/components/ui/chart/chart.module.css +86 -70
  15. package/registry/components/ui/chart/chart.tsx +117 -31
  16. package/registry/components/ui/input-fields/common/input-field-common.module.css +39 -65
  17. package/registry/components/ui/input-fields/date-picker/calendar.module.css +2 -6
  18. package/registry/components/ui/input-fields/date-picker/date-picker.module.css +47 -3
  19. package/registry/components/ui/input-fields/date-picker/date-picker.tsx +12 -12
  20. package/registry/components/ui/input-fields/media-input/media-input.module.css +12 -0
  21. package/registry/components/ui/input-fields/media-input/media-input.tsx +10 -9
  22. package/registry/components/ui/input-fields/media-input/useMediaUpload.tsx +19 -5
  23. package/registry/components/ui/input-fields/media-input/utils.ts +13 -5
  24. package/registry/registry.json +64 -1
@@ -1,14 +1,15 @@
1
1
  /* ── Container card ───────────────────────────────────────────── */
2
- .card {
3
- width: 100%;
4
- background-color: var(--color-background);
5
- border: var(--border-1) solid var(--color-border);
6
- border-radius: var(--radius-lg);
7
- padding: var(--spacing-7);
8
- display: flex;
9
- flex-direction: column;
10
- gap: var(--spacing-8);
11
- }
2
+ .card {
3
+ width: 100%;
4
+ min-width: 0;
5
+ background-color: var(--color-background);
6
+ border: var(--border-1) solid var(--color-border);
7
+ border-radius: var(--radius-lg);
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: var(--spacing-6);
11
+ padding: var(--spacing-6);
12
+ }
12
13
 
13
14
  .header {
14
15
  display: flex;
@@ -29,18 +30,19 @@
29
30
  color: var(--color-muted-foreground);
30
31
  }
31
32
 
32
- .canvas {
33
- width: 100%;
34
- position: relative;
35
- }
33
+ .canvas {
34
+ width: 100%;
35
+ min-width: 0;
36
+ position: relative;
37
+ }
36
38
 
37
- .plot {
38
- width: 100%;
39
- min-width: 0;
40
- display: flex;
41
- flex-direction: column;
42
- gap: var(--spacing-5);
43
- }
39
+ .plot {
40
+ width: 100%;
41
+ min-width: 0;
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--spacing-4);
45
+ }
44
46
 
45
47
  .plot :global(.recharts-cartesian-axis-tick-value) {
46
48
  font-variant-numeric: tabular-nums;
@@ -70,10 +72,11 @@
70
72
  /* Match the page surface so series colors (designed against the page bg)
71
73
  stay readable inside the tooltip. Border defines the floating edge
72
74
  without relying on shadow alone. */
73
- .tooltip {
74
- min-width: 10rem;
75
- background-color: var(--color-background);
76
- color: var(--color-foreground);
75
+ .tooltip {
76
+ min-width: 10rem;
77
+ max-width: min(18rem, calc(100vw - var(--spacing-8)));
78
+ background-color: var(--color-background);
79
+ color: var(--color-foreground);
77
80
  border: var(--border-1) solid var(--color-border);
78
81
  border-radius: var(--radius-md);
79
82
  padding: var(--spacing-4) var(--spacing-5);
@@ -86,55 +89,68 @@
86
89
  margin-bottom: var(--spacing-2);
87
90
  }
88
91
 
89
- .tooltip_row {
90
- display: flex;
91
- align-items: center;
92
- gap: var(--spacing-3);
93
- font-size: var(--font-size-xs);
92
+ .tooltip_row {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: var(--spacing-3);
96
+ font-size: var(--font-size-xs);
97
+ min-width: 0;
94
98
 
95
99
  &:not(:last-child) {
96
100
  margin-bottom: var(--spacing-2);
97
101
  }
98
102
  }
99
103
 
100
- .tooltip_dot {
101
- width: 8px;
102
- height: 8px;
103
- border-radius: var(--radius-full);
104
- flex-shrink: 0;
105
- }
106
-
107
- .tooltip_value {
108
- margin-left: auto;
109
- font-weight: var(--font-weight-semibold);
110
- padding-left: var(--spacing-3);
111
- font-variant-numeric: tabular-nums;
112
- }
104
+ .tooltip_dot {
105
+ display: block;
106
+ width: 8px;
107
+ height: 8px;
108
+ border-radius: var(--radius-full);
109
+ flex-shrink: 0;
110
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-background) 84%, transparent);
111
+ }
112
+
113
+ .tooltip_value {
114
+ margin-left: auto;
115
+ font-weight: var(--font-weight-semibold);
116
+ padding-left: var(--spacing-3);
117
+ font-variant-numeric: tabular-nums;
118
+ white-space: nowrap;
119
+ }
113
120
 
114
121
  /* ── Legend (shared across all chart types) ──────────────────── */
115
- .legend {
116
- display: flex;
117
- flex-wrap: wrap;
118
- gap: var(--spacing-3) var(--spacing-6);
119
- justify-content: center;
120
- }
121
-
122
- .legend_item {
123
- display: inline-flex;
124
- align-items: center;
125
- gap: var(--spacing-2);
126
- font-size: var(--font-size-xs);
127
- font-weight: var(--font-weight-medium);
128
- color: var(--color-muted-foreground);
129
- white-space: nowrap;
130
- }
131
-
132
- .legend_dot {
133
- width: 8px;
134
- height: 8px;
135
- border-radius: var(--radius-full);
136
- flex-shrink: 0;
137
- }
122
+ .legend {
123
+ display: flex;
124
+ flex-wrap: wrap;
125
+ gap: var(--spacing-3) var(--spacing-5);
126
+ justify-content: center;
127
+ min-width: 0;
128
+ }
129
+
130
+ .legend_item {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ gap: var(--spacing-2);
134
+ min-width: 0;
135
+ font-size: var(--font-size-xs);
136
+ font-weight: var(--font-weight-medium);
137
+ color: var(--color-muted-foreground);
138
+ line-height: 1.2;
139
+ }
140
+
141
+ .legend_dot {
142
+ display: block;
143
+ width: 8px;
144
+ height: 8px;
145
+ border-radius: var(--radius-full);
146
+ flex-shrink: 0;
147
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-background) 84%, transparent);
148
+ }
149
+
150
+ .legend_item > span:last-child {
151
+ overflow: hidden;
152
+ text-overflow: ellipsis;
153
+ }
138
154
 
139
155
  .center_overlay {
140
156
  position: absolute;
@@ -151,10 +167,10 @@
151
167
  }
152
168
 
153
169
  @media (width <= 600px) {
154
- .card {
155
- padding: var(--spacing-5);
156
- gap: var(--spacing-5);
157
- }
170
+ .card {
171
+ gap: var(--spacing-5);
172
+ padding: var(--spacing-5);
173
+ }
158
174
 
159
175
  .tooltip {
160
176
  min-width: 8rem;
@@ -77,9 +77,7 @@ export type {
77
77
  // ─── Constants ────────────────────────────────────────────────────────────────
78
78
 
79
79
  const DEFAULT_CHART_HEIGHT = 260;
80
- // left is intentionally negative: pulls Y-axis labels into the card's padding
81
- // so the visible whitespace on both sides feels balanced.
82
- const CARTESIAN_MARGIN = { top: 10, right: 10, bottom: 10, left: -8 } as const;
80
+ const CARTESIAN_MARGIN = { top: 8, right: 12, bottom: 4, left: 0 } as const;
83
81
  const YAXIS_WIDTH = 56;
84
82
  const YAXIS_WIDTH_HORIZONTAL = 80;
85
83
  const BAR_TOP_RADIUS: [number, number, number, number] = [6, 6, 0, 0];
@@ -114,6 +112,8 @@ type ChartTooltipProps = {
114
112
  // a single dataKey across all sectors), read the row label from the original
115
113
  // datum at this key so the tooltip shows "Aarav" instead of the dataKey.
116
114
  nameKey?: string;
115
+ /** Read a per-datum color from tooltip payload before falling back to series color. */
116
+ colorKey?: string;
117
117
  };
118
118
 
119
119
  type CartesianRenderOptions = {
@@ -160,6 +160,37 @@ type LegendItem = { key: string; label: string; color: string };
160
160
  const toLegendItems = (series: PreparedSeries[]): LegendItem[] =>
161
161
  series.map(({ key, label, color }) => ({ key, label, color }));
162
162
 
163
+ const toCategoryLegendItems = ({
164
+ data,
165
+ categoryKey,
166
+ colors,
167
+ fallbackColor,
168
+ }: {
169
+ data: ChartDatum[];
170
+ categoryKey: string;
171
+ colors?: Record<string, string>;
172
+ fallbackColor: string;
173
+ }): LegendItem[] => {
174
+ const seen = new Set<string>();
175
+ const items: LegendItem[] = [];
176
+
177
+ for (const entry of data) {
178
+ const rawLabel = entry[categoryKey];
179
+ const label = String(rawLabel ?? "Unknown");
180
+ const lookup = toLookupKey(rawLabel);
181
+ if (seen.has(lookup)) continue;
182
+
183
+ seen.add(lookup);
184
+ items.push({
185
+ key: lookup || label,
186
+ label,
187
+ color: resolveColorToken(colors?.[lookup], fallbackColor),
188
+ });
189
+ }
190
+
191
+ return items;
192
+ };
193
+
163
194
  // ─── Option resolution ────────────────────────────────────────────────────────
164
195
 
165
196
  const resolveCartesianOptions = (opts: CartesianRenderOptions) => ({
@@ -311,6 +342,11 @@ const formatTooltipValue = (value: TooltipValue): string => {
311
342
  return String(value);
312
343
  };
313
344
 
345
+ const toFiniteNumber = (value: unknown, fallback = 0) => {
346
+ const number = typeof value === "number" ? value : Number(value);
347
+ return Number.isFinite(number) ? number : fallback;
348
+ };
349
+
314
350
  const formatTooltipEntryValue = (
315
351
  value: TooltipValue,
316
352
  valueFormatter: TooltipValueFormatter | undefined,
@@ -331,6 +367,25 @@ const formatTooltipLabel = (
331
367
  return String(label);
332
368
  };
333
369
 
370
+ const payloadString = (
371
+ payload: Record<string, unknown> | undefined,
372
+ key: string,
373
+ ) => {
374
+ const value = payload?.[key];
375
+ return typeof value === "string" && value.trim() ? value : undefined;
376
+ };
377
+
378
+ const resolveTooltipColor = (
379
+ entry: TooltipPayloadItem,
380
+ colorKey: string | undefined,
381
+ ) =>
382
+ (colorKey ? payloadString(entry.payload, colorKey) : undefined) ??
383
+ payloadString(entry.payload, "__color") ??
384
+ payloadString(entry.payload, "fill") ??
385
+ payloadString(entry.payload, "stroke") ??
386
+ entry.color ??
387
+ "var(--color-muted-foreground)";
388
+
334
389
  function ChartTooltip({
335
390
  active,
336
391
  payload,
@@ -338,6 +393,7 @@ function ChartTooltip({
338
393
  valueFormatter,
339
394
  labelFormatter,
340
395
  nameKey,
396
+ colorKey,
341
397
  }: ChartTooltipProps) {
342
398
  if (!active || !payload?.length) return null;
343
399
 
@@ -354,7 +410,10 @@ function ChartTooltip({
354
410
  key={`${entry.dataKey ?? entry.name ?? "value"}-${index}`}
355
411
  className={s.tooltip_row}
356
412
  >
357
- <span className={s.tooltip_dot} style={{ backgroundColor: entry.color }} />
413
+ <span
414
+ className={s.tooltip_dot}
415
+ style={{ backgroundColor: resolveTooltipColor(entry, colorKey) }}
416
+ />
358
417
  <span>{String(rowName)}</span>
359
418
  <span className={s.tooltip_value}>
360
419
  {formatTooltipEntryValue(entry.value, valueFormatter, {
@@ -373,11 +432,11 @@ function ChartTooltip({
373
432
 
374
433
  function ChartLegend({ items }: { items: LegendItem[] }) {
375
434
  return (
376
- <div className={s.legend}>
377
- {items.map((item) => (
378
- <div key={item.key} className={s.legend_item}>
435
+ <div className={s.legend} aria-label="Chart legend">
436
+ {items.map((item, index) => (
437
+ <div key={`${item.key}-${index}`} className={s.legend_item}>
379
438
  <span className={s.legend_dot} style={{ backgroundColor: item.color }} />
380
- <span>{item.label}</span>
439
+ <span title={item.label}>{item.label}</span>
381
440
  </div>
382
441
  ))}
383
442
  </div>
@@ -394,6 +453,7 @@ const renderCartesianFrame = ({
394
453
  options,
395
454
  axisConfig,
396
455
  tooltipCursor,
456
+ tooltipColorKey,
397
457
  orientation = "vertical",
398
458
  }: {
399
459
  categoryKey: string;
@@ -401,6 +461,7 @@ const renderCartesianFrame = ({
401
461
  options: ResolvedCartesianOptions;
402
462
  axisConfig: AxisRenderConfig;
403
463
  tooltipCursor: TooltipCursor;
464
+ tooltipColorKey?: string;
404
465
  orientation?: "vertical" | "horizontal";
405
466
  }): ReactNode[] => {
406
467
  const isHorizontal = orientation === "horizontal";
@@ -496,6 +557,7 @@ const renderCartesianFrame = ({
496
557
  <ChartTooltip
497
558
  valueFormatter={options.tooltipValueFormatter}
498
559
  labelFormatter={options.tooltipLabelFormatter}
560
+ colorKey={tooltipColorKey}
499
561
  />
500
562
  }
501
563
  cursor={tooltipCursor}
@@ -579,14 +641,30 @@ function BarChartRenderer({
579
641
  const topStackSeriesKeys = resolveStackTopSeriesKeys(preparedSeries);
580
642
  const usesCategoryColorMap =
581
643
  preparedSeries.length === 1 && !series?.length && Boolean(colors);
582
- const legendItems = toLegendItems(preparedSeries);
644
+ const legendItems = usesCategoryColorMap
645
+ ? toCategoryLegendItems({
646
+ data,
647
+ categoryKey,
648
+ colors,
649
+ fallbackColor: preparedSeries[0]?.color ?? palette.primary,
650
+ })
651
+ : toLegendItems(preparedSeries);
583
652
  const isHorizontal = orientation === "horizontal";
653
+ const chartData: Array<ChartDatum & { __color?: string }> = usesCategoryColorMap
654
+ ? data.map((entry) => {
655
+ const key = toLookupKey(entry[categoryKey]);
656
+ return {
657
+ ...entry,
658
+ __color: resolveColorToken(colors?.[key], preparedSeries[0]?.color ?? palette.primary),
659
+ };
660
+ })
661
+ : data;
584
662
 
585
663
  return (
586
664
  <>
587
665
  <ResponsiveContainer width="100%" height={height}>
588
666
  <RechartsBarChart
589
- data={data}
667
+ data={chartData}
590
668
  layout={isHorizontal ? "vertical" : "horizontal"}
591
669
  margin={CARTESIAN_MARGIN}
592
670
  {...(barCategoryGap !== undefined ? { barCategoryGap } : {})}
@@ -597,6 +675,7 @@ function BarChartRenderer({
597
675
  options,
598
676
  axisConfig,
599
677
  tooltipCursor: { fill: palette.cursor },
678
+ tooltipColorKey: usesCategoryColorMap ? "__color" : undefined,
600
679
  orientation,
601
680
  })}
602
681
 
@@ -612,9 +691,10 @@ function BarChartRenderer({
612
691
  yAxisId={options.showYAxis ? item.yAxisId : undefined}
613
692
  >
614
693
  {usesCategoryColorMap &&
615
- data.map((entry, index) => {
694
+ chartData.map((entry, index) => {
616
695
  const key = toLookupKey(entry[categoryKey]);
617
- const fill = resolveColorToken(colors?.[key], item.color);
696
+ const fill =
697
+ typeof entry.__color === "string" ? entry.__color : item.color;
618
698
  return <Cell key={`${item.key}-${key}-${index}`} fill={fill} />;
619
699
  })}
620
700
  </Bar>
@@ -967,29 +1047,28 @@ function DonutChartRenderer({
967
1047
  }: DonutChartProps & { height: number }) {
968
1048
  const palette = createChartPalette();
969
1049
 
970
- const chartData = data.map((entry) => ({
971
- ...entry,
972
- __chartValue:
973
- typeof entry[dataKey] === "number"
974
- ? (entry[dataKey] as number)
975
- : Number(entry[dataKey] ?? 0) || 0,
976
- }));
977
-
978
- const legendItems: LegendItem[] = data.map((entry, index) => {
1050
+ const chartData = data.map((entry, index) => {
979
1051
  const rawLabel = entry[nameKey];
980
1052
  const label =
981
1053
  rawLabel !== undefined && rawLabel !== null && tooltipLabelFormatter
982
1054
  ? tooltipLabelFormatter(rawLabel as string | number)
983
1055
  : String(rawLabel ?? `Item ${index + 1}`);
984
1056
  const lookup = toLookupKey(rawLabel);
1057
+ const color = resolveColorToken(colors?.[lookup], pickSeriesColor(palette, index));
985
1058
  return {
986
- key: label,
987
- label,
988
- // Fix: use series color rotation, not palette.muted, for uncolored segments
989
- color: resolveColorToken(colors?.[lookup], pickSeriesColor(palette, index)),
1059
+ ...entry,
1060
+ __chartValue: Math.max(0, toFiniteNumber(entry[dataKey])),
1061
+ __color: color,
1062
+ __label: label,
990
1063
  };
991
1064
  });
992
1065
 
1066
+ const legendItems: LegendItem[] = chartData.map((entry) => ({
1067
+ key: entry.__label,
1068
+ label: entry.__label,
1069
+ color: entry.__color,
1070
+ }));
1071
+
993
1072
  const resolvedOuterRadius = Math.max(outerRadius ?? Math.max(height * 0.34, 88), 36);
994
1073
  const resolvedInnerRadius = Math.max(
995
1074
  16,
@@ -1024,6 +1103,8 @@ function DonutChartRenderer({
1024
1103
  <ChartTooltip
1025
1104
  valueFormatter={tooltipValueFormatter}
1026
1105
  labelFormatter={tooltipLabelFormatter}
1106
+ nameKey="__label"
1107
+ colorKey="__color"
1027
1108
  />
1028
1109
  }
1029
1110
  />
@@ -1065,9 +1146,7 @@ function RadialBarChartRenderer({
1065
1146
  const lookup = toLookupKey(rawLabel);
1066
1147
  const color = resolveColorToken(colors?.[lookup], pickSeriesColor(palette, index));
1067
1148
  const value =
1068
- typeof entry[dataKey] === "number"
1069
- ? (entry[dataKey] as number)
1070
- : Number(entry[dataKey] ?? 0) || 0;
1149
+ Math.max(0, toFiniteNumber(entry[dataKey]));
1071
1150
  return {
1072
1151
  ...entry,
1073
1152
  __value: value,
@@ -1082,7 +1161,10 @@ function RadialBarChartRenderer({
1082
1161
  color: item.__color,
1083
1162
  }));
1084
1163
 
1085
- const domainMax = maxValue ?? Math.max(...chartData.map((d) => d.__value), 1);
1164
+ const domainMax =
1165
+ typeof maxValue === "number" && Number.isFinite(maxValue) && maxValue > 0
1166
+ ? maxValue
1167
+ : Math.max(...chartData.map((d) => d.__value), 1);
1086
1168
 
1087
1169
  return (
1088
1170
  <>
@@ -1111,7 +1193,8 @@ function RadialBarChartRenderer({
1111
1193
  <ChartTooltip
1112
1194
  valueFormatter={tooltipValueFormatter}
1113
1195
  labelFormatter={tooltipLabelFormatter}
1114
- nameKey={nameKey}
1196
+ nameKey="__label"
1197
+ colorKey="__color"
1115
1198
  />
1116
1199
  }
1117
1200
  />
@@ -1228,7 +1311,10 @@ const EMPTY_STATE_GRACE_MS = 150;
1228
1311
 
1229
1312
  export function Chart(props: ChartProps) {
1230
1313
  const { title, description, className, emptyMessage, isLoading = false } = props;
1231
- const height = props.height ?? DEFAULT_CHART_HEIGHT;
1314
+ const height =
1315
+ typeof props.height === "number" && Number.isFinite(props.height)
1316
+ ? Math.max(120, props.height)
1317
+ : DEFAULT_CHART_HEIGHT;
1232
1318
 
1233
1319
  const isEmpty =
1234
1320
  props.type === "scatter"
@@ -1,7 +1,4 @@
1
- /* This file contains basic / common heirarchy for all input fields */
2
-
3
- /* contains form field (with label) and field message (errors info etc.) */
4
- .container {
1
+ .container {
5
2
  width: 100%;
6
3
  min-width: fit-content;
7
4
  display: flex;
@@ -17,8 +14,7 @@
17
14
  }
18
15
  }
19
16
 
20
- /* contains form field elements like label etc... */
21
- .field_container {
17
+ .field_container {
22
18
  width: 100%;
23
19
  display: flex;
24
20
  flex-direction: column;
@@ -35,8 +31,7 @@
35
31
  gap: var(--spacing-2);
36
32
  }
37
33
 
38
- /* layout */
39
- &.inline {
34
+ &.inline {
40
35
  flex-direction: row;
41
36
  align-items: center;
42
37
  gap: var(--spacing-3);
@@ -44,17 +39,13 @@
44
39
 
45
40
  .label {
46
41
  flex-direction: column;
47
- /* margin-inline: unset; */
48
- }
49
-
50
- /* direction */
51
- &.rev {
52
- flex-direction: row-reverse;
53
-
54
- /* due to reverse direction it will become flex-end */
55
- justify-content: flex-end;
56
- }
57
- }
42
+ }
43
+
44
+ &.rev {
45
+ flex-direction: row-reverse;
46
+ justify-content: flex-end;
47
+ }
48
+ }
58
49
 
59
50
  /* layout: centered - column-stacked with horizontally centered control + label. */
60
51
  &.centered {
@@ -66,8 +57,7 @@
66
57
  }
67
58
  }
68
59
 
69
- /* layout */
70
- &.inline_justify {
60
+ &.inline_justify {
71
61
  flex-direction: row;
72
62
  align-items: center;
73
63
  gap: var(--spacing-3);
@@ -83,8 +73,7 @@
83
73
  /* margin-inline: unset; */
84
74
  }
85
75
 
86
- /* direction */
87
- &.rev {
76
+ &.rev {
88
77
  flex-direction: row-reverse;
89
78
 
90
79
  .field_wrapper {
@@ -115,8 +104,7 @@
115
104
  align-self: center;
116
105
  }
117
106
 
118
- /* mostly for positining to set icons inside input fields */
119
- .field_wrapper {
107
+ .field_wrapper {
120
108
  --field-content-color: var(--color-foreground);
121
109
  --field-placeholder-color: var(--color-muted-foreground);
122
110
  --field-icon-color: var(--color-secondary-foreground);
@@ -125,12 +113,11 @@
125
113
  position: relative;
126
114
  display: inline-flex;
127
115
 
128
- /* Action Padding Mathematics Metrics */
129
- --action-inset: var(--spacing-5); /* Exact match for right: var(--spacing-5) */
130
- --action-icon: var(--spacing-8); /* Safe optical width for 24px SVGs */
131
- --action-gap: var(--spacing-2); /* Exact match for flex gap */
132
- --action-clearance: var(--spacing-3); /* Crisp 6px optical breathing room */
133
- }
116
+ --action-inset: var(--spacing-5);
117
+ --action-icon: var(--spacing-8);
118
+ --action-gap: var(--spacing-2);
119
+ --action-clearance: var(--spacing-3);
120
+ }
134
121
 
135
122
  .field_wrapper_variant {
136
123
  --field-content-color: var(--button-fg, var(--color-foreground));
@@ -141,8 +128,7 @@
141
128
  --field-icon-color: var(--button-icon, var(--field-content-color));
142
129
  }
143
130
 
144
- /* icons wrapped in span at start like search etc... */
145
- .icon_start {
131
+ .icon_start {
146
132
  width: fit-content;
147
133
  position: absolute;
148
134
  top: 50%;
@@ -156,8 +142,7 @@
156
142
  color: var(--field-icon-color);
157
143
  }
158
144
 
159
- /* action buttons at end like cross password eyes etc... */
160
- .action_end_wrapper {
145
+ .action_end_wrapper {
161
146
  width: fit-content;
162
147
  display: flex;
163
148
  align-items: center;
@@ -169,34 +154,26 @@
169
154
  flex-shrink: 0;
170
155
  --icon-color: var(--field-icon-color);
171
156
  color: var(--field-icon-color);
172
-
173
- /* icons */
174
- }
175
-
176
- /* default style */
177
- .field_default {
178
- /* layout */
179
- width: 100%;
180
- min-height: var(--spacing-11);
181
-
182
- /* typography */
183
- font-family: var(--font-family-1);
184
- font-size: var(--font-size-sm);
185
- color: var(--field-content-color);
157
+ }
158
+
159
+ .field_default {
160
+ width: 100%;
161
+ min-height: var(--spacing-11);
162
+
163
+ font-family: var(--font-family-1);
164
+ font-size: var(--font-size-sm);
165
+ color: var(--field-content-color);
186
166
  text-align: start;
187
167
  vertical-align: middle;
188
168
 
189
- /* necessary */
190
- line-height: 1.125;
191
-
192
- /* visual */
193
- padding-top: var(--spacing-3);
194
- padding-bottom: var(--spacing-3);
195
- padding-left: var(--spacing-6);
196
- padding-right: var(--spacing-6);
197
-
198
- /* display */
199
- display: flex;
169
+ line-height: 1.125;
170
+
171
+ padding-top: var(--spacing-3);
172
+ padding-bottom: var(--spacing-3);
173
+ padding-left: var(--spacing-6);
174
+ padding-right: var(--spacing-6);
175
+
176
+ display: flex;
200
177
  align-items: center;
201
178
  justify-content: flex-start;
202
179
  gap: var(--spacing-4);
@@ -206,8 +183,7 @@
206
183
  outline: none;
207
184
  background-color: var(--color-muted);
208
185
 
209
- /* interaction */
210
- transition:
186
+ transition:
211
187
  border-color var(--transition-base),
212
188
  box-shadow var(--transition-base),
213
189
  background-color var(--transition-base);
@@ -231,9 +207,7 @@
231
207
  cursor: not-allowed;
232
208
  opacity: 0.5;
233
209
  }
234
-
235
- /* we need to adjust paddings of input or select fields inline dynamically due to icons at start and ends */
236
- }
210
+ }
237
211
 
238
212
  .field_button_variant {
239
213
  color: var(--field-content-color);