diff options
| author | Oliver <oliver@mohlin.dev> | 2025-11-03 09:25:07 +0100 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-11-04 14:16:37 +0100 |
| commit | 1182e3bbb5e900c513970006c0614fd0073a47cd (patch) | |
| tree | ebdfbcd74c26c9ac3e222be187a17b097f48c441 | |
| parent | d0f4e5fa0d48fe09293fdc61200ba7bf99759741 (diff) | |
| download | mullvadvpn-1182e3bbb5e900c513970006c0614fd0073a47cd.tar.xz mullvadvpn-1182e3bbb5e900c513970006c0614fd0073a47cd.zip | |
Refactor remaining components to use new Switch
7 files changed, 35 insertions, 100 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx index 1018f11259..61779e36d3 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx @@ -8,6 +8,7 @@ import { RoutePath } from '../../shared/routes'; import { useAppContext } from '../context'; import { useApiAccessMethodTest } from '../lib/api-access-methods'; import { Button, Container, Flex, Spinner } from '../lib/components'; +import { Switch } from '../lib/components/switch'; import { colors, spacings } from '../lib/foundations'; import { useHistory } from '../lib/history'; import { generateRoutePath } from '../lib/routeHelpers'; @@ -293,7 +294,11 @@ function ApiAccessMethod(props: ApiAccessMethodProps) { <ContextMenuTrigger /> <ContextMenu items={menuItems} align="right" /> </ContextMenuContainer> - <Cell.Switch isOn={props.method.enabled} onChange={toggle} /> + <Switch checked={props.method.enabled} onCheckedChange={toggle}> + <Switch.Trigger> + <Switch.Thumb /> + </Switch.Trigger> + </Switch> </Flex> {/* Confirmation dialog for method removal */} diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx index 1e7005c554..5fccace6b1 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx @@ -1,5 +1,6 @@ import { createContext, ReactNode, useCallback, useContext, useMemo, useState } from 'react'; import { sprintf } from 'sprintf-js'; +import styled from 'styled-components'; import { urls } from '../../shared/constants'; import { messages } from '../../shared/gettext'; @@ -8,13 +9,13 @@ import { RoutePath } from '../../shared/routes'; import { useAppContext } from '../context'; import { Button, Flex } from '../lib/components'; import { FlexColumn } from '../lib/components/flex-column'; +import { spacings } from '../lib/foundations'; import { useHistory } from '../lib/history'; import { useExclusiveTask } from '../lib/hooks/use-exclusive-task'; import { IconBadge } from '../lib/icon-badge'; import { formatDeviceName } from '../lib/utils'; import { useSelector } from '../redux/store'; import { AppMainHeader } from './app-main-header'; -import * as Cell from './cell'; import DeviceInfoButton from './DeviceInfoButton'; import { StyledAccountNumberContainer, @@ -25,11 +26,11 @@ import { StyledCustomScrollbars, StyledDeviceLabel, StyledMessage, - StyledModalCellContainer, StyledTitle, } from './ExpiredAccountErrorViewStyles'; import { Footer, Layout } from './Layout'; import { ModalAlert, ModalAlertType, ModalMessage } from './Modal'; +import { SettingsToggleListItem } from './settings-toggle-list-item'; enum RecoveryAction { openBrowser, @@ -37,6 +38,10 @@ enum RecoveryAction { disableLockdownMode, } +const StyledSettingsToggleListItem = styled(SettingsToggleListItem)` + margin-top: ${spacings.medium}; +`; + export default function ExpiredAccountErrorView() { return ( <ExpiredAccountContextProvider> @@ -258,10 +263,12 @@ function LockdownModeAlert() { 'Remember, turning it off will allow network traffic while the VPN is disconnected until you turn it back on under Advanced settings.', )} </ModalMessage> - <StyledModalCellContainer> - <Cell.Label>{messages.pgettext('vpn-settings-view', 'Lockdown mode')}</Cell.Label> - <Cell.Switch isOn={lockdownMode} onChange={onChange} /> - </StyledModalCellContainer> + <StyledSettingsToggleListItem checked={lockdownMode} onCheckedChange={onChange}> + <SettingsToggleListItem.Label> + {messages.pgettext('vpn-settings-view', 'Lockdown mode')} + </SettingsToggleListItem.Label> + <SettingsToggleListItem.Switch /> + </StyledSettingsToggleListItem> </ModalAlert> ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorViewStyles.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorViewStyles.tsx index b39e4900fb..fd1182f572 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorViewStyles.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorViewStyles.tsx @@ -2,7 +2,6 @@ import styled from 'styled-components'; import { colors } from '../lib/foundations'; import AccountNumberLabel from './AccountNumberLabel'; -import * as Cell from './cell'; import { hugeText, measurements, tinyText } from './common-styles'; import CustomScrollbars from './CustomScrollbars'; import { Container } from './Layout'; @@ -15,12 +14,6 @@ export const StyledAccountNumberLabel = styled(AccountNumberLabel)({ color: colors.white, }); -export const StyledModalCellContainer = styled(Cell.Container)({ - marginTop: '18px', - paddingLeft: '12px', - paddingRight: '12px', -}); - export const StyledCustomScrollbars = styled(CustomScrollbars)({ flex: 1, }); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx index c90a0db195..3d36fff9c9 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx @@ -11,9 +11,9 @@ import { import { messages } from '../../shared/gettext'; import { Button, Flex } from '../lib/components'; import { FlexRow } from '../lib/components/flex-row'; +import { Switch } from '../lib/components/switch'; import { IpAddress } from '../lib/ip'; import { useEffectEvent } from '../lib/utility-hooks'; -import * as Cell from './cell'; import { SettingsForm, useSettingsFormSubmittable } from './cell/SettingsForm'; import { SettingsGroup } from './cell/SettingsGroup'; import { SettingsRadioGroup } from './cell/SettingsRadioGroup'; @@ -424,7 +424,11 @@ function EditSocks5Remote(props: EditProxyProps<Socks5RemoteCustomProxy>) { </SettingsRow> <SettingsRow label={messages.pgettext('api-access-methods-view', 'Authentication')}> - <Cell.Switch isOn={authentication} onChange={setAuthentication} /> + <Switch checked={authentication} onCheckedChange={setAuthentication}> + <Switch.Trigger> + <Switch.Thumb /> + </Switch.Trigger> + </Switch> </SettingsRow> {authentication && ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Switch.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Switch.tsx deleted file mode 100644 index 48c3ff6b1a..0000000000 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Switch.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; - -import { colors, ColorVariables } from '../lib/foundations'; - -interface IProps { - id?: string; - 'aria-labelledby'?: string; - 'aria-describedby'?: string; - isOn: boolean; - onChange?: (isOn: boolean) => void; - className?: string; - disabled?: boolean; - innerRef?: React.Ref<HTMLDivElement>; -} - -const SwitchContainer = styled.div<{ disabled: boolean }>((props) => ({ - position: 'relative', - width: '34px', - height: '22px', - borderColor: props.disabled ? colors.whiteAlpha20 : colors.whiteAlpha80, - borderWidth: '2px', - borderStyle: 'solid', - borderRadius: '11px', - padding: '1px', -})); - -const Knob = styled.div<{ $isOn: boolean; disabled: boolean }>((props) => { - let backgroundColor: ColorVariables = props.$isOn ? colors.green : colors.red; - if (props.disabled) { - backgroundColor = props.$isOn ? colors.green40 : colors.red40; - } - - return { - position: 'absolute', - height: '16px', - borderRadius: '8px', - transition: 'all 200ms linear', - width: '16px', - backgroundColor, - // When enabled the button should be placed all the way to the right (100%) minus padding (1px) - // minus it's own width (16px). - left: props.$isOn ? 'calc(100% - 1px - 16px)' : '1px', - }; -}); - -export default class Switch extends React.PureComponent<IProps> { - public render() { - return ( - <SwitchContainer - ref={this.props.innerRef} - id={this.props.id} - role="checkbox" - aria-labelledby={this.props['aria-labelledby']} - aria-describedby={this.props['aria-describedby']} - aria-checked={this.props.isOn} - onClick={this.handleClick} - disabled={this.props.disabled ?? false} - aria-disabled={this.props.disabled ?? false} - tabIndex={-1} - className={this.props.className}> - <Knob disabled={this.props.disabled ?? false} $isOn={this.props.isOn} /> - </SwitchContainer> - ); - } - - private handleClick = () => { - if (!this.props.disabled) { - this.props.onChange?.(!this.props.isOn); - } - }; -} diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx index 7955870c2d..20b685e10f 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useContext, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import { IconButton } from '../../lib/components'; @@ -6,17 +6,8 @@ import { colors } from '../../lib/foundations'; import { useBoolean, useCombinedRefs, useEffectEvent, useStyledRef } from '../../lib/utility-hooks'; import { normalText } from '../common-styles'; import { BackAction } from '../KeyboardNavigation'; -import StandaloneSwitch from '../Switch'; import { CellDisabledContext, Container } from './Container'; -export const Switch = React.forwardRef(function SwitchT( - props: StandaloneSwitch['props'], - ref: React.Ref<StandaloneSwitch>, -) { - const disabled = useContext(CellDisabledContext); - return <StandaloneSwitch ref={ref} disabled={disabled} {...props} />; -}); - const inputTextStyles: React.CSSProperties = { ...normalText, height: '18px', diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/split-tunneling/components/split-tunneling-settings/components/split-tunneling-settings-header/components/split-tunneling-state-switch/SplitTunnelingStateSwitch.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/split-tunneling/components/split-tunneling-settings/components/split-tunneling-settings-header/components/split-tunneling-state-switch/SplitTunnelingStateSwitch.tsx index bf641a6f5e..0cac9fcca7 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/views/split-tunneling/components/split-tunneling-settings/components/split-tunneling-settings-header/components/split-tunneling-state-switch/SplitTunnelingStateSwitch.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/split-tunneling/components/split-tunneling-settings/components/split-tunneling-settings-header/components/split-tunneling-state-switch/SplitTunnelingStateSwitch.tsx @@ -1,6 +1,6 @@ import { useAppContext } from '../../../../../../../../../context'; +import { Switch } from '../../../../../../../../../lib/components/switch'; import { useSelector } from '../../../../../../../../../redux/store'; -import { Switch } from '../../../../../../../../cell'; import { useDisabled } from './hooks'; export function SplitTunnelingStateSwitch() { @@ -9,6 +9,13 @@ export function SplitTunnelingStateSwitch() { const splitTunnelingEnabled = useSelector((state) => state.settings.splitTunneling); return ( - <Switch isOn={splitTunnelingEnabled} disabled={disabled} onChange={setSplitTunnelingState} /> + <Switch + checked={splitTunnelingEnabled} + disabled={disabled} + onCheckedChange={setSplitTunnelingState}> + <Switch.Trigger> + <Switch.Thumb /> + </Switch.Trigger> + </Switch> ); } |
