@kolkrabbi/kol-component 0.171.0 → 0.172.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.171.0",
3
+ "version": "0.172.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",
@@ -44,6 +44,14 @@ import { minHeightClass } from './sectionHeights.js'
44
44
  * the node owns its own clipping (SectionSplitMediaClip, kol-website 2026-08-26: TiltCard's
45
45
  * lifted corners were being cut flat). `mediaHover` and a self-animating node are
46
46
  * mutually exclusive in practice — pick one.
47
+ * @param {boolean} [fill=false] THE HALF-FILLING FORM (section-split-fill-variant,
48
+ * kol-client-olina 2026-09-03). The bounded frame is the right rule for a card with media
49
+ * and the wrong one for a half: `fill` releases it — the media column loses the ratio, the
50
+ * rung-minus-padding height, the radius and the section padding, and covers its half edge to
51
+ * edge, with the text centred in the other. `align` still picks the side; below 901px the
52
+ * media stacks on top at `min-h-[50vh]`. This is the layout `SectionHero variant="split"`
53
+ * draws, without the hero's overlay / glass panel / carousel machinery or its name — the
54
+ * user's reason for not putting a hero under an About section.
47
55
  * @param {'right'|'left'|'center'} [align='right'] media side, or centred single column
48
56
  * @param {'full'|'80'|'60'|string} [height='60'] min-height on the family's ladder — full = 100dvh,
49
57
  * 80 = 70svh / 80vh, 60 = 50svh / 60vh (default), 40 = 35svh / 40vh; the columns stay vertically centred inside it
@@ -72,6 +80,7 @@ export default function SectionSplit({
72
80
  mediaHover = false,
73
81
  mediaClip = true,
74
82
  align = 'right',
83
+ fill = false,
75
84
  height = '60',
76
85
  caption,
77
86
  bgImage,
@@ -94,6 +103,60 @@ export default function SectionSplit({
94
103
  const grid = centred
95
104
  ? 'grid grid-cols-1 justify-items-center gap-[clamp(48px,6vw,96px)]'
96
105
  : 'grid grid-cols-1 min-[901px]:grid-cols-2 items-center gap-[clamp(48px,6vw,96px)]'
106
+
107
+ /* THE FILL FORM — two halves, no frame. Deliberately its own return rather
108
+ * than conditionals threaded through the bounded one: every bounded rule
109
+ * (the container cap, the section padding, the ratio box, the rung-minus-
110
+ * padding height) is a rule this form does not have, so sharing the JSX would
111
+ * mean negating each of them at its own site. `.kol-section-split-visual`
112
+ * stays on the media half because its `img { object-fit: cover }` rule is
113
+ * exactly what a filling half wants — the class earns its keep here without a
114
+ * line of new CSS. `centred` has no meaning with two halves and is ignored. */
115
+ if (fill && media) {
116
+ return (
117
+ <section
118
+ ref={themeRef}
119
+ data-theme={themeStamp}
120
+ className={`kol-section-split kol-section-split--fill grid grid-cols-1 min-[901px]:grid-cols-2 ${minHeightClass(height)} ${surfaceClass(background, 'none')} ${bleed} ${className}`.replace(/\s+/g, ' ').trim()}
121
+ style={sectionStyle}
122
+ >
123
+ <div
124
+ className={`kol-section-split-visual relative h-full min-h-[50vh] overflow-hidden min-[901px]:min-h-0 ${mediaHover ? 'is-hoverable' : ''} ${mediaFirst ? '' : 'min-[901px]:order-2'} ${columnClassName}`.replace(/\s+/g, ' ').trim()}
125
+ >
126
+ {media}
127
+ {caption && <div className="kol-section-split-visual-veil" aria-hidden="true" />}
128
+ {caption && <span className="kol-section-split-visual-caption">{caption}</span>}
129
+ </div>
130
+ <div className={`flex items-center justify-center px-5 py-16 md:px-8 md:py-24 lg:px-14 ${mediaFirst ? '' : 'min-[901px]:order-1'} ${innerClassName}`.replace(/\s+/g, ' ').trim()}>
131
+ <SectionText
132
+ eyebrow={eb}
133
+ headline={headline}
134
+ headlineSize={headlineSize}
135
+ headlineAs={headlineAs}
136
+ body={body}
137
+ actions={actions}
138
+ actionsClass="flex flex-wrap gap-4 pt-2 justify-center"
139
+ align="center"
140
+ slotClass={slotClass}
141
+ slotStyle={slotStyle}
142
+ className="max-w-[var(--kol-content-column)]"
143
+ >
144
+ {meta && meta.length > 0 && (
145
+ <div className="kol-section-split-meta flex flex-wrap gap-y-7 gap-x-12 pt-4 justify-center">
146
+ {meta.map((m) => (
147
+ <div key={m.label} className="flex flex-col gap-0.5">
148
+ <span className="kol-section-split-meta-num">{m.num}</span>
149
+ <span className="kol-section-split-meta-label">{m.label}</span>
150
+ </div>
151
+ ))}
152
+ </div>
153
+ )}
154
+ </SectionText>
155
+ </div>
156
+ </section>
157
+ )
158
+ }
159
+
97
160
  return (
98
161
  <section
99
162
  ref={themeRef}