diff options
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/components/SelectLocation.tsx | 115 | ||||
| -rw-r--r-- | gui/src/renderer/components/SelectLocationStyles.tsx | 12 | ||||
| -rw-r--r-- | gui/src/renderer/components/SettingsHeader.tsx | 6 |
3 files changed, 78 insertions, 55 deletions
diff --git a/gui/src/renderer/components/SelectLocation.tsx b/gui/src/renderer/components/SelectLocation.tsx index f7a694917f..a125cecfe1 100644 --- a/gui/src/renderer/components/SelectLocation.tsx +++ b/gui/src/renderer/components/SelectLocation.tsx @@ -55,6 +55,7 @@ interface IProps { interface IState { showFilterMenu: boolean; + headingHeight: number; } interface ISelectLocationSnapshot { @@ -63,7 +64,8 @@ interface ISelectLocationSnapshot { } export default class SelectLocation extends React.Component<IProps, IState> { - public state = { showFilterMenu: false }; + // The default headingHeight value is based on a one-line heading. + public state = { showFilterMenu: false, headingHeight: 50 }; private scrollView = React.createRef<CustomScrollbars>(); private spacePreAllocationViewRef = React.createRef<SpacePreAllocationView>(); @@ -76,9 +78,14 @@ export default class SelectLocation extends React.Component<IProps, IState> { private snapshotByScope: { [index: number]: ISelectLocationSnapshot } = {}; private filterButtonRef = React.createRef<HTMLDivElement>(); + private headingRef = React.createRef<HTMLHeadingElement>(); public componentDidMount() { this.scrollToSelectedCell(); + this.setState((state) => ({ + // 10 px is the margin ontop of the heading. + headingHeight: (this.headingRef.current?.offsetHeight ?? state.headingHeight) + 10, + })); } public componentDidUpdate( @@ -117,10 +124,15 @@ export default class SelectLocation extends React.Component<IProps, IState> { <Layout onClick={this.onClickAnywhere}> <StyledContainer> <NavigationContainer> - <NavigationBar alwaysDisplayBarTitle={true}> + <NavigationBar> <NavigationItems> <CloseBarItem action={this.props.onClose} /> - <TitleBarItem /> + <TitleBarItem> + { + // TRANSLATORS: Title label in navigation bar + messages.pgettext('select-location-nav', 'Select location') + } + </TitleBarItem> <StyledFilterContainer ref={this.filterButtonRef}> <StyledFilterIconButton @@ -143,55 +155,60 @@ export default class SelectLocation extends React.Component<IProps, IState> { )} </StyledFilterContainer> </NavigationItems> - <StyledNavigationBarAttachment> - <StyledSettingsHeader> - <HeaderTitle> - { - // TRANSLATORS: Heading in select location view - messages.pgettext('select-location-nav', 'Select location') - } - </HeaderTitle> - </StyledSettingsHeader> - - {this.props.providers.length > 0 && ( - <StyledProviderCountRow> - {messages.pgettext('select-location-view', 'Filtered:')} - <StyledProvidersCount> - {sprintf( - messages.pgettext( - 'select-location-view', - 'Providers: %(numberOfProviders)d', - ), - { - numberOfProviders: this.props.providers.length, - }, - )} - <StyledClearProvidersButton - aria-label={messages.gettext('Clear')} - onClick={this.props.onClearProviders}> - <ImageView - height={16} - width={16} - source="icon-close" - tintColor={colors.white60} - tintHoverColor={colors.white80} - /> - </StyledClearProvidersButton> - </StyledProvidersCount> - </StyledProviderCountRow> - )} - {this.props.allowBridgeSelection && ( - <StyledScopeBar - defaultSelectedIndex={this.props.locationScope} - onChange={this.props.onChangeLocationScope}> - <ScopeBarItem>{messages.pgettext('select-location-nav', 'Entry')}</ScopeBarItem> - <ScopeBarItem>{messages.pgettext('select-location-nav', 'Exit')}</ScopeBarItem> - </StyledScopeBar> - )} - </StyledNavigationBarAttachment> </NavigationBar> <NavigationScrollbars ref={this.scrollView}> <SpacePreAllocationView ref={this.spacePreAllocationViewRef}> + <StyledNavigationBarAttachment top={-this.state.headingHeight}> + <StyledSettingsHeader> + <HeaderTitle ref={this.headingRef}> + { + // TRANSLATORS: Heading in select location view + messages.pgettext('select-location-view', 'Select location') + } + </HeaderTitle> + </StyledSettingsHeader> + + {this.props.providers.length > 0 && ( + <StyledProviderCountRow> + {messages.pgettext('select-location-view', 'Filtered:')} + <StyledProvidersCount> + {sprintf( + messages.pgettext( + 'select-location-view', + 'Providers: %(numberOfProviders)d', + ), + { + numberOfProviders: this.props.providers.length, + }, + )} + <StyledClearProvidersButton + aria-label={messages.gettext('Clear')} + onClick={this.props.onClearProviders}> + <ImageView + height={16} + width={16} + source="icon-close" + tintColor={colors.white60} + tintHoverColor={colors.white80} + /> + </StyledClearProvidersButton> + </StyledProvidersCount> + </StyledProviderCountRow> + )} + {this.props.allowBridgeSelection && ( + <StyledScopeBar + defaultSelectedIndex={this.props.locationScope} + onChange={this.props.onChangeLocationScope}> + <ScopeBarItem> + {messages.pgettext('select-location-nav', 'Entry')} + </ScopeBarItem> + <ScopeBarItem> + {messages.pgettext('select-location-nav', 'Exit')} + </ScopeBarItem> + </StyledScopeBar> + )} + </StyledNavigationBarAttachment> + <StyledContent> {this.props.locationScope === LocationScope.relay ? ( <ExitLocations diff --git a/gui/src/renderer/components/SelectLocationStyles.tsx b/gui/src/renderer/components/SelectLocationStyles.tsx index 0da4c40184..308421a46f 100644 --- a/gui/src/renderer/components/SelectLocationStyles.tsx +++ b/gui/src/renderer/components/SelectLocationStyles.tsx @@ -20,10 +20,13 @@ export const StyledContent = styled.div({ overflow: 'visible', }); -export const StyledNavigationBarAttachment = styled.div({ - marginTop: '8px', - paddingHorizontal: '4px', -}); +export const StyledNavigationBarAttachment = styled.div({}, (props: { top: number }) => ({ + position: 'sticky', + top: `${props.top}px`, + padding: '8px 18px 8px 16px', + backgroundColor: colors.darkBlue, + zIndex: 1, +})); export const StyledFilterContainer = styled.div({ position: 'relative', @@ -45,6 +48,7 @@ export const StyledFilterMenu = styled.div({ borderRadius: '4px', backgroundColor: colors.darkBlue, overflow: 'hidden', + zIndex: 2, }); export const StyledFilterByProviderButton = styled.button({ diff --git a/gui/src/renderer/components/SettingsHeader.tsx b/gui/src/renderer/components/SettingsHeader.tsx index ea1d2ab634..64bcfec595 100644 --- a/gui/src/renderer/components/SettingsHeader.tsx +++ b/gui/src/renderer/components/SettingsHeader.tsx @@ -21,12 +21,14 @@ interface ISettingsHeaderProps { className?: string; } -export default function SettingsHeader(props: ISettingsHeaderProps) { +function SettingsHeader(props: ISettingsHeaderProps, forwardRef: React.Ref<HTMLDivElement>) { return ( - <Container className={props.className}> + <Container ref={forwardRef} className={props.className}> {React.Children.map(props.children, (child) => { return React.isValidElement(child) ? <ContentWrapper>{child}</ContentWrapper> : undefined; })} </Container> ); } + +export default React.forwardRef(SettingsHeader); |
