Skip to content

Commit 2b98c82

Browse files
committed
chore: add docs
1 parent e1b483d commit 2b98c82

29 files changed

Lines changed: 633 additions & 49 deletions

File tree

.stylelintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
/coverage
44
/.yarn
55
/packages/site/dist
6+
/packages/site/src/app/routes

packages/icons/Icon.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ function renderAbstractNode(node: AbstractNode, options: DRenderIconOptions): JS
3333

3434
export interface DIconContextData {
3535
props?: Omit<DIconProps, 'dIcon'>;
36-
prefix: string;
36+
namespace: string;
3737
twoToneColor: (theme?: DIconProps['dTheme']) => [string, string];
3838
}
3939
export const DIconContext = React.createContext<DIconContextData>({
40-
prefix: 'd-',
40+
namespace: 'd',
4141
twoToneColor: (theme) => [
4242
theme ? `var(--d-color-${theme})` : `var(--d-text-color)`,
4343
theme ? `var(--d-background-color-${theme})` : `rgb(var(--d-text-color-rgb) / 10%)`,
@@ -61,7 +61,7 @@ export function DIcon(props: DIconProps): JSX.Element | null {
6161
const twoToneColorByTheme = useContext(DIconContext).twoToneColor;
6262
const twoToneColor = dTwoToneColor ?? twoToneColorByTheme(dTheme);
6363

64-
const svgProps = useIconDefinition(restProps);
64+
const svgProps = useIconDefinition({ ...restProps, dTheme });
6565

6666
return renderIconDefinition(dIcon, {
6767
placeholders: {

packages/icons/useIconDefinition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function useIconDefinition(props: DIconBaseProps) {
2424
...restProps
2525
} = props;
2626

27-
const prefix = useContext(DIconContext).prefix;
27+
const prefix = `${useContext(DIconContext).namespace}-`;
2828

2929
const svgProps: React.SVGAttributes<SVGElement> = {
3030
...restProps,

packages/site/src/app/components/layout/Layout.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import { useState } from 'react';
1+
import { useEffect, useState } from 'react';
2+
import { useLocation } from 'react-router-dom';
23

34
import { AppHeader } from './header';
45
import { AppSidebar } from './sidebar';
56

67
export function AppLayout() {
78
const [menuOpen, setMenuOpen] = useState(false);
89

10+
const location = useLocation();
11+
12+
useEffect(() => {
13+
setMenuOpen(false);
14+
}, [location]);
15+
916
return (
1017
<>
1118
<AppHeader aMenuOpen={menuOpen} onMenuOpenChange={setMenuOpen} />

packages/site/src/app/components/layout/header/Header.scss

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,41 @@
8080
@include font-size(1.5rem);
8181
}
8282

83+
.app-header__menu {
84+
min-width: unset;
85+
height: 100%;
86+
margin-right: 20px;
87+
88+
&::after {
89+
content: none;
90+
}
91+
92+
.d-menu__item--horizontal {
93+
height: 100%;
94+
95+
&::after {
96+
top: -8px;
97+
bottom: unset;
98+
}
99+
}
100+
101+
a {
102+
font: inherit;
103+
color: inherit;
104+
text-decoration: none;
105+
106+
&::after {
107+
position: absolute;
108+
inset: 0;
109+
content: '';
110+
}
111+
112+
&.disabled {
113+
pointer-events: none;
114+
}
115+
}
116+
}
117+
83118
.app-header__button-container {
84119
display: inline-flex;
85120
gap: 0 8px;

packages/site/src/app/components/layout/header/Header.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useTranslation } from 'react-i18next';
2+
import { Link, useLocation } from 'react-router-dom';
23

34
import { DCustomIcon, GithubOutlined } from '@react-devui/icons';
4-
import { useMediaMatch } from '@react-devui/ui';
5+
import { DMenu, useMediaMatch } from '@react-devui/ui';
56
import { useContextRequired } from '@react-devui/ui/hooks';
67
import { getClassName } from '@react-devui/utils';
78

@@ -17,6 +18,9 @@ export function AppHeader(props: { aMenuOpen: boolean; onMenuOpenChange: (open:
1718

1819
const mediaMatch = useMediaMatch();
1920

21+
const location = useLocation();
22+
const activeId = location.pathname.startsWith('/docs') ? 'docs' : location.pathname.startsWith('/components') ? 'components' : null;
23+
2024
const switchLang =
2125
i18n.language === 'en-US'
2226
? {
@@ -52,7 +56,33 @@ export function AppHeader(props: { aMenuOpen: boolean; onMenuOpenChange: (open:
5256
</div>
5357
</button>
5458
)}
55-
59+
{mediaMatch.includes('md') && (
60+
<DMenu
61+
className="app-header__menu"
62+
dList={[
63+
{
64+
id: 'docs',
65+
title: (
66+
<Link className={activeId === 'docs' ? 'disabled' : undefined} to="/docs/Overview">
67+
{t('Docs')}
68+
</Link>
69+
),
70+
type: 'item',
71+
},
72+
{
73+
id: 'components',
74+
title: (
75+
<Link className={activeId === 'components' ? 'disabled' : undefined} to="/components/Button">
76+
{t('Components')}
77+
</Link>
78+
),
79+
type: 'item',
80+
},
81+
]}
82+
dMode="horizontal"
83+
dActive={activeId}
84+
></DMenu>
85+
)}
5686
<div className="app-header__button-container">
5787
<button
5888
className="app-header__button app-header__button--language"

packages/site/src/app/components/layout/sidebar/Sidebar.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,18 @@
5353
}
5454
}
5555
}
56+
57+
.app-sidebar__link-button {
58+
display: flex;
59+
gap: 0 4px;
60+
align-items: center;
61+
justify-content: center;
62+
height: 46px;
63+
margin: 20px 16px 10px;
64+
font: inherit;
65+
color: inherit;
66+
text-decoration: none;
67+
border: 1px solid var(--d-color-border);
68+
/* stylelint-disable-next-line declaration-property-value-allowed-list */
69+
border-radius: 10px;
70+
}

packages/site/src/app/components/layout/sidebar/Sidebar.tsx

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import menu from 'packages/site/dist/menu.json';
66
import { useTranslation } from 'react-i18next';
77
import { Link, useLocation } from 'react-router-dom';
88

9+
import { AppstoreOutlined, BookOutlined } from '@react-devui/icons';
910
import { DDrawer, DMenu, useMediaMatch } from '@react-devui/ui';
1011

1112
import './Sidebar.scss';
@@ -16,34 +17,57 @@ export function AppSidebar(props: { aMenuOpen: boolean; onMenuOpenChange: (open:
1617
const { t, i18n } = useTranslation();
1718

1819
const location = useLocation();
19-
const page = location.pathname.startsWith('/components/') ? 'Components' : 'Components';
20-
const activeId = location.pathname.match(/(?<=^\/components\/).+$/)?.[0] ?? null;
20+
const page = location.pathname.startsWith('/docs') ? 'Docs' : location.pathname.startsWith('/components') ? 'Components' : null;
21+
const regex = new RegExp(String.raw`(?<=^\/${page === 'Docs' ? 'docs' : 'components'}\/).+$`);
22+
const activeId = location.pathname.match(regex)?.[0] ?? null;
2123

2224
const menuNode = (
2325
<DMenu
2426
className="app-sidebar__menu"
25-
dList={menu.map<DNestedChildren<DMenuItem<string> & { to?: string }>>((group) => ({
26-
id: group.title,
27-
title: t(`menu.components-group.${group.title}`),
28-
type: 'group',
29-
children: (group.title === 'Other'
30-
? group.children.concat([{ title: 'Interface', to: '/components/Interface' }])
31-
: group.children
32-
).map((child) => ({
33-
id: child.title,
34-
title: (
35-
<Link to={child.to}>
36-
{child.title}
37-
{i18n.language !== 'en-US' && <span className="app-sidebar__subtitle">{t(`menu.components.${child.title}`)}</span>}
38-
</Link>
39-
),
40-
type: 'item',
41-
})),
42-
}))}
27+
dList={
28+
page === 'Docs'
29+
? [
30+
{
31+
id: 'Overview',
32+
title: <Link to="/docs/Overview">{t('docs-menu.Overview')}</Link>,
33+
type: 'item',
34+
},
35+
{
36+
id: 'GettingStarted',
37+
title: <Link to="/docs/GettingStarted">{t('docs-menu.Getting Started')}</Link>,
38+
type: 'item',
39+
},
40+
{
41+
id: 'DynamicTheme',
42+
title: <Link to="/docs/DynamicTheme">{t('docs-menu.Dynamic Theme')}</Link>,
43+
type: 'item',
44+
},
45+
{
46+
id: 'Internationalization',
47+
title: <Link to="/docs/Internationalization">{t('docs-menu.Internationalization')}</Link>,
48+
type: 'item',
49+
},
50+
]
51+
: menu.map<DNestedChildren<DMenuItem<string> & { to?: string }>>((group) => ({
52+
id: group.title,
53+
title: t(`menu.components-group.${group.title}`),
54+
type: 'group',
55+
children: (group.title === 'Other'
56+
? group.children.concat([{ title: 'Interface', to: '/components/Interface' }])
57+
: group.children
58+
).map((child) => ({
59+
id: child.title,
60+
title: (
61+
<Link to={child.to}>
62+
{child.title}
63+
{i18n.language !== 'en-US' && <span className="app-sidebar__subtitle">{t(`menu.components.${child.title}`)}</span>}
64+
</Link>
65+
),
66+
type: 'item',
67+
})),
68+
}))
69+
}
4370
dActive={activeId}
44-
onActiveChange={() => {
45-
onMenuOpenChange(false);
46-
}}
4771
></DMenu>
4872
);
4973

@@ -64,6 +88,10 @@ export function AppSidebar(props: { aMenuOpen: boolean; onMenuOpenChange: (open:
6488
dWidth={280}
6589
onVisibleChange={onMenuOpenChange}
6690
>
91+
<Link className="app-sidebar__link-button" to={page === 'Docs' ? '/components/Button' : '/docs/Overview'}>
92+
{page === 'Docs' ? <AppstoreOutlined /> : <BookOutlined />}
93+
{t(page === 'Docs' ? 'Components' : 'Docs')}
94+
</Link>
6795
{menuNode}
6896
</DDrawer>
6997
);

packages/site/src/app/components/route/RouteArticle.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { DTransitionState } from '@react-devui/ui/components/_transition';
22

33
import { isString, isUndefined } from 'lodash';
44
import { useEffect, useLayoutEffect, useState } from 'react';
5+
import { useTranslation } from 'react-i18next';
56

67
import { useImmer } from '@react-devui/hooks';
78
import { DCustomIcon } from '@react-devui/icons';
@@ -21,6 +22,7 @@ export interface AppRouteArticleProps {
2122
export function AppRouteArticle(props: AppRouteArticleProps) {
2223
const html = props.html ? marked(toString(props.html)) : undefined;
2324

25+
const { i18n } = useTranslation();
2426
const mediaMatch = useMediaMatch();
2527

2628
const [_links, setLinks] = useImmer<{ title: string; href: string }[]>([]);
@@ -63,7 +65,7 @@ m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,
6365
setLinks(arr);
6466
}
6567
// eslint-disable-next-line react-hooks/exhaustive-deps
66-
}, []);
68+
}, [i18n.language]);
6769

6870
useEffect(() => {
6971
if (isString(html)) {

packages/site/src/app/i18n/i18n.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ i18n
1111
.use(initReactI18next) // passes i18n down to react-i18next
1212
.init({
1313
resources,
14-
lng: localStorage.getItem('language') ?? 'zh-Hant', // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
14+
lng: localStorage.getItem('language') ?? 'en-US', // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
1515
// you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
1616
// if you're using a language detector, do not define the lng option
1717

0 commit comments

Comments
 (0)