docs(website): sidebar mobile
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex } from 'reflexbox';
|
||||
|
||||
import { getThemeSpacePx } from 'utils/css-utils';
|
||||
import Icon from 'components/Icon';
|
||||
|
||||
const Close = styled(Flex)`
|
||||
padding: ${getThemeSpacePx(1)};
|
||||
line-height: 1;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
`;
|
||||
|
||||
export default ({ onClick, ...props }) => {
|
||||
return (
|
||||
<Flex pb={4} alignItems="center" justifyContent="center" {...props}>
|
||||
<Close alignItems="center" justifyContent="center" onClick={onClick}>
|
||||
<Icon name="close" strokeColor="text" colorizeStroke />
|
||||
</Close>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,14 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'gatsby';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex, Box } from 'reflexbox';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Button from 'components/Button';
|
||||
import Close from 'components/Close';
|
||||
import { getThemeColor, getThemeSpacePx, device, px } from 'utils/css-utils';
|
||||
import useMenuHeight from 'hooks/useMenuHeight';
|
||||
|
||||
import ReactFlowLogo from 'assets/images/react-flow-logo.svg';
|
||||
|
||||
const Centered = styled(Flex)`
|
||||
@@ -26,7 +29,7 @@ const NavWrapper = styled(Box)`
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: ${getThemeSpacePx(3)};
|
||||
z-index: 100;
|
||||
z-index: 500;
|
||||
background: ${getThemeColor('background')};
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
@@ -112,6 +115,18 @@ const NavItem = styled(Link)`
|
||||
`;
|
||||
|
||||
const GithubButton = styled.a`
|
||||
font-size: 30px;
|
||||
display: block;
|
||||
padding: ${(p) => (p.isButton ? '8px 16px' : '16px 0')};
|
||||
text-align: center;
|
||||
color: ${getThemeColor('textLight')};
|
||||
|
||||
&:focus,
|
||||
&:visited,
|
||||
&:active {
|
||||
color: ${getThemeColor('textLight')};
|
||||
}
|
||||
|
||||
@media ${device.tablet} {
|
||||
margin-left: 50px;
|
||||
font-size: 16px;
|
||||
@@ -126,16 +141,6 @@ const GithubButton = styled.a`
|
||||
}
|
||||
`;
|
||||
|
||||
const Close = styled.div`
|
||||
padding: ${getThemeSpacePx(1)};
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
`;
|
||||
|
||||
const NavButton = styled.div`
|
||||
cursor: pointer;
|
||||
|
||||
@@ -166,10 +171,9 @@ const LogoSubtitle = styled(Box)`
|
||||
`;
|
||||
|
||||
const Header = () => {
|
||||
const [menuHeight, setMenuHeight] = useState(
|
||||
typeof window !== 'undefined' ? window.innerHeight : 0
|
||||
);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const menuHeight = useMenuHeight();
|
||||
|
||||
const toggleMenu = () => {
|
||||
const nextMenuOpen = !menuOpen;
|
||||
|
||||
@@ -178,18 +182,6 @@ const Header = () => {
|
||||
setMenuOpen(nextMenuOpen);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => {
|
||||
setMenuHeight(typeof window !== 'undefined' ? window.innerHeight : 0);
|
||||
};
|
||||
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Centered>
|
||||
@@ -228,21 +220,17 @@ const Header = () => {
|
||||
Github
|
||||
</Button>
|
||||
|
||||
<a
|
||||
<GithubButton
|
||||
href="https://github.com/wbkd/react-flow"
|
||||
activeClassName="active"
|
||||
className="mobile"
|
||||
isButton
|
||||
>
|
||||
Github
|
||||
</a>
|
||||
</GithubButton>
|
||||
</NavInner>
|
||||
</Nav>
|
||||
<Flex pb={4} alignItems="center" className="mobile">
|
||||
<Close onClick={toggleMenu}>
|
||||
<Icon name="close" strokeColor="text" colorizeStroke />
|
||||
</Close>
|
||||
</Flex>
|
||||
<Close onClick={toggleMenu} className="mobile" />
|
||||
</NavWrapper>
|
||||
</Centered>
|
||||
</Wrapper>
|
||||
|
||||
@@ -9,15 +9,11 @@ const Wrapper = styled(Flex)`
|
||||
border-top: 1px solid ${(p) => p.theme.colors.silverLighten30};
|
||||
`;
|
||||
|
||||
const left =
|
||||
typeof window !== 'undefined' && window.innerWidth > 1000
|
||||
? Math.min(350, window.innerWidth * 0.3) / 2
|
||||
: 0;
|
||||
|
||||
const DocWrapper = styled(Box)`
|
||||
max-width: 620px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
padding: 0 16px;
|
||||
`;
|
||||
|
||||
export default ({ children, menu = [], ...rest }) => (
|
||||
|
||||
@@ -1,14 +1,54 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { Fragment, useState } from 'react';
|
||||
import Link from 'gatsby-link';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex } from 'reflexbox';
|
||||
|
||||
import { getThemeColor, getThemeSpacePx } from 'utils/css-utils';
|
||||
import Icon from 'components/Icon';
|
||||
import Close from 'components/Close';
|
||||
import useMenuHeight from 'hooks/useMenuHeight';
|
||||
import { getThemeColor, getThemeSpacePx, device, px } from 'utils/css-utils';
|
||||
|
||||
const Aside = styled.aside`
|
||||
width: 30%;
|
||||
max-width: 300px;
|
||||
padding: 16px;
|
||||
border-right: 1px solid ${getThemeColor('silverLighten30')};
|
||||
display: ${(p) => (p.isOpen ? 'block' : 'none')};
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: ${(p) => px(p.height)};
|
||||
overflow-y: auto;
|
||||
background: white;
|
||||
z-index: 400;
|
||||
|
||||
@media ${device.tablet} {
|
||||
width: 30%;
|
||||
max-width: 300px;
|
||||
padding: 16px;
|
||||
border-right: 1px solid ${getThemeColor('silverLighten30')};
|
||||
display: block;
|
||||
position: relative;
|
||||
height: auto;
|
||||
|
||||
.mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const AsideInner = styled.div``;
|
||||
|
||||
const MobileButton = styled(Flex)`
|
||||
z-index: 10;
|
||||
background: ${getThemeColor('violetLighten5')};
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
color: white;
|
||||
border-radius: 100%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const MenuLink = styled(Link)`
|
||||
@@ -53,10 +93,34 @@ const SideBarParts = ({ items, level }) =>
|
||||
});
|
||||
|
||||
const Sidebar = ({ menu }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const menuHeight = useMenuHeight();
|
||||
|
||||
const toggleSidebar = () => {
|
||||
const nextMenuOpen = !isOpen;
|
||||
|
||||
document.body.classList.toggle('noscroll', nextMenuOpen);
|
||||
|
||||
setIsOpen(nextMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<Aside>
|
||||
<SideBarParts items={menu} level={0} />
|
||||
</Aside>
|
||||
<>
|
||||
<MobileButton onClick={toggleSidebar}>
|
||||
<Icon
|
||||
name="menu"
|
||||
width="24px"
|
||||
colorizeStroke
|
||||
strokeColor="silverLighten60"
|
||||
/>
|
||||
</MobileButton>
|
||||
<Aside isOpen={isOpen} height={menuHeight}>
|
||||
<AsideInner>
|
||||
<SideBarParts items={menu} level={0} />
|
||||
<Close className="mobile" onClick={toggleSidebar} />
|
||||
</AsideInner>
|
||||
</Aside>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
const getInnerHeight = () => {
|
||||
return typeof window !== 'undefined' ? window.innerHeight : 0;
|
||||
};
|
||||
|
||||
export default function useMenuHeight() {
|
||||
const [menuHeight, setMenuHeight] = useState(getInnerHeight());
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => {
|
||||
setMenuHeight(getInnerHeight());
|
||||
};
|
||||
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
};
|
||||
});
|
||||
|
||||
return menuHeight;
|
||||
}
|
||||
@@ -2,14 +2,34 @@ import React from 'react';
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
|
||||
const elements = [
|
||||
{ id: '1', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||
// you can also pass a React component as a label
|
||||
{ id: '2', data: { label: <div>Node 2</div> }, position: { x: 100, y: 100 } },
|
||||
// input node
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'Input Node' },
|
||||
position: { x: 250, y: 25 },
|
||||
},
|
||||
// default node
|
||||
{
|
||||
id: '2',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: <div>Default Node</div> },
|
||||
position: { x: 100, y: 125 },
|
||||
},
|
||||
// output node
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: 'Output Node' },
|
||||
position: { x: 250, y: 250 },
|
||||
},
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e2-3', source: '2', target: '3' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<div style={{ height: 400, border: '1px solid #EAEDF1', borderRadius: 5 }}>
|
||||
<div style={{ height: 300, border: '1px solid #EAEDF1', borderRadius: 5 }}>
|
||||
<ReactFlow elements={elements} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -25,10 +25,31 @@ import React from 'react';
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
|
||||
const elements = [
|
||||
{ id: '1', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||
// you can also pass a React component as a label
|
||||
{ id: '2', data: { label: <div>Node 2</div> }, position: { x: 100, y: 100 } },
|
||||
// input node
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'Input Node' },
|
||||
position: { x: 250, y: 25 },
|
||||
},
|
||||
// default node
|
||||
{
|
||||
id: '2',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: <div>Default Node</div> },
|
||||
position: { x: 100, y: 125 },
|
||||
},
|
||||
// output node
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: 'Output Node' },
|
||||
position: { x: 250, y: 250 },
|
||||
},
|
||||
// animated edge
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e2-3', source: '2', target: '3' },
|
||||
];
|
||||
|
||||
const BasicFlow = () => <ReactFlow elements={elements} />;
|
||||
|
||||
@@ -100,7 +100,7 @@ const Home = () => {
|
||||
<Flex mt={3} alignItems="center">
|
||||
<DocsButton
|
||||
as={Link}
|
||||
to="/docs"
|
||||
to="/docs/"
|
||||
icon="code"
|
||||
colorizeStroke
|
||||
color="textInverted"
|
||||
@@ -108,7 +108,7 @@ const Home = () => {
|
||||
>
|
||||
Documentation
|
||||
</DocsButton>
|
||||
<ExampleButton to="/examples">
|
||||
<ExampleButton to="/examples/">
|
||||
Examples
|
||||
<Icon
|
||||
width="24px"
|
||||
|
||||
@@ -9,7 +9,7 @@ import CodeBlock from 'components/CodeBlock/Mdx';
|
||||
|
||||
import { getThemeSpacePx } from 'utils/css-utils';
|
||||
|
||||
const PostWrapper = styled.div`
|
||||
const DocWrapper = styled.div`
|
||||
${Text} {
|
||||
margin-bottom: ${getThemeSpacePx(3)};
|
||||
margin-top: ${getThemeSpacePx(3)};
|
||||
@@ -18,16 +18,21 @@ const PostWrapper = styled.div`
|
||||
background: rgb(246, 248, 250);
|
||||
border-radius: 2px;
|
||||
padding: 0 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: ${getThemeSpacePx(5)};
|
||||
padding-left: ${getThemeSpacePx(4)};
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: ${getThemeSpacePx(2)};
|
||||
|
||||
code {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
@@ -123,9 +128,9 @@ const CustomComponents = {
|
||||
const BlogMdx = ({ content = null }) => {
|
||||
return (
|
||||
<MDXProvider components={CustomComponents}>
|
||||
<PostWrapper>
|
||||
<DocWrapper>
|
||||
<MDXRenderer>{content}</MDXRenderer>
|
||||
</PostWrapper>
|
||||
</DocWrapper>
|
||||
</MDXProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user