feat: add ItemList
This commit is contained in:
committed by
Mathias Schopmans
parent
f910c9e1e5
commit
5603384603
31
src/components/ItemList/ItemList.module.css
Normal file
31
src/components/ItemList/ItemList.module.css
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
+ .item {
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
&.isFadedOut {
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.isActive {
|
||||||
|
background: var(--foreground);
|
||||||
|
color: var(--background);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/components/ItemList/ItemList.tsx
Normal file
33
src/components/ItemList/ItemList.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import styles from "./ItemList.module.css";
|
||||||
|
|
||||||
|
import { FlagBadge } from "@/components/Badge/Badge";
|
||||||
|
import { Item } from "@/lib/types";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
interface ItemListProps {
|
||||||
|
items: Item[];
|
||||||
|
activeId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ItemList({ items, activeId }: ItemListProps) {
|
||||||
|
return (
|
||||||
|
<ul className={styles.list}>
|
||||||
|
{items.map((item) => (
|
||||||
|
<li className={styles.item} key={item.id}>
|
||||||
|
<Link
|
||||||
|
className={cn(styles.link, {
|
||||||
|
[styles.isFadedOut]: !item.featured,
|
||||||
|
[styles.isActive]: item.id === activeId,
|
||||||
|
})}
|
||||||
|
href={`/${item.quadrant}/${item.id}`}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
<FlagBadge className={styles.flag} flag={item.flag} />
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
.layout.default {
|
.layout.default {
|
||||||
.content {
|
.content {
|
||||||
max-width: var(--max-width);
|
max-width: var(--max-width);
|
||||||
|
min-height: calc(100vh - 250px);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import config from "../../data/config.json";
|
import config from "../../data/config.json";
|
||||||
|
import data from "../../data/data.json";
|
||||||
import messages from "../../data/messages.json";
|
import messages from "../../data/messages.json";
|
||||||
|
|
||||||
import { Quadrant, Ring } from "@/lib/types";
|
import { Flag, Item, Quadrant, Ring } from "@/lib/types";
|
||||||
|
|
||||||
export function getMessages() {
|
export function getMessages() {
|
||||||
return messages;
|
return messages;
|
||||||
@@ -11,10 +12,22 @@ export function getAppName() {
|
|||||||
return messages.radarName;
|
return messages.radarName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFlag(flag: Exclude<Flag, Flag.Default>) {
|
||||||
|
return config.flags[flag];
|
||||||
|
}
|
||||||
|
|
||||||
export function getRings(): Ring[] {
|
export function getRings(): Ring[] {
|
||||||
return config.rings;
|
return config.rings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRing(id: string): Ring | undefined {
|
||||||
|
return getRings().find((r) => r.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getReleases(): string[] {
|
||||||
|
return data.releases;
|
||||||
|
}
|
||||||
|
|
||||||
export function getQuadrants(): Quadrant[] {
|
export function getQuadrants(): Quadrant[] {
|
||||||
return config.quadrants;
|
return config.quadrants;
|
||||||
}
|
}
|
||||||
@@ -22,3 +35,14 @@ export function getQuadrants(): Quadrant[] {
|
|||||||
export function getQuadrant(id: string): Quadrant | undefined {
|
export function getQuadrant(id: string): Quadrant | undefined {
|
||||||
return getQuadrants().find((q) => q.id === id);
|
return getQuadrants().find((q) => q.id === id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getItems(featured?: boolean): Item[] {
|
||||||
|
return data.items.filter((item) => !featured || item.featured) as Item[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getItem(id: string): Item | undefined {
|
||||||
|
return data.items.find((item) => item.id === id) as Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sortByFeaturedAndTitle = (a: Item, b: Item) =>
|
||||||
|
Number(b.featured) - Number(a.featured) || a.title.localeCompare(b.title);
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
// Format the title of the page
|
|
||||||
import { getAppName } from "@/lib/data";
|
import { getAppName } from "@/lib/data";
|
||||||
|
|
||||||
export function formatTitle(title: string = ""): string {
|
// Format the title of the page
|
||||||
if (!title) return getAppName();
|
export function formatTitle(...title: string[]): string {
|
||||||
return `${title} | ${getAppName()}`;
|
return [...title, getAppName()].join(" | ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats a release (2024-02-14) to a date (February 2024)
|
||||||
|
export function formatRelease(release: string): string {
|
||||||
|
const date = new Date(release);
|
||||||
|
return date.toLocaleDateString("en-US", {
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,5 +38,4 @@ export interface Quadrant {
|
|||||||
description: string;
|
description: string;
|
||||||
color: string;
|
color: string;
|
||||||
position: number;
|
position: number;
|
||||||
items?: Item[];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,19 @@
|
|||||||
|
import { ItemList } from "@/components/ItemList/ItemList";
|
||||||
|
import { getAppName, getItems, getReleases } from "@/lib/data";
|
||||||
import { CustomPage } from "@/pages/_app";
|
import { CustomPage } from "@/pages/_app";
|
||||||
|
|
||||||
const Home: CustomPage = () => {
|
const Home: CustomPage = () => {
|
||||||
return <h1>Hello world.</h1>;
|
const appName = getAppName();
|
||||||
|
const version = getReleases().length;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>
|
||||||
|
{appName}{" "}
|
||||||
|
<span style={{ color: "var(--highlight)" }}>Version #{version}</span>
|
||||||
|
</h1>
|
||||||
|
<ItemList items={getItems()} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
--foreground: #fff;
|
--foreground: #fff;
|
||||||
--background: #173d7a;
|
--background: #173d7a;
|
||||||
|
--highlight: #029df7;
|
||||||
|
--border: rgba(255, 255, 255, 0.1);
|
||||||
|
--badge: #333; /* local color which get's overridden by the element */
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -15,6 +18,10 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
@@ -24,6 +31,8 @@ body {
|
|||||||
body {
|
body {
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -35,6 +44,10 @@ p {
|
|||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -44,8 +57,29 @@ svg {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
h1,
|
||||||
max-width: var(--max-width);
|
h2,
|
||||||
margin: 0 auto;
|
h3,
|
||||||
padding: 0 1rem;
|
h4 {
|
||||||
|
line-height: 1.1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 37px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding-left: 16px;
|
||||||
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user