diff --git a/AGENTS.md b/AGENTS.md index abd1342a..96a620fd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ breaking changes with `!` or a `BREAKING CHANGE:` footer. -# This is NOT the Next.js you know +## This is NOT the Next.js you know This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. diff --git a/src/components/card-caption.tsx b/src/components/card-caption.tsx index 70468f5c..62c63927 100644 --- a/src/components/card-caption.tsx +++ b/src/components/card-caption.tsx @@ -12,6 +12,7 @@ export function CardCaption({ iconPosition = "right", image, href, + onClick, footer, className, titleClassName, @@ -24,6 +25,7 @@ export function CardCaption({ /** An image shown in place of the icon, e.g. a project's logo. */ image?: string href?: string + onClick?: () => void /** Pinned to the bottom of the card, e.g. where a link leads to. */ footer?: ReactNode className?: string @@ -31,12 +33,18 @@ export function CardCaption({ captionClassName?: string }) { return ( - // Only cards that lead somewhere react to hover a:focus-visible]:ring-2 has-[>a:focus-visible]:ring-blue-secondary", className)} + hoverBackground={Boolean(href || onClick)} + className={cn( + (href || onClick) && "has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-blue-secondary", + className + )} > - {href && } + {href ? ( + + ) : onClick ? ( + diff --git a/src/components/home/materials.tsx b/src/components/home/materials.tsx index 146f16d7..f62968dd 100644 --- a/src/components/home/materials.tsx +++ b/src/components/home/materials.tsx @@ -1,14 +1,17 @@ +"use client" + import Link from "next/link" import { Fragment } from "react" import { FiArrowUpRight, FiBook, FiBookOpen, FiClipboard, FiFileText, FiUploadCloud } from "react-icons/fi" import { CardIcon } from "@/components/card-icon" import { MATERIALS_URL } from "@/components/header/constants" import { CONTAINER } from "@/components/layout/page" +import { useActivationToast } from "@/components/ui/activation-toast" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" import { CardCaption } from "../card-caption" -// "Carica" has no destination yet, so it stays a plain card +// Upload and per-type archive pages will be activated later. const featuredCards = [ { title: "Carica", @@ -25,7 +28,6 @@ const featuredCards = [ }, ] -// What the archive holds. Not links: the archive has no per-type pages to open const archiveTypes = [ { title: "Dispense", icon: FiBook }, { title: "Esami", icon: FiFileText }, @@ -33,6 +35,7 @@ const archiveTypes = [ ] export function Materials() { + const { showActivationToast, activationToast } = useActivationToast() return (
@@ -87,10 +92,17 @@ export function Materials() {
{archiveTypes.map((card) => ( - + ))}
+ {activationToast}
) } diff --git a/src/components/ui/activation-toast.tsx b/src/components/ui/activation-toast.tsx new file mode 100644 index 00000000..3ac5b8d6 --- /dev/null +++ b/src/components/ui/activation-toast.tsx @@ -0,0 +1,34 @@ +"use client" + +import { useEffect, useState } from "react" +import { createPortal } from "react-dom" +import { FiInfo } from "react-icons/fi" + +/** One short notice at a time; another click restarts its three-second timeout. */ +export function useActivationToast() { + const [announcement, setAnnouncement] = useState(0) + + useEffect(() => { + if (!announcement) return + const timeout = window.setTimeout(() => setAnnouncement(0), 3000) + return () => window.clearTimeout(timeout) + }, [announcement]) + + return { + showActivationToast: () => setAnnouncement((current) => current + 1), + activationToast: announcement + ? createPortal( + + + In attivazione + , + document.body + ) + : null, + } +}