@kolkrabbi/kol-component 0.5.0 → 0.7.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 (97) hide show
  1. package/package.json +5 -3
  2. package/src/atoms/Button.jsx +9 -5
  3. package/src/atoms/Input.jsx +9 -6
  4. package/src/atoms/Textarea.jsx +36 -5
  5. package/src/atoms/ToggleSwitch.jsx +31 -4
  6. package/src/chess/ChessPiece.jsx +191 -0
  7. package/src/chess/apparatus/AlternativeControlsMock.jsx +460 -0
  8. package/src/chess/apparatus/ChessAnalysisLayout.jsx +24 -0
  9. package/src/chess/apparatus/ChessBoard.jsx +210 -0
  10. package/src/chess/apparatus/ChessBoardFullscreen.jsx +49 -0
  11. package/src/chess/apparatus/ChessBoardWithControls.jsx +41 -0
  12. package/src/chess/apparatus/ChessBoardWithSidebar.jsx +122 -0
  13. package/src/chess/apparatus/ChessSidebar.jsx +131 -0
  14. package/src/chess/apparatus/GameArchiveTable.jsx +493 -0
  15. package/src/chess/apparatus/GameSelector.jsx +47 -0
  16. package/src/chess/apparatus/NotationPanel.jsx +70 -0
  17. package/src/chess/apparatus/PlaybackControls.jsx +52 -0
  18. package/src/chess/apparatus/VariationTree.jsx +137 -0
  19. package/src/chess/assets/chess-extra-set/set-1/bishop-1.svg +6 -0
  20. package/src/chess/assets/chess-extra-set/set-1/bishop.svg +6 -0
  21. package/src/chess/assets/chess-extra-set/set-1/king-1.svg +9 -0
  22. package/src/chess/assets/chess-extra-set/set-1/king.svg +7 -0
  23. package/src/chess/assets/chess-extra-set/set-1/knight-1.svg +8 -0
  24. package/src/chess/assets/chess-extra-set/set-1/knight.svg +7 -0
  25. package/src/chess/assets/chess-extra-set/set-1/pawn-1.svg +3 -0
  26. package/src/chess/assets/chess-extra-set/set-1/pawn.svg +3 -0
  27. package/src/chess/assets/chess-extra-set/set-1/queen-1.svg +11 -0
  28. package/src/chess/assets/chess-extra-set/set-1/queen.svg +6 -0
  29. package/src/chess/assets/chess-extra-set/set-1/rook-1.svg +7 -0
  30. package/src/chess/assets/chess-extra-set/set-1/rook.svg +11 -0
  31. package/src/chess/assets/chess-extra-set/set-2/bishop-1.svg +4 -0
  32. package/src/chess/assets/chess-extra-set/set-2/bishop.svg +4 -0
  33. package/src/chess/assets/chess-extra-set/set-2/king-1.svg +4 -0
  34. package/src/chess/assets/chess-extra-set/set-2/king.svg +4 -0
  35. package/src/chess/assets/chess-extra-set/set-2/knight-1.svg +5 -0
  36. package/src/chess/assets/chess-extra-set/set-2/knight.svg +5 -0
  37. package/src/chess/assets/chess-extra-set/set-2/pawn-1.svg +4 -0
  38. package/src/chess/assets/chess-extra-set/set-2/pawn.svg +4 -0
  39. package/src/chess/assets/chess-extra-set/set-2/queen-1.svg +4 -0
  40. package/src/chess/assets/chess-extra-set/set-2/queen.svg +4 -0
  41. package/src/chess/assets/chess-extra-set/set-2/rook-1.svg +5 -0
  42. package/src/chess/assets/chess-extra-set/set-2/rook.svg +5 -0
  43. package/src/chess/assets/chess-extra-set/set-3/bishop-1.svg +10 -0
  44. package/src/chess/assets/chess-extra-set/set-3/bishop.svg +3 -0
  45. package/src/chess/assets/chess-extra-set/set-3/king-1.svg +12 -0
  46. package/src/chess/assets/chess-extra-set/set-3/king.svg +3 -0
  47. package/src/chess/assets/chess-extra-set/set-3/knight-1.svg +3 -0
  48. package/src/chess/assets/chess-extra-set/set-3/knight.svg +10 -0
  49. package/src/chess/assets/chess-extra-set/set-3/pawn-1.svg +10 -0
  50. package/src/chess/assets/chess-extra-set/set-3/pawn.svg +10 -0
  51. package/src/chess/assets/chess-extra-set/set-3/queen-1.svg +10 -0
  52. package/src/chess/assets/chess-extra-set/set-3/queen.svg +3 -0
  53. package/src/chess/assets/chess-extra-set/set-3/rook-1.svg +3 -0
  54. package/src/chess/assets/chess-extra-set/set-3/rook.svg +11 -0
  55. package/src/chess/assets/chess-vector-set/ABoard.svg +164 -0
  56. package/src/chess/assets/chess-vector-set/BBiskup.svg +12 -0
  57. package/src/chess/assets/chess-vector-set/BKing.svg +15 -0
  58. package/src/chess/assets/chess-vector-set/BKnight.svg +13 -0
  59. package/src/chess/assets/chess-vector-set/BPawn.svg +7 -0
  60. package/src/chess/assets/chess-vector-set/BQueen.svg +6 -0
  61. package/src/chess/assets/chess-vector-set/BRook.svg +12 -0
  62. package/src/chess/assets/chess-vector-set/WBiskup.svg +14 -0
  63. package/src/chess/assets/chess-vector-set/WKing.svg +13 -0
  64. package/src/chess/assets/chess-vector-set/WKnight.svg +10 -0
  65. package/src/chess/assets/chess-vector-set/WPawn.svg +8 -0
  66. package/src/chess/assets/chess-vector-set/WQueen.svg +17 -0
  67. package/src/chess/assets/chess-vector-set/WRook.svg +13 -0
  68. package/src/chess/context/ChessControlsContext.jsx +379 -0
  69. package/src/chess/dashboards/ChessHero.jsx +303 -0
  70. package/src/chess/index.js +32 -0
  71. package/src/chess/utils/parsePgnTree.js +97 -0
  72. package/src/dashboards/cards/DashAlertCard.jsx +44 -0
  73. package/src/dashboards/cards/DashChartCard.jsx +44 -0
  74. package/src/dashboards/cards/DashFeaturedCard.jsx +42 -0
  75. package/src/dashboards/cards/DashListCard.jsx +87 -0
  76. package/src/dashboards/cards/DashMetricCard.jsx +59 -0
  77. package/src/dashboards/cards/DashSlotCard.jsx +45 -0
  78. package/src/dashboards/cards/DashStackedBarCard.jsx +70 -0
  79. package/src/dashboards/cards/DashTableCard.jsx +31 -0
  80. package/src/dashboards/cards/_shared/CardHeader.jsx +15 -0
  81. package/src/dashboards/cards/_shared/LegendRow.jsx +25 -0
  82. package/src/dashboards/charts/Candlestick.jsx +79 -0
  83. package/src/dashboards/charts/DonutChart.jsx +87 -0
  84. package/src/dashboards/charts/Heatmap.jsx +79 -0
  85. package/src/dashboards/charts/Histogram.jsx +56 -0
  86. package/src/dashboards/charts/LineChart.jsx +157 -0
  87. package/src/dashboards/charts/ScatterPlot.jsx +93 -0
  88. package/src/dashboards/charts/Sparkline.jsx +63 -0
  89. package/src/dashboards/index.js +28 -0
  90. package/src/dashboards/layout/DashboardGrid.jsx +30 -0
  91. package/src/dashboards/layout/GridCard.jsx +44 -0
  92. package/src/dashboards/shared/DashTooltip.jsx +6 -0
  93. package/src/dashboards/shared/formatMetric.js +26 -0
  94. package/src/dashboards/shared/useChartTooltip.js +25 -0
  95. package/src/dashboards/shared/useCountUp.js +107 -0
  96. package/src/molecules/Dropdown.jsx +50 -96
  97. package/src/molecules/Slider.jsx +4 -14
@@ -0,0 +1,25 @@
1
+ import { useState, useCallback, useRef } from 'react'
2
+
3
+ const useChartTooltip = () => {
4
+ const [activeIndex, setActiveIndex] = useState(null)
5
+ const containerRef = useRef(null)
6
+
7
+ const containerHandlers = {
8
+ onMouseMove: (e) => {
9
+ if (!containerRef.current) return
10
+ const rect = containerRef.current.getBoundingClientRect()
11
+ containerRef.current.style.setProperty('--tx', `${e.clientX - rect.left}px`)
12
+ containerRef.current.style.setProperty('--ty', `${e.clientY - rect.top}px`)
13
+ },
14
+ onMouseLeave: () => setActiveIndex(null)
15
+ }
16
+
17
+ const handlers = useCallback((index) => ({
18
+ onMouseEnter: () => setActiveIndex(index),
19
+ onMouseLeave: () => setActiveIndex(null)
20
+ }), [])
21
+
22
+ return { activeIndex, handlers, containerHandlers, containerRef }
23
+ }
24
+
25
+ export default useChartTooltip
@@ -0,0 +1,107 @@
1
+ import { useState, useEffect, useRef } from 'react'
2
+
3
+ const parseNumeric = (value) => {
4
+ const str = String(value)
5
+ const match = str.match(/^([^0-9]*?)([\d,.]+)(.*?)$/)
6
+ if (!match) return null
7
+ const prefix = match[1]
8
+ const numStr = match[2]
9
+ const suffix = match[3]
10
+ const num = parseFloat(numStr.replace(/,/g, ''))
11
+ if (isNaN(num)) return null
12
+ const hasCommas = numStr.includes(',')
13
+ const decimalMatch = numStr.match(/\.(\d+)/)
14
+ const decimals = decimalMatch ? decimalMatch[1].length : 0
15
+ return { prefix, num, suffix, hasCommas, decimals }
16
+ }
17
+
18
+ const formatNumber = (n, hasCommas, decimals) => {
19
+ const fixed = n.toFixed(decimals)
20
+ if (!hasCommas) return fixed
21
+ const [intPart, decPart] = fixed.split('.')
22
+ const withCommas = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
23
+ return decPart ? `${withCommas}.${decPart}` : withCommas
24
+ }
25
+
26
+ const useCountUp = (targetValue, { duration = 600, enabled = true } = {}) => {
27
+ const [displayValue, setDisplayValue] = useState(targetValue)
28
+ const ref = useRef(null)
29
+ const hasEnteredRef = useRef(false)
30
+ const prevTargetRef = useRef(targetValue)
31
+ const rafRef = useRef(null)
32
+ const elRef = useRef(null)
33
+
34
+ useEffect(() => {
35
+ if (!enabled) {
36
+ setDisplayValue(targetValue)
37
+ return
38
+ }
39
+
40
+ const animate = (from, to) => {
41
+ const parsed = parseNumeric(to)
42
+ if (!parsed) {
43
+ setDisplayValue(to)
44
+ return
45
+ }
46
+
47
+ const parsedFrom = parseNumeric(from)
48
+ const startNum = parsedFrom ? parsedFrom.num : 0
49
+ const endNum = parsed.num
50
+ const startTime = performance.now()
51
+
52
+ const step = (now) => {
53
+ const elapsed = now - startTime
54
+ const t = Math.min(elapsed / duration, 1)
55
+ const eased = t * (2 - t) // ease-out quadratic
56
+ const current = startNum + (endNum - startNum) * eased
57
+ const formatted = `${parsed.prefix}${formatNumber(current, parsed.hasCommas, parsed.decimals)}${parsed.suffix}`
58
+ setDisplayValue(formatted)
59
+ if (t < 1) {
60
+ rafRef.current = requestAnimationFrame(step)
61
+ }
62
+ }
63
+
64
+ if (rafRef.current) cancelAnimationFrame(rafRef.current)
65
+ rafRef.current = requestAnimationFrame(step)
66
+ }
67
+
68
+ // On target change while already visible
69
+ if (hasEnteredRef.current && prevTargetRef.current !== targetValue) {
70
+ animate(prevTargetRef.current, targetValue)
71
+ prevTargetRef.current = targetValue
72
+ return
73
+ }
74
+
75
+ prevTargetRef.current = targetValue
76
+
77
+ // IntersectionObserver for first entry
78
+ if (hasEnteredRef.current) return
79
+
80
+ const el = elRef.current
81
+ if (!el) {
82
+ setDisplayValue(targetValue)
83
+ return
84
+ }
85
+
86
+ const observer = new IntersectionObserver(
87
+ ([entry]) => {
88
+ if (entry.isIntersecting && !hasEnteredRef.current) {
89
+ hasEnteredRef.current = true
90
+ animate('0', targetValue)
91
+ observer.disconnect()
92
+ }
93
+ },
94
+ { threshold: 0.1 }
95
+ )
96
+ observer.observe(el)
97
+
98
+ return () => {
99
+ observer.disconnect()
100
+ if (rafRef.current) cancelAnimationFrame(rafRef.current)
101
+ }
102
+ }, [targetValue, duration, enabled])
103
+
104
+ return { displayValue, ref: elRef }
105
+ }
106
+
107
+ export default useCountUp
@@ -3,20 +3,34 @@ import { Icon } from '@kolkrabbi/kol-icons'
3
3
  import { MenuDropdownItem } from './MenuItem.jsx'
4
4
  import { PopoverPanel, usePopover } from '../atoms/Popover.jsx'
5
5
 
6
- const SIZE_MAP = {
7
- sm: { fontSize: 12, paddingY: 4, paddingX: 12, radius: 14, panelRadius: 14, icon: 10 },
8
- md: { fontSize: 12, paddingY: 6, paddingX: 16, radius: 22, panelRadius: 22, icon: 12 },
9
- lg: { fontSize: 14, paddingY: 8, paddingX: 20, radius: 24, panelRadius: 24, icon: 14 }
10
- }
11
-
12
- const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-12', lg: 'kol-mono-14' }
6
+ /**
7
+ * Dropdown trigger IS button chrome (2026-07-08 chrome law).
8
+ *
9
+ * The trigger emits `kol-btn kol-btn-{variant} kol-btn-{size}` so it renders
10
+ * pixel-identical to a Button of the same variant/size — fills, hover,
11
+ * active, focus ring all come from the button rules in kol-theme.
12
+ * `.kol-dd-*` classes only add trigger layout + the open/panel fusion.
13
+ *
14
+ * variant="primary" (default) — filled trigger; open panel continues the
15
+ * same fill (one piece: no border, no gap, hairline divider inside)
16
+ * variant="outline" — bordered trigger; open panel carries the
17
+ * same border, trigger's bottom edge acts as the divider
18
+ *
19
+ * Legacy aliases (pre-law variants, kept so call-sites don't break):
20
+ * default → primary · subtle → primary · minimal → outline
21
+ */
22
+
23
+ const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }
24
+ const ICON_SIZE = { sm: 14, md: 16, lg: 18 }
25
+
26
+ const LEGACY_VARIANTS = { default: 'primary', subtle: 'primary', minimal: 'outline' }
13
27
 
14
28
  const Dropdown = ({
15
29
  options = [],
16
30
  value,
17
31
  onChange,
18
32
  size,
19
- variant = 'default',
33
+ variant = 'primary',
20
34
  defaultOpen = false,
21
35
  className = ''
22
36
  }) => {
@@ -24,15 +38,17 @@ const Dropdown = ({
24
38
  const [resolvedSize, setResolvedSize] = useState('md')
25
39
  const [dropdownWidth, setDropdownWidth] = useState('100px')
26
40
 
41
+ const resolvedVariant = LEGACY_VARIANTS[variant] || variant
42
+
27
43
  /* Floating-ui popover. `flip: false` keeps the panel below the button
28
- * — the seamless border-radius edge between button and panel assumes
29
- * the panel sits below; flipping above would visually disconnect them.
44
+ * — the seamless fused edge between trigger and panel assumes the panel
45
+ * sits below; flipping above would visually disconnect them.
30
46
  * `matchReferenceWidth: true` pins panel min-width to the button. */
31
47
  const popover = usePopover({
32
48
  open: isOpen,
33
49
  onOpenChange: setIsOpen,
34
50
  placement: 'bottom-start',
35
- offset: variant === 'minimal' ? 0 : -1,
51
+ offset: -1,
36
52
  flip: false,
37
53
  matchReferenceWidth: true,
38
54
  role: 'listbox',
@@ -67,63 +83,23 @@ const Dropdown = ({
67
83
  }
68
84
  }, [size])
69
85
 
70
- // Width management for variants
86
+ // Width management 100px mobile, 140px tablet, 180px desktop
71
87
  useEffect(() => {
72
88
  const updateWidth = () => {
73
89
  if (typeof window === 'undefined') return
74
90
 
75
- if (variant === 'minimal' || variant === 'subtle') {
76
- // Minimal/subtle: 100px mobile, 140px tablet+
77
- setDropdownWidth(window.innerWidth >= 768 ? '140px' : '100px')
78
- } else if (variant === 'default') {
79
- // Default: 100px mobile, 140px tablet, 180px desktop
80
- if (window.innerWidth >= 1024) {
81
- setDropdownWidth('180px')
82
- } else if (window.innerWidth >= 768) {
83
- setDropdownWidth('140px')
84
- } else {
85
- setDropdownWidth('100px')
86
- }
91
+ if (window.innerWidth >= 1024) {
92
+ setDropdownWidth('180px')
93
+ } else if (window.innerWidth >= 768) {
94
+ setDropdownWidth('140px')
95
+ } else {
96
+ setDropdownWidth('100px')
87
97
  }
88
98
  }
89
99
  updateWidth()
90
100
  window.addEventListener('resize', updateWidth)
91
101
  return () => window.removeEventListener('resize', updateWidth)
92
- }, [variant])
93
-
94
- const metrics = SIZE_MAP[resolvedSize] || SIZE_MAP.md
95
-
96
- // Variant-specific styles
97
- const variantStyles = {
98
- default: {
99
- border: '1px solid var(--kol-border-default)',
100
- borderRadius: isOpen
101
- ? `${metrics.radius}px ${metrics.radius}px 0 0`
102
- : `${metrics.radius}px`,
103
- backgroundColor: 'var(--kol-surface-primary)',
104
- padding: `${metrics.paddingY}px ${metrics.paddingX}px`
105
- },
106
- minimal: {
107
- border: 'none',
108
- borderRadius: '0',
109
- backgroundColor: 'transparent',
110
- padding: '0',
111
- height: '24px',
112
- display: 'flex',
113
- alignItems: 'center'
114
- },
115
- subtle: {
116
- /* 1px transparent border so total height matches Button + Input + the
117
- * other shared-control atoms (which have a transparent 1px border for
118
- * hover/focus consistency). Without this, subtle is 2px shorter. */
119
- border: '1px solid transparent',
120
- borderRadius: isOpen ? '4px 4px 0 0' : '4px',
121
- backgroundColor: 'var(--kol-surface-secondary)',
122
- padding: `${metrics.paddingY}px ${metrics.paddingX}px`
123
- }
124
- }
125
-
126
- const styles = variantStyles[variant] || variantStyles.default
102
+ }, [])
127
103
 
128
104
  const handleSelect = (option) => {
129
105
  onChange?.(option.value)
@@ -132,11 +108,20 @@ const Dropdown = ({
132
108
 
133
109
  const currentOption = options.find((opt) => opt.value === value) || options[0]
134
110
 
111
+ const triggerCls = [
112
+ 'kol-btn',
113
+ `kol-btn-${resolvedVariant}`,
114
+ `kol-btn-${resolvedSize}`,
115
+ SIZE_TYPE[resolvedSize],
116
+ 'kol-dd-trigger',
117
+ isOpen && 'kol-dd-trigger--open',
118
+ ].filter(Boolean).join(' ')
119
+
135
120
  return (
136
121
  <div
137
122
  className={`relative block ${className}`}
138
123
  style={{
139
- ...((variant === 'minimal' || variant === 'default' || variant === 'subtle') && dropdownWidth && !className.includes('w-full') && {
124
+ ...(dropdownWidth && !className.includes('w-full') && {
140
125
  width: dropdownWidth,
141
126
  minWidth: dropdownWidth
142
127
  })
@@ -146,26 +131,15 @@ const Dropdown = ({
146
131
  ref={popover.refs.setReference}
147
132
  {...popover.getReferenceProps()}
148
133
  type="button"
149
- className={`w-full flex items-center justify-between transition-colors duration-200 ${SIZE_TYPE[resolvedSize]}`}
150
- style={{
151
- border: styles.border,
152
- borderRadius: styles.borderRadius,
153
- backgroundColor: styles.backgroundColor,
154
- color: 'var(--kol-surface-on-primary)',
155
- padding: styles.padding,
156
- transition: 'background-color 0.2s, color 0.2s, border-color 0.2s',
157
- ...(variant === 'minimal' && {
158
- height: styles.height,
159
- }),
160
- }}
134
+ className={triggerCls}
161
135
  aria-haspopup="listbox"
162
136
  aria-expanded={isOpen}
163
137
  data-state={isOpen ? 'open' : 'closed'}
164
138
  >
165
- <span className="opacity-100">{currentOption?.label}</span>
139
+ <span>{currentOption?.label}</span>
166
140
  <Icon
167
141
  name="chevron-down"
168
- size={metrics.icon}
142
+ size={ICON_SIZE[resolvedSize]}
169
143
  className="ml-auto"
170
144
  style={{
171
145
  transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
@@ -178,29 +152,9 @@ const Dropdown = ({
178
152
  popover={popover}
179
153
  panel={false}
180
154
  focus={false}
181
- style={{
182
- backgroundColor: variant === 'minimal'
183
- ? 'var(--kol-surface-primary)'
184
- : styles.backgroundColor,
185
- color: 'var(--kol-surface-on-primary)',
186
- border: variant === 'subtle' ? 'none' : styles.border,
187
- borderRadius: variant === 'minimal'
188
- ? '0'
189
- : (variant === 'subtle'
190
- ? '0 0 4px 4px'
191
- : `0 0 ${metrics.panelRadius}px ${metrics.panelRadius}px`),
192
- }}
155
+ className={`kol-dd-panel kol-dd-panel--${resolvedVariant}`}
193
156
  >
194
- {variant !== 'minimal' && (
195
- <div style={{ padding: `0 ${metrics.paddingX}px` }}>
196
- <div
197
- style={{
198
- height: '1px',
199
- backgroundColor: 'var(--kol-border-default)'
200
- }}
201
- />
202
- </div>
203
- )}
157
+ {resolvedVariant === 'primary' && <div className="kol-dd-div" />}
204
158
 
205
159
  <div className="flex max-h-[300px] flex-col items-stretch overflow-y-auto" role="listbox">
206
160
  {options.map((option) => {
@@ -4,11 +4,9 @@ import Input from '../atoms/Input.jsx'
4
4
  /**
5
5
  * Slider — range slider with label and an editable value readout.
6
6
  *
7
- * Variants (track/shell styling):
8
- * default bordered track + boxed value.
9
- * minimal bare track + boxed value. 99% of real usage (foundry previews,
10
- * inline controls). PRESERVED from web.
11
- * subtle — filled rounded chip; for inspector-style controls.
7
+ * One bare inline row: label · track · editable readout. (Bordered
8
+ * `default` and chip `subtle` variants retired 2026-07-08 — minimal is
9
+ * the only slider.)
12
10
  *
13
11
  * The value readout is an editable <Input> (type a value, commit on
14
12
  * blur / Enter, revert on Escape). Track color is exposed as the
@@ -21,7 +19,6 @@ import Input from '../atoms/Input.jsx'
21
19
  * @param {number} props.max - Maximum value
22
20
  * @param {number} props.value - Current value
23
21
  * @param {Function} props.onChange - Change handler
24
- * @param {'default'|'minimal'|'subtle'} props.variant - Visual variant (default: 'default')
25
22
  * @param {string} props.className - Additional wrapper classes
26
23
  * @param {number} props.displayWidth - Width of the value readout, in characters (default: 6)
27
24
  * @param {string} props.fontSize - Font size for label/value (e.g., '11px')
@@ -34,7 +31,6 @@ const Slider = ({
34
31
  max = 100,
35
32
  value = 0,
36
33
  onChange,
37
- variant = 'default',
38
34
  className = '',
39
35
  displayWidth = 6,
40
36
  fontSize,
@@ -47,12 +43,6 @@ const Slider = ({
47
43
  }
48
44
  }
49
45
 
50
- const variantClass = variant === 'minimal'
51
- ? 'control-slider-minimal'
52
- : variant === 'subtle'
53
- ? 'control-slider-subtle'
54
- : 'control-slider'
55
-
56
46
  const decimals = useMemo(() => {
57
47
  if (formatValue) return null
58
48
  if (!Number.isFinite(step)) return 0
@@ -94,7 +84,7 @@ const Slider = ({
94
84
  }
95
85
 
96
86
  return (
97
- <div className={`${variantClass} gap-3 shadow-none ${className}`}>
87
+ <div className={`control-slider gap-3 shadow-none ${className}`}>
98
88
  {label && (
99
89
  <label className="kol-helper-12 whitespace-nowrap shrink-0 w-fit" style={fontSize ? { fontSize } : undefined}>
100
90
  {label}