Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ Compatible with the 55+ design systems in [awesome-design-md](https://github.com

Render a canvas at multiple viewport sizes. Defaults to mobile (390x844), tablet (768x1024), and desktop (1440x900).

The renderer emits `clamp()` for paddings ≥ 32px and font sizes ≥ 24px, so headlines and large spacing shrink proportionally at narrower viewports (assuming a 1440px design width). Smaller values stay static.
The renderer emits `clamp()` for paddings ≥ 32px and font sizes ≥ 24px, so headlines and large spacing shrink proportionally at narrower viewports. Font sizes render as authored at the root's own width (a 33px title on a 390 phone artboard renders 33px; 1440 when the root has no numeric width) and shrink below it, to 60% at most (16px floor); paddings shrink against a 1440px design width. Smaller values stay static.

| Param | Type | Description |
|-------|------|-------------|
Expand Down
4 changes: 3 additions & 1 deletion VISION.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,9 @@ The mobile attempt (2026-09-07) built one iOS screen end to end on v2.2.0 and go
- [x] Slice D — vocabulary: `fixed` / `sticky` positioning with the renderer reserving room for pinned chrome, a root that grows with long content (closing slice C's long-screen gap), the `status-bar`, `home-indicator`, `nav-bar`, `tab-bar`, `button`, `list-row` and `sheet` primitives, the primitives joining the 44px target rule, `mobile-tab-bar`, and pinned bars in the safe-area rule (`safeArea` on the root landed in slice B)
- [x] Slice E — starting points: anatomy and realisation on structures, resolution by canvas type, six mobile realisations, and the pattern gate extended to them
- [x] Slice F — the viewer: thumbnails at the artboard's real proportions and a device frame with a safe-area overlay
- [ ] Slice G — the acceptance re-run
- [x] Slice G — the acceptance re-run: Ridgeline Today rebuilt from `dashboard-mobile` in 33 nodes (93 by hand), 100/100 and READY in fast and detailed mode with no dark-theme finding, `canvas_stress` CLEAN, every tap target a primitive, pinned as `test-ridgeline.ts`; the re-run surfaced two render defects, fixed here: large type now scales against the artboard's own width (a phone's titles rendered at 60%, under the body), and chart tick labels no longer stretch with the plot

All seven slices are merged and the acceptance re-run passed. The phase is closed.

_Full spec-driven breakdown in [`docs/specs/PHASE-30-SPEC.md`](docs/specs/PHASE-30-SPEC.md). Deliberately out of scope: an Android profile, tablet and other types, a tappable flag on frames, a thumb-reach rule, interaction and flows, mobile import, and mobile commerce archetypes (those come next, on the anatomy/realisation split this phase creates)._

Expand Down
4 changes: 2 additions & 2 deletions docs/GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ The `chart` node owns the value→coordinate math — give it data and domains,
- **One node per chart, multi-series inside.** `series: [{ data, stroke, strokeDasharray?, area?, points? }]` — the 4-series pace-to-goal chart is one node with a shared scale.
- **Dash is the convention for projected vs actual.** Solid accent line + `strokeDasharray: "6 4"` reference/forecast lines — don't differentiate similar lines by colour alone.
- **X positions are data indexes.** A 7-point booked series against a 12-point target series stops at 7/12 of the width automatically; `xDomain`/`yDomain` default from the data (bars floor at 0).
- **Furniture is opt-in props**: `gridlines: 4`, `xLabels`/`yLabels` (spread evenly; empty strings skip intermediate ticks), `curve: "smooth"`, `kind: "bar"` for grouped bars.
- **Furniture is opt-in props**: `gridlines: 4`, `xLabels`/`yLabels` (spread evenly, and on a bar chart with one label per bar each centres under its bar; empty strings skip intermediate ticks; labels keep their 11px size at any chart width, so `width: "100%"` is safe; each x label truncates with an ellipsis inside its slot (its bar, or halfway to the nearest labelled tick on each side), so on a narrow chart use short labels ("Sep", not "September") and on a line chart leave ticks empty to give labels room: twelve months on a phone read as "Jan", "", "Mar", …), `curve: "smooth"`, `kind: "bar"` for grouped bars.
- **Editing a data point is a one-prop edit** — update the series array, done.
- **Bar emphasis is a prop, not a rebuild.** `highlight: [11]` (or just `highlight: 11`) on a bar series renders the selected bar solid while the rest go muted (~30%) — an entry that isn't an index into `data` emphasizes nothing, and the `batch_design` op result warns about it; add `barGradient: true` and the muted bars fade vertically inside the SVG — invisible to the gradient-overuse tell by construction. The floating tooltip card stays your composition (`position: "absolute"` frame with `$elevation.floating`).
- **Donuts are data-bound.** `kind: "donut"` + `segments: [{ value: 385, color: "$chart-1", label: "North" }, …]` + `innerRatio?` + `centerValue`/`centerLabel` — slices run clockwise from 12 o'clock, the center figure renders tabular and bold. Compose the legend yourself: rows of `$chart-*` dots + labels + values (legend layout is design, not charting). Never fake a ring with conic gradients.
Expand All @@ -190,7 +190,7 @@ The `chart` node owns the value→coordinate math — give it data and domains,
- **Three fixed-pixel cards in a horizontal row.** `width: 360` × 3 in a row without `responsive: "stack"` clips on a 390px mobile viewport instead of reflowing. Either set `responsive: "stack"` or use `width: "100%", maxWidth: 360`.
- **Setting `margin` on every node.** Use `gap` on the parent flex container and `padding` on the child. The renderer doesn't surface `margin`.
- **Setting `fontFamily` on every text node.** The renderer defaults to a system sans-serif stack at the body level. Only set `fontFamily` when you want a *different* face — and prefer `system-ui, -apple-system, sans-serif`-style stacks; if you need quoted multi-word names (`'Segoe UI'`), they're supported, but keep them inside the double-quoted value.
- **Hardcoding pixel font sizes everywhere.** Large sizes get a `clamp()` treatment by the renderer to scale down on small viewports — only set `fontSize` to the *desktop* value and let the renderer handle the rest.
- **Hardcoding pixel font sizes everywhere.** Large sizes (24px and up) get a `clamp()` treatment by the renderer to scale down on small viewports — set `fontSize` to the value you want at your artboard's width (the desktop value on a 1440 page, the phone value on a 390 mobile canvas) and let the renderer handle the rest.
- **Unicode glyphs as icon stand-ins.** `✓ ● ▾ ○` read as unfinished. Use the `icon` node type — two sets render by name as inline SVG: 1,900+ [Lucide](https://lucide.dev) (`icon: "check"`) and 3,800+ [Material Symbols](https://fonts.google.com/icons) (`icon: "material:check"`, `iconStyle: "outlined" | "rounded" | "sharp"`, `-fill` suffix for filled variants). `I("parent", { type: "icon", icon: "material:check", iconSize: 16, iconColor: "$primary" })`. For Material-style design systems, prefer the Material set.
- **Spelling an icon in the other set's style.** Lucide hyphenates multi-word names (`chevron-right`); Material Symbols keeps underscores and needs the prefix (`material:chevron_right`, `material:chevron_right-fill`). A bare `chevron_right` is looked up in Lucide and renders nothing. A name that resolves in neither set renders an empty slot, so `canvas_evaluate` reports it as a `structure` warning naming the spellings that do resolve — and `canvas_autofix` rewrites it when exactly one does.
- **Baking uppercase into `content`.** Use `textTransform: "uppercase"` (with `letterSpacing` for tracking) so the underlying copy stays editable and case-styling lives in the design, not the data.
Expand Down
Loading
Loading