Skip to content

Commit f9ab81a

Browse files
jbromaclaude
andauthored
feat: custom PrevNextPage component (#119)
Co-authored-by: Claude <[email protected]>
1 parent cb9c653 commit f9ab81a

File tree

6 files changed

+170
-74
lines changed

6 files changed

+170
-74
lines changed

packages/theme/src/plugin/theme.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
HomeHero,
1111
LinkCard,
1212
OutlineCTA,
13+
PrevNextPage,
1314
SwitchAppearance,
1415
VersionBadge,
1516
// @ts-ignore
@@ -63,6 +64,7 @@ export {
6364
HomeHero,
6465
LinkCard,
6566
OutlineCTA,
67+
PrevNextPage,
6668
SwitchAppearance,
6769
VersionBadge,
6870
};

packages/theme/src/styles/nav.css

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -215,77 +215,3 @@ div.rspress-nav-appearance > div,
215215
font-weight: 500 !important;
216216
}
217217

218-
/*
219-
========================================
220-
Prev next page
221-
========================================
222-
*/
223-
224-
:root {
225-
--rp-prev-next-page-gap: 12px;
226-
}
227-
228-
.rp-prev-next-page {
229-
gap: var(--rp-prev-next-page-gap);
230-
231-
@media (max-width: 480px) {
232-
flex-direction: column;
233-
}
234-
}
235-
236-
.rp-prev-next-page__item {
237-
width: 100%;
238-
position: relative;
239-
border: 1px solid var(--rp-c-divider-light);
240-
border-radius: var(--rp-radius-small) !important;
241-
align-self: stretch;
242-
justify-content: flex-start !important;
243-
}
244-
245-
.rp-prev-next-page__item:hover {
246-
background-color: initial !important;
247-
opacity: initial !important;
248-
}
249-
250-
.rp-prev-next-page__icon {
251-
content: url("../assets/arrow-bar-right.svg?react");
252-
width: 16px;
253-
height: 16px;
254-
padding: calc((40px - 16px) / 2);
255-
background-color: var(--rp-c-divider-light);
256-
border-radius: var(--rp-radius-small);
257-
box-sizing: content-box;
258-
}
259-
260-
.rp-prev-next-page__next {
261-
align-items: flex-start !important;
262-
}
263-
264-
.rp-prev-next-page__item__desc {
265-
position: absolute;
266-
top: 10px;
267-
left: var(--rp-prev-next-page-gap);
268-
}
269-
270-
.rp-prev-next-page__next .rp-prev-next-page__item__desc {
271-
padding-left: 0;
272-
}
273-
274-
.rp-prev-next-page__prev .rp-prev-next-page__item__desc {
275-
padding-left: calc(40px + var(--rp-prev-next-page-gap));
276-
}
277-
278-
.rp-prev-next-page__prev .rp-prev-next-page__item__title {
279-
justify-content: flex-start;
280-
}
281-
282-
.rp-prev-next-page__item__title {
283-
gap: var(--rp-prev-next-page-gap) !important;
284-
justify-content: space-between;
285-
width: 100%;
286-
align-items: flex-start !important;
287-
}
288-
289-
.rp-prev-next-page__item__title > span {
290-
padding-top: var(--rp-prev-next-page-gap);
291-
}
Lines changed: 3 additions & 0 deletions
Loading

packages/theme/src/theme/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export { HomeFooter } from './home-footer';
99
export { HomeHero } from './home-hero';
1010
export { LinkCard } from './link-card';
1111
export { OutlineCTA } from './outline-cta';
12+
export { PrevNextPage } from './prev-next-page';
1213
export { SwitchAppearance } from './switch-appearance';
1314
export { VersionBadge } from './version-badge';
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
.container {
2+
display: flex;
3+
gap: 12px;
4+
5+
@media (max-width: 480px) {
6+
flex-direction: column;
7+
}
8+
}
9+
10+
.placeholder {
11+
flex: 1;
12+
}
13+
14+
.pagerLink {
15+
display: flex;
16+
flex: 1;
17+
align-items: center;
18+
gap: 16px;
19+
border: 1px solid var(--rp-c-divider-light);
20+
border-radius: var(--rp-radius-small);
21+
padding: 12px;
22+
text-decoration: none;
23+
background: linear-gradient(
24+
to right,
25+
var(--ck-foreground-primary) 50%,
26+
transparent 50%
27+
)
28+
right bottom / 200% 100%;
29+
transition: background-position 0.45s cubic-bezier(0.625, 0.05, 0, 1);
30+
}
31+
32+
.pagerLink:hover,
33+
.pagerLink:focus {
34+
border-color: var(--ck-accent);
35+
background-position: left bottom;
36+
}
37+
38+
.pagerLink:hover .title,
39+
.pagerLink:focus .title {
40+
color: var(--ck-accent);
41+
}
42+
43+
.pagerLink:hover .iconBox,
44+
.pagerLink:focus .iconBox {
45+
background-color: var(--ck-accent);
46+
}
47+
48+
.pagerLink:hover .icon,
49+
.pagerLink:focus .icon {
50+
color: #ffffff;
51+
}
52+
53+
.iconBox {
54+
display: flex;
55+
flex-shrink: 0;
56+
align-items: center;
57+
justify-content: center;
58+
width: 40px;
59+
height: 40px;
60+
background-color: var(--rp-c-divider-light);
61+
border-radius: var(--rp-radius-small);
62+
overflow: hidden;
63+
transition: background-color 0.45s cubic-bezier(0.625, 0.05, 0, 1);
64+
}
65+
66+
.icon {
67+
width: 16px;
68+
height: 16px;
69+
transition: color 0.45s cubic-bezier(0.625, 0.05, 0, 1);
70+
}
71+
72+
@media (pointer: fine) {
73+
.pagerLink:hover .icon {
74+
animation:
75+
slide-out 0.2s cubic-bezier(0.625, 0.05, 0, 1),
76+
slide-in 0.25s cubic-bezier(0.625, 0.05, 0, 1) 0.2s;
77+
}
78+
}
79+
80+
.next .textWrap {
81+
align-items: flex-end;
82+
}
83+
84+
.textWrap {
85+
display: flex;
86+
flex: 1;
87+
flex-direction: column;
88+
gap: 2px;
89+
}
90+
91+
.desc {
92+
font-size: 12px;
93+
line-height: 1;
94+
color: var(--rp-c-text-2);
95+
letter-spacing: -0.24px;
96+
transition: color 0.45s cubic-bezier(0.625, 0.05, 0, 1);
97+
}
98+
99+
.title {
100+
font-size: 16px;
101+
line-height: 1.5;
102+
color: var(--rp-c-text-1);
103+
letter-spacing: -0.32px;
104+
transition: color 0.45s cubic-bezier(0.625, 0.05, 0, 1);
105+
}
106+
107+
@keyframes slide-out {
108+
from {
109+
transform: translateX(0%);
110+
}
111+
to {
112+
transform: translateX(150%);
113+
}
114+
}
115+
116+
@keyframes slide-in {
117+
from {
118+
transform: translateX(-150%);
119+
}
120+
to {
121+
transform: translateX(0%);
122+
}
123+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useI18n } from '@rspress/core/runtime';
2+
import { Link, renderInlineMarkdown, usePrevNextPage } from '@theme';
3+
import IconArrowBarLeft from '../../assets/arrow-bar-left.svg?react';
4+
import IconArrowBarRight from '../../assets/arrow-bar-right.svg?react';
5+
import styles from './index.module.scss';
6+
7+
export function PrevNextPage() {
8+
const { prevPage, nextPage } = usePrevNextPage();
9+
const t = useI18n();
10+
11+
return (
12+
<div className={styles.container}>
13+
{prevPage ? (
14+
<Link href={prevPage.link} className={styles.pagerLink}>
15+
<span className={styles.iconBox}>
16+
<IconArrowBarLeft className={styles.icon} />
17+
</span>
18+
<span className={styles.textWrap}>
19+
<span className={styles.desc}>{t('prevPageText')}</span>
20+
<span className={styles.title} {...renderInlineMarkdown(prevPage.text)} />
21+
</span>
22+
</Link>
23+
) : (
24+
<div className={styles.placeholder} />
25+
)}
26+
{nextPage ? (
27+
<Link href={nextPage.link} className={`${styles.pagerLink} ${styles.next}`}>
28+
<span className={styles.textWrap}>
29+
<span className={styles.desc}>{t('nextPageText')}</span>
30+
<span className={styles.title} {...renderInlineMarkdown(nextPage.text)} />
31+
</span>
32+
<span className={styles.iconBox}>
33+
<IconArrowBarRight className={styles.icon} />
34+
</span>
35+
</Link>
36+
) : (
37+
<div className={styles.placeholder} />
38+
)}
39+
</div>
40+
);
41+
}

0 commit comments

Comments
 (0)