@kolkrabbi/kol-component 0.50.0 → 0.52.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.50.0",
3
+ "version": "0.52.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",
@@ -67,9 +67,13 @@ const HOVER = {
67
67
  * of its own; article frames because its media is a 16/9 thumbnail that rarely
68
68
  * fills its box. */
69
69
  const MEDIA = {
70
- print: { ring: true },
70
+ /* zoom is for IMAGE-LED cards — where the artwork is the content and the
71
+ * card is a frame around it. A catalog tile whose preview is a diagram, or
72
+ * a default file card whose thumb is a 48px chip, gets nothing from it. */
73
+ print: { ring: true, zoom: true },
74
+ work: { zoom: true },
71
75
  /* ListingCard's card media steps its border on hover — fg-08 → fg-16 */
72
- article: { frame: true, borderHover: true },
76
+ article: { frame: true, borderHover: true, zoom: true },
73
77
  }
74
78
 
75
79
  export default function ContentCard({
@@ -80,6 +84,7 @@ export default function ContentCard({
80
84
  fit,
81
85
  frame,
82
86
  ring,
87
+ zoom,
83
88
  control,
84
89
  actions,
85
90
  selected = false,
@@ -146,6 +151,7 @@ export default function ContentCard({
146
151
  frame: frame ?? MEDIA[variant]?.frame ?? false,
147
152
  ring: ring ?? MEDIA[variant]?.ring ?? false,
148
153
  borderHover: MEDIA[variant]?.borderHover ?? false,
154
+ zoom: zoom ?? MEDIA[variant]?.zoom ?? false,
149
155
  }
150
156
 
151
157
  /* `control` — the in-frame control slot (user ruling 2026-08-15). One node,
@@ -53,6 +53,8 @@ import AssetPlaceholder from '../utilities/AssetPlaceholder.jsx'
53
53
  * @param {string} bg tint only, no border — a raw token value
54
54
  * @param {string} borderHover border colour on hover (article's fg-16 step)
55
55
  * @param {boolean} ring hairline border OVER the media, inset
56
+ * @param {boolean} zoom the artwork creeps up inside its frame on the
57
+ * CARD's hover — image-led variants only
56
58
  * @param {ReactNode} children the real media
57
59
  */
58
60
  const FIT = {
@@ -70,6 +72,7 @@ export default function ContentMedia({
70
72
  bg,
71
73
  borderHover,
72
74
  ring = false,
75
+ zoom = false,
73
76
  children,
74
77
  className = '',
75
78
  }) {
@@ -79,7 +82,7 @@ export default function ContentMedia({
79
82
  const round = radius ? 'rounded-[var(--kol-radius-sm)]' : ''
80
83
  return (
81
84
  <div
82
- className={`relative w-full overflow-hidden ${round} ${FIT[fit] ?? FIT.cover} ${frame ? 'bg-fg-04 border border-fg-08' : ''} ${border ? 'border border-fg-08' : ''} ${borderHover ? 'transition-colors hover:border-fg-16' : ''} ${ratio == null ? 'h-full' : ''} ${className}`.trim()}
85
+ className={`relative w-full overflow-hidden ${round} ${FIT[fit] ?? FIT.cover} ${frame ? 'bg-fg-04 border border-fg-08' : ''} ${border ? 'border border-fg-08' : ''} ${zoom ? 'kol-media-zoom' : ''} ${borderHover ? 'transition-colors hover:border-fg-16' : ''} ${ratio == null ? 'h-full' : ''} ${className}`.trim()}
83
86
  style={{ ...(ratio != null ? { aspectRatio: ratio } : null), background: bg }}
84
87
  >
85
88
  {children}
@@ -118,7 +118,7 @@ export default function ContentRow({
118
118
  )
119
119
 
120
120
  const common = {
121
- className: `kol-row flex ${box.column ? 'flex-col' : ''} ${box.align} ${box.divider ? 'border-b border-fg-08' : ''} ${box.frame ? 'rounded-[var(--kol-radius-sm)] border' : ''} ${interactive ? 'cursor-pointer select-none' : ''} ${interactive && box.hover ? 'kol-content-hover' : ''} ${interactive && box.frameHover ? 'kol-content-hover-frame' : ''} ${className}`.trim(),
121
+ className: `kol-row group flex ${box.column ? 'flex-col' : ''} ${box.align} ${box.divider ? 'kol-row--divided' : ''} ${box.frame ? 'rounded-[var(--kol-radius-sm)] border' : ''} ${interactive ? 'cursor-pointer select-none' : ''} ${interactive && box.hover ? 'kol-content-hover' : ''} ${interactive && box.frameHover ? 'kol-content-hover-frame' : ''} ${className}`.trim(),
122
122
  style: vars,
123
123
  }
124
124
 
@@ -44,7 +44,6 @@ import { Icon } from '@kolkrabbi/kol-icons'
44
44
 
45
45
  const SIZE_TYPE = { sm: 'kol-mono-12', md: 'kol-mono-14' }
46
46
  const ICON_SIZE = { sm: 14, md: 14 }
47
- const CUBIC_EASE = 'var(--kol-ease-house)'
48
47
 
49
48
  export default function SearchInput({
50
49
  value = '',
@@ -80,8 +79,9 @@ export default function SearchInput({
80
79
  if (expanding) {
81
80
  return (
82
81
  <div
83
- className={`flex items-center bg-fg-04 rounded-full h-9 ${className}`.trim()}
84
- style={{ width: isOpen ? expandedWidth : 36, transition: `width 600ms ${CUBIC_EASE}` }}
82
+ className={`kol-expand flex items-center bg-fg-04 rounded-full h-9 ${className}`.trim()}
83
+ /* motion is `.kol-expand` in kol-theme; only the WIDTH is per-instance */
84
+ style={{ width: isOpen ? expandedWidth : 36 }}
85
85
  >
86
86
  <button
87
87
  type="button"
@@ -231,13 +231,12 @@ const ContentFilters = ({
231
231
  <IconSeam name="filter" size={16} />
232
232
  </button>
233
233
  <div
234
- className="flex items-center justify-center rounded-sm cursor-pointer hover:bg-fg-04 transition-colors"
234
+ className="kol-expand flex items-center justify-center rounded-sm cursor-pointer hover:bg-fg-04"
235
235
  style={{
236
236
  height: 32,
237
237
  width: searchOpen ? 200 : 32,
238
238
  background: searchOpen ? 'var(--kol-surface-secondary)' : 'transparent',
239
239
  border: 'none',
240
- transition: 'width 600ms var(--kol-ease-house), background 400ms var(--kol-ease-house)',
241
240
  overflow: 'hidden',
242
241
  }}
243
242
  onClick={() => {
@@ -249,10 +248,9 @@ const ContentFilters = ({
249
248
  * wearing kol-btn chrome. The clickable thing is the wrapper
250
249
  * div, not this span. */}
251
250
  <span
252
- className="flex items-center justify-center flex-shrink-0"
251
+ className="kol-expand-content flex items-center justify-center flex-shrink-0"
253
252
  style={{
254
253
  opacity: searchOpen ? 0 : 1,
255
- transition: 'opacity 300ms var(--kol-ease-house)',
256
254
  position: searchOpen ? 'absolute' : 'relative',
257
255
  }}
258
256
  >