Skip to content

Commit

Permalink
feat: background and direction modes to playground
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed May 12, 2020
1 parent c662455 commit 58bf9f3
Show file tree
Hide file tree
Showing 17 changed files with 453 additions and 240 deletions.
66 changes: 36 additions & 30 deletions integrations/storybook/README.md

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion misc/storybook-custom-docs/preset copy.js

This file was deleted.

2 changes: 1 addition & 1 deletion misc/storybook-custom-docs/src/preview-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const attachPages = (pageConfigs, viewMode) => {
node.setAttribute('id', id);
document.body.appendChild(node);
}
const root = document.getElementById('storybook-root') || document.getElementById('root');
const root = document.getElementById('story-root') || document.getElementById('root');
const pageIndex = activePages.indexOf(id);
if (active) {
if (pageIndex < 0) {
Expand Down
66 changes: 36 additions & 30 deletions ui/blocks/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export const ComponentsBlockContainer: FC<ComponentsBlockContainerProps> = ({
}}
</ComponentsContainer>
);
console.log(visibility, React.Children.count(block));
return (
<BlockContainer
title={title}
Expand Down
142 changes: 39 additions & 103 deletions ui/blocks/src/Playground/Playground.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,36 @@
import React, { FC, MouseEvent } from 'react';
import React, { FC } from 'react';
import Octicon, { Plus, Dash, Sync } from '@primer/octicons-react';
import { useThemeUI } from 'theme-ui';
import {
Collapsible,
Tab,
Tabs,
TabList,
TabPanel,
getSortedPanels,
ActionItems,
ActionItem,
ActionContainer,
ActionContainerProps,
BackgroundType,
DirectionType,
PanelContainer,
PanelContainerProps,
IconButton,
Zoom,
} from '@component-controls/components';

import { Button, ButtonProps, useThemeUI } from 'theme-ui';
import {
StoryBlockContainer,
StoryBlockContainerProps,
} from '../BlockContainer';
import { StoryConfig } from '../StoryConfig';
import { StorySource } from '../StorySource';

const IconButton = (props: ButtonProps) => (
<Button style={{ paddingTop: '3px', paddingBottom: '3px' }} {...props} />
);

export interface PlaygroundOwnProps {
/**
* default scale for the zoom feature. If scale is set to 0, the zoom feature will be disabled.
*/
scale?: number;
/**
* by default, which tab to have open.
*/
openTab?: React.ReactNode;

/**
* whether to use the dark theme for the story source component.
*/
dark?: boolean;

/**
* if true, the tabs on story panels will be visible
*/
visibleTabs?: boolean;
}
export type PlaygroundProps = PlaygroundOwnProps &
StoryBlockContainerProps &
ActionContainerProps;
PanelContainerProps;

export const Playground: FC<PlaygroundProps> = ({
title,
Expand All @@ -62,11 +44,12 @@ export const Playground: FC<PlaygroundProps> = ({
visibleTabs = false,
scale: userScale = 1,
}) => {
const [tabsIndex, setTabsIndex] = React.useState<number | undefined>(
undefined,
);
const { theme } = useThemeUI();

const [scale, setScale] = React.useState(userScale);
const [background, setBackground] = React.useState<BackgroundType>('light');
const [direction, setDirection] = React.useState<DirectionType>('ltr');

React.useEffect(() => setScale(userScale), [userScale]);
let storyId: string;
const childArr = React.Children.toArray(children);
Expand All @@ -78,6 +61,7 @@ export const Playground: FC<PlaygroundProps> = ({
userActions.push({
title: 'source',
id: 'source',
group: 'panels',
'aria-label': 'display story source code',
panel: (
<StorySource dark={isDark} sxStyle={{ mt: 0, mb: 0 }} id={storyId} />
Expand All @@ -86,54 +70,13 @@ export const Playground: FC<PlaygroundProps> = ({
userActions.push({
title: 'config',
id: 'config',
group: 'panels',
'aria-label': 'display story configuration object',
panel: (
<StoryConfig dark={isDark} sxStyle={{ mt: 0, mb: 0 }} id={storyId} />
),
});
}
const panels: ActionItems = getSortedPanels(userActions);

React.useEffect(() => {
const index = panels.findIndex(
(p: ActionItem) => (p.id || p.title) === openTab,
);
setTabsIndex(index > -1 ? index : undefined);
}, [openTab]);
const panelActions = React.useMemo(
() =>
userActions.map((panel: ActionItem) => {
const index = panels.findIndex((p: ActionItem) => p.id === panel.id);
return panel.panel
? {
...panel,
title: `${tabsIndex === index ? 'close' : 'open'} ${panel.title}`,
onClick: (e: MouseEvent<HTMLButtonElement>) => {
if (index < 0) {
return undefined;
}
if (tabsIndex === index) {
setTabsIndex(undefined);
} else {
if (panel.onClick) {
const ret = panel.onClick(e);
if (ret === true) {
setTabsIndex(index);
return ret;
} else if (ret === false) {
setTabsIndex(undefined);
return ret;
}
}
setTabsIndex(index);
}
return undefined;
},
}
: panel;
}),
[userActions],
);
const zoomActions = React.useMemo(
() => [
{
Expand Down Expand Up @@ -172,9 +115,23 @@ export const Playground: FC<PlaygroundProps> = ({
],
[scale],
);
const storyActions = [
{
title: background === 'light' ? 'dark' : 'light',
id: 'background',
group: 'story',
onClick: () => setBackground(background === 'light' ? 'dark' : 'light'),
},
{
title: direction === 'rtl' ? 'LTR' : 'RTL',
id: 'direction',
group: 'story',
onClick: () => setDirection(direction === 'rtl' ? 'ltr' : 'rtl'),
},
];
const actionsItems = userScale
? [...zoomActions, ...panelActions]
: panelActions;
? [...storyActions, ...zoomActions, ...userActions]
: [...storyActions, ...userActions];
return (
<StoryBlockContainer
useStoryDescription={true}
Expand All @@ -184,37 +141,16 @@ export const Playground: FC<PlaygroundProps> = ({
collapsible={collapsible}
>
{() => (
<ActionContainer plain={false} actions={actionsItems}>
<PanelContainer
plain={false}
actions={actionsItems}
openTab={openTab}
visibleTabs={visibleTabs}
background={background}
direction={direction}
>
<Zoom scale={scale || 1}>{children}</Zoom>
<Collapsible isOpen={tabsIndex !== undefined}>
{panels.length === 1 ? (
panels[0].panel
) : (
<Tabs
selectedIndex={tabsIndex || 0}
onSelect={(index: number) => setTabsIndex(index)}
>
<TabList
hidden={!visibleTabs}
style={{
textAlign: 'right',
}}
>
{panels.map((panel: ActionItem) => (
<Tab key={`playground_tab_${panel.title}`}>
{panel.title}
</Tab>
))}
</TabList>
{panels.map((panel: ActionItem) => (
<TabPanel key={`playground_panel_${panel.title}`}>
{panel.panel}
</TabPanel>
))}
</Tabs>
)}
</Collapsible>
</ActionContainer>
</PanelContainer>
)}
</StoryBlockContainer>
);
Expand Down
75 changes: 45 additions & 30 deletions ui/blocks/src/Story/Story.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @jsx jsx */
import { FC, createElement } from 'react';
import { FC, createElement, forwardRef } from 'react';
import { jsx, Box } from 'theme-ui';
import { deepMerge, StoryRenderFn } from '@component-controls/specification';
import { getControlValues } from '@component-controls/core';
Expand All @@ -8,35 +8,50 @@ import {
StoryBlockContainerProps,
} from '../BlockContainer/story';

export type StoryProps = StoryBlockContainerProps;
export type StoryProps = StoryBlockContainerProps & {
ref?: React.Ref<HTMLDivElement>;
};

export const Story: FC<StoryProps> = (props: StoryProps) => (
<StoryBlockContainer {...props}>
{(context, rest) => {
const { story, options = {} } = context;
if (story && story.renderFn) {
try {
const values = getControlValues(story.controls);
const { decorators: globalDecorators = [] } = options;
const { decorators: storyDecorators = [] } = story;
const decorators = deepMerge(globalDecorators, storyDecorators);
const renderFn = decorators.reduce(
(acc: StoryRenderFn, item: StoryRenderFn) => () =>
item(acc, { context }),
//@ts-ignore
() => story.renderFn(values, { context }),
);
return (
<Box id={story.id} sx={{ px: 3 }} {...rest}>
<div style={{ all: 'unset' }}>{createElement(renderFn)}</div>
</Box>
);
} catch (e) {
console.error(e);
export const Story: FC<StoryProps> = forwardRef(
(props: StoryProps, ref: React.Ref<HTMLDivElement>) => (
<StoryBlockContainer {...props}>
{(context, rest) => {
const { story, options = {} } = context;
if (story && story.renderFn) {
try {
const values = getControlValues(story.controls);
const { decorators: globalDecorators = [] } = options;
const { decorators: storyDecorators = [] } = story;
const decorators = deepMerge(globalDecorators, storyDecorators);
const renderFn = decorators.reduce(
(acc: StoryRenderFn, item: StoryRenderFn) => () =>
item(acc, { context }),
//@ts-ignore
() => story.renderFn(values, { context }),
);
return (
<Box
id={story.id}
sx={{
px: 4,
py: 3,
}}
{...rest}
>
<div style={{ all: 'unset' }} ref={ref}>
{createElement(renderFn)}
</div>
</Box>
);
} catch (e) {
console.error(e);
}
}
}
console.error('Story function not found', props, story);
return null;
}}
</StoryBlockContainer>
console.error('Story function not found', props, story);
return null;
}}
</StoryBlockContainer>
),
);

Story.displayName = 'Story';
54 changes: 42 additions & 12 deletions ui/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- [<ins>Collapsible</ins>](#inscollapsibleins)
- [<ins>ExternalLink</ins>](#insexternallinkins)
- [<ins>Markdown</ins>](#insmarkdownins)
- [<ins>IconButton</ins>](#insiconbuttonins)
- [<ins>PanelContainer</ins>](#inspanelcontainerins)
- [<ins>Popover</ins>](#inspopoverins)
- [<ins>Source</ins>](#inssourceins)
- [<ins>Subtitle</ins>](#inssubtitleins)
Expand Down Expand Up @@ -146,6 +148,33 @@ _Markdown [source code](https:/github.com/ccontrols/component-controls/tree/mast
| `children` | _ReactNode_ | the markdown source code is passed as a children pro. |
| `components` | _{ \[key: string]: ComponentOverride&lt;any, any>; a?: ComponentOverride&lt;any, any>; br?: ComponentOverride&lt;any, any>; button?: ComponentOverride&lt;any, any>; ... 27 more ...; ul?: ComponentOverride&lt;...>; }_ | components to customize the markdown display. |

## <ins>IconButton</ins>

_IconButton [source code](https:/github.com/ccontrols/component-controls/tree/master/ui/components/src/PanelContainer/PanelContainer.tsx)_

### properties

| Name | Type | Description |
| ----- | ---------------------------------------------------------------------------- | ----------- |
| `ref` | _((instance: HTMLButtonElement) => void) \| RefObject&lt;HTMLButtonElement>_ | |

## <ins>PanelContainer</ins>

an action container with built-in collapsible panels

_PanelContainer [source code](https:/github.com/ccontrols/component-controls/tree/master/ui/components/src/PanelContainer/PanelContainer.tsx)_

### properties

| Name | Type | Description |
| ------------- | ---------------- | --------------------------------------------------------- |
| `openTab` | _any_ | by default, which tab to have open. |
| `visibleTabs` | _boolean_ | if true, the tabs on the panels will be visible |
| `background` | _BackgroundType_ | background pattern type |
| `direction` | _DirectionType_ | direction type |
| `actions` | _ActionItem\[]_ | optional actions provided to the component |
| `plain` | _boolean_ | if plain, skip the border and spacing around the children |

## <ins>Popover</ins>

A Popover container that is triggered by a click/hover event.
Expand Down Expand Up @@ -214,18 +243,19 @@ _Table [source code](https:/github.com/ccontrols/component-controls/tree/master/

### properties

| Name | Type | Description |
| --------------- | ------------------------------ | ------------------------------------------------------------------------------ |
| `columns*` | _Column&lt;{}>\[]_ | the colmns object as an array. |
| `data` | _any\[]_ | array of data rows. |
| `header` | _boolean_ | show or hide the header element. |
| `sorting` | _boolean_ | enable.disable sorting. |
| `filtering` | _boolean_ | enable/disable filtering. |
| `itemsLabel` | _string_ | string label for 'items' - used in the filter placeholder and grouping header. |
| `groupBy` | _string\[]_ | field to be grouped by. |
| `hiddenColumns` | _string\[]_ | list of columns to hide. |
| `expanded` | _{ \[key: string]: boolean; }_ | object listing the initially expanded rows. |
| `skipPageReset` | _boolean_ | reset state update while update table data |
| Name | Type | Description |
| ----------------------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
| `columns*` | _Column&lt;{}>\[]_ | the columns object as an array. |
| `data` | _any\[]_ | array of data rows. |
| `header` | _boolean_ | show or hide the header element. |
| `sorting` | _boolean_ | enable.disable sorting. |
| `filtering` | _boolean_ | enable/disable filtering. |
| `itemsLabel` | _string_ | string label for 'items' - used in the filter placeholder and grouping header. |
| `groupBy` | _string\[]_ | field to be grouped by. |
| `hiddenColumns` | _string\[]_ | list of columns to hide. |
| `expanded` | _{ \[key: string]: boolean; }_ | object listing the initially expanded rows. |
| `skipPageReset` | _boolean_ | reset state update while update table data |
| `renderRowSubComponent` | _(props: { row: Row&lt;{}>; }) => ReactNode_ | |

## <ins>Tab</ins>

Expand Down
Loading

0 comments on commit 58bf9f3

Please sign in to comment.