Add global links & open icon links in new tab

This commit is contained in:
Xevion
2022-12-25 23:38:30 -06:00
parent 3c16258b8e
commit 283850d8b8
3 changed files with 38 additions and 19 deletions

View File

@@ -1,11 +1,12 @@
import React, {useRef} from "react";
import {useOnClickOutside, useToggle} from "usehooks-ts";
import {classNames, isHoverable} from "../utils/helpers";
import {classNames, isHoverable, stopPropagation} from "../utils/helpers";
import DependentImage from "./DependentImage";
import ReactMarkdown from 'react-markdown'
import Link from "next/link";
import {LinkIcon, LinkIcons} from "../pages";
import {useRouter} from "next/router";
type ItemCardProps = {
banner: string;
@@ -13,11 +14,13 @@ type ItemCardProps = {
title: string;
description: string;
links?: LinkIcon[];
location: string;
}
const ItemCard = ({banner, bannerBlur, title, description, links}: ItemCardProps) => {
const ItemCard = ({banner, bannerBlur, title, description, links, location}: ItemCardProps) => {
const itemRef = useRef<HTMLDivElement>(null);
const [active, toggleActive, setActive] = useToggle()
const router = useRouter();
useOnClickOutside(itemRef, () => {
setActive(false);
@@ -27,6 +30,9 @@ const ItemCard = ({banner, bannerBlur, title, description, links}: ItemCardProps
className={classNames("item", active ? "active" : null)}
onClick={() => {
if (!isHoverable()) toggleActive();
else {
router.push(location);
}
}}>
<DependentImage fill src={banner} blurDataURL={bannerBlur}
className={(loaded) => classNames("object-cover", loaded ? null : "blur-xl")}
@@ -34,21 +40,24 @@ const ItemCard = ({banner, bannerBlur, title, description, links}: ItemCardProps
alt={`Banner for ${title}`}
/>
<div className="elements grid grid-cols-12 h-full m-2 px-1 sm:px-4">
<div className="col-span-9 lg:col-span-8 max-h-full overflow-hidden drop-shadow-2xl pb-2 md:p-1 pl-2">
<Link href={{pathname: location}}
className=" col-span-9 lg:col-span-8 max-h-full overflow-hidden drop-shadow-2xl pb-2 md:p-1 pl-2">
<div className="text-2xl sm:text-2xl md:text-3xl font-semibold">{title}</div>
<div className="mt-0 md:mt-1.5 text-xl sm:text-lg md:text-xl overflow-hidden ">
<ReactMarkdown>{description}</ReactMarkdown>
<ReactMarkdown children={description}/>
</div>
</div>
{ (links?.length ?? 0) > 0 ? <div className="col-span-3 lg:col-span-4 w-full flex justify-end max-h-full md:py-5">
<div className="grid grid-cols-2 grid-rows-2 p-2 md:gap-3 aspect-square icon-grid">
{links!.map(({icon, location}) => {
return <Link href={location} >
{LinkIcons[icon]({})}
</Link>
})}
</div>
</div> : null}
</Link>
{(links?.length ?? 0) > 0 ?
<div className="col-span-3 lg:col-span-4 w-full flex justify-end max-h-full md:py-5">
<div className="grid grid-cols-2 grid-rows-2 p-2 md:gap-3 aspect-square icon-grid">
{links!.map(({icon, location, newTab}) =>
<Link href={location} target={(newTab ?? true) ? "_blank" : "_self"}
onClick={stopPropagation}>
{LinkIcons[icon]!({})}
</Link>)}
</div>
</div> : null}
</div>
</div>
}

View File

@@ -14,19 +14,19 @@ export type Project = {
longDescription: string;
shortDescription: string;
links?: LinkIcon[];
location: string;
}
export type LinkIconType = "github" | "external" | "link";
export const LinkIcons: Record<LinkIconType, IconType> = {
export const LinkIcons: Record<string, IconType> = {
github: AiFillGithub,
external: RxOpenInNewWindow,
link: AiOutlineLink
}
export type LinkIcon = {
icon: LinkIconType;
icon: keyof typeof LinkIcons;
location: string;
newTab?: boolean;
}
type ProjectWithBlur = Project & { bannerBlur: string };
@@ -41,6 +41,7 @@ export async function getStaticProps(context: GetStaticPropsContext) {
{
title: "Phototag",
banner: "/phototag.png",
location: "/phototag",
longDescription: `Using Google's Vision API and supporting metadata formats on Windows, Phototag makes it easy to quickly add rich, descriptive tags to your photos, saving you time and effort.`,
shortDescription: "Effortlessly add rich & descriptive tags to your photos with Phototag.",
links: [
@@ -57,13 +58,14 @@ export async function getStaticProps(context: GetStaticPropsContext) {
{
title: "Paths",
banner: "/paths.png",
location: "/paths",
shortDescription: "Discover the power of graph traversal algorithms with my interactive application.",
longDescription: `Discover the power of graph traversal algorithms with my interactive Unity application!
Easily generate and edit graphs, create mazes, and experiment with different algorithm configurations to find the most efficient path.`,
links: [
{
icon: "github",
location: "https://github.com/Xevion/Paths"
location: "https://github.com/Xevion/Paths",
}
]
}

View File

@@ -6,6 +6,14 @@ export function classNames(...classes: (string | null | undefined)[]) {
return classes.filter(Boolean).join(" ");
}
/**
* A handler that simply calls the `stopPropagation` method on an event.
* @param event The event to prevent propagation on.
*/
export const stopPropagation = (event: Event) => {
event.stopPropagation();
};
const isClient = (): boolean => {
return typeof window !== "undefined";
}