diff --git a/site/theme/static/dark.less b/site/theme/static/dark.less
index b76ae999f7..6351c82670 100644
--- a/site/theme/static/dark.less
+++ b/site/theme/static/dark.less
@@ -353,4 +353,13 @@
.token.strong {
font-weight: bold;
}
+
+ .components-overview {
+ &-img {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ &-search input {
+ color: rgba(255, 255, 255, 0.65);
+ }
+ }
}
diff --git a/site/theme/template/Content/ComponentOverview.jsx b/site/theme/template/Content/ComponentOverview.jsx
index a0db795fe8..841fa0745b 100644
--- a/site/theme/template/Content/ComponentOverview.jsx
+++ b/site/theme/template/Content/ComponentOverview.jsx
@@ -34,6 +34,7 @@ const ComponentOverview = ({
meta: { title },
content,
},
+ location,
utils: { toReactComponent },
}) => {
const { locale, formatMessage } = useIntl();
@@ -103,7 +104,7 @@ const ComponentOverview = ({
const url = `${component.filename
.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '')
.toLowerCase()}/`;
- const href = getLocalizedPathname(url, locale === 'zh-CN');
+ const href = getLocalizedPathname(url, locale === 'zh-CN', location.query);
return (
onClickCard(href)}>
diff --git a/site/theme/template/Content/MainContent.jsx b/site/theme/template/Content/MainContent.jsx
index b16c2bd5e7..9acbf1f3a9 100644
--- a/site/theme/template/Content/MainContent.jsx
+++ b/site/theme/template/Content/MainContent.jsx
@@ -1,5 +1,5 @@
import React, { Component } from 'react';
-import { Link } from 'bisheng/router';
+import { Link, browserHistory } from 'bisheng/router';
import { Row, Col, Menu, Affix, Tooltip, Avatar, Dropdown } from 'antd';
import { injectIntl } from 'react-intl';
import { LeftOutlined, RightOutlined, ExportOutlined } from '@ant-design/icons';
@@ -230,6 +230,7 @@ class MainContent extends Component {
generateMenuItem(isTop, item, { before = null, after = null }) {
const {
intl: { locale },
+ location,
} = this.props;
const key = fileNameToPath(item.filename);
if (!item.title) {
@@ -246,11 +247,13 @@ class MainContent extends Component {
];
const { disabled } = item;
const url = item.filename.replace(/(\/index)?((\.zh-cn)|(\.en-us))?\.md$/i, '').toLowerCase();
+
const child = !item.link ? (
@@ -312,8 +315,19 @@ class MainContent extends Component {
changeThemeMode = theme => {
const { setTheme, theme: selectedTheme } = this.context;
+ const { pathname, hash, query } = this.props.location;
if (selectedTheme !== theme) {
setTheme(theme);
+ if (theme === 'default') {
+ delete query.theme;
+ } else {
+ query.theme = theme;
+ }
+ browserHistory.push({
+ pathname: `/${pathname}`,
+ query,
+ hash,
+ });
}
};
@@ -438,7 +452,7 @@ class MainContent extends Component {
)}
-
+
diff --git a/site/theme/template/Home/Banner/index.tsx b/site/theme/template/Home/Banner/index.tsx
index 327a00459d..63b3f509b2 100644
--- a/site/theme/template/Home/Banner/index.tsx
+++ b/site/theme/template/Home/Banner/index.tsx
@@ -10,7 +10,8 @@ import Logo from './Logo';
import './index.less';
import SiteContext from '../../Layout/SiteContext';
-export default function Banner() {
+const Banner = (props: { location: any }) => {
+ const { location } = props;
const { isMobile } = React.useContext(SiteContext);
const { locale } = useIntl();
const isZhCN = locale === 'zh-CN';
@@ -74,12 +75,12 @@ export default function Banner() {
{isZhCN && {qrNode}
}
-
+
-
+
@@ -89,4 +90,6 @@ export default function Banner() {
);
-}
+};
+
+export default Banner;
diff --git a/site/theme/template/Home/DesignPage/index.tsx b/site/theme/template/Home/DesignPage/index.tsx
index c153676a8e..cda11c7fb3 100644
--- a/site/theme/template/Home/DesignPage/index.tsx
+++ b/site/theme/template/Home/DesignPage/index.tsx
@@ -68,7 +68,8 @@ const MiniPanel = ({
href,
link,
isZhCN,
-}: PanelProps & { isZhCN: boolean }) => {
+ query,
+}: PanelProps & { isZhCN: boolean } & { query: object }) => {
let content = (
);
} else if (link) {
- content = {content};
+ content = {content};
}
return (
@@ -96,7 +97,8 @@ const MiniPanel = ({
);
};
-export default function DesignPage() {
+const DesignPage = (props: { location: any }) => {
+ const { location } = props;
const { locale } = useIntl();
const isZhCN = locale === 'zh-CN';
const { direction } = React.useContext(SiteContext);
@@ -123,7 +125,7 @@ export default function DesignPage() {
{IconComponent}
@@ -195,13 +197,13 @@ export default function DesignPage() {
-
-
+
{IconComponent}
-
-
+
{IconComponent}
@@ -242,7 +244,9 @@ export default function DesignPage() {
-
-
+
Ant Design of React
{IconComponent}
@@ -284,9 +288,11 @@ export default function DesignPage() {
className="design-mini-panels"
>
{MINI_LIST.map(panel => (
-
+
))}
);
-}
+};
+
+export default DesignPage;
diff --git a/site/theme/template/Home/index.tsx b/site/theme/template/Home/index.tsx
index ae3de951b9..7b3a16fd19 100644
--- a/site/theme/template/Home/index.tsx
+++ b/site/theme/template/Home/index.tsx
@@ -42,33 +42,42 @@ const BlockContent: React.FC = ({ title, children, extra }) =
);
-export default function Home() {
+const Home = (props: { location: any }) => {
+ const { location } = props;
const { locale } = useIntl();
const isZhCN = locale === 'zh-CN';
+ const getLink = () => {
+ const path = getLocalizedPathname('/docs/resources', isZhCN, location.query, {
+ zhCN: '文章',
+ enUS: 'Articles',
+ });
+ const { pathname, query } = path;
+ const pathnames = pathname.split('#');
+ if ('direction' in query) {
+ return `${pathnames[0]}?direction=rtl#${pathnames[1]}`;
+ }
+ return path;
+ };
+
return (
-
+
}>
}>
-
+
{isZhCN ? (
}
extra={
-
+
}
@@ -77,7 +86,9 @@ export default function Home() {
) : null}
-
+
);
-}
+};
+
+export default Home;
diff --git a/site/theme/template/Layout/Footer.tsx b/site/theme/template/Layout/Footer.tsx
index 1aef2e3a27..ba70e72c3e 100644
--- a/site/theme/template/Layout/Footer.tsx
+++ b/site/theme/template/Layout/Footer.tsx
@@ -22,7 +22,7 @@ import {
import { isLocalStorageNameSupported, loadScript, getLocalizedPathname } from '../utils';
import ColorPicker from '../Color/ColorPicker';
-class Footer extends React.Component {
+class Footer extends React.Component {
lessLoaded = false;
state = {
@@ -47,9 +47,29 @@ class Footer extends React.Component {
}
getColumns() {
- const { intl } = this.props;
+ const { intl, location } = this.props;
+
const isZhCN = intl.locale === 'zh-CN';
+ const getLinkHash = (path: string, hash: { zhCN: string; enUS: string }) => {
+ const pathName = getLocalizedPathname(path, isZhCN, location.query, hash);
+ const { pathname, query } = pathName;
+ const pathnames = pathname.split('#');
+ if ('direction' in query) {
+ return `${pathnames[0]}?direction=rtl#${pathnames[1]}`;
+ }
+ return pathname;
+ };
+
+ const getLink = (path: string) => {
+ const pathName = getLocalizedPathname(path, isZhCN, location.query);
+ const { pathname, query } = pathName;
+ if ('direction' in query) {
+ return `${pathname}?direction=rtl}`;
+ }
+ return pathname;
+ };
+
const col1 = {
title: ,
items: [
@@ -128,7 +148,7 @@ class Footer extends React.Component {
},
{
title: ,
- url: getLocalizedPathname('/docs/resources', isZhCN, {
+ url: getLinkHash('/docs/resources', {
zhCN: '设计资源',
enUS: 'Design-Resources',
}),
@@ -193,7 +213,7 @@ class Footer extends React.Component {
col2.items.push({
icon: ,
title: ,
- url: getLocalizedPathname('/docs/resources', isZhCN, {
+ url: getLinkHash('/docs/resources', {
zhCN: '加入我们',
enUS: 'JoinUs',
}),
@@ -213,13 +233,13 @@ class Footer extends React.Component {
{
icon: ,
title: ,
- url: getLocalizedPathname('/changelog', isZhCN),
+ url: getLink('/changelog'),
LinkComponent: Link,
},
{
icon: ,
title: ,
- url: getLocalizedPathname('/docs/react/faq', isZhCN),
+ url: getLink('/docs/react/faq'),
LinkComponent: Link,
},
{
diff --git a/site/theme/template/Layout/Header/Logo.tsx b/site/theme/template/Layout/Header/Logo.tsx
index 47ce1fbe34..9fa4a7f6af 100644
--- a/site/theme/template/Layout/Header/Logo.tsx
+++ b/site/theme/template/Layout/Header/Logo.tsx
@@ -1,15 +1,23 @@
import * as React from 'react';
import { Link } from 'bisheng/router';
import * as utils from '../../utils';
-import { SharedProps } from './interface';
import './Logo.less';
-export default ({ isZhCN }: SharedProps) => (
-
-
-
- Ant Design
-
-
-);
+export interface LogoProps {
+ isZhCN: boolean;
+ location: any;
+}
+
+const Logo = ({ isZhCN, location }: LogoProps) => {
+ return (
+
+
+
+ Ant Design
+
+
+ );
+};
+
+export default Logo;
diff --git a/site/theme/template/Layout/Header/Navigation.tsx b/site/theme/template/Layout/Header/Navigation.tsx
index 7cc3c0d163..1914bc14dd 100644
--- a/site/theme/template/Layout/Header/Navigation.tsx
+++ b/site/theme/template/Layout/Header/Navigation.tsx
@@ -15,7 +15,7 @@ export interface NavigationProps extends SharedProps {
isRTL: boolean;
pathname: string;
responsive: null | 'narrow' | 'crowded';
- location: { pathname: string };
+ location: { pathname: string; query: any };
directionText: string;
onLangChange: () => void;
onDirectionChange: () => void;
@@ -81,22 +81,22 @@ export default ({
id="nav"
>
-
+
-
+
-
+
-
+
diff --git a/site/theme/template/Layout/Header/index.tsx b/site/theme/template/Layout/Header/index.tsx
index 1d308b13eb..3a33558099 100644
--- a/site/theme/template/Layout/Header/index.tsx
+++ b/site/theme/template/Layout/Header/index.tsx
@@ -51,7 +51,7 @@ export interface HeaderProps {
intl: {
locale: string;
};
- location: { pathname: string };
+ location: { pathname: string; query: any };
router: any;
themeConfig: { docVersions: Record };
changeDirection: (direction: string) => void;
@@ -158,7 +158,7 @@ class Header extends React.Component {
onLangChange = () => {
const {
- location: { pathname },
+ location: { pathname, query },
} = this.props;
const currentProtocol = `${window.location.protocol}//`;
const currentHref = window.location.href.substr(currentProtocol.length);
@@ -171,7 +171,7 @@ class Header extends React.Component {
currentProtocol +
currentHref.replace(
window.location.pathname,
- utils.getLocalizedPathname(pathname, !utils.isZhCN(pathname)),
+ utils.getLocalizedPathname(pathname, !utils.isZhCN(pathname), query).pathname,
);
};
@@ -316,7 +316,7 @@ class Header extends React.Component {
)}
-
+
{searchBox}
diff --git a/site/theme/template/Layout/index.jsx b/site/theme/template/Layout/index.jsx
index 7e32e5dd0f..719c984dca 100644
--- a/site/theme/template/Layout/index.jsx
+++ b/site/theme/template/Layout/index.jsx
@@ -10,6 +10,7 @@ import 'moment/locale/zh-cn';
import { ConfigProvider } from 'antd';
import LogRocket from 'logrocket';
import setupLogRocketReact from 'logrocket-react';
+import { browserHistory } from 'bisheng/router';
// eslint-disable-next-line import/no-unresolved
import zhCN from 'antd/es/locale/zh_CN';
import Header from './Header';
@@ -57,7 +58,6 @@ if (typeof window !== 'undefined') {
}
const RESPONSIVE_MOBILE = 768;
-const SITE_THEME_STORE_KEY = 'site-theme';
// for dark.css timestamp to remove cache
const timestamp = new Date().getTime();
@@ -73,6 +73,8 @@ const { switcher } = themeSwitcher(themeConfig);
export default class Layout extends React.Component {
static contextType = SiteContext;
+ isBeforeComponent = false;
+
constructor(props) {
super(props);
const { pathname } = props.location;
@@ -80,10 +82,7 @@ export default class Layout extends React.Component {
this.state = {
appLocale,
- theme:
- typeof localStorage !== 'undefined'
- ? localStorage.getItem(SITE_THEME_STORE_KEY) || 'default'
- : 'default',
+ theme: 'default',
setTheme: this.setTheme,
direction: 'ltr',
setIframeTheme: this.setIframeTheme,
@@ -91,25 +90,46 @@ export default class Layout extends React.Component {
}
componentDidMount() {
- const { theme } = this.state;
const { location, router } = this.props;
- router.listen(loc => {
+ router.listen(({ pathname, search }) => {
+ const { theme } = this.props.location.query;
if (typeof window.ga !== 'undefined') {
- window.ga('send', 'pageview', loc.pathname + loc.search);
+ window.ga('send', 'pageview', pathname + search);
}
// eslint-disable-next-line
if (typeof window._hmt !== 'undefined') {
// eslint-disable-next-line
- window._hmt.push(['_trackPageview', loc.pathname + loc.search]);
+ window._hmt.push(['_trackPageview', pathname + search]);
}
- const { pathname } = loc;
const componentPage = /^\/?components/.test(pathname);
+
// only component page can use `dark` theme
if (!componentPage) {
+ this.isBeforeComponent = false;
this.setTheme('default', false);
+ } else if (theme && !this.isBeforeComponent) {
+ this.isBeforeComponent = true;
+ this.setTheme(theme, false);
}
});
- this.setTheme(/^\/?components/.test(location.pathname) ? theme : 'default');
+
+ if (location.query.theme && /^\/?components/.test(location.pathname)) {
+ this.isBeforeComponent = true;
+ this.setTheme(location.query.theme, false);
+ } else {
+ this.isBeforeComponent = false;
+ this.setTheme('default', false);
+ }
+
+ if (location.query.direction) {
+ this.setState({
+ direction: location.query.direction,
+ });
+ } else {
+ this.setState({
+ direction: 'ltr',
+ });
+ }
const nprogressHiddenStyle = document.getElementById('nprogress-style');
if (nprogressHiddenStyle) {
@@ -180,6 +200,17 @@ export default class Layout extends React.Component {
this.setState({
direction,
});
+ const { pathname, hash, query } = this.props.location;
+ if (direction === 'ltr') {
+ delete query.direction;
+ } else {
+ query.direction = 'rtl';
+ }
+ browserHistory.push({
+ pathname: `/${pathname}`,
+ query,
+ hash,
+ });
};
render() {
diff --git a/site/theme/template/NotFound.tsx b/site/theme/template/NotFound.tsx
index d5924253e7..52bbb2438f 100644
--- a/site/theme/template/NotFound.tsx
+++ b/site/theme/template/NotFound.tsx
@@ -39,7 +39,7 @@ export default function NotFound(props: NotFoundProps) {
for (let i = 0; i < directLinks.length; i += 1) {
const matchPath = directLinks[i];
if (pathname.includes(matchPath)) {
- router.replace(utils.getLocalizedPathname(`/${DIRECT_MAP[matchPath]}`, isZhCN));
+ router.replace(utils.getLocalizedPathname(`/${DIRECT_MAP[matchPath]}`, isZhCN).pathname);
}
}
}, []);
diff --git a/site/theme/template/Resources/index.tsx b/site/theme/template/Resources/index.tsx
index 7e5efeb480..232214176c 100644
--- a/site/theme/template/Resources/index.tsx
+++ b/site/theme/template/Resources/index.tsx
@@ -30,6 +30,7 @@ interface PagesData {
interface ResourcesProps {
location: {
pathname: string;
+ query: object;
};
data: PagesData;
localizedPageData: PageData;
@@ -116,7 +117,7 @@ function injectCards(content: ContentUnit[]): ContentUnit[] {
}
const Resources = (props: ResourcesProps) => {
- const { localizedPageData } = props;
+ const { localizedPageData, location } = props;
const { locale } = useIntl();
const content = React.useMemo(() => injectCards(localizedPageData.content), [
@@ -137,7 +138,7 @@ const Resources = (props: ResourcesProps) => {
titleRegionClassName="title-region"
/>
-
+
);
};
diff --git a/site/theme/template/utils.tsx b/site/theme/template/utils.tsx
index 9ff0aeccdc..e16f334222 100644
--- a/site/theme/template/utils.tsx
+++ b/site/theme/template/utils.tsx
@@ -118,6 +118,7 @@ export function isZhCN(pathname: string) {
export function getLocalizedPathname(
path: string,
zhCN?: boolean,
+ query = {},
hash?: {
zhCN: string;
enUS: string;
@@ -141,7 +142,7 @@ export function getLocalizedPathname(
fullPath += `#${localHash}`;
}
- return fullPath;
+ return { pathname: fullPath, query };
}
export function ping(callback: (status: string) => void) {