diff --git a/src/components/ItemDetail/ItemDetail.module.css b/src/components/ItemDetail/ItemDetail.module.css index a7f2433..c36917c 100644 --- a/src/components/ItemDetail/ItemDetail.module.css +++ b/src/components/ItemDetail/ItemDetail.module.css @@ -1,3 +1,14 @@ +.header { + display: flex; + flex-wrap: wrap; + align-items: center; + margin: 0 0 20px; +} + +.title { + margin: 0 30px 0 0; +} + .revision { padding: 30px 0 15px 35px; margin-left: 5px; diff --git a/src/components/ItemDetail/ItemDetail.tsx b/src/components/ItemDetail/ItemDetail.tsx index e182acb..07dfff2 100644 --- a/src/components/ItemDetail/ItemDetail.tsx +++ b/src/components/ItemDetail/ItemDetail.tsx @@ -2,6 +2,7 @@ import styles from "./ItemDetail.module.css"; import { RingBadge } from "@/components/Badge/Badge"; import Attention from "@/components/Icons/Attention"; +import { Tag } from "@/components/Tags/Tags"; import { getReleases } from "@/lib/data"; import { Item } from "@/lib/types"; import { cn } from "@/lib/utils"; @@ -19,7 +20,12 @@ interface ItemProps { export function ItemDetail({ item }: ItemProps) { return ( <> -

{item.title}

+
+

{item.title}

+ {item.tags.map((tag) => ( + + ))} +
{isNotMaintained(item.release) && (
diff --git a/src/components/Radar/Radar.module.css b/src/components/Radar/Radar.module.css index 8232f1e..672cd7f 100644 --- a/src/components/Radar/Radar.module.css +++ b/src/components/Radar/Radar.module.css @@ -1,6 +1,5 @@ .radar { - padding: 0 15px; - margin-bottom: 60px; + padding: 0 15px 30px; position: relative; transition: padding 200ms ease-in-out; } diff --git a/src/components/Tags/Tags.module.css b/src/components/Tags/Tags.module.css new file mode 100644 index 0000000..e8101f6 --- /dev/null +++ b/src/components/Tags/Tags.module.css @@ -0,0 +1,43 @@ +.icon { + width: 16px; + height: 16px; + display: inline-block; + vertical-align: middle; + margin: -2px 6px 0 -5px; +} + +.tag { + position: relative; + display: inline-block; + vertical-align: middle; + padding: 6px 15px 5px; + margin: 6px; + text-transform: uppercase; + border: 1px solid var(--tag); + border-radius: 13px; + background: var(--tag); + font-size: 14px; + line-height: 1; + overflow: hidden; + text-decoration: none; + transition: all 150ms ease-in-out; + + &:hover, + &:focus, + &.active { + background: var(--foreground); + color: var(--background); + } + + &.active { + .icon { + transform: scale(0.8); + } + } +} + +.tags { + text-align: center; + margin: 0 auto 60px; + max-width: 600px; +} diff --git a/src/components/Tags/Tags.tsx b/src/components/Tags/Tags.tsx new file mode 100644 index 0000000..d2aab08 --- /dev/null +++ b/src/components/Tags/Tags.tsx @@ -0,0 +1,45 @@ +import Link, { LinkProps } from "next/link"; +import { ComponentPropsWithoutRef } from "react"; + +import styles from "./Tags.module.css"; + +import IconRemove from "@/components/Icons/Close"; +import IconTag from "@/components/Icons/Tag"; +import { cn } from "@/lib/utils"; + +type TagProps = { + tag: string; + isActive?: boolean; +} & Omit & + ComponentPropsWithoutRef<"a">; + +export function Tag({ tag, isActive, className, ...props }: TagProps) { + const Icon = isActive ? IconRemove : IconTag; + return ( + + + {tag} + + ); +} + +interface TagsProps { + tags: string[]; + activeTag?: string; + className?: string; +} + +export function Tags({ tags, activeTag, className }: TagsProps) { + return ( +
+

Filter by Tag

+ {tags.map((tag) => ( + + ))} +
+ ); +} diff --git a/src/icons/tag.svg b/src/icons/tag.svg new file mode 100644 index 0000000..1369650 --- /dev/null +++ b/src/icons/tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/lib/data.ts b/src/lib/data.ts index 67535fd..f1d451d 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -36,6 +36,10 @@ export function getReleases(): string[] { return data.releases; } +export function getTags(): string[] { + return data.tags; +} + export function getQuadrants(): Quadrant[] { return config.quadrants; } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index f7fb4be..a6e76fe 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,20 +1,30 @@ +import { useRouter } from "next/router"; + import { QuadrantList } from "@/components/QuadrantList/QuadrantList"; import { Radar } from "@/components/Radar/Radar"; +import { Tags } from "@/components/Tags/Tags"; import { getAppName, getItems, getQuadrants, getReleases, getRings, + getTags, } from "@/lib/data"; import { CustomPage } from "@/pages/_app"; const Home: CustomPage = () => { + const router = useRouter(); + const tag = router.query.tag as string | undefined; const appName = getAppName(); const version = getReleases().length; const rings = getRings(); const quadrants = getQuadrants(); - const items = getItems(undefined, true); + const tags = getTags(); + const items = getItems(undefined, true).filter( + (item) => !tag || item.tags.includes(tag), + ); + return ( <>

@@ -24,6 +34,7 @@ const Home: CustomPage = () => {

+ ); diff --git a/src/styles/globals.css b/src/styles/globals.css index a03facc..810361b 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -10,6 +10,7 @@ --text: #575757; --highlight: #029df7; --border: rgba(255, 255, 255, 0.1); + --tag: rgba(255, 255, 255, 0.1); --overlay: #081a37b5; --dialog-bg: #173d7a; @@ -24,12 +25,9 @@ margin: 0; } -html { - scroll-behavior: smooth; -} - html, body { + scroll-behavior: smooth; max-width: 100vw; margin: 0; padding: 0; @@ -62,6 +60,7 @@ img { svg { display: block; + fill: currentColor; } h1,