Skip to content

Commit

Permalink
feat: screen resizer
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed May 31, 2020
1 parent 804cc93 commit 47d94ba
Show file tree
Hide file tree
Showing 15 changed files with 261 additions and 104 deletions.
67 changes: 44 additions & 23 deletions integrations/gatsby-theme-stories/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx jsx */
import React, { FC } from 'react';
import { jsx, Flex, Container } from 'theme-ui';
import React, { FC, useState } from 'react';
import { jsx, Container } from 'theme-ui';
import { Global } from '@emotion/core';
import {
ThemeProvider,
Expand All @@ -9,7 +9,11 @@ import {
TabList,
TabPanel,
} from '@component-controls/components';
import { SidebarContextProvider } from '@component-controls/app-components';
import {
SidebarContextProvider,
SidebarContext,
Resizer,
} from '@component-controls/app-components';
import { PageContainer } from '@component-controls/blocks';
import { Store } from '@component-controls/store';
import { SEO } from './SEO';
Expand Down Expand Up @@ -43,28 +47,45 @@ export const Layout: FC<LayoutProps> = ({
/>
<SEO title={title} />
<SidebarContextProvider>
<Flex sx={{ flexDirection: 'row', alignItems: 'stretch' }}>
<Sidebar storyId={storyId} />
<Container>
<Tabs>
<Header title={title}>
{pages.length > 1 && (
<TabList>
<SidebarContext.Consumer>
{({ collapsed }) => {
const content = (
<Container>
<Tabs>
<Header title={title}>
{pages.length > 1 && (
<TabList>
{pages.map(page => (
<Tab key={`tab_${page.key}`}>{page.title}</Tab>
))}
</TabList>
)}
</Header>

<PageContainer store={storyStore} storyId={storyId}>
{pages.map(page => (
<Tab key={`tab_${page.key}`}>{page.title}</Tab>
<TabPanel key={`panel_${page.key}`}>
{page.render()}
</TabPanel>
))}
</TabList>
)}
</Header>

<PageContainer store={storyStore} storyId={storyId}>
{pages.map(page => (
<TabPanel key={`panel_${page.key}`}>{page.render()}</TabPanel>
))}
</PageContainer>
</Tabs>
</Container>
</Flex>
</PageContainer>
</Tabs>
</Container>
);
return collapsed ? (
content
) : (
<Resizer
sectionOneProps={{
defaultSize: 300,
}}
>
<Sidebar storyId={storyId} />
{content}
</Resizer>
);
}}
</SidebarContext.Consumer>
</SidebarContextProvider>
</ThemeProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const Sidebar: FC<SidebarProps> = ({ storyId }) => {

const [search, setSearch] = useState<string | undefined>(undefined);
return (
<AppSidebar sx={{ px: 1, backgroundColor: 'sidebar' }} width={380}>
<AppSidebar sx={{ px: 1, backgroundColor: 'sidebar' }}>
{siteTitle}
<Box sx={{ py: 2 }}>
<Input
Expand Down
7 changes: 6 additions & 1 deletion integrations/storybook/src/docs-page/DocsContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ export const PageContextContainer: FC<DocsContainerProps> = ({
const isDark = useIsDark();
return (
<ThemeProvider theme={theme} dark={isDark}>
<BlockPageContainer store={store} storyId={storyId} options={options}>
<BlockPageContainer
maxWidth="1000px"
store={store}
storyId={storyId}
options={options}
>
{children}
</BlockPageContainer>
</ThemeProvider>
Expand Down
1 change: 1 addition & 0 deletions ui/app-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Third-party libraries used in no particular order:

- [theme-ui](https://theme-ui.com) as the theming and components foundation.
- [octicons](https://octicons.github.com) for icons used in the components.
- [react-simple-resizer](https://github.com/LeetCode-OpenSource/react-simple-resizer) for panels resizing.

# List of components

Expand Down
1 change: 1 addition & 0 deletions ui/app-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@primer/octicons-react": "^9.6.0",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"react-simple-resizer": "^2.1.0",
"theme-ui": "^0.3.1",
"@theme-ui/match-media": "^0.3.1"
},
Expand Down
14 changes: 5 additions & 9 deletions ui/app-components/src/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export interface HeaderProps {
*/
export const Header: FC<HeaderProps & BoxProps> = ({
children,
zIndex,
position,
zIndex = 10,
position = 'sticky',
...rest
}) => (
<Box
Expand All @@ -32,8 +32,9 @@ export const Header: FC<HeaderProps & BoxProps> = ({
zIndex,
}
: undefined),
background: 'primary',
p: 2,
position,
backgroundColor: 'background',
px: 2,
mb: 1,
justifyItems: 'between',
alignItems: 'center',
Expand All @@ -44,8 +45,3 @@ export const Header: FC<HeaderProps & BoxProps> = ({
{children}
</Box>
);

Header.defaultProps = {
position: 'relative',
zIndex: 10,
};
133 changes: 82 additions & 51 deletions ui/app-components/src/Navmenu/Navmenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
/** @jsx jsx */
import React, { FC, useEffect, useState } from 'react';
import { jsx, Box, Flex, Button, ButtonProps, LinkProps, Text } from 'theme-ui';
import {
jsx,
Box,
Flex,
Button,
ButtonProps,
LinkProps,
Text,
Theme,
} from 'theme-ui';
import Octicon, { ChevronDown, ChevronUp } from '@primer/octicons-react';
import {
Keyboard,
Expand Down Expand Up @@ -39,10 +48,8 @@ export interface NavMenuProps {
/** Array of menu items */
items: MenuItems;
/** Initially active menu item */
activeItem?: {
id?: string;
label?: string;
};
activeItem?: Pick<MenuItem, 'id' | 'label'>;

/** Custom class to use for the button instead of Button */
buttonClass?: ButtonClassType;

Expand All @@ -55,22 +62,28 @@ export interface NavMenuProps {
/** If specified, will filter the items by the search terms */
search?: string;
}
const isActive = (active: MenuItem, item: MenuItem): boolean =>
item.id === active.id || item.label === active.label;
const isActive = (
item: MenuItem,
active?: Pick<MenuItem, 'id' | 'label'>,
): boolean =>
active ? item.id === active.id || item.label === active.label : false;

const hasActiveChidlren = (active: MenuItem, item: MenuItem): boolean => {
if (isActive(active, item)) {
const hasActiveChidlren = (
item: MenuItem,
active?: Pick<MenuItem, 'id' | 'label'>,
): boolean => {
if (isActive(item, active)) {
return true;
}
return item.items
? item.items.some(t => hasActiveChidlren(active, t))
? item.items.some(t => hasActiveChidlren(t, active))
: false;
};

const getExpandedItems = (children: MenuItems, active?: MenuItem): MenuItems =>
children.reduce((expandedItems: MenuItems, item: MenuItem) => {
const { items, expanded } = item;
if (expanded || (active && hasActiveChidlren(active, item))) {
if (expanded || hasActiveChidlren(item, active)) {
expandedItems.push(item);
}
if (items) {
Expand Down Expand Up @@ -156,6 +169,36 @@ const filterItems = (items: MenuItems, search?: string): MenuItems => {
return items;
};

const stateFromProps = ({
items,
expandAll,
activeItem,
search,
}: Pick<NavMenuProps, 'items' | 'expandAll' | 'activeItem' | 'search'>) => {
const filteredItems = filterItems(items, search);
const collapsibleItems = getCollapsibleItems(filteredItems);
let expandedItems;
if (expandAll || (search && search.length)) {
expandedItems = collapsibleItems;
} else {
expandedItems = getExpandedItems(filteredItems, activeItem);
}

const allExpanded =
typeof expandAll !== 'undefined'
? expandAll
: collapsibleItems.length === expandedItems.length;
return {
expandedItems,
items,
filteredItems,
search,
collapsibleItems,
allExpanded,
expandAll,
originalExpandAll: expandAll,
};
};
interface NavMenuState {
expandedItems?: MenuItems;
originalExpandAll?: boolean;
Expand All @@ -170,50 +213,33 @@ interface NavMenuState {
* Hierarchical collapsible menu
*/

export const Navmenu: FC<NavMenuProps> = props => {
const stateFromProps = ({
items,
expandAll,
activeItem,
search,
}: Pick<NavMenuProps, 'items' | 'expandAll' | 'activeItem' | 'search'>) => {
const filteredItems = filterItems(items, search);
const collapsibleItems = getCollapsibleItems(filteredItems);
let expandedItems;
if (expandAll || (search && search.length)) {
expandedItems = collapsibleItems;
} else {
expandedItems = getExpandedItems(filteredItems, activeItem);
}

const allExpanded =
typeof expandAll !== 'undefined'
? expandAll
: collapsibleItems.length === expandedItems.length;
return {
expandedItems,
export const Navmenu: FC<NavMenuProps> = ({
items,
expandAll,
activeItem,
search,
onSelect,
buttonClass,
}) => {
const [state, setState] = useState<NavMenuState>(
stateFromProps({
items,
filteredItems,
search,
collapsibleItems,
allExpanded,
expandAll,
originalExpandAll: expandAll,
};
};

const [state, setState] = useState<NavMenuState>(stateFromProps(props));
activeItem,
search,
}),
);

useEffect(() => {
setState(
stateFromProps({
items: props.items,
expandAll: props.expandAll,
activeItem: props.activeItem,
search: props.search,
items,
expandAll,
activeItem,
search,
}),
);
}, [props.items, props.expandAll, props.activeItem, props.search]);
}, [items, expandAll, activeItem, search]);

const onMenuChange = (item: MenuItem, expanded: boolean) => {
const { expandedItems, filteredItems } = state;
Expand Down Expand Up @@ -243,7 +269,6 @@ export const Navmenu: FC<NavMenuProps> = props => {
};

const renderItem = (item: MenuItem, level: number = 1) => {
const { activeItem, onSelect, buttonClass } = props;
const { expandedItems } = state;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { items, id, label, widget, icon, onClick, ...rest } = item;
Expand All @@ -258,9 +283,14 @@ export const Navmenu: FC<NavMenuProps> = props => {
if (activeItem && activeItem.id === id) {
background = 'active';
}

const isActiveParent = hasActiveChidlren(item, activeItem);
const content = (
<Flex sx={{ background }}>
<Flex
sx={{
background,
pl: level,
}}
>
<ButtonClass
sx={{
width: '100%',
Expand All @@ -270,6 +300,8 @@ export const Navmenu: FC<NavMenuProps> = props => {
background: 'none',
textDecoration: 'none',
cursor: 'pointer',
borderLeft: (t: Theme) =>
isActiveParent ? `6px solid ${t.colors?.accent}` : 'none',
}}
onClick={() => {
if (items) {
Expand All @@ -285,7 +317,6 @@ export const Navmenu: FC<NavMenuProps> = props => {
flexDirection: 'row',
alignItems: 'center',
position: 'relative',
ml: level,
'& strong': {
color: 'text',
},
Expand Down
Loading

0 comments on commit 47d94ba

Please sign in to comment.