Skip to content

feat(a2ui-playground): preview QR pane — inline on desktop, drawer on mobile, draggable divider#2791

Merged
Huxpro merged 3 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-preview-qr-inline-desktop
Jun 3, 2026
Merged

feat(a2ui-playground): preview QR pane — inline on desktop, drawer on mobile, draggable divider#2791
Huxpro merged 3 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-preview-qr-inline-desktop

Conversation

@Huxpro
Copy link
Copy Markdown
Collaborator

@Huxpro Huxpro commented Jun 3, 2026

Summary

The preview-panel container query @container preview-panel (max-width: 660px) always matched — the panel is fixed at width: min(520px, 100%), so on desktop the inline COMPONENTS chips + Web/Native QR cards were hidden and the Vaul drawer behind the Smartphone icon was the only channel.

  • Swap the container-width guard for a viewport-level useMediaQuery('(max-width: 720px)') hook (matches the app's existing mobile breakpoint — same threshold as MobileTabBar, .brand hide, etc.).
  • Conditionally mount either the inline .previewPanelExtras (desktop) or the previewInfoBtn + Drawer.Root (mobile). Both code paths still call the same renderExtras() closure, but only one is mounted at a time — so QrCode's async toDataURL runs once per card and the live-component tag-appear animation doesn't double up.
  • Add a staggered slide-up + fade entrance on the inline children (cubic-bezier(0.22, 1, 0.36, 1), 360ms, 70ms stagger, prefers-reduced-motion: reduce opt-out) so the extras glide into the panel when the preview becomes ready, instead of popping in.
Before After
Desktop drawer-only (Smartphone icon → bottom sheet) Desktop inline (chips + Web/Native QR cards under the phone preview)
Mobile drawer Mobile drawer (unchanged)

Test plan

  • pnpm run build succeeds.
  • Desktop @ 1440×900: COMPONENTS chips + Web Preview + Native Preview QR cards render inline in the right panel. Smartphone button is absent.
  • Mobile @ 390×844 (Preview tab): inline section is hidden, Smartphone button appears in the header, tap opens the Vaul bottom sheet with the same content.
  • Snapshot diff confirms only one extras instance is mounted at a time on each breakpoint.
  • Smoke-check on a real phone via the QR (web + LynxExplorer) — not run; the unrelated build:lynx typia ESM resolution failure on this workspace prevented an end-to-end preview, but the React shell + UI changes are exercised by rsbuild dev.

Summary by CodeRabbit

  • New Features

    • Preview panel adapts to mobile/desktop with viewport-aware controls (shows "Open on phone" only on compact view).
    • Desktop extras pane supports draggable vertical resizing with persisted height.
  • Refactor

    • Extras content reused across inline panel and mobile drawer to avoid duplicate mounting.
  • Style

    • Extras panel layout and resizer styling updated; staggered entrance animations added with reduced-motion support.

…bile

The container query `@container preview-panel (max-width: 660px)` always
matched — the panel is fixed at `width: min(520px, 100%)`, so even on a
wide desktop the inline COMPONENTS chips + Web/Native QR cards were
hidden and the Vaul drawer behind a Smartphone icon was the only channel.

Replace the container-width guard with a viewport-level `useMediaQuery`
hook at the existing 720px mobile breakpoint, and conditionally mount
either the inline `.previewPanelExtras` (desktop) or the
`previewInfoBtn` + `Drawer.Root` (mobile). Both code paths still call
the same `renderExtras()` closure, but only one is mounted at a time —
so `QrCode`'s async `toDataURL` runs once per card and the live-component
`tag-appear` animation doesn't fire twice.

Add a staggered slide-up + fade entrance on the inline children
(`cubic-bezier(0.22, 1, 0.36, 1)`, 360ms, 70ms stagger), with a
`prefers-reduced-motion` opt-out, so the extras section glides into the
panel when the preview becomes ready instead of popping in.
Copilot AI review requested due to automatic review settings June 3, 2026 16:04
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 3, 2026

⚠️ No Changeset found

Latest commit: 7639a79

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a client-side useMediaQuery hook and updates PreviewPanel to conditionally mount extras: desktop shows an inline resizable extras pane with persisted height; compact viewports render the same extras inside the mobile Drawer. Styles change to a flex extras panel with staggered entry animations and a resizer handle.

Changes

Compact viewport extras and animations

Layer / File(s) Summary
Media query hook infrastructure
packages/genui/a2ui-playground/src/hooks/useMediaQuery.ts
Introduces useMediaQuery(query: string): boolean, a client-side React hook that initializes from window.matchMedia(query).matches, subscribes to change events, and cleans up on unmount.
PreviewPanel responsive imports & gating
packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
Switches to typed import type forms, imports useMediaQuery('(max-width: 720px)'), computes isCompactViewport, tightens "Open on phone" button to hasExtras && isCompactViewport, and reuses precomputed liveComponentsBlock/qrSectionBlock across inline and Drawer mount paths.
Extras sizing, pointer resize, and persistence
packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
Adds sizing constants, clamp helper, localStorage-backed extrasHeight, isResizingExtras flag, and a pointer-driven vertical resize handler that clamps height, toggles document.body.dataset.panelResize, updates extrasHeight, and persists final height.
Extras panel styling and animations
packages/genui/a2ui-playground/src/styles.css
Replaces container-query hiding with a flex-column .previewPanelExtras panel, adds .previewPanelExtrasResizer styles, staggered preview-extras-enter animations for children, and a prefers-reduced-motion override to disable animations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • lynx-family/lynx-stack#2731: Refactors PreviewPanel extras/QR rendering used by both inline preview and mobile Drawer; directly related to extras composition changes.
  • lynx-family/lynx-stack#2766: Modifies PreviewPanel extras and QR rendering logic that intersects with the responsive gating and blocks refactor here.

Suggested reviewers

  • HuJean

Poem

🐰 I nibble queries, listen for the view,
Gate extras to desk or slide down for you.
A resizer paw keeps heights just right,
Animations hop in soft delight,
Motion-muted for calm, responsive night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The PR title accurately describes the main feature: responsive preview QR pane with inline desktop display, mobile drawer, and draggable divider—directly matching the core changes across all three modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the preview “extras” (components chips + Web/Native QR cards) rendering logic in a2ui-playground so desktop shows the extras inline in the right preview panel, while mobile continues to use the Vaul drawer. It replaces a container-query-based split (which always matched due to the panel’s fixed width) with a viewport breakpoint via a new useMediaQuery hook, and adds a subtle entrance animation for inline extras.

Changes:

  • Replace the (always-matching) preview panel container query with a viewport breakpoint ((max-width: 720px)) via a new useMediaQuery hook.
  • Conditionally mount either inline extras (desktop) or the drawer trigger + drawer content (mobile) to avoid duplicate work/animations.
  • Add a slide-up + fade-in animation for inline extras with a prefers-reduced-motion opt-out.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/genui/a2ui-playground/src/styles.css Removes the preview-panel container-query setup and adds mount-time entrance animation for inline extras.
packages/genui/a2ui-playground/src/hooks/useMediaQuery.ts Introduces a matchMedia-based hook for viewport breakpoint detection.
packages/genui/a2ui-playground/src/components/PreviewPanel.tsx Switches extras rendering logic to viewport-based branching; mounts inline vs drawer content exclusively per breakpoint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
Comment thread packages/genui/a2ui-playground/src/hooks/useMediaQuery.ts
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

…pane

Build on the inline-desktop fix by letting the user resize the split
between the phone preview and the COMPONENTS + QR cards below it.

The handle borrows the visual language of the existing chat/preview
`.panelResizeHandle` (8px hit area, top+bottom 1px borders, centered
2px grip dot that widens and brightens on hover/active, `ns-resize`
cursor, global `body[data-panel-resize="vertical"]` while dragging).

State lives in `PreviewPanel` and is hydrated from / persisted to
`localStorage` (`a2ui-playground:preview-extras-height`, default 280px).
The pointerdown handler captures the panel's current rect and the
extras pane's `scrollHeight`, then clamps drag output to
`[80, min(panelHeight - 200, contentNatural + 12)]` — the content cap
prevents the user from dragging into wasted empty space below the QR
cards when content is short.

`.previewPanelExtras` moves from `display: contents` to a real flex
column with `overflow-y: auto` and an inline-styled `height`, and the
legacy `border-top` on its first child is dropped so the resizer's
own borders are the only divider line. The mobile drawer path stays
unchanged — no resizer inside the bottom sheet.
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jun 3, 2026

Merging this PR will not alter performance

✅ 87 untouched benchmarks
⏩ 26 skipped benchmarks1


Comparing Huxpro:Huxpro/a2ui-preview-qr-inline-desktop (7639a79) with main (a22943e)

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/genui/a2ui-playground/src/components/PreviewPanel.tsx`:
- Around line 375-433: The handler handleExtrasResizeStart sets
document.body.dataset.panelResize = 'vertical' and registers window pointer
listeners but only clears them in handleEnd; add a cleanup effect (useEffect)
that on unmount clears document.body.dataset.panelResize and removes any
lingering window listeners (pointermove/pointerup/pointercancel) tied to the
same handlers so the global marker/cursors and iframe pointer blocking can't get
stuck if the component unmounts or the extras branch is removed; locate
handleExtrasResizeStart and the inner handleMove/handleEnd closures and ensure
the effect references stable handler refs or re-registers safe no-op removers to
detach the exact listeners and delete the dataset key on cleanup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 523848db-90c1-4aee-99de-5b86f6f7077a

📥 Commits

Reviewing files that changed from the base of the PR and between b31d728 and 4994ef3.

📒 Files selected for processing (2)
  • packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
  • packages/genui/a2ui-playground/src/styles.css

Comment thread packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
@Huxpro Huxpro changed the title fix(a2ui-playground): show preview QR inline on desktop, drawer on mobile feat(a2ui-playground): preview QR pane — inline on desktop, drawer on mobile, draggable divider Jun 3, 2026
@Huxpro Huxpro enabled auto-merge (squash) June 3, 2026 18:47
@Huxpro Huxpro disabled auto-merge June 3, 2026 22:25
@Huxpro Huxpro merged commit 5365ab3 into lynx-family:main Jun 3, 2026
41 of 43 checks passed
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.

3 participants