Skip to content

Commit

Permalink
Merge pull request #69 from celestiaorg/feature/add-copy-button-to-gl…
Browse files Browse the repository at this point in the history
…ossary

Added copy link button for glossary sections
  • Loading branch information
alex-beckett authored Jan 29, 2025
2 parents f17049e + 05f6902 commit 20bedd0
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 63 deletions.
2 changes: 1 addition & 1 deletion src/app/glossary/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import seo from "@/data/glossary/seo";
export const metadata = meta(seo);

export default async function Glossary({ children }) {
return children;
return children;
}
19 changes: 16 additions & 3 deletions src/components/Accordion/GlossaryAccordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import PrimaryButton from "@/macros/Buttons/PrimaryButton";
import { usePathname } from "next/navigation";
import Markdown from "markdown-to-jsx";
import RichText from "@/macros/Copy/RichText";
import CopyButton from "@/macros/Buttons/CopyButton";

const GlossaryDirectory = ({ glossaryData }) => {
const router = useRouter();
Expand Down Expand Up @@ -69,6 +70,11 @@ const GlossaryDirectory = ({ glossaryData }) => {
}
}, [pathname]);

const getTermUrl = (slug) => {
if (typeof window === "undefined") return "";
return `${window.location.origin}/glossary/${slug}`;
};

return (
<Container size='xl'>
<Row className={"py-10 lg:flex lg:gap-12 lg:items-center"}>
Expand Down Expand Up @@ -129,9 +135,16 @@ const GlossaryDirectory = ({ glossaryData }) => {
{groupedTerms[letter].map((term) => (
<div key={term.slug} id={`accordion-${term.slug}`} className='border-b border-black-subtle last:border-b-0'>
<div className='py-6'>
<Heading tag={"h3"} size={"sm"} className={"text-left mb-4"}>
{term.title}
</Heading>
<div className='flex items-center gap-3 mb-4'>
<Heading tag={"h3"} size={"sm"} className={"text-left"}>
{term.title}
</Heading>
<CopyButton
copy={getTermUrl(term.slug)}
hover={true}
className='flex flex-col items-center [&_button]:mb-0'
/>
</div>
<RichText size={"md"} className={`text-black-subtle`}>
<Markdown>{term.content || term.description}</Markdown>
</RichText>
Expand Down
70 changes: 30 additions & 40 deletions src/macros/Buttons/CopyButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,38 @@ import Icon from "@/macros/Icons/Icon";
import CopySVG from "@/macros/SVGs/CopySVG";
import { motion, AnimatePresence } from "framer-motion";

const CopyButton = ({ copy, hover = true }) => {
const [copied, setCopied] = useState(false);
const CopyButton = ({ copy, hover = true, className }) => {
const [copied, setCopied] = useState(false);

const handleCopy = () => {
navigator.clipboard.writeText(copy).then(() => {
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 1500); // Tooltip disappears after 2 seconds
});
};
const handleCopy = () => {
navigator.clipboard.writeText(copy).then(() => {
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 1500); // Tooltip disappears after 2 seconds
});
};

return (
<div className="relative inline-block">
<button
onClick={handleCopy}
className="group mb-2.5 active:scale-[0.8] transition-transform"
>
<Icon
Icon={<CopySVG />}
dark={false}
hover={hover}
border
HoverIcon={<CopySVG dark />}
size={"sm"}
/>
</button>
<AnimatePresence>
{copied && (
<motion.div
initial={{ opacity: 0, y: 10, x: "-50%" }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="absolute bottom-full left-1/2 transform mb-1 bg-black-subtle text-white text-xs px-2 py-1 rounded opacity-90"
>
Copied
</motion.div>
)}
</AnimatePresence>
</div>
);
return (
<div className={`relative inline-block ${className}`}>
<button onClick={handleCopy} className='group mb-2.5 active:scale-[0.8] transition-transform'>
<Icon Icon={<CopySVG />} dark={false} hover={hover} border HoverIcon={<CopySVG dark />} size={"sm"} />
</button>
<AnimatePresence>
{copied && (
<motion.div
initial={{ opacity: 0, y: 10, x: "-50%" }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className='absolute px-2 py-1 mb-1 text-xs text-white transform rounded bottom-full left-1/2 bg-black-subtle opacity-90'
>
Copied
</motion.div>
)}
</AnimatePresence>
</div>
);
};

export default CopyButton;
32 changes: 13 additions & 19 deletions src/macros/Copy/Heading.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
const Heading = ({
children,
className,
tag = "h1",
size = "lg",
...props
}) => {
const Tag = tag;
const sizeClasses = {
xs: "",
sm: "text-xl leading-[1.4] lg:text-2xl lg:leading-[1.333333333333333]",
md: "text-[1.75rem] leading-[1.2] lg:text-[2rem] lg:leading-tight",
lg: "text-4xl leading-[1.2] lg:text-[2.5rem] lg:leading-tight",
};
const Heading = ({ children, className, tag = "h1", size = "lg", ...props }) => {
const Tag = tag;
const sizeClasses = {
xs: "",
sm: "text-xl leading-[1.4] lg:text-2xl lg:leading-[1.333333333333333]",
md: "text-[1.75rem] leading-[1.2] lg:text-[2rem] lg:leading-tight",
lg: "text-4xl leading-[1.2] lg:text-[2.5rem] lg:leading-tight",
};

return (
<Tag {...props} className={`font-youth ${sizeClasses[size]} ${className}`}>
{children}
</Tag>
);
return (
<Tag {...props} className={`font-youth ${sizeClasses[size]} ${className}`}>
{children}
</Tag>
);
};

export default Heading;

0 comments on commit 20bedd0

Please sign in to comment.