-
Notifications
You must be signed in to change notification settings - Fork 324
feat(opensource): add guide sharing button and dynamic open graph pre… #1460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,15 @@ | ||
| import React from "react"; | ||
| import React, { useCallback } from "react"; | ||
| import { Link } from "react-router"; | ||
| import { motion } from "framer-motion"; | ||
| import { | ||
| GitPullRequest, Trophy, Award, GraduationCap, | ||
| BookOpen, GitBranch, MessageSquare, Settings, | ||
| BookOpen, GitBranch, MessageSquare, Settings, Share2, | ||
| type LucideIcon, | ||
| } from "lucide-react"; | ||
| import { GuideSearch } from "./GuideSearch"; | ||
| import { SITE_URL } from "../../../lib/seo.utils"; | ||
| import toast from "../../../components/ui/toast"; | ||
| import { Button } from "../../../components/ui/button"; | ||
|
|
||
| interface GuidanceCard { | ||
| to: string; | ||
|
|
@@ -27,6 +30,18 @@ const GUIDANCE_CARDS: GuidanceCard[] = [ | |
| ]; | ||
|
|
||
| export const GuidanceCards = React.memo(function GuidanceCards() { | ||
| const handleShare = useCallback((e: React.MouseEvent, path: string) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
|
|
||
| const url = `${SITE_URL}${path}`; | ||
| void navigator.clipboard.writeText(url).then(() => { | ||
| toast.success("Link copied to clipboard!"); | ||
| }).catch(() => { | ||
| toast.error("Failed to copy link."); | ||
| }); | ||
|
Comment on lines
+33
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate and show the relevant portion of the file
FILE="client/src/module/student/opensource/GuidanceCards.tsx"
if [ ! -f "$FILE" ]; then
echo "Missing file: $FILE"
exit 1
fi
echo "---- file: $FILE (lines 1-120) ----"
nl -ba "$FILE" | sed -n '1,120p'
echo "---- file: $FILE (lines 20-80) ----"
nl -ba "$FILE" | sed -n '20,80p'Repository: Sachinchaurasiya360/InternHack Length of output: 221 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE="client/src/module/student/opensource/GuidanceCards.tsx"
if [ ! -f "$FILE" ]; then
echo "Missing file: $FILE"
exit 1
fi
echo "---- file: $FILE (lines 1-140) ----"
cat -n "$FILE" | sed -n '1,140p'
echo "---- file: $FILE (lines 30-80) ----"
cat -n "$FILE" | sed -n '30,80p'Repository: Sachinchaurasiya360/InternHack Length of output: 8486 Guard Minimal guard- const url = `${SITE_URL}${path}`;
- void navigator.clipboard.writeText(url).then(() => {
+ const url = `${SITE_URL}${path}`;
+ if (!navigator.clipboard?.writeText) {
+ toast.error("Clipboard is not supported in this browser.");
+ return;
+ }
+ void navigator.clipboard.writeText(url).then(() => {
toast.success("Link copied to clipboard!");
}).catch(() => {
toast.error("Failed to copy link.");
});🤖 Prompt for AI Agents |
||
| }, []); | ||
|
|
||
| return ( | ||
| <div className="mb-10"> | ||
| <div className="flex items-center gap-2 mb-3"> | ||
|
|
@@ -45,24 +60,37 @@ export const GuidanceCards = React.memo(function GuidanceCards() { | |
| initial={{ opacity: 0, y: 16 }} | ||
| animate={{ opacity: 1, y: 0 }} | ||
| transition={{ delay: 0.05 + Math.min(i, 6) * 0.04, duration: 0.35 }} | ||
| className="group relative" | ||
| > | ||
| <Link | ||
| to={card.to} | ||
| className="group relative flex flex-col gap-3 p-4 h-full bg-white dark:bg-stone-900 border-r border-b border-stone-200 dark:border-white/10 no-underline hover:bg-stone-900 dark:hover:bg-stone-50 transition-colors" | ||
| className="flex flex-col gap-3 p-4 h-full bg-white dark:bg-stone-900 border-r border-b border-stone-200 dark:border-white/10 no-underline hover:bg-stone-50 dark:hover:bg-stone-800 transition-colors" | ||
| > | ||
| <div className="flex items-center justify-between"> | ||
| <span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-400"> | ||
| <span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-500 transition-colors"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace arbitrary Tailwind text size with canonical scale class. At Line 70, As per coding guidelines, do not use arbitrary bracket sizes like 🤖 Prompt for AI Agents |
||
| / {String(i + 1).padStart(2, "0")} | ||
| </span> | ||
| <div className="w-8 h-8 rounded-md bg-stone-100 dark:bg-white/5 group-hover:bg-white/10 dark:group-hover:bg-stone-900/10 flex items-center justify-center transition-colors"> | ||
| <card.icon className="w-4 h-4 text-stone-700 dark:text-stone-300 group-hover:text-lime-400" aria-hidden /> | ||
| <div className="flex items-center gap-2"> | ||
| <Button | ||
| variant="ghost" | ||
| mode="icon" | ||
| size="sm" | ||
| className="h-8 w-8 rounded-md opacity-0 group-hover:opacity-100 transition-all hover:bg-lime-400/10 hover:text-lime-600 dark:hover:text-lime-400" | ||
| onClick={(e) => handleShare(e, card.to)} | ||
| title="Share Guide" | ||
| > | ||
| <Share2 className="w-3.5 h-3.5" /> | ||
| </Button> | ||
|
Comment on lines
65
to
+83
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid nesting At Line 65-83, the share Suggested structure change- <Link to={card.to} className="...">
- ...
- <Button onClick={(e) => handleShare(e, card.to)} ... />
- ...
- </Link>
+ <div className="relative">
+ <Link to={card.to} className="...">
+ ...
+ </Link>
+ <Button
+ variant="ghost"
+ mode="icon"
+ size="sm"
+ className="absolute top-3 right-3 h-8 w-8 rounded-md ..."
+ onClick={(e) => handleShare(e, card.to)}
+ title="Share Guide"
+ >
+ <Share2 className="w-3.5 h-3.5" />
+ </Button>
+ </div>As per coding guidelines, interactive UI should use accessible patterns and this change currently introduces a non-compliant nested interaction model. 🤖 Prompt for AI Agents |
||
| <div className="w-8 h-8 rounded-md bg-stone-100 dark:bg-white/5 group-hover:bg-lime-400/10 flex items-center justify-center transition-colors"> | ||
| <card.icon className="w-4 h-4 text-stone-700 dark:text-stone-300 group-hover:text-lime-600 dark:group-hover:text-lime-400" aria-hidden /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <div className="flex flex-col gap-1"> | ||
| <p className="text-sm font-bold tracking-tight text-stone-900 dark:text-stone-50 group-hover:text-stone-50 dark:group-hover:text-stone-900"> | ||
| <p className="text-sm font-bold tracking-tight text-stone-900 dark:text-stone-50"> | ||
| {card.title} | ||
| </p> | ||
| <p className="text-xs text-stone-600 dark:text-stone-400 group-hover:text-stone-300 dark:group-hover:text-stone-700 line-clamp-2"> | ||
| <p className="text-xs text-stone-600 dark:text-stone-400 line-clamp-2 leading-relaxed"> | ||
| {card.desc} | ||
| </p> | ||
| </div> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add
ogImageto the loading state SEO component for consistency.The loading skeleton's SEO component (lines 100-105) is missing the
ogImageprop that was added here on line 158. Both SEO components should have identical metadata to ensure consistent Open Graph previews regardless of loading state.🔧 Proposed fix
Add the same
ogImageprop to the SEO component in the loading state:<SEO title="First Pull Request Guide - Open Source for Beginners" description="Step-by-step roadmap to making your first pull request on GitHub. Learn git workflow, finding issues, and contributing to open source projects." keywords="first pull request, open source contribution, GitHub beginner, git workflow, contribute to open source" canonicalUrl={canonicalUrl("/student/opensource/first-pr")} + ogImage="/og/og-first-pr.png" />📝 Committable suggestion
🤖 Prompt for AI Agents