--- import Picker from '../layouts/Picker.astro'; import Artboard from '../components/Artboard.astro'; import QuestionScreen from '../components/QuestionScreen.astro'; import iconPacks from '../data/icon-packs.json'; import { SURFACE_MODES, surfaceAttrs, surfaceTabsAttrs } from '../data/surfaces.js'; const roles = [ ['primary', 'Primary'], ['secondary', 'Secondary'], ['tertiary', 'Tertiary'], ['neutral', 'Neutral'], ]; // Musical intervals, smallest step first. The ratio is the multiplier between // one size and the next; the description says what that much contrast is for, // since the number alone tells nobody which to pick. const scales = [ ['minor-second', 1.067, 'Minor Second', 'Almost no contrast. For dense tools where weight and color carry hierarchy instead of size.'], ['major-second', 1.125, 'Major Second', 'A quiet step. Long documents and data screens that need many levels close together.'], ['minor-third', 1.2, 'Minor Third', 'The workhorse. Clear order without shouting, and it survives on small screens.'], ['major-third', 1.25, 'Major Third', 'Confident separation. A safe default when the page has both marketing and interface on it.'], ['perfect-fourth', 1.333, 'Perfect Fourth', 'Real jumps between levels. Landing pages where the headline has to lead.'], ['augmented-fourth', 1.414, 'Augmented Fourth', 'Sharp contrast. Editorial layouts built from few sizes used decisively.'], ['perfect-fifth', 1.5, 'Perfect Fifth', 'Display type against small text, with little in between. Poster thinking.'], ['golden-ratio', 1.618, 'Golden Ratio', 'The widest range here. Beautiful with one big statement, awkward with six levels.'], ]; // Exponent above the 16px base: P sits at the base, H1 six steps up. const scaleRows = [['H1', 6], ['H2', 5], ['H3', 4], ['H4', 3], ['H5', 2], ['H6', 1], ['P', 0]]; // Only the row copy is rendered here. The glyphs are 109KB of markup for sets // the run will use one of, so they are fetched when the screen first opens. const iconRows = iconPacks.packs.map((pack) => ({ id: pack.id, name: pack.name, license: pack.license, url: pack.url, note: pack.note, meta: `${pack.grid} grid / ${pack.weight} / ${pack.license}`, })); // The surface tiles and the per-surface answer matrix both live in // data/surfaces.js, so the tiles carry what each surface allows without the // matrix being restated on every screen that reads it. // The five questions that are answered by looking at a wireframe page. Each one // only rewrites the artboard slots it owns, so by the last screen the page is // showing every decision made before it. Motion is the one question whose answer // cannot be read on a handset, so it takes the frame alone. // // All five draw a board per surface they are put to, which is four on // boundaries, corners, and depth and a pair each on the two scoped questions, // motion and layout. A structural answer is a claim about a kind of page, and the // kinds are not the same shape: an app shell divides into a rail, a working // column, and a panel, a document is a rail and a measure, an index is a run of // entries. Repainting one landing page under four labels showed the same page // four times and asked the visitor to imagine the rest. // // Which board is showing is read off `data-surface`, the attribute the component // already publishes and the one the tab strip toggles, rather than a class per // screen per surface. Screen 06 takes a class because its scenes are written per // board; the rest ask the same question of every board and only need to know // which anatomy is under them. const questions = [ { id: '06', step: 'Motion', slug: 'motion', name: 'motion-energy', title: 'How much movement should it have?', legend: 'Motion energy', cta: 'Select motion energy', previewClass: 'picker-preview-motion', phone: false, // The two surfaces this question is put to, and the only screen where a // surface answers on a page of its own kind: an energy is demonstrated by // watching a page use it, and a landing page and a portfolio use movement // for different ends. Repainting one wireframe would show the same scene // twice under two labels. boards: [ { surface: 'persuade', cell: 'persuade-restrained' }, { surface: 'persuade', cell: 'persuade-responsive' }, { surface: 'persuade', cell: 'persuade-choreographed' }, { surface: 'experience', class: 'picker-preview-motion--index', cell: 'experience-restrained' }, { surface: 'experience', class: 'picker-preview-motion--index', cell: 'experience-responsive' }, { surface: 'experience', class: 'picker-preview-motion--index', cell: 'experience-choreographed' }, ], options: [ { value: 'restrained', title: 'Restrained', desc: 'State changes only. Things are already changed by the time you see them.', }, { value: 'responsive', title: 'Responsive', desc: 'Feedback and transitions on whatever you touch. Nothing is orchestrated.', }, { value: 'choreographed', title: 'Choreographed', desc: 'Entrances are staged and scrolling drives sequences.', }, ], }, { id: '07', step: 'Layout', slug: 'layout', name: 'layout-structure', title: 'How strict should the layout feel?', legend: 'Layout structure', cta: 'Select layout structure', previewClass: 'picker-strategy-preview picker-preview-layout', // The two surfaces this question is put to, for the reason in // data/surfaces.js: a landing page answers in the spans its hero and its // card row take and a portfolio in how each entry splits between the work // and its caption, where a shell and a document are composed by what they // hold. The answer is one value all the same, and the boards on the screens // after this one show it on all four pages. boards: [ { surface: 'persuade' }, { surface: 'experience' }, ], options: [ { value: 'simple-grid', title: 'Simple grid', desc: 'Everything lines up. Equal columns and one rhythm down the page.', }, { value: 'balanced', title: 'Balanced', desc: 'An aligned grid with a few deliberate breaks that carry the emphasis.', }, { value: 'freeform', title: 'Freeform', desc: 'Blocks step out of the grid and overlap where it pays off.', }, ], }, { id: '08', step: 'Boundaries', slug: 'boundaries', name: 'boundary-style', title: 'How should sections be separated?', legend: 'Boundary style', cta: 'Select boundary style', previewClass: 'picker-preview-boundaries', derived: true, boards: [{ surface: 'persuade' }], options: [ { value: 'open-space', title: 'Open space', desc: 'Nothing between sections but room. Spacing does the dividing.', blocked: 'Sidebars and toolbars need a ground of their own, which is the one thing air cannot give them.', }, { value: 'thin-dividers', title: 'Thin dividers', desc: 'A hairline marks where one section ends and the next starts.', }, { value: 'surface-changes', title: 'Surface changes', desc: 'Bands of tone. Sections are told apart by the ground they sit on.', }, { value: 'cards-and-panels', title: 'Cards and panels', desc: 'Content sits inside containers with edges you can see.', blocked: 'An edge around every block comes between people and the thing they came for.', }, ], }, { id: '09', step: 'Corners', slug: 'corners', name: 'corner-style', title: 'How round should shapes be?', legend: 'Corner style', cta: 'Select corner style', previewClass: 'picker-preview-corners', derived: true, boards: [{ surface: 'persuade' }], options: [ { value: 'sharp', title: 'Sharp', desc: 'Square corners throughout. Precise, drafted, architectural.', }, { value: 'slightly-soft', title: 'Slightly soft', desc: 'Just enough radius to take the edge off without being noticed.', }, { value: 'friendly', title: 'Friendly', desc: 'Cards, buttons, and images are clearly rounded.', }, { value: 'pill', title: 'Pill-like', desc: 'Buttons and tags go fully round.', blocked: 'Fully round controls are the loudest shape on a page where the work should lead.', }, ], }, { id: '10', step: 'Depth', slug: 'depth', name: 'depth-style', title: 'How much depth should the surface have?', legend: 'Depth style', cta: 'Select depth style', previewClass: 'picker-preview-depth', derived: true, boards: [], options: [ { value: 'flat', title: 'Flat', desc: 'One plane. Nothing casts a shadow.', }, { value: 'soft-lift', title: 'Soft lift', desc: 'Cards and controls sit a little off the page.', }, { value: 'floating', title: 'Floating', desc: 'Panels are well above the surface, with the lift to prove it.', blocked: 'Lift this deep belongs to menus and dialogs, not to a page people work in or read at length.', }, ], }, ]; ---
{/* Which per-surface answers were actually opened. Every chosen surface leaves an answer either way, so the value alone cannot tell a confirmed default from an inherited one, and the design context document says which. Filled by the questionnaire as it runs. */}
Impeccable

Let's build your
design system.

{/* Shown only when the boot contract restored a run; the body attribute the restore sets is what reveals it. */}

Arrow keys to move

{questions.filter((question) => question.id === '07').map((question) => )} {/* Screen 04b: the configure hub. Every remaining question already holds an answer (defaults are pre-filled the moment a surface tile is checked), so the run can end here. The cards are skeletons; previews, tabs, tooltip summaries, and edited marks are written by renderHub() in scripts/palette-picker.js on every arrival. The column wrappers are display: contents, so the five near-uniform cards flow the grid three over two. */} {questions.filter((question) => question.id !== '07').map((question) => )}
{/* Design context document — hidden until the review screen saves the answers. Mosaic, morph, and article vocabulary ported unchanged from docs/design-context-categorization/design-context.html; the detail templates start empty and are filled from the interview by scripts/design-context.js. */} {/* Detail articles: empty shells filled per run by design-context.js. */} {/* Expander shell: sidebar + topbar + main, cloned per open. */} {/* Edit-request modal: complex changes the document cannot apply itself are written up here and queued for the agent over the doc session. */}

Request a change

Describe the change; the agent applies it to the design document and the page updates here.

Change
{/* Live edit tray: every queued request with its status, fed by polling. */}

Add a custom font

Link a hosted stylesheet or upload a face. Nothing is checked until you finish.

{[['heading', 'Heading'], ['body', 'Body']].map(([role, label]) => (
{label}

or

))}