Skip to content

Commit 921297e

Browse files
cijiugechucsr632
andauthored
feat(theme-doc): add footer (#89)
* feat: implement footer * fix * import rc-footer style and overwrite it * expose more options * improve footer options * add footer to doc-site * support footer theme * improve footer light theme * backgroundColor of light theme Co-authored-by: csr632 <[email protected]>
1 parent 0a6779e commit 921297e

File tree

11 files changed

+375
-1
lines changed

11 files changed

+375
-1
lines changed

doc-site/pages/_theme.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react'
22
import { createTheme, defaultSideNavs } from 'vite-pages-theme-doc'
33

44
import Component404 from './404'
5+
import { footerConfig } from './themConfig/footer'
56

67
export default createTheme({
78
topNavs: [
@@ -28,5 +29,8 @@ export default createTheme({
2829
},
2930
})
3031
},
32+
footer: ({ resolvedLocale: { localeKey } }) => {
33+
return footerConfig.en
34+
},
3135
Component404,
3236
})

doc-site/pages/themConfig/footer.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react'
2+
import type { FooterConfig } from 'vite-pages-theme-doc'
3+
import {
4+
QuestionCircleOutlined,
5+
BugOutlined,
6+
GithubFilled,
7+
TeamOutlined,
8+
LinkOutlined,
9+
} from '@ant-design/icons'
10+
11+
export const footerConfig: { [locale: string]: FooterConfig } = {
12+
en: {
13+
message: `2020 - ${new Date().getFullYear()}`,
14+
copyright: 'Released under the MIT License.',
15+
columns: [
16+
{
17+
icon: <TeamOutlined />,
18+
title: 'Community',
19+
items: [
20+
{
21+
icon: <QuestionCircleOutlined />,
22+
label: 'Stack Overflow',
23+
url: 'https://stackoverflow.com/questions/tagged/vite-plugin-react-pages',
24+
},
25+
{
26+
icon: <BugOutlined />,
27+
label: 'Help',
28+
url: 'https://github.com/vitejs/vite-plugin-react-pages/issues',
29+
},
30+
],
31+
},
32+
{
33+
icon: <LinkOutlined />,
34+
title: 'Resources',
35+
items: [
36+
{
37+
icon: <img src="https://vitejs.dev/logo.svg" alt="vite" />,
38+
label: 'Vite',
39+
url: 'https://vitejs.dev/',
40+
},
41+
{
42+
icon: <GithubFilled />,
43+
label: 'GitHub',
44+
url: 'https://github.com/vitejs/vite-plugin-react-pages',
45+
},
46+
],
47+
},
48+
],
49+
},
50+
zh: {
51+
message: `2020 - ${new Date().getFullYear()}`,
52+
copyright: '以 MIT 许可证发布',
53+
columns: [
54+
{
55+
title: '社区',
56+
items: [
57+
{
58+
label: 'Stack Overflow',
59+
url: 'https://stackoverflow.com/questions/tagged/vite-plugin-react-pages',
60+
},
61+
{
62+
label: '帮助',
63+
url: 'https://github.com/vitejs/vite-plugin-react-pages/issues',
64+
},
65+
],
66+
},
67+
{
68+
title: '更多',
69+
items: [
70+
{
71+
label: 'Vite',
72+
url: 'https://vitejs.dev/',
73+
},
74+
{
75+
label: 'GitHub',
76+
url: 'https://github.com/vitejs/vite-plugin-react-pages',
77+
},
78+
],
79+
},
80+
],
81+
},
82+
}

packages/playground/use-theme-doc/pages/_theme.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Button } from 'antd'
44
import Component404 from './404'
55
import { topNavsConfig } from './themeConfig/topNavs'
66
import { sideNavsConfig } from './themeConfig/sideNavs'
7+
import { footerConfig } from './themeConfig/footer'
78

89
export default createTheme({
910
i18n: {
@@ -50,6 +51,9 @@ export default createTheme({
5051
} = ctx
5152
return defaultSideNavs(ctx, sideNavsConfig[localeKey!])
5253
},
54+
footer: ({ resolvedLocale: { localeKey } }) => {
55+
return footerConfig[localeKey!]
56+
},
5357
Component404,
5458
})
5559

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React from 'react'
2+
import type { FooterConfig } from '../themeDev'
3+
import {
4+
QuestionCircleOutlined,
5+
BugOutlined,
6+
GithubFilled,
7+
TeamOutlined,
8+
LinkOutlined,
9+
} from '@ant-design/icons'
10+
11+
export const footerConfig: { [locale: string]: FooterConfig } = {
12+
en: {
13+
message: `2020 - ${new Date().getFullYear()}`,
14+
copyright: 'Released under the MIT License.',
15+
columns: [
16+
{
17+
icon: <TeamOutlined />,
18+
title: 'Community',
19+
items: [
20+
{
21+
icon: <QuestionCircleOutlined />,
22+
label: 'Stack Overflow',
23+
url: 'https://stackoverflow.com/questions/tagged/vite-plugin-react-pages',
24+
},
25+
{
26+
icon: <BugOutlined />,
27+
label: 'Help',
28+
url: 'https://github.com/vitejs/vite-plugin-react-pages/issues',
29+
},
30+
],
31+
},
32+
{
33+
icon: <LinkOutlined />,
34+
title: 'Resources',
35+
items: [
36+
{
37+
icon: <img src="https://vitejs.dev/logo.svg" alt="vite" />,
38+
label: 'Vite',
39+
url: 'https://vitejs.dev/',
40+
},
41+
{
42+
icon: <GithubFilled />,
43+
label: 'GitHub',
44+
url: 'https://github.com/vitejs/vite-plugin-react-pages',
45+
},
46+
],
47+
},
48+
],
49+
},
50+
zh: {
51+
// test dark theme
52+
theme: 'dark',
53+
message: `2020 - ${new Date().getFullYear()}`,
54+
copyright: '以 MIT 许可证发布',
55+
columns: [
56+
{
57+
title: '社区',
58+
items: [
59+
{
60+
label: 'Stack Overflow',
61+
url: 'https://stackoverflow.com/questions/tagged/vite-plugin-react-pages',
62+
},
63+
{
64+
label: '帮助',
65+
url: 'https://github.com/vitejs/vite-plugin-react-pages/issues',
66+
},
67+
],
68+
},
69+
{
70+
title: '更多',
71+
items: [
72+
{
73+
label: 'Vite',
74+
url: 'https://vitejs.dev/',
75+
},
76+
{
77+
label: 'GitHub',
78+
url: 'https://github.com/vitejs/vite-plugin-react-pages',
79+
},
80+
],
81+
},
82+
],
83+
},
84+
}

packages/theme-doc/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"less": "^4.1.3",
5555
"postcss": "^8.4.16",
5656
"prism-react-renderer": "^1.3.5",
57+
"rc-footer": "^0.6.6",
5758
"rimraf": "^3.0.2",
5859
"rollup": "^2.79.0",
5960
"rollup-plugin-postcss": "^4.0.0",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@import 'rc-footer/assets/index.less';
2+
3+
@footer-prefix-cls: footer;
4+
5+
.@{footer-prefix-cls} {
6+
font-size: 16px;
7+
8+
a {
9+
&:hover {
10+
text-decoration: underline;
11+
}
12+
}
13+
14+
&-container {
15+
padding: 32px 0 20px;
16+
}
17+
18+
&-column {
19+
margin-bottom: 20px;
20+
&-icon {
21+
margin-right: 0.4em;
22+
width: auto;
23+
}
24+
}
25+
26+
// theme style
27+
28+
&.theme-dark {
29+
color: rgb(235, 237, 240);
30+
background-color: #2b3137;
31+
a {
32+
color: rgb(235, 237, 240);
33+
}
34+
}
35+
36+
&.theme-light {
37+
border-top: 1px solid rgba(60, 60, 60, 0.12);
38+
background-color: rgb(246, 248, 248);
39+
40+
.@{footer-prefix-cls}-bottom {
41+
&-container {
42+
border-top: none;
43+
}
44+
}
45+
}
46+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import React, { useContext, useMemo } from 'react'
2+
import RcFooter from 'rc-footer'
3+
4+
import { themeConfigCtx, useThemeCtx } from '../ctx'
5+
import s from './Footer.module.less'
6+
7+
export type FooterLink = {
8+
/**
9+
* Text to be displayed for this link.
10+
*/
11+
label: string
12+
/**
13+
* navigating to other websites
14+
*/
15+
url: string
16+
/**
17+
* link target would be `_blank` if `openExternal` is ture
18+
* @default true
19+
*/
20+
openExternal?: boolean
21+
/**
22+
* icon that before link label
23+
*/
24+
icon?: React.ReactNode
25+
/**
26+
* description of column, come after title
27+
*/
28+
description?: React.ReactNode
29+
}
30+
31+
export type FooterColumn = {
32+
/**
33+
* Label of the section of these links.
34+
*/
35+
title?: React.ReactNode
36+
/**
37+
* icon that before column title
38+
*/
39+
icon?: React.ReactNode
40+
/**
41+
* Links in this section.
42+
*/
43+
items?: Array<FooterLink>
44+
}
45+
46+
export type FooterConfig = {
47+
/**
48+
* The link groups to be present.
49+
*/
50+
columns?: Array<FooterColumn>
51+
/**
52+
* The message to be displayed at the bottom.
53+
*/
54+
message?: React.ReactNode
55+
/**
56+
* The copyright message to be displayed at the bottom.
57+
*/
58+
copyright?: React.ReactNode
59+
/**
60+
* Footer theme preset
61+
* @default 'light'
62+
*/
63+
theme?: 'light' | 'dark'
64+
}
65+
66+
/**
67+
* adapter for FooterLink that
68+
* replace `label` field with
69+
* `title` to adapt RcFooter' props
70+
*/
71+
const replaceLabelWithTitle = (columns: FooterColumn[]) => {
72+
return columns.map((col) => ({
73+
title: col.title,
74+
icon: col.icon,
75+
items: col.items?.map((i) => ({
76+
title: i.label,
77+
url: i.url,
78+
openExternal: i.openExternal === false ? false : true,
79+
icon: i.icon,
80+
description: i.description,
81+
})),
82+
}))
83+
}
84+
85+
export const Footer = () => {
86+
const themeConfig = useContext(themeConfigCtx)
87+
const themeCtxValue = useThemeCtx()
88+
89+
const resolvedFooterConfig = useMemo(() => {
90+
if (typeof themeConfig.footer === 'function') {
91+
return themeConfig.footer(themeCtxValue)
92+
}
93+
return themeConfig.footer
94+
}, [themeCtxValue])
95+
96+
if (!resolvedFooterConfig) {
97+
return null
98+
}
99+
100+
const {
101+
message,
102+
copyright,
103+
columns = [],
104+
theme = 'light',
105+
} = resolvedFooterConfig
106+
107+
const themeCls = theme === 'dark' ? s['theme-dark'] : s['theme-light']
108+
109+
return (
110+
<RcFooter
111+
theme={theme}
112+
bottom={
113+
<>
114+
{message ? <div>{message}</div> : null}
115+
{copyright ? <div>{copyright}</div> : null}
116+
</>
117+
}
118+
columns={replaceLabelWithTitle(columns)}
119+
columnLayout="space-around"
120+
className={`${s.footer} ${themeCls}`}
121+
prefixCls={s.footer}
122+
/>
123+
)
124+
}

packages/theme-doc/src/Layout/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { themeConfigCtx } from '../ctx'
1111
export { default as MDX } from './MDX'
1212
import { useThemeCtx } from '..'
1313
import { LayoutContext } from './ctx'
14+
import { Footer } from './Footer'
1415

1516
ConfigProvider.config({
1617
prefixCls: 'vp-antd',
@@ -57,6 +58,7 @@ const AppLayout: React.FC<Props> = ({ children }) => {
5758
)}
5859
<div className={s.content}>{children}</div>
5960
</div>
61+
<Footer />
6062
</div>
6163
</LayoutContext.Provider>
6264
</ConfigProvider>

0 commit comments

Comments
 (0)