diff --git a/src/components/controls/panelChevron.tsx b/src/components/controls/panelChevron.tsx
new file mode 100644
index 000000000..520a99fce
--- /dev/null
+++ b/src/components/controls/panelChevron.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+import styled from 'styled-components';
+import { FaChevronRight, FaChevronDown } from "react-icons/fa";
+
+const Container = styled.span`
+ padding-right: 6px;
+ color: ${(props) => props.theme.color};
+`
+
+type Props = {
+ show: boolean
+}
+
+/**
+ * An interactive chevron to show/hide a panel's options.
+ */
+export const PanelChevron = ({ show }: Props) => {
+ const icon = show ? :
+
+ return (
+
+ {icon}
+
+ )
+}
diff --git a/src/components/controls/panelHeader.tsx b/src/components/controls/panelHeader.tsx
index fea38adb3..cd69ba568 100644
--- a/src/components/controls/panelHeader.tsx
+++ b/src/components/controls/panelHeader.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { HeaderContainer } from "./styles";
import PanelToggle from "./panelToggle";
import { AnnotatedTitle } from "./annotatedTitle";
+import { PanelChevron } from "./panelChevron";
type Props = {
/** Panel identifier used internally. */
@@ -16,6 +17,15 @@ type Props = {
/** Indicates panel visibility. */
panelIsVisible: boolean
+ /** Indicates whether there are options for the panel. */
+ hasOptions: boolean
+
+ /** Indicates options visibility. */
+ optionsAreVisible: boolean
+
+ /** Update options visibility. */
+ setOptionsAreVisible: React.Dispatch>
+
/** Indicates mobile display. */
mobile: boolean
}
@@ -23,13 +33,26 @@ type Props = {
/**
* A header used by all panel controls, containing an interactive title.
*/
-export const PanelHeader = ({ panel, title, tooltip, panelIsVisible, mobile }: Props) => {
+export const PanelHeader = ({ panel, title, tooltip, panelIsVisible, hasOptions, optionsAreVisible, setOptionsAreVisible, mobile }: Props) => {
+
+ let titleContainerProps = {}
+
+ if (hasOptions) {
+ titleContainerProps = {
+ role: "button",
+ onClick: () => setOptionsAreVisible(!optionsAreVisible),
+ }
+ }
+
return (
-
+
+ {hasOptions && }
+
+
diff --git a/src/components/controls/panelSection.tsx b/src/components/controls/panelSection.tsx
index b4c5a30a8..c66f5dc9f 100644
--- a/src/components/controls/panelSection.tsx
+++ b/src/components/controls/panelSection.tsx
@@ -30,6 +30,14 @@ export const PanelSection = ({ panel, title, tooltip, options=undefined, mobile
const panelIsVisible = panelsToDisplay.includes(panel)
+ // Initially, panel visibility determines options visibility.
+ const [optionsAreVisible, setOptionsAreVisible] = React.useState(panelIsVisible);
+
+ // Subsequent panel visibility updates also determines options visibility.
+ React.useEffect(() => {
+ setOptionsAreVisible(panelIsVisible)
+ }, [panelIsVisible])
+
return (
- {panelIsVisible && options}
+ {optionsAreVisible && options}
);
};