Skip to content

Commit

Permalink
feat(v2): bootstrap theme, preset, template, CI previews (#2981)
Browse files Browse the repository at this point in the history
* fix(v2): doc sidebar

* chore(v2): prettier

* fix(v2): docs navbar path

* fix(v2): fix error about activepath

* chore(v2): prettier

* feat(v2): change active color

* feat(v2): Add bootstrap doc

* docs(v2): Update preset

* doc(v2): finish bootstrap documentation

* chore(v2): run lint

* doc(v2): update hook

* fix theme bootstrap layout (far from perfect)

* Try to fix bootstrap theme and deploy it!

* fix netlify error

Co-authored-by: slorber <lorber.sebastien@gmail.com>
  • Loading branch information
fanny and slorber authored Aug 17, 2020
1 parent 5fdf96c commit 8c05aa8
Show file tree
Hide file tree
Showing 17 changed files with 560 additions and 66 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"start:v2": "yarn workspace docusaurus-2-website start",
"start:v2:watch": "nodemon --watch \"./packages/*/lib/**/*.*\" --exec \"yarn start:v2\"",
"start:v2:baseUrl": "yarn workspace docusaurus-2-website start:baseUrl",
"start:v2:bootstrap": "yarn workspace docusaurus-2-website start:bootstrap",
"build": "yarn build:packages && yarn build:v2",
"build:packages": "lerna run build --no-private",
"build:v1": "yarn workspace docusaurus-1-website build",
Expand Down
38 changes: 20 additions & 18 deletions packages/docusaurus-init/templates/bootstrap/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,26 @@ function Home() {
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />">
<header>
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link to={useBaseUrl('docs/')}>Get Started</Link>
</div>
</header>
<main>
{features && features.length > 0 && (
<section className={styles.features}>
<div className="row">
{features.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</section>
)}
</main>
<div className={styles.hero}>
<header>
<h1>{siteConfig.title}</h1>
<p>{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link to={useBaseUrl('docs/')}>Get Started</Link>
</div>
</header>
<main>
{features && features.length > 0 && (
<section className={styles.section}>
<div className={styles.features}>
{features.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</section>
)}
</main>
</div>
</Layout>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@
justify-content: center;
}

.hero {
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
place-content: center;
}

.section {
margin: 10rem;
}

.features {
display: flex;
align-items: center;
Expand Down
57 changes: 34 additions & 23 deletions packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,44 @@ import Layout from '@theme/Layout';
import {MDXProvider} from '@mdx-js/react';
import {matchPath} from '@docusaurus/router';

function DocPage(props) {
const {route: baseRoute, docsMetadata, location} = props;
// case-sensitive route such as it is defined in the sidebar
const currentRoute =
baseRoute.routes.find((route) => {
return matchPath(location.pathname, route);
}) || {};
const {permalinkToSidebar, docsSidebars} = docsMetadata;
const sidebar = permalinkToSidebar[currentRoute.path];
function DocPageContent({currentDocRoute, versionMetadata, children}) {
const {permalinkToSidebar, docsSidebars} = versionMetadata;
const sidebarName = permalinkToSidebar[currentDocRoute.path];
const sidebar = docsSidebars[sidebarName];
return (
<Layout title="Doc page" description="My Doc page">
<div className="d-flex vh-100 overflow-hidden">
{sidebar && (
<div className="vh-100" role="complementary">
<DocSidebar path={currentDocRoute.path} sidebar={sidebar} />
</div>
)}
<main className="vh-100 w-100 d-flex flex-column align-items-center overflow-auto p-5">
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</main>
</div>
</Layout>
);
}

if (Object.keys(currentRoute).length === 0) {
function DocPage(props) {
const {
route: {routes: docRoutes},
versionMetadata,
location,
} = props;
const currentDocRoute = docRoutes.find((docRoute) =>
matchPath(location.pathname, docRoute),
);
if (!currentDocRoute) {
return <NotFound {...props} />;
}

return (
<Layout title="Doc page" description="My Doc page">
<DocSidebar
docsSidebars={docsSidebars}
path={currentRoute.path}
sidebar={sidebar}
/>
<section className="offset-1 mr-4 mt-4 col-xl-6 offset-xl-4 p-0 justify-content-center align-self-center overflow-hidden">
<MDXProvider components={MDXComponents}>
{renderRoutes(baseRoute.routes)}
</MDXProvider>
</section>
</Layout>
<DocPageContent
currentDocRoute={currentDocRoute}
versionMetadata={versionMetadata}>
{renderRoutes(docRoutes)}
</DocPageContent>
);
}

Expand Down
18 changes: 2 additions & 16 deletions packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,28 +61,14 @@ const DocSidebarItem = ({item, onItemClick, ...props}) => {
}
};

const DocSidebar = (props) => {
const {docsSidebars, sidebar: currentSidebar} = props;

const DocSidebar = ({sidebar, path}) => {
const [sidebarShown, setSidebarShown] = useState(false);
const handleSidebarToggle = useCallback(() => {
setSidebarShown(!sidebarShown);
}, [sidebarShown, setSidebarShown]);

useLockBodyScroll(sidebarShown);

if (!currentSidebar) {
return null;
}

const sidebarData = docsSidebars[currentSidebar];

if (!sidebarData) {
throw new Error(
`Cannot find the sidebar "${currentSidebar}" in the sidebar config!`,
);
}

return (
<div className={classNames('bg-info', styles.sidebar)}>
<div
Expand Down Expand Up @@ -115,7 +101,7 @@ const DocSidebar = (props) => {
</div>
<div className={classNames(styles.sideMenu)}>
<Nav vertical className="list-unstyled p-3 mr-auto">
{sidebarData.map((item) => (
{sidebar.map((item) => (
<DocSidebarItem
key={item.label}
item={item}
Expand Down
32 changes: 32 additions & 0 deletions packages/docusaurus-theme-bootstrap/src/theme/MDXPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import Layout from '@theme/Layout';
import {MDXProvider} from '@mdx-js/react';
import MDXComponents from '@theme/MDXComponents';

function MDXPage(props) {
const {content: MDXPageContent} = props;
const {frontMatter, metadata} = MDXPageContent;
const {title, description} = frontMatter;
const {permalink} = metadata;

return (
<Layout title={title} description={description} permalink={permalink}>
<main>
<div className="container margin-vert--lg padding-vert--lg">
<MDXProvider components={MDXComponents}>
<MDXPageContent />
</MDXProvider>
</div>
</main>
</Layout>
);
}

export default MDXPage;
14 changes: 14 additions & 0 deletions packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';

function TabItem(props) {
return <div>{props.children}</div>;
}

export default TabItem;
154 changes: 154 additions & 0 deletions packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React, {useState, Children, useEffect} from 'react';

import clsx from 'clsx';

import styles from './styles.module.css';

const keys = {
left: 37,
right: 39,
tab: 9,
};

// TODO quick fix to make bootstrap theme work
function useUserPreferencesContext() {
const [state, setState] = useState({});

return {
tabGroupChoices: state,
setTabGroupChoices: (id, value) => {
setState((s) => ({...s, [id]: value}));
},
};
}

function Tabs(props) {
const {block, children, defaultValue, values, groupId} = props;

const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();

const [selectedValue, setSelectedValue] = useState(defaultValue);
const [keyboardPress, setKeyboardPress] = useState(false);

if (groupId != null) {
const relevantTabGroupChoice = tabGroupChoices[groupId];
if (
relevantTabGroupChoice != null &&
relevantTabGroupChoice !== selectedValue &&
values.some((value) => value.value === relevantTabGroupChoice)
) {
setSelectedValue(relevantTabGroupChoice);
}
}

const changeSelectedValue = (newValue) => {
setSelectedValue(newValue);
if (groupId != null) {
setTabGroupChoices(groupId, newValue);
}
};

const tabRefs = [];

const focusNextTab = (tabs, target) => {
const next = tabs.indexOf(target) + 1;

if (!tabs[next]) {
tabs[0].focus();
} else {
tabs[next].focus();
}
};

const focusPreviousTab = (tabs, target) => {
const prev = tabs.indexOf(target) - 1;

if (!tabs[prev]) {
tabs[tabs.length - 1].focus();
} else {
tabs[prev].focus();
}
};

const handleKeydown = (tabs, target, event) => {
switch (event.keyCode) {
case keys.right:
focusNextTab(tabs, target);
break;
case keys.left:
focusPreviousTab(tabs, target);
break;
default:
break;
}
};

const handleKeyboardEvent = (event) => {
if (event.metaKey || event.altKey || event.ctrlKey) {
return;
}

setKeyboardPress(true);
};

const handleMouseEvent = () => {
setKeyboardPress(false);
};

useEffect(() => {
window.addEventListener('keydown', handleKeyboardEvent);
window.addEventListener('mousedown', handleMouseEvent);
}, []);

return (
<div>
<ul
role="tablist"
aria-orientation="horizontal"
className={clsx('tabs', {
'tabs--block': block,
})}>
{values.map(({value, label}) => (
<li
role="tab"
tabIndex={0}
aria-selected={selectedValue === value}
className={clsx('tabs__item', styles.tabItem, {
'tabs__item--active': selectedValue === value,
})}
style={keyboardPress ? {} : {outline: 'none'}}
key={value}
ref={(tabControl) => tabRefs.push(tabControl)}
onKeyDown={(event) => {
handleKeydown(tabRefs, event.target, event);
handleKeyboardEvent(event);
}}
onFocus={() => changeSelectedValue(value)}
onClick={() => {
changeSelectedValue(value);
setKeyboardPress(false);
}}
onPointerDown={() => setKeyboardPress(false)}>
{label}
</li>
))}
</ul>
<div role="tabpanel" className="margin-vert--md">
{
Children.toArray(children).filter(
(child) => child.props.value === selectedValue,
)[0]
}
</div>
</div>
);
}

export default Tabs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

.tabItem {
margin-top: 0 !important;
}

Loading

0 comments on commit 8c05aa8

Please sign in to comment.