diff --git a/docs/architecture/05-rendering-theming-preview.md b/docs/architecture/05-rendering-theming-preview.md index c1b0496..6ebeafe 100644 --- a/docs/architecture/05-rendering-theming-preview.md +++ b/docs/architecture/05-rendering-theming-preview.md @@ -576,6 +576,14 @@ It does two deterministic things, on a **deep copy** of the spec: and **removes** `width`; Full sets both — see spec §04 → Fit-mode sizing), recursing the same way. +The fit recursion has one Vega-Lite limit: **`"container"` sizing only works on +single and layered views** — facet children fall back with a warning (panel +widths become timing-dependent) and concat children fall back to pad-autosize +(axes overflow a fixed card). A surface that renders a composed spec at a fixed +size must ask for `fitMode: 'default'` and let the spec's declared per-view +`width`/`height` stand — the landing's `LandingChart` exposes this as a prop +for its composed demos. + This is _content_ preparation, not embedding, and it is fully covered by the _Live Preview_ spec. The only invariant this doc cares about: diff --git a/src/landing/Landing.module.css b/src/landing/Landing.module.css index 47ae816..3e85ffc 100644 --- a/src/landing/Landing.module.css +++ b/src/landing/Landing.module.css @@ -220,6 +220,20 @@ align-items: center; gap: var(--space-3); } +/* "Open in Astrolabe →" beside the Preview column head — the hand-off from + playing with the demo to holding the same chart in the app. */ +.colHeadLink { + margin-left: auto; + color: var(--accent); + text-decoration: none; + text-transform: none; + letter-spacing: normal; + font-size: 12px; +} +.colHeadLink:hover { + text-decoration: underline; +} + .libList { flex: 1 1 auto; min-height: 0; @@ -461,9 +475,11 @@ } /* theme demo */ +/* Compact grid — the theme *switch* is the demo; three charts in one glance, + not a page of scroll. */ .gallery { - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); margin-top: var(--space-5); } @@ -598,6 +614,248 @@ margin-left: auto; } +/* ── editor proof: staged still of the editor mid-thought (no Monaco) ─────── */ +.edBody { + position: relative; + padding: var(--space-4) var(--space-5); + font-family: var(--font-mono); + font-size: 12px; + overflow-x: auto; +} +.edLines { + margin: 0; + line-height: 1.7; + white-space: pre; + color: var(--text); +} +.edLens { + display: block; + font-size: 11px; + color: var(--accent); + margin-bottom: 2px; +} +.edCursor { + display: inline-block; + width: 2px; + height: 13px; + vertical-align: text-bottom; + background: var(--accent); +} +.edPopup { + display: flex; + margin: var(--space-2) 0 var(--space-3) var(--space-8); + max-width: 420px; + border: 1px solid var(--border); + background: var(--layer-01); + box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.4); + font-size: 12px; +} +.edOptions { + list-style: none; + margin: 0; + padding: var(--space-1) 0; + min-width: 110px; + border-right: 1px solid var(--border); +} +.edOptions li { + padding: 2px var(--space-3); +} +.edOptionSel { + background: var(--accent-soft); + color: var(--accent); +} +.edDoc { + padding: var(--space-2) var(--space-3); + color: var(--text-secondary); + line-height: 1.5; +} +.edSquiggle { + text-decoration: underline wavy var(--support-error); + text-underline-offset: 3px; +} +/* Marker hover, anchored under the squiggled token like Monaco's. */ +.edHover { + margin: var(--space-2) 0 0 var(--space-8); + max-width: 420px; + padding: var(--space-2) var(--space-3); + border: 1px solid var(--border); + border-left: 3px solid var(--support-error); + background: var(--layer-01); + box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.4); + font-size: 12px; + color: var(--text-secondary); + line-height: 1.5; +} + +/* ── objections: the habit cluster, answered as on-ramps ──────────────────── */ +.objections { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: var(--space-7); + padding: 0 0 var(--space-9); +} +.objections h3 { + font-size: 15px; + font-weight: 600; + margin: 0 0 var(--space-2); +} +.objections p { + margin: 0; + font-size: 14px; + line-height: 1.55; + color: var(--text-secondary); +} + +/* Inline accent link inside body copy (builder CTA, close note). */ +.inlineLink { + color: var(--accent); + text-decoration: none; +} +.inlineLink:hover { + text-decoration: underline; +} + +/* Store-once-reference-many diagram: a dataset with its snippets as a tree. */ +.refDiagram { + padding: var(--space-4); + border-bottom: 1px solid var(--border); +} +.refDataset { + display: flex; + align-items: center; + gap: var(--space-2); + font-size: 13px; + font-weight: 600; +} +.refDot { + width: 10px; + height: 10px; + border-radius: 50%; + background: var(--accent); + flex: 0 0 auto; +} +.refMeta { + font-weight: 400; + color: var(--text-secondary); +} +.refTree { + list-style: none; + margin: var(--space-1) 0 0 4px; + padding: 0; +} +.refTree li { + position: relative; + padding: 3px 0 3px 22px; + font-size: 13px; +} +/* Tree connectors: a vertical rail plus an elbow per row. */ +.refTree li::before { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + border-left: 1px solid var(--border-strong); +} +.refTree li:last-child::before { + bottom: auto; + height: 14px; +} +.refTree li::after { + content: ''; + position: absolute; + left: 0; + top: 14px; + width: 14px; + border-top: 1px solid var(--border-strong); +} +.refMore { + color: var(--text-secondary); + font-style: italic; +} + +/* Stacked capability section: text intro above, demo at full column width. */ +.capStack { + padding: var(--space-9) 0; +} +.capStack .shot { + margin-top: var(--space-6); +} + +.themeNote { + margin: var(--space-3) 0 0; + font-size: 13px; + color: var(--text-secondary); +} + +.closeNote { + margin-top: var(--space-4); + font-size: 14px; + color: var(--text-secondary); +} + +/* ── showcase: live spec ↔ chart demos ("What Vega-Lite can do") ─────────── */ +.showcase { + padding: var(--space-9) 0 var(--space-5); +} +.showcaseIntro { + max-width: 62ch; + margin-bottom: var(--space-8); +} +.demo { + margin-bottom: var(--space-9); +} +.demoTitle { + font-size: 18px; + font-weight: 600; + margin: 0 0 var(--space-2); +} +.demoBlurb { + color: var(--text-secondary); + font-size: 14px; + line-height: 1.55; + max-width: 66ch; + margin: 0 0 var(--space-5); +} +.demoRow { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); + gap: var(--space-6); + align-items: stretch; +} +/* The spec pane: same chrome as the hero window's code column; the inner .code + pre scrolls when the spec outgrows the cap. */ +.demoCode { + display: flex; + min-width: 0; + border: 1px solid var(--border); + background: var(--layer-01); + max-height: 400px; + overflow: hidden; +} +.demoCode .code { + min-width: 0; +} +.demoChartCard { + min-width: 0; + border: 1px solid var(--border); + background: var(--bg); + box-shadow: 0 16px 40px -20px rgba(0, 0, 0, 0.3); + padding: var(--space-5); + display: flex; + flex-direction: column; + justify-content: center; + /* Fixed-size composed charts (the facet demo) scroll inside the card rather + than widening the page on small screens. */ + overflow-x: auto; +} +.demoHint { + margin: var(--space-4) 0 0; + font-family: var(--font-mono); + font-size: 12px; + color: var(--accent); +} + @media (max-width: 760px) { .appBody { grid-template-columns: 1fr; @@ -612,11 +870,24 @@ .code { max-height: 320px; } + /* minmax(0, …): a plain 1fr track lets pre-formatted code set the column's + min-content width and push the page wider than the viewport. */ .cap, - .creedGrid { - grid-template-columns: 1fr; + .creedGrid, + .demoRow, + .objections, + .gallery { + grid-template-columns: minmax(0, 1fr); gap: var(--space-6); } + .demoCode { + max-height: 300px; + } + /* Section anchors don't fit a phone-width nav row; the page is one scroll + anyway — keep brand, theme toggle, and the CTA. */ + .navLink { + display: none; + } .capRev .capText { order: 0; } diff --git a/src/landing/Landing.tsx b/src/landing/Landing.tsx index 12621a7..7e22d26 100644 --- a/src/landing/Landing.tsx +++ b/src/landing/Landing.tsx @@ -27,10 +27,18 @@ import { } from '@core/sample-dataset'; import { DEMO_CUSTOM_THEMES } from './demo-themes'; import { LandingChart } from './LandingChart'; +import { + SHOWCASE_DEMOS, + showcaseDisplaySpec, + showcaseFitMode, + type ShowcaseDemo, +} from './showcase-specs'; import styles from './Landing.module.css'; // TODO: import { UiTheme } from '@core/theme' instead of redeclaring it — the // learn entry already uses the canonical one. +// TODO: this file is the repo's second-largest; on the next added section, split +// into per-section files under src/landing/ (eng-council 2026-07). type UiTheme = 'light' | 'dark'; // Minimal JSON syntax highlighter for the read-only spec view: keys, strings, @@ -85,12 +93,41 @@ function Brand(): ReactNode { ); } +/** The framed app-window chrome (traffic-dot title bar) every section shot sits in. */ +function Shot({ bar, children }: { bar: ReactNode; children: ReactNode }): ReactNode { + return ( +
{demo.blurb}
+{demo.hint}
++ Vega-Lite is a grammar: declare what the data is and how it maps to marks, and the + rendering — axes, legends, interaction — follows. The three charts below are live, and the + text beside each one is its whole program — the data referenced by name, the way a snippet + in Astrolabe reads. +
++ Editorial, Blueprint, and Sunset are custom themes made in the Theme Builder; the rest ship + as presets. +
- Astrolabe is a local studio for Vega-Lite. Write a spec by hand or build one by - clicking, give it a theme, and keep all your charts in one searchable library. + Astrolabe is a local studio for Vega-Lite — the grammar that turns a short JSON spec + into an interactive chart. Write specs by hand or build them by clicking, give them a + theme, and keep every chart in one searchable library.
Export a single chart or the whole library as standard JSON and open it in any other - Vega tool. + Vega tool. If Astrolabe vanished tomorrow, your charts wouldn't notice.
- Author by hand or by clicking, with your own fonts and themes. Arrange the library - to match how you work. + The whole workspace — snippets, datasets, themes, fonts — exports as a single JSON + file. Back it up like any file you own and import it on any machine. No sync service + to trust.
+ New to Vega-Lite?{' '} + + Start with the deep dives + + . +