Merge branch 'refactor/task-07-primitives'
This commit is contained in:
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
// Callout — gold-background emphasis block. Covers the two existing variants
|
||||||
|
// the source uses:
|
||||||
|
// • `variant="label"` (default) — 150px label + body. Matches `.callout`.
|
||||||
|
// • `variant="split"` — 2 equal columns; the named `aside` slot fills the
|
||||||
|
// right column. Matches the full-guide `.thesis` (where the right side
|
||||||
|
// holds a "signal" visualisation).
|
||||||
|
//
|
||||||
|
// Background is always `var(--gold)`. The label uses the Eyebrow treatment.
|
||||||
|
// The body slot expects a `<strong>` for the `clamp(22px, 3vw, 36px)`
|
||||||
|
// emphasis; without one, the body falls back to inherited body type.
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Short uppercase label, same treatment as Eyebrow. */
|
||||||
|
label: string;
|
||||||
|
/** Colour tone for the label. */
|
||||||
|
tone?: 'accent' | 'gold' | 'red';
|
||||||
|
/** Layout variant. Defaults to the label+body `.callout` shape. */
|
||||||
|
variant?: 'label' | 'split';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { label, tone = 'accent', variant = 'label' } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<section class:list={['callout', `variant-${variant}`]}>
|
||||||
|
<span class:list={['label', `tone-${tone}`]}>{label}</span>
|
||||||
|
<div class="body"><slot /></div>
|
||||||
|
{
|
||||||
|
variant === 'split' && (
|
||||||
|
<div class="aside">
|
||||||
|
<slot name="aside" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.callout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px 1fr;
|
||||||
|
gap: 30px;
|
||||||
|
margin-top: 70px;
|
||||||
|
padding: 27px;
|
||||||
|
background: var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thesis variant: 2 equal columns with the right column reserved for the
|
||||||
|
aside slot. Matches full-guide `.thesis`. */
|
||||||
|
.callout.variant-split {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 110px;
|
||||||
|
padding: 28px;
|
||||||
|
}
|
||||||
|
.callout.variant-split .body {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The label spans the eyebrow treatment. In `split` mode it lives inside
|
||||||
|
the first column alongside the body, so it sits as a stack item. */
|
||||||
|
.label {
|
||||||
|
font:
|
||||||
|
600 var(--step-0) 'DM Mono',
|
||||||
|
monospace;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.callout.variant-split .label {
|
||||||
|
align-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The body renders the slot verbatim; the strong treatment that the source
|
||||||
|
markup uses is set here so the call site can just write <strong>…</strong>. */
|
||||||
|
.body :global(strong) {
|
||||||
|
max-width: 850px;
|
||||||
|
font-size: clamp(22px, 3vw, 36px);
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
.callout.variant-split .body :global(strong) {
|
||||||
|
font-size: clamp(24px, 4vw, 46px);
|
||||||
|
line-height: 1.05;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-accent {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.tone-gold {
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
.tone-red {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.callout,
|
||||||
|
.callout.variant-split {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
// CodeBlock — `<pre>` on `--ink` with gold text. Default treatment matches
|
||||||
|
// `.worktrees pre` from `styles.css` and the dark pre blocks across the
|
||||||
|
// guide (rule stage-detail, skill-detail, example-grid, copy-lab, prompt-card,
|
||||||
|
// install-skills). It is the one canonical "code on dark" surface — every
|
||||||
|
// page-level variation (the `.skills>pre` lighter text, the `.builder-artifact`
|
||||||
|
// grid backdrop, etc.) layers extra styles on top via the call site.
|
||||||
|
//
|
||||||
|
// `tone` flips between the warm `--gold` (default) and the lighter `--paper`
|
||||||
|
// for the few blocks that read as documentation rather than terminal output.
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Text colour, mapped to a token. Default is the warm gold used on every
|
||||||
|
* current `.worktrees pre` and rule `.stage-detail pre` style. */
|
||||||
|
tone?: 'gold' | 'paper';
|
||||||
|
/** Optional accessible label. Use when the contents have no heading context. */
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tone = 'gold', label } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<pre class:list={['code-block', `tone-${tone}`]} aria-label={label}>
|
||||||
|
<code><slot /></code>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.code-block {
|
||||||
|
margin: 32px 0 0;
|
||||||
|
padding: 20px;
|
||||||
|
overflow: auto;
|
||||||
|
color: var(--gold);
|
||||||
|
background: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deliberately no font declaration. `.worktrees pre` — the block this
|
||||||
|
component reproduces — sets none either, so the text inherits the UA
|
||||||
|
default for `pre`. Declaring one here would change how the page renders,
|
||||||
|
which is a redesign, not a refactor.
|
||||||
|
Two *other* legacy blocks do set one, and neither is this component's job:
|
||||||
|
`chapters.css .panel code` (14px/1.8 ui-monospace) and
|
||||||
|
`skills-review/styles.css .preview code` (12px/1.65 ui-monospace). Whoever
|
||||||
|
migrates those needs tokens for them first. */
|
||||||
|
|
||||||
|
/* Lighter text used by `.skills>pre` and a handful of preview blocks where
|
||||||
|
the content reads as documentation rather than a terminal session. */
|
||||||
|
.tone-paper {
|
||||||
|
color: var(--paper);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
// Eyebrow — the small uppercase monospace label that opens almost every
|
||||||
|
// section on the guide surface. Single most repeated treatment on the site
|
||||||
|
// (19+ HTML occurrences) and a signature of the design.
|
||||||
|
//
|
||||||
|
// `tone` maps directly to the design-system tokens. Pages inside a `--deep`
|
||||||
|
// surface (e.g. `.worktrees`) pass `tone="gold"` so the label stays readable
|
||||||
|
// on the dark background. Chapters pages (drifted palette) use `tone="red"`.
|
||||||
|
//
|
||||||
|
// The font stack keeps 'DM Mono' first — when the broken @font-face gets
|
||||||
|
// fixed, the intended face will render. Today it falls through to the generic
|
||||||
|
// monospace, which is what the site has been rendering all along.
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Short uppercase label, rendered literally. Wrap in markup at the call site
|
||||||
|
* if you need an inline icon or emphasis inside the eyebrow. */
|
||||||
|
label: string;
|
||||||
|
/** Colour tone. Maps to a token; defaults to the guide-surface accent. */
|
||||||
|
tone?: 'accent' | 'gold' | 'red';
|
||||||
|
/** Element override. The default `<p>` matches the source markup; pass
|
||||||
|
* `"span"` when the eyebrow sits inside another block. */
|
||||||
|
as?: 'p' | 'span' | 'div';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { label, tone = 'accent', as: Tag = 'p' } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Tag class:list={['eyebrow', `tone-${tone}`]}>{label}</Tag>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.eyebrow {
|
||||||
|
margin: 0;
|
||||||
|
/* UNRESOLVED — this consolidates three drifted legacy declarations and
|
||||||
|
matches none of them exactly:
|
||||||
|
styles.css 500 10px 'DM Mono', monospace .1em
|
||||||
|
chapters.css 700 11px monospace .12em
|
||||||
|
skills-review/styles.css 700 10px monospace .1em
|
||||||
|
`var(--step-0)` (11px) is task 02's decided token, so the size is
|
||||||
|
deliberate. The 600 weight is not — legacy uses 500 and 700, never 600.
|
||||||
|
Settle this with the font decision in .agents/context/design-system.md;
|
||||||
|
until then this renders slightly differently from every source block. */
|
||||||
|
font:
|
||||||
|
600 var(--step-0) 'DM Mono',
|
||||||
|
monospace;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.tone-accent {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.tone-gold {
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
.tone-red {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
// Rule — the gold-top-border section divider. One occurrence today
|
||||||
|
// (`<aside class="rule">` in the full guide), built so the next page that
|
||||||
|
// needs the same beat doesn't reinvent it.
|
||||||
|
//
|
||||||
|
// Layout is a 150px label column + body, matching `styles.css`'s `.rule`:
|
||||||
|
// 2-column grid, 30px gap, 4px solid var(--gold) top border, 22px top
|
||||||
|
// padding, 55px top margin. The body expects a single `<strong>` to carry
|
||||||
|
// the `clamp(24px, 3.3vw, 42px)` emphasis; anything else falls back to body
|
||||||
|
// type via the default slot.
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Short uppercase label, same treatment as Eyebrow but rendered as a
|
||||||
|
* `<span>` so it can live inside an `<aside>`. */
|
||||||
|
label: string;
|
||||||
|
/** Colour tone for the label. */
|
||||||
|
tone?: 'accent' | 'gold' | 'red';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { label, tone = 'accent' } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<aside class="rule">
|
||||||
|
<span class:list={['label', `tone-${tone}`]}>{label}</span>
|
||||||
|
<div class="body"><slot /></div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.rule {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px 1fr;
|
||||||
|
gap: 30px;
|
||||||
|
margin-top: 55px;
|
||||||
|
padding-top: 22px;
|
||||||
|
border-top: 4px solid var(--gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font:
|
||||||
|
600 var(--step-0) 'DM Mono',
|
||||||
|
monospace;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The body renders the slot verbatim; the strong treatment that the source
|
||||||
|
markup uses is set here so the call site can just write <strong>…</strong>. */
|
||||||
|
.body :global(strong) {
|
||||||
|
max-width: 850px;
|
||||||
|
font-size: clamp(24px, 3.3vw, 42px);
|
||||||
|
line-height: 1.12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-accent {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.tone-gold {
|
||||||
|
color: var(--gold);
|
||||||
|
}
|
||||||
|
.tone-red {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.rule {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user