From 149ba232aeb28c6163ae0a52b2bcd249548adc45 Mon Sep 17 00:00:00 2001
From: ev <4164774+ev-sc@users.noreply.github.com>
Date: Sat, 7 Dec 2024 13:54:24 +0000
Subject: [PATCH] Implement display popover
---
nextjs/package-lock.json | 10 +++++
nextjs/package.json | 1 +
.../[id]/(components)/ConstituenciesPanel.tsx | 10 ++++-
.../[id]/(components)/ReportConfiguration.tsx | 2 -
.../(components)/ReportDisplaySettings.tsx | 42 +++++++++++++++++++
.../[id]/(components)/ReportNavbar.tsx | 4 +-
.../[id]/(components)/ReportSidebarLeft.tsx | 8 +++-
nextjs/src/app/reports/[id]/page.tsx | 3 +-
.../src/app/reports/[id]/useSelectBoundary.ts | 28 +++++++++----
nextjs/src/components/ui/button.tsx | 3 +-
10 files changed, 94 insertions(+), 17 deletions(-)
create mode 100644 nextjs/src/app/reports/[id]/(components)/ReportDisplaySettings.tsx
diff --git a/nextjs/package-lock.json b/nextjs/package-lock.json
index 4f438decf..a1a1e99d1 100644
--- a/nextjs/package-lock.json
+++ b/nextjs/package-lock.json
@@ -22,6 +22,7 @@
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.0.6",
+ "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-popover": "^1.0.7",
@@ -4330,6 +4331,15 @@
}
}
},
+ "node_modules/@radix-ui/react-icons": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz",
+ "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
"node_modules/@radix-ui/react-id": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
diff --git a/nextjs/package.json b/nextjs/package.json
index fca80a2db..5161b3b04 100644
--- a/nextjs/package.json
+++ b/nextjs/package.json
@@ -38,6 +38,7 @@
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.0.6",
+ "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-popover": "^1.0.7",
diff --git a/nextjs/src/app/reports/[id]/(components)/ConstituenciesPanel.tsx b/nextjs/src/app/reports/[id]/(components)/ConstituenciesPanel.tsx
index 8e1627dfa..dbbfbf07b 100644
--- a/nextjs/src/app/reports/[id]/(components)/ConstituenciesPanel.tsx
+++ b/nextjs/src/app/reports/[id]/(components)/ConstituenciesPanel.tsx
@@ -1,10 +1,13 @@
-import { useAtom } from 'jotai'
+import { useAtom, useAtomValue } from 'jotai'
import { useEffect, useRef } from 'react'
import { ConstituencyElectionDeepDive } from '@/app/reports/[id]/(components)/reportsConstituencyItem'
import { Card } from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
-import { constituencyPanelTabAtom } from '@/lib/map/state'
+import {
+ constituencyPanelTabAtom,
+ isConstituencyPanelOpenAtom,
+} from '@/lib/map/state'
import { selectedBoundaryAtom } from '../useSelectBoundary'
import { useReport } from './ReportProvider'
@@ -13,6 +16,8 @@ import { TopConstituencies } from './TopConstituencies'
export function ConstituenciesPanel() {
const [selectedBoundary, setSelectedConstituency] =
useAtom(selectedBoundaryAtom)
+
+ const isConstituencyPanelOpen = useAtomValue(isConstituencyPanelOpenAtom)
const [tab, setTab] = useAtom(constituencyPanelTabAtom)
const {
report: {
@@ -32,6 +37,7 @@ export function ConstituenciesPanel() {
}, [selectedBoundary, setTab])
if (!analyticalAreaType) return null
+ if (!isConstituencyPanelOpen) return null
return (
diff --git a/nextjs/src/app/reports/[id]/(components)/ReportConfiguration.tsx b/nextjs/src/app/reports/[id]/(components)/ReportConfiguration.tsx
index a15fa4de3..8415ffebd 100644
--- a/nextjs/src/app/reports/[id]/(components)/ReportConfiguration.tsx
+++ b/nextjs/src/app/reports/[id]/(components)/ReportConfiguration.tsx
@@ -16,7 +16,6 @@ import {
import { ChevronsUpDown } from 'lucide-react'
import { getPoliticalTilesetsByCountry } from '../politicalTilesets'
import { useReport } from './ReportProvider'
-import ReportConfigLegacyControls from './_ReportConfigLegacyControls'
const ReportConfiguration: React.FC = () => {
const { report, updateReport } = useReport()
@@ -74,7 +73,6 @@ const ReportConfiguration: React.FC = () => {
-
)
diff --git a/nextjs/src/app/reports/[id]/(components)/ReportDisplaySettings.tsx b/nextjs/src/app/reports/[id]/(components)/ReportDisplaySettings.tsx
new file mode 100644
index 000000000..67a8aff48
--- /dev/null
+++ b/nextjs/src/app/reports/[id]/(components)/ReportDisplaySettings.tsx
@@ -0,0 +1,42 @@
+import { Button } from '@/components/ui/button'
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from '@/components/ui/popover'
+import { isConstituencyPanelOpenAtom } from '@/lib/map'
+import { MixerHorizontalIcon } from '@radix-ui/react-icons'
+import { useAtomValue } from 'jotai'
+import React from 'react'
+import { NAVBAR_HEIGHT } from './ReportNavbar'
+import ReportConfigLegacyControls from './_ReportConfigLegacyControls'
+
+const ReportDisplaySettings: React.FC = () => {
+ const isConstituencyPanelOpen = useAtomValue(isConstituencyPanelOpenAtom)
+
+ return (
+
+
+
+
+
+ Display
+
+
+
+
+
+
+
+ )
+}
+
+export default ReportDisplaySettings
diff --git a/nextjs/src/app/reports/[id]/(components)/ReportNavbar.tsx b/nextjs/src/app/reports/[id]/(components)/ReportNavbar.tsx
index 339f9a1dd..fbd0b8eb3 100644
--- a/nextjs/src/app/reports/[id]/(components)/ReportNavbar.tsx
+++ b/nextjs/src/app/reports/[id]/(components)/ReportNavbar.tsx
@@ -7,6 +7,7 @@ import { MappedIcon } from '../../../../components/icons/MappedIcon'
// You can set the title & href of the top left icon link based on route & context
export const navbarTitleAtom = atom('')
+export const NAVBAR_HEIGHT = 48
export default function ReportNavbar() {
const title = useAtomValue(navbarTitleAtom)
@@ -14,7 +15,8 @@ export default function ReportNavbar() {
return (
diff --git a/nextjs/src/app/reports/[id]/(components)/ReportSidebarLeft.tsx b/nextjs/src/app/reports/[id]/(components)/ReportSidebarLeft.tsx
index 2ad11b217..7707ccc0a 100644
--- a/nextjs/src/app/reports/[id]/(components)/ReportSidebarLeft.tsx
+++ b/nextjs/src/app/reports/[id]/(components)/ReportSidebarLeft.tsx
@@ -3,6 +3,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import ReportConfiguration from './ReportConfiguration'
import { ReportDataSources } from './ReportDataSources'
+import { NAVBAR_HEIGHT } from './ReportNavbar'
const classes = {
tabsTrigger:
@@ -11,7 +12,12 @@ const classes = {
export function ReportSidebarLeft() {
return (
-
+
@@ -63,6 +63,7 @@ export default function Page({ params: { id } }: { params: Params }) {
>
+
diff --git a/nextjs/src/app/reports/[id]/useSelectBoundary.ts b/nextjs/src/app/reports/[id]/useSelectBoundary.ts
index 3b966ea5b..a853e6172 100644
--- a/nextjs/src/app/reports/[id]/useSelectBoundary.ts
+++ b/nextjs/src/app/reports/[id]/useSelectBoundary.ts
@@ -1,6 +1,6 @@
'use client'
-import { useLoadedMap } from '@/lib/map'
-import { atom, useAtom } from 'jotai'
+import { isConstituencyPanelOpenAtom, useLoadedMap } from '@/lib/map'
+import { atom, useAtom, useSetAtom } from 'jotai'
import { useEffect } from 'react'
import { Tileset } from './types'
@@ -9,6 +9,7 @@ export const selectedBoundaryAtom = atom(null)
const useSelectBoundary = (tileset?: Tileset | null) => {
const { loadedMap } = useLoadedMap()
const [selectedBoundary, setSelectedBoundary] = useAtom(selectedBoundaryAtom)
+ const setIsConstituencyPanelOpen = useSetAtom(isConstituencyPanelOpenAtom)
useEffect(
function selectConstituency() {
@@ -30,12 +31,15 @@ const useSelectBoundary = (tileset?: Tileset | null) => {
if (feature.source === tileset.mapboxSourceId) {
const id = feature.properties?.[tileset.promoteId]
if (id) {
- console.log('Selected constituency:', id)
- setSelectedBoundary(id)
-
- // setSelectedConstituency(id)
- // setIsConstituencyPanelOpen(true)
- // setTab('selected')
+ // If already selected boundary, deselect it
+ if (selectedBoundary === id) {
+ setSelectedBoundary(null)
+ setIsConstituencyPanelOpen(false)
+ return
+ } else {
+ setSelectedBoundary(id)
+ setIsConstituencyPanelOpen(true)
+ }
}
}
}
@@ -44,7 +48,13 @@ const useSelectBoundary = (tileset?: Tileset | null) => {
}
})
},
- [loadedMap, tileset]
+ [
+ loadedMap,
+ tileset,
+ selectedBoundary,
+ setSelectedBoundary,
+ setIsConstituencyPanelOpen,
+ ]
)
}
diff --git a/nextjs/src/components/ui/button.tsx b/nextjs/src/components/ui/button.tsx
index f3bb3a533..1dc1b6e33 100644
--- a/nextjs/src/components/ui/button.tsx
+++ b/nextjs/src/components/ui/button.tsx
@@ -5,7 +5,7 @@ import * as React from 'react'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
- 'font-IBMPlexCondensed inline-flex items-center justify-center whitespace-nowrap rounded-sm font-medium ring-offset-meepGray-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
+ 'font-IBMPlexCondensed inline-flex gap-2 flex-row items-center justify-center whitespace-nowrap rounded-sm font-medium ring-offset-meepGray-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
@@ -21,6 +21,7 @@ const buttonVariants = cva(
link: 'text-primary underline-offset-4 hover:underline',
reverse:
'bg-white hover:bg-slate-100 !text-gray-900 hover:!text-gray-900',
+ muted: 'bg-muted text-meepGray-400 hover:text-meepGray-200 opacity-100',
},
size: {
default: 'rounded text-label h-10 px-4 py-2',