@kolkrabbi/kol-component 0.14.3 → 0.15.1

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.14.3",
3
+ "version": "0.15.1",
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",
@@ -0,0 +1,57 @@
1
+ import { Icon } from '@kolkrabbi/kol-icons'
2
+
3
+ /**
4
+ * IconFrame — a STATIC square frame holding one icon.
5
+ *
6
+ * The visual weight of a button rung with none of its interactivity: a heading
7
+ * ornament, a label ornament, a legend swatch — anywhere an icon needs the
8
+ * button's box and background but must not read or behave as a control.
9
+ *
10
+ * Promoted 2026-07-30 from kol-website's `SectionTitle`, where it lived as an
11
+ * anonymous `<span className="kol-btn kol-btn-secondary kol-btn-md
12
+ * kol-btn-icon">` (user ruling: *"span? that's fucked up, not even a button?
13
+ * …take that span and make it a component for icons with no states."*).
14
+ *
15
+ * It owns `.kol-icon-frame*` rather than borrowing `kol-btn-*`, and that is the
16
+ * entire point. Reusing button classes on a `<span>` suppresses hover/active/
17
+ * focus/disabled **by element** — the "no states" property was an accident of
18
+ * the tag, not a guarantee of the API, and would leak back the moment someone
19
+ * changed the element or a rule stopped requiring `:hover` on a focusable. The
20
+ * frame's own classes declare the same background, foreground and geometry and
21
+ * simply have no state rules to inherit.
22
+ *
23
+ * `variant` borrows the kol-btn COLOUR SET verbatim so the frame sits in the
24
+ * same visual system as real buttons; `primary` and `secondary` are inverse
25
+ * pairs that flip with the theme, so light/dark comes free from the tokens with
26
+ * no per-theme props.
27
+ *
28
+ * `size` moves the square and the glyph together — one prop, never two — on the
29
+ * solo-glyph law (16/20/24 against the pinned squares 28/32/36).
30
+ *
31
+ * Deliberately absent: `onClick`, `href`, `disabled`, `aria-pressed`, `title`.
32
+ * Wanting any of those means wanting a `Button` with `iconOnly`, not this.
33
+ *
34
+ * @param {string} name icon name (kol-icons)
35
+ * @param {string} variant primary|secondary|accent|outline|ghost|nav|grey|danger
36
+ * @param {string} size sm|md|lg — square + glyph together
37
+ * @param {string} className escape hatch
38
+ */
39
+ const GLYPH = { sm: 16, md: 20, lg: 24 }
40
+
41
+ export default function IconFrame({
42
+ name,
43
+ variant = 'secondary',
44
+ size = 'md',
45
+ className = '',
46
+ ...rest
47
+ }) {
48
+ if (!name) return null
49
+ return (
50
+ <span
51
+ className={`kol-icon-frame kol-icon-frame-${variant} kol-icon-frame-${size} ${className}`.trim()}
52
+ {...rest}
53
+ >
54
+ <Icon name={name} size={GLYPH[size] ?? GLYPH.md} />
55
+ </span>
56
+ )
57
+ }
package/src/index.js CHANGED
@@ -28,6 +28,7 @@ export { default as Divider } from './atoms/Divider.jsx'
28
28
  export { default as DocsToc } from './atoms/DocsToc.jsx'
29
29
  export { default as DropdownTagFilter } from './atoms/DropdownTagFilter.jsx'
30
30
  export { default as EmptyState } from './atoms/EmptyState.jsx'
31
+ export { default as IconFrame } from './atoms/IconFrame.jsx'
31
32
  export { default as ExitPreview } from './atoms/ExitPreview.jsx'
32
33
  export { default as Figure } from './atoms/Figure.jsx'
33
34
  export { default as FullscreenOverlay } from './atoms/FullscreenOverlay.jsx'