summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer/components/cell
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-11-07 11:06:02 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-11-07 11:06:02 +0100
commit3b8e28cd91aaa59e236a4c4875d9cb43e823042f (patch)
treefd70a5d3702b45466b917446c037328e1e68f1c4 /gui/src/renderer/components/cell
parent2968800c8da2877d7270bef512e543c4dee84223 (diff)
parentd20b3826f313c91da881c31c1fd3eb17a81ff044 (diff)
downloadmullvadvpn-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.tsx64
-rw-r--r--gui/src/renderer/components/cell/Selector.tsx56
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 }) => ({