Skip to content

desktop: resize the conversation pane by dragging its edge - #238

Open
raymondginger2018-sudo wants to merge 1 commit into
HKUDS:mainfrom
raymondginger2018-sudo:feat/conversation-pane-splitter
Open

raymondginger2018-sudo wants to merge 1 commit into
HKUDS:mainfrom
raymondginger2018-sudo:feat/conversation-pane-splitter

Conversation

@raymondginger2018-sudo

Copy link
Copy Markdown
Contributor

Addresses the second half of #151 — the maintainer's invitation to add a draggable separator next to the width slider, which landed in 696aa654. (Close the issue if you consider it complete with this; leaving that call to you.)

What it does

A 12px handle rides the right edge of the conversation column. Dragging previews a new width live and releasing persists it to the existing conversationWidth setting, so the Appearance slider and the handle always show the same number. Keyboard resizing (Arrow / Home / End), double-click to restore the default, and role="separator" with aria-valuenow/aria-valuemin/aria-valuemax are included so the affordance is reachable without a pointer.

Design notes

  • The drag is delta-based, not absolute. conversationWidth is not a plain percentage at its maximum: toCss(100) is min(820px, 100%) — the width the column had before this setting existed — so on a window wider than 820px, 100 renders narrower than 99. An absolute pointer→percentage mapping would have to pick one of those two scales and would jump on the first pixel of movement. The handle measures the column's rendered width at pointerdown and maps rendered + 2 * deltaX, which stays continuous under either scale.
  • The drag writes 40–99, not 40–100. 100 is that legacy cap rather than "fill the workspace", so a drag writing it would shrink the column on wide windows. 100 stays reachable from the slider and from the handle's double-click reset, and desktop/README.md documents the interaction.
  • One appearance write path. The live preview goes through the appearance store (useAppearance().previewConversationWidth), which writes the single custom property the stylesheets consume. The component does not call applyAppearance itself — an earlier revision of this branch did, which re-applied theme and font work on every pointermove and left the store disagreeing with the DOM for the duration of the drag.
  • No new dependency. App.tsx stays composition-only and the i18n header's convention (zh-CN row, English default inline in the component) is respected.

Verification

In desktop/ (Node 25 locally; CI's Node 22 is unaffected by the note below):

  • npx tsc --noEmit — clean
  • npx eslint . — clean
  • npx vitest run41 files, 283 tests passed, including 2 new cases: the drag preview changes the width and nothing else in the appearance, and unmounting mid-drag restores the preview
  • npm run build (= check:version + check:tauri + check:protocol + tsc + vite build) — clean

One environment note: on Node 25 this suite needs NODE_OPTIONS=--no-experimental-webstorage, because Node 25's webstorage stub shadows jsdom's localStorage and reds every test that touches it. That is a local-only quirk, mentioned in case you hit it.

Not verified

  • No visual/manual pass in a real browser or Tauri window. Three things are reasoned from the stylesheets rather than measured: the 1080px media query (the handle is hidden where the column already fills the workspace — 248px sidebar + 12px margin + the 820px cap), the ≤4px offset a classic scrollbar introduces between the handle's anchor (.workspace) and the column's true edge (the column is centred inside .conversationScroller), and reduced-motion behaviour (inherited from the global transition-duration: 0.01ms !important in styles/tokens.css).
  • Drag feel and the screen-reader announcement of the separator were not hand-tested; jsdom implements no layout, so the tests stub the element boxes.

Review

The branch was reviewed along two axes with fresh-context reviewers. Adopted: the second appearance-write path described above, and moving the media-query threshold from 920px to 1080px (arithmetic above). Not adopted, with reasons: a second handle facing the sidebar (only the one edge was invited), and redefining the persisted value as a share of the window (that is the existing variable's meaning and wording, from the merged slider work — this PR keeps it).

Happy to trim the diff if you would rather have only the pointer behaviour and none of the keyboard/ARIA extras.

The width setting (HKUDS#151) shipped as a slider in Settings; the handle the
issue also asked for is the same preference reached from the pane itself.

- The pointer previews --conversation-width and one write lands on release,
  so a drag costs one localStorage write instead of one per pointermove.
- Arrow keys step by the slider's 5%, Home/End jump to the ends of the
  range, and a double click restores the default. The strip is a
  role="separator", so the share it manages is announced.
- Shares come from the column's rendered width plus the pointer delta,
  because 100 means the built-in 820px cap rather than "fill the
  workspace": a drag writes 40-99 and leaves the cap to the slider.
- The preview goes through useAppearance, which keeps the store the only
  writer of appearance state; applyAppearanceSetting moves one custom
  property instead of repainting the theme on every pointermove.
- Hidden below 1080px, where the workspace is already at or under the cap
  and the column spans it; the slider still resizes it there.

Refs HKUDS#151.
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