Skip to content

fix(web): improve code block copy button for mobile and add position setting#2092

Open
roni-estein wants to merge 6 commits intopingdotgg:mainfrom
roni-estein:fix/mobile-copy-button
Open

fix(web): improve code block copy button for mobile and add position setting#2092
roni-estein wants to merge 6 commits intopingdotgg:mainfrom
roni-estein:fix/mobile-copy-button

Conversation

@roni-estein
Copy link
Copy Markdown

@roni-estein roni-estein commented Apr 16, 2026

What Changed

Three focused improvements to the code block copy button, primarily for mobile and remote (HTTP) usage:

  1. Configurable position (top or bottom) — new client setting under Settings → General
  2. Visible on touch devices@media (hover: none) rule shows the button without requiring hover
  3. Clipboard fallback for non-secure contextsdocument.execCommand("copy") fallback when navigator.clipboard is unavailable (HTTP over Tailscale, etc.)

Why

When using T3 Code remotely on a phone (via t3 serve over Tailscale), the code block copy button has two problems:

  • Position: Generated code blocks and explanations are often long. On mobile, the copy button sits at the top-right corner, requiring the user to scroll back up past the entire block to reach it. A "bottom" option places it at the end where you naturally finish reading.

  • Visibility: The button relies on :hover to appear (opacity: 0opacity: 1). Touch devices don't have hover, so the button never becomes visible or interactive — it renders as an inert SVG icon with pointer-events: none.

  • Clipboard API: navigator.clipboard.writeText() requires a secure context (HTTPS). Remote T3 Code sessions served over plain HTTP (common with Tailscale) silently fail because the API isn't available. The fallback uses the legacy execCommand("copy") path.

Why not existing PRs

Files changed

File Change
packages/contracts/src/settings.ts Add copyButtonPosition to ClientSettingsSchema
apps/web/src/components/ChatMarkdown.tsx Read setting, apply position via inline style, add clipboard fallback
apps/web/src/components/settings/SettingsPanels.tsx Add position dropdown to General settings, wire up restore defaults
apps/web/src/index.css Add @media (hover: none) rule for touch devices
apps/web/src/components/ChatMarkdown.logic.test.ts Unit tests for position style resolution and clipboard detection
apps/desktop/src/clientPersistence.test.ts Add new field to test fixture
apps/web/src/localApi.test.ts Add new field to test fixtures

UI Changes

Settings → General — new "Copy button position" dropdown:

Default is "Top" (preserves existing behavior). "Bottom" places the button at the bottom-right corner of the code block.

Touch devices — copy button always visible:

On devices without hover (phones, tablets), the button renders at 70% opacity and goes to full opacity on tap, instead of being permanently hidden.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after context for UI changes
  • Tests pass (bun run typecheck, bun run test — 865/865 passing)

Note

Medium Risk
Touches user interaction and clipboard behavior (including a legacy execCommand path) and adds a new persisted client setting, which could affect cross-platform copying and settings migration if edge cases exist.

Overview
Improves the chat Markdown code-block copy button for mobile and non-HTTPS deployments.

Adds a new client setting copyButtonPosition (top/bottom) to the shared settings contracts and exposes it in the General settings panel (including restore-defaults dirty-state tracking), then applies it via inline positioning in MarkdownCodeBlock.

Updates copy behavior to use navigator.clipboard.writeText when available and fall back to a hidden textarea + document.execCommand("copy") when Clipboard API isn’t present, and adjusts CSS to keep the copy button visible on touch devices (@media (hover: none)). Tests/fixtures are updated and a small logic test file is added to cover the positioning/clipboard guards.

Reviewed by Cursor Bugbot for commit 8c911b5. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add copy button position setting and mobile visibility fix for code blocks

  • Adds a copyButtonPosition setting (top/bottom) to ClientSettingsSchema with a default of top, and exposes a UI control in the General settings panel to configure it.
  • Applies the position as an inline style on the copy button in ChatMarkdown.tsx, overriding the CSS default.
  • Adds a execCommand('copy') textarea fallback in the copy handler for environments where navigator.clipboard is unavailable (common on mobile).
  • On touch devices, the copy button is always visible at 70% opacity via a (hover: none) media query in index.css instead of appearing only on hover.

Macroscope summarized 8c911b5.

…setting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b73d61d1-d031-4480-9284-c2089c340b4f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ 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.

@github-actions github-actions bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Apr 16, 2026
macroscopeapp[bot]
macroscopeapp bot previously approved these changes Apr 16, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 16, 2026

Approvability

Verdict: Approved

Low-risk UI enhancement adding a configurable copy button position setting for mobile users and a clipboard fallback for non-HTTPS contexts. Changes are self-contained to the code block component with tests included, no sensitive areas touched.

You can customize Macroscope's approvability policy. Learn more.

Incorporate upstream's sidebarProjectGroupingMode and refactored test
fixtures alongside copyButtonPosition field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@macroscopeapp macroscopeapp bot dismissed their stale review April 16, 2026 23:53

Dismissing prior approval to re-evaluate 07d8ca7

Comment thread apps/web/src/components/ChatMarkdown.tsx Outdated
roni-estein and others added 3 commits April 16, 2026 18:58
The document.execCommand("copy") fallback was calling onSuccess()
unconditionally. Now gates the success indicator on the boolean return
value so users aren't shown "Copied" when the browser blocked the
operation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b94c26c. Configure here.

Comment thread apps/web/src/components/ChatMarkdown.tsx
Move removeChild into a finally block so the hidden textarea is always
cleaned up, even if select() or execCommand() throws.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roni-estein added a commit to roni-estein/t3code that referenced this pull request Apr 17, 2026
roni-estein added a commit to roni-estein/t3code that referenced this pull request Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant