@kolkrabbi/kol-component 0.151.0 → 0.153.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.151.0",
3
+ "version": "0.153.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",
@@ -12,7 +12,7 @@ const FOCUSABLE =
12
12
 
13
13
  /**
14
14
  * ShellDrawer — THE edge drawer: a portalled panel that slides in from the
15
- * left or right viewport edge over a dimming backdrop. Distinct from Modal
15
+ * left, right or BOTTOM viewport edge over a dimming backdrop. Distinct from Modal
16
16
  * (centered prompt/confirm) and FullscreenOverlay (fills the whole viewport,
17
17
  * not an edge sheet). Escape, backdrop click and the built-in close button
18
18
  * all call `onClose`; body scroll locks while open; focus moves into the
@@ -26,8 +26,16 @@ const FOCUSABLE =
26
26
  *
27
27
  * @param {boolean} open drawer visible (drives slide in/out)
28
28
  * @param {Function} onClose close request (Esc / backdrop / close button)
29
- * @param {string} side 'left' | 'right' — edge the panel slides from
30
- * @param {number|string} width panel width (px number or CSS length); omit for full-width sheet
29
+ * @param {string} side 'left' | 'right' | 'bottom' — edge the panel slides from.
30
+ * `bottom` (ShellDrawerBottomSide, kol-mirror 2026-09-01) is the
31
+ * phone's sheet: full viewport width, slides up from +100% on Y,
32
+ * takes `height` where the sides take `width`, and pads its foot by
33
+ * `env(safe-area-inset-bottom)` so the last row clears the home bar.
34
+ * ONE DETENT — open or closed. A collapsed bar that grows on tap is
35
+ * a second height the consumer owns (mirror's 56px → 68dvh); this
36
+ * sheet does not carry it, and says so rather than half-build it.
37
+ * @param {number|string} width panel width (px number or CSS length); omit for full-width sheet — sides only
38
+ * @param {number|string} height panel height (px number or CSS length); omit for a content-sized sheet — `bottom` only
31
39
  * @param {ReactNode} header header-row content beside the close button (replaces the source's baked-in wordmark)
32
40
  * @param {boolean} backdrop render the dimming scrim (default true); false = panel alone, no darken/blur, close via × / Esc
33
41
  * @param {ReactNode} children scrollable panel body
@@ -38,6 +46,7 @@ export default function ShellDrawer({
38
46
  onClose,
39
47
  side = 'left',
40
48
  width,
49
+ height,
41
50
  header,
42
51
  closeSide = 'end',
43
52
  backdrop = true,
@@ -130,10 +139,18 @@ export default function ShellDrawer({
130
139
 
131
140
  if (!present || typeof document === 'undefined') return null
132
141
 
133
- const slideOut = side === 'right' ? 'translate-x-full' : '-translate-x-full'
142
+ const bottom = side === 'bottom'
143
+ const slideOut = bottom ? 'translate-y-full' : side === 'right' ? 'translate-x-full' : '-translate-x-full'
134
144
  const motionPanel = reduced
135
145
  ? ''
136
- : `transition-transform duration-200 ease-out ${shown ? 'translate-x-0' : slideOut}`
146
+ : `transition-transform duration-200 ease-out ${shown ? (bottom ? 'translate-y-0' : 'translate-x-0') : slideOut}`
147
+ /* the sheet's edge is the top; the sides' is the inner vertical */
148
+ const place = bottom
149
+ ? `inset-x-0 bottom-0 w-full max-h-full ${edge ? 'border-t' : ''}`
150
+ : `inset-y-0 max-w-full ${side === 'right' ? `right-0 ${edge ? 'border-l' : ''}` : `left-0 ${edge ? 'border-r' : ''}`} ${width == null ? 'w-full' : ''}`
151
+ const size = bottom
152
+ ? { ...(height != null ? { height: typeof height === 'number' ? `${height}px` : height } : {}), paddingBottom: 'calc(1rem + env(safe-area-inset-bottom, 0px))' }
153
+ : width != null ? { width: typeof width === 'number' ? `${width}px` : width } : undefined
137
154
  const motionBackdrop = reduced
138
155
  ? ''
139
156
  : `transition-opacity duration-200 ease-out ${shown ? 'opacity-100' : 'opacity-0'}`
@@ -159,10 +176,8 @@ export default function ShellDrawer({
159
176
  tabIndex={-1}
160
177
  /* `edge` / `shadow` (SettingsPanelApproved, 2026-08-27): the approved settings
161
178
  * drawer has neither — the sheet meets the page flat */
162
- className={`fixed inset-y-0 z-[200] flex max-w-full flex-col bg-surface-primary px-4 py-4 outline-none md:px-5 lg:px-6 ${backdrop && shadow ? 'shadow-2xl' : ''} ${
163
- side === 'right' ? `right-0 ${edge ? 'border-l' : ''}` : `left-0 ${edge ? 'border-r' : ''}`
164
- } border-oq-08 ${width == null ? 'w-full' : ''} ${motionPanel} ${className}`}
165
- style={width != null ? { width: typeof width === 'number' ? `${width}px` : width } : undefined}
179
+ className={`fixed z-[200] flex flex-col bg-surface-primary px-4 py-4 outline-none md:px-5 lg:px-6 ${backdrop && shadow ? 'shadow-2xl' : ''} ${place} border-oq-08 ${motionPanel} ${className}`}
180
+ style={size}
166
181
  >
167
182
  {/* closeSide="start": the reference sets the × glyph ~9px deeper than
168
183
  * the label column's edge, with extra top air (both reference frames
@@ -65,10 +65,14 @@ export default function FullscreenOverlay({ open, onClose, closeButton = true, c
65
65
  <div className="kol-overlay" role="dialog" aria-modal="true" onMouseDown={onBackdropClick}>
66
66
  <div ref={sheetRef} tabIndex={-1} className="kol-overlay-sheet outline-none">
67
67
  {closeButton && (
68
+ /* ONE close idiom (FullscreenOverlayCloseIdiom, kol-chess 2026-09-01,
69
+ * user ruling): the estate's close X is the drawer trigger's bare
70
+ * `nav` glyph — the boxed outline treatment was a second design one
71
+ * tap away from the first, and had he kept a box it would have worn
72
+ * `primary`, never `outline`. Same variant, same default square as
73
+ * the trigger. */
68
74
  <Button
69
- variant="outline"
70
- quiet
71
- size="sm"
75
+ variant="nav"
72
76
  iconOnly="x"
73
77
  className="kol-overlay-close"
74
78
  onClick={onClose}