Skip to content

Commit bc06ab1

Browse files
authored
Feedback for system and header (#3547)
* button height should match input height * add select variant link * add sandbox as deps for app * add drop background * apply button styles only to first child
1 parent 5607878 commit bc06ab1

File tree

6 files changed

+115
-35
lines changed

6 files changed

+115
-35
lines changed

packages/app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
"@babel/preset-env": "^7.5.5",
7676
"@codesandbox/executors": "^0.1.0",
7777
"@codesandbox/template-icons": "^1.1.0",
78+
"@codesandbox/components": "0.0.1",
7879
"@emmetio/codemirror-plugin": "^0.3.5",
7980
"@sentry/webpack-plugin": "^1.8.0",
8081
"@styled-system/css": "^5.0.23",

packages/app/src/app/pages/Sandbox/Editor/Header/Actions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const Actions = () => {
4848
else primaryAction = owned ? 'Embed' : 'Fork';
4949

5050
return (
51-
<Stack align="center" gap={1} css={{ button: { width: 'auto' } }}>
51+
<Stack align="center" gap={1} css={{ '> button': { width: 'auto' } }}>
5252
{updateStatus === 'available' && (
5353
<TooltipButton
5454
tooltip="Update Available! Click to Refresh."

packages/common/src/themes/codesandbox-black.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const colors = {
6363
editorGroup: {
6464
background: tokens.grays[700],
6565
border: tokens.grays[600],
66-
dropBackground: tokens.grays[700],
66+
dropBackground: tokens.blues[500] + '1a',
6767
},
6868
editorGroupHeader: {
6969
noTabsBackground: null,

packages/components/src/components/Button/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const Button = styled(Element).attrs({ as: 'button' })<{
9494
fontFamily: 'Inter, sans-serif',
9595
paddingY: 0,
9696
paddingX: 2,
97-
height: 6,
97+
height: '26px', // match with inputs
9898
width: '100%',
9999
fontSize: 2,
100100
fontWeight: 'medium',

packages/components/src/components/Select/index.stories.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,37 @@ export const onChange = () => (
4444
</Select>
4545
</Element>
4646
);
47+
48+
export const Variants = () => (
49+
<Element style={{ width: 250 }}>
50+
<Select onChange={action('select')} placeholder="Please select an option">
51+
<option>One</option>
52+
<option>Two</option>
53+
</Select>
54+
<Select
55+
variant="link"
56+
onChange={action('select')}
57+
placeholder="Please select an option"
58+
>
59+
<option>One</option>
60+
<option>Two</option>
61+
</Select>
62+
<Select
63+
icon={Icon}
64+
onChange={action('select')}
65+
placeholder="Please select an option"
66+
>
67+
<option>One</option>
68+
<option>Two</option>
69+
</Select>
70+
<Select
71+
icon={Icon}
72+
variant="link"
73+
onChange={action('select')}
74+
placeholder="Please select an option"
75+
>
76+
<option>One</option>
77+
<option>Two</option>
78+
</Select>
79+
</Element>
80+
);
Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,78 @@
11
import React from 'react';
2+
import deepmerge from 'deepmerge';
23
import styled from 'styled-components';
34
import css from '@styled-system/css';
45
import { Input } from '../Input';
56
import { Element } from '../Element';
67

7-
// caret icon
8-
const svg = color =>
9-
`"data:image/svg+xml,%3Csvg width='8' height='24' viewBox='0 0 8 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.00006 17L1 13L7 13L4.00006 17Z' fill='%23${
10-
(color || '').split('#')[1]
11-
}'/%3E%3Cpath d='M3.99994 7L7 11H1L3.99994 7Z' fill='%23${
12-
(color || '').split('#')[1]
13-
}'/%3E%3C/svg%3E%0A"`;
8+
const variantStyles = {
9+
default: {
10+
// inherits from input
11+
},
12+
link: {
13+
border: 'none',
14+
backgroundColor: 'transparent',
15+
},
16+
};
1417

15-
const SelectComponent = styled(Input).attrs({ as: 'select' })(
16-
css({
17-
appearance: 'none',
18-
color: 'input.placeholderForeground',
19-
transition: 'all ease',
20-
transitionDuration: theme => theme.speeds[2],
18+
const variantCarets = {
19+
default: fill => `
20+
<svg width="8" height="24" viewBox="0 0 8 24" fill="none" xmlns="http://www.w3.org/2000/svg">
21+
<path d="M4 7L7 11H1L4 7Z" fill="${fill}" />
22+
<path d="M4 17L1 13L7 13L4 17Z" fill="${fill}" />
23+
</svg>
24+
`,
25+
link: fill => `
26+
<svg width="8" height="24" viewBox="0 0 8 24" fill="none" xmlns="http://www.w3.org/2000/svg">
27+
<path d="M4 15L1 11L7 11L4 15Z" fill="${fill}" />
28+
</svg>
29+
`,
30+
};
31+
// <path d="M4 14L1 10H7L4 14Z" fill="${fill}" />
2132

22-
paddingRight: 5, // select has a caret icon on the right
33+
const getSVG = (variant, color) => {
34+
const fill = '#' + (color || '').split('#')[1];
2335

24-
backgroundImage: theme =>
25-
theme && `url(${svg(theme.colors.input.placeholderForeground)})`,
26-
backgroundPosition: 'calc(100% - 8px) center',
27-
backgroundRepeat: 'no-repeat',
36+
// caret icon
37+
const svgString = variantCarets[variant](fill);
38+
39+
const header = 'data:image/svg+xml,';
40+
const encoded = encodeURIComponent(svgString)
41+
.replace(/'/g, '%27')
42+
.replace(/"/g, '%22');
43+
return header + encoded;
44+
};
45+
46+
const SelectComponent = styled(Input).attrs({ as: 'select' })<{
47+
variant?: string;
48+
}>(({ variant = 'default' }) =>
49+
css(
50+
deepmerge(variantStyles[variant], {
51+
appearance: 'none',
52+
color: 'input.placeholderForeground',
53+
transition: 'all ease',
54+
transitionDuration: theme => theme.speeds[2],
55+
56+
paddingRight: 5, // select has a caret icon on the right
2857

29-
':hover, :focus': {
30-
color: 'input.foreground',
3158
backgroundImage: theme =>
32-
theme && `url(${svg(theme.colors.input.foreground)})`,
33-
},
34-
})
59+
theme &&
60+
`url(${getSVG(variant, theme.colors.input.placeholderForeground)})`,
61+
backgroundPosition: 'calc(100% - 8px) center',
62+
backgroundRepeat: 'no-repeat',
63+
64+
':hover, :focus': {
65+
color: 'input.foreground',
66+
backgroundImage: theme =>
67+
theme && `url(${getSVG(variant, theme.colors.input.foreground)})`,
68+
},
69+
})
70+
)
3571
);
3672

37-
const SelectWithIcon = styled(Element)(
73+
const SelectWithIcon = styled(Element)<{
74+
variant?: string;
75+
}>(({ variant = 'default' }) =>
3876
css({
3977
position: 'relative',
4078
color: 'input.placeholderForeground',
@@ -57,7 +95,8 @@ const SelectWithIcon = styled(Element)(
5795
color: 'input.foreground',
5896
select: {
5997
color: 'input.foreground',
60-
backgroundImage: theme => `url(${svg(theme.colors.input.foreground)})`,
98+
backgroundImage: theme =>
99+
`url(${getSVG(variant, theme.colors.input.foreground)})`,
61100
},
62101
},
63102
})
@@ -71,25 +110,31 @@ interface ISelectProps {
71110
onChange?: any;
72111
value?: string | number;
73112
defaultValue?: string | number;
113+
variant?: string;
74114
}
75115

76116
export const Select = ({
77117
icon = null,
78118
placeholder = null,
79119
...props
80120
}: ISelectProps) => {
81-
const PrefixIcon = icon || React.Fragment;
82-
const SelectContainer = icon ? SelectWithIcon : React.Fragment;
121+
const PrefixIcon = icon;
83122

84-
return (
85-
<>
86-
<SelectContainer>
123+
if (icon)
124+
return (
125+
<SelectWithIcon variant={props.variant}>
87126
<PrefixIcon />
88127
<SelectComponent {...props}>
89128
{placeholder ? <option value="">{placeholder}</option> : null}
90129
{props.children}
91130
</SelectComponent>
92-
</SelectContainer>
93-
</>
131+
</SelectWithIcon>
132+
);
133+
134+
return (
135+
<SelectComponent {...props}>
136+
{placeholder ? <option value="">{placeholder}</option> : null}
137+
{props.children}
138+
</SelectComponent>
94139
);
95140
};

0 commit comments

Comments
 (0)