Skip to content

Commit 2bebc70

Browse files
authored
Add menu component (codesandbox#3589)
* add menu component * add support for as type i think * i dont know typescript * idk how to tell you, thats what i want
1 parent 9236106 commit 2bebc70

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

packages/components/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@codesandbox/common": "^1.0.8",
3232
"@codesandbox/template-icons": "^1.1.0",
3333
"@reach/auto-id": "^0.7.1",
34+
"@reach/menu-button": "^0.8.5",
3435
"@reach/visually-hidden": "^0.7.0",
3536
"@styled-system/css": "^5.1.4",
3637
"codesandbox-api": "0.0.24",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React from 'react';
2+
import deepmerge from 'deepmerge';
3+
import * as ReachMenu from '@reach/menu-button';
4+
import { Element } from '../Element';
5+
import { Button } from '../Button';
6+
import { List } from '../List';
7+
8+
const Menu = ({ ...props }) => (
9+
<Element as={ReachMenu.Menu} {...props}>
10+
{props.children}
11+
</Element>
12+
);
13+
14+
const MenuButton = ({ css = {}, ...props }) => (
15+
<Button
16+
// @ts-ignore
17+
as={ReachMenu.MenuButton}
18+
variant="link"
19+
css={deepmerge(css, { width: 'auto' })}
20+
{...props}
21+
>
22+
{props.children}
23+
</Button>
24+
);
25+
26+
const MenuList = props => (
27+
<List
28+
as={ReachMenu.MenuList}
29+
css={{
30+
minWidth: 100,
31+
backgroundColor: 'menuList.background',
32+
borderRadius: 3,
33+
boxShadow: 2,
34+
overflow: 'hidden',
35+
border: '1px solid',
36+
borderColor: 'menuList.border',
37+
':focus': { outline: 'none' },
38+
}}
39+
{...props}
40+
>
41+
{props.children}
42+
</List>
43+
);
44+
45+
const MenuItem = props => (
46+
<Element
47+
as={ReachMenu.MenuItem}
48+
css={{
49+
fontSize: 2,
50+
paddingY: 2,
51+
paddingX: 3,
52+
cursor: 'pointer',
53+
outline: 'none',
54+
color: 'menuList.foreground',
55+
'&[data-selected]': {
56+
outline: 'none',
57+
backgroundColor: 'menuList.hoverBackground',
58+
},
59+
}}
60+
{...props}
61+
/>
62+
);
63+
64+
Menu.Button = MenuButton;
65+
Menu.List = MenuList;
66+
Menu.Item = MenuItem;
67+
68+
export { Menu };
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from 'react';
2+
3+
import { Menu } from '.';
4+
import { Element } from '../Element';
5+
import { Stack } from '../Stack';
6+
import { Text } from '../Text';
7+
8+
export default {
9+
title: 'components/Menu',
10+
component: Menu,
11+
};
12+
13+
export const Access = () => {
14+
const permissions = ['Can View', 'Can Edit', 'Can Comment'];
15+
const [selected, select] = React.useState(permissions[0]);
16+
17+
return (
18+
<Stack justify="flex-end" align="center" css={{ '> *': { lineHeight: 1 } }}>
19+
<Menu>
20+
<Text size={2} variant="muted">
21+
Everyone with link
22+
</Text>{' '}
23+
<Menu.Button css={{ color: 'white' }}>
24+
{selected}{' '}
25+
<Element
26+
as="svg"
27+
marginLeft={2}
28+
width="7"
29+
height="4"
30+
viewBox="0 0 7 4"
31+
fill="none"
32+
xmlns="http://www.w3.org/2000/svg"
33+
>
34+
<path
35+
d="M3.95023 4L0.90033 1.23979e-06L7 7.15256e-07L3.95023 4Z"
36+
fill="currentColor"
37+
/>
38+
</Element>
39+
</Menu.Button>
40+
<Menu.List>
41+
{permissions.map(permission => (
42+
<Menu.Item onSelect={() => select(permission)}>
43+
{permission}
44+
</Menu.Item>
45+
))}
46+
</Menu.List>
47+
</Menu>
48+
</Stack>
49+
);
50+
};
51+
52+
export const IconButton = () => {
53+
const options = ['All', 'Open', 'Resolved', 'Mentions'];
54+
const [selected, select] = React.useState(options[0]);
55+
56+
return (
57+
<Stack justify="flex-end" align="center" css={{ '> *': { lineHeight: 1 } }}>
58+
<Menu>
59+
<Menu.Button
60+
css={{
61+
[selected !== options[0] && 'color']: 'blues.500',
62+
}}
63+
>
64+
<svg
65+
width="14"
66+
height="10"
67+
viewBox="0 0 14 10"
68+
fill="none"
69+
xmlns="http://www.w3.org/2000/svg"
70+
>
71+
<path
72+
fillRule="evenodd"
73+
clipRule="evenodd"
74+
d="M0 1C0 0.447715 0.447715 0 1 0H13C13.5523 0 14 0.447715 14 1C14 1.55228 13.5523 2 13 2H1C0.447716 2 0 1.55228 0 1ZM2 5C2 4.44772 2.44772 4 3 4H11C11.5523 4 12 4.44772 12 5C12 5.55228 11.5523 6 11 6H3C2.44772 6 2 5.55228 2 5ZM5 8C4.44772 8 4 8.44771 4 9C4 9.55229 4.44772 10 5 10H9C9.55228 10 10 9.55229 10 9C10 8.44771 9.55228 8 9 8H5Z"
75+
fill="currentColor"
76+
/>
77+
</svg>
78+
</Menu.Button>
79+
<Menu.List>
80+
{options.map(option => (
81+
<Menu.Item onSelect={() => select(option)}>{option}</Menu.Item>
82+
))}
83+
</Menu.List>
84+
</Menu>
85+
</Stack>
86+
);
87+
};

packages/components/src/utils/polyfill-theme.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const polyfillTheme = vsCodeTheme => {
3636
sideBar: {},
3737
activityBar: {},
3838
titleBar: {},
39+
menuList: {},
3940
};
4041

4142
const type = vsCodeTheme.type || guessType(vsCodeTheme);
@@ -186,6 +187,12 @@ const polyfillTheme = vsCodeTheme => {
186187
backgroundOn: uiColors.button.background,
187188
toggle: designLanguage.colors.white,
188189
},
190+
menuList: {
191+
background: uiColors.sideBar.background,
192+
border: uiColors.sideBar.border,
193+
hoverBackground: uiColors.sideBar.border,
194+
foreground: uiColors.sideBar.foreground,
195+
},
189196
};
190197

191198
uiColors = deepmerge(uiColors, addedColors);

0 commit comments

Comments
 (0)