#9716: feat(ui): add GitHub-style floating copy button to code blocks
app: web-ui
stale
size: M
Cluster:
Web UI Enhancements and Fixes
## 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
#19259: fix(ui): add legacy fallback for copy-as-markdown on non-secure con...
by assistent-dries-robuxio · 2026-02-17
78.9%
#12719: feat(ui): add copy button to logs page
by billgetman · 2026-02-09
78.6%
#19555: feat(android): collapsible thinking/code blocks in chat
by gregmousseau · 2026-02-17
74.7%
#7528: feat: Adds slash command suggestions to chat
by JohnnyD1776 · 2026-02-02
74.0%
#6521: fix: addressed style issue for chat compose and thread on mobile
by spencer-rafada · 2026-02-01
73.7%
#13548: feat(control-ui): Add quote reply and send message to session features
by Annaxiebot · 2026-02-10
73.5%
#8342: Fix debug interface CSS layout issues
by Klopib · 2026-02-03
73.1%
#15204: fix(ui): preserve angle-bracketed text in chat
by bufordtjustice2918 · 2026-02-13
72.5%
#20405: feat(ui): KaTeX math rendering, collapsible tool cards, image attac...
by ayaanngandhi · 2026-02-18
72.3%
#16733: fix(ui): avoid injected newlines when tool output is hidden
by jp117 · 2026-02-15
72.2%