@kolkrabbi/kol-component 0.171.0 → 0.173.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.173.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,21 @@ 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.
|
|
55
|
+
* @param {'center'|'start'} [textAlign] how the TYPE rags inside the text block —
|
|
56
|
+
* `align` places the block, this aligns what is in it (section-split-fill-text-align,
|
|
57
|
+
* kol-client-olina 2026-09-03; user: *"same placement but just aligned to left … can the
|
|
58
|
+
* text align left and everything else kinda stays as is?"*). Works in BOTH forms rather
|
|
59
|
+
* than only in `fill`, because a prop that silently does nothing in the default form is a
|
|
60
|
+
* seam wired to nothing. Unset, each form keeps exactly what it did: `fill` centres,
|
|
61
|
+
* bounded follows `align` (centred when `align="center"`, else start).
|
|
47
62
|
* @param {'right'|'left'|'center'} [align='right'] media side, or centred single column
|
|
48
63
|
* @param {'full'|'80'|'60'|string} [height='60'] min-height on the family's ladder — full = 100dvh,
|
|
49
64
|
* 80 = 70svh / 80vh, 60 = 50svh / 60vh (default), 40 = 35svh / 40vh; the columns stay vertically centred inside it
|
|
@@ -72,6 +87,8 @@ export default function SectionSplit({
|
|
|
72
87
|
mediaHover = false,
|
|
73
88
|
mediaClip = true,
|
|
74
89
|
align = 'right',
|
|
90
|
+
textAlign,
|
|
91
|
+
fill = false,
|
|
75
92
|
height = '60',
|
|
76
93
|
caption,
|
|
77
94
|
bgImage,
|
|
@@ -91,9 +108,67 @@ export default function SectionSplit({
|
|
|
91
108
|
const bleed = fullBleed ? FULL_BLEED : ''
|
|
92
109
|
const centred = align === 'center'
|
|
93
110
|
const mediaFirst = align === 'left'
|
|
111
|
+
/* unset = each form's own prior behaviour, so nothing existing moves */
|
|
112
|
+
const fillText = textAlign ?? 'center'
|
|
113
|
+
const boundedText = textAlign ?? (centred ? 'center' : 'start')
|
|
114
|
+
const justify = (a) => (a === 'center' ? 'justify-center' : 'justify-start')
|
|
94
115
|
const grid = centred
|
|
95
116
|
? 'grid grid-cols-1 justify-items-center gap-[clamp(48px,6vw,96px)]'
|
|
96
117
|
: 'grid grid-cols-1 min-[901px]:grid-cols-2 items-center gap-[clamp(48px,6vw,96px)]'
|
|
118
|
+
|
|
119
|
+
/* THE FILL FORM — two halves, no frame. Deliberately its own return rather
|
|
120
|
+
* than conditionals threaded through the bounded one: every bounded rule
|
|
121
|
+
* (the container cap, the section padding, the ratio box, the rung-minus-
|
|
122
|
+
* padding height) is a rule this form does not have, so sharing the JSX would
|
|
123
|
+
* mean negating each of them at its own site. `.kol-section-split-visual`
|
|
124
|
+
* stays on the media half because its `img { object-fit: cover }` rule is
|
|
125
|
+
* exactly what a filling half wants — the class earns its keep here without a
|
|
126
|
+
* line of new CSS. `centred` has no meaning with two halves and is ignored. */
|
|
127
|
+
if (fill && media) {
|
|
128
|
+
return (
|
|
129
|
+
<section
|
|
130
|
+
ref={themeRef}
|
|
131
|
+
data-theme={themeStamp}
|
|
132
|
+
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()}
|
|
133
|
+
style={sectionStyle}
|
|
134
|
+
>
|
|
135
|
+
<div
|
|
136
|
+
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()}
|
|
137
|
+
>
|
|
138
|
+
{media}
|
|
139
|
+
{caption && <div className="kol-section-split-visual-veil" aria-hidden="true" />}
|
|
140
|
+
{caption && <span className="kol-section-split-visual-caption">{caption}</span>}
|
|
141
|
+
</div>
|
|
142
|
+
<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()}>
|
|
143
|
+
<SectionText
|
|
144
|
+
eyebrow={eb}
|
|
145
|
+
headline={headline}
|
|
146
|
+
headlineSize={headlineSize}
|
|
147
|
+
headlineAs={headlineAs}
|
|
148
|
+
body={body}
|
|
149
|
+
actions={actions}
|
|
150
|
+
actionsClass={`flex flex-wrap gap-4 pt-2 ${justify(fillText)}`}
|
|
151
|
+
align={fillText}
|
|
152
|
+
slotClass={slotClass}
|
|
153
|
+
slotStyle={slotStyle}
|
|
154
|
+
className="max-w-[var(--kol-content-column)]"
|
|
155
|
+
>
|
|
156
|
+
{meta && meta.length > 0 && (
|
|
157
|
+
<div className={`kol-section-split-meta flex flex-wrap gap-y-7 gap-x-12 pt-4 ${justify(fillText)}`}>
|
|
158
|
+
{meta.map((m) => (
|
|
159
|
+
<div key={m.label} className="flex flex-col gap-0.5">
|
|
160
|
+
<span className="kol-section-split-meta-num">{m.num}</span>
|
|
161
|
+
<span className="kol-section-split-meta-label">{m.label}</span>
|
|
162
|
+
</div>
|
|
163
|
+
))}
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
</SectionText>
|
|
167
|
+
</div>
|
|
168
|
+
</section>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
97
172
|
return (
|
|
98
173
|
<section
|
|
99
174
|
ref={themeRef}
|
|
@@ -114,14 +189,14 @@ export default function SectionSplit({
|
|
|
114
189
|
headlineAs={headlineAs}
|
|
115
190
|
body={body}
|
|
116
191
|
actions={actions}
|
|
117
|
-
actionsClass={`flex flex-wrap gap-4 pt-2${
|
|
118
|
-
align={
|
|
192
|
+
actionsClass={`flex flex-wrap gap-4 pt-2 ${justify(boundedText)}`}
|
|
193
|
+
align={boundedText}
|
|
119
194
|
slotClass={slotClass}
|
|
120
195
|
slotStyle={slotStyle}
|
|
121
196
|
className={`max-w-[640px] ${mediaFirst ? 'order-2' : ''} ${columnClassName}`}
|
|
122
197
|
>
|
|
123
198
|
{meta && meta.length > 0 && (
|
|
124
|
-
<div className={`kol-section-split-meta flex flex-wrap gap-y-7 gap-x-12 pt-4${
|
|
199
|
+
<div className={`kol-section-split-meta flex flex-wrap gap-y-7 gap-x-12 pt-4 ${justify(boundedText)}`}>
|
|
125
200
|
{meta.map((m) => (
|
|
126
201
|
<div key={m.label} className="flex flex-col gap-0.5">
|
|
127
202
|
<span className="kol-section-split-meta-num">{m.num}</span>
|