@kolkrabbi/kol-framework 0.59.0 → 0.61.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/kol-framework.css +61 -1
- package/package.json +5 -5
- package/src/SiteHero.jsx +64 -0
- package/src/index.js +2 -0
package/kol-framework.css
CHANGED
|
@@ -32,8 +32,15 @@ body {
|
|
|
32
32
|
* law, brand-app ruling): text is selectable everywhere — copyability beats
|
|
33
33
|
* chrome purity. */
|
|
34
34
|
|
|
35
|
-
/*
|
|
35
|
+
/* SELECTED TEXT IS NEUTRAL BY DEFAULT (ArticleRendererHomeHeroSelection, kol-website 2026-10-28 — user: accents are opt-in,
|
|
36
|
+
* not default; brand's selections were yellow): the page's own ink pair, inverted — a white highlight with dark ink in dark
|
|
37
|
+
* mode, its inverse in light. An app (or any subtree) opts into the accent with `.kol-select-accent`. */
|
|
36
38
|
::selection {
|
|
39
|
+
background-color: var(--kol-surface-on-primary);
|
|
40
|
+
color: var(--kol-surface-primary);
|
|
41
|
+
}
|
|
42
|
+
.kol-select-accent::selection,
|
|
43
|
+
.kol-select-accent ::selection {
|
|
37
44
|
background-color: var(--kol-accent-primary);
|
|
38
45
|
color: var(--kol-accent-on-primary);
|
|
39
46
|
}
|
|
@@ -211,6 +218,59 @@ body {
|
|
|
211
218
|
line-height: 1;
|
|
212
219
|
transition: transform 150ms ease, opacity 120ms ease, visibility 0s linear 120ms;
|
|
213
220
|
}
|
|
221
|
+
/* THE SPLIT ROW (user 2026-10-28: "expand anywhere except the title"): a foldernote's row is two targets on one box.
|
|
222
|
+
* The caret button fills the row under the link (the Tooltip wrapper is the positioned box, so it covers the head and
|
|
223
|
+
* not the open list below), its chevron where the floated caret sat; the link above passes the pointer through except
|
|
224
|
+
* on its glyph and title. The row still brightens as one when either half is hovered. */
|
|
225
|
+
.kol-sidenav-hop-caret--row {
|
|
226
|
+
top: 0;
|
|
227
|
+
right: 0;
|
|
228
|
+
bottom: 0;
|
|
229
|
+
left: 0;
|
|
230
|
+
justify-content: flex-end;
|
|
231
|
+
align-items: flex-start;
|
|
232
|
+
/* the chevron's 12 from the top and 16 from the edge ride the element as utilities (`pt-3 pr-4`) — a padding here
|
|
233
|
+
* would lose to the utility layer, which is how the first cut put the chevron 12px high */
|
|
234
|
+
}
|
|
235
|
+
.kol-sidenav-hop-chevron {
|
|
236
|
+
display: inline-flex;
|
|
237
|
+
transition: transform 150ms ease;
|
|
238
|
+
}
|
|
239
|
+
.kol-sidenav-hop--split {
|
|
240
|
+
pointer-events: none;
|
|
241
|
+
}
|
|
242
|
+
.kol-sidenav-hop--split .kol-sidenav-hop-icon,
|
|
243
|
+
.kol-sidenav-hop--split .kol-sidenav-hop-title {
|
|
244
|
+
pointer-events: auto;
|
|
245
|
+
}
|
|
246
|
+
.kol-sidenav-hop-split:has(> .kol-sidenav-hop-caret--row:hover) .kol-sidenav-hop {
|
|
247
|
+
color: var(--kol-fg-96);
|
|
248
|
+
}
|
|
249
|
+
.kol-sidenav-hop-split:has(> .kol-sidenav-hop-caret--row:hover) .kol-sidenav-hop-icon {
|
|
250
|
+
color: var(--kol-surface-on-primary);
|
|
251
|
+
}
|
|
252
|
+
:root[data-sidenav="collapsed"] .kol-sidenav-hop--split { pointer-events: auto; }
|
|
253
|
+
/* THE TREE FADES AT ITS CLIP (user 2026-10-28: "we also are missing a fade when list clips in navrail") — the app rail's
|
|
254
|
+
* `.kol-shell-rail-list--fade` and the workshop rail's `.shell-rail`, the same 3rem ramp; the element's `pb-12` (a utility,
|
|
255
|
+
* which a components-layer padding here could not outrank) lets the last row scroll clear of it, so at the end of the list nothing stays faded. `NavRail variant="site" fade={false}` drops it. */
|
|
256
|
+
.kol-sidenav-scroll--fade {
|
|
257
|
+
-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 3rem), transparent);
|
|
258
|
+
mask-image: linear-gradient(to bottom, #000 calc(100% - 3rem), transparent);
|
|
259
|
+
}
|
|
260
|
+
/* THE SITE HERO'S WASH (SiteHero, 2026-10-28) — kol-website's `.landing-hero-overlay` and `.stack-hero-overlay`, one rule:
|
|
261
|
+
* the inverse ink mixed over the image, 32 % light · 80 % dark, the theme law's selectors (explicit > system > light).
|
|
262
|
+
* SiteHero's `overlay` prop sets the two variables. */
|
|
263
|
+
.kol-site-hero-overlay {
|
|
264
|
+
background-color: color-mix(in srgb, var(--kol-surface-on-inverse, currentColor) var(--kol-site-hero-mix, 32%), transparent);
|
|
265
|
+
}
|
|
266
|
+
:is([data-theme="dark"], .dark) .kol-site-hero-overlay {
|
|
267
|
+
background-color: color-mix(in srgb, var(--kol-surface-on-inverse, currentColor) var(--kol-site-hero-mix-dark, 80%), transparent);
|
|
268
|
+
}
|
|
269
|
+
@media (prefers-color-scheme: dark) {
|
|
270
|
+
:root:not([data-theme="light"]) .kol-site-hero-overlay {
|
|
271
|
+
background-color: color-mix(in srgb, var(--kol-surface-on-inverse, currentColor) var(--kol-site-hero-mix-dark, 80%), transparent);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
214
274
|
.kol-sidenav-list {
|
|
215
275
|
display: flex;
|
|
216
276
|
flex-direction: column;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "Site shell and page layout",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"./kol-brand-color.css": "./kol-brand-color.css"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@kolkrabbi/kol-component": ">=0.
|
|
17
|
+
"@kolkrabbi/kol-component": ">=0.308.0",
|
|
18
18
|
"@kolkrabbi/kol-icons": ">=0.18.0",
|
|
19
19
|
"@kolkrabbi/kol-markdown": ">=0.2.0",
|
|
20
20
|
"@kolkrabbi/kol-theme": ">=0.186.0",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"react-router-dom": "^6.0.0 || ^7.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@kolkrabbi/kol-
|
|
27
|
-
"@kolkrabbi/kol-
|
|
28
|
-
"@kolkrabbi/kol-
|
|
26
|
+
"@kolkrabbi/kol-component": "^0.310.0",
|
|
27
|
+
"@kolkrabbi/kol-icons": "^0.52.0",
|
|
28
|
+
"@kolkrabbi/kol-markdown": "0.2.0"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"src",
|
package/src/SiteHero.jsx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { VectorLoader } from '@kolkrabbi/kol-component'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SiteHero — A site's landing: a full-screen image, a wash, the mark, the name. kol-website apps/brand's `Landing`, class
|
|
5
|
+
* for class (ArticleRendererHomeHeroSelection, kol-website 2026-10-28 — three hand-built copies: brand's Landing, record's
|
|
6
|
+
* Home, site-hub's Home; web's /stack hero wears the same wash). Every part is optional, so the next site needs no copy.
|
|
7
|
+
*
|
|
8
|
+
* Not `PageHero`: that is a page's opening band (label · title · lede beside a mark). This is the home page itself.
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} image `{ src, srcSet?, sizes?, position?, alt? }` — the ground, `object-cover`, `sizes` 100vw by default
|
|
11
|
+
* @param {ReactNode} media any node in place of `image` (a video, a canvas), filling the ground
|
|
12
|
+
* @param {ReactNode|string} mark a node, or an SVG url inlined in currentColor (`VectorLoader`); the hero sizes it, the
|
|
13
|
+
* landing's clamp(140px, 16vw, 220px)
|
|
14
|
+
* @param {string} markTitle the mark's accessible name when it is a url
|
|
15
|
+
* @param {ReactNode} title the h1, `kol-prose-display uppercase`
|
|
16
|
+
* @param {ReactNode} tagline `kol-prose-tagline`
|
|
17
|
+
* @param {ReactNode} actions buttons under the tagline, wrapped and centred
|
|
18
|
+
* @param {number|{light,dark}|false} overlay the wash: the inverse ink mixed over the image, 32 % light · 80 % dark by
|
|
19
|
+
* default (the sites' line); a number sets both, `false` drops it
|
|
20
|
+
* @param {'center'|'start'} align the text column — centred (default) or from the left
|
|
21
|
+
* @param {string} minHeight default `100dvh`
|
|
22
|
+
*/
|
|
23
|
+
export default function SiteHero({ image, media, mark, markTitle, title, tagline, actions, overlay, align = 'center', minHeight = '100dvh', className = '' }) {
|
|
24
|
+
const start = align === 'start'
|
|
25
|
+
const wash = overlay === false ? null
|
|
26
|
+
: typeof overlay === 'number' ? { '--kol-site-hero-mix': `${overlay}%`, '--kol-site-hero-mix-dark': `${overlay}%` }
|
|
27
|
+
: overlay && typeof overlay === 'object' ? { ...(overlay.light != null && { '--kol-site-hero-mix': `${overlay.light}%` }), ...(overlay.dark != null && { '--kol-site-hero-mix-dark': `${overlay.dark}%` }) }
|
|
28
|
+
: {}
|
|
29
|
+
return (
|
|
30
|
+
<section className={`relative flex items-center ${start ? 'justify-start' : 'justify-center'} overflow-hidden ${className}`.trim()} style={{ minHeight }}>
|
|
31
|
+
{(image || media) && (
|
|
32
|
+
<div className="absolute inset-0 w-full h-full">
|
|
33
|
+
{media ?? (
|
|
34
|
+
<img
|
|
35
|
+
src={image.src}
|
|
36
|
+
srcSet={image.srcSet}
|
|
37
|
+
sizes={image.srcSet ? (image.sizes ?? '100vw') : undefined}
|
|
38
|
+
alt={image.alt ?? ''}
|
|
39
|
+
className="w-full h-full object-cover"
|
|
40
|
+
style={{ objectPosition: image.position ?? 'center' }}
|
|
41
|
+
/>
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
)}
|
|
45
|
+
{wash && <div className="kol-site-hero-overlay absolute inset-0 w-full h-full pointer-events-none" style={wash} aria-hidden="true" />}
|
|
46
|
+
|
|
47
|
+
<div className={`relative z-[1] flex flex-col gap-10 px-8 ${start ? 'items-start text-left' : 'items-center text-center'}`}>
|
|
48
|
+
{mark && (
|
|
49
|
+
<div className="w-[clamp(140px,16vw,220px)] text-emphasis">
|
|
50
|
+
{typeof mark === 'string'
|
|
51
|
+
? <VectorLoader src={mark} size="100%" className="block" role={markTitle ? 'img' : undefined} aria-label={markTitle} />
|
|
52
|
+
: mark}
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
{title && <h1 className="kol-prose-display uppercase">{title}</h1>}
|
|
57
|
+
|
|
58
|
+
{tagline && <p className="kol-prose-tagline">{tagline}</p>}
|
|
59
|
+
|
|
60
|
+
{actions && <div className={`flex flex-wrap items-center gap-3 mt-4 ${start ? 'justify-start' : 'justify-center'}`}>{actions}</div>}
|
|
61
|
+
</div>
|
|
62
|
+
</section>
|
|
63
|
+
)
|
|
64
|
+
}
|
package/src/index.js
CHANGED
|
@@ -26,6 +26,8 @@ export { default as PageSection } from './PageSection.jsx'
|
|
|
26
26
|
export { default as PortalFooter } from './PortalFooter.jsx'
|
|
27
27
|
export { default as ScrollToTop } from './ScrollToTop.jsx'
|
|
28
28
|
export { default as PageHero, default as BrandHero, default as SubPageHero } from './PageHero.jsx'
|
|
29
|
+
/* a site's landing — the full-screen image, wash, mark and name (ArticleRendererHomeHeroSelection, 2026-10-28) */
|
|
30
|
+
export { default as SiteHero } from './SiteHero.jsx'
|
|
29
31
|
export { default as CategoryPage } from './CategoryPage.jsx'
|
|
30
32
|
/* the document page (plan-2026-10-28-document W5.2): a markdown file as `.kol-sheet`, the hover card for its links,
|
|
31
33
|
* a folder of files as page rows */
|