summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOliver <oliver@mohlin.dev>2024-12-02 13:49:34 +0100
committerOskar <oskar@mullvad.net>2024-12-04 14:05:25 +0100
commit02c46a282c7ca632f2d4f7490f5bbeeb03dcc595 (patch)
tree12d5a2301caa5c396b8b97c4d6dcf0a3226bc1f2
parent67321f3d4af6d2fd79f916510d652f15b2d999ec (diff)
downloadmullvadvpn-02c46a282c7ca632f2d4f7490f5bbeeb03dcc595.tar.xz
mullvadvpn-02c46a282c7ca632f2d4f7490f5bbeeb03dcc595.zip
Use spacing tokens and components in user interface and vpn settings
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx5
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx48
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx43
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx15
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx28
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SettingsStyles.tsx8
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx63
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx7
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx90
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx106
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx46
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/CellButton.tsx27
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/Container.tsx3
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/Label.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx8
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/common-styles.ts41
17 files changed, 255 insertions, 315 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
index 0b4d24cbfb..9522b422e5 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
@@ -3,8 +3,9 @@ import styled from 'styled-components';
import { useHistory } from '../lib/history';
import { useBoolean } from '../lib/utility-hooks';
+import { Spacings } from '../tokens';
import * as AppButton from './AppButton';
-import { measurements, spacings } from './common-styles';
+import { measurements } from './common-styles';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import {
@@ -24,7 +25,7 @@ const StyledContent = styled.div({
});
const StyledButtonGroup = styled.div({
- margin: `${spacings.spacing6} ${measurements.horizontalViewMargin}`,
+ margin: `${Spacings.spacing6} ${measurements.horizontalViewMargin}`,
});
export default function Debug() {
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
index 865fc790f6..8ff848cb12 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
@@ -1,7 +1,8 @@
import styled from 'styled-components';
-import { colors } from '../../config.json';
-import { measurements, spacings } from './common-styles';
+import { Colors, Spacings } from '../tokens';
+import { Flex } from './common/layout/Flex';
+import { measurements } from './common-styles';
import HeaderBar from './HeaderBar';
import { NavigationScrollbars } from './NavigationBar';
@@ -13,7 +14,7 @@ export const Container = styled.div({
display: 'flex',
flexDirection: 'column',
flex: 1,
- backgroundColor: colors.blue,
+ backgroundColor: Colors.blue,
overflow: 'hidden',
});
@@ -25,7 +26,7 @@ export const Layout = styled.div({
});
export const SettingsContainer = styled(Container)({
- backgroundColor: colors.darkBlue,
+ backgroundColor: Colors.darkBlue,
});
export const SettingsNavigationScrollbars = styled(NavigationScrollbars)({
@@ -40,32 +41,39 @@ export const SettingsContent = styled.div({
marginBottom: measurements.verticalViewMargin,
});
-export const SettingsStack = styled.div({
- display: 'flex',
- flexDirection: 'column',
- gap: spacings.spacing5,
-});
-
export const Footer = styled.div({
display: 'flex',
flexDirection: 'column',
flex: 0,
- padding: `${spacings.spacing6} ${measurements.horizontalViewMargin} ${measurements.verticalViewMargin}`,
+ padding: `${Spacings.spacing6} ${measurements.horizontalViewMargin} ${measurements.verticalViewMargin}`,
[`${SettingsContent} &&`]: {
paddingBottom: 0,
},
});
-export const Spacing = styled.div<{ height: string }>((props) => ({
- height: props.height,
-}));
+export const SettingsStack = styled(Flex).attrs({
+ $flexDirection: 'column',
+ $gap: Spacings.spacing5,
+})({});
-export const ButtonStack = styled.div({
- display: 'flex',
- flexDirection: 'column',
- gap: spacings.spacing5,
- margin: `0 ${spacings.spacing6}`,
+export const SettingsGroup = styled(Flex).attrs({
+ $flex: 1,
+ $flexDirection: 'column',
+})({});
+
+export const ButtonStack = styled(Flex).attrs(() => ({
+ $flexDirection: 'column',
+ $gap: Spacings.spacing5,
+ $margin: `0 ${Spacings.spacing6}`,
+}))({
[`${Footer} &&`]: {
- margin: `0 ${spacings.spacing3}`,
+ margin: `0 ${Spacings.spacing3}`,
},
});
+
+export const LabelStack = styled(Flex).attrs(() => ({
+ $flexGrow: 1,
+ $flexDirection: 'row',
+ $alignItems: 'center',
+ $gap: Spacings.spacing3,
+}))({});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
index 4c79f0225c..15f760941f 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
@@ -1,27 +1,30 @@
import { useCallback } from 'react';
-import { colors, strings } from '../../config.json';
+import { strings } from '../../config.json';
import { messages } from '../../shared/gettext';
import { getDownloadUrl } from '../../shared/version';
import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
import { useSelector } from '../redux/store';
+import { Colors } from '../tokens';
import { RedButton } from './AppButton';
import * as Cell from './cell';
+import { TitleBig } from './common/text';
import { BackAction } from './KeyboardNavigation';
import {
ButtonStack,
Footer,
+ LabelStack,
Layout,
SettingsContainer,
SettingsContent,
+ SettingsGroup,
SettingsNavigationScrollbars,
SettingsStack,
} from './Layout';
import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
-import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-import { StyledCellIcon } from './SettingsStyles';
+import SettingsHeader from './SettingsHeader';
export default function Support() {
const history = useHistory();
@@ -52,44 +55,44 @@ export default function Support() {
<SettingsNavigationScrollbars fillContainer>
<SettingsContent>
<SettingsHeader>
- <HeaderTitle>{messages.pgettext('navigation-bar', 'Settings')}</HeaderTitle>
+ <TitleBig>{messages.pgettext('navigation-bar', 'Settings')}</TitleBig>
</SettingsHeader>
<SettingsStack>
{showSubSettings ? (
<>
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<UserInterfaceSettingsButton />
<MultihopButton />
<DaitaButton />
<VpnSettingsButton />
- </Cell.Group>
+ </SettingsGroup>
{showSplitTunneling && (
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<SplitTunnelingButton />
- </Cell.Group>
+ </SettingsGroup>
)}
</>
) : (
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<UserInterfaceSettingsButton />
- </Cell.Group>
+ </SettingsGroup>
)}
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<ApiAccessMethodsButton />
- </Cell.Group>
+ </SettingsGroup>
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<SupportButton />
<AppVersionButton />
- </Cell.Group>
+ </SettingsGroup>
{window.env.development && (
- <Cell.Group $noMarginBottom>
+ <SettingsGroup>
<DebugButton />
- </Cell.Group>
+ </SettingsGroup>
)}
</SettingsStack>
<Footer>
@@ -229,7 +232,7 @@ function AppVersionButton() {
const message = !consistentVersion ? inconsistentVersionMessage : updateAvailableMessage;
- alertIcon = <StyledCellIcon source="icon-alert" width={18} tintColor={colors.red} />;
+ alertIcon = <Cell.UntintedIcon source="icon-alert" width={18} tintColor={Colors.red} />;
footer = (
<Cell.CellFooter>
<Cell.CellFooterText>{message}</Cell.CellFooterText>
@@ -246,8 +249,10 @@ function AppVersionButton() {
source: 'icon-extLink',
'aria-label': messages.pgettext('accessibility', 'Opens externally'),
}}>
- {alertIcon}
- <Cell.Label>{messages.pgettext('settings-view', 'App version')}</Cell.Label>
+ <LabelStack>
+ {alertIcon}
+ <Cell.Label>{messages.pgettext('settings-view', 'App version')}</Cell.Label>
+ </LabelStack>
<Cell.SubText>{appVersion}</Cell.SubText>
</Cell.CellNavigationButton>
{footer}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx
index 1d1a1f4e71..8b78264a9a 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx
@@ -1,12 +1,12 @@
import * as React from 'react';
import styled from 'styled-components';
-import { colors } from '../../config.json';
-import { hugeText, spacings, tinyText } from './common-styles';
+import { Colors, Spacings } from '../tokens';
+import { LabelTiny, TitleBig } from './common/text';
export const Container = styled.div({
flex: 0,
- margin: `${spacings.spacing3} ${spacings.spacing5} ${spacings.spacing4}`,
+ margin: `${Spacings.spacing3} ${Spacings.spacing5} ${Spacings.spacing4}`,
});
export const ContentWrapper = styled.div({
@@ -15,13 +15,14 @@ export const ContentWrapper = styled.div({
},
});
-export const HeaderTitle = styled.span(hugeText, {
+export const HeaderTitle = styled(TitleBig)({
wordWrap: 'break-word',
hyphens: 'auto',
});
-export const HeaderSubTitle = styled.span(tinyText, {
- color: colors.white60,
-});
+
+export const HeaderSubTitle = styled(LabelTiny).attrs({
+ $color: Colors.white60,
+})({});
interface ISettingsHeaderProps {
children?: React.ReactNode;
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
index a9777defaf..8da1f41e87 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
@@ -12,8 +12,8 @@ import { RoutePath } from '../lib/routes';
import { useBoolean, useEffectEvent } from '../lib/utility-hooks';
import settingsImportActions from '../redux/settings-import/actions';
import { useSelector } from '../redux/store';
-import { measurements, normalText } from './common-styles';
-import { tinyText } from './common-styles';
+import { Flex } from './common/layout/Flex';
+import { measurements, normalText, tinyText } from './common-styles';
import ImageView from './ImageView';
import { BackAction } from './KeyboardNavigation';
import { Footer, Layout, SettingsContainer } from './Layout';
@@ -25,20 +25,7 @@ import {
TitleBarItem,
} from './NavigationBar';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
-import { SmallButton, SmallButtonGrid } from './SmallButton';
-import { SmallButtonColor } from './SmallButton';
-
-const ContentContainer = styled.div({
- display: 'flex',
- flexDirection: 'column',
- flex: 1,
-});
-
-const Content = styled.div({
- display: 'flex',
- flexDirection: 'column',
- flex: 1,
-});
+import { SmallButton, SmallButtonColor, SmallButtonGrid } from './SmallButton';
const StyledSmallButtonGrid = styled(SmallButtonGrid)({
margin: `0 ${measurements.horizontalViewMargin}`,
@@ -157,8 +144,7 @@ export default function SettingsImport() {
/>
</NavigationItems>
</NavigationBar>
-
- <ContentContainer>
+ <Flex $flexDirection="column" $flex={1}>
<SettingsHeader>
<HeaderTitle>
{messages.pgettext('settings-import', 'Server IP override')}
@@ -171,7 +157,7 @@ export default function SettingsImport() {
</HeaderSubTitle>
</SettingsHeader>
- <Content>
+ <Flex $flexDirection="column" $flex={1}>
<StyledSmallButtonGrid>
<SmallButton onClick={navigateTextImport}>
{messages.pgettext('settings-import', 'Import via text')}
@@ -182,7 +168,7 @@ export default function SettingsImport() {
</StyledSmallButtonGrid>
<SettingsImportStatus status={importStatus} />
- </Content>
+ </Flex>
<Footer>
<SmallButton
@@ -211,7 +197,7 @@ export default function SettingsImport() {
'Clearing the imported overrides changes the server IPs, in the Select location view, back to default.',
)}
/>
- </ContentContainer>
+ </Flex>
</SettingsContainer>
</Layout>
</BackAction>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsStyles.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsStyles.tsx
deleted file mode 100644
index 55915945f4..0000000000
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsStyles.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import styled from 'styled-components';
-
-import * as Cell from './cell';
-import { spacings } from './common-styles';
-
-export const StyledCellIcon = styled(Cell.UntintedIcon)({
- marginRight: spacings.spacing3,
-});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
index 072f62728c..5dad65219f 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { sprintf } from 'sprintf-js';
-import { colors, strings } from '../../config.json';
+import { strings } from '../../config.json';
import {
IApplication,
ILinuxSplitTunnelingApplication,
@@ -14,13 +14,16 @@ import { useHistory } from '../lib/history';
import { formatHtml } from '../lib/html-formatter';
import { useEffectEvent, useStyledRef } from '../lib/utility-hooks';
import { IReduxState } from '../redux/store';
+import { Colors, Spacings } from '../tokens';
import Accordion from './Accordion';
import * as AppButton from './AppButton';
import * as Cell from './cell';
+import { Flex } from './common/layout';
+import { FootnoteMini } from './common/text';
import { CustomScrollbarsRef } from './CustomScrollbars';
import ImageView from './ImageView';
import { BackAction } from './KeyboardNavigation';
-import { Layout, SettingsContainer, Spacing } from './Layout';
+import { Layout, SettingsContainer } from './Layout';
import List from './List';
import { ModalAlert, ModalAlertType } from './Modal';
import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
@@ -37,7 +40,6 @@ import {
StyledIcon,
StyledIconPlaceholder,
StyledListContainer,
- StyledMiniTitle,
StyledNavigationScrollbars,
StyledNoResult,
StyledNoResultText,
@@ -201,7 +203,7 @@ function LinuxSplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsProps
<ModalAlert
isOpen={browseError !== undefined}
type={ModalAlertType.warning}
- iconColor={colors.red}
+ iconColor={Colors.red}
message={sprintf(
// TRANSLATORS: Error message showed in a dialog when an application fails to launch.
messages.pgettext(
@@ -240,7 +242,7 @@ function LinuxApplicationRow(props: ILinuxApplicationRowProps) {
const hideWarningDialog = useCallback(() => setShowWarning(false), []);
const disabled = props.application.warning === 'launches-elsewhere';
- const warningColor = disabled ? colors.red : colors.yellow;
+ const warningColor = disabled ? Colors.red : Colors.yellow;
const warningMessage = disabled
? sprintf(
messages.pgettext(
@@ -538,34 +540,33 @@ function MacOsSplitTunnelingAvailability({
const { showFullDiskAccessSettings, daemonPrepareRestart } = useAppContext();
const restartDaemon = useCallback(() => daemonPrepareRestart(true), [daemonPrepareRestart]);
+ if (!needFullDiskPermissions) return null;
+
return (
- <>
- {needFullDiskPermissions === true ? (
- <>
- <HeaderSubTitle>
- {messages.pgettext(
- 'split-tunneling-view',
- 'To use split tunneling please enable “Full disk access” for “Mullvad VPN” in the macOS system settings.',
- )}
- </HeaderSubTitle>
- <Spacing height="24px" />
+ <Flex $flexDirection="column" $gap={Spacings.spacing6}>
+ <HeaderSubTitle>
+ {messages.pgettext(
+ 'split-tunneling-view',
+ 'To use split tunneling please enable “Full disk access” for “Mullvad VPN” in the macOS system settings.',
+ )}
+ </HeaderSubTitle>
+ <Flex $flexDirection="column" $gap={Spacings.spacing3}>
+ <Flex $flexDirection="column" $gap={Spacings.spacing7}>
<WideSmallButton onClick={showFullDiskAccessSettings}>
{messages.pgettext('split-tunneling-view', 'Open System Settings')}
</WideSmallButton>
- <Spacing height="32px" />
- <StyledMiniTitle>
+ <FootnoteMini $color={Colors.white60}>
{messages.pgettext(
'split-tunneling-view',
'Enabled "Full disk access" and still having issues?',
)}
- </StyledMiniTitle>
- <Spacing height="8px" />
- <WideSmallButton onClick={restartDaemon}>
- {messages.pgettext('split-tunneling-view', 'Restart Mullvad Service')}
- </WideSmallButton>
- </>
- ) : null}
- </>
+ </FootnoteMini>
+ </Flex>
+ <WideSmallButton onClick={restartDaemon}>
+ {messages.pgettext('split-tunneling-view', 'Restart Mullvad Service')}
+ </WideSmallButton>
+ </Flex>
+ </Flex>
);
}
@@ -635,8 +636,8 @@ function ApplicationRow(props: IApplicationRowProps) {
source="icon-close"
width={18}
onClick={onDelete}
- tintColor={colors.white40}
- tintHoverColor={colors.white60}
+ tintColor={Colors.white40}
+ tintHoverColor={Colors.white60}
/>
)}
{props.onAdd && (
@@ -644,8 +645,8 @@ function ApplicationRow(props: IApplicationRowProps) {
source="icon-add"
width={18}
onClick={onAdd}
- tintColor={colors.white40}
- tintHoverColor={colors.white60}
+ tintColor={Colors.white40}
+ tintHoverColor={Colors.white60}
/>
)}
{props.onRemove && (
@@ -653,8 +654,8 @@ function ApplicationRow(props: IApplicationRowProps) {
source="icon-remove"
width={18}
onClick={onRemove}
- tintColor={colors.white40}
- tintHoverColor={colors.white60}
+ tintColor={Colors.white40}
+ tintHoverColor={Colors.white60}
/>
)}
</Cell.CellButton>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
index a2046e61c9..01eb73ec50 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
@@ -3,7 +3,7 @@ import styled from 'styled-components';
import { colors } from '../../config.json';
import * as AppButton from './AppButton';
import * as Cell from './cell';
-import { measurements, miniText, normalText } from './common-styles';
+import { measurements, normalText } from './common-styles';
import ImageView from './ImageView';
import { NavigationScrollbars } from './NavigationBar';
import SearchBar from './SearchBar';
@@ -118,11 +118,6 @@ export const StyledHeaderTitle = styled(HeaderTitle)({
flex: 1,
});
-export const StyledMiniTitle = styled.span({
- ...miniText,
- color: colors.white60,
-});
-
export const StyledSearchBar = styled(SearchBar)({
marginLeft: measurements.horizontalViewMargin,
marginRight: measurements.horizontalViewMargin,
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
index 9c3415d90d..38a0f71bbd 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
@@ -9,7 +9,14 @@ import { useSelector } from '../redux/store';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import { BackAction } from './KeyboardNavigation';
-import { Layout, SettingsContainer } from './Layout';
+import {
+ LabelStack,
+ Layout,
+ SettingsContainer,
+ SettingsContent,
+ SettingsGroup,
+ SettingsStack,
+} from './Layout';
import {
NavigationBar,
NavigationContainer,
@@ -19,18 +26,7 @@ import {
} from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-const StyledContent = styled.div({
- display: 'flex',
- flexDirection: 'column',
- flex: 1,
- marginBottom: '2px',
-});
-
-const StyledCellIcon = styled(Cell.UntintedIcon)({
- marginRight: '8px',
-});
-
-const StyledAnimateMapSettingsGroup = styled(Cell.Group)({
+const StyledAnimateMapCellGroup = styled(SettingsGroup)({
'@media (prefers-reduced-motion: reduce)': {
display: 'none',
},
@@ -63,35 +59,37 @@ export default function UserInterfaceSettings() {
</HeaderTitle>
</SettingsHeader>
- <StyledContent>
- <Cell.Group>
- <NotificationsSetting />
- </Cell.Group>
- <Cell.Group>
- <MonochromaticTrayIconSetting />
- </Cell.Group>
+ <SettingsContent>
+ <SettingsStack>
+ <SettingsGroup>
+ <NotificationsSetting />
+ </SettingsGroup>
+ <SettingsGroup>
+ <MonochromaticTrayIconSetting />
+ </SettingsGroup>
- <Cell.Group>
- <LanguageButton />
- </Cell.Group>
+ <SettingsGroup>
+ <LanguageButton />
+ </SettingsGroup>
- {(window.env.platform === 'win32' ||
- (window.env.platform === 'darwin' && window.env.development)) && (
- <Cell.Group>
- <UnpinnedWindowSetting />
- </Cell.Group>
- )}
+ {(window.env.platform === 'win32' ||
+ (window.env.platform === 'darwin' && window.env.development)) && (
+ <SettingsGroup>
+ <UnpinnedWindowSetting />
+ </SettingsGroup>
+ )}
- {unpinnedWindow && (
- <Cell.Group>
- <StartMinimizedSetting />
- </Cell.Group>
- )}
+ {unpinnedWindow && (
+ <SettingsGroup>
+ <StartMinimizedSetting />
+ </SettingsGroup>
+ )}
- <StyledAnimateMapSettingsGroup>
- <AnimateMapSetting />
- </StyledAnimateMapSettingsGroup>
- </StyledContent>
+ <StyledAnimateMapCellGroup>
+ <AnimateMapSetting />
+ </StyledAnimateMapCellGroup>
+ </SettingsStack>
+ </SettingsContent>
</NavigationScrollbars>
</NavigationContainer>
</SettingsContainer>
@@ -259,13 +257,15 @@ function LanguageButton() {
return (
<Cell.CellNavigationButton onClick={navigate}>
- <StyledCellIcon width={24} height={24} source="icon-language" />
- <Cell.Label>
- {
- // TRANSLATORS: Navigation button to the 'Language' settings view
- messages.pgettext('user-interface-settings-view', 'Language')
- }
- </Cell.Label>
+ <LabelStack>
+ <Cell.UntintedIcon width={24} height={24} source="icon-language" />
+ <Cell.Label>
+ {
+ // TRANSLATORS: Navigation button to the 'Language' settings view
+ messages.pgettext('user-interface-settings-view', 'Language')
+ }
+ </Cell.Label>
+ </LabelStack>
<Cell.SubText>{localeDisplayName}</Cell.SubText>
</Cell.CellNavigationButton>
);
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
index c23ecdbf47..c27072cab2 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
@@ -2,7 +2,7 @@ import { useCallback, useMemo } from 'react';
import { sprintf } from 'sprintf-js';
import styled from 'styled-components';
-import { colors, strings } from '../../config.json';
+import { strings } from '../../config.json';
import { IDnsOptions, TunnelProtocol, wrapConstraint } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import log from '../../shared/logging';
@@ -15,6 +15,7 @@ import { RoutePath } from '../lib/routes';
import { useBoolean } from '../lib/utility-hooks';
import { RelaySettingsRedux } from '../redux/settings/reducers';
import { useSelector } from '../redux/store';
+import { Colors, Spacings } from '../tokens';
import * as AppButton from './AppButton';
import { AriaDescription, AriaDetails, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
@@ -22,7 +23,7 @@ import Selector, { SelectorItem } from './cell/Selector';
import CustomDnsSettings from './CustomDnsSettings';
import InfoButton, { InfoIcon } from './InfoButton';
import { BackAction } from './KeyboardNavigation';
-import { Layout, SettingsContainer } from './Layout';
+import { Layout, SettingsContainer, SettingsContent, SettingsGroup, SettingsStack } from './Layout';
import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
import {
NavigationBar,
@@ -33,19 +34,8 @@ import {
} from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-const StyledContent = styled.div({
- display: 'flex',
- flexDirection: 'column',
- flex: 1,
- marginBottom: '2px',
-});
-
const StyledInfoIcon = styled(InfoIcon)({
- marginRight: '16px',
-});
-
-const StyledSelectorContainer = styled.div({
- flex: 0,
+ marginRight: Spacings.spacing5,
});
const StyledTitleLabel = styled(Cell.SectionTitle)({
@@ -53,16 +43,16 @@ const StyledTitleLabel = styled(Cell.SectionTitle)({
});
const StyledSectionItem = styled(Cell.Container)({
- backgroundColor: colors.blue40,
+ backgroundColor: Colors.blue40,
});
const LanIpRanges = styled.ul({
listStyle: 'disc outside',
- marginLeft: '20px',
+ marginLeft: Spacings.spacing6,
});
const IndentedValueLabel = styled(Cell.ValueLabel)({
- marginLeft: '16px',
+ marginLeft: Spacings.spacing5,
});
export default function VpnSettings() {
@@ -89,46 +79,48 @@ export default function VpnSettings() {
<HeaderTitle>{messages.pgettext('vpn-settings-view', 'VPN settings')}</HeaderTitle>
</SettingsHeader>
- <StyledContent>
- <Cell.Group>
- <AutoStart />
- <AutoConnect />
- </Cell.Group>
+ <SettingsContent>
+ <SettingsStack>
+ <SettingsGroup>
+ <AutoStart />
+ <AutoConnect />
+ </SettingsGroup>
- <Cell.Group>
- <AllowLan />
- </Cell.Group>
+ <SettingsGroup>
+ <AllowLan />
+ </SettingsGroup>
- <Cell.Group>
- <DnsBlockers />
- </Cell.Group>
+ <SettingsGroup>
+ <DnsBlockers />
+ </SettingsGroup>
- <Cell.Group>
- <EnableIpv6 />
- </Cell.Group>
+ <SettingsGroup>
+ <EnableIpv6 />
+ </SettingsGroup>
- <Cell.Group>
- <KillSwitchInfo />
- <LockdownMode />
- </Cell.Group>
+ <SettingsGroup>
+ <KillSwitchInfo />
+ <LockdownMode />
+ </SettingsGroup>
- <Cell.Group>
- <TunnelProtocolSetting />
- </Cell.Group>
+ <SettingsGroup>
+ <TunnelProtocolSetting />
+ </SettingsGroup>
- <Cell.Group>
- <WireguardSettingsButton />
- <OpenVpnSettingsButton />
- </Cell.Group>
+ <SettingsGroup>
+ <WireguardSettingsButton />
+ <OpenVpnSettingsButton />
+ </SettingsGroup>
- <Cell.Group>
- <CustomDnsSettings />
- </Cell.Group>
+ <SettingsGroup>
+ <CustomDnsSettings />
+ </SettingsGroup>
- <Cell.Group>
- <IpOverrideButton />
- </Cell.Group>
- </StyledContent>
+ <SettingsGroup>
+ <IpOverrideButton />
+ </SettingsGroup>
+ </SettingsStack>
+ </SettingsContent>
</NavigationScrollbars>
</NavigationContainer>
</SettingsContainer>
@@ -736,15 +728,13 @@ function TunnelProtocolSetting() {
return (
<AriaInputGroup>
- <StyledSelectorContainer>
- <Selector
- title={messages.pgettext('vpn-settings-view', 'Tunnel protocol')}
- items={tunnelProtocolItems}
- value={tunnelProtocol ?? null}
- onSelect={setTunnelProtocol}
- automaticValue={null}
- />
- </StyledSelectorContainer>
+ <Selector
+ title={messages.pgettext('vpn-settings-view', 'Tunnel protocol')}
+ items={tunnelProtocolItems}
+ value={tunnelProtocol ?? null}
+ onSelect={setTunnelProtocol}
+ automaticValue={null}
+ />
{openVpnDisabled ? (
<Cell.CellFooter>
<AriaDescription>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
index b199bd5ee5..b9ee3dedb1 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
@@ -21,7 +21,7 @@ import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGro
import * as Cell from './cell';
import Selector, { SelectorItem, SelectorWithCustomItem } from './cell/Selector';
import { BackAction } from './KeyboardNavigation';
-import { Layout, SettingsContainer } from './Layout';
+import { Layout, SettingsContainer, SettingsContent, SettingsGroup, SettingsStack } from './Layout';
import { ModalMessage } from './Modal';
import {
NavigationBar,
@@ -40,13 +40,6 @@ function mapPortToSelectorItem(value: number): SelectorItem<number> {
return { label: value.toString(), value };
}
-const StyledContent = styled.div({
- display: 'flex',
- flexDirection: 'column',
- flex: 1,
- marginBottom: '2px',
-});
-
const StyledSelectorContainer = styled.div({
flex: 0,
});
@@ -84,28 +77,29 @@ export default function WireguardSettings() {
)}
</HeaderTitle>
</SettingsHeader>
+ <SettingsContent>
+ <SettingsStack>
+ <SettingsGroup>
+ <PortSelector />
+ </SettingsGroup>
- <StyledContent>
- <Cell.Group>
- <PortSelector />
- </Cell.Group>
-
- <Cell.Group>
- <ObfuscationSettings />
- </Cell.Group>
+ <SettingsGroup>
+ <ObfuscationSettings />
+ </SettingsGroup>
- <Cell.Group>
- <QuantumResistantSetting />
- </Cell.Group>
+ <SettingsGroup>
+ <QuantumResistantSetting />
+ </SettingsGroup>
- <Cell.Group>
- <IpVersionSetting />
- </Cell.Group>
+ <SettingsGroup>
+ <IpVersionSetting />
+ </SettingsGroup>
- <Cell.Group>
- <MtuSetting />
- </Cell.Group>
- </StyledContent>
+ <SettingsGroup>
+ <MtuSetting />
+ </SettingsGroup>
+ </SettingsStack>
+ </SettingsContent>
</NavigationScrollbars>
</NavigationContainer>
</SettingsContainer>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/CellButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/CellButton.tsx
index 83f73be146..f637008a68 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/CellButton.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/CellButton.tsx
@@ -1,8 +1,8 @@
import React, { useContext } from 'react';
import styled from 'styled-components';
-import { colors } from '../../../config.json';
-import { spacings } from '../common-styles';
+import { Colors, Spacings } from '../../tokens';
+import { Center } from '../common/layout';
import { IImageViewProps } from '../ImageView';
import { CellDisabledContext } from './Container';
import { Icon } from './Label';
@@ -16,15 +16,15 @@ interface IStyledCellButtonProps extends React.HTMLAttributes<HTMLButtonElement>
const StyledCellButton = styled(Row)<IStyledCellButtonProps>((props) => {
const backgroundColor = props.$selected
- ? colors.green
+ ? Colors.green
: props.$containedInSection
- ? colors.blue40
- : colors.blue;
- const backgroundColorHover = props.$selected ? colors.green : colors.blue80;
+ ? Colors.blue40
+ : Colors.blue;
+ const backgroundColorHover = props.$selected ? Colors.green : Colors.blue80;
return {
- paddingRight: spacings.spacing5,
- paddingLeft: spacings.spacing5,
+ paddingRight: Spacings.spacing5,
+ paddingLeft: Spacings.spacing5,
flex: 1,
alignContent: 'center',
cursor: 'default',
@@ -58,13 +58,6 @@ export const CellButton = styled(
}),
)({});
-const StyledNavigationButtonIcon = styled('div')({
- display: 'grid',
- placeItems: 'center',
- width: '24px',
- height: '24px',
-});
-
interface ICellNavigationButtonProps extends ICellButtonProps {
isAriaDescription?: boolean;
icon?: IImageViewProps;
@@ -80,9 +73,9 @@ export function CellNavigationButton({
return (
<CellButton {...props}>
{children}
- <StyledNavigationButtonIcon>
+ <Center $height="24px" $width="24px">
<Icon {...icon} />
- </StyledNavigationButtonIcon>
+ </Center>
</CellButton>
);
}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Container.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Container.tsx
index e35babf790..f8db1c45e6 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Container.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Container.tsx
@@ -1,10 +1,11 @@
import React from 'react';
import styled from 'styled-components';
+import { Spacings } from '../../tokens';
import { Row } from './Row';
const StyledContainer = styled(Row)({
- paddingRight: '16px',
+ padding: `0 ${Spacings.spacing5}`,
});
export const CellDisabledContext = React.createContext<boolean>(false);
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx
index 8d5391c002..2454225638 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx
@@ -1,16 +1,12 @@
import styled from 'styled-components';
-import { colors } from '../../../config.json';
-import { spacings, tinyText } from '../common-styles';
+import { Colors, Spacings } from '../../tokens';
+import { LabelTiny } from '../common/text';
export const CellFooter = styled.div({
- margin: `${spacings.spacing1} ${spacings.spacing6} 0px`,
+ margin: `${Spacings.spacing1} ${Spacings.spacing6} 0px`,
});
-export const CellFooterText = styled.span(tinyText, {
- color: colors.white60,
-});
-
-export const CellFooterBoldText = styled(CellFooterText)({
- fontWeight: 900,
-});
+export const CellFooterText = styled(LabelTiny).attrs({
+ $color: Colors.white60,
+})({});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Label.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Label.tsx
index 556481e50e..3123a31dc4 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Label.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Label.tsx
@@ -1,8 +1,8 @@
import React, { useContext } from 'react';
import styled from 'styled-components';
-import { colors } from '../../../config.json';
-import { buttonText, normalText, spacings, tinyText } from '../common-styles';
+import { Colors, Spacings } from '../../tokens';
+import { buttonText, normalText, tinyText } from '../common-styles';
import ImageView, { IImageViewProps } from '../ImageView';
import { CellButton } from './CellButton';
import { CellDisabledContext } from './Container';
@@ -11,7 +11,7 @@ const StyledLabel = styled.div<{ disabled: boolean }>(buttonText, (props) => ({
display: 'flex',
margin: '10px 0',
flex: 1,
- color: props.disabled ? colors.white40 : colors.white,
+ color: props.disabled ? Colors.white40 : Colors.white,
textAlign: 'left',
[`${LabelContainer} &&`]: {
@@ -27,10 +27,10 @@ const StyledLabel = styled.div<{ disabled: boolean }>(buttonText, (props) => ({
}));
const StyledSubText = styled.span<{ disabled: boolean }>(tinyText, (props) => ({
- color: props.disabled ? colors.white20 : colors.white60,
+ color: props.disabled ? Colors.white20 : Colors.white60,
flex: -1,
textAlign: 'right',
- margin: `0 ${spacings.spacing3}`,
+ margin: `0 ${Spacings.spacing3}`,
}));
const StyledIconContainer = styled.div<{ disabled: boolean }>((props) => ({
@@ -38,8 +38,8 @@ const StyledIconContainer = styled.div<{ disabled: boolean }>((props) => ({
}));
const StyledTintedIcon = styled(ImageView).attrs((props: IImageViewProps) => ({
- tintColor: props.tintColor ?? colors.white,
- tintHoverColor: props.tintHoverColor ?? props.tintColor ?? colors.white60,
+ tintColor: props.tintColor ?? Colors.white,
+ tintHoverColor: props.tintHoverColor ?? props.tintColor ?? Colors.white60,
}))((props: IImageViewProps) => ({
'&&:hover': {
backgroundColor: props.tintHoverColor,
@@ -52,7 +52,7 @@ const StyledTintedIcon = styled(ImageView).attrs((props: IImageViewProps) => ({
const StyledSubLabel = styled.div<{ disabled: boolean }>(tinyText, {
display: 'flex',
alignItems: 'center',
- color: colors.white60,
+ color: Colors.white60,
marginBottom: '5px',
lineHeight: '14px',
height: '14px',
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx
index b7465ecb93..0e390eb901 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx
@@ -1,10 +1,10 @@
import React, { useEffect } from 'react';
import styled from 'styled-components';
-import { colors } from '../../../config.json';
import { useAppContext } from '../../context';
import { useHistory } from '../../lib/history';
import { useBoolean, useEffectEvent } from '../../lib/utility-hooks';
+import { Colors, Spacings } from '../../tokens';
import Accordion from '../Accordion';
import ChevronButton from '../ChevronButton';
import { buttonText, openSans, sourceSansPro } from '../common-styles';
@@ -22,8 +22,8 @@ interface SectionTitleProps {
}
export const SectionTitle = styled(Row)<SectionTitleProps>(buttonText, (props) => ({
- paddingRight: '16px',
- color: props.disabled ? colors.white20 : colors.white,
+ paddingRight: Spacings.spacing5,
+ color: props.disabled ? Colors.white20 : Colors.white,
fontWeight: props.$thin ? 400 : 600,
fontSize: props.$thin ? '15px' : '18px',
...(props.$thin ? openSans : sourceSansPro),
@@ -49,7 +49,7 @@ export function Section(props: SectionProps) {
const StyledChevronButton = styled(ChevronButton)({
padding: 0,
- marginRight: '16px',
+ marginRight: Spacings.spacing5,
});
const StyledTitleContainer = styled(Container)({
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common-styles.ts b/desktop/packages/mullvad-vpn/src/renderer/components/common-styles.ts
index 18c5237843..fc08d8411d 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/common-styles.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/common-styles.ts
@@ -1,6 +1,6 @@
import React from 'react';
-import { colors } from '../../config.json';
+import { Colors, Spacings } from '../tokens';
export const openSans: React.CSSProperties = {
fontFamily: 'Open Sans',
@@ -10,13 +10,6 @@ export const sourceSansPro: React.CSSProperties = {
fontFamily: '"Source Sans Pro", "Noto Sans Myanmar", "Noto Sans Thai", sans-serif',
};
-export const miniText = {
- ...openSans,
- fontSize: '10px',
- fontWeight: 600,
- lineHeight: '15px',
-};
-
export const tinyText = {
...openSans,
fontSize: '12px',
@@ -29,7 +22,7 @@ export const smallText = {
fontSize: '14px',
fontWeight: 600,
lineHeight: '20px',
- color: colors.white80,
+ color: Colors.white80,
};
export const smallNormalText = {
@@ -52,7 +45,7 @@ export const largeText = {
export const buttonText = {
...largeText,
- color: colors.white,
+ color: Colors.white,
};
export const bigText = {
@@ -67,29 +60,13 @@ export const hugeText = {
fontSize: '32px',
fontWeight: 700,
lineHeight: '34px',
- color: colors.white,
-};
-
-export const spacings = {
- spacing1: '4px',
- spacing2: '6px',
- spacing3: '8px',
- spacing4: '12px',
- spacing5: '16px',
- spacing6: '24px',
- spacing7: '32px',
- spacing8: '40px',
- spacing9: '48px',
- spacing10: '56px',
- spacing11: '64px',
- spacing12: '72px',
- spacing13: '80px',
+ color: Colors.white,
};
export const measurements = {
- rowMinHeight: spacings.spacing9,
- horizontalViewMargin: spacings.spacing5,
- verticalViewMargin: spacings.spacing6,
- rowVerticalMargin: spacings.spacing6,
- buttonVerticalMargin: spacings.spacing5,
+ rowMinHeight: Spacings.spacing9,
+ horizontalViewMargin: Spacings.spacing5,
+ verticalViewMargin: Spacings.spacing6,
+ rowVerticalMargin: Spacings.spacing6,
+ buttonVerticalMargin: Spacings.spacing5,
};