diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-11-07 11:06:02 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-11-07 11:06:02 +0100 |
| commit | 3b8e28cd91aaa59e236a4c4875d9cb43e823042f (patch) | |
| tree | fd70a5d3702b45466b917446c037328e1e68f1c4 /gui/src/renderer/components/cell | |
| parent | 2968800c8da2877d7270bef512e543c4dee84223 (diff) | |
| parent | d20b3826f313c91da881c31c1fd3eb17a81ff044 (diff) | |
| download | mullvadvpn-3b8e28cd91aaa59e236a4c4875d9cb43e823042f.tar.xz mullvadvpn-3b8e28cd91aaa59e236a4c4875d9cb43e823042f.zip | |
Merge branch 'make-dns-blockers-collapsible'
Diffstat (limited to 'gui/src/renderer/components/cell')
| -rw-r--r-- | gui/src/renderer/components/cell/Section.tsx | 64 | ||||
| -rw-r--r-- | gui/src/renderer/components/cell/Selector.tsx | 56 |
2 files changed, 88 insertions, 32 deletions
diff --git a/gui/src/renderer/components/cell/Section.tsx b/gui/src/renderer/components/cell/Section.tsx index 38df17ebdb..8ba5975476 100644 --- a/gui/src/renderer/components/cell/Section.tsx +++ b/gui/src/renderer/components/cell/Section.tsx @@ -1,8 +1,14 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; import { colors } from '../../../config.json'; +import { useAppContext } from '../../context'; +import { useHistory } from '../../lib/history'; +import { useBoolean } from '../../lib/utilityHooks'; +import Accordion from '../Accordion'; +import ChevronButton from '../ChevronButton'; import { buttonText, openSans, sourceSansPro } from '../common-styles'; +import { Container } from './Container'; import { Row } from './Row'; const StyledSection = styled.div({ @@ -25,11 +31,61 @@ export const SectionTitle = styled(Row)(buttonText, (props: SectionTitleProps) = export const CellSectionContext = React.createContext<boolean>(false); -export function Section(props: React.HTMLAttributes<HTMLDivElement>) { - const { children, ...otherProps } = props; +interface SectionProps extends React.HTMLAttributes<HTMLDivElement> { + sectionTitle?: React.ReactElement; +} + +export function Section(props: SectionProps) { + const { children, sectionTitle, ...otherProps } = props; return ( <StyledSection {...otherProps}> - <CellSectionContext.Provider value={true}>{children}</CellSectionContext.Provider> + <CellSectionContext.Provider value={true}> + {sectionTitle && <StyledTitleContainer>{sectionTitle}</StyledTitleContainer>} + {children} + </CellSectionContext.Provider> </StyledSection> ); } + +const StyledChevronButton = styled(ChevronButton)({ + padding: 0, + marginRight: '16px', +}); + +const StyledTitleContainer = styled(Container)({ + display: 'flex', + padding: 0, +}); + +interface ExpandableSectionProps extends SectionProps { + expandableId: string; + expandedInitially?: boolean; +} + +export function ExpandableSection(props: ExpandableSectionProps) { + const { expandableId, expandedInitially, sectionTitle, ...otherProps } = props; + + const history = useHistory(); + const { setNavigationHistory } = useAppContext(); + const expandedValue = + history.location.state.expandedSections[props.expandableId] ?? !!expandedInitially; + const [expanded, , , toggleExpanded] = useBoolean(expandedValue); + + useEffect(() => { + history.location.state.expandedSections[props.expandableId] = expanded; + setNavigationHistory(history.asObject); + }, [expanded]); + + const title = ( + <> + {sectionTitle} + <StyledChevronButton up={expanded} onClick={toggleExpanded} /> + </> + ); + + return ( + <Section className={props.className} sectionTitle={title} {...otherProps}> + <Accordion expanded={expanded}>{props.children}</Accordion> + </Section> + ); +} diff --git a/gui/src/renderer/components/cell/Selector.tsx b/gui/src/renderer/components/cell/Selector.tsx index cb0d6344b6..ed49444da1 100644 --- a/gui/src/renderer/components/cell/Selector.tsx +++ b/gui/src/renderer/components/cell/Selector.tsx @@ -3,28 +3,15 @@ import styled from 'styled-components'; import { colors } from '../../../config.json'; import { messages } from '../../../shared/gettext'; -import { useBoolean } from '../../lib/utilityHooks'; -import Accordion from '../Accordion'; import { AriaDetails, AriaInput, AriaLabel } from '../AriaGroup'; -import ChevronButton from '../ChevronButton'; import { normalText } from '../common-styles'; import InfoButton from '../InfoButton'; import * as Cell from '.'; -const StyledTitle = styled(Cell.Container)({ - display: 'flex', - padding: 0, -}); - const StyledTitleLabel = styled(Cell.SectionTitle)({ flex: 1, }); -const StyledChevronButton = styled(ChevronButton)({ - padding: 0, - marginRight: '16px', -}); - export interface SelectorItem<T> { label: string; value: T; @@ -39,7 +26,7 @@ interface CommonSelectorProps<T, U> { selectedCellRef?: React.Ref<HTMLElement>; className?: string; details?: React.ReactElement; - expandable?: boolean; + expandable?: { expandable: boolean; id: string }; disabled?: boolean; thinTitle?: boolean; automaticLabel?: string; @@ -52,8 +39,6 @@ interface SelectorProps<T, U> extends CommonSelectorProps<T, U> { } export default function Selector<T, U>(props: SelectorProps<T, U>) { - const [expanded, , , toggleExpanded] = useBoolean(!props.expandable); - const items = props.items.map((item) => { const selected = props.value === item.value; const ref = selected ? (props.selectedCellRef as React.Ref<HTMLButtonElement>) : undefined; @@ -88,8 +73,8 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) { ); } - const title = props.title && ( - <StyledTitle> + const title = props.title ? ( + <> <AriaLabel> <StyledTitleLabel as="label" disabled={props.disabled} thin={props.thinTitle}> {props.title} @@ -100,8 +85,9 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) { <InfoButton>{props.details}</InfoButton> </AriaDetails> )} - {props.expandable && <StyledChevronButton up={expanded} onClick={toggleExpanded} />} - </StyledTitle> + </> + ) : ( + <></> ); // Add potential additional items to the list. Used for custom entry. @@ -112,14 +98,28 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) { </Cell.Group> ); - return ( - <AriaInput> - <Cell.Section role="listbox" className={props.className}> - {title} - {props.expandable ? <Accordion expanded={expanded}>{children}</Accordion> : children} - </Cell.Section> - </AriaInput> - ); + if (props.expandable?.expandable) { + return ( + <AriaInput> + <Cell.ExpandableSection + role="listbox" + expandedInitially={false} + className={props.className} + sectionTitle={title} + expandableId={props.expandable.id}> + {children} + </Cell.ExpandableSection> + </AriaInput> + ); + } else { + return ( + <AriaInput> + <Cell.Section role="listbox" className={props.className} sectionTitle={title}> + {children} + </Cell.Section> + </AriaInput> + ); + } } const StyledCellIcon = styled(Cell.Icon)((props: { visible: boolean }) => ({ |
