Skip to content

Commit

Permalink
feat: Add DocumentationPage layout. (#359)
Browse files Browse the repository at this point in the history
* feat: Add DocumentationPage layout.

* docs: Fix headline level.
  • Loading branch information
goloroden authored Mar 5, 2020
1 parent 7ce8005 commit 1e3af00
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 167 deletions.
4 changes: 2 additions & 2 deletions lib/components/documentation/Code/Documentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Documentation = (): ReactElement => (
</Code>
</ComponentPreview>

<Headline>Languages</Headline>
<Headline level='2'>Languages</Headline>

<Paragraph>
Besides the default `language` JavaScript the component also renders
Expand Down Expand Up @@ -65,7 +65,7 @@ const Documentation = (): ReactElement => (
</Fragment>
</ComponentPreview>

<Headline>Inline</Headline>
<Headline level='2'>Inline</Headline>

<Paragraph>
Code can also be rendered inline in a Paragraph.
Expand Down
6 changes: 6 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ControlGroupDivider } from './components/forms/ControlGroupDivider';
import { ControlGroupItem } from './components/forms/ControlGroupItem';
import { createRedirect } from './createRedirect';
import { Dialogs } from './components/feedback/Dialogs';
import { DocumentationPage } from './layouts/DocumentationPage';
import { Dropdown } from './components/input/Dropdown';
import { Footer } from './components/layout/Footer';
import { Form } from './components/forms/Form';
Expand All @@ -30,6 +31,7 @@ import { Icon } from './components/graphics/Icon';
import { Icons } from './components/graphics/Icons';
import { IconSize } from './types/IconSize';
import { Label } from './components/typography/Label';
import { Language } from './types/Language';
import { LayoutComponent } from './types/LayoutComponent';
import { Link } from './components/input/Link';
import { LogoFull } from './components/graphics/LogoFull';
Expand All @@ -41,6 +43,7 @@ import { Message } from './components/feedback/Message';
import { MobileToggle } from './components/navigation/MobileToggle';
import { Modal } from './components/feedback/Modal';
import { ModalRow } from './components/feedback/ModalRow';
import { MultiLanguagePageTree } from './types/MultiLanguagePageTree';
import { NextApp } from './NextApp';
import { NextDocument } from './NextDocument';
import { NonIdealState } from './components/feedback/NonIdealState';
Expand Down Expand Up @@ -94,6 +97,7 @@ export {
createRedirect,
dialogs,
Dialogs,
DocumentationPage,
Dropdown,
excecutionEnvironment,
Form,
Expand All @@ -111,6 +115,7 @@ export {
IconSize,
Icons,
Label,
Language,
LayoutComponent,
Link,
LogoFull,
Expand All @@ -122,6 +127,7 @@ export {
MobileToggle,
Modal,
ModalRow,
MultiLanguagePageTree,
NextApp,
NextDocument,
NonIdealState,
Expand Down
59 changes: 59 additions & 0 deletions lib/layouts/DocumentationPage/Documentation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Code, Headline, Link, Paragraph } from '../..';
import React, { ReactElement } from 'react';

const Documentation = (): ReactElement => (
<React.Fragment>
<Headline>DocumentationPage</Headline>

<Paragraph>
Use this layout to render documentation sites that feature a tree
navigation structure. It consists of a <Link href='/components/navigation/sidebar'><code>SideBar</code></Link>,
a <Link href='/components/navigation/pagenavigation'><code>PageNavigation</code></Link>, and
a content panel.
</Paragraph>

<Headline level='2'>Responsive behaviour</Headline>

<Paragraph>
On <code>xs</code> screens, the content panel will fill the whole page and
the <code>PageNavigation</code> will be rendered in a fullscreen container.
A <Link href='/components/navigation/mobiletoggle'><code>MobileToggle</code></Link> can
then be used to toggle this navigation.
</Paragraph>

<Headline level='2'>Defining the layout in a page</Headline>

<Paragraph>
Wrap your page within the layout and set the <code>navigation</code>, <code>productName</code>, <code>siteTitle</code>, and <code>yearOfCreation</code> properties.
Additionally you can pass a <code>pageTitle</code> for each page.
</Paragraph>

<Code>{`
const navigation: MultiLanguagePageTree = {
'en-us': [
{
title: 'First Section',
children: [
{ title: 'Page A' },
{ title: 'Page B' }
]
}
]
};
// ...
<DocumentationPage
siteTitle='the native web UX'
productName='ux'
navigation={ navigation }
yearOfCreation={ 2017 }
>
<div>My page content goes here</div>
</DocumentationPage>
`}
</Code>
</React.Fragment>
);

export { Documentation };
167 changes: 167 additions & 0 deletions lib/layouts/DocumentationPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import Head from 'next/head';
import NextLink from 'next/link';
import { useRouter } from 'next/router';
import {
Breadcrumbs,
Footer,
getLanguageFromUrl,
HorizontalBar,
Link,
MobileToggle,
MultiLanguagePageTree,
NonIdealState,
PageNavigation,
PageTree,
Product,
Sidebar,
SidebarBrand,
SidebarItem,
Theme,
useDevice,
useRouteChange
} from '../..';
import { classNames, createUseStyles } from '../../styles';
import { DocumentationPageClassNames, styles } from './styles';
import React, { FunctionComponent, ReactElement, useCallback, useEffect, useState } from 'react';

const useStyles = createUseStyles<Theme, DocumentationPageClassNames>(styles);

interface DocumentationPageProps {
navigation: MultiLanguagePageTree;
siteTitle: string;
pageTitle?: string;
productName: string;
yearOfCreation: number;
}

const DocumentationPage: FunctionComponent<DocumentationPageProps> = ({
children,
navigation,
pageTitle,
productName,
siteTitle,
yearOfCreation
}): ReactElement | null => {
const router = useRouter();
const classes = useStyles();
const device = useDevice();
const isMobile = device === 'xs';

const [ isNavigationVisible, setIsNavigationVisible ] = useState(true);
const [ activePath, setActivePath ] = useState(router.pathname);

const language = getLanguageFromUrl(router.pathname);
const basePath = `/${language}`;
const navigationItemsForLanguage = navigation[language];

if (!Array.isArray(navigationItemsForLanguage)) {
return null;
}

const pageTree = new PageTree({
items: navigationItemsForLanguage,
basePath
});

const currentPage = pageTree.getPageItemByPath(activePath);

const componentClasses = classNames(classes.DocumentationPage, {
[classes.WithNavigationVisible]: isNavigationVisible
});

const hideNavigationOnMobile = useCallback((): void => {
if (isMobile) {
setIsNavigationVisible(false);
}
}, []);

const toggleNavigation = useCallback((): void => {
setIsNavigationVisible(!isNavigationVisible);
}, [ isNavigationVisible ]);

useRouteChange((newPath): void => {
setActivePath(newPath);
hideNavigationOnMobile();
}, [ device ]);

useEffect(hideNavigationOnMobile, []);

return (
<div className={ componentClasses }>
<Head>
{
pageTitle ?
<title>{ siteTitle } | { pageTitle }</title> :
<title>{ siteTitle }{ currentPage ? ` | ${currentPage.title}` : '' }</title>
}
<link key='favicon' rel='icon' href='/favicon.png' type='image/png' />
<meta key='viewport' name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover' />
</Head>
<div className={ classes.NavigationForDesktop }>
<Sidebar>
<NextLink href={ basePath }>
<Link href={ basePath }>
<SidebarBrand>
<Product name={ productName } />
</SidebarBrand>
</Link>
</NextLink>
<SidebarItem
iconName='toggle-left-panel'
onClick={ toggleNavigation }
isActive={ isNavigationVisible }
/>
</Sidebar>
</div>

<HorizontalBar
background='dark'
paddingHorizontal='sm'
borderBottom={ false }
className={ classes.NavigationForMobile }
>
<NextLink href={ basePath }>
<Link href={ basePath }>
<Product name={ productName } size='sm' />
</Link>
</NextLink>
</HorizontalBar>

<MobileToggle
isVisible={ isNavigationVisible }
onClick={ toggleNavigation }
/>

<div className={ classes.NavigationUniversal }>
<PageNavigation
nonIdealState={
<NonIdealState cause='Sorry, no pages found.'>
<p>
Try searching for something else!
</p>
</NonIdealState>
}
pageTree={ pageTree }
showSearchBar={ true }
activePath={ activePath }
/>
</div>

<div className={ classes.Content }>
{
currentPage && (
<HorizontalBar paddingHorizontal='none' className={ classes.ContentTopBar }>
<Breadcrumbs items={ currentPage.breadcrumbs } size='md' color='light' />
</HorizontalBar>
)
}

{ children }

<Footer yearOfCreation={ yearOfCreation } />
</div>
</div>
);
};

export { DocumentationPage };
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Styles } from 'jss';
import { Theme } from '../../../lib';
import { ComponentClassNames, Theme } from '../..';

export type StyleguideClassNames =
'Styleguide' |
export type DocumentationPageClassNames =
'DocumentationPage' |
'WithNavigationVisible' |
'NavigationUniversal' |
'NavigationForDesktop'|
Expand All @@ -14,8 +13,8 @@ const navigationPanelWidthXs = '100%';
const navigationPanelWidthSm = '200px';
const navigationPanelWidthMd = '300px';

const styles = (theme: Theme): Styles<StyleguideClassNames> => ({
Styleguide: {
const styles = (theme: Theme): ComponentClassNames<DocumentationPageClassNames> => ({
DocumentationPage: {
background: theme.color.brand.white
},

Expand Down Expand Up @@ -103,7 +102,7 @@ const styles = (theme: Theme): Styles<StyleguideClassNames> => ({
},

NavigationForMobile: {
display: 'none'
display: 'none !important'
},

NavigationUniversal: {
Expand Down
3 changes: 3 additions & 0 deletions lib/types/MultiLanguagePageTree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Language, PageTreeItem } from '..';

export type MultiLanguagePageTree = Record<Language, PageTreeItem []>;
10 changes: 5 additions & 5 deletions styleguide/configuration/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Language } from '../../lib/types/Language';
import { PageTreeItem } from '../../lib';

type Navigation = Record<Language, PageTreeItem []>;
import { MultiLanguagePageTree } from '../../lib';

/* eslint-disable object-property-newline */
const navigation: Navigation = {
const navigation: MultiLanguagePageTree = {
'en-us': [
{ title: 'Components', children: [
{ title: 'Roots', children: [
Expand Down Expand Up @@ -73,6 +70,9 @@ const navigation: Navigation = {
{ title: 'Code' }
]}
]},
{ title: 'Layouts', children: [
{ title: 'DocumentationPage' }
]},
{ title: 'Services', children: [
{ title: 'dialogs' },
{ title: 'notifications' }
Expand Down
Loading

0 comments on commit 1e3af00

Please sign in to comment.