From 765543920c2208a50eba9b7e28935d751a84b177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Mon, 2 Mar 2026 14:13:52 +0100 Subject: [PATCH] add zustand stores for ephemeral ui state (search queries survive tab switches) Co-Authored-By: Claude Opus 4.6 --- bun.lock | 2 +- package.json | 2 +- .../politicians/components/politician-search.tsx | 4 +++- src/features/politicians/store.ts | 11 +++++++++++ src/features/topics/components/topic-list.tsx | 5 +++-- src/features/topics/store.ts | 11 +++++++++++ 6 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 src/features/politicians/store.ts create mode 100644 src/features/topics/store.ts diff --git a/bun.lock b/bun.lock index 151e459..ce7565c 100644 --- a/bun.lock +++ b/bun.lock @@ -16,7 +16,7 @@ "react-dom": "^19.1.0", "tailwind-merge": "^3.5.0", "zod": "^3.24.3", - "zustand": "^5.0.5", + "zustand": "^5.0.11", }, "devDependencies": { "@biomejs/biome": "^1.9.4", diff --git a/package.json b/package.json index db1f4d6..c098ec8 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "react-dom": "^19.1.0", "tailwind-merge": "^3.5.0", "zod": "^3.24.3", - "zustand": "^5.0.5" + "zustand": "^5.0.11" }, "devDependencies": { "@biomejs/biome": "^1.9.4", diff --git a/src/features/politicians/components/politician-search.tsx b/src/features/politicians/components/politician-search.tsx index 23579f6..dd4f932 100644 --- a/src/features/politicians/components/politician-search.tsx +++ b/src/features/politicians/components/politician-search.tsx @@ -6,6 +6,7 @@ import { Block, Button, Card, List, ListItem, Navbar, Searchbar } from "konsta/r import { useEffect, useMemo, useState } from "react" import { type GeoResult, loadCachedResult } from "../../location/lib/geo" import { getPartyMeta } from "../../location/lib/parties" +import { usePoliticiansUI } from "../store" interface PartyGroup { partyLabel: string @@ -55,7 +56,8 @@ function mandateFunction(m: MandateWithPolitician): string | null { export function PoliticianSearch() { const db = useDb() const [result, setResult] = useState(null) - const [search, setSearch] = useState("") + const search = usePoliticiansUI((s) => s.searchQuery) + const setSearch = usePoliticiansUI((s) => s.setSearchQuery) const { isFollowing, follow, unfollow } = useFollows() useEffect(() => { diff --git a/src/features/politicians/store.ts b/src/features/politicians/store.ts new file mode 100644 index 0000000..b010e79 --- /dev/null +++ b/src/features/politicians/store.ts @@ -0,0 +1,11 @@ +import { create } from "zustand" + +interface PoliticiansUIState { + searchQuery: string + setSearchQuery: (query: string) => void +} + +export const usePoliticiansUI = create((set) => ({ + searchQuery: "", + setSearchQuery: (query) => set({ searchQuery: query }), +})) diff --git a/src/features/topics/components/topic-list.tsx b/src/features/topics/components/topic-list.tsx index 4a26a02..746641d 100644 --- a/src/features/topics/components/topic-list.tsx +++ b/src/features/topics/components/topic-list.tsx @@ -1,12 +1,13 @@ import { useFollows } from "@/shared/hooks/use-follows" import { Button, List, ListItem, Navbar, Preloader, Searchbar } from "konsta/react" -import { useState } from "react" import { useTopics } from "../hooks/use-topics" +import { useTopicsUI } from "../store" export function TopicList() { const { topics, loading, error } = useTopics() const { isFollowing, follow, unfollow } = useFollows() - const [search, setSearch] = useState("") + const search = useTopicsUI((s) => s.searchQuery) + const setSearch = useTopicsUI((s) => s.setSearchQuery) const filtered = topics.filter((t) => t.label.toLowerCase().includes(search.toLowerCase())) diff --git a/src/features/topics/store.ts b/src/features/topics/store.ts new file mode 100644 index 0000000..7807093 --- /dev/null +++ b/src/features/topics/store.ts @@ -0,0 +1,11 @@ +import { create } from "zustand" + +interface TopicsUIState { + searchQuery: string + setSearchQuery: (query: string) => void +} + +export const useTopicsUI = create((set) => ({ + searchQuery: "", + setSearchQuery: (query) => set({ searchQuery: query }), +}))