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:
225
examples/app.js
225
examples/app.js
@@ -8,6 +8,7 @@ import {
|
||||
Switch,
|
||||
} from 'react-router-dom'
|
||||
|
||||
import { Icon } from './components'
|
||||
import CheckLists from './check-lists'
|
||||
import CodeHighlighting from './code-highlighting'
|
||||
import Embeds from './embeds'
|
||||
@@ -40,30 +41,30 @@ import Mentions from './mentions'
|
||||
*/
|
||||
|
||||
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'],
|
||||
['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'],
|
||||
['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'],
|
||||
['Syncing Operations', SyncingOperations, '/syncing-operations'],
|
||||
['Read-only', ReadOnly, '/read-only'],
|
||||
['RTL', RTL, '/rtl'],
|
||||
['Plugins', Plugins, '/plugins'],
|
||||
['Forced Layout', ForcedLayout, '/forced-layout'],
|
||||
['Huge Document', HugeDocument, '/huge-document'],
|
||||
['History', History, '/history'],
|
||||
['Tables', Tables, '/tables'],
|
||||
['Versions', Versions, '/versions'],
|
||||
['Input Tester', InputTester, '/input-tester'],
|
||||
['Mentions', Mentions, '/mentions'],
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -72,18 +73,23 @@ const EXAMPLES = [
|
||||
* @type {Component}
|
||||
*/
|
||||
|
||||
const Nav = styled('div')`
|
||||
padding: 10px 15px;
|
||||
color: #aaa;
|
||||
const Header = styled('div')`
|
||||
align-items: center;
|
||||
background: #000;
|
||||
color: #aaa;
|
||||
display: flex;
|
||||
height: 42px;
|
||||
position: relative;
|
||||
z-index: 1; /* To appear above the underlay */
|
||||
`
|
||||
|
||||
const Title = styled('span')`
|
||||
margin-right: 0.5em;
|
||||
margin-left: 1em;
|
||||
`
|
||||
|
||||
const LinkList = styled('div')`
|
||||
float: right;
|
||||
margin-left: auto;
|
||||
margin-right: 1em;
|
||||
`
|
||||
|
||||
const Link = styled('a')`
|
||||
@@ -98,13 +104,37 @@ const Link = styled('a')`
|
||||
`
|
||||
|
||||
const TabList = styled('div')`
|
||||
padding: 15px 15px;
|
||||
background-color: #222;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
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 */
|
||||
`
|
||||
|
||||
& > * + * {
|
||||
margin-left: 0.5em;
|
||||
const TabListUnderlay = styled('div')`
|
||||
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)`
|
||||
display: inline-block;
|
||||
margin-bottom: 0.2em;
|
||||
padding: 0.2em 0.5em;
|
||||
padding: 0.2em 1em;
|
||||
border-radius: 0.2em;
|
||||
text-decoration: none;
|
||||
color: ${p => (p.active ? 'white' : '#777')};
|
||||
@@ -126,11 +156,25 @@ const Tab = styled(MaskedRouterLink)`
|
||||
|
||||
const Wrapper = styled('div')`
|
||||
max-width: 42em;
|
||||
margin: 0 auto 20px;
|
||||
margin: 20px auto;
|
||||
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;
|
||||
`
|
||||
|
||||
@@ -161,6 +205,7 @@ export default class App extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
info: null,
|
||||
isTabListVisible: false,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,29 +229,23 @@ export default class App extends React.Component {
|
||||
return (
|
||||
<HashRouter>
|
||||
<div>
|
||||
<Nav>
|
||||
<Title>Slate Examples</Title>
|
||||
<LinkList>
|
||||
<Link href="https://github.com/ianstormtaylor/slate">GitHub</Link>
|
||||
<Link href="https://docs.slatejs.org/">Docs</Link>
|
||||
</LinkList>
|
||||
</Nav>
|
||||
<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 ? (
|
||||
{this.renderHeader()}
|
||||
{this.renderExampleHeader()}
|
||||
{this.renderTabList()}
|
||||
{this.state.error ? this.renderError() : this.renderExample()}
|
||||
<TabListUnderlay
|
||||
isVisible={this.state.isTabListVisible}
|
||||
onClick={this._hideTabList}
|
||||
/>
|
||||
</div>
|
||||
</HashRouter>
|
||||
)
|
||||
}
|
||||
|
||||
renderError() {
|
||||
return (
|
||||
<Warning>
|
||||
<p>
|
||||
An error was thrown by one of the example's React components!
|
||||
</p>
|
||||
<p>An error was thrown by one of the example's React components!</p>
|
||||
<pre>
|
||||
<code>
|
||||
{this.state.error.stack}
|
||||
@@ -215,18 +254,84 @@ export default class App extends React.Component {
|
||||
</code>
|
||||
</pre>
|
||||
</Warning>
|
||||
) : (
|
||||
<Example>
|
||||
)
|
||||
}
|
||||
|
||||
renderExample() {
|
||||
return (
|
||||
<Switch>
|
||||
{EXAMPLES.map(([name, Component, path]) => (
|
||||
<Route key={path} path={path} component={Component} />
|
||||
<Route key={path} path={path}>
|
||||
<div>
|
||||
<ExampleContent>
|
||||
<Component />
|
||||
</ExampleContent>
|
||||
</div>
|
||||
</Route>
|
||||
))}
|
||||
<Redirect from="/" to="/rich-text" />
|
||||
</Switch>
|
||||
</Example>
|
||||
)}
|
||||
</div>
|
||||
</HashRouter>
|
||||
)
|
||||
}
|
||||
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user