Skip to content

fix(frontend): responsive layout for PC / tablet / Android (builds on #1878) - #48

Draft
lyingbug wants to merge 16 commits into
mainfrom
cursor/responsive-multi-device-followup-41a7
Draft

fix(frontend): responsive layout for PC / tablet / Android (builds on #1878)#48
lyingbug wants to merge 16 commits into
mainfrom
cursor/responsive-multi-device-followup-41a7

Conversation

@lyingbug

@lyingbug lyingbug commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Closes Tencent#917.

This branch takes #1878 (the most complete responsive PR that still merges cleanly into main) and fixes the defects that survived it. Tencent#1878 is merged as-is in the first commit; every later commit is the follow-up work.

Why build on Tencent#1878

Eleven PRs target Tencent#917. Of those, seven merge cleanly into current main, and all of them remove the min-width: 600px on .main that caused the original Android clipping. Tencent#1878 was the broadest of the clean-merging set (chat, settings, knowledge base, dialogs, drawers, tables) and is pixel-identical to main at 1440px, so it was the best base to extend.

What this adds on top of Tencent#1878

Composer no longer has a dead zone at 768–1250px. creatChat.vue and KnowledgeBase.vue pinned .t-textarea__inner to hard-coded widths (654px / 500px / 340px / 300px) per breakpoint. Tencent#1878 only overrode those below 767px, so between 768px and 1250px the typing area stopped up to 438px short of the input box border. The hard-coded widths and the matching translateX(...) offsets are removed, and the composer sizes itself from its container.

Composer gets narrow-screen gutters. Tencent#1878 left the input box flush against both screen edges on phones, clipping its rounded border and shadow. The component now applies its own padding-inline at the tablet and phone breakpoints.

Control bar stays on one row on phones. With gutters the wrapped control bar spilled onto a second row at 360–390px, growing the composer and pushing the send action out of thumb reach. The optional controls become a horizontally scrollable strip and the send action no longer shrinks.

Settings rows stack on phones. The setting pages pin the control column to min-width: 280px and write an inline width: 280px on the select. At 360px that crushed the label column to 48px, rendering 语言 / 主题模式 / 界面字体 one character per line. Rows now stack label-above-control, releasing both the column minimum and the inline width.

App-wide img { user-drag: none } restored. Tencent#1878 changed platform/index.vue from a global <style> block to scoped, which silently limited that rule to this one component's template. It moves back into an unscoped block.

Touch-device session actions actually apply. Tencent#1878 added .aside_box :deep(.menu-more-wrap) to theme.css, but :deep() is not valid CSS outside a Vue SFC, so the browser discarded the rule and the row action button stayed invisible on touch devices. The rule moves into menu.vue, where it can outrank the scoped opacity: 0 default.

Breakpoints resolve at module load and prefer matchMedia. platform/index.vue and the UI store read the breakpoint refs before mount, so deferring the first evaluation to App.vue's onMounted made phones render the desktop sidebar for one frame. Reading matchMedia instead of window.innerWidth also keeps the JS form factor in step with the CSS near a boundary, where a classic scrollbar makes the two disagree by up to 15px. The tablet sidebar watcher becomes immediate to match — otherwise opening the app straight into a tablet width never triggered the collapse.

Also removes four unused @/api/chat imports that Tencent#1878 reintroduced in menu.vue, and moves its defineProps / defineEmits out of the middle of the import list.

Tests. Tencent#1878 shipped none. This adds useBreakpoint.test.ts (breakpoint classification, boundary values, matchMedia-vs-innerWidth, SSR fallback) and responsiveChatComposer.test.mjs (layout contracts that guard against the hard-coded widths, the global img rule, the one-row control bar, the stacked setting rows, and the immediate tablet watcher).

Verification

npm test (307 passing), npm run type-check and npm run build all pass.

Measured with Playwright against the production build at 360 / 390 / 640 / 700 / 768 / 820 / 900 / 1000 / 1044 / 1100 / 1250 / 1440px on the new-chat, existing-chat, knowledge-base list, agent list, organization and settings routes. document.scrollWidth equals clientWidth at every width, no element is clipped past the right edge without being reachable, and the composer has zero dead space at every width. The 1440px new-chat render is pixel-identical to main.

Before / after on a 390px phone — main clips the content column, Tencent#1878 fixes the overflow but the input box is flush against both edges, this branch adds gutters and keeps the control row intact:

New chat at 390px on main, PR #1878 and this branch

The composer dead zone at 1000px. Blue outlines the input box, red outlines the actual typing area:

Composer dead zone at 1000px on main, PR #1878 and this branch

Settings at 360px — main is a cramped two-column modal, Tencent#1878 makes it full screen but the label column collapses to one character per line, this branch stacks each row:

Settings modal at 360px on main, PR #1878 and this branch

Walkthrough from 1440px down to 360px, including the drawer sidebar and the full-screen settings modal, then back to desktop:

responsive_walkthrough_desktop_tablet_phone.mp4

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

hiasky and others added 16 commits July 1, 2026 22:48
Implement responsive layout adapting the frontend for PC (>=1024px),
tablet (768-1023px), and Android phone (<768px) viewports.

### New Files
- useBreakpoint.ts: reactive breakpoint detection composable using
  matchMedia with shared refs for isMobile/isTablet/isDesktop
- responsive.less: Less mixins (.mobile, .tablet, .desktop, .touch)
  auto-injected to all Vue SFCs via vite config

### Core Layout (platform/index.vue)
- Remove hardcoded min-width: 600px
- Mobile: top nav bar with hamburger menu, sidebar rendered inside
  TDesign Drawer (left-slide overlay)
- Tablet: sidebar auto-collapses to 60px, user can drag to expand
- Route change auto-closes mobile drawer

### Sidebar (menu.vue)
- New variant prop ("sidebar"|"drawer") for dual-mode rendering
- Drawer mode: full-width, no collapse toggle, touch-friendly 44px targets
- emit("navigate") for drawer auto-close

### Chat View (chat/index.vue)
- Remove min-width: 400px
- Mobile: full-width messages, reduced padding, responsive input
- Responsive suggested questions grid

### Settings & Modals
- Settings.vue, AgentEditorModal, IntegrationsModal,
  KnowledgeBaseEditorModal, OrganizationSettingsModal,
  OrganizationEditorModal: mobile sidebar becomes horizontal
  scrollable pill tab bar, modal goes fullscreen
- SettingDrawer.vue: mobile full-width override for minWidth constraint
- ShareKnowledgeBaseDialog, MyInvitationsDialog: t-dialog full-width
  on mobile via scoped :deep()

### List Pages
- KnowledgeBaseList, AgentList, OrganizationList:
  mobile/tablet header size and padding adjustments

### Login Page
- Added <=380px super-small screen support
- Touch device button min-height 44px

### Global Styles
- theme.css: responsive CSS variables, touch hover rules,
  mobile font-size 15px, min touch target 44px
- suggested-questions.less: mobile single-column full-width cards
…d detail drawers

- doc-content.vue: main/trace drawers fullscreen on mobile, metadata
  rows stacked vertically, resize handles hidden, tablet max 85vw
- DocumentListView.vue: 8-column grid collapsed to 3 columns
  (checkbox+name+status) on mobile, source column hidden on tablet
- KnowledgeBaseList.vue: shared detail drawer 100vw on mobile,
  420px on tablet
- KnowledgeBase.vue: reduced container padding/margins for mobile
  and tablet, filter fields full-width stacked on mobile
- WikiBrowser.vue: sidebar stacked above reader on mobile with
  45vh max-height, all wiki drawers (graph/issues/fix) 100vw
- FAQEntryManager.vue: tag panel becomes top horizontal scroll
  bar, editor/search drawers fullscreen, import/tag modals
  fullscreen
…DocumentListView

- Merge conflict resolved in DocumentListView.vue
- Retained mobile and tablet responsive design CSS
- Added missing responsive grid layouts for different screen sizes
Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
…1878

- restore the app-wide img user-drag rule that the newly scoped platform
  style block silently dropped
- move the touch-device session action rule out of theme.css, where the
  :deep() pseudo made it an invalid selector, into menu.vue where it can
  actually outrank the scoped opacity: 0 default
- drop the legacy per-breakpoint translateX offsets and pinned
  t-textarea__inner widths, which left a dead gap inside the composer
  between 768px and 1044px
- give the composer narrow-screen gutters so its rounded border is not
  clipped by the screen edge
- evaluate breakpoints at module load and prefer matchMedia so the JS
  form factor matches the rendered layout from the first frame
- add regression coverage for the breakpoint logic and the composer
  layout contract

Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
…ollapse

The composer gutters made the wrapped control bar spill onto a second row
on 360-390px screens. Compact the optional controls into a horizontally
scrollable strip and pin the send action so it stays in thumb reach.

Also make the tablet sidebar watcher immediate: breakpoints are now
resolved at module load, so a deferred watcher never fired when the app
opened straight into a tablet width and the sidebar stayed expanded.

Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
The setting pages pin the control column to min-width: 280px and write an
inline width on the select, so at 360px the label column collapsed to
48px and rendered one character per line. Stack the row on phones and
release both the column minimum and the inline width.

Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
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.

[Feature]: 请尝试适配pc,平板和安卓的显示

2 participants