← Back to PRs

#9716: feat(ui): add GitHub-style floating copy button to code blocks

by BigUncle open 2026-02-05 16:02 View on GitHub →
app: web-ui stale size: M
## PR Description ### Summary Adds a floating copy button to fenced code blocks in the web chat interface, mimicking GitHub's design. The button allows users to easily copy code snippets to the clipboard. ### Changes - **`ui/src/ui/markdown.ts`**: - Custom `marked` renderer to wrap code blocks in `.code-block-wrapper` container. - Add a copy button with copy/check icons to the wrapper. - Implemented `initCodeBlockCopy()` function using event delegation for clipboard operations. - Visual feedback for copied/error states. - Removed explicit code block header for a cleaner, floating-button design. - **`ui/src/styles/chat/text.css`**: - Styles for `.code-block-wrapper` and absolute positioning for `.code-block-copy-btn`. - Floating button appears on hover (top-right corner) with a semi-transparent backdrop. - Always visible on touch devices. - Adapted styles for light/dark themes. - Added "Copied" (green) and "Error" (red) visual states. - **`ui/src/ui/app-lifecycle.ts`**: - Initialize code block copy functionality on app first update. - **`ui/src/ui/markdown.test.ts`**: - Updated tests to match the new code block structure (wrapper + floating button). ### Screenshots | Before | After | |--------|-------| | Code blocks have no copy button | Code blocks have a floating copy button in the top-right corner that appears on hover (GitHub style) | <img width="1056" height="132" alt="image" src="https://github.com/user-attachments/assets/c4bd206e-11ab-458f-9073-8f67fcbcede4" /> ### Testing - [x] Verified copy functionality works in Chrome/Firefox. - [x] Verified light/dark theme styles. - [x] Verified floating behavior (hover/touch). ## Files changed ``` ui/src/ui/markdown.ts ui/src/ui/markdown.test.ts ui/src/ui/app-lifecycle.ts ui/src/styles/chat/text.css ``` <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> - Changes markdown rendering to wrap fenced code blocks in a `.code-block-wrapper` and inject a floating “copy to clipboard” button (GitHub-style). - Adds event-delegated click handler (`initCodeBlockCopy`) to copy `<pre><code>` text to the clipboard and toggle copied/error UI states. - Updates chat text CSS to position/style the floating button and adjust code block spacing/theme rules. - Wires initialization into the UI lifecycle and updates markdown unit tests for the new structure. <h3>Confidence Score: 3/5</h3> - Reasonably safe, but needs fixes to avoid runtime failures and event handler duplication in some environments. - Core UI change is localized and tests were updated, but the new global click listener has no teardown (can duplicate under re-mount/HMR) and clipboard usage is not guarded for unsupported/denied contexts, which can throw and break the handler path. - ui/src/ui/markdown.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs