summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2024-08-29 21:52:38 +0200
committerOskar <oskar@mullvad.net>2024-08-30 20:04:00 +0200
commite2e6180c3b74f1dcc7a9da84e0e0efd1d73a9e4d (patch)
treedefa10afceba7fcdbb3551bcab403de4729352ef /gui/src
parente5abae7800ed50a0151ab4eee9c1cf2764f948fb (diff)
downloadmullvadvpn-e2e6180c3b74f1dcc7a9da84e0e0efd1d73a9e4d.tar.xz
mullvadvpn-e2e6180c3b74f1dcc7a9da84e0e0efd1d73a9e4d.zip
Add support for sub-labels and navigation in selector items
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/cell/Selector.tsx99
1 files changed, 81 insertions, 18 deletions
diff --git a/gui/src/renderer/components/cell/Selector.tsx b/gui/src/renderer/components/cell/Selector.tsx
index 6bfeeb3887..2868a50aee 100644
--- a/gui/src/renderer/components/cell/Selector.tsx
+++ b/gui/src/renderer/components/cell/Selector.tsx
@@ -3,8 +3,11 @@ import styled from 'styled-components';
import { colors } from '../../../config.json';
import { messages } from '../../../shared/gettext';
+import { useHistory } from '../../lib/history';
+import { RoutePath } from '../../lib/routes';
import { useStyledRef } from '../../lib/utilityHooks';
import { AriaDetails, AriaInput, AriaLabel } from '../AriaGroup';
+import ImageView from '../ImageView';
import InfoButton from '../InfoButton';
import * as Cell from '.';
@@ -17,6 +20,8 @@ export interface SelectorItem<T> {
value: T;
disabled?: boolean;
'data-testid'?: string;
+ details?: { path: RoutePath; ariaLabel: string };
+ subLabel?: string;
}
// T represents the available values and U represent the value of "Automatic"/"Any" if there is one.
@@ -53,6 +58,8 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) {
disabled={props.disabled || item.disabled}
forwardedRef={ref}
onSelect={props.onSelect}
+ subLabel={item.subLabel}
+ details={item.details}
data-testid={item['data-testid']}>
{item.label}
</SelectorCell>
@@ -133,39 +140,95 @@ interface SelectorCellProps<T> {
isSelected: boolean;
disabled?: boolean;
onSelect: (value: T) => void;
- children: React.ReactNode | Array<React.ReactNode>;
+ children: string;
+ subLabel?: string;
forwardedRef?: React.Ref<HTMLButtonElement>;
'data-testid'?: string;
+ details?: SelectorItem<unknown>['details'];
}
+const StyledSelectorCell = styled.div({
+ display: 'flex',
+});
+
+const StyledSideButtonImage = styled(ImageView)({
+ padding: '0 3px',
+});
+
+const StyledSideButton = styled(Cell.SideButton)({
+ marginBottom: '1px',
+});
+
function SelectorCell<T>(props: SelectorCellProps<T>) {
+ const history = useHistory();
+
const handleClick = useCallback(() => {
if (!props.isSelected) {
props.onSelect(props.value);
}
}, [props.isSelected, props.onSelect, props.value]);
+ const navigate = useCallback(() => {
+ if (props.details) {
+ history.push(props.details.path);
+ }
+ }, [history.push, props.details?.path]);
+
return (
- <Cell.CellButton
- ref={props.forwardedRef}
- onClick={handleClick}
- selected={props.isSelected}
- disabled={props.disabled}
- role="option"
- aria-selected={props.isSelected}
- aria-disabled={props.disabled}
- data-testid={props['data-testid']}>
- <StyledCellIcon
- $visible={props.isSelected}
- source="icon-tick"
- width={18}
- tintColor={colors.white}
- />
- <Cell.ValueLabel>{props.children}</Cell.ValueLabel>
- </Cell.CellButton>
+ <StyledSelectorCell>
+ <Cell.CellButton
+ ref={props.forwardedRef}
+ onClick={handleClick}
+ selected={props.isSelected}
+ disabled={props.disabled}
+ role="option"
+ aria-selected={props.isSelected}
+ aria-disabled={props.disabled}
+ data-testid={props['data-testid']}>
+ <StyledCellIcon
+ $visible={props.isSelected}
+ source="icon-tick"
+ width={18}
+ tintColor={colors.white}
+ />
+ <SelectorCellLabel subLabel={props.subLabel}>{props.children}</SelectorCellLabel>
+ </Cell.CellButton>
+ {props.details && (
+ <StyledSideButton
+ $backgroundColor={colors.blue40}
+ $backgroundColorHover={colors.blue80}
+ aria-label={props.details.ariaLabel}
+ onClick={navigate}>
+ <StyledSideButtonImage
+ source="icon-chevron"
+ width={7}
+ tintColor={colors.white}
+ tintHoverColor={colors.white80}
+ />
+ </StyledSideButton>
+ )}
+ </StyledSelectorCell>
);
}
+interface SelectorCellLabelProps {
+ children: string;
+ subLabel?: string;
+}
+
+function SelectorCellLabel(props: SelectorCellLabelProps) {
+ if (props.subLabel) {
+ return (
+ <Cell.LabelContainer>
+ <Cell.ValueLabel>{props.children}</Cell.ValueLabel>
+ {props.subLabel && <Cell.SubLabel>{props.subLabel}</Cell.SubLabel>}
+ </Cell.LabelContainer>
+ );
+ } else {
+ return <Cell.ValueLabel>{props.children}</Cell.ValueLabel>;
+ }
+}
+
interface StyledCustomContainerProps {
selected: boolean;
}