Skip to content

Commit

Permalink
ProjectDetailsButtonLink
Browse files Browse the repository at this point in the history
  • Loading branch information
gilhanan committed Feb 2, 2024
1 parent 7c7779f commit d23e825
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 43 deletions.
21 changes: 7 additions & 14 deletions src/app/components/ButtonLink.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ describe("ButtonLink", () => {
const props: ButtonLinkProps = {
url: "https://example.com",
text: "Example Text",
lightSrc: "light-image.png",
darkSrc: "dark-image.png",
};

it("should render the link", () => {
Expand All @@ -21,17 +19,12 @@ describe("ButtonLink", () => {
expect(screen.getByText(props.text)).toBeInTheDocument();
});

it("should render a ThemedImage component with the provided props", () => {
render(<ButtonLink {...props} />);
expect(
screen.getByRole("img", {
name: `${props.text} (dark)`,
}),
).toBeInTheDocument();
expect(
screen.getByRole("img", {
name: `${props.text} (light)`,
}),
).toBeInTheDocument();
it("should render a child component", () => {
render(
<ButtonLink {...props}>
<div data-testid="child-component" />
</ButtonLink>,
);
expect(screen.getByTestId("child-component")).toBeInTheDocument();
});
});
15 changes: 3 additions & 12 deletions src/app/components/ButtonLink.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import Link from "next/link";
import { ThemedImage } from "@components/ThemedImage";

export interface ButtonLinkProps {
url: string;
text: string;
lightSrc: string;
darkSrc: string;
}

export function ButtonLink({
url,
text,
lightSrc,
darkSrc,
}: ButtonLinkProps): ReturnType<React.FC> {
children,
}: React.PropsWithChildren<ButtonLinkProps>): ReturnType<React.FC> {
return (
<Link
href={url}
target="_blank"
className="flex gap-2 text-sm items-center p-1 border rounded-md shadow-sm hover:bg-slate-100 dark:hover:bg-slate-800"
>
<ThemedImage
lightSrc={lightSrc}
darkSrc={darkSrc}
width={30}
alt={text}
/>
<div className="w-8 h-8 p-1">{children}</div>
<span className="text-primary">{text}</span>
</Link>
);
Expand Down
25 changes: 11 additions & 14 deletions src/app/components/ProjectDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FiTag } from "react-icons/fi";
import chromeWebStore from "@images/chrome-web-store.svg";
import githubLight from "@images/github.svg";
import githubDark from "@images/github-dark.svg";
import { Project } from "@shared/models";
import { ThemedImage } from "@components/ThemedImage";
import { ButtonLink } from "@components/ButtonLink";
import { ProjectDetailsButtonLink } from "@components/ProjectDetailsButtonLink";

interface ProjectDetailsProps {
project: Project;
Expand All @@ -23,7 +23,7 @@ export function ProjectDetails({
return (
<section className="mt-12 sm:mt-6">
<div className="flex sm:flex-row flex-col gap-8">
<div className="w-full sm:w-80 flex flex-col gap-8">
<div className="w-full sm:max-w-[300px] flex flex-col gap-8">
<ThemedImage
lightSrc={light}
darkSrc={dark}
Expand All @@ -38,18 +38,15 @@ export function ProjectDetails({
<div>
<h2 className="text-primary">Links</h2>
<div className="flex flex-col gap-2">
<ButtonLink
url={url}
text="Get extension"
lightSrc={chromeWebStore}
darkSrc={chromeWebStore}
/>
<ButtonLink
url={repo}
text="Source code"
lightSrc={githubLight}
darkSrc={githubDark}
/>
<ProjectDetailsButtonLink category={category} url={url} />
<ButtonLink url={repo} text="Source code">
<ThemedImage
lightSrc={githubLight}
darkSrc={githubDark}
className="w-full h-full"
alt="Source code"
/>
</ButtonLink>
</div>
</div>
</div>
Expand Down
22 changes: 22 additions & 0 deletions src/app/components/ProjectDetailsButtonLink.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { render, screen } from "@testing-library/react";
import { ProjectDetailsButtonLink } from "./ProjectDetailsButtonLink";
import { Category } from "../shared/models";

describe("ProjectDetailsButtonLink", () => {
it.each([
["Chrome Extension", "Get extension"],
["Web development", "Open website"],
] satisfies [Category, string][])(
`renders the correct link title for %s category`,
(category, title) => {
render(
<ProjectDetailsButtonLink
category={category}
url={"https://example.com"}
/>,
);
const linkTitle = screen.getByText(title);
expect(linkTitle).toBeInTheDocument();
},
);
});
35 changes: 35 additions & 0 deletions src/app/components/ProjectDetailsButtonLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Image from "next/image";
import { FiGlobe } from "react-icons/fi";
import chromeWebStore from "@images/chrome-web-store.svg";
import { Category } from "@shared/models";
import { ButtonLink } from "@components/ButtonLink";

interface ProjectDetailsButtonLinkProps {
category: Category;
url: string;
}

const categoryToLinkIcon: Record<
Category,
{ title: string; icon: JSX.Element }
> = {
"Chrome Extension": {
title: "Get extension",
icon: <Image src={chromeWebStore} alt="Chrome Web Store" />,
},
"Web development": {
title: "Open website",
icon: <FiGlobe className="w-full h-full text-primary" />,
},
};

export function ProjectDetailsButtonLink({
category,
url,
}: ProjectDetailsButtonLinkProps): ReturnType<React.FC> {
return (
<ButtonLink url={url} text={categoryToLinkIcon[category].title}>
{categoryToLinkIcon[category].icon}
</ButtonLink>
);
}
11 changes: 8 additions & 3 deletions src/app/components/ProjectTile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Link from "next/link";
import { FiCode, FiShoppingBag } from "react-icons/fi";
import { Project } from "@shared/models";
import { FiCode, FiGlobe, FiShoppingBag } from "react-icons/fi";
import { Category, Project } from "@shared/models";
import { ThemedImage } from "@components/ThemedImage";

interface TileLinkProps {
Expand All @@ -22,6 +22,11 @@ function TileLink({ url, icon, label }: TileLinkProps): ReturnType<React.FC> {
);
}

const categoryToTileLinkIcon: Record<Category, React.ReactNode> = {
"Chrome Extension": <FiShoppingBag />,
"Web development": <FiGlobe />,
};

export function ProjectTile({
id,
title,
Expand All @@ -38,7 +43,7 @@ export function ProjectTile({
},
{
url,
icon: <FiShoppingBag />,
icon: categoryToTileLinkIcon[category],
label: `View ${title} project`,
},
];
Expand Down

0 comments on commit d23e825

Please sign in to comment.