Skip to content

Commit 9ab2ba9

Browse files
search box overhaul
1 parent 502cdbb commit 9ab2ba9

File tree

7 files changed

+351
-93
lines changed

7 files changed

+351
-93
lines changed

assets/search-icons.svg

-29
This file was deleted.

lib/components/searchBox.tsx

+227-47
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,260 @@
1-
import React from 'react';
1+
import React, {useCallback} from 'react';
22
import {SearchBoxProps} from '../hyper';
3+
import {VscArrowUp} from '@react-icons/all-files/vsc/VscArrowUp';
4+
import {VscArrowDown} from '@react-icons/all-files/vsc/VscArrowDown';
5+
import {VscClose} from '@react-icons/all-files/vsc/VscClose';
6+
import {VscCaseSensitive} from '@react-icons/all-files/vsc/VscCaseSensitive';
7+
import {VscRegex} from '@react-icons/all-files/vsc/VscRegex';
8+
import {VscWholeWord} from '@react-icons/all-files/vsc/VscWholeWord';
9+
import clsx from 'clsx';
310

4-
const searchBoxStyling: React.CSSProperties = {
5-
float: 'right',
6-
height: '28px',
7-
backgroundColor: 'white',
8-
position: 'absolute',
9-
right: '10px',
10-
top: '0px',
11-
width: '224px',
12-
zIndex: 9999
11+
type SearchButtonColors = {
12+
foregroundColor: string;
13+
selectionColor: string;
14+
backgroundColor: string;
1315
};
1416

15-
const enterKey = 13;
17+
type SearchButtonProps = React.PropsWithChildren<
18+
{
19+
onClick: () => void;
20+
active: boolean;
21+
title: string;
22+
} & SearchButtonColors
23+
>;
1624

17-
export default class SearchBox extends React.PureComponent<SearchBoxProps> {
25+
const SearchButton = ({
26+
onClick,
27+
active,
28+
title,
29+
foregroundColor,
30+
backgroundColor,
31+
selectionColor,
32+
children
33+
}: SearchButtonProps) => {
34+
const handleKeyUp = useCallback(
35+
(event: React.KeyboardEvent<HTMLDivElement>) => {
36+
if (event.key === 'Enter' || event.key === ' ') {
37+
onClick();
38+
}
39+
},
40+
[onClick]
41+
);
42+
43+
return (
44+
<div
45+
onClick={onClick}
46+
className={clsx('search-button', {'search-button-active': active})}
47+
tabIndex={0}
48+
onKeyUp={handleKeyUp}
49+
title={title}
50+
>
51+
{children}
52+
<style jsx>
53+
{`
54+
.search-button {
55+
cursor: pointer;
56+
color: ${foregroundColor};
57+
padding: 2px;
58+
margin: 4px 0px;
59+
height: 18px;
60+
width: 18px;
61+
border-radius: 2px;
62+
}
63+
64+
.search-button:focus {
65+
outline: ${selectionColor} solid 2px;
66+
}
67+
68+
.search-button:hover {
69+
background-color: ${backgroundColor};
70+
}
71+
72+
.search-button-active {
73+
background-color: ${selectionColor};
74+
}
75+
76+
.search-button-active:hover {
77+
background-color: ${selectionColor};
78+
}
79+
`}
80+
</style>
81+
</div>
82+
);
83+
};
84+
85+
class SearchBox extends React.PureComponent<SearchBoxProps> {
1886
searchTerm: string;
87+
input: HTMLInputElement | null = null;
88+
searchButtonColors: SearchButtonColors;
89+
1990
constructor(props: SearchBoxProps) {
2091
super(props);
2192
this.searchTerm = '';
93+
this.searchButtonColors = {
94+
backgroundColor: this.props.borderColor,
95+
selectionColor: this.props.selectionColor,
96+
foregroundColor: this.props.foregroundColor
97+
};
2298
}
2399

24100
handleChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
25101
this.searchTerm = event.currentTarget.value;
26-
if (event.keyCode === enterKey) {
27-
this.props.search(event.currentTarget.value);
102+
if (event.shiftKey && event.key === 'Enter') {
103+
this.props.prev(this.searchTerm);
104+
} else if (event.key === 'Enter') {
105+
this.props.next(this.searchTerm);
28106
}
29107
};
30108

109+
componentDidMount(): void {
110+
this.input?.focus();
111+
}
112+
31113
render() {
114+
const {
115+
caseSensitive,
116+
wholeWord,
117+
regex,
118+
results,
119+
toggleCaseSensitive,
120+
toggleWholeWord,
121+
toggleRegex,
122+
next,
123+
prev,
124+
close,
125+
backgroundColor,
126+
foregroundColor,
127+
borderColor,
128+
selectionColor,
129+
font
130+
} = this.props;
131+
32132
return (
33-
<div style={searchBoxStyling}>
34-
<input type="text" className="search-box" onKeyUp={this.handleChange} ref={(input) => input?.focus()} />
35-
<svg className="search-button" onClick={() => this.props.prev(this.searchTerm)}>
36-
<use xlinkHref="./renderer/assets/search-icons.svg#left-arrow" />
37-
</svg>
38-
<svg className="search-button" onClick={() => this.props.next(this.searchTerm)}>
39-
<use xlinkHref="./renderer/assets/search-icons.svg#right-arrow" />
40-
</svg>
41-
<svg className="search-button" onClick={() => this.props.close()}>
42-
<use xlinkHref="./renderer/assets/search-icons.svg#cancel" />
43-
</svg>
133+
<div className="flex-row search-container">
134+
<div className="flex-row search-box">
135+
<input
136+
className="search-input"
137+
type="text"
138+
onKeyDown={this.handleChange}
139+
ref={(input) => {
140+
this.input = input;
141+
}}
142+
placeholder="Search"
143+
></input>
144+
145+
<SearchButton
146+
onClick={toggleCaseSensitive}
147+
active={caseSensitive}
148+
title="Match Case"
149+
{...this.searchButtonColors}
150+
>
151+
<VscCaseSensitive size="14px" />
152+
</SearchButton>
153+
154+
<SearchButton
155+
onClick={toggleWholeWord}
156+
active={wholeWord}
157+
title="Match Whole Word"
158+
{...this.searchButtonColors}
159+
>
160+
<VscWholeWord size="14px" />
161+
</SearchButton>
162+
163+
<SearchButton
164+
onClick={toggleRegex}
165+
active={regex}
166+
title="Use Regular Expression"
167+
{...this.searchButtonColors}
168+
>
169+
<VscRegex size="14px" />
170+
</SearchButton>
171+
</div>
172+
173+
<span style={{minWidth: '60px', marginLeft: '4px'}}>
174+
{results === undefined
175+
? ''
176+
: results.resultCount === 0
177+
? 'No results'
178+
: `${results.resultIndex + 1} of ${results.resultCount}`}
179+
</span>
180+
181+
<div className="flex-row">
182+
<SearchButton
183+
onClick={() => prev(this.searchTerm)}
184+
active={false}
185+
title="Previous Match"
186+
{...this.searchButtonColors}
187+
>
188+
<VscArrowUp size="14px" />
189+
</SearchButton>
190+
191+
<SearchButton
192+
onClick={() => next(this.searchTerm)}
193+
active={false}
194+
title="Next Match"
195+
{...this.searchButtonColors}
196+
>
197+
<VscArrowDown size="14px" />
198+
</SearchButton>
199+
200+
<SearchButton onClick={() => close()} active={false} title="Close" {...this.searchButtonColors}>
201+
<VscClose size="14px" />
202+
</SearchButton>
203+
</div>
204+
44205
<style jsx>
45206
{`
46-
.search-box {
47-
font-size: 18px;
48-
padding: 3px 6px;
49-
width: 152px;
50-
border: none;
51-
float: left;
207+
.search-container {
208+
background-color: ${backgroundColor};
209+
border: 1px solid ${borderColor};
210+
border-radius: 2px;
211+
position: absolute;
212+
right: 13px;
213+
top: 4px;
214+
z-index: 10;
215+
padding: 4px;
216+
font-family: ${font};
217+
font-size: 12px;
52218
}
53219
54-
.search-box:focus {
220+
.search-input {
55221
outline: none;
222+
background-color: transparent;
223+
border: none;
224+
color: ${foregroundColor};
225+
align-self: stretch;
226+
width: 100px;
56227
}
57228
58-
.search-button {
59-
background-color: #ffffff;
60-
color: black;
61-
padding: 7px 5.5px;
62-
text-align: center;
63-
text-decoration: none;
64-
display: inline-block;
65-
font-size: 16px;
66-
transition-duration: 0.4s;
67-
cursor: pointer;
68-
height: 27px;
69-
width: 24px;
70-
float: left;
229+
.flex-row {
230+
display: flex;
231+
flex-direction: row;
232+
justify-content: space-between;
233+
align-items: center;
234+
gap: 4px;
71235
}
72-
.search-button:hover {
73-
background-color: #e7e7e7;
236+
237+
.search-box {
238+
border: none;
239+
border-radius: 2px;
240+
outline: ${borderColor} solid 1px;
241+
background-color: ${backgroundColor};
242+
color: ${foregroundColor};
243+
padding: 0px 4px;
244+
}
245+
246+
.search-input::placeholder {
247+
color: ${foregroundColor};
248+
}
249+
250+
.search-box:focus-within {
251+
outline: ${selectionColor} solid 2px;
74252
}
75253
`}
76254
</style>
77255
</div>
78256
);
79257
}
80258
}
259+
260+
export default SearchBox;

lib/components/style-sheet.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@ export default class StyleSheet extends React.PureComponent<StyleSheetProps> {
137137
overflow: hidden;
138138
}
139139
140+
.xterm .xterm-decoration-overview-ruler {
141+
position: absolute;
142+
z-index: 10;
143+
right: 0px;
144+
top: unset;
145+
left: unset;
146+
pointer-events: none;
147+
}
148+
140149
::-webkit-scrollbar {
141150
width: 5px;
142151
}

0 commit comments

Comments
 (0)