agentsclimarketplace

Vectojs responsive layout

Skill vectojs/vectojs-skills/skills/vectojs-responsive-layout

Agent skills for building, optimizing, embedding, and exporting VectoJS projects with Codex, Claude Code, Cursor, and GitHub Copilot.

Install
npx -y skills add vectojs/vectojs-skills --skill vectojs-responsive-layout

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when designing adaptive VectoJS canvas layouts with browser resize or zoom, Stack, Flow, Card, ScrollView, VirtualList, responsive panels, dashboards, forms, or layout reflow.

SKILL.md

10.8 KB, as published. Nobody here has run it

VectoJS Responsive Layout

Use this skill when a VectoJS UI must adapt to viewport size, browser zoom, density, content length, or resizable panels.

Layout workflow

  1. Define layout state in logical CSS pixels, not backing-store pixels.
  2. Resize the Scene from the containing element, not blindly from window, when embedding in an app shell.
  3. Compose with Stack, Flow, Card, ScrollView, VirtualList, TreeView, and resizable panels.
  4. After direct child size changes, call the parent layout method and mark the scene dirty.
  5. Keep one scroll owner per region; avoid nested wheel handlers without clear boundaries.
  6. Use role labels and semantic regions even for canvas-rendered layout containers.

Read references/layout-recipes.md for copyable patterns. For OS/browser/zoom/DPR consistency and text-selection alignment (embedded scene.resize() bridge, Firefox Range recalibration, web-font race, the DPR-1-vs-2 test matrix), read references/cross-environment.md.

Design rules

  • Use scene.resize(width, height) for logical layout dimensions.
  • Let VectoJS/Canvas handle high-DPI backing stores; do not multiply layout coordinates by DPR.
  • Make breakpoint decisions from available logical width/height.
  • Prefer reflowing existing entities to destroying and recreating the full tree.
  • Reserve virtualization for long lists/tables/trees; do not render thousands of offscreen rows as regular children.
  • Treat browser zoom as a layout-input multiplier only when product requirements explicitly need density changes beyond normal CSS pixel behavior.

Common mistakes

MistakeCorrection
Reading canvas.width for layoutUse container CSS size or scene.width / scene.height.
Recreating every component on resizeReposition/reconfigure existing entities, then scene.markDirty().
ScrollView inside another wheel-capturing regionGive each wheel gesture one owner or define escape behavior.
Fixed desktop-only coordinatesAdd breakpoint functions and test narrow, wide, and zoomed layouts.
Changing child size without relayoutCall stack.layout() / equivalent and mark dirty.
Hand-syncing content.width = panel.width after every PanelGroup drag/resizePanel.setContent(content, fit?) / Card.setContent(content, fit?) (>= @vectojs/[email protected]) track the container's box automatically, fit: true by default. Pass fit: false for self-sizing content (bare Text with no maxWidth) — the default would overwrite its self-computed box every frame; wrap it in a Stack first if it needs to fill the viewport instead.
Growing ScrollView content without re-measuringscrollView.add() measures automatically, but mutating an existing child's size needs scrollView.updateContentSize() or the max-scroll clamp goes stale.
Guessing estimatedRowHeight for fixed-height VirtualList rowsSet it to the exact row height — the estimate only exists for variable rows (measured heights are cached per index); setItems() resets scroll and that cache.
Passing canvas.width/canvas.height into a layout functionThose are the DPR-scaled backing store (2× at retina). Pass window.innerWidth/scene.width — the logical size — or panels double in width.
Expecting Tabs to stay legible with many tabsTabs (>= @vectojs/[email protected]) keeps a fixed tabWidth (floor minTabWidth) and scrolls horizontally; pass closable: true + onClose for per-tab × close. Since 1.9.4 surplus bar width stays empty (never stretches past tabWidth).
Wanting no tab bar while only one tab exists (Vim showtabline=1)Tabs (>= @vectojs/[email protected]) autoHideTabBar: true — bar + hit region vanish below two tabs, content takes full height; read the live effectiveTabBarHeight getter (not tabHeight) when laying out siblings around the bar.
Drag handler reading localX deltas from the dragged handlePanelResizeHandle (>= 1.1.3) uses sceneX/sceneY — a coordinate space that does not move with the handle. Any custom drag must do the same or it lags the cursor.
Selection highlights drift after zoom (Firefox), canvas looks fineThe app owns sizing but never calls scene.resize() — it is the Range-metric recalibration hook. Bridge the container via ResizeObserver (references/cross-environment.md).
Hit/selection tests pass headless, fail on real laptopsHeadless runs DPR 1; real machines are DPR 2 — run pointer/selection tests at deviceScaleFactor: 2 too. Offset proportional to distance from origin ⇒ DPR bug.
Text renders in a different font than it was measured withWeb-font race: construct text after await document.fonts.ready, re-measure from document.fonts.onloadingdone for lazy fonts.

Scroll owners and RTL

One scroll owner per region. ScrollView, VirtualList, TreeView, and a virtualized Table (viewportHeight) each own their region's scroll. Nesting two owners, or adding your own wheel/drag handler on top of one, produces double-scrolling. All four also drag-to-scroll on touch (the content follows the finger 1:1), so don't add a touch handler either.

Sizing notes that bite:

  • VirtualList needs a sane estimatedRowHeight; a wrong estimate shows as a scrollbar that jumps as real heights are measured.
  • Table virtualizes only when you give it viewportHeight. Without it the whole grid mounts.
  • TreeView fires its toggle on pointerup and only within ~6px of the pointerdown, so a drag scrolls instead of expanding a row.

RTL is a layout concern, not just a text one. An RTL paragraph right-aligns, and selection anchors at the visual origin. For the a11y layer, set readingDirection: 'rtl' on the Scene so tab order reverses inline within each visual row — tab order follows where things are drawn, not the order they were added, so an RTL UI that skips this tabs in the wrong direction.

Verification

Check at least:

  • narrow mobile width;
  • desktop width;
  • browser zoom 125% and 150%;
  • keyboard navigation/focus order;
  • an RTL pass (readingDirection: 'rtl') if the app is ever localized;
  • role-based automation for interactive controls.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.