docs: components and documentation in two pages (#20330)

* 📝 Add documentation in header nav

* site: fix header active item and menu items

* 💄 better components menu group style

* 💄 more details of site menu style

*  fix eslint error
This commit is contained in:
偏右 2019-12-19 14:47:12 +08:00 committed by 二货机器人
parent 1c4bae59ba
commit 4ca79ffc07
8 changed files with 106 additions and 91 deletions

View File

@ -1,5 +1,5 @@
--- ---
order: 1 order: 7
title: V3 to V4 title: V3 to V4
--- ---

View File

@ -1,5 +1,5 @@
--- ---
order: 1 order: 7
title: 从 v3 到 v4 title: 从 v3 到 v4
--- ---

View File

@ -3,8 +3,7 @@ module.exports = {
messages: { messages: {
'app.header.search': 'Search...', 'app.header.search': 'Search...',
'app.header.menu.home': 'Home', 'app.header.menu.home': 'Home',
'app.header.menu.practice': 'Practice', 'app.header.menu.documentation': 'Documentation',
'app.header.menu.pattern': 'Patterns',
'app.header.menu.components': 'Components', 'app.header.menu.components': 'Components',
'app.header.menu.spec': 'Guidelines', 'app.header.menu.spec': 'Guidelines',
'app.header.menu.resource': 'Resources', 'app.header.menu.resource': 'Resources',

View File

@ -38,6 +38,7 @@ a {
z-index: 1; z-index: 1;
&-inner { &-inner {
height: 100%;
max-height: 100vh; max-height: 100vh;
overflow-x: hidden; overflow-x: hidden;
overflow-y: hidden; overflow-y: hidden;
@ -46,22 +47,56 @@ a {
&:hover &-inner { &:hover &-inner {
overflow-y: auto; overflow-y: auto;
} }
> div,
> div > div {
height: 100%;
}
} }
.aside-container { .aside-container {
height: 100%;
padding-bottom: 48px; padding-bottom: 48px;
font-family: Avenir, @font-family, sans-serif; font-family: Avenir, @font-family, sans-serif;
&.ant-menu-inline .ant-menu-submenu-title h4, &.ant-menu-inline {
&.ant-menu-inline > .ant-menu-item, .ant-menu-submenu-title h4,
&.ant-menu-inline .ant-menu-item a { > .ant-menu-item,
.ant-menu-item a {
overflow: hidden; overflow: hidden;
font-weight: 500;
font-size: 14px; font-size: 14px;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
&.ant-menu-inline .ant-menu-item-group-title { .ant-menu-item-group-title {
padding-left: 56px; margin-top: 16px;
margin-bottom: 16px;
font-size: 13px;
&::after {
position: relative;
top: 12px;
display: block;
width: calc(100% - 20px);
height: 1px;
background: @border-color-split;
content: '';
}
}
> .ant-menu-item,
> .ant-menu-submenu > .ant-menu-submenu-title,
> .ant-menu-item-group > .ant-menu-item-group-title,
> .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item {
padding-left: 40px !important;
}
.ant-menu-item-group:first-child {
.ant-menu-item-group-title {
margin-top: 0;
}
}
} }
a[disabled] { a[disabled] {
@ -112,12 +147,6 @@ a {
.ant-menu-item > a:hover { .ant-menu-item > a:hover {
color: @primary-color; color: @primary-color;
} }
.menu-antd-components-count {
margin-left: 0.5em;
color: @disabled-color;
font-size: 12px;
}
} }
#react-content { #react-content {

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Link } from 'bisheng/router'; import { Link } from 'bisheng/router';
import { Row, Col, Menu, Affix } from 'antd'; import { Row, Col, Menu, Affix } from 'antd';
import { FormattedMessage, injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import get from 'lodash/get'; import get from 'lodash/get';
import MobileMenu from 'rc-drawer'; import MobileMenu from 'rc-drawer';
@ -25,15 +25,18 @@ function getModuleData(props) {
.filter(item => item) .filter(item => item)
.slice(0, 2) .slice(0, 2)
.join('/'); .join('/');
const moduleData =
moduleName === 'components' ||
moduleName === 'docs/react' ||
moduleName === 'changelog' ||
moduleName === 'changelog-cn'
? [...props.picked.components, ...props.picked['docs/react'], ...props.picked.changelog]
: props.picked[moduleName];
const excludedSuffix = utils.isZhCN(props.location.pathname) ? 'en-US.md' : 'zh-CN.md'; const excludedSuffix = utils.isZhCN(props.location.pathname) ? 'en-US.md' : 'zh-CN.md';
return moduleData.filter(({ meta }) => !meta.filename.endsWith(excludedSuffix)); let data;
switch (moduleName) {
case 'docs/react':
case 'changelog':
case 'changelog-cn':
data = [...props.picked['docs/react'], ...props.picked.changelog];
break;
default:
data = props.picked[moduleName];
}
return data.filter(({ meta }) => !meta.filename.endsWith(excludedSuffix));
} }
function fileNameToPath(filename) { function fileNameToPath(filename) {
@ -52,24 +55,6 @@ const getSideBarOpenKeys = nextProps => {
return shouldOpenKeys; return shouldOpenKeys;
}; };
const getSubMenuTitle = menuItem => {
if (menuItem.title !== 'Components') {
return menuItem.title;
}
let count = 0;
menuItem.children.forEach(item => {
if (item.children) {
count += item.children.length;
}
});
return (
<h4>
<FormattedMessage id="app.header.menu.components" />
<span className="menu-antd-components-count">{count}</span>
</h4>
);
};
class MainContent extends Component { class MainContent extends Component {
static contextTypes = { static contextTypes = {
isMobile: PropTypes.bool.isRequired, isMobile: PropTypes.bool.isRequired,
@ -128,21 +113,19 @@ class MainContent extends Component {
themeConfig.typeOrder, themeConfig.typeOrder,
); );
return menuItems.map(menuItem => { return menuItems.map(menuItem => {
if (menuItem.children) { if (menuItem.type === 'type') {
return ( return (
<SubMenu title={getSubMenuTitle(menuItem)} key={menuItem.title}> <Menu.ItemGroup title={menuItem.title} key={menuItem.title}>
{menuItem.children.map(child => { {menuItem.children
if (child.type === 'type') {
return (
<Menu.ItemGroup title={child.title} key={child.title}>
{child.children
.sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0)) .sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0))
.map(leaf => this.generateMenuItem(false, leaf, footerNavIcons))} .map(leaf => this.generateMenuItem(false, leaf, footerNavIcons))}
</Menu.ItemGroup> </Menu.ItemGroup>
); );
} }
return this.generateMenuItem(false, child, footerNavIcons); if (menuItem.children) {
})} return (
<SubMenu title={menuItem.title} key={menuItem.title}>
{menuItem.children.map(child => this.generateMenuItem(false, child, footerNavIcons))}
</SubMenu> </SubMenu>
); );
} }
@ -298,7 +281,7 @@ class MainContent extends Component {
}); });
const menuChild = ( const menuChild = (
<Menu <Menu
inlineIndent={40} inlineIndent={30}
className="aside-container menu-site" className="aside-container menu-site"
mode="inline" mode="inline"
openKeys={openKeys} openKeys={openKeys}

View File

@ -127,7 +127,7 @@ class Header extends React.Component {
.slice(0, -1) .slice(0, -1)
.join('/'); .join('/');
let activeMenuItem = module || 'home'; let activeMenuItem = module || 'home';
if (activeMenuItem === 'components' || location.pathname === 'changelog') { if (location.pathname === 'changelog') {
activeMenuItem = 'docs/react'; activeMenuItem = 'docs/react';
} }
const isZhCN = locale === 'zh-CN'; const isZhCN = locale === 'zh-CN';
@ -176,6 +176,11 @@ class Header extends React.Component {
</Menu.Item> </Menu.Item>
<Menu.Item key="docs/react"> <Menu.Item key="docs/react">
<Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN)}> <Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN)}>
<FormattedMessage id="app.header.menu.documentation" />
</Link>
</Menu.Item>
<Menu.Item key="components">
<Link to={utils.getLocalizedPathname('/components/button/', isZhCN)}>
<FormattedMessage id="app.header.menu.components" /> <FormattedMessage id="app.header.menu.components" />
</Link> </Link>
</Menu.Item> </Menu.Item>

View File

@ -9,9 +9,24 @@ export function getMenuItems(moduleData, locale, categoryOrder, typeOrder) {
menuMeta.sort(sortFn).forEach(meta => { menuMeta.sort(sortFn).forEach(meta => {
if (!meta.category) { if (!meta.category) {
menuItems.push(meta); menuItems.push(meta);
} else { return;
}
if (meta.category === 'Components' && meta.type) {
let type = menuItems.find(i => i.title === meta.type);
if (!type) {
type = {
type: 'type',
title: meta.type,
children: [],
order: typeOrder[meta.type],
};
menuItems.push(type);
}
type.children.push(meta);
return;
}
const category = meta.category[locale] || meta.category; const category = meta.category[locale] || meta.category;
let group = menuItems.filter(i => i.title === category)[0]; let group = menuItems.find(i => i.title === category);
if (!group) { if (!group) {
group = { group = {
type: 'category', type: 'category',
@ -21,22 +36,7 @@ export function getMenuItems(moduleData, locale, categoryOrder, typeOrder) {
}; };
menuItems.push(group); menuItems.push(group);
} }
if (meta.type) {
let type = group.children.filter(i => i.title === meta.type)[0];
if (!type) {
type = {
type: 'type',
title: meta.type,
children: [],
order: typeOrder[meta.type],
};
group.children.push(type);
}
type.children.push(meta);
} else {
group.children.push(meta); group.children.push(meta);
}
}
}); });
return menuItems return menuItems
.map(i => { .map(i => {

View File

@ -3,10 +3,9 @@ module.exports = {
messages: { messages: {
'app.header.search': '全文本搜索...', 'app.header.search': '全文本搜索...',
'app.header.menu.home': '首页', 'app.header.menu.home': '首页',
'app.header.menu.practice': '实践', 'app.header.menu.documentation': '文档',
'app.header.menu.pattern': '模式',
'app.header.menu.components': '组件', 'app.header.menu.components': '组件',
'app.header.menu.spec': '设计语言', 'app.header.menu.spec': '设计',
'app.header.menu.resource': '资源', 'app.header.menu.resource': '资源',
'app.header.menu.mobile': '移动版', 'app.header.menu.mobile': '移动版',
'app.header.menu.pro.v4': 'Ant Design Pro v4', 'app.header.menu.pro.v4': 'Ant Design Pro v4',