@kolkrabbi/kol-component 0.64.0 → 0.66.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-component",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.66.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/Divider.jsx
CHANGED
|
@@ -10,15 +10,24 @@ import React from 'react'
|
|
|
10
10
|
* @param {Object} props
|
|
11
11
|
* @param {string} props.variant - 'horizontal' or 'vertical' (default: 'horizontal')
|
|
12
12
|
* @param {string} props.className - Additional classes
|
|
13
|
+
* @param {number} props.height - vertical variant only: the rule's height in px
|
|
14
|
+
* (default 16 — sized to the type it separates, not to the row)
|
|
13
15
|
* @param {string} props.opacity - Opacity level (01, 02, 04, 08, 12, 16, 24, 32, 48, 64, 80, 88, 96) (default: '08')
|
|
14
16
|
*/
|
|
15
|
-
const Divider = ({ variant = 'horizontal', className = '', opacity = '08', inverse = false }) => {
|
|
17
|
+
const Divider = ({ variant = 'horizontal', className = '', opacity = '08', inverse = false, height = 16 }) => {
|
|
16
18
|
const isVertical = variant === 'vertical'
|
|
17
19
|
const opacityClass = inverse ? `bg-fg-inverse-${opacity}` : `bg-fg-${opacity}`
|
|
18
20
|
|
|
19
21
|
if (isVertical) {
|
|
22
|
+
/* THE RULE IS CENTRED ON WHAT IT SEPARATES, not stretched to the row.
|
|
23
|
+
*
|
|
24
|
+
* This hardcoded `self-stretch` AHEAD of `className`, so the wrapper always
|
|
25
|
+
* filled the flex line — a row whose height comes from 32px icon buttons
|
|
26
|
+
* gave a rule taller than the 18px type beside it, and any `self-*` passed
|
|
27
|
+
* from a call site lost to the hardcoded one. `align-self: center` with an
|
|
28
|
+
* explicit height puts it back on the type; `height` stays overridable. */
|
|
20
29
|
return (
|
|
21
|
-
<div className={`
|
|
30
|
+
<div className={`flex self-center items-center justify-center ${className}`.trim()} style={{ height }}>
|
|
22
31
|
<div className={opacityClass} style={{ width: '1px', height: '100%' }} />
|
|
23
32
|
</div>
|
|
24
33
|
)
|
|
@@ -111,6 +111,20 @@ export default function SearchInput({
|
|
|
111
111
|
* served the second case and silently broke the first. */
|
|
112
112
|
const fieldH = fieldHeight ?? square
|
|
113
113
|
|
|
114
|
+
/* THE GLYPH WAITS FOR THE COLLAPSE. Mounting it the instant `isOpen` flips
|
|
115
|
+
* put a search icon inside a 200px pill that was still shrinking around it —
|
|
116
|
+
* the one frame of the animation that looks like a bug. It reappears at
|
|
117
|
+
* 520ms, just under the 600ms `.kol-expand` width transition, so it lands as
|
|
118
|
+
* the pill arrives rather than riding it down. Opening hides it immediately:
|
|
119
|
+
* the field should take the space at once. */
|
|
120
|
+
const [glyphIn, setGlyphIn] = useState(!open)
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (!expanding) return undefined
|
|
123
|
+
if (isOpen) { setGlyphIn(false); return undefined }
|
|
124
|
+
const t = setTimeout(() => setGlyphIn(true), 520)
|
|
125
|
+
return () => clearTimeout(t)
|
|
126
|
+
}, [expanding, isOpen])
|
|
127
|
+
|
|
114
128
|
/* Escape closes, and so does clicking away — a field that can only be closed
|
|
115
129
|
* by emptying it and blurring is a trap, and this one had neither wired. The
|
|
116
130
|
* listener only exists while open. */
|
|
@@ -147,7 +161,7 @@ export default function SearchInput({
|
|
|
147
161
|
2026-08-15). Once the field is open the caret is the affordance;
|
|
148
162
|
keeping the magnifier there spends the widest part of the pill
|
|
149
163
|
restating what the blinking cursor already says. */}
|
|
150
|
-
{!isOpen && (
|
|
164
|
+
{glyphIn && !isOpen && (
|
|
151
165
|
<button
|
|
152
166
|
type="button"
|
|
153
167
|
className="flex items-center justify-center rounded-full text-auto flex-shrink-0 border border-transparent transition-colors hover:border-oq-08"
|
|
@@ -81,12 +81,12 @@ const ContentFilters = ({
|
|
|
81
81
|
/* THE LOOK SEAMS. Every one defaults to what the component shipped, so
|
|
82
82
|
* passing nothing renders exactly as before — these exist because the
|
|
83
83
|
* hardcoded values were the wrong call for every consumer but one. */
|
|
84
|
-
/*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
84
|
+
/* HELPER + UPPERCASE. The title is part of the header STRIP — same chrome as
|
|
85
|
+
* RECENT/SAVED beside it — and helper is the single-line ramp that strip
|
|
86
|
+
* runs on. Casing and ramp are separate props precisely so a consumer whose
|
|
87
|
+
* titles wrap can move to `kol-mono-14` without losing the casing. */
|
|
88
88
|
titleClassName = 'kol-helper-14',
|
|
89
|
-
titleUppercase =
|
|
89
|
+
titleUppercase = true,
|
|
90
90
|
labelClassName = 'kol-helper-12 text-fg-96',
|
|
91
91
|
labelUppercase = true,
|
|
92
92
|
tagVariant = 'primary',
|
|
@@ -276,7 +276,7 @@ const ContentFilters = ({
|
|
|
276
276
|
{titleIcon && <IconFrame name={titleIcon} variant="secondary" size="md" />}
|
|
277
277
|
<span className={titleClassName} style={titleUppercase ? { textTransform: 'uppercase', letterSpacing: 1 } : undefined}>{title}</span>
|
|
278
278
|
</h2>
|
|
279
|
-
<Divider variant="vertical"
|
|
279
|
+
<Divider variant="vertical" />
|
|
280
280
|
<div className="flex items-center gap-1">
|
|
281
281
|
{/* IconFrame, not a kol-btn with its chrome cancelled inline.
|
|
282
282
|
* 05-control-chrome.md:109 — "any icon-only control in chrome is
|