Skip to content

feat: add copy-to-clipboard toast feedback on profile pages#64

Open
SdSarthak wants to merge 2 commits into
Dev-Card:mainfrom
SdSarthak:feat/copy-toast
Open

feat: add copy-to-clipboard toast feedback on profile pages#64
SdSarthak wants to merge 2 commits into
Dev-Card:mainfrom
SdSarthak:feat/copy-toast

Conversation

@SdSarthak
Copy link
Copy Markdown

Summary

Adds success/failure toast feedback for copy-to-clipboard actions on both public profile pages.

Changes

apps/web/src/routes/u/[username]/+page.svelte

  • Detects platforms with followStrategy === 'copy' (e.g. Discord, which has no profile URL) and renders a <button> tile instead of an <a> link
  • Clicking the button calls navigator.clipboard.writeText(username) and shows a toast
  • On failure (e.g. HTTP context), shows "Failed to copy. Please copy manually."
  • Toast auto-dismisses after 3 seconds

apps/web/src/routes/devcard/[id]/+page.svelte

  • Imports PLATFORMS from @devcard/shared and checks followStrategy in handlePlatformClick
  • 'copy' strategy → clipboard copy + toast; all others → window.open (unchanged)

Both pages include:

  • <div aria-live="polite" aria-atomic="true" class="sr-only"> — announces the message to screen readers
  • <div role="status" class="toast"> — visible 3-second popup at bottom-center
  • CSS for toast (fixed position, dark themed) and .sr-only utility class

Closes #20

Test plan

  • Navigate to a profile with a Discord link → tile shows a copy icon (⎘) instead of →
  • Click Discord tile → "Copied to clipboard!" toast appears for 3 seconds
  • Paste in another app → correct username is pasted
  • All other platform tiles (GitHub, LinkedIn, etc.) still open links in new tab
  • Screen reader announces the copy feedback via the aria-live region
  • No console errors on any interaction

- u/[username]/+page.svelte: detect platforms with followStrategy='copy'
  (Discord, etc.) and render a <button> instead of <a>; clicking copies
  the username to clipboard and shows a 3-second toast
- devcard/[id]/+page.svelte: update handlePlatformClick to check
  followStrategy and copy to clipboard for 'copy' platforms instead of
  window.open
- Both pages include:
  - aria-live="polite" + aria-atomic="true" hidden region for screen readers
  - Visible toast with role="status" rendered for 3 seconds on success/failure
  - Failure path shows "Failed to copy" message when Clipboard API is unavailable

Closes Dev-Card#20
Copilot AI review requested due to automatic review settings May 10, 2026 18:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds user feedback (success/failure) for “copy to clipboard” platform actions on public profile and devcard pages, including an accessible announcement channel and a visible toast.

Changes:

  • Added toast state + 3s auto-dismiss logic and clipboard-copy handlers.
  • Updated public profile platform tiles to render a <button> for followStrategy === 'copy' platforms (e.g., Discord).
  • Updated devcard platform click handling to respect followStrategy (copy → clipboard + toast; otherwise open URL).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
apps/web/src/routes/u/[username]/+page.svelte Renders copy-only platform tiles as buttons; adds clipboard copy + toast UI and styles.
apps/web/src/routes/devcard/[id]/+page.svelte Adds followStrategy handling for platform clicks; adds toast UI and styles.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +349 to +357
/* Copy button — matches anchor tile styles */
button.platform-tile {
background: none;
border: 1px solid var(--border);
cursor: pointer;
font: inherit;
text-align: left;
width: 100%;
}
Comment on lines +135 to +137
<!-- Accessible live region for copy feedback -->
<div aria-live="polite" aria-atomic="true" class="sr-only">{toastMessage}</div>

Comment on lines +16 to +23
let toastMessage = $state('');
let toastTimer: ReturnType<typeof setTimeout> | null = null;

function showToast(message: string) {
toastMessage = message;
if (toastTimer) clearTimeout(toastTimer);
toastTimer = setTimeout(() => { toastMessage = ''; }, 3000);
}
Comment on lines 7 to +28
@@ -10,13 +15,30 @@
instagram: '#E4405F',
youtube: '#FF0000',
devto: '#0A0A0A',
hashnode: '#2962FF'
hashnode: '#2962FF',
discord: '#5865F2',
};
return colors[platform.toLowerCase()] || '#6366F1';
}

function handlePlatformClick(link: any) {
window.open(link.url, '_blank');
function showToast(message: string) {
toastMessage = message;
if (toastTimer) clearTimeout(toastTimer);
toastTimer = setTimeout(() => { toastMessage = ''; }, 3000);
}
Comment on lines +126 to +130
<!-- Accessible live region for copy feedback -->
<div aria-live="polite" aria-atomic="true" class="sr-only">{toastMessage}</div>

{#if toastMessage}
<div class="toast" role="status">{toastMessage}</div>
showToast('Failed to copy. Please copy manually.');
}
} else {
window.open(link.url, '_blank');
@SdSarthak
Copy link
Copy Markdown
Author

All fixed in the follow-up commit:

  • button.platform-tile background changed from none to var(--bg-elevated) to match the anchor tile style.
  • Removed the duplicate aria-live sr-only element — the visible toast now carries aria-live="polite" aria-atomic="true" directly, so screen readers only get one announcement.
  • Added onDestroy(() => { if (toastTimer) clearTimeout(toastTimer); }) in both Svelte components so the timer is cancelled if the user navigates away before it fires.
  • window.open in the devcard page now passes 'noopener,noreferrer' as the third argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web: add success/failure toast for copy button on profile pages

2 participants