feat: add copy-to-clipboard functionality for answers#262
Conversation
|
@Owais-Siddique-11 is attempting to deploy a commit to the Karan Mani Tripathi 's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Technical Review
Hi @Owais-Siddique-11! Thank you for your contribution to DoubtDesk.
The code changes look good. Before we can complete the technical review, approve, and merge this pull request, we have one final requirement for all contributors: Please star the DoubtDesk repository.
Once you have starred the repository, please drop a comment here saying "done" (or we will automatically detect it) and we will proceed with approving and merging your PR. Thank you.
There was a problem hiding this comment.
Pull request overview
Adds copy-to-clipboard functionality to the classroom Ask AI view (AskAIView). A local useCopyToClipboard hook wraps navigator.clipboard.writeText with Sonner toast feedback and a transient "copied" state, and two new buttons surface this — a "Copy All" button for the full AI response and a per-section "Copy" button placed alongside the existing "Generate Video" button.
Changes:
- Introduce a
useCopyToClipboardhook with success/error toasts and a per-id copied state. - Add a "Copy All" button above the parsed sections that copies the full raw response.
- Add a per-section "Copy" button in each section header, grouped with the existing Generate Video action.
Comments suppressed due to low confidence (1)
components/AskAIView.tsx:358
- The indentation in this JSX block is inconsistent with the rest of the file (which uses 4-space indentation matched to the JSX nesting). Lines 311–325 and lines 336–358 are flush-left or use 4-space top-level indentation while the surrounding JSX tree is nested several levels deeper. Please re-indent these blocks to match the existing nesting so the structure stays readable and
git blame/diffs remain clean.
<div className="space-y-4">
<div className="flex justify-end">
<button
onClick={() => copy(response, "full-response")}
className="flex items-center gap-2 px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl font-bold uppercase tracking-tighter text-[9px] transition-all text-slate-400 hover:text-white"
aria-label="Copy full response"
>
{copied === "full-response" ? (
<><Check className="w-3 h-3 text-green-400" /> All Copied!</>
) : (
<><Copy className="w-3 h-3" /> Copy All</>
)}
</button>
</div>
{sections.map((sec, idx) => {
const meta = SECTION_META[sec.title];
return (
<div key={idx} className="bg-white/60 dark:bg-slate-900/60 border border-slate-200 dark:border-white/8 rounded-3xl overflow-hidden shadow-lg">
<div className={`flex items-center gap-3 px-6 py-4 border-b border-slate-200 dark:border-white/5`}>
{meta && (
<div className={`flex items-center justify-center w-8 h-8 rounded-xl bg-slate-100 dark:bg-white/5 border ${meta.badge}`}>
{meta.icon}
</div>
)}
<h2 className="text-slate-900 dark:text-white font-black tracking-tight text-sm uppercase italic">{sec.title}</h2>
<div className="ml-auto flex items-center gap-2">
<button
onClick={() => copy(sec.content, `section-${idx}`)}
className="flex items-center gap-1.5 px-3 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl font-bold uppercase tracking-tighter text-[9px] transition-all text-slate-400 hover:text-white"
aria-label="Copy section content"
title="Copy to clipboard"
>
{copied === `section-${idx}` ? (
<><Check className="w-3 h-3 text-green-400" /> Copied!</>
) : (
<><Copy className="w-3 h-3" /> Copy</>
)}
</button>
{idx === 0 && (
<button
onClick={handleGenerateVideo}
disabled={isVideoLoading}
className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-blue-600 to-indigo-600 text-slate-900 dark:text-white rounded-xl font-bold uppercase tracking-tighter text-[9px] shadow-lg shadow-blue-500/20 active:scale-95 transition-all disabled:opacity-50"
>
{isVideoLoading ? <Loader2 className="w-3 h-3 animate-spin" /> : <Zap className="w-3 h-3 text-yellow-400 fill-yellow-400" />} {isVideoLoading ? "Generating..." : "Generate Video"}
</button>
)}
</div>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const [isVideoLoading, setIsVideoLoading] = useState(false); | ||
| const [videoUrl, setVideoUrl] = useState<string | null>(null); | ||
| const fileInputRef = useRef<HTMLInputElement>(null); | ||
| const { copied, copy } = useCopyToClipboard(); |
|
Hey I have started the repo |
Description
Added a copy-to-clipboard feature for answers/solutions to improve workflow efficiency and usability.
Changes Made
Closes #233