From 3413cffdfe76ca7a4ab768e6c1aab34da7e92b2f Mon Sep 17 00:00:00 2001 From: nofurtherinformation Date: Tue, 14 Jan 2025 10:56:22 -0600 Subject: [PATCH] resizable accordion panels --- .../app/components/Toolbar/ColorPicker.tsx | 2 +- app/src/app/components/sidebar/DataPanels.tsx | 112 ++++++++++++------ app/src/app/components/sidebar/Sidebar.tsx | 11 +- 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/app/src/app/components/Toolbar/ColorPicker.tsx b/app/src/app/components/Toolbar/ColorPicker.tsx index d5dff693..ed5753a6 100644 --- a/app/src/app/components/Toolbar/ColorPicker.tsx +++ b/app/src/app/components/Toolbar/ColorPicker.tsx @@ -31,7 +31,7 @@ export const ColorPicker = ({ const mapDocument = useMapStore(state => state.mapDocument); const hotkeyRef = useRef(null); const timeoutRef = useRef | null>(null); - const numDistricts = 20; //mapDocument?.num_districts || 4; + const numDistricts = mapDocument?.num_districts || 4; const handleKeyPressSubmit = () => { if (!hotkeyRef.current) return; diff --git a/app/src/app/components/sidebar/DataPanels.tsx b/app/src/app/components/sidebar/DataPanels.tsx index 88aacd11..4636098b 100644 --- a/app/src/app/components/sidebar/DataPanels.tsx +++ b/app/src/app/components/sidebar/DataPanels.tsx @@ -1,14 +1,15 @@ -import {Box} from '@radix-ui/themes'; +import {Box, IconButton} from '@radix-ui/themes'; import Evaluation from '@components/sidebar/Evaluation'; import PopulationPanel from '@components/sidebar/PopulationPanel'; import React from 'react'; -import classNames from "classnames"; -import * as Accordion from "@radix-ui/react-accordion"; -import { DoubleArrowDownIcon } from "@radix-ui/react-icons"; -import {useMapStore} from '@/app/store/mapStore'; +import classNames from 'classnames'; +import * as Accordion from '@radix-ui/react-accordion'; +import {DoubleArrowDownIcon, DragHandleHorizontalIcon} from '@radix-ui/react-icons'; +import {MapStore, useMapStore} from '@/app/store/mapStore'; +import Draggable from 'react-draggable'; interface DataPanelSpec { - title: string; + title: MapStore['sidebarPanels'][number]; label: string; icon?: React.ReactNode; content?: React.ReactNode; @@ -30,48 +31,91 @@ const defaultPanels: DataPanelSpec[] = [ content: , }, ]; - -const DataPanels: React.FC = ({ - panels = defaultPanels, -}) => { +const ResizableAccordionPanel: React.FC<{panel: DataPanelSpec, open: boolean}> = ({panel, open}) => { + const [height, setHeight] = React.useState(null); + const [hovered, setHovered] = React.useState(false); + const itemRef = React.useRef(null); + return ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + {panel.label} + + {panel.content} + +
+ { + const top = itemRef.current?.getBoundingClientRect().top; + if (top) { + setHeight(e.clientY - top); + } + }} + position={{x: 0, y: 0}} + axis="y" + > + + + + +
+
+ ); +}; +const DataPanels: React.FC = ({panels = defaultPanels}) => { const sidebarPanels = useMapStore(state => state.sidebarPanels); const setSidebarPanels = useMapStore(state => state.setSidebarPanels); return ( - - {panels.map(panel => ( - - - {panel.label} - - - {panel.content} - - + > + {panels.map((panel, i) => ( + ))} ); }; - const AccordionTrigger = React.forwardRef< HTMLButtonElement, React.ComponentPropsWithoutRef ->(({ children, className, ...props }, forwardedRef) => ( +>(({children, className, ...props}, forwardedRef) => ( ->(({ children, className, ...props }, forwardedRef) => ( +>(({children, className, ...props}, forwardedRef) => ( { export default function SidebarComponent() { const document_id = useMapStore(store => store.mapDocument?.document_id); const [width, setWidth] = React.useState(window.innerWidth * 0.25); + const [hovered, setHovered] = React.useState(false); return ( setHovered(true)} + onMouseLeave={() => setHovered(false)} >
+ Districtr @@ -96,7 +103,7 @@ export default function SidebarComponent() { > - +
); }