feat: add copy button to code blocks in README#636
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
| opacity: 1; | ||
| } | ||
|
|
||
| .readme :deep(.readme-copy-button:hover) { |
There was a problem hiding this comment.
this should also be visible when focused 🙏
| const html = highlightCodeSync(shiki, text, lang || 'text') | ||
| // Add copy button | ||
| return `<div class="readme-code-block" dir="ltr"> | ||
| <button type="button" class="readme-copy-button" title="Copy code" check-icon="i-carbon:checkmark" copy-icon="i-carbon:copy" data-copy> |
There was a problem hiding this comment.
I think we need accessible text as well
danielroe
left a comment
There was a problem hiding this comment.
thank you - this looks amazing!
I left some comments for a11y, and I think we'll also need to bump the readme cache key 🙏
|
@danielroe hii! can you check now? ⟡˙⋆ |
serhalp
left a comment
There was a problem hiding this comment.
❤️ This is such a great little feature! I think all these little delightful touches in the app are how we make npmx shine and be successful!
💯
| const originalIcon = 'i-carbon:copy' | ||
| const successIcon = 'i-carbon:checkmark' | ||
|
|
||
| icon.classList.remove(originalIcon) | ||
| icon.classList.add(successIcon) | ||
|
|
||
| setTimeout(() => { | ||
| icon.classList.remove(successIcon) | ||
| icon.classList.add(originalIcon) | ||
| }, 2000) |
There was a problem hiding this comment.
I wonder if there's any way we could accomplish this with native CSS transitions?
| renderer.code = ({ text, lang }: Tokens.Code) => { | ||
| return highlightCodeSync(shiki, text, lang || 'text') | ||
| const html = highlightCodeSync(shiki, text, lang || 'text') | ||
| // Add copy button |
There was a problem hiding this comment.
| // Add copy button | |
| // Add copy button | |
| // NOTE: `app/components/Readme.vue` makes some assumptions about the exact DOM structured injected here. | |
| // If you make changes here, you may need to update there as well. |
| opacity: 1; | ||
| } | ||
|
|
||
| .readme :deep(.readme-copy-button:hover) { |
| const handleCopy = async (e: MouseEvent) => { | ||
| const target = (e.target as HTMLElement).closest('[data-copy]') | ||
| if (!target) return | ||
|
|
||
| const wrapper = target.closest('.readme-code-block') | ||
| if (!wrapper) return | ||
|
|
||
| const pre = wrapper.querySelector('pre') | ||
| if (!pre?.textContent) return | ||
|
|
||
| await copy(pre.textContent) | ||
|
|
||
| const icon = target.querySelector('span') | ||
| if (!icon) return |
There was a problem hiding this comment.
Since this is making leaky assumptions about the DOM structure here, this feature seems like a prime candidate for some test coverage.
🙏🏼 Would you be up for opening a follow-up PR with at least a happy path test? Otherwise we can open an issue to track it.
…v#636) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This pull request enhances the user experience for code blocks in the
Readme.vuecomponent by adding a copy-to-clipboard feature with visual feedback. The changes include frontend event handling, UI improvements for code block interactions, and backend support for rendering copy buttons in code blocks.Frontend functionality and UI improvements:
Readme.vueto enable copying code blocks to the clipboard and provide visual feedback by toggling between copy and success icons.Readme.vueto position and animate the copy button, making it visible on code block hover and improving its appearance.Backend rendering and sanitization:
server/utils/readme.tsto render code blocks with a copy button by default, wrapping highlighted code in a.readme-code-blockdiv and injecting a button for copy functionality.server/utils/readme.tsto supportbuttonelements and necessary attributes for the copy feature.