Skip to content

Commit 246d8cb

Browse files
committed
feat: add pagination in projects
1 parent 42983de commit 246d8cb

File tree

6 files changed

+147
-5
lines changed

6 files changed

+147
-5
lines changed

src/components/ProjectCard.astro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ const { Content } = await render(project);
4848
}
4949
</Card>
5050
</Grid>
51+
<Card title="tags" mt="2">
52+
{repository.topics.join(", ")}
53+
</Card>

src/components/ProjectPagination.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Pagination } from "@ark-ui/solid";
2+
import type { Page } from "astro";
3+
import type { CollectionEntry } from "astro:content";
4+
import { For, type Component } from "solid-js";
5+
import TablerChevronLeft from "~icons/tabler/chevron-left";
6+
import TablerChevronRight from "~icons/tabler/chevron-right";
7+
import { navigate } from "astro:transitions/client";
8+
import { paginationStyles } from "~/styles/pagination";
9+
10+
export const ProjectPagination: Component<{
11+
page: Page<CollectionEntry<"projects">>;
12+
}> = (props) => {
13+
return (
14+
<Pagination.Root
15+
count={props.page.total}
16+
pageSize={props.page.size}
17+
page={props.page.currentPage}
18+
onPageChange={(details) => navigate(`/projects/${details.page}`)}
19+
class={paginationStyles.root}
20+
>
21+
<Pagination.PrevTrigger class={paginationStyles.trigger}>
22+
<TablerChevronLeft />
23+
</Pagination.PrevTrigger>
24+
<Pagination.Context>
25+
{(api) => (
26+
<For each={api().pages}>
27+
{(page, index) =>
28+
page.type === "page" ? (
29+
<Pagination.Item {...page} class={paginationStyles.item}>{page.value}</Pagination.Item>
30+
) : (
31+
<Pagination.Ellipsis index={index()}>
32+
&#8230;
33+
</Pagination.Ellipsis>
34+
)
35+
}
36+
</For>
37+
)}
38+
</Pagination.Context>
39+
<Pagination.NextTrigger class={paginationStyles.trigger}>
40+
<TablerChevronRight />
41+
</Pagination.NextTrigger>
42+
</Pagination.Root>
43+
);
44+
};

src/components/ui/Card.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import type { ParentComponent } from "solid-js";
1+
import { splitProps, type ParentComponent } from "solid-js";
22
import { css } from "styled-system/css";
3-
import { Box, HStack } from "styled-system/jsx";
3+
import { Box, HStack, type BoxProps } from "styled-system/jsx";
44

5-
export const Card: ParentComponent<{ title: string }> = (props) => {
5+
interface CardProps extends BoxProps {
6+
title: string;
7+
}
8+
9+
export const Card: ParentComponent<CardProps> = (_props) => {
10+
const [props, boxProps] = splitProps(_props, ["title", "children"]);
611
const HorizontalLine = (
712
<Box
813
borderTopWidth="normal"
@@ -14,7 +19,7 @@ export const Card: ParentComponent<{ title: string }> = (props) => {
1419
);
1520

1621
return (
17-
<Box>
22+
<Box {...boxProps}>
1823
<HStack alignItems="end">
1924
{HorizontalLine}
2025
<span class={css({ marginBottom: "-0.5em" })}>{props.title}</span>

src/pages/projects/[page].astro

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import { CollectionEntry, getCollection } from "astro:content";
44
import { css } from "styled-system/css";
55
import MDContainer from "~/components/MDContainer.astro";
66
import ProjectCard from "~/components/ProjectCard.astro";
7+
import { ProjectPagination } from "~/components/ProjectPagination";
78
import BaseLayout from "~/layouts/BaseLayout.astro";
89
910
export const getStaticPaths = (async ({ paginate }) => {
1011
const projects = (await getCollection("projects")).sort(
1112
(a, b) => b.data.priority - a.data.priority,
1213
);
1314
14-
return paginate(projects, { pageSize: 4 });
15+
return paginate(projects, { pageSize: 3 });
1516
}) satisfies GetStaticPaths;
1617
1718
interface Props {
@@ -28,7 +29,10 @@ const { page } = Astro.props;
2829
Some of my most cherished and meticulously developed projects.
2930
</p>
3031
<hr />
32+
<ProjectPagination page={page} client:load transition:persist="p1" />
3133
{page.data.map((project) => <ProjectCard project={project} />)}
34+
<br />
35+
<ProjectPagination page={page} client:load transition:persist="p2" />
3236
<hr />
3337
<p>
3438
See more of my work and other open-source contributions over on my

src/styles/button.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { cva } from "styled-system/css";
2+
3+
export const buttonStyles = cva({
4+
base: {
5+
alignItems: "center",
6+
appearance: "none",
7+
cursor: "pointer",
8+
display: "inline-flex",
9+
fontWeight: "semibold",
10+
isolation: "isolate",
11+
minWidth: "0",
12+
justifyContent: "center",
13+
outline: "none",
14+
position: "relative",
15+
transitionDuration: "normal",
16+
transitionProperty: "background, border-color, color, box-shadow",
17+
transitionTimingFunction: "default",
18+
userSelect: "none",
19+
verticalAlign: "middle",
20+
whiteSpace: "nowrap",
21+
_hidden: {
22+
display: "none",
23+
},
24+
"& :where(svg)": {
25+
fontSize: "1.1em",
26+
width: "1.1em",
27+
height: "1.1em",
28+
},
29+
},
30+
variants: {
31+
variant: {
32+
solid: {
33+
backgroundColor: "fg.default",
34+
color: "bg.default",
35+
_hover: {
36+
backgroundColor: "fg.canvas",
37+
},
38+
},
39+
},
40+
size: {
41+
md: {
42+
h: "8",
43+
minW: "8",
44+
textStyle: "sm",
45+
px: "2",
46+
gap: "2",
47+
},
48+
},
49+
icon: {
50+
true: {
51+
px: 0,
52+
},
53+
},
54+
},
55+
defaultVariants: {
56+
variant: "solid",
57+
size: "md",
58+
icon: false,
59+
},
60+
});

src/styles/pagination.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { css } from "styled-system/css";
2+
import { buttonStyles } from "./button";
3+
import { token } from "styled-system/tokens";
4+
5+
export const paginationStyles = {
6+
root: css({
7+
display: "flex",
8+
justifyContent: "center",
9+
alignItems: "stretch",
10+
gap: "6",
11+
}),
12+
trigger: buttonStyles({ icon: true }),
13+
item: css({
14+
cursor: "pointer",
15+
fontVariantNumeric: "tabular-nums",
16+
backgroundColor: "bg.canvas",
17+
px: "2",
18+
fontSize: "lg",
19+
"&[data-selected]": {
20+
textDecoration: "underline",
21+
textDecorationThickness: token.var("borderWidths.normal"),
22+
backgroundColor: "fg.default",
23+
color: "bg.canvas"
24+
},
25+
}),
26+
};

0 commit comments

Comments
 (0)