Skip to content

feat(viewer): fill the host container, stack the sidebar on narrow hosts, and leave keys to focused controls - #97

Merged
joaner merged 6 commits into
mainfrom
feat/embed-fill-host
Oct 17, 2026
Merged

joaner merged 6 commits into
mainfrom
feat/embed-fill-host

Conversation

@joaner

@joaner joaner commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

What

  • Fill the host. .lerobot-root now fills its container. The viewer measures its own width with a @container/viewer query, not the window:
    • Below 640 px of container width, the episode sidebar moves under the player and stays resizable. It is moved, not remounted.
    • At the same width the playback bar wraps: progress gets its own row, the transport is centred, and FPS and version are hidden.
  • Keep the chosen sidebar width. A narrow host caps the rendered width without overwriting the user's choice, so the chosen width returns when the host widens again.
    • The resize handle is a focusable ARIA window splitter. It has aria-orientation, aria-valuenow, aria-valuemin and aria-valuemax, and arrow keys resize it.
  • Navbar on phones. The dataset title stays in the layout flow, truncates with a full-name tooltip, and never overlaps the controls. Below sm, the playback-bar toggle and GitHub link are hidden.
  • Shortcuts leave keys to focused controls. Text fields, composite widgets (tabs, sliders, radios, checkboxes, menus, listboxes, resize handles) and dialogs keep Space and the arrow keys.
    • A focused button or link keeps Space for its own activation: one press is one click, never a click plus play/pause. The arrow keys still step playback there.
    • With focus on the page or an episode row, Space plays and pauses as before.
    • Element checks are realm-safe for hosts that render into another window.
  • Dev tooling. Bumps source-map-js to 1.2.2 (GHSA-68fv-2mgg-jv7q). This is dev-only, so it has no changeset.
  • Changesets. embed-fill-host (minor), shortcuts-own-keys (patch) and navbar-phone-title (patch).
  • Bundle budgets. webInitialJs gzip rises to 745,000 bytes and libEntry raw to 405,000 bytes (+5 KB each). The layout, splitter and shortcut code bring both level with their previous ceilings.

The version bump and CHANGELOG are not in this PR. Following the repo's changesets flow, they belong to the separate release PR.

Why

When the viewer was embedded in a fixed-size or resizable pane:

  • it sized itself to its content instead of the host;
  • the sidebar squeezed the player on narrow panes;
  • the navbar title overlapped the controls on phones;
  • Space and the arrow keys were taken globally, so they fought with the host's tabs, sliders, search fields and buttons.

Tests

New and updated tests:

  • tests/browser/embed-layout.browser.spec.tsx:
    • fills the host;
    • split at 900 px and stacked below 640 px, in DOM and focus order;
    • moves the sidebar without remounting it;
    • the chosen width (400 px) survives a narrower host (capped at 380 px) and the stacked layout;
    • separator ARIA values;
    • keyboard resizing of the stacked sidebar.
  • tests/browser/space-on-controls.browser.spec.tsx, on the real viewer:
    • Space on a focused "Next frame" button clicks it exactly once and does not toggle playback;
    • Space on a focused Play/pause button toggles once per press;
    • with no control focused, Space toggles playback.
  • tests/browser/shortcut-target.browser.spec.ts: role and element ownership, including Space on button, link, role="button" and summary, and cross-realm elements.
  • tests/browser/navbar-title.browser.spec.tsx: no overlap at 390 px and 1280 px.
  • tests/resizable-sidebar.spec.ts and tests/embed-root-sizing.spec.ts (the .lerobot-root rule in the built CSS).

Checks run locally: format:check, check:docs-i18n, lint, typecheck, api:report:check, test:coverage, build:lib, check:package, build, check:bundle-size, test:browser.

Manual pass in Chrome on the standalone app and on an embedded build:

  • 1920 light en, 1440 dark zh, 390 light zh, 390 dark en;
  • opening a dataset, playback, the keyboard, sidebar resizing and the navbar.

Note for consumers

The @zip.js/zip.js range is unchanged (^2.8.51), so fresh installs currently resolve to 2.24.0. Some npm mirrors may not carry that release yet. Pinning 2.23.0 through overrides (npm) or pnpm.overrides works in the meantime.

@joaner
joaner merged commit c375995 into main Oct 17, 2026
7 checks passed
@joaner joaner mentioned this pull request Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant