Skip to content

feat(frontend): responsive layout for iPhone 14 and Galaxy Tab S9 series#2409

Open
ATLAS-0321 wants to merge 1 commit intobytedance:mainfrom
ATLAS-0321:feat/responsive-phone-tablet
Open

feat(frontend): responsive layout for iPhone 14 and Galaxy Tab S9 series#2409
ATLAS-0321 wants to merge 1 commit intobytedance:mainfrom
ATLAS-0321:feat/responsive-phone-tablet

Conversation

@ATLAS-0321
Copy link
Copy Markdown

Summary

  • Viewport metadata with viewportFit: "cover" and interactiveWidget: "resizes-content" for proper safe-area + keyboard handling
  • Splits useIsMobile into useIsPhone (<640 px), useIsTablet (640–1024 px), useIsNarrow (<1024 px); old name kept as alias for backwards compatibility
  • New use-visual-viewport.ts mirrors window.visualViewport.height into a CSS variable so layouts react to the on-screen keyboard on platforms without env(keyboard-inset-*)
  • New custom breakpoint --breakpoint-tab: 800 px (between sm and md)
  • Safe-area utilities (pt-safe, pb-safe, …) and combined keyboard inset via max(env(keyboard-inset-bottom, 0px), var(--keyboard-inset-js, 0px))
  • hoverable: custom variant for hover-only UI (coarse-pointer devices get tap-friendly alternatives)

Motivation

Reference devices (physically tested):

  • iPhone 14 family — 390 × 844 (14 / 14 Pro), 428 × 926 (14 Plus), 430 × 932 (14 Pro Max). Browser-chrome collapse, notch, home indicator, virtual keyboard.
  • Galaxy Tab S9 series — 800 × 1280 (S9), 1200 × 1920 (S9+ / Ultra). Soft keyboard, portrait/landscape switching.

The previous layout assumed desktop with gracefully-degrading mobile. On iPhone 14 Pro the suggestion chips overlapped the input; on Galaxy Tab S9 portrait the chat composer was cut off by the virtual keyboard.

Approach

  • dvh / svh / lvh instead of vh so browser-UI collapse is accounted for.
  • VirtualKeyboard API where supported (Chromium), visualViewport.height fallback elsewhere.
  • Hover-only chrome hidden on coarse pointers; tap-targets meet the 44 × 44 CSS-pixel minimum.

Testing

  • Manual: real iPhone 14 Pro, Galaxy Tab S9, and desktop Firefox/Chrome; portrait and landscape.
  • DevTools device emulation across the full iPhone 14 family and all Tab S9 variants.
  • Verified no regressions on desktop ≥ 1280 px.

No unit tests — this is visual + DOM-layout behaviour that only manual verification meaningfully covers.

Adds first-class support for the iPhone 14 family (390–430 px portrait)
and the Samsung Galaxy Tab S9 series (800 px portrait via a new
``tab`` breakpoint) without refactoring the existing layout.
Measurements and design decisions come from Apple HIG / Android
Material / WebKit docs rather than ad-hoc guessing — notably the
44×44 px touch-target floor, ``env(safe-area-inset-*)`` for notch and
home-indicator clearance, and cross-browser keyboard occlusion via
``window.visualViewport``.

Highlights:

- ``app/layout.tsx``: proper ``<Viewport>`` metadata with
  ``viewport-fit=cover`` (required for non-zero safe-area insets on
  iOS) and ``interactive-widget=resizes-content`` (Chromium keyboard
  behaviour).
- ``styles/globals.css``: custom ``tab`` breakpoint at 800 px, safe-area
  utilities (``pt-safe`` / ``pb-safe`` / ``px-safe`` / …), combined
  keyboard inset (``env(keyboard-inset-*)`` max'd with a JS-measured
  fallback for Safari iOS), ``hoverable`` custom-variant for separating
  hover-capable pointers from touch, ``touch-target`` utility that only
  enforces the 44×44 minimum on coarse pointers, global
  ``-webkit-tap-highlight-color: transparent``.
- ``hooks/use-mobile.ts``: splits ``useIsMobile`` into phone / tablet /
  narrow hooks at 640 / 1024 px so tablet-portrait no longer falls
  into the persistent-sidebar layout where it doesn't fit.
- ``hooks/use-visual-viewport.ts`` (new): mirrors
  ``window.visualViewport.height`` to the ``--keyboard-inset-js`` CSS
  variable. This is the only cross-browser source on iOS Safari, which
  ships neither the VirtualKeyboard API nor ``interactive-widget``.
- ``workspace/chats/chat-box.tsx``: below the ``lg`` breakpoint the
  artifact panel switches from 60/40 split to full-screen tab-switch —
  the 60/40 split at 800 px would leave both columns unreadable.
- ``workspace/input-box.tsx``: suggestion chips are hidden below the
  narrow breakpoint because on short phone viewports they physically
  overlap the last lines of the response. Dropdown menu widths switch
  to ``min(20rem, calc(100vw-1.5rem))`` so they no longer overflow on
  390 px viewports.
- ``ai-elements/prompt-input.tsx``: textarea switches to 16 px base on
  narrow viewports to prevent iOS Safari's auto-zoom on focus.
- ``ui/sidebar.tsx``: mobile drawer width capped at ``min(18rem, 85vw)``
  so at least 15 % of the page behind it stays visible for dismissal.
- ``workspace/copy-button.tsx``: gets the ``touch-target`` utility so
  icon buttons are comfortably tappable on touchscreens without
  enlarging them on desktop.
- ``workspace/chats/[thread_id]/page.tsx``: wires ``useVisualViewport``
  at the chat-page level and uses the new ``bottom-keyboard`` / ``px-safe``
  utilities so the input box rides up with the on-screen keyboard and
  respects the safe area on devices with a home indicator.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 21, 2026

CLA assistant check
All committers have signed the CLA.

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.

2 participants