Skip to content

Commit

Permalink
chore(react-menu): implement local storybook with stories
Browse files Browse the repository at this point in the history
  • Loading branch information
Hotell committed Mar 15, 2021
1 parent 5c33b10 commit fa31ec3
Show file tree
Hide file tree
Showing 6 changed files with 378 additions and 2 deletions.
5 changes: 5 additions & 0 deletions packages/react-menu/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const rootMain = require('../../../.storybook/main');

module.exports = {
stories: [...rootMain.stories, '../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
};
9 changes: 9 additions & 0 deletions packages/react-menu/.storybook/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true
},
"exclude": ["../**/*.spec.ts", "../**/*.spec.js", "../**/*.spec.tsx", "../**/*.spec.jsx"],
"include": ["../src/**/*", "*.js"]
}
3 changes: 2 additions & 1 deletion packages/react-menu/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"code-style": "just-scripts code-style",
"just": "just-scripts",
"lint": "just-scripts lint",
"start": "just-scripts dev:storybook",
"start": "echo \"This is DEPRECATED instead use 'storybook'\" && just-scripts dev:storybook",
"storybook": "start-storybook",
"start-test": "echo \"This is DEPRECATED instead use 'test --watch'\" && just-scripts jest-watch",
"test": "jest",
"update-snapshots": "echo \"This is DEPRECATED instead use 'test -u'\" && just-scripts jest -u"
Expand Down
86 changes: 86 additions & 0 deletions packages/react-menu/src/components/Menu/Menu.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from 'react';
import {
Menu,
MenuTrigger,
MenuList,
MenuItem,
MenuItemRadio,
MenuItemCheckbox,
MenuGroup,
MenuDivider,
MenuGroupHeader,
} from '@fluentui/react-menu';
import { CutIcon, PasteIcon, EditIcon, AcceptIcon } from '@fluentui/react-icons-mdl2';

export const MenuExample = () => (
<>
<Menu>
<MenuTrigger>
<button>Toggle menu</button>
</MenuTrigger>

<MenuList>
<MenuItem>Item 1</MenuItem>
<MenuItem>Item 1</MenuItem>
<MenuItem>Item 1</MenuItem>
</MenuList>
</Menu>
</>
);

export const MenuControlledExample = () => {
const [open, setOpen] = React.useState(false);
return (
<>
<Menu open={open}>
<MenuTrigger>
<button onClick={() => setOpen(s => !s)}>Toggle menu</button>
</MenuTrigger>

<MenuList>
<MenuItem>Item 1</MenuItem>
<MenuItem>Item 1</MenuItem>
<MenuItem>Item 1</MenuItem>
</MenuList>
</Menu>
</>
);
};

export const MenuSelectionExample = () => (
<>
<Menu>
<MenuTrigger>
<button>Toggle menu</button>
</MenuTrigger>

<MenuList>
<MenuGroup>
<MenuGroupHeader>Checkbox group</MenuGroupHeader>
<MenuItemCheckbox icon={<CutIcon />} name="edit" value="cut" checkmark={<AcceptIcon />}>
Cut
</MenuItemCheckbox>
<MenuItemCheckbox icon={<PasteIcon />} name="edit" value="paste" checkmark={<AcceptIcon />}>
Paste
</MenuItemCheckbox>
<MenuItemCheckbox icon={<EditIcon />} name="edit" value="edit" checkmark={<AcceptIcon />}>
Edit
</MenuItemCheckbox>
</MenuGroup>
<MenuDivider />
<MenuGroup>
<MenuGroupHeader>Radio group</MenuGroupHeader>
<MenuItemRadio icon={<CutIcon />} name="font" value="segoe" checkmark={<AcceptIcon />}>
Segoe
</MenuItemRadio>
<MenuItemRadio icon={<PasteIcon />} name="font" value="calibri" checkmark={<AcceptIcon />}>
Caliri
</MenuItemRadio>
<MenuItemRadio icon={<EditIcon />} name="font" value="arial" checkmark={<AcceptIcon />}>
Arial
</MenuItemRadio>
</MenuGroup>
</MenuList>
</Menu>
</>
);
274 changes: 274 additions & 0 deletions packages/react-menu/src/components/MenuList/MenuList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
import * as React from 'react';

import {
MenuList,
MenuItem,
MenuItemCheckbox,
MenuItemRadio,
MenuGroup,
MenuDivider,
MenuGroupHeader,
MenuItemCheckboxProps,
MenuItemRadioProps,
MenuListProps,
} from '@fluentui/react-menu';
import { CutIcon, PasteIcon, EditIcon, AcceptIcon } from '@fluentui/react-icons-mdl2';
import { makeStylesCompat } from '@fluentui/react-make-styles';

const useContainerStyles = makeStylesCompat([
// This should eventually be the popup container styles
[
null,
theme => ({
backgroundColor: theme.alias.color.neutral.neutralBackground1,
minWidth: '128px',
minHeight: '48px',
maxWidth: '128px',
boxShadow: `${theme.alias.shadow.shadow16}`,
paddingTop: '4px',
paddingBottom: '4px',
}),
],
]);
const Container: React.FC = props => {
const classNames = useContainerStyles({});
return <div className={classNames}>{props.children}</div>;
};

export const MenuListExample = () => (
<Container>
<MenuList>
<MenuItem>Cut</MenuItem>
<MenuItem>Paste</MenuItem>
<MenuItem>Edit</MenuItem>
</MenuList>
</Container>
);

export const MenuListWithIconsExample = () => (
<Container>
<MenuList>
<MenuItem icon={<CutIcon />}>Cut</MenuItem>
<MenuItem icon={<PasteIcon />}>Paste</MenuItem>
<MenuItem icon={<EditIcon />}>Edit</MenuItem>
</MenuList>
</Container>
);

export const MenuListWithGroups = () => (
<Container>
<MenuList>
<MenuGroup>
<MenuGroupHeader>Section header</MenuGroupHeader>
<MenuItem icon={<CutIcon />}>Cut</MenuItem>
<MenuItem icon={<PasteIcon />}>Paste</MenuItem>
<MenuItem icon={<EditIcon />}>Edit</MenuItem>
</MenuGroup>
<MenuDivider />
<MenuGroup>
<MenuGroupHeader>Section header</MenuGroupHeader>
<MenuItem icon={<CutIcon />}>Cut</MenuItem>
<MenuItem icon={<PasteIcon />}>Paste</MenuItem>
<MenuItem icon={<EditIcon />}>Edit</MenuItem>
</MenuGroup>
</MenuList>
</Container>
);

export const MenuListWithDivider = () => (
<Container>
<MenuList>
<MenuItem icon={<CutIcon />}>Cut</MenuItem>
<MenuItem icon={<PasteIcon />}>Paste</MenuItem>
<MenuItem icon={<EditIcon />}>Edit</MenuItem>
<MenuDivider />
<MenuItem icon={<CutIcon />}>Cut</MenuItem>
<MenuItem icon={<PasteIcon />}>Paste</MenuItem>
<MenuItem icon={<EditIcon />}>Edit</MenuItem>
</MenuList>
</Container>
);

export const MenuListWithCheckboxes = (props: { defaultCheckedValues?: MenuListProps['defaultCheckedValues'] }) => {
const checkmark = <AcceptIcon />;

return (
<Container>
<MenuList defaultCheckedValues={props.defaultCheckedValues}>
<MenuItemCheckbox icon={<CutIcon />} name="edit" value="cut" checkmark={checkmark}>
Cut
</MenuItemCheckbox>
<MenuItemCheckbox icon={<PasteIcon />} name="edit" value="paste" checkmark={checkmark}>
Paste
</MenuItemCheckbox>
<MenuItemCheckbox icon={<EditIcon />} name="edit" value="edit" checkmark={checkmark}>
Edit
</MenuItemCheckbox>
</MenuList>
</Container>
);
};

export const MenuListWithRadios = () => {
const checkmark = <AcceptIcon />;

return (
<Container>
<MenuList>
<MenuItemRadio icon={<CutIcon />} name="font" value="segoe" checkmark={checkmark}>
Segoe
</MenuItemRadio>
<MenuItemRadio icon={<PasteIcon />} name="font" value="calibri" checkmark={checkmark}>
Calibri
</MenuItemRadio>
<MenuItemRadio icon={<EditIcon />} name="font" value="arial" checkmark={checkmark}>
Arial
</MenuItemRadio>
</MenuList>
</Container>
);
};

export const DefaultCheckedValues = () => <MenuListWithCheckboxes defaultCheckedValues={{ edit: ['cut'] }} />;

export const MenuListWithSelectionGroups = () => {
const checkmark = <AcceptIcon />;

return (
<Container>
<MenuList>
<MenuGroup>
<MenuGroupHeader>Checkbox group</MenuGroupHeader>
<MenuItemCheckbox icon={<CutIcon />} name="edit" value="cut" checkmark={checkmark}>
Cut
</MenuItemCheckbox>
<MenuItemCheckbox icon={<PasteIcon />} name="edit" value="paste" checkmark={checkmark}>
Paste
</MenuItemCheckbox>
<MenuItemCheckbox icon={<EditIcon />} name="edit" value="edit" checkmark={checkmark}>
Edit
</MenuItemCheckbox>
</MenuGroup>
<MenuDivider />
<MenuGroup>
<MenuGroupHeader>Radio group</MenuGroupHeader>
<MenuItemRadio icon={<CutIcon />} name="font" value="segoe" checkmark={checkmark}>
Segoe
</MenuItemRadio>
<MenuItemRadio icon={<PasteIcon />} name="font" value="calibri" checkmark={checkmark}>
Caliri
</MenuItemRadio>
<MenuItemRadio icon={<EditIcon />} name="font" value="arial" checkmark={checkmark}>
Arial
</MenuItemRadio>
</MenuGroup>
</MenuList>
</Container>
);
};

const MemoRadio = React.memo((props: MenuItemRadioProps) => {
// use icons in the memo because JSX will always create a new object
// possible to memoize icons but it can be overkill
return (
<MenuItemRadio icon={<EditIcon />} name={props.name} value={props.value} checkmark={<AcceptIcon />}>
{props.children}
</MenuItemRadio>
);
});

export const MemoRadioItems = () => {
return (
<Container>
<MenuList>
<MemoRadio name="font" value="segoe">
Segoe
</MemoRadio>
<MemoRadio name="font" value="calibri">
Calibri
</MemoRadio>
<MemoRadio name="font" value="arial">
Arial
</MemoRadio>
</MenuList>
</Container>
);
};

const MemoCheckbox = React.memo((props: MenuItemCheckboxProps) => {
// use icons in the memo because JSX will always create a new object
// possible to memoize icons but it can be overkill
return (
<MenuItemCheckbox icon={<EditIcon />} name={props.name} value={props.value} checkmark={<AcceptIcon />}>
{props.children}
</MenuItemCheckbox>
);
});

export const MemoCheckboxItems = () => {
return (
<Container>
<MenuList>
<MemoCheckbox name="font" value="segoe">
Segoe
</MemoCheckbox>
<MemoCheckbox name="font" value="calibri">
Calibri
</MemoCheckbox>
<MemoCheckbox name="font" value="arial">
Arial
</MemoCheckbox>
</MenuList>
</Container>
);
};

export const MenuListWithCheckboxesControlled = () => {
const checkmark = <AcceptIcon />;
const [checkedValues, setCheckedValues] = React.useState<Record<string, string[]>>({});
const onChange = (e: React.SyntheticEvent, name: string, items: string[]) => {
setCheckedValues(s => {
return s ? { ...s, [name]: items } : { [name]: items };
});
};

return (
<Container>
<MenuList checkedValues={checkedValues} onCheckedValueChange={onChange}>
<MenuItemCheckbox icon={<CutIcon />} name="edit" value="cut" checkmark={checkmark}>
Cut
</MenuItemCheckbox>
<MenuItemCheckbox icon={<PasteIcon />} name="edit" value="paste" checkmark={checkmark}>
Paste
</MenuItemCheckbox>
<MenuItemCheckbox icon={<EditIcon />} name="edit" value="edit" checkmark={checkmark}>
Edit
</MenuItemCheckbox>
</MenuList>
</Container>
);
};

export const MenuListWithRadiosControlled = () => {
const checkmark = <AcceptIcon />;
const [checkedValues, setCheckedValues] = React.useState<Record<string, string[]>>({ checkbox: ['2'] });
const onChange = (e: React.SyntheticEvent, name: string, items: string[]) => {
setCheckedValues(s => ({ ...s, [name]: items }));
};

return (
<Container>
<MenuList checkedValues={checkedValues} onCheckedValueChange={onChange}>
<MenuItemRadio icon={<CutIcon />} name="font" value="segoe" checkmark={checkmark}>
Segoe
</MenuItemRadio>
<MenuItemRadio icon={<PasteIcon />} name="font" value="calibri" checkmark={checkmark}>
Calibri
</MenuItemRadio>
<MenuItemRadio icon={<EditIcon />} name="font" value="arial" checkmark={checkmark}>
Arial
</MenuItemRadio>
</MenuList>
</Container>
);
};
3 changes: 2 additions & 1 deletion packages/react-menu/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
"preserveConstEnums": true,
"types": ["jest", "custom-global", "inline-style-expand-shorthand"]
},
"include": ["src"]
"include": ["src"],
"exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx"]
}

0 comments on commit fa31ec3

Please sign in to comment.