Skip to content

Commit 7b4f901

Browse files
authored
Small improvements to dependency picker (codesandbox#363)
1 parent a135fcb commit 7b4f901

File tree

3 files changed

+84
-9
lines changed

3 files changed

+84
-9
lines changed

packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddVersion.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import modalActionCreators from 'app/store/modal/actions';
88

99
import SearchDependencies from './SearchDependencies';
1010

11-
const ButtonContainer = styled.div`margin: 0.5rem 1rem;`;
11+
const ButtonContainer = styled.div`
12+
margin: 0.5rem 1rem;
13+
`;
1214

1315
type Props = {
1416
addDependency: (dependency: string, version: string) => Promise<boolean>,

packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/DependencyHit.js

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React from 'react';
22
import HomeIcon from 'react-icons/lib/io/home';
3+
import SearchIcon from 'react-icons/lib/go/search';
34
import { Highlight } from 'react-instantsearch/dom';
45
import styled from 'styled-components';
56

67
import Select from 'app/components/Select';
8+
import UserWithAvatar from 'app/components/user/UserWithAvatar';
79
import Tooltip from 'common/components/Tooltip';
810

911
import GitHubLogo from '../Git/modals/GitHubLogo';
@@ -12,12 +14,18 @@ import formatDownloads from './formatDownloads';
1214
const Container = styled.div`
1315
display: flex;
1416
background: ${props =>
15-
props.highlighted ? props.theme.background3 : props.theme.background2};
17+
props.highlighted
18+
? props.theme.background2.darken(0.3)
19+
: props.theme.background2};
1620
color: ${props => props.theme.white};
1721
cursor: pointer;
1822
&:not(:last-child) {
1923
border-bottom: 1px solid ${props => props.theme.background3};
2024
}
25+
26+
&:hover {
27+
background-color: ${props => props.theme.background2.darken(0.2)};
28+
}
2129
`;
2230

2331
const Left = styled.div`
@@ -36,16 +44,22 @@ const Row = styled.div`
3644
}
3745
`;
3846

47+
const Description = Row.extend`
48+
font-size: 0.875rem;
49+
color: rgba(255, 255, 255, 0.6);
50+
`;
51+
3952
const Downloads = styled.span`
4053
color: ${props => props.theme.gray};
54+
font-weight: 500;
4155
font-size: 12px;
4256
`;
4357

4458
const License = styled.span`
45-
border: 1px solid ${props => props.theme.gray};
59+
border: 1px solid rgba(255, 255, 255, 0.4);
4660
border-radius: 3px;
4761
padding: 1px 3px;
48-
color: ${props => props.theme.gray};
62+
color: rgba(255, 255, 255, 0.6);
4963
font-size: 12px;
5064
`;
5165

@@ -54,6 +68,15 @@ const IconLink = styled.a`
5468
color: rgba(255, 255, 255, 0.8);
5569
`;
5670

71+
const StyledSelect = Select.extend`
72+
font-size: 0.875rem;
73+
`;
74+
75+
const StyledUserWithAvatar = styled(UserWithAvatar)`
76+
font-size: 0.75rem;
77+
font-weight: 500;
78+
`;
79+
5780
type Props = {
5881
highlighted: boolean,
5982
hit: Object,
@@ -77,6 +100,12 @@ export default class DependencyHit extends React.PureComponent {
77100
return `https://github.com/${repo.user}/${repo.project}`;
78101
}
79102

103+
makeSearchUrl(hitName: string) {
104+
return `https://codesandbox.io/search?refinementList%5Bnpm_dependencies.dependency%5D%5B0%5D=${
105+
hitName
106+
}&page=1`;
107+
}
108+
80109
stopPropagation(e) {
81110
e.stopPropagation();
82111
}
@@ -91,6 +120,7 @@ export default class DependencyHit extends React.PureComponent {
91120
const { highlighted, hit, onClick } = this.props;
92121
const versions = Object.keys(hit.versions);
93122
versions.reverse();
123+
94124
return (
95125
<Container highlighted={highlighted} onClick={onClick}>
96126
<Left>
@@ -99,7 +129,13 @@ export default class DependencyHit extends React.PureComponent {
99129
<Downloads>{formatDownloads(hit.downloadsLast30Days)}</Downloads>
100130
{hit.license && <License>{hit.license}</License>}
101131
</Row>
102-
<Row>{hit.description}</Row>
132+
<Description>{hit.description}</Description>
133+
<Row>
134+
<StyledUserWithAvatar
135+
username={hit.owner.name}
136+
avatarUrl={hit.owner.avatar}
137+
/>
138+
</Row>
103139
</Left>
104140
<Right>
105141
<Row>
@@ -127,13 +163,23 @@ export default class DependencyHit extends React.PureComponent {
127163
</IconLink>
128164
</Tooltip>
129165
)}
130-
<Select
166+
<Tooltip title={`Search for sandboxes using ${hit.name}`}>
167+
<IconLink
168+
href={this.makeSearchUrl(hit.name)}
169+
target="_blank"
170+
rel="noreferrer noopener"
171+
onClick={this.stopPropagation}
172+
>
173+
<SearchIcon />
174+
</IconLink>
175+
</Tooltip>
176+
<StyledSelect
131177
onClick={this.stopPropagation}
132178
onChange={this.handleVersionChange}
133179
value={this.state.selectedVersion}
134180
>
135181
{versions.map(v => <option key={v}>{v}</option>)}
136-
</Select>
182+
</StyledSelect>
137183
</Row>
138184
</Right>
139185
</Container>

packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/SearchDependencies.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ const AutoCompleteInput = styled.input`
1414
box-sizing: border-box;
1515
border: none;
1616
outline: none;
17-
background-color: ${props => props.theme.background};
17+
background-color: ${props => props.theme.background2};
18+
font-weight: 600;
1819
color: ${props => props.theme.white};
19-
padding: 1em;
20+
padding: .75em 1em;
2021
}`;
2122

2223
type RawAutoCompleteProps = {
2324
onSelect: (hit: Object) => void,
25+
onManualSelect: (hit: string) => void,
2426
onHitVersionChange: (version: string) => void,
2527
hits: Array<Object>,
2628
refine: string,
@@ -29,6 +31,7 @@ type RawAutoCompleteProps = {
2931

3032
function RawAutoComplete({
3133
onSelect,
34+
onManualSelect,
3235
onHitVersionChange,
3336
hits,
3437
refine,
@@ -46,12 +49,20 @@ function RawAutoComplete({
4649
}
4750
},
4851
value: currentRefinement,
52+
placeholder: 'Search or enter npm dependency',
4953
onChange(e) {
5054
refine(e.target.value);
5155
},
56+
onKeyUp(e) {
57+
// If enter with no selection
58+
if (e.keyCode === 13) {
59+
onManualSelect(e.target.value);
60+
}
61+
},
5262
})}
5363
/>
5464
<Pagination />
65+
5566
<div>
5667
{hits.map((hit, index) => (
5768
<DependencyHit
@@ -90,6 +101,21 @@ export default class SearchDependencies extends React.PureComponent {
90101
this.props.onConfirm(hit.name, version);
91102
};
92103

104+
handleManualSelect = (hitName: string) => {
105+
const isScoped = hitName.startsWith('@');
106+
let version = 'latest';
107+
108+
const splittedName = hitName.split('@');
109+
110+
if (splittedName.length > (isScoped ? 2 : 1)) {
111+
version = splittedName.pop();
112+
}
113+
114+
const depName = splittedName.join('@');
115+
116+
this.props.onConfirm(depName, version);
117+
};
118+
93119
handleHitVersionChange = (hit, version) => {
94120
this.hitToVersionMap.set(hit, version);
95121
};
@@ -104,6 +130,7 @@ export default class SearchDependencies extends React.PureComponent {
104130
<Configure hitsPerPage={5} />
105131
<ConnectedAutoComplete
106132
onSelect={this.handleSelect}
133+
onManualSelect={this.handleManualSelect}
107134
onHitVersionChange={this.handleHitVersionChange}
108135
/>
109136
</InstantSearch>

0 commit comments

Comments
 (0)