diff --git a/apps/desktop/src/app/chat/composer/attachments.test.tsx b/apps/desktop/src/app/chat/composer/attachments.test.tsx index 7377691f0f..ab491a00a5 100644 --- a/apps/desktop/src/app/chat/composer/attachments.test.tsx +++ b/apps/desktop/src/app/chat/composer/attachments.test.tsx @@ -236,6 +236,18 @@ describe('AttachmentList', () => { ) }) + it('shows the remove control at rest and does not hide it behind hover', async () => { + const onRemove = vi.fn() + + await renderWithI18n() + + const remove = screen.getByRole('button', { name: 'Remove doc.pdf' }) + + expect(remove.className.split(/\s+/)).not.toContain('opacity-0') + fireEvent.click(remove) + expect(onRemove).toHaveBeenCalledWith('a') + }) + it('still routes a non-image attachment to the preview rail', async () => { $previewTabs.set([]) diff --git a/apps/desktop/src/app/chat/composer/attachments.tsx b/apps/desktop/src/app/chat/composer/attachments.tsx index b87e69068f..39216e0372 100644 --- a/apps/desktop/src/app/chat/composer/attachments.tsx +++ b/apps/desktop/src/app/chat/composer/attachments.tsx @@ -149,7 +149,7 @@ function AttachmentPill({ attachment, onRemove }: { attachment: ComposerAttachme return ( <> -
+
)}
diff --git a/apps/desktop/src/components/assistant-ui/markdown-text.artifacts.test.tsx b/apps/desktop/src/components/assistant-ui/markdown-text.artifacts.test.tsx index 89fc0b61c1..af573eadfd 100644 --- a/apps/desktop/src/components/assistant-ui/markdown-text.artifacts.test.tsx +++ b/apps/desktop/src/components/assistant-ui/markdown-text.artifacts.test.tsx @@ -65,6 +65,14 @@ describe('MarkdownTextContent artifacts', () => { expect(artifactsForSession('session-artifacts')).toHaveLength(0) }) + it('keeps the code-block copy control visible without hover', async () => { + render() + + const copy = await screen.findByRole('button', { name: 'Copy code' }) + + expect(copy.className.split(/\s+/)).not.toContain('opacity-0') + }) + it('does not register while the message is still streaming', async () => { render() diff --git a/apps/desktop/src/components/chat/shiki-highlighter.tsx b/apps/desktop/src/components/chat/shiki-highlighter.tsx index 6823bba7cf..eaa8a2bc67 100644 --- a/apps/desktop/src/components/chat/shiki-highlighter.tsx +++ b/apps/desktop/src/components/chat/shiki-highlighter.tsx @@ -15,7 +15,8 @@ import { isLikelyProseCodeBlock } from '@/lib/markdown-code' * own the wrapping `` here and neutralize the upstream * `data-streamdown="code-block"` chrome from styles.css. The card is * background-only — no header row, no language label — so a fence reads as a - * tinted slab of the reply; copy is a hover-reveal control in the corner. + * tinted slab of the reply. Copy stays visible in the corner (not hover-only) + * so Windows / touch / no-hover surfaces can still find it. * * `react-shiki` full bundle so all `bundledLanguages` work; theme switches * follow the document `color-scheme` via `defaultColor="light-dark()"`. @@ -148,7 +149,7 @@ export const SyntaxHighlighter: FC = ({