@kolkrabbi/kol-component 0.73.0 → 0.74.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.
|
|
3
|
+
"version": "0.74.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",
|
|
@@ -227,7 +227,11 @@ export default function ContentText({
|
|
|
227
227
|
)
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
/* NOT `order.map(render)`: map passes (entry, index, ARRAY) and the array
|
|
231
|
+
* landed in `trailing`, so every top-level stack right-aligned — the article
|
|
232
|
+
* card's title and body sat flush right under left-aligned tags for eleven
|
|
233
|
+
* days (found on the comparison page, 2026-08-26). */
|
|
234
|
+
const nodes = order.map((entry, i) => render(entry, i))
|
|
231
235
|
|
|
232
236
|
return (
|
|
233
237
|
<div
|
|
@@ -2,7 +2,9 @@ import { isValidElement } from 'react'
|
|
|
2
2
|
import HlsVideo from '../atoms/HlsVideo.jsx'
|
|
3
3
|
import Image from '../atoms/Image.jsx'
|
|
4
4
|
import OverlayGlassPanel from '../utilities/OverlayGlassPanel.jsx'
|
|
5
|
-
import
|
|
5
|
+
import AssetPlaceholder from '../utilities/AssetPlaceholder.jsx'
|
|
6
|
+
import ContentMedia from '../molecules/ContentMedia.jsx'
|
|
7
|
+
import SectionText, { HEADLINE_ROLE } from '../molecules/SectionText.jsx'
|
|
6
8
|
|
|
7
9
|
/** Height presets; anything else is passed through as a class string. */
|
|
8
10
|
const HEIGHTS = {
|
|
@@ -66,7 +68,16 @@ function MediaLayer({ media }) {
|
|
|
66
68
|
* the hero renders your node exactly as before — the escape hatch, and what
|
|
67
69
|
* every existing call site does; nothing there moves.
|
|
68
70
|
*
|
|
69
|
-
*
|
|
71
|
+
* TWO VARIANTS (user ask 2026-08-26). `media` (default): the cover-fit hero
|
|
72
|
+
* above. `split`: the whole viewport in two halves — media fills one edge to
|
|
73
|
+
* edge (no media → AssetPlaceholder), the text sits centred in the other, no
|
|
74
|
+
* glass panel, headline UPPERCASE by role (`.kol-section-text-caps`). It is
|
|
75
|
+
* SectionSplit blown up to 100vh/100vw with no padding, no ratio, no cap.
|
|
76
|
+
* `align` picks the media side there ('left' default · 'right'); below `md`
|
|
77
|
+
* the halves stack, media first.
|
|
78
|
+
*
|
|
79
|
+
* @param {'media'|'split'} variant
|
|
80
|
+
* @param {ReactNode|{src, kind, poster, srcSet, alt}} media background (media) / the half (split)
|
|
70
81
|
* @param {number} overlayOpacity 0–100 surface-primary scrim over the media (default 0)
|
|
71
82
|
* @param {string} height 'screen' | 'lg' | 'md' preset, or a height class string
|
|
72
83
|
* @param {ReactNode} label · headline · body · actions the composed text (SectionText)
|
|
@@ -74,10 +85,14 @@ function MediaLayer({ media }) {
|
|
|
74
85
|
* @param {string} [panelMaxWidth='max-w-[440px]'] the glass panel's cap on the composed route
|
|
75
86
|
* @param {ReactNode} panel a caller-authored content node; wins over the text props and children
|
|
76
87
|
* @param {ReactNode} children fallback content slot
|
|
77
|
-
* @param {string} align 'center' | 'start' | 'end' —
|
|
88
|
+
* @param {string} align media: 'center' | 'start' | 'end' — placement of the content ·
|
|
89
|
+
* split: 'left' | 'right' — the media side
|
|
90
|
+
* @param {boolean} fullBleed span the full viewport width (100vw breakout) — split
|
|
78
91
|
* @param {string} className extra classes on the section
|
|
79
92
|
*/
|
|
80
93
|
export default function SectionHero({
|
|
94
|
+
variant = 'media',
|
|
95
|
+
fullBleed = false,
|
|
81
96
|
media,
|
|
82
97
|
overlayOpacity = 0,
|
|
83
98
|
height = 'lg',
|
|
@@ -92,6 +107,37 @@ export default function SectionHero({
|
|
|
92
107
|
align = 'center',
|
|
93
108
|
className = '',
|
|
94
109
|
}) {
|
|
110
|
+
if (variant === 'split') {
|
|
111
|
+
const mediaFirst = align !== 'right'
|
|
112
|
+
const bleed = fullBleed ? 'w-screen ml-[calc(50%-50vw)]' : 'w-full'
|
|
113
|
+
const mediaNode = media == null
|
|
114
|
+
? <AssetPlaceholder radius={false} className="h-full w-full" />
|
|
115
|
+
: isValidElement(media) || typeof media !== 'object'
|
|
116
|
+
? <ContentMedia ratio={null} radius={false} fit="cover" className="h-full">{media}</ContentMedia>
|
|
117
|
+
: <MediaLayer media={media} />
|
|
118
|
+
return (
|
|
119
|
+
<section className={`kol-section-hero-split grid min-h-screen grid-cols-1 md:grid-cols-2 ${bleed} ${className}`.replace(/\s+/g, ' ').trim()}>
|
|
120
|
+
<div className={`relative min-h-[50vh] overflow-hidden md:min-h-0 ${mediaFirst ? '' : 'md:order-2'}`.trim()}>{mediaNode}</div>
|
|
121
|
+
<div className={`flex items-center justify-center p-10 ${mediaFirst ? '' : 'md:order-1'}`.trim()}>
|
|
122
|
+
<SectionText
|
|
123
|
+
label={label}
|
|
124
|
+
headline={headline}
|
|
125
|
+
headlineSize={headlineSize === 'display-04' ? 'heading-02' : headlineSize}
|
|
126
|
+
headlineClass={`${HEADLINE_ROLE[headlineSize === 'display-04' ? 'heading-02' : headlineSize] ?? HEADLINE_ROLE['heading-02']} kol-section-text-caps`}
|
|
127
|
+
body={body}
|
|
128
|
+
actions={actions}
|
|
129
|
+
align="center"
|
|
130
|
+
gap="gap-6"
|
|
131
|
+
labelClass="kol-helper-12 text-meta"
|
|
132
|
+
bodyClass="kol-sans-body-02 text-body"
|
|
133
|
+
actionsClass="flex flex-wrap gap-4 justify-center"
|
|
134
|
+
className="max-w-[var(--kol-content-column)]"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
</section>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
95
141
|
const heightCls = HEIGHTS[height] || height
|
|
96
142
|
const alignCls =
|
|
97
143
|
align === 'start' ? 'justify-start'
|