diff options
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/components/AppButton.tsx | 12 | ||||
| -rw-r--r-- | gui/src/renderer/components/Connect.tsx | 40 | ||||
| -rw-r--r-- | gui/src/renderer/components/ErrorBoundary.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/HeaderBar.tsx | 8 | ||||
| -rw-r--r-- | gui/src/renderer/components/ImageView.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/Launch.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/NavigationBar.tsx | 29 | ||||
| -rw-r--r-- | gui/src/renderer/components/NavigationBarStyles.tsx | 10 | ||||
| -rw-r--r-- | gui/src/renderer/components/NotificationArea.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/NotificationBanner.tsx | 11 | ||||
| -rw-r--r-- | gui/src/renderer/components/SecuredLabel.tsx | 6 | ||||
| -rw-r--r-- | gui/src/renderer/components/SettingsHeader.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/Switch.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/TunnelControl.tsx | 5 |
14 files changed, 87 insertions, 48 deletions
diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx index c0731917d0..5b2c7fa62e 100644 --- a/gui/src/renderer/components/AppButton.tsx +++ b/gui/src/renderer/components/AppButton.tsx @@ -38,7 +38,7 @@ export function Icon(props: IIconProps) { return <ImageView {...props} tintColor={colors.white} />; } -export interface IProps { +export interface IProps extends React.HTMLAttributes<HTMLButtonElement> { children?: React.ReactNode; className?: string; disabled?: boolean; @@ -67,19 +67,17 @@ class BaseButton extends React.Component<IProps, IState> { } public render() { + const { children, ...otherProps } = this.props; + return ( <ButtonContext.Provider value={{ textAdjustment: this.state.textAdjustment, textRef: this.textRef, }}> - <StyledButton - ref={this.buttonRef} - disabled={this.props.disabled} - onClick={this.props.onClick} - className={this.props.className}> + <StyledButton ref={this.buttonRef} {...otherProps}> <StyledButtonContent> - {React.Children.map(this.props.children, (child) => + {React.Children.map(children, (child) => typeof child === 'string' ? <Label>{child as string}</Label> : child, )} </StyledButtonContent> diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx index 184465bd7d..36b88b81df 100644 --- a/gui/src/renderer/components/Connect.tsx +++ b/gui/src/renderer/components/Connect.tsx @@ -61,6 +61,12 @@ const StyledNotificationArea = styled(NotificationArea)({ right: 0, }); +const StyledMain = styled.main({ + display: 'flex', + flexDirection: 'column', + flex: 1, +}); + interface IState { isAccountExpired: boolean; } @@ -137,24 +143,26 @@ export default class Connect extends React.Component<IProps, IState> { <> <StyledMap {...this.getMapProps()} /> <Content> - {/* show spinner when connecting */} - {this.showMarkerOrSpinner() === 'spinner' ? ( - <StatusIcon source="icon-spinner" height={60} width={60} /> - ) : null} + <StyledNotificationArea /> - <TunnelControl - tunnelState={this.props.connection.status} - blockWhenDisconnected={this.props.blockWhenDisconnected} - selectedRelayName={this.props.selectedRelayName} - city={this.props.connection.city} - country={this.props.connection.country} - onConnect={this.props.onConnect} - onDisconnect={this.props.onDisconnect} - onReconnect={this.props.onReconnect} - onSelectLocation={this.props.onSelectLocation} - /> + <StyledMain> + {/* show spinner when connecting */} + {this.showMarkerOrSpinner() === 'spinner' ? ( + <StatusIcon source="icon-spinner" height={60} width={60} /> + ) : null} - <StyledNotificationArea /> + <TunnelControl + tunnelState={this.props.connection.status} + blockWhenDisconnected={this.props.blockWhenDisconnected} + selectedRelayName={this.props.selectedRelayName} + city={this.props.connection.city} + country={this.props.connection.country} + onConnect={this.props.onConnect} + onDisconnect={this.props.onDisconnect} + onReconnect={this.props.onReconnect} + onSelectLocation={this.props.onSelectLocation} + /> + </StyledMain> </Content> </> ); diff --git a/gui/src/renderer/components/ErrorBoundary.tsx b/gui/src/renderer/components/ErrorBoundary.tsx index bd20abcbdc..6470a2052d 100644 --- a/gui/src/renderer/components/ErrorBoundary.tsx +++ b/gui/src/renderer/components/ErrorBoundary.tsx @@ -23,7 +23,7 @@ const StyledContainer = styled(Container)({ backgroundColor: colors.blue, }); -const Title = styled.span({ +const Title = styled.h1({ fontFamily: 'DINPro', fontSize: '24px', fontWeight: 900, diff --git a/gui/src/renderer/components/HeaderBar.tsx b/gui/src/renderer/components/HeaderBar.tsx index 9569dd187e..20045086be 100644 --- a/gui/src/renderer/components/HeaderBar.tsx +++ b/gui/src/renderer/components/HeaderBar.tsx @@ -19,7 +19,7 @@ const headerBarStyleColorMap = { [HeaderBarStyle.success]: colors.green, }; -const HeaderBarContainer = styled.div({}, (props: { barStyle?: HeaderBarStyle }) => ({ +const HeaderBarContainer = styled.header({}, (props: { barStyle?: HeaderBarStyle }) => ({ padding: '12px 16px', paddingTop: process.platform === 'darwin' ? '24px' : '12px', backgroundColor: headerBarStyleColorMap[props.barStyle ?? HeaderBarStyle.default], @@ -53,7 +53,7 @@ const BrandContainer = styled.div({ alignItems: 'center', }); -const Title = styled.span({ +const Title = styled.h1({ fontFamily: 'DINPro', fontSize: '24px', fontWeight: 900, @@ -91,7 +91,9 @@ export function HeaderBarSettingsButton() { }, [history]); return ( - <HeaderBarSettingsButtonContainer onClick={openSettings}> + <HeaderBarSettingsButtonContainer + onClick={openSettings} + aria-label={messages.gettext('Settings')}> <ImageView height={24} width={24} diff --git a/gui/src/renderer/components/ImageView.tsx b/gui/src/renderer/components/ImageView.tsx index 6765b89a53..0414f8f1ff 100644 --- a/gui/src/renderer/components/ImageView.tsx +++ b/gui/src/renderer/components/ImageView.tsx @@ -55,7 +55,7 @@ export default function ImageView(props: IImageViewProps) { } else { return ( <Wrapper onClick={props.onClick} className={props.className}> - <img src={url} width={props.width} height={props.height} /> + <img src={url} width={props.width} height={props.height} aria-hidden={true} /> </Wrapper> ); } diff --git a/gui/src/renderer/components/Launch.tsx b/gui/src/renderer/components/Launch.tsx index 9cb7a23d44..fec3ab68ba 100644 --- a/gui/src/renderer/components/Launch.tsx +++ b/gui/src/renderer/components/Launch.tsx @@ -14,7 +14,7 @@ const StyledContainer = styled(Container)({ marginTop: '-150px', }); -const Title = styled.span({ +const Title = styled.h1({ fontFamily: 'DINPro', fontSize: '24px', fontWeight: 900, diff --git a/gui/src/renderer/components/NavigationBar.tsx b/gui/src/renderer/components/NavigationBar.tsx index 7d6e5a0714..28b6178397 100644 --- a/gui/src/renderer/components/NavigationBar.tsx +++ b/gui/src/renderer/components/NavigationBar.tsx @@ -1,10 +1,12 @@ import React, { useCallback, useContext, useLayoutEffect, useRef, useState } from 'react'; import { colors } from '../../config.json'; +import { messages } from '../../shared/gettext'; import CustomScrollbars, { IScrollEvent } from './CustomScrollbars'; import { StyledBackBarItemButton, StyledBackBarItemIcon, StyledBackBarItemLabel, + StyledCloseBarItemButton, StyledCloseBarItemIcon, StyledNavigationBar, StyledNavigationBarSeparator, @@ -213,11 +215,17 @@ export const TitleBarItem = React.memo(function TitleBarItemT(props: ITitleBarIt return ( <StyledTitleBarItemContainer ref={titleContainerRef}> - <StyledTitleBarItemLabel titleAdjustment={titleAdjustment} visible={visible}> + <StyledTitleBarItemLabel + titleAdjustment={titleAdjustment} + visible={visible} + aria-hidden={!visible}> {props.children} </StyledTitleBarItemLabel> - <StyledTitleBarItemMeasuringLabel titleAdjustment={0} ref={measuringTitleRef}> + <StyledTitleBarItemMeasuringLabel + titleAdjustment={0} + ref={measuringTitleRef} + aria-hidden={true}> {props.children} </StyledTitleBarItemMeasuringLabel> </StyledTitleBarItemContainer> @@ -233,14 +241,15 @@ export function CloseBarItem(props: ICloseBarItemProps) { // title bar. const iconName = process.platform === 'linux' ? 'icon-close-down' : 'icon-close'; return ( - <StyledCloseBarItemIcon - height={24} - width={24} - source={iconName} - onClick={props.action} - tintColor={colors.white60} - tintHoverColor={colors.white80} - /> + <StyledCloseBarItemButton aria-label={messages.gettext('Close')} onClick={props.action}> + <StyledCloseBarItemIcon + height={24} + width={24} + source={iconName} + tintColor={colors.white60} + tintHoverColor={colors.white80} + /> + </StyledCloseBarItemButton> ); } diff --git a/gui/src/renderer/components/NavigationBarStyles.tsx b/gui/src/renderer/components/NavigationBarStyles.tsx index 2f785f14e4..c141f4cfed 100644 --- a/gui/src/renderer/components/NavigationBarStyles.tsx +++ b/gui/src/renderer/components/NavigationBarStyles.tsx @@ -17,7 +17,7 @@ export const StyledNavigationItems = styled.div({ flexDirection: 'row', }); -export const StyledNavigationBar = styled.div({ +export const StyledNavigationBar = styled.nav({ flex: 0, padding: '12px', paddingTop: process.platform === 'darwin' ? '24px' : '12px', @@ -65,6 +65,14 @@ export const StyledTitleBarItemMeasuringLabel = styled(StyledTitleBarItemLabel)( opacity: 0, }); +export const StyledCloseBarItemButton = styled.button({ + borderWidth: 0, + padding: 0, + margin: 0, + cursor: 'default', + backgroundColor: 'transparent', +}); + export const StyledCloseBarItemIcon = styled(ImageView)({ flex: 0, }); diff --git a/gui/src/renderer/components/NotificationArea.tsx b/gui/src/renderer/components/NotificationArea.tsx index 8cbee0df0f..9c5d8f13f6 100644 --- a/gui/src/renderer/components/NotificationArea.tsx +++ b/gui/src/renderer/components/NotificationArea.tsx @@ -66,7 +66,7 @@ export default function NotificationArea(props: IProps) { return ( <NotificationBanner className={props.className} visible> <NotificationIndicator type={notification.indicator} /> - <NotificationContent> + <NotificationContent role="alert" aria-live="assertive"> <NotificationTitle>{notification.title}</NotificationTitle> <NotificationSubtitle>{notification.subtitle}</NotificationSubtitle> </NotificationContent> @@ -80,7 +80,7 @@ export default function NotificationArea(props: IProps) { } } - return <NotificationBanner className={props.className} visible={false} />; + return <NotificationBanner className={props.className} visible={false} aria-hidden={true} />; } interface INotificationActionWrapperProps { diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx index 5a9948b8bd..235ab6de2e 100644 --- a/gui/src/renderer/components/NotificationBanner.tsx +++ b/gui/src/renderer/components/NotificationBanner.tsx @@ -1,10 +1,13 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import { colors } from '../../config.json'; +import { messages } from '../../shared/gettext'; import { InAppNotificationIndicatorType } from '../../shared/notifications/notification'; import { BlockingButton } from './AppButton'; import ImageView from './ImageView'; +const NOTIFICATION_AREA_ID = 'notification-area'; + export const NotificationTitle = styled.span({ fontFamily: 'Open Sans', fontSize: '13px', @@ -52,7 +55,9 @@ interface INotifcationOpenLinkActionProps { export function NotificationOpenLinkAction(props: INotifcationOpenLinkActionProps) { return ( <BlockingButton onClick={props.onClick}> - <NotificationOpenLinkActionButton> + <NotificationOpenLinkActionButton + aria-describedby={NOTIFICATION_AREA_ID} + aria-label={messages.gettext('Open URL')}> <NotificationOpenLinkActionIcon height={12} width={12} @@ -64,7 +69,7 @@ export function NotificationOpenLinkAction(props: INotifcationOpenLinkActionProp ); } -export const NotificationContent = styled.div({ +export const NotificationContent = styled.div.attrs({ id: NOTIFICATION_AREA_ID })({ display: 'flex', flexDirection: 'column', flex: 1, @@ -125,7 +130,7 @@ const Collapsible = styled.div({}, (props: ICollapsibleProps) => { }; }); -const Content = styled.div({ +const Content = styled.section({ display: 'flex', flexDirection: 'row', padding: '8px 12px 8px 16px', diff --git a/gui/src/renderer/components/SecuredLabel.tsx b/gui/src/renderer/components/SecuredLabel.tsx index 7f68b100ae..36cee2db18 100644 --- a/gui/src/renderer/components/SecuredLabel.tsx +++ b/gui/src/renderer/components/SecuredLabel.tsx @@ -29,7 +29,11 @@ interface ISecuredLabelProps { } export default function SecuredLabel(props: ISecuredLabelProps) { - return <StyledSecuredLabel {...props}>{getLabelText(props.displayStyle)}</StyledSecuredLabel>; + return ( + <StyledSecuredLabel {...props} role="alert" aria-live="polite"> + {getLabelText(props.displayStyle)} + </StyledSecuredLabel> + ); } function getLabelText(displayStyle: SecuredDisplayStyle) { diff --git a/gui/src/renderer/components/SettingsHeader.tsx b/gui/src/renderer/components/SettingsHeader.tsx index 808b6f80c7..c0223461e0 100644 --- a/gui/src/renderer/components/SettingsHeader.tsx +++ b/gui/src/renderer/components/SettingsHeader.tsx @@ -13,7 +13,7 @@ export const ContentWrapper = styled.div({ }, }); -export const HeaderTitle = styled.span(bigText); +export const HeaderTitle = styled.h1(bigText); export const HeaderSubTitle = styled.span(smallText); interface ISettingsHeaderProps { diff --git a/gui/src/renderer/components/Switch.tsx b/gui/src/renderer/components/Switch.tsx index ff56843e79..0578064e71 100644 --- a/gui/src/renderer/components/Switch.tsx +++ b/gui/src/renderer/components/Switch.tsx @@ -80,6 +80,8 @@ export default class Switch extends React.Component<IProps, IState> { public render() { return ( <SwitchContainer + role="checkbox" + aria-checked={this.state.isOn} ref={this.containerRef} onClick={this.handleClick} disabled={this.props.disabled ?? false} diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx index a36e5b9486..e5f674d7c4 100644 --- a/gui/src/renderer/components/TunnelControl.tsx +++ b/gui/src/renderer/components/TunnelControl.tsx @@ -114,7 +114,10 @@ export default class TunnelControl extends React.Component<ITunnelControlProps> ); const Reconnect = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => ( - <AppButton.RedTransparentButton onClick={this.props.onReconnect} {...props}> + <AppButton.RedTransparentButton + onClick={this.props.onReconnect} + aria-label={messages.gettext('Reconnect')} + {...props}> <ImageView height={22} width={22} source="icon-reload" tintColor="white" /> </AppButton.RedTransparentButton> ); |
