feat(v2): support external links and linking to docs from other sidebars (#1052)

* feat(sidebar): support external links and linking to docs from other sidebars

* Update styles.css
This commit is contained in:
Sviatoslav 2018-10-25 07:01:39 +03:00 committed by Yangshun Tay
parent edde297504
commit a2d3f26722
8 changed files with 466 additions and 139 deletions

View file

@ -0,0 +1,32 @@
import React from 'react';
import classnames from 'classnames';
import styles from './styles.css';
export default function SidebarCategory({
label,
items,
subCategory,
renderItem,
}) {
const Heading = subCategory ? 'h4' : 'h3';
return (
<div
className={classnames(styles.sidebarGroup, {
[styles.sidebarSubGroup]: subCategory,
})}
key={label}>
<Heading
className={classnames(
styles.sidebarItem,
styles.sidebarGroupTitle,
styles.sidebarGroupCategoryTitle,
)}>
{label}
</Heading>
<ul className={styles.sidebarList}>{items.map(renderItem)}</ul>
</div>
);
}

View file

@ -0,0 +1,24 @@
import React from 'react';
import {NavLink} from 'react-router-dom';
import classnames from 'classnames';
import styles from './styles.css';
export default function SidebarLink({href, label}) {
const isExternal = /^(https?:|\/\/)/.test(href);
const Link = isExternal
? // eslint-disable-next-line jsx-a11y/anchor-has-content
({to, activeClassName, ...linkProps}) => <a {...linkProps} href={to} />
: NavLink;
return (
<li className={styles.sidebarListItem}>
<Link
activeClassName={styles.sidebarLinkActive}
className={classnames(styles.sidebarLink, styles.sidebarItem)}
to={href}>
{label}
</Link>
</li>
);
}

View file

@ -1,80 +1,63 @@
import React from 'react';
import {NavLink} from 'react-router-dom';
import classnames from 'classnames';
import SidebarLink from './SidebarLink';
import SidebarCategory from './SidebarCategory';
import styles from './styles.css';
function Sidebar(props) {
const {metadata, docsSidebars, docsMetadatas} = props;
const {sidebar, language} = metadata;
if (!sidebar || !docsSidebars) {
if (!sidebar) {
return null;
}
const thisSidebar = docsSidebars[sidebar];
const renderItemLink = rawLinkID => {
const linkID = (language ? `${language}-` : '') + rawLinkID;
if (!thisSidebar) {
throw new Error(`Can not find ${sidebar} config`);
}
const convertDocLink = item => {
const linkID = (language ? `${language}-` : '') + item.id;
const linkMetadata = docsMetadatas[linkID];
if (!linkMetadata) {
throw new Error(
`Improper sidebars.json file, document with id '${linkID}' not found.`,
);
}
return (
<li className={styles.sidebarListItem} key={linkID}>
<NavLink
activeClassName={styles.sidebarLinkActive}
className={classnames(styles.sidebarLink, styles.sidebarItem)}
to={linkMetadata.permalink}>
{linkMetadata.sidebar_label || linkMetadata.title}
</NavLink>
</li>
);
return {
type: 'link',
label: linkMetadata.sidebar_label || linkMetadata.title,
href: linkMetadata.permalink,
};
};
const renderCategory = categoryName => {
const category = thisSidebar[categoryName];
return (
<div className={styles.sidebarGroup} key={categoryName}>
<h3
className={classnames(
styles.sidebarItem,
styles.sidebarGroupTitle,
styles.sidebarGroupCategoryTitle,
)}>
{categoryName}
</h3>
<ul className={styles.sidebarList}>
{Array.isArray(category)
? category.map(renderItemLink)
: Object.keys(category).map(subCategoryName => (
<div className={styles.sidebarSubGroup} key={subCategoryName}>
<h4
className={classnames(
styles.sidebarItem,
styles.sidebarGroupTitle,
styles.sidebarGroupSubcategorytitle,
)}>
{subCategoryName}
</h4>
<ul className={styles.sidebarList}>
{category[subCategoryName].map(renderItemLink)}
</ul>
</div>
))}
</ul>
</div>
);
const renderItem = (item, {root} = {}) => {
switch (item.type) {
case 'category':
return (
<SidebarCategory
{...item}
key={item.label}
subCategory={!root}
renderItem={renderItem}
/>
);
case 'link':
return <SidebarLink {...item} key={item.href} />;
case 'ref':
default:
return renderItem(convertDocLink(item));
}
};
return (
thisSidebar && (
<div className={styles.sidebar}>
{Object.keys(thisSidebar).map(renderCategory)}
</div>
)
<div className={styles.sidebar}>
{thisSidebar.map(item => renderItem(item, {root: true}))}
</div>
);
}

View file

@ -17,6 +17,10 @@
padding: 8px 12px;
}
.sidebarSubGroup {
margin-left: 0.25em;
}
.sidebarGroupTitle {
font-size: 1em;
font-weight: 500;