Commit ab816682 by PLN (Algolia)

blog: skim via data hooks; titles break out wide and balance

parent 0be22c50
...@@ -134,10 +134,11 @@ export default function ArticleEnhance({ lang, languages }) { ...@@ -134,10 +134,11 @@ export default function ArticleEnhance({ lang, languages }) {
// --- skim mode (?skim=1) ------------------------------------------- // --- skim mode (?skim=1) -------------------------------------------
// Refactoring English's skimmer test as a URL: headings, figures, code // Refactoring English's skimmer test as a URL: headings, figures, code
// and tables stay; prose paragraphs fold away. Dev/review tool — the // and tables stay; prose paragraphs fold away. Dev/review tool — the
// page ships unchanged without the param. // page ships unchanged without the param. Addressed via data-prose
// (CSS-module class names are hashed out of the live DOM).
if (new URLSearchParams(window.location.search).get('skim') === '1') { if (new URLSearchParams(window.location.search).get('skim') === '1') {
const prose = article.querySelector('.prose'); const prose = article.querySelector('[data-prose]');
if (prose) prose.classList.add('prose-skim'); if (prose) prose.dataset.skim = '1';
} }
return () => cleanups.forEach((fn) => fn()); return () => cleanups.forEach((fn) => fn());
......
...@@ -124,6 +124,17 @@ ...@@ -124,6 +124,17 @@
text-wrap: balance; text-wrap: balance;
} }
/* Belt and suspenders for long titles: balance (above) makes any wrap even,
and on wide screens the title escapes the 68ch prose measure the way code
blocks do — a one-line title beats a balanced two-line one. */
@media (min-width: 80rem) {
.title {
width: min(56rem, calc(100vw - 30rem));
margin-left: 50%;
transform: translateX(-50%);
}
}
.meta { .meta {
margin: 0.6rem 0 0; margin: 0.6rem 0 0;
display: flex; display: flex;
...@@ -600,11 +611,118 @@ ...@@ -600,11 +611,118 @@
} }
/* ?skim=1 (ArticleEnhance) — the skimmer's-eye view: structure and media /* ?skim=1 (ArticleEnhance) — the skimmer's-eye view: structure and media
stay, prose paragraphs fold. What's left should still tell the story. */ stay, prose paragraphs fold. What's left should still tell the story.
.article .prose.prose-skim p { Attribute hooks, not classes: the prose div's class name is hashed. */
.article [data-prose][data-skim] p {
display: none; display: none;
} }
/* Hydra islands (HydraEmbed) — bookend sketches resolved at build time.
The facade is an <a> so no-JS readers keep a real link to the sketch's
origin; the credit strip is hover-revealed, always visible on touch. */
.hydra {
margin: 2rem 0;
}
.hydraStage {
position: relative;
border-radius: 10px;
overflow: hidden;
background: #000;
}
.hydraCanvas,
.hydraFacade {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
}
.hydraCanvas {
background: #000;
}
.hydraFacade {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.75rem;
color: #eee;
text-decoration: none;
}
.hydraPlay {
font-size: 2.2rem;
line-height: 1;
width: 4rem;
height: 4rem;
display: grid;
place-items: center;
border: 1px solid rgba(255, 255, 255, 0.4);
border-radius: 50%;
padding-left: 0.2rem;
transition: transform 0.2s ease, background 0.2s ease;
}
.hydraFacade:hover .hydraPlay {
transform: scale(1.08);
background: rgba(255, 255, 255, 0.08);
}
.hydraHint {
font-size: 0.85rem;
opacity: 0.8;
}
.hydraFooter {
position: absolute;
inset: auto 0 0 0;
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 0.3rem 1rem;
padding: 0.4rem 0.9rem;
font-size: 0.78rem;
/* Strictly monochrome — this strip floats over the sketch's output, so
theme tokens (which flip with the site's light/dark) would betray it. */
color: rgba(255, 255, 255, 0.85);
background: linear-gradient(transparent, rgba(0, 0, 0, 0.78));
opacity: 0;
transition: opacity 0.2s ease;
}
.hydraStage:hover .hydraFooter,
.hydraStage:focus-within .hydraFooter {
opacity: 1;
}
@media (hover: none) {
.hydraFooter {
opacity: 1;
}
}
.hydraTitle {
font-weight: 600;
}
.hydraFooter a {
color: inherit;
text-decoration: underline;
text-underline-offset: 2px;
}
.hydraFooter a:visited,
.hydraFooter a:hover {
color: rgba(255, 255, 255, 0.85);
}
.hydraCode {
margin-top: 0.4rem;
}
.hydraCode summary {
cursor: pointer;
font-size: 0.8rem;
color: var(--text-muted);
}
.hydraCode pre {
max-height: 22rem;
overflow: auto;
padding: 0.9rem 1.1rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
font-size: 0.8rem;
line-height: 1.5;
}
/* Code blocks break out of the 68ch prose measure on wide screens: code /* Code blocks break out of the 68ch prose measure on wide screens: code
wants ~120 mono columns, prose wants its measure. The breakout centers on wants ~120 mono columns, prose wants its measure. The breakout centers on
the core (which is viewport-centered), capped so it never slides under the the core (which is viewport-centered), capped so it never slides under the
...@@ -817,7 +935,7 @@ ...@@ -817,7 +935,7 @@
.pager a { .pager a {
color: var(--text-primary); color: var(--text-primary);
text-decoration: none; text-decoration: none;
max-width: 34ch; max-width: 42ch;
/* Long titles wrap — balance evens the lines so a 2-line title looks /* Long titles wrap — balance evens the lines so a 2-line title looks
set, not squeezed. */ set, not squeezed. */
text-wrap: balance; text-wrap: balance;
......
...@@ -34,7 +34,7 @@ export default function Blog() { ...@@ -34,7 +34,7 @@ export default function Blog() {
className="block rounded-xl border p-4 leading-relaxed transition-colors border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--surface-raised)]" className="block rounded-xl border p-4 leading-relaxed transition-colors border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--surface-raised)]"
> >
<span className="flex items-baseline justify-between gap-3"> <span className="flex items-baseline justify-between gap-3">
<span className="font-medium text-[var(--text-primary)]"> <span className="font-medium text-[var(--text-primary)] text-balance">
{title} {title}
</span> </span>
<span className="text-xs whitespace-nowrap text-[var(--text-muted)]"> <span className="text-xs whitespace-nowrap text-[var(--text-muted)]">
......
...@@ -17,7 +17,7 @@ function TeaserCard({ href, title, meta, description }) { ...@@ -17,7 +17,7 @@ function TeaserCard({ href, title, meta, description }) {
href={href} href={href}
className="block rounded-xl border p-4 leading-relaxed transition-colors border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--surface-raised)]" className="block rounded-xl border p-4 leading-relaxed transition-colors border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--surface-raised)]"
> >
<span className="block font-medium text-[var(--text-primary)]">{title}</span> <span className="block font-medium text-[var(--text-primary)] text-balance">{title}</span>
{meta && ( {meta && (
<span className="block mt-1 text-xs text-[var(--text-muted)]">{meta}</span> <span className="block mt-1 text-xs text-[var(--text-muted)]">{meta}</span>
)} )}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment