Skip to content

Commit

Permalink
feat: responsive sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed May 31, 2020
1 parent 3c85207 commit 99e0b7e
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 63 deletions.
44 changes: 24 additions & 20 deletions integrations/gatsby-theme-stories/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @jsx jsx */
import { FC, useContext } from 'react';
import { jsx } from 'theme-ui';
import { Flex } from '@theme-ui/components';
import { jsx, Flex, Text } from 'theme-ui';
import { Link as GatsbyLink } from 'gatsby';
import {
ColorMode,
SidebarContext,
Expand All @@ -11,36 +11,40 @@ import {
interface HeaderProps {
title?: string;
}
export const Header: FC<HeaderProps> = ({ children }) => {
const { SidebarToggle, collapsed } = useContext(SidebarContext);
export const Header: FC<HeaderProps> = () => {
const { SidebarToggle, collapsed, responsive } = useContext(SidebarContext);

return (
<AppHeader position="sticky">
<Flex
sx={{
py: 3,
flexDirection: 'row',
alignItems: `center`,
justifyContent: `space-between`,
alignItems: 'center',
color: `secondary`,
a: {
color: `secondary`,
':hover': { color: `accent` },
fontWeight: '700',
},
}}
>
<Flex sx={{ flexDirection: 'row', alignItems: 'center' }}>
{collapsed && <SidebarToggle />}
{children}
</Flex>

{collapsed && <SidebarToggle />}
<Flex
sx={{
boxSizing: `border-box`,
variant: `dividers.bottom`,
justifyContent: `space-between`,
color: `secondary`,
a: { color: `secondary`, ':hover': { color: `accent` } },
flexFlow: `wrap`,
flexDirection: 'row',
alignItems: 'center',
py: 3,
}}
></Flex>
<ColorMode />
>
<GatsbyLink to="/">
<Text sx={{ px: 2 }}>Home</Text>
</GatsbyLink>
<GatsbyLink to="/docs">
<Text sx={{ px: 2 }}>Docs</Text>
</GatsbyLink>
</Flex>
</Flex>
{!responsive && <ColorMode />}
</AppHeader>
);
};
32 changes: 16 additions & 16 deletions integrations/gatsby-theme-stories/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ export const Layout: FC<LayoutProps> = ({
/>
<SEO title={title} />
<SidebarContextProvider>
<Tabs fontSize={16}>
<Header title={title}>
{pages && pages.length > 1 && (
<TabList>
{pages.map(page => (
<Tab key={`tab_${page.key}`}>{page.title}</Tab>
))}
</TabList>
)}
</Header>
<Flex sx={{ flexDirection: 'row' }}>
<Sidebar storyId={storyId} />
<Container>
<Header title={title}></Header>
<Flex sx={{ flexDirection: 'row' }}>
<Sidebar storyId={storyId} />
<Container>
<Tabs fontSize={16}>
{pages && pages.length > 1 && (
<TabList>
{pages.map(page => (
<Tab key={`tab_${page.key}`}>{page.title}</Tab>
))}
</TabList>
)}

<PageContainer
store={storyStore}
storyId={storyId}
Expand All @@ -67,9 +67,9 @@ export const Layout: FC<LayoutProps> = ({
</TabPanel>
))}
</PageContainer>
</Container>
</Flex>
</Tabs>
</Tabs>
</Container>
</Flex>
</SidebarContextProvider>
</ThemeProvider>
);
Expand Down
42 changes: 27 additions & 15 deletions integrations/gatsby-theme-stories/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
/** @jsx jsx */
import { FC, useState, useMemo } from 'react';
import { FC, useState, useMemo, useContext } from 'react';
import { jsx, Input, LinkProps, Box, Theme } from 'theme-ui';

import { graphql, useStaticQuery, Link as GatsbyLink } from 'gatsby';
import { Story } from '@component-controls/specification';
import {
Sidebar as AppSidebar,
ColorMode,
SidebarContext,
Navmenu,
MenuItems,
MenuItem,
Header,
} from '@component-controls/app-components';

import { useSiteMetadata } from '../hooks/use-site-metadata';
Expand Down Expand Up @@ -62,7 +66,7 @@ const createMenuItem = (
};
export const Sidebar: FC<SidebarProps> = ({ storyId }) => {
const { siteTitle } = useSiteMetadata();

const { SidebarClose, responsive } = useContext(SidebarContext);
const data = useStaticQuery(graphql`
query {
allStory {
Expand Down Expand Up @@ -105,23 +109,31 @@ export const Sidebar: FC<SidebarProps> = ({ storyId }) => {
const [search, setSearch] = useState<string | undefined>(undefined);
return (
<AppSidebar
sx={{ px: 3, borderRight: (t: Theme) => `1px solid ${t.colors?.shadow}` }}
sx={{ borderRight: (t: Theme) => `1px solid ${t.colors?.shadow}` }}
width={380}
>
{siteTitle}
<Box sx={{ py: 2 }}>
<Input
placeholder="filter stories..."
value={search}
onChange={e => setSearch(e.target.value)}
{responsive && (
<Header shadow={false}>
<SidebarClose />
<ColorMode />
</Header>
)}
<Box sx={{ px: 2 }}>
{siteTitle}
<Box sx={{ py: 2, px: 3 }}>
<Input
placeholder="filter stories..."
value={search}
onChange={e => setSearch(e.target.value)}
/>
</Box>
<Navmenu
buttonClass={Link}
activeItem={{ id: storyId }}
search={search}
items={menuItems}
/>
</Box>
<Navmenu
buttonClass={Link}
activeItem={{ id: storyId }}
search={search}
items={menuItems}
/>
</AppSidebar>
);
};
19 changes: 14 additions & 5 deletions ui/app-components/src/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/** @jsx jsx */
import { FC } from 'react';
import { jsx, Box, BoxProps, Theme } from 'theme-ui';
import { jsx, Flex, BoxProps, Theme } from 'theme-ui';

export interface HeaderProps {
/** Position property for the header element */
position?: 'fixed' | 'absolute' | 'sticky' | 'static' | 'relative';

/** z-index for the header */
zIndex?: number;

/**
* whether to display a bottom border shadow
*/
shadow?: boolean;
}

/**
Expand All @@ -17,9 +22,10 @@ export const Header: FC<HeaderProps & BoxProps> = ({
children,
zIndex = 10,
position = 'sticky',
shadow = true,
...rest
}) => (
<Box
<Flex
as="header"
sx={{
...(position === 'fixed' ||
Expand All @@ -36,12 +42,15 @@ export const Header: FC<HeaderProps & BoxProps> = ({
backgroundColor: 'background',
px: 2,
mb: 1,
justifyItems: 'between',
justifyContent: `space-between`,
flexDirection: 'row',
alignItems: 'center',
boxShadow: (t: Theme) => `0 1px 3px 1px ${t.colors?.shadow}`,
boxShadow: shadow
? (t: Theme) => `0 1px 3px 1px ${t.colors?.shadow}`
: undefined,
}}
{...rest}
>
{children}
</Box>
</Flex>
);
23 changes: 20 additions & 3 deletions ui/app-components/src/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx jsx */
import React, { FC, useContext } from 'react';
import { jsx, Box, Flex, BoxProps, Heading } from 'theme-ui';
import { jsx, Box, Flex, BoxProps, Heading, SxStyleProp } from 'theme-ui';
import { SidebarContext } from './SidebarContext';

export interface SidebarProps {
Expand Down Expand Up @@ -33,9 +33,26 @@ export const Sidebar: FC<SidebarProps & BoxProps> = ({
...rest
}) => {
const toggleContext = useContext(SidebarContext);
const { collapsed } = toggleContext || {};
const { collapsed, responsive } = toggleContext || {};
const defaultStyle: SxStyleProp = {
overflowY: 'auto',
overflowX: 'hidden',
width,
};
const style: SxStyleProp = !responsive
? defaultStyle
: {
...defaultStyle,
position: 'absolute',
width: '100%',
minWidth: '100%',
zIndex: 9999,
backgroundColor: 'background',
top: 0,
left: 0,
};
return collapsed ? null : (
<Box sx={{ overflowY: 'auto', overflowX: 'hidden', width }} {...rest}>
<Box sx={style} {...rest}>
<Flex sx={{ pb: 1, flexDirection: 'row', alignItems: 'center' }}>
{title && (
<Box as="header">
Expand Down
31 changes: 27 additions & 4 deletions ui/app-components/src/Sidebar/SidebarContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC, createContext, useEffect } from 'react';
import { Button, ButtonProps } from 'theme-ui';
import Octicon, { ThreeBars } from '@primer/octicons-react';
import Octicon, { ThreeBars, X } from '@primer/octicons-react';
import { useBreakpointIndex } from '@theme-ui/match-media';

export type SidebarToggleProps = {
Expand All @@ -9,13 +9,17 @@ export type SidebarToggleProps = {

export interface SidebarContextProps {
SidebarToggle: FC<SidebarToggleProps>;
SidebarClose: FC<SidebarToggleProps>;
collapsed?: boolean;
collapsible?: boolean;
responsive: boolean;
setCollapsed: (value: boolean) => void;
}
export const SidebarContext = createContext<SidebarContextProps>({
SidebarToggle: () => null,
SidebarClose: () => null,
setCollapsed: () => {},
responsive: false,
});
export interface SidebarContextProviderProps {
collapsible?: boolean;
Expand All @@ -32,7 +36,7 @@ export const SidebarContextProvider: FC<SidebarContextProviderProps> = ({
if (collapsible) {
setCollapsed(size <= 1);
}
}, [size, collapsible, collapsed]);
}, [size, collapsible]);

const SidebarToggle: FC<SidebarToggleProps> = ({ icon, ...rest }) => {
return collapsible ? (
Expand All @@ -41,14 +45,31 @@ export const SidebarContextProvider: FC<SidebarContextProviderProps> = ({
onClick={() => setCollapsed(!collapsed)}
sx={{
background: 'none',
p: 2,
boxShadow: 'none',
cursor: 'pointer',
color: 'text',
}}
{...rest}
>
{icon || <Octicon icon={ThreeBars} />}
{icon || <Octicon size="medium" icon={ThreeBars} />}
</Button>
) : null;
};

const SidebarClose: FC<SidebarToggleProps> = ({ icon, ...rest }) => {
return collapsible ? (
<Button
aria-label={collapsed ? 'Expand side bar' : 'Collapse side bar'}
onClick={() => setCollapsed(true)}
sx={{
background: 'none',
boxShadow: 'none',
cursor: 'pointer',
color: 'text',
}}
{...rest}
>
{icon || <Octicon size="medium" icon={X} />}
</Button>
) : null;
};
Expand All @@ -58,7 +79,9 @@ export const SidebarContextProvider: FC<SidebarContextProviderProps> = ({
collapsed,
setCollapsed,
SidebarToggle,
SidebarClose,
collapsible,
responsive: size <= 1,
}}
>
{children}
Expand Down

0 comments on commit 99e0b7e

Please sign in to comment.