@kolkrabbi/kol-component 0.159.0 → 0.161.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.
- package/package.json +1 -1
- package/src/atoms/Badge.jsx +2 -1
- package/src/atoms/IconFrame.jsx +1 -1
- package/src/atoms/SegmentedToggle.jsx +1 -1
- package/src/atoms/Tag.jsx +2 -2
- package/src/atoms/Textarea.jsx +1 -1
- package/src/atoms/ToggleSwitch.jsx +4 -3
- package/src/molecules/Dropdown.jsx +4 -1
- package/src/molecules/MenuItem.jsx +9 -2
- package/src/molecules/SearchInput.jsx +2 -2
- package/src/molecules/Stepper.jsx +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-component",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.161.0",
|
|
4
4
|
"description": "KOL design-system components — atoms through organisms, emitting canonical kol-* classes. Pairs with @kolkrabbi/kol-theme for styling.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/atoms/Badge.jsx
CHANGED
|
@@ -23,12 +23,13 @@ const VARIANT_MAP = {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const SIZE_MAP = {
|
|
26
|
+
xs: 'kol-badge-xs',
|
|
26
27
|
sm: 'kol-badge-sm',
|
|
27
28
|
md: 'kol-badge-md',
|
|
28
29
|
lg: 'kol-badge-lg'
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
const ICON_SIZES = { sm: 12, md: 14, lg: 16 }
|
|
32
|
+
const ICON_SIZES = { xs: 10, sm: 12, md: 14, lg: 16 }
|
|
32
33
|
|
|
33
34
|
const Badge = ({
|
|
34
35
|
children,
|
package/src/atoms/IconFrame.jsx
CHANGED
|
@@ -61,7 +61,7 @@ import { toneClass } from '../utilities/tone.js'
|
|
|
61
61
|
*
|
|
62
62
|
* @param {string} name icon name (kol-icons)
|
|
63
63
|
* @param {string} variant primary|secondary|accent|outline|ghost|nav|grey|danger
|
|
64
|
-
* @param {string} size sm|md|lg — square + glyph together
|
|
64
|
+
* @param {string} size xs|sm|md|lg — square + glyph together (xs = 20px square, 12 glyph; the panel rung, 2026-09-01)
|
|
65
65
|
* @param {string} radius sm (default, the system's 4px) | full (9999px).
|
|
66
66
|
* Two values, nothing between: a round frame is its
|
|
67
67
|
* own chrome idiom (edge-straddling controls, avatars),
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* className — additional classes on the outer shell
|
|
48
48
|
*/
|
|
49
49
|
export default function SegmentedToggle({ value, onChange, options = [], variant = 'default', size = 'md', ariaLabel, className = '' }) {
|
|
50
|
-
const cellType = { sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }[size]
|
|
50
|
+
const cellType = { xs: 'kol-mono-8', sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }[size]
|
|
51
51
|
const stateless = value == null
|
|
52
52
|
const focusIdx = Math.max(0, options.findIndex((opt) => opt.value === value))
|
|
53
53
|
|
package/src/atoms/Tag.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Icon } from '@kolkrabbi/kol-icons'
|
|
2
2
|
|
|
3
|
-
const ICON_SIZES = { sm: 10, md: 12, lg: 14 }
|
|
3
|
+
const ICON_SIZES = { xs: 8, sm: 10, md: 12, lg: 14 }
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Tag — the INTERACTIVE chip: filterable, selectable, removable.
|
|
@@ -35,7 +35,7 @@ const ICON_SIZES = { sm: 10, md: 12, lg: 14 }
|
|
|
35
35
|
* @param {ReactNode} children label content
|
|
36
36
|
* @param {string} text content fallback when no children (brand SwatchControls)
|
|
37
37
|
* @param {string} variant 'primary' | 'secondary' | 'inverse' · `tertiary` = secondary's fill, no outline, mono at fg-80 (2026-08-27)
|
|
38
|
-
* @param {string} size 'sm' | 'md' | 'lg' — `sm` is the default and
|
|
38
|
+
* @param {string} size 'xs' | 'sm' | 'md' | 'lg' — `sm` is the default and
|
|
39
39
|
* should stay the answer; `lg` needs a reason
|
|
40
40
|
* @param {boolean} active selected state (filter chips)
|
|
41
41
|
* @param {boolean} hash prepend `#` (default true); false for plain labels
|
package/src/atoms/Textarea.jsx
CHANGED
|
@@ -31,7 +31,7 @@ import { Icon } from '@kolkrabbi/kol-icons'
|
|
|
31
31
|
* Pairs with `<Input>` for single-line.
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
|
-
const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }
|
|
34
|
+
const SIZE_TYPE = { xs: 'kol-mono-8', sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }
|
|
35
35
|
|
|
36
36
|
export default function Textarea({
|
|
37
37
|
value,
|
|
@@ -7,15 +7,16 @@ import React from 'react'
|
|
|
7
7
|
* variant="primary" — filled shell (surface-secondary), button geometry
|
|
8
8
|
* variant="outline" — bordered shell (border-oq-16), button geometry
|
|
9
9
|
*
|
|
10
|
-
* size="sm" / "md" (default) / "lg" — shells match button heights
|
|
11
|
-
* (26/32/40); the track scales with size in all variants.
|
|
10
|
+
* size="xs" / "sm" / "md" (default) / "lg" — shells match button heights
|
|
11
|
+
* (22/26/32/40); the track scales with size in all variants. xs is the
|
|
12
|
+
* panel rung (2026-09-01).
|
|
12
13
|
*
|
|
13
14
|
* Legacy aliases: 'plain' → bare · 'default' (the old boxed look) → outline.
|
|
14
15
|
* Type via kol-mono-{12,14,16}; no auto-uppercase — casing is authored at
|
|
15
16
|
* the call site (KOL no-auto-casing rule).
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
|
-
const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }
|
|
19
|
+
const SIZE_TYPE = { xs: 'kol-mono-8', sm: 'kol-mono-12', md: 'kol-mono-14', lg: 'kol-mono-16' }
|
|
19
20
|
const LEGACY_VARIANTS = { plain: 'bare', default: 'outline' }
|
|
20
21
|
|
|
21
22
|
const ToggleSwitch = ({
|
|
@@ -184,6 +184,8 @@ const Dropdown = ({
|
|
|
184
184
|
className={`kol-dd-panel kol-dd-panel--${resolvedVariant} ${toneClass(tone)}`.trim()}
|
|
185
185
|
style={{
|
|
186
186
|
'--kol-dd-max-rows': maxRows ?? 10,
|
|
187
|
+
/* xs rows are 20px; the panel's max-height reads the row height */
|
|
188
|
+
...(resolvedSize === 'xs' && rowHeight == null ? { '--kol-dd-row-h': '20px' } : null),
|
|
187
189
|
...(rowHeight != null ? { '--kol-dd-row-h': typeof rowHeight === 'number' ? `${rowHeight}px` : rowHeight } : null),
|
|
188
190
|
}}
|
|
189
191
|
>
|
|
@@ -202,11 +204,12 @@ const Dropdown = ({
|
|
|
202
204
|
* all — and this was the last one left, the option row's ink
|
|
203
205
|
* brighten. The check mark is what marks the current value. */
|
|
204
206
|
hover={false}
|
|
207
|
+
size={resolvedSize}
|
|
205
208
|
height={rowHeight}
|
|
206
209
|
onPointerEnter={onOptionHover ? () => reportHover(option.value) : undefined}
|
|
207
210
|
onPointerLeave={onOptionHover ? () => reportHover(null) : undefined}
|
|
208
211
|
onClick={() => handleSelect(option)}
|
|
209
|
-
shortcut={isActive ? <Icon name="check" size={11} /> : undefined}
|
|
212
|
+
shortcut={isActive ? <Icon name="check" size={resolvedSize === 'xs' ? indicatorSize('xs') : 11} /> : undefined}
|
|
210
213
|
>
|
|
211
214
|
{option.label}
|
|
212
215
|
</MenuDropdownItem>
|
|
@@ -99,7 +99,14 @@ export function MenuItem({
|
|
|
99
99
|
* - children — main label, flex-1.
|
|
100
100
|
* - shortcut — trailing content (text shortcut hint, ✓ marker, or icon).
|
|
101
101
|
*/
|
|
102
|
-
|
|
102
|
+
/* the row follows the trigger's rung (DropdownXsList, kol-monitor 2026-09-01):
|
|
103
|
+
* at xs the list kept sm rows — kol-helper-12 in a 32px pitch — inside a panel
|
|
104
|
+
* fused to an 8px-type trigger, so the options truncated. One map, both ends. */
|
|
105
|
+
/* xs wears the TRIGGER's face (kol-mono-8), not the helper: the trigger's ghost
|
|
106
|
+
* stack reserves the widest label in its own face, and a row set in a different
|
|
107
|
+
* one measured 3px wider and clipped the selected row beside its check. */
|
|
108
|
+
const ROW_BY_SIZE = { xs: 'kol-mono-8 px-2 h-5', sm: 'kol-helper-12 px-3 h-8', md: 'kol-helper-12 px-3 h-8', lg: 'kol-helper-12 px-3 h-8' }
|
|
109
|
+
export function MenuDropdownItem({ onClick, onPointerEnter, onPointerLeave, disabled, prefix, iconLeft, shortcut, hover = true, height, size = 'sm', children }) {
|
|
103
110
|
return (
|
|
104
111
|
<button
|
|
105
112
|
type="button"
|
|
@@ -110,7 +117,7 @@ export function MenuDropdownItem({ onClick, onPointerEnter, onPointerLeave, disa
|
|
|
110
117
|
disabled={disabled}
|
|
111
118
|
role="menuitem"
|
|
112
119
|
style={height != null ? { height } : undefined}
|
|
113
|
-
className={`w-full
|
|
120
|
+
className={`w-full ${ROW_BY_SIZE[size] ?? ROW_BY_SIZE.sm} shrink-0 inline-flex items-center gap-2 text-body ${hover ? 'hover:text-emphasis' : ''} disabled:opacity-40 disabled:cursor-not-allowed text-left`}
|
|
114
121
|
>
|
|
115
122
|
{prefix && <span className="shrink-0 inline-flex items-center">{prefix}</span>}
|
|
116
123
|
{iconLeft && <span className="shrink-0 w-4 inline-flex items-center justify-center">{iconLeft}</span>}
|
|
@@ -33,7 +33,7 @@ import { glyphSize } from '../hooks/glyphLadders.js'
|
|
|
33
33
|
* @param {Function} onClear () => void — trailing × click; × renders only when set and value is non-empty
|
|
34
34
|
* @param {string} shortcutHint caller-authored kbd chip (e.g. "⌘K"); shown while the value is empty
|
|
35
35
|
* @param {Function} onFocus (event) => void — input focus
|
|
36
|
-
* @param {string} size 'sm' | 'md' — kol-control size + matched mono type class
|
|
36
|
+
* @param {string} size 'xs' | 'sm' | 'md' — kol-control size + matched mono type class (xs = the panel rung, 2026-09-01)
|
|
37
37
|
* @param {string} variant 'filled' | 'ghost' | 'outline' — kol-control variant, same chrome as Input (ignored when bare/expanding)
|
|
38
38
|
* @param {string} tone 'default' | 'inverse' — the dark chip for a washed plane (ControlToneInverse, 2026-08-27); on the expanding pill it is the OPEN fill
|
|
39
39
|
* @param {boolean} bare borderless inline field for overlay panels (full width, no shell chrome; keeps icon/clear/chip slots)
|
|
@@ -67,7 +67,7 @@ import { glyphSize } from '../hooks/glyphLadders.js'
|
|
|
67
67
|
*
|
|
68
68
|
* The flat `{ sm: 14, md: 14 }` it used to carry was the ADJACENT sm rung
|
|
69
69
|
* frozen for both sizes — right ladder, no size. */
|
|
70
|
-
const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-14' }
|
|
70
|
+
const SIZE_TYPE = { xs: 'kol-mono-8', sm: 'kol-mono-12', md: 'kol-mono-14' }
|
|
71
71
|
|
|
72
72
|
export default function SearchInput({
|
|
73
73
|
value = '',
|
|
@@ -12,6 +12,15 @@
|
|
|
12
12
|
* at both ends, and `onChange` reports the option in the same event shape
|
|
13
13
|
* as the number path — `{ target: { value: option } }`.
|
|
14
14
|
*
|
|
15
|
+
* layout="inline" — `‹ value ›` on ONE line (StepperInlineVariant, kol-monitor
|
|
16
|
+
* 2026-09-02; the rack's Selector shape, the other half of its collapse onto
|
|
17
|
+
* this): the chevrons flank the value as left/right hit targets, the value is
|
|
18
|
+
* centred in a 3ch floor so the row does not jitter as it steps, and there is
|
|
19
|
+
* NO `.kol-control` field chrome — it is inline text on the panel. Value
|
|
20
|
+
* `text-fg-64`, chevrons `text-fg-40`, type from the size ladder; casing is the
|
|
21
|
+
* caller's. Works for `options` and for the number range alike. Default
|
|
22
|
+
* `stacked` is the field with the chevron stack, exactly as before.
|
|
23
|
+
*
|
|
15
24
|
* Loaded from `00-kol/chevron-{up,down}.svg` via the Icon registry — first
|
|
16
25
|
* stroke icons in the kol curated set. For a plain number input without
|
|
17
26
|
* bump affordance, use `<Input type="number" />`.
|
|
@@ -28,6 +37,7 @@ export default function Stepper({
|
|
|
28
37
|
max,
|
|
29
38
|
step = 1,
|
|
30
39
|
options,
|
|
40
|
+
layout = 'stacked',
|
|
31
41
|
size = 'sm',
|
|
32
42
|
className = '',
|
|
33
43
|
style = {},
|
|
@@ -63,6 +73,23 @@ export default function Stepper({
|
|
|
63
73
|
onChange?.(e)
|
|
64
74
|
}
|
|
65
75
|
|
|
76
|
+
/* INLINE — ‹ value › with no field: the chevrons are the hit targets, the
|
|
77
|
+
* value is text on the panel. `min-w-[3ch]` holds the width across steps. */
|
|
78
|
+
if (layout === 'inline') {
|
|
79
|
+
const chev = CHEVRON_SIZE[size]
|
|
80
|
+
return (
|
|
81
|
+
<div className={`inline-flex items-center justify-center gap-0.5 select-none ${SIZE_TYPE[size]} ${className}`.trim()} style={style}>
|
|
82
|
+
<button type="button" onClick={handleDecrement} className="inline-flex items-center justify-center px-0.5 text-fg-40 hover:text-emphasis transition-colors" aria-label="Previous">
|
|
83
|
+
<Icon name="chevron-left" size={chev} />
|
|
84
|
+
</button>
|
|
85
|
+
<span className="min-w-[3ch] text-center text-fg-64" {...props}>{value ?? ''}</span>
|
|
86
|
+
<button type="button" onClick={handleIncrement} className="inline-flex items-center justify-center px-0.5 text-fg-40 hover:text-emphasis transition-colors" aria-label="Next">
|
|
87
|
+
<Icon name="chevron-right" size={chev} />
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
66
93
|
const shellCls = [
|
|
67
94
|
'kol-control',
|
|
68
95
|
'kol-control--filled',
|