summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-11-09 10:55:00 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-11-24 16:26:28 +0100
commit8c40662a0816a43f2423a68596ea2f1b0b3a492a (patch)
tree13f7590ae5acd1a594d5a7a3d3e2f911ee04d975 /gui/src
parent1fcdf3c0ab63dd78fc491f0537a0a09a367b804c (diff)
downloadmullvadvpn-8c40662a0816a43f2423a68596ea2f1b0b3a492a.tar.xz
mullvadvpn-8c40662a0816a43f2423a68596ea2f1b0b3a492a.zip
Move search bar to it's own file
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/SearchBar.tsx105
-rw-r--r--gui/src/renderer/components/SplitTunnelingSettings.tsx51
-rw-r--r--gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx65
3 files changed, 117 insertions, 104 deletions
diff --git a/gui/src/renderer/components/SearchBar.tsx b/gui/src/renderer/components/SearchBar.tsx
new file mode 100644
index 0000000000..a659f6130f
--- /dev/null
+++ b/gui/src/renderer/components/SearchBar.tsx
@@ -0,0 +1,105 @@
+import { useCallback, useRef } from 'react';
+import styled from 'styled-components';
+
+import { colors } from '../../config.json';
+import { messages } from '../../shared/gettext';
+import { normalText } from './common-styles';
+import ImageView from './ImageView';
+
+export const StyledSearchContainer = styled.div({
+ position: 'relative',
+ display: 'flex',
+});
+
+export const StyledSearchInput = styled.input.attrs({ type: 'text' })({
+ ...normalText,
+ flex: 1,
+ border: 'none',
+ borderRadius: '4px',
+ padding: '9px 38px',
+ margin: 0,
+ color: colors.white60,
+ backgroundColor: colors.white10,
+ '::placeholder': {
+ color: colors.white60,
+ },
+ ':focus': {
+ color: colors.blue,
+ backgroundColor: colors.white,
+ '::placeholder': {
+ color: colors.blue40,
+ },
+ },
+});
+
+export const StyledClearButton = styled.button({
+ position: 'absolute',
+ top: '50%',
+ transform: 'translateY(-50%)',
+ right: '9px',
+ border: 'none',
+ background: 'none',
+ padding: 0,
+});
+
+export const StyledSearchIcon = styled(ImageView)({
+ position: 'absolute',
+ top: '50%',
+ transform: 'translateY(-50%)',
+ left: '9px',
+ [`${StyledSearchInput}:focus ~ &`]: {
+ backgroundColor: colors.blue,
+ },
+});
+
+export const StyledClearIcon = styled(ImageView)({
+ ':hover': {
+ backgroundColor: colors.white60,
+ },
+ [`${StyledSearchInput}:focus ~ ${StyledClearButton} &`]: {
+ backgroundColor: colors.blue40,
+ ':hover': {
+ backgroundColor: colors.blue,
+ },
+ },
+});
+
+interface ISearchBarProps {
+ searchTerm: string;
+ onSearch: (searchTerm: string) => void;
+ className?: string;
+}
+
+export default function SearchBar(props: ISearchBarProps) {
+ const inputRef = useRef() as React.RefObject<HTMLInputElement>;
+
+ const onInput = useCallback(
+ (event: React.FormEvent) => {
+ const element = event.target as HTMLInputElement;
+ props.onSearch(element.value);
+ },
+ [props.onSearch],
+ );
+
+ const onClear = useCallback(() => {
+ props.onSearch('');
+ inputRef.current?.blur();
+ }, [props.onSearch]);
+
+ return (
+ <StyledSearchContainer className={props.className}>
+ <StyledSearchInput
+ ref={inputRef}
+ value={props.searchTerm}
+ onInput={onInput}
+ placeholder={messages.gettext('Search for...')}
+ />
+ <StyledSearchIcon source="icon-search" width={24} tintColor={colors.white60} />
+ {props.searchTerm.length > 0 && (
+ <StyledClearButton onClick={onClear}>
+ <StyledClearIcon source="icon-close" width={18} tintColor={colors.white40} />
+ </StyledClearButton>
+ )}
+ </StyledSearchContainer>
+ );
+}
diff --git a/gui/src/renderer/components/SplitTunnelingSettings.tsx b/gui/src/renderer/components/SplitTunnelingSettings.tsx
index f68be19589..7ddf34f55a 100644
--- a/gui/src/renderer/components/SplitTunnelingSettings.tsx
+++ b/gui/src/renderer/components/SplitTunnelingSettings.tsx
@@ -31,8 +31,6 @@ import {
StyledCellButton,
StyledCellLabel,
StyledCellWarningIcon,
- StyledClearButton,
- StyledClearIcon,
StyledContent,
StyledHeaderTitle,
StyledHeaderTitleContainer,
@@ -43,9 +41,7 @@ import {
StyledNoResult,
StyledNoResultText,
StyledPageCover,
- StyledSearchContainer,
- StyledSearchIcon,
- StyledSearchInput,
+ StyledSearchBar,
StyledSpinnerRow,
} from './SplitTunnelingSettingsStyles';
import Switch from './Switch';
@@ -176,7 +172,7 @@ function LinuxSplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsProps
</HeaderSubTitle>
</SettingsHeader>
- <SearchBar searchTerm={searchTerm} onSearch={setSearchTerm} />
+ <StyledSearchBar searchTerm={searchTerm} onSearch={setSearchTerm} />
<ApplicationList applications={filteredApplications} rowRenderer={rowRenderer} />
<StyledBrowseButton onClick={launchWithFilePicker}>
@@ -435,7 +431,9 @@ export function WindowsSplitTunnelingSettings(props: IPlatformSplitTunnelingSett
</HeaderSubTitle>
</SettingsHeader>
- {splitTunnelingEnabled && <SearchBar searchTerm={searchTerm} onSearch={setSearchTerm} />}
+ {splitTunnelingEnabled && (
+ <StyledSearchBar searchTerm={searchTerm} onSearch={setSearchTerm} />
+ )}
<Accordion expanded={showSplitSection}>
<Cell.Section sectionTitle={excludedTitle}>
@@ -566,45 +564,6 @@ function WindowsApplicationRow(props: IWindowsApplicationRowProps) {
);
}
-interface ISearchBarProps {
- searchTerm: string;
- onSearch: (searchTerm: string) => void;
-}
-
-function SearchBar(props: ISearchBarProps) {
- const inputRef = useRef() as React.RefObject<HTMLInputElement>;
-
- const onInput = useCallback(
- (event: React.FormEvent) => {
- const element = event.target as HTMLInputElement;
- props.onSearch(element.value);
- },
- [props.onSearch],
- );
-
- const onClear = useCallback(() => {
- props.onSearch('');
- inputRef.current?.blur();
- }, [props.onSearch]);
-
- return (
- <StyledSearchContainer>
- <StyledSearchInput
- ref={inputRef}
- value={props.searchTerm}
- onInput={onInput}
- placeholder={messages.pgettext('split-tunneling-view', 'Filter...')}
- />
- <StyledSearchIcon source="icon-filter" width={24} tintColor={colors.white60} />
- {props.searchTerm.length > 0 && (
- <StyledClearButton onClick={onClear}>
- <StyledClearIcon source="icon-close" width={18} tintColor={colors.white40} />
- </StyledClearButton>
- )}
- </StyledSearchContainer>
- );
-}
-
function includesSearchTerm(application: IApplication, searchTerm: string) {
return application.name.toLowerCase().includes(searchTerm.toLowerCase());
}
diff --git a/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx b/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
index 6b135486db..028fac30a3 100644
--- a/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
+++ b/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
@@ -6,6 +6,7 @@ import * as Cell from './cell';
import { measurements, normalText } from './common-styles';
import ImageView from './ImageView';
import { NavigationScrollbars } from './NavigationBar';
+import SearchBar from './SearchBar';
import { HeaderTitle } from './SettingsHeader';
export const StyledPageCover = styled.div({}, (props: { show: boolean }) => ({
@@ -87,64 +88,6 @@ export const StyledCellContainer = styled(Cell.Container)({
marginBottom: measurements.rowVerticalMargin,
});
-export const StyledSearchContainer = styled.div({
- position: 'relative',
- marginBottom: measurements.buttonVerticalMargin,
-});
-
-export const StyledSearchInput = styled.input.attrs({ type: 'text' })({
- ...normalText,
- width: `calc(100% - ${measurements.viewMargin} * 2)`,
- border: 'none',
- borderRadius: '4px',
- padding: '9px 38px',
- margin: `0 ${measurements.viewMargin}`,
- color: colors.white60,
- backgroundColor: colors.white10,
- '::placeholder': {
- color: colors.white60,
- },
- ':focus': {
- color: colors.blue,
- backgroundColor: colors.white,
- '::placeholder': {
- color: colors.blue40,
- },
- },
-});
-
-export const StyledClearButton = styled.button({
- position: 'absolute',
- top: '50%',
- transform: 'translateY(-50%)',
- right: '28px',
- border: 'none',
- background: 'none',
- padding: 0,
-});
-
-export const StyledSearchIcon = styled(ImageView)({
- position: 'absolute',
- top: '50%',
- transform: 'translateY(-50%)',
- left: '28px',
- [`${StyledSearchInput}:focus ~ &`]: {
- backgroundColor: colors.blue,
- },
-});
-
-export const StyledClearIcon = styled(ImageView)({
- ':hover': {
- backgroundColor: colors.white60,
- },
- [`${StyledSearchInput}:focus ~ ${StyledClearButton} &`]: {
- backgroundColor: colors.blue40,
- ':hover': {
- backgroundColor: colors.blue,
- },
- },
-});
-
export const StyledNoResult = styled(Cell.CellFooter)({
display: 'flex',
flexDirection: 'column',
@@ -164,3 +107,9 @@ export const StyledHeaderTitleContainer = styled.div({
export const StyledHeaderTitle = styled(HeaderTitle)({
flex: 1,
});
+
+export const StyledSearchBar = styled(SearchBar)({
+ marginLeft: measurements.viewMargin,
+ marginRight: measurements.viewMargin,
+ marginBottom: measurements.buttonVerticalMargin,
+});