summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOliver <oliver@mohlin.dev>2025-01-09 12:26:47 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2025-01-13 15:02:51 +0100
commit1e5964d0ee1defcfb18fa170f64c897d81c413e4 (patch)
tree3fca44cec7a713a409fed7bdf6ffafff3da2808a
parente311a5e181e4115f35cd800cc52b2100ef853379 (diff)
downloadmullvadvpn-1e5964d0ee1defcfb18fa170f64c897d81c413e4.tar.xz
mullvadvpn-1e5964d0ee1defcfb18fa170f64c897d81c413e4.zip
Use AppNavigationHeader in app
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx18
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx59
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/DaitaSettings.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/EditApiAccessMethod.tsx9
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/EditCustomBridge.tsx9
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Filter.tsx27
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/InfoButton.tsx40
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx2
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/MultihopSettings.tsx18
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/NavigationBar.tsx230
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/NavigationBarStyles.tsx57
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/NavigationContainer.tsx64
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx73
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/OpenVpnSettings.tsx32
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx18
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SelectLanguage.tsx26
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx19
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx60
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SettingsTextImport.tsx34
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Shadowsocks.tsx26
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx9
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx2
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/Support.tsx26
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/UdpOverTcp.tsx26
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx26
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx54
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx32
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/Selector.tsx9
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsGroup.tsx2
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/index.ts1
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/select-location/SelectLocation.tsx45
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpecialLocationList.tsx4
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx19
35 files changed, 401 insertions, 723 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx
index 1cc666910e..115196a49d 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx
@@ -7,6 +7,7 @@ import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { useEffectEvent } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import AccountNumberLabel from './AccountNumberLabel';
import {
AccountContainer,
@@ -23,7 +24,6 @@ import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGrou
import DeviceInfoButton from './DeviceInfoButton';
import { BackAction } from './KeyboardNavigation';
import { Footer, Layout, SettingsContainer } from './Layout';
-import { NavigationBar, NavigationItems, TitleBarItem } from './NavigationBar';
import { RedeemVoucherButton } from './RedeemVoucher';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
@@ -49,16 +49,12 @@ export default function Account() {
<BackAction action={history.pop}>
<Layout>
<SettingsContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('account-view', 'Account')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('account-view', 'Account')
+ }
+ />
<AccountContainer>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx
index bf1a2025df..83142d29d7 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/ApiAccessMethods.tsx
@@ -14,6 +14,7 @@ import { generateRoutePath } from '../lib/routeHelpers';
import { RoutePath } from '../lib/routes';
import { useBoolean } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import * as Cell from './cell';
import {
ContextMenu,
@@ -26,13 +27,7 @@ import InfoButton from './InfoButton';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer, SettingsContent, SettingsNavigationScrollbars } from './Layout';
import { ModalAlert, ModalAlertType } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationInfoButton,
- NavigationItems,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import { SmallButton, SmallButtonColor } from './SmallButton';
@@ -42,7 +37,7 @@ const StyledContextMenuButton = styled(Cell.Icon)({
marginRight: Spacings.spacing3,
});
-const StyledMethodInfoButton = styled(InfoButton)({
+const StyledMethodInfoButton = styled(InfoButton).attrs({ size: 'small' })({
marginRight: Spacings.spacing4,
});
@@ -82,32 +77,28 @@ export default function ApiAccessMethods() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('navigation-bar', 'API access')
- }
- </TitleBarItem>
- <NavigationInfoButton
- message={[
- messages.pgettext(
- 'api-access-methods-view',
- 'The app needs to communicate with a Mullvad API server to log you in, fetch server lists, and other critical operations.',
- ),
- messages.pgettext(
- 'api-access-methods-view',
- 'On some networks, where various types of censorship are being used, the API servers might not be directly reachable.',
- ),
- messages.pgettext(
- 'api-access-methods-view',
- 'This feature allows you to circumvent that censorship by adding custom ways to access the API via proxies and similar methods.',
- ),
- ]}
- />
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('navigation-bar', 'API access')
+ }>
+ <AppNavigationHeader.InfoButton
+ message={[
+ messages.pgettext(
+ 'api-access-methods-view',
+ 'The app needs to communicate with a Mullvad API server to log you in, fetch server lists, and other critical operations.',
+ ),
+ messages.pgettext(
+ 'api-access-methods-view',
+ 'On some networks, where various types of censorship are being used, the API servers might not be directly reachable.',
+ ),
+ messages.pgettext(
+ 'api-access-methods-view',
+ 'This feature allows you to circumvent that censorship by adding custom ways to access the API via proxies and similar methods.',
+ ),
+ ]}
+ />
+ </AppNavigationHeader>
<SettingsNavigationScrollbars fillContainer>
<SettingsContent>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/DaitaSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/DaitaSettings.tsx
index 264b389f84..a3ebac27be 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/DaitaSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/DaitaSettings.tsx
@@ -10,19 +10,15 @@ import { Spacings } from '../lib/foundations';
import { useHistory } from '../lib/history';
import { useBoolean } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import InfoButton from './InfoButton';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import PageSlider from './PageSlider';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import { SmallButton, SmallButtonColor } from './SmallButton';
@@ -44,11 +40,7 @@ export default function DaitaSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{strings.daita}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={strings.daita} />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
index fee86b00cc..6e3fe6540c 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Debug.tsx
@@ -4,17 +4,13 @@ import styled from 'styled-components';
import { Spacings } from '../lib/foundations';
import { useHistory } from '../lib/history';
import { useBoolean } from '../lib/utility-hooks';
+import { AppNavigationHeader } from './';
import * as AppButton from './AppButton';
import { measurements } from './common-styles';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const StyledContent = styled.div({
@@ -36,11 +32,7 @@ export default function Debug() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>Developer tools</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title="Developer tools" />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/EditApiAccessMethod.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/EditApiAccessMethod.tsx
index 79c7de6861..6dec1e8eb6 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/EditApiAccessMethod.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/EditApiAccessMethod.tsx
@@ -14,11 +14,12 @@ import { useApiAccessMethodTest } from '../lib/api-access-methods';
import { useHistory } from '../lib/history';
import { useLastDefinedValue } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { SettingsForm } from './cell/SettingsForm';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer, SettingsContent, SettingsNavigationScrollbars } from './Layout';
import { ModalAlert, ModalAlertType } from './Modal';
-import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
import { NamedProxyForm } from './ProxyForm';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import { SmallButton } from './SmallButton';
@@ -95,11 +96,7 @@ function AccessMethodForm() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{title}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={title} />
<SettingsNavigationScrollbars fillContainer>
<SettingsContent>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/EditCustomBridge.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/EditCustomBridge.tsx
index 2ab8f81083..6d45eda229 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/EditCustomBridge.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/EditCustomBridge.tsx
@@ -6,11 +6,12 @@ import { useBridgeSettingsUpdater } from '../lib/constraint-updater';
import { useHistory } from '../lib/history';
import { useBoolean } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { SettingsForm } from './cell/SettingsForm';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer, SettingsContent, SettingsNavigationScrollbars } from './Layout';
import { ModalAlert, ModalAlertType } from './Modal';
-import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
import { ProxyForm } from './ProxyForm';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
import { SmallButton, SmallButtonColor } from './SmallButton';
@@ -66,11 +67,7 @@ function CustomBridgeForm() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{title}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={title} />
<SettingsNavigationScrollbars fillContainer>
<SettingsContent>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Filter.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Filter.tsx
index 940563fd87..790215cab4 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Filter.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Filter.tsx
@@ -15,6 +15,7 @@ import { useNormalRelaySettings, useTunnelProtocol } from '../lib/relay-settings
import { useBoolean } from '../lib/utility-hooks';
import { IRelayLocationCountryRedux } from '../redux/settings/reducers';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import Accordion from './Accordion';
import * as AppButton from './AppButton';
import { AriaInputGroup, AriaLabel } from './AriaGroup';
@@ -24,13 +25,8 @@ import { normalText } from './common-styles';
import ImageView from './ImageView';
import { BackAction } from './KeyboardNavigation';
import { Footer, Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
const StyledNavigationScrollbars = styled(NavigationScrollbars)({
backgroundColor: colors.darkBlue,
@@ -83,16 +79,13 @@ export default function Filter() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar alwaysDisplayBarTitle={true}>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('filter-nav', 'Filter')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('filter-nav', 'Filter')
+ }
+ titleVisible
+ />
<StyledNavigationScrollbars>
<FilterByOwnership
ownership={ownership}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/InfoButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/InfoButton.tsx
index 7f77f115e7..8243e5b3be 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/InfoButton.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/InfoButton.tsx
@@ -1,20 +1,10 @@
-import styled from 'styled-components';
-
import { colors } from '../../config.json';
import { messages } from '../../shared/gettext';
+import { Button, IconButton, IconButtonProps } from '../lib/components';
import { useBoolean } from '../lib/utility-hooks';
-import * as AppButton from './AppButton';
import ImageView from './ImageView';
import { ModalAlert, ModalAlertType } from './Modal';
-const StyledInfoButton = styled.button({
- margin: '0 16px 0 8px',
- borderWidth: 0,
- padding: 0,
- cursor: 'default',
- backgroundColor: 'transparent',
-});
-
interface IInfoIconProps {
className?: string;
size?: number;
@@ -34,39 +24,35 @@ export function InfoIcon(props: IInfoIconProps) {
);
}
-export interface IInfoButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
+export interface InfoButtonProps extends Omit<IconButtonProps, 'icon'> {
+ title?: string;
message?: string | Array<string>;
children?: React.ReactNode;
- title?: string;
- size?: number;
- tintColor?: string;
- tintHoverColor?: string;
}
-export default function InfoButton(props: IInfoButtonProps) {
- const { message, children, size, tintColor, tintHoverColor, ...otherProps } = props;
+export default function InfoButton({ title, message, children, ...props }: InfoButtonProps) {
const [isOpen, show, hide] = useBoolean(false);
return (
<>
- <StyledInfoButton
+ <IconButton
+ icon="icon-info"
onClick={show}
aria-label={messages.pgettext('accessibility', 'More information')}
- {...otherProps}>
- <InfoIcon size={size} tintColor={tintColor} tintHoverColor={tintHoverColor} />
- </StyledInfoButton>
+ {...props}
+ />
<ModalAlert
isOpen={isOpen}
- title={props.title}
- message={props.message}
+ title={title}
+ message={message}
type={ModalAlertType.info}
buttons={[
- <AppButton.BlueButton key="back" onClick={hide}>
+ <Button key="back" onClick={hide}>
{messages.gettext('Got it!')}
- </AppButton.BlueButton>,
+ </Button>,
]}
close={hide}>
- {props.children}
+ {children}
</ModalAlert>
</>
);
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
index 9ea55431f0..ff7c8c7943 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Layout.tsx
@@ -3,7 +3,7 @@ import styled from 'styled-components';
import { Flex } from '../lib/components';
import { Colors, Spacings } from '../lib/foundations';
import { measurements } from './common-styles';
-import { NavigationScrollbars } from './NavigationBar';
+import { NavigationScrollbars } from './NavigationScrollbars';
export const Container = styled.div({
display: 'flex',
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/MultihopSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/MultihopSettings.tsx
index e7e16b395a..d885dd8533 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/MultihopSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/MultihopSettings.tsx
@@ -8,18 +8,14 @@ import { Flex } from '../lib/components';
import { useRelaySettingsUpdater } from '../lib/constraint-updater';
import { useHistory } from '../lib/history';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import { StyledIllustration } from './DaitaSettings';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
export default function MultihopSettings() {
@@ -30,13 +26,7 @@ export default function MultihopSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {messages.pgettext('wireguard-settings-view', 'Multihop')}
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={messages.pgettext('wireguard-settings-view', 'Multihop')} />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBar.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBar.tsx
deleted file mode 100644
index 680393a6c7..0000000000
--- a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBar.tsx
+++ /dev/null
@@ -1,230 +0,0 @@
-import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef } from 'react';
-import styled from 'styled-components';
-
-import { colors } from '../../config.json';
-import { messages } from '../../shared/gettext';
-import { useAppContext } from '../context';
-import { transitions, useHistory } from '../lib/history';
-import { useCombinedRefs, useEffectEvent } from '../lib/utility-hooks';
-import CustomScrollbars, { CustomScrollbarsRef, IScrollEvent } from './CustomScrollbars';
-import InfoButton from './InfoButton';
-import { BackActionContext } from './KeyboardNavigation';
-import {
- StyledBackBarItemButton,
- StyledBackBarItemIcon,
- StyledNavigationBar,
- StyledNavigationBarSeparator,
- StyledNavigationItems,
- StyledTitleBarItemLabel,
-} from './NavigationBarStyles';
-
-interface INavigationContainerProps {
- children?: React.ReactNode;
-}
-
-interface INavigationContainerState {
- showsBarTitle: boolean;
- showsBarSeparator: boolean;
-}
-
-const NavigationScrollContext = React.createContext({
- showsBarTitle: false,
- showsBarSeparator: false,
- onScroll(_event: IScrollEvent): void {
- throw Error('NavigationScrollContext provider missing');
- },
-});
-
-export class NavigationContainer extends React.Component<
- INavigationContainerProps,
- INavigationContainerState
-> {
- public state = {
- showsBarTitle: false,
- showsBarSeparator: false,
- };
-
- public componentDidMount() {
- this.updateBarAppearance({ scrollLeft: 0, scrollTop: 0 });
- }
-
- public render() {
- return (
- <NavigationScrollContext.Provider
- value={{
- ...this.state,
- onScroll: this.onScroll,
- }}>
- {this.props.children}
- </NavigationScrollContext.Provider>
- );
- }
-
- public onScroll = (event: IScrollEvent) => {
- this.updateBarAppearance(event);
- };
-
- private updateBarAppearance(event: IScrollEvent) {
- // that's where SettingsHeader.HeaderTitle intersects the navigation bar
- const showsBarSeparator = event.scrollTop > 11;
-
- // that's when SettingsHeader.HeaderTitle goes behind the navigation bar
- const showsBarTitle = event.scrollTop > 20;
-
- if (
- this.state.showsBarSeparator !== showsBarSeparator ||
- this.state.showsBarTitle !== showsBarTitle
- ) {
- this.setState({ showsBarSeparator, showsBarTitle });
- }
- }
-}
-
-interface INavigationScrollbarsProps {
- className?: string;
- fillContainer?: boolean;
- children?: React.ReactNode;
-}
-
-export const NavigationScrollbars = React.forwardRef(function NavigationScrollbarsT(
- props: INavigationScrollbarsProps,
- forwardedRef?: React.Ref<CustomScrollbarsRef>,
-) {
- const history = useHistory();
- const { setNavigationHistory } = useAppContext();
- const { onScroll } = useContext(NavigationScrollContext);
-
- const ref = useRef<CustomScrollbarsRef>();
- const combinedRefs = useCombinedRefs(forwardedRef, ref);
-
- const beforeunload = useEffectEvent(() => {
- if (ref.current) {
- history.recordScrollPosition(ref.current.getScrollPosition());
- setNavigationHistory(history.asObject);
- }
- });
-
- useEffect(() => {
- window.addEventListener('beforeunload', beforeunload);
- return () => window.removeEventListener('beforeunload', beforeunload);
- }, []);
-
- const onMount = useEffectEvent(() => {
- const location = history.location;
- if (history.action === 'POP') {
- ref.current?.scrollTo(...location.state.scrollPosition);
- }
- });
-
- const onUnmount = useEffectEvent(() => {
- if (history.action === 'PUSH' && ref.current) {
- history.recordScrollPosition(ref.current.getScrollPosition());
- setNavigationHistory(history.asObject);
- }
- });
-
- useLayoutEffect(() => {
- onMount();
- return () => onUnmount();
- }, []);
-
- const handleScroll = useCallback(
- (event: IScrollEvent) => {
- onScroll(event);
- },
- [onScroll],
- );
-
- return (
- <CustomScrollbars
- ref={combinedRefs}
- className={props.className}
- fillContainer={props.fillContainer}
- onScroll={handleScroll}>
- {props.children}
- </CustomScrollbars>
- );
-});
-
-const TitleBarItemContext = React.createContext({
- visible: false,
-});
-
-interface INavigationBarProps {
- children?: React.ReactNode;
- alwaysDisplayBarTitle?: boolean;
-}
-
-export const NavigationBar = function NavigationBarT(props: INavigationBarProps) {
- const { showsBarSeparator, showsBarTitle } = useContext(NavigationScrollContext);
-
- return (
- <StyledNavigationBar>
- <TitleBarItemContext.Provider
- value={{ visible: props.alwaysDisplayBarTitle || showsBarTitle }}>
- {props.children}
- </TitleBarItemContext.Provider>
- {showsBarSeparator && <StyledNavigationBarSeparator />}
- </StyledNavigationBar>
- );
-};
-
-interface INavigationItemsProps {
- children: React.ReactNode;
-}
-
-export function NavigationItems(props: INavigationItemsProps) {
- const { parentBackAction } = useContext(BackActionContext);
- return (
- <StyledNavigationItems>
- {parentBackAction && <BackBarItem />}
- {props.children}
- </StyledNavigationItems>
- );
-}
-
-interface ITitleBarItemProps {
- children?: React.ReactText;
-}
-
-export const TitleBarItem = React.memo(function TitleBarItemT(props: ITitleBarItemProps) {
- const { visible } = useContext(TitleBarItemContext);
- return <StyledTitleBarItemLabel $visible={visible}>{props.children}</StyledTitleBarItemLabel>;
-});
-
-export function BackBarItem() {
- const history = useHistory();
- // Compare the transition name with dismiss to infer wheter or not the view will slide
- // horizontally or vertically and then use matching button.
- const backIcon = useMemo(
- () => history.getPopTransition().name !== transitions.dismiss.name,
- [history],
- );
- const { parentBackAction } = useContext(BackActionContext);
- const iconSource = backIcon ? 'icon-back' : 'icon-close-down';
- const ariaLabel = backIcon ? messages.gettext('Back') : messages.gettext('Close');
-
- return (
- <StyledBackBarItemButton aria-label={ariaLabel} onClick={parentBackAction}>
- <StyledBackBarItemIcon source={iconSource} tintColor={colors.white40} width={24} />
- </StyledBackBarItemButton>
- );
-}
-
-const navigationRightHandSideButton: React.CSSProperties = {
- justifySelf: 'end',
- borderWidth: 0,
- padding: 0,
- margin: 0,
- cursor: 'default',
- backgroundColor: 'transparent',
-};
-
-export const NavigationBarButton = styled.button({ ...navigationRightHandSideButton });
-export const NavigationInfoButton = styled(InfoButton).attrs({
- size: 24,
- tintColor: colors.white40,
- tintHoverColor: colors.white60,
-})({
- ...navigationRightHandSideButton,
-});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBarStyles.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBarStyles.tsx
deleted file mode 100644
index eb4472c900..0000000000
--- a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationBarStyles.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import styled from 'styled-components';
-
-import { colors } from '../../config.json';
-import { normalText } from './common-styles';
-import ImageView from './ImageView';
-
-export const StyledNavigationBarSeparator = styled.div({
- backgroundColor: 'rgba(0, 0, 0, 0.2)',
- position: 'absolute',
- bottom: 0,
- left: 0,
- right: 0,
- height: '1px',
-});
-
-export const StyledNavigationItems = styled.div({
- flex: 1,
- display: 'grid',
- gridTemplateColumns: '1fr auto 1fr',
- alignItems: 'center',
-});
-
-export const StyledNavigationBar = styled.nav({
- flex: 0,
- padding: '12px',
-});
-
-export const StyledTitleBarItemLabel = styled.h1<{ $visible?: boolean }>(normalText, (props) => ({
- fontWeight: 400,
- lineHeight: '22px',
- color: colors.white,
- padding: '0 5px',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- opacity: props.$visible ? 1 : 0,
- transition: 'opacity 250ms ease-in-out',
-}));
-
-export const StyledBackBarItemButton = styled.button({
- justifySelf: 'start',
- borderWidth: 0,
- padding: 0,
- margin: 0,
- cursor: 'default',
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- backgroundColor: 'transparent',
-});
-
-export const StyledBackBarItemIcon = styled(ImageView)({
- marginRight: '8px',
- [StyledBackBarItemButton + ':hover &&']: {
- backgroundColor: colors.white60,
- },
-});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationContainer.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationContainer.tsx
new file mode 100644
index 0000000000..5bfeb24253
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationContainer.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+
+import { IScrollEvent } from './CustomScrollbars';
+
+interface NavigationContainerProps {
+ children?: React.ReactNode;
+}
+
+interface NavigationContainerState {
+ showsBarTitle: boolean;
+ showsBarSeparator: boolean;
+}
+
+export class NavigationContainer extends React.Component<
+ NavigationContainerProps,
+ NavigationContainerState
+> {
+ public state = {
+ showsBarTitle: false,
+ showsBarSeparator: false,
+ };
+
+ public componentDidMount() {
+ this.updateBarAppearance({ scrollLeft: 0, scrollTop: 0 });
+ }
+
+ public render() {
+ return (
+ <NavigationScrollContext.Provider
+ value={{
+ ...this.state,
+ onScroll: this.onScroll,
+ }}>
+ {this.props.children}
+ </NavigationScrollContext.Provider>
+ );
+ }
+
+ public onScroll = (event: IScrollEvent) => {
+ this.updateBarAppearance(event);
+ };
+
+ private updateBarAppearance(event: IScrollEvent) {
+ // that's where SettingsHeader.HeaderTitle intersects the navigation bar
+ const showsBarSeparator = event.scrollTop > 11;
+
+ // that's when SettingsHeader.HeaderTitle goes behind the navigation bar
+ const showsBarTitle = event.scrollTop > 20;
+
+ if (
+ this.state.showsBarSeparator !== showsBarSeparator ||
+ this.state.showsBarTitle !== showsBarTitle
+ ) {
+ this.setState({ showsBarSeparator, showsBarTitle });
+ }
+ }
+}
+export const NavigationScrollContext = React.createContext({
+ showsBarTitle: false,
+ showsBarSeparator: false,
+ onScroll(_event: IScrollEvent): void {
+ throw Error('NavigationScrollContext provider missing');
+ },
+});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx
new file mode 100644
index 0000000000..81583b1c4e
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx
@@ -0,0 +1,73 @@
+import React, { useCallback, useContext, useEffect, useLayoutEffect, useRef } from 'react';
+
+import { useAppContext } from '../context';
+import { useHistory } from '../lib/history';
+import { useCombinedRefs, useEffectEvent } from '../lib/utility-hooks';
+import CustomScrollbars, { CustomScrollbarsRef, IScrollEvent } from './CustomScrollbars';
+import { NavigationScrollContext } from './NavigationContainer';
+
+export interface NavigationScrollbarsProps {
+ className?: string;
+ fillContainer?: boolean;
+ children?: React.ReactNode;
+}
+
+export const NavigationScrollbars = React.forwardRef(function NavigationScrollbarsT(
+ props: NavigationScrollbarsProps,
+ forwardedRef?: React.Ref<CustomScrollbarsRef>,
+) {
+ const history = useHistory();
+ const { setNavigationHistory } = useAppContext();
+ const { onScroll } = useContext(NavigationScrollContext);
+
+ const ref = useRef<CustomScrollbarsRef>();
+ const combinedRefs = useCombinedRefs(forwardedRef, ref);
+
+ const beforeunload = useEffectEvent(() => {
+ if (ref.current) {
+ history.recordScrollPosition(ref.current.getScrollPosition());
+ setNavigationHistory(history.asObject);
+ }
+ });
+
+ useEffect(() => {
+ window.addEventListener('beforeunload', beforeunload);
+ return () => window.removeEventListener('beforeunload', beforeunload);
+ }, []);
+
+ const onMount = useEffectEvent(() => {
+ const location = history.location;
+ if (history.action === 'POP') {
+ ref.current?.scrollTo(...location.state.scrollPosition);
+ }
+ });
+
+ const onUnmount = useEffectEvent(() => {
+ if (history.action === 'PUSH' && ref.current) {
+ history.recordScrollPosition(ref.current.getScrollPosition());
+ setNavigationHistory(history.asObject);
+ }
+ });
+
+ useLayoutEffect(() => {
+ onMount();
+ return () => onUnmount();
+ }, []);
+
+ const handleScroll = useCallback(
+ (event: IScrollEvent) => {
+ onScroll(event);
+ },
+ [onScroll],
+ );
+
+ return (
+ <CustomScrollbars
+ ref={combinedRefs}
+ className={props.className}
+ fillContainer={props.fillContainer}
+ onScroll={handleScroll}>
+ {props.children}
+ </CustomScrollbars>
+ );
+});
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/OpenVpnSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/OpenVpnSettings.tsx
index 37e72b13e7..d1288b30a1 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/OpenVpnSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/OpenVpnSettings.tsx
@@ -17,19 +17,15 @@ import { useRelaySettingsUpdater } from '../lib/constraint-updater';
import { useHistory } from '../lib/history';
import { formatHtml } from '../lib/html-formatter';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import Selector, { SelectorItem } from './cell/Selector';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import { ModalMessage } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const MIN_MSSFIX_VALUE = 1000;
@@ -70,19 +66,15 @@ export default function OpenVpnSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {sprintf(
- // TRANSLATORS: Title label in navigation bar
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(openvpn)s - Will be replaced with "OpenVPN"
- messages.pgettext('openvpn-settings-nav', '%(openvpn)s settings'),
- { openvpn: strings.openvpn },
- )}
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={sprintf(
+ // TRANSLATORS: Title label in navigation bar
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(openvpn)s - Will be replaced with "OpenVPN"
+ messages.pgettext('openvpn-settings-nav', '%(openvpn)s settings'),
+ { openvpn: strings.openvpn },
+ )}
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx
index 36ddc09c45..e4213d871f 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx
@@ -20,13 +20,13 @@ import { useHistory } from '../lib/history';
import { useEffectEvent } from '../lib/utility-hooks';
import { useSelector } from '../redux/store';
import support from '../redux/support/actions';
+import { AppNavigationHeader } from './';
import * as AppButton from './AppButton';
import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup';
import ImageView from './ImageView';
import { BackAction } from './KeyboardNavigation';
import { Footer, Layout, SettingsContainer } from './Layout';
import { ModalAlert, ModalAlertType } from './Modal';
-import { NavigationBar, NavigationItems, TitleBarItem } from './NavigationBar';
import {
StyledContent,
StyledContentContainer,
@@ -66,16 +66,12 @@ function ProblemReportComponent() {
<BackAction action={history.pop}>
<Layout>
<SettingsContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('support-view', 'Report a problem')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('support-view', 'Report a problem')
+ }
+ />
<StyledContentContainer>
<Header />
<Content />
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SelectLanguage.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SelectLanguage.tsx
index 84f572fc5a..91ee78429a 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SelectLanguage.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SelectLanguage.tsx
@@ -5,18 +5,14 @@ import { useAppContext } from '../../renderer/context';
import { messages } from '../../shared/gettext';
import { useHistory } from '../lib/history';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaInputGroup } from './AriaGroup';
import Selector, { SelectorItem } from './cell/Selector';
import { CustomScrollbarsRef } from './CustomScrollbars';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const StyledSelector = styled(Selector)({
@@ -56,16 +52,12 @@ export default function SelectLanguage() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('select-language-nav', 'Select language')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('select-language-nav', 'Select language')
+ }
+ />
<NavigationScrollbars ref={scrollView}>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
index f2c4c2760a..1eb7253533 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx
@@ -7,6 +7,7 @@ import { Button, TitleBig } from '../lib/components';
import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import * as Cell from './cell';
import { BackAction } from './KeyboardNavigation';
import {
@@ -19,7 +20,7 @@ import {
SettingsNavigationScrollbars,
SettingsStack,
} from './Layout';
-import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
import SettingsHeader from './SettingsHeader';
export default function Support() {
@@ -37,16 +38,12 @@ export default function Support() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ />
<SettingsNavigationScrollbars fillContainer>
<SettingsContent>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
index 8b7169ab06..b2ebe680d8 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx
@@ -13,17 +13,12 @@ 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 { AppNavigationHeader } from './';
import { measurements, normalText, tinyText } from './common-styles';
import ImageView from './ImageView';
import { BackAction } from './KeyboardNavigation';
import { Footer, Layout, SettingsContainer } from './Layout';
import { ModalAlert, ModalAlertType } from './Modal';
-import {
- NavigationBar,
- NavigationInfoButton,
- NavigationItems,
- TitleBarItem,
-} from './NavigationBar';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import { SmallButton, SmallButtonColor, SmallButtonGrid } from './SmallButton';
@@ -116,34 +111,31 @@ export default function SettingsImport() {
<BackAction action={history.pop}>
<Layout>
<SettingsContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar. This is for a feature that lets
- // TRANSLATORS: users import server IP settings.
- messages.pgettext('settings-import', 'Server IP override')
- }
- </TitleBarItem>
- <NavigationInfoButton
- title={messages.pgettext('settings-import', 'Server IP override')}
- message={[
- messages.pgettext(
- 'settings-import',
- 'On some networks, where various types of censorship are being used, our server IP addresses are sometimes blocked.',
- ),
- messages.pgettext(
- 'settings-import',
- 'To circumvent this you can import a file or a text, provided by our support team, with new IP addresses that override the default addresses of the servers in the Select location view.',
- ),
- messages.pgettext(
- 'settings-import',
- 'If you are having issues connecting to VPN servers, please contact support.',
- ),
- ]}
- />
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar. This is for a feature that lets
+ // TRANSLATORS: users import server IP settings.
+ messages.pgettext('settings-import', 'Server IP override')
+ }>
+ <AppNavigationHeader.InfoButton
+ title={messages.pgettext('settings-import', 'Server IP override')}
+ variant="secondary"
+ message={[
+ messages.pgettext(
+ 'settings-import',
+ 'On some networks, where various types of censorship are being used, our server IP addresses are sometimes blocked.',
+ ),
+ messages.pgettext(
+ 'settings-import',
+ 'To circumvent this you can import a file or a text, provided by our support team, with new IP addresses that override the default addresses of the servers in the Select location view.',
+ ),
+ messages.pgettext(
+ 'settings-import',
+ 'If you are having issues connecting to VPN servers, please contact support.',
+ ),
+ ]}
+ />
+ </AppNavigationHeader>
<Flex $flexDirection="column" $flex={1}>
<SettingsHeader>
<HeaderTitle>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsTextImport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsTextImport.tsx
index c6cb325b0c..ed2dd84695 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsTextImport.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsTextImport.tsx
@@ -8,10 +8,9 @@ import { useHistory } from '../lib/history';
import { useCombinedRefs, useRefCallback, useStyledRef } from '../lib/utility-hooks';
import settingsImportActions from '../redux/settings-import/actions';
import { useSelector } from '../redux/store';
-import ImageView from './ImageView';
+import { AppNavigationHeader } from './';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import { NavigationBar, NavigationBarButton, NavigationItems, TitleBarItem } from './NavigationBar';
const StyledTextArea = styled.textarea({
width: '100%',
@@ -54,25 +53,18 @@ export default function SettingsTextImport() {
<BackAction action={back}>
<Layout>
<SettingsContainer>
- <NavigationBar alwaysDisplayBarTitle>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('settings-import', 'Import via text')
- }
- </TitleBarItem>
- <NavigationBarButton onClick={save} aria-label={messages.gettext('Save')}>
- <ImageView
- source="icon-check"
- tintColor={colors.white40}
- tintHoverColor={colors.white60}
- height={24}
- width={24}
- />
- </NavigationBarButton>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('settings-import', 'Import via text')
+ }
+ titleVisible>
+ <AppNavigationHeader.IconButton
+ icon="icon-check"
+ onClick={save}
+ aria-label={messages.gettext('Save')}
+ />
+ </AppNavigationHeader>
<StyledTextArea ref={combinedTextAreaRef} />
</SettingsContainer>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Shadowsocks.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Shadowsocks.tsx
index 4c59bde50e..b23fe817fc 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Shadowsocks.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Shadowsocks.tsx
@@ -8,18 +8,14 @@ import { removeNonNumericCharacters } from '../../shared/string-helpers';
import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInputGroup } from './AriaGroup';
import * as Cell from './cell';
import { SelectorItem, SelectorWithCustomItem } from './cell/Selector';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const PORTS: Array<SelectorItem<number>> = [];
@@ -44,16 +40,12 @@ export default function Shadowsocks() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('wireguard-settings-nav', 'Shadowsocks')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('wireguard-settings-nav', 'Shadowsocks')
+ }
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
index cab859b8c9..849b420cd1 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx
@@ -16,6 +16,7 @@ import { useHistory } from '../lib/history';
import { formatHtml } from '../lib/html-formatter';
import { useEffectEvent, useStyledRef } from '../lib/utility-hooks';
import { IReduxState } from '../redux/store';
+import { AppNavigationHeader } from './';
import Accordion from './Accordion';
import * as AppButton from './AppButton';
import * as Cell from './cell';
@@ -26,7 +27,7 @@ import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import List from './List';
import { ModalAlert, ModalAlertType } from './Modal';
-import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import {
StyledActionIcon,
@@ -60,11 +61,7 @@ export default function SplitTunneling() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{strings.splitTunneling}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={strings.splitTunneling} />
<StyledNavigationScrollbars ref={scrollbarsRef}>
<PlatformSpecificSplitTunnelingSettings
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
index 554f2a2a11..98438116c9 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettingsStyles.tsx
@@ -6,7 +6,7 @@ import * as AppButton from './AppButton';
import * as Cell from './cell';
import { measurements, normalText } from './common-styles';
import ImageView from './ImageView';
-import { NavigationScrollbars } from './NavigationBar';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SearchBar from './SearchBar';
import { SmallButton } from './SmallButton';
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Support.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Support.tsx
index 2785883ecf..34f49a1c30 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/Support.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/Support.tsx
@@ -7,6 +7,7 @@ import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import {
AriaDescribed,
AriaDescription,
@@ -18,13 +19,8 @@ import {
import * as Cell from './cell';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const StyledContent = styled.div({
@@ -42,16 +38,12 @@ export default function Support() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('support-view', 'Support')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('support-view', 'Support')
+ }
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/UdpOverTcp.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/UdpOverTcp.tsx
index 7179daca77..c6e6ff43f6 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/UdpOverTcp.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/UdpOverTcp.tsx
@@ -6,19 +6,15 @@ import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaInputGroup } from './AriaGroup';
import * as Cell from './cell';
import Selector, { SelectorItem } from './cell/Selector';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import { ModalMessage } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const UDP2TCP_PORTS = [80, 5001];
@@ -46,16 +42,12 @@ export default function UdpOverTcp() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('wireguard-settings-nav', 'UDP-over-TCP')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('wireguard-settings-nav', 'UDP-over-TCP')
+ }
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
index 38a0f71bbd..13c29a7ea7 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/UserInterfaceSettings.tsx
@@ -6,6 +6,7 @@ import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import { BackAction } from './KeyboardNavigation';
@@ -17,13 +18,8 @@ import {
SettingsGroup,
SettingsStack,
} from './Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const StyledAnimateMapCellGroup = styled(SettingsGroup)({
@@ -41,16 +37,12 @@ export default function UserInterfaceSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('user-interface-settings-view', 'User interface settings')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('user-interface-settings-view', 'User interface settings')
+ }
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
index 5754ebce72..a45d461dbc 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/VpnSettings.tsx
@@ -16,25 +16,23 @@ import { RoutePath } from '../lib/routes';
import { useBoolean } from '../lib/utility-hooks';
import { RelaySettingsRedux } from '../redux/settings/reducers';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import * as AppButton from './AppButton';
import { AriaDescription, AriaDetails, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import Selector, { SelectorItem } from './cell/Selector';
import CustomDnsSettings from './CustomDnsSettings';
-import InfoButton, { InfoIcon } from './InfoButton';
+import InfoButton from './InfoButton';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer, SettingsContent, SettingsGroup, SettingsStack } from './Layout';
import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-const StyledInfoIcon = styled(InfoIcon)({
+const StyledInfoButton = styled(InfoButton).attrs({
+ size: 'small',
+})({
marginRight: Spacings.spacing5,
});
@@ -63,16 +61,12 @@ export default function VpnSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('vpn-settings-view', 'VPN settings')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('vpn-settings-view', 'VPN settings')
+ }
+ />
<NavigationScrollbars>
<SettingsHeader>
@@ -204,7 +198,7 @@ function AllowLan() {
</Cell.InputLabel>
</AriaLabel>
<AriaDetails>
- <InfoButton>
+ <StyledInfoButton>
<ModalMessage>
{messages.pgettext(
'vpn-settings-view',
@@ -225,7 +219,7 @@ function AllowLan() {
<li>fc00::/7</li>
</LanIpRanges>
</ModalMessage>
- </InfoButton>
+ </StyledInfoButton>
</AriaDetails>
<AriaInput>
<Cell.Switch isOn={allowLan} onChange={setAllowLan} />
@@ -263,7 +257,7 @@ function DnsBlockers() {
<StyledTitleLabel as="label" disabled={dns.state === 'custom'}>
{messages.pgettext('vpn-settings-view', 'DNS content blockers')}
</StyledTitleLabel>
- <InfoButton>
+ <StyledInfoButton>
<ModalMessage>
{messages.pgettext(
'vpn-settings-view',
@@ -287,7 +281,7 @@ function DnsBlockers() {
),
)}
</ModalMessage>
- </InfoButton>
+ </StyledInfoButton>
</>
);
@@ -368,14 +362,14 @@ function BlockMalware() {
</IndentedValueLabel>
</AriaLabel>
<AriaDetails>
- <InfoButton>
+ <StyledInfoButton>
<ModalMessage>
{messages.pgettext(
'vpn-settings-view',
'Warning: The malware blocker is not an anti-virus and should not be treated as such, this is just an extra layer of protection.',
)}
</ModalMessage>
- </InfoButton>
+ </StyledInfoButton>
</AriaDetails>
<AriaInput>
<Cell.Switch
@@ -510,7 +504,7 @@ function EnableIpv6() {
<Cell.InputLabel>{messages.pgettext('vpn-settings-view', 'Enable IPv6')}</Cell.InputLabel>
</AriaLabel>
<AriaDetails>
- <InfoButton>
+ <StyledInfoButton>
<ModalMessage>
{messages.pgettext(
'vpn-settings-view',
@@ -523,7 +517,7 @@ function EnableIpv6() {
'IPv4 is always enabled and the majority of websites and applications use this protocol. We do not recommend enabling IPv6 unless you know you need it.',
)}
</ModalMessage>
- </InfoButton>
+ </StyledInfoButton>
</AriaDetails>
<AriaInput>
<Cell.Switch isOn={enableIpv6} onChange={setEnableIpv6} />
@@ -545,7 +539,7 @@ function KillSwitchInfo() {
{messages.pgettext('vpn-settings-view', 'Kill switch')}
</Cell.InputLabel>
</AriaLabel>
- <StyledInfoIcon />
+ <StyledInfoButton />
<AriaInput>
<Cell.Switch isOn disabled />
</AriaInput>
@@ -622,7 +616,7 @@ function LockdownMode() {
</Cell.InputLabel>
</AriaLabel>
<AriaDetails>
- <InfoButton>
+ <StyledInfoButton>
<ModalMessage>
{messages.pgettext(
'vpn-settings-view',
@@ -635,7 +629,7 @@ function LockdownMode() {
'With Lockdown Mode enabled, you must be connected to a Mullvad VPN server to be able to reach the internet. Manually disconnecting or quitting the app will block your connection.',
)}
</ModalMessage>
- </InfoButton>
+ </StyledInfoButton>
</AriaDetails>
<AriaInput>
<Cell.Switch isOn={blockWhenDisconnected} onChange={setLockDownMode} />
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
index 5a87ffdb8b..450ced9d31 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/WireguardSettings.tsx
@@ -17,19 +17,15 @@ import { useRelaySettingsUpdater } from '../lib/constraint-updater';
import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
import { useSelector } from '../redux/store';
+import { AppNavigationHeader } from './';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import Selector, { SelectorItem, SelectorWithCustomItem } from './cell/Selector';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer, SettingsContent, SettingsGroup, SettingsStack } from './Layout';
import { ModalMessage } from './Modal';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from './NavigationBar';
+import { NavigationContainer } from './NavigationContainer';
+import { NavigationScrollbars } from './NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const MIN_WIREGUARD_MTU_VALUE = 1280;
@@ -52,19 +48,15 @@ export default function WireguardSettings() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>
- {sprintf(
- // TRANSLATORS: Title label in navigation bar
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(wireguard)s - Will be replaced with the string "WireGuard"
- messages.pgettext('wireguard-settings-nav', '%(wireguard)s settings'),
- { wireguard: strings.wireguard },
- )}
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={sprintf(
+ // TRANSLATORS: Title label in navigation bar
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(wireguard)s - Will be replaced with the string "WireGuard"
+ messages.pgettext('wireguard-settings-nav', '%(wireguard)s settings'),
+ { wireguard: strings.wireguard },
+ )}
+ />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Selector.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Selector.tsx
index b1e20a0c41..4fc8e15925 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Selector.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Selector.tsx
@@ -3,6 +3,7 @@ import styled from 'styled-components';
import { colors } from '../../../config.json';
import { messages } from '../../../shared/gettext';
+import { Spacings } from '../../lib/foundations';
import { useHistory } from '../../lib/history';
import { RoutePath } from '../../lib/routes';
import { useStyledRef } from '../../lib/utility-hooks';
@@ -15,6 +16,10 @@ const StyledTitleLabel = styled(Cell.SectionTitle)({
flex: 1,
});
+const StyledInfoButton = styled(InfoButton)({
+ marginRight: Spacings.spacing5,
+});
+
export interface SelectorItem<T> {
label: string;
value: T;
@@ -94,7 +99,9 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) {
</AriaLabel>
{props.details && (
<AriaDetails>
- <InfoButton title={props.infoTitle}>{props.details}</InfoButton>
+ <StyledInfoButton title={props.infoTitle} size="small">
+ {props.details}
+ </StyledInfoButton>
</AriaDetails>
)}
</>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsGroup.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsGroup.tsx
index c1b9ac80d1..ccca7cdc0b 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsGroup.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsGroup.tsx
@@ -85,7 +85,7 @@ export function SettingsGroup(props: React.PropsWithChildren<SettingsGroupProps>
<StyledTitle>
{props.title}
{props.infoMessage !== undefined && (
- <StyledInfoButton size={12} message={props.infoMessage} />
+ <StyledInfoButton size="small" message={props.infoMessage} />
)}
</StyledTitle>
)}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/index.ts
new file mode 100644
index 0000000000..612a0df28f
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/index.ts
@@ -0,0 +1 @@
+export * from './app-navigation-header';
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SelectLocation.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SelectLocation.tsx
index 32c516d0a0..7779d6fb2b 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SelectLocation.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SelectLocation.tsx
@@ -4,6 +4,7 @@ import { sprintf } from 'sprintf-js';
import { colors, strings } from '../../../config.json';
import { Ownership } from '../../../shared/daemon-rpc-types';
import { messages } from '../../../shared/gettext';
+import { IconButton } from '../../lib/components';
import { useRelaySettingsUpdater } from '../../lib/constraint-updater';
import { daitaFilterActive, filterSpecialLocations } from '../../lib/filter-locations';
import { useHistory } from '../../lib/history';
@@ -11,19 +12,14 @@ import { formatHtml } from '../../lib/html-formatter';
import { useNormalRelaySettings } from '../../lib/relay-settings-hooks';
import { RoutePath } from '../../lib/routes';
import { useSelector } from '../../redux/store';
+import { AppNavigationHeader } from '../';
import * as Cell from '../cell';
import { useFilteredProviders } from '../Filter';
import ImageView from '../ImageView';
import { BackAction } from '../KeyboardNavigation';
import { Layout, SettingsContainer } from '../Layout';
-import {
- NavigationBar,
- NavigationBarButton,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from '../NavigationBar';
+import { NavigationContainer } from '../NavigationContainer';
+import { NavigationScrollbars } from '../NavigationScrollbars';
import CombinedLocationList, { CombinedLocationListProps } from './CombinedLocationList';
import CustomLists from './CustomLists';
import { useRelayListContext } from './RelayListContext';
@@ -133,26 +129,19 @@ export default function SelectLocation() {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar alwaysDisplayBarTitle>
- <NavigationItems>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('select-location-nav', 'Select location')
- }
- </TitleBarItem>
-
- <NavigationBarButton onClick={onViewFilter} aria-label={messages.gettext('Filter')}>
- <ImageView
- source="icon-filter-round"
- tintColor={colors.white40}
- tintHoverColor={colors.white60}
- height={24}
- width={24}
- />
- </NavigationBarButton>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader
+ title={
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('select-location-nav', 'Select location')
+ }
+ titleVisible>
+ <IconButton
+ icon="icon-filter-round"
+ variant="secondary"
+ onClick={onViewFilter}
+ aria-label={messages.gettext('Filter')}
+ />
+ </AppNavigationHeader>
<StyledNavigationBarAttachment>
{allowEntrySelection && (
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpecialLocationList.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpecialLocationList.tsx
index e4d105d635..552f86d9fc 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpecialLocationList.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpecialLocationList.tsx
@@ -35,7 +35,9 @@ export default function SpecialLocationList<T>({ source, ...props }: SpecialLoca
);
}
-const StyledSpecialLocationInfoButton = styled(InfoButton)({ padding: '0 25px', margin: 0 });
+const StyledSpecialLocationInfoButton = styled(InfoButton).attrs({
+ size: 'small',
+})({ width: '56px', height: '48px' });
const StyledSpecialLocationSideButton = styled(ImageView)({ padding: '0 3px' });
interface SpecialLocationRowProps<T> {
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx
index 41671c46a9..dedf6b72bb 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx
@@ -1,14 +1,10 @@
import { messages } from '../../../../shared/gettext';
import { useHistory } from '../../../lib/history';
+import { AppNavigationHeader } from '../../';
import { BackAction } from '../../KeyboardNavigation';
import { Layout, SettingsContainer, SettingsGroup, SettingsStack } from '../../Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from '../../NavigationBar';
+import { NavigationContainer } from '../../NavigationContainer';
+import { NavigationScrollbars } from '../../NavigationScrollbars';
import SettingsHeader, { HeaderTitle } from '../../SettingsHeader';
import { AppVersionListItem, ChangelogListItem } from './components';
@@ -19,11 +15,7 @@ export const AppInfoView = () => {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{messages.pgettext('app-info-view', 'App info')}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={messages.pgettext('app-info-view', 'App info')} />
<NavigationScrollbars>
<SettingsHeader>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx
index 4a93908e65..19a499a34d 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx
@@ -4,21 +4,16 @@ import styled from 'styled-components';
import { links } from '../../../../config.json';
import { messages } from '../../../../shared/gettext';
import { useAppContext } from '../../../context';
-import { BodySmall, Button, Flex, TitleBig, TitleLarge } from '../../../lib/components';
-import { Container } from '../../../lib/components';
+import { BodySmall, Button, Container, Flex, TitleBig, TitleLarge } from '../../../lib/components';
import { Colors, Spacings } from '../../../lib/foundations';
import { useHistory } from '../../../lib/history';
import { useSelector } from '../../../redux/store';
+import { AppNavigationHeader } from '../../';
import ImageView from '../../ImageView';
import { BackAction } from '../../KeyboardNavigation';
import { Layout, SettingsContainer } from '../../Layout';
-import {
- NavigationBar,
- NavigationContainer,
- NavigationItems,
- NavigationScrollbars,
- TitleBarItem,
-} from '../../NavigationBar';
+import { NavigationContainer } from '../../NavigationContainer';
+import { NavigationScrollbars } from '../../NavigationScrollbars';
import SettingsHeader from '../../SettingsHeader';
const StyledList = styled(Flex)({
@@ -49,11 +44,7 @@ export const ChangelogView = () => {
<Layout>
<SettingsContainer>
<NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <TitleBarItem>{messages.pgettext('changelog-view', 'What’s new')}</TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <AppNavigationHeader title={messages.pgettext('changelog-view', 'What’s new')} />
<NavigationScrollbars>
<SettingsHeader>