1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-18 21:21:21 +02:00

feat(Examples): improve example navigation (#2450)

* feat(Examples) make tab menu responsive

For small screens, don't show tabs by default. Instead, show a hamburger menu. When clicking the hamburger menu, expand the examples list.
This commit is contained in:
Eric Edem
2019-01-11 10:32:06 -08:00
committed by Sunny Hirai
parent 44e47d7ffe
commit 68e5ff95d9

View File

@@ -8,6 +8,7 @@ import {
Switch, Switch,
} from 'react-router-dom' } from 'react-router-dom'
import { Icon } from './components'
import CheckLists from './check-lists' import CheckLists from './check-lists'
import CodeHighlighting from './code-highlighting' import CodeHighlighting from './code-highlighting'
import Embeds from './embeds' import Embeds from './embeds'
@@ -40,30 +41,30 @@ import Mentions from './mentions'
*/ */
const EXAMPLES = [ const EXAMPLES = [
['Rich Text', RichText, '/rich-text'],
['Plain Text', PlainText, '/plain-text'],
['Hovering Menu', HoveringMenu, '/hovering-menu'],
['Links', Links, '/links'],
['Images', Images, '/images'],
['Embeds', Embeds, '/embeds'],
['Emojis', Emojis, '/emojis'],
['Markdown Preview', MarkdownPreview, '/markdown-preview'],
['Markdown Shortcuts', MarkdownShortcuts, '/markdown-shortcuts'],
['Check Lists', CheckLists, '/check-lists'], ['Check Lists', CheckLists, '/check-lists'],
['Code Highlighting', CodeHighlighting, '/code-highlighting'], ['Code Highlighting', CodeHighlighting, '/code-highlighting'],
['Tables', Tables, '/tables'], ['Embeds', Embeds, '/embeds'],
['Emojis', Emojis, '/emojis'],
['Forced Layout', ForcedLayout, '/forced-layout'],
['History', History, '/history'],
['Hovering Menu', HoveringMenu, '/hovering-menu'],
['Huge Document', HugeDocument, '/huge-document'],
['Images', Images, '/images'],
['Input Tester', InputTester, '/input-tester'],
['Links', Links, '/links'],
['Markdown Preview', MarkdownPreview, '/markdown-preview'],
['Markdown Shortcuts', MarkdownShortcuts, '/markdown-shortcuts'],
['Mentions', Mentions, '/mentions'],
['Paste HTML', PasteHtml, '/paste-html'], ['Paste HTML', PasteHtml, '/paste-html'],
['Plain Text', PlainText, '/plain-text'],
['Plugins', Plugins, '/plugins'],
['Read-only', ReadOnly, '/read-only'],
['Rich Text', RichText, '/rich-text'],
['RTL', RTL, '/rtl'],
['Search Highlighting', SearchHighlighting, '/search-highlighting'], ['Search Highlighting', SearchHighlighting, '/search-highlighting'],
['Syncing Operations', SyncingOperations, '/syncing-operations'], ['Syncing Operations', SyncingOperations, '/syncing-operations'],
['Read-only', ReadOnly, '/read-only'], ['Tables', Tables, '/tables'],
['RTL', RTL, '/rtl'],
['Plugins', Plugins, '/plugins'],
['Forced Layout', ForcedLayout, '/forced-layout'],
['Huge Document', HugeDocument, '/huge-document'],
['History', History, '/history'],
['Versions', Versions, '/versions'], ['Versions', Versions, '/versions'],
['Input Tester', InputTester, '/input-tester'],
['Mentions', Mentions, '/mentions'],
] ]
/** /**
@@ -72,18 +73,23 @@ const EXAMPLES = [
* @type {Component} * @type {Component}
*/ */
const Nav = styled('div')` const Header = styled('div')`
padding: 10px 15px; align-items: center;
color: #aaa;
background: #000; background: #000;
color: #aaa;
display: flex;
height: 42px;
position: relative;
z-index: 1; /* To appear above the underlay */
` `
const Title = styled('span')` const Title = styled('span')`
margin-right: 0.5em; margin-left: 1em;
` `
const LinkList = styled('div')` const LinkList = styled('div')`
float: right; margin-left: auto;
margin-right: 1em;
` `
const Link = styled('a')` const Link = styled('a')`
@@ -98,13 +104,37 @@ const Link = styled('a')`
` `
const TabList = styled('div')` const TabList = styled('div')`
padding: 15px 15px;
background-color: #222; background-color: #222;
text-align: center; display: flex;
margin-bottom: 30px; flex-direction: column;
overflow: hidden;
padding-top: 0.2em;
position: absolute;
transition: width 0.2s;
width: ${props => (props.isVisible ? '200px' : '0')};
white-space: nowrap;
z-index: 1; /* To appear above the underlay */
`
& > * + * { const TabListUnderlay = styled('div')`
margin-left: 0.5em; background-color: rgba(200, 200, 200, 0.8);
display: ${props => (props.isVisible ? 'block' : 'none')};
height: 100%;
top: 0;
position: fixed;
width: 100%;
`
const TabButton = styled('span')`
margin-left: 0.8em;
&:hover {
cursor: pointer;
}
.material-icons {
color: #aaa;
font-size: 24px;
} }
` `
@@ -113,7 +143,7 @@ const MaskedRouterLink = ({ active, ...props }) => <RouterLink {...props} />
const Tab = styled(MaskedRouterLink)` const Tab = styled(MaskedRouterLink)`
display: inline-block; display: inline-block;
margin-bottom: 0.2em; margin-bottom: 0.2em;
padding: 0.2em 0.5em; padding: 0.2em 1em;
border-radius: 0.2em; border-radius: 0.2em;
text-decoration: none; text-decoration: none;
color: ${p => (p.active ? 'white' : '#777')}; color: ${p => (p.active ? 'white' : '#777')};
@@ -126,11 +156,25 @@ const Tab = styled(MaskedRouterLink)`
const Wrapper = styled('div')` const Wrapper = styled('div')`
max-width: 42em; max-width: 42em;
margin: 0 auto 20px; margin: 20px auto;
padding: 20px; padding: 20px;
` `
const Example = styled(Wrapper)` const ExampleHeader = styled('div')`
align-items: center;
background-color: #555;
color: #ddd;
display: flex;
height: 42px;
position: relative;
z-index: 1; /* To appear above the underlay */
`
const ExampleTitle = styled('span')`
margin-left: 1em;
`
const ExampleContent = styled(Wrapper)`
background: #fff; background: #fff;
` `
@@ -161,6 +205,7 @@ export default class App extends React.Component {
state = { state = {
error: null, error: null,
info: null, info: null,
isTabListVisible: false,
} }
/** /**
@@ -184,49 +229,109 @@ export default class App extends React.Component {
return ( return (
<HashRouter> <HashRouter>
<div> <div>
<Nav> {this.renderHeader()}
<Title>Slate Examples</Title> {this.renderExampleHeader()}
<LinkList> {this.renderTabList()}
<Link href="https://github.com/ianstormtaylor/slate">GitHub</Link> {this.state.error ? this.renderError() : this.renderExample()}
<Link href="https://docs.slatejs.org/">Docs</Link> <TabListUnderlay
</LinkList> isVisible={this.state.isTabListVisible}
</Nav> onClick={this._hideTabList}
<TabList> />
{EXAMPLES.map(([name, Component, path]) => (
<Route key={path} exact path={path}>
{({ match }) => (
<Tab to={path} active={match && match.isExact}>
{name}
</Tab>
)}
</Route>
))}
</TabList>
{this.state.error ? (
<Warning>
<p>
An error was thrown by one of the example's React components!
</p>
<pre>
<code>
{this.state.error.stack}
{'\n'}
{this.state.info.componentStack}
</code>
</pre>
</Warning>
) : (
<Example>
<Switch>
{EXAMPLES.map(([name, Component, path]) => (
<Route key={path} path={path} component={Component} />
))}
<Redirect from="/" to="/rich-text" />
</Switch>
</Example>
)}
</div> </div>
</HashRouter> </HashRouter>
) )
} }
renderError() {
return (
<Warning>
<p>An error was thrown by one of the example's React components!</p>
<pre>
<code>
{this.state.error.stack}
{'\n'}
{this.state.info.componentStack}
</code>
</pre>
</Warning>
)
}
renderExample() {
return (
<Switch>
{EXAMPLES.map(([name, Component, path]) => (
<Route key={path} path={path}>
<div>
<ExampleContent>
<Component />
</ExampleContent>
</div>
</Route>
))}
<Redirect from="/" to="/rich-text" />
</Switch>
)
}
renderExampleHeader() {
return (
<ExampleHeader>
<TabButton
onClick={e => {
e.stopPropagation()
this.setState({
isTabListVisible: !this.state.isTabListVisible,
})
}}
>
<Icon>menu</Icon>
</TabButton>
<Switch>
{EXAMPLES.map(([name, Component, path]) => (
<Route key={path} exact path={path}>
<ExampleTitle>{name}</ExampleTitle>
</Route>
))}
</Switch>
</ExampleHeader>
)
}
renderHeader() {
return (
<Header>
<Title>Slate Examples</Title>
<LinkList>
<Link href="https://github.com/ianstormtaylor/slate">GitHub</Link>
<Link href="https://docs.slatejs.org/">Docs</Link>
</LinkList>
</Header>
)
}
renderTabList() {
return (
<TabList isVisible={this.state.isTabListVisible}>
{EXAMPLES.map(([name, Component, path]) => (
<Route key={path} exact path={path}>
{({ match }) => (
<Tab
to={path}
active={match && match.isExact}
onClick={this._hideTabList}
>
{name}
</Tab>
)}
</Route>
))}
</TabList>
)
}
_hideTabList = () => {
this.setState({ isTabListVisible: false })
}
} }