feat: shared backlog filter popover + sprint header polish (v1.3.3) (#184)
- Move sprint switcher into sprint header, centered between title and actions - Extract BacklogFilterPopover as shared component used by sprint and product backlog - Add sort options (code/priority/status) with single-pill asc/desc toggle - Default sprint backlog status filter to OPEN, remove "alleen niet klaar" button - Persist collapsed state and filter popover open in localStorage - Fix hydration flicker: defer localStorage read to useEffect with prefsLoaded gate for writes - Increase sprint switcher text size for readability Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a9b53dedf0
commit
1f8cbacb0a
9 changed files with 424 additions and 330 deletions
22
lib/use-local-storage-pref.ts
Normal file
22
lib/use-local-storage-pref.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* SSR-safe synchronous read of a localStorage value with a typed parser.
|
||||
*
|
||||
* Use inside `useState(() => readLocalStoragePref(...))` so the first render
|
||||
* already has the persisted value — no useEffect-driven re-render flicker.
|
||||
*
|
||||
* On the server `window` is undefined → returns `fallback`. On the client the
|
||||
* raw value is parsed; if the parser returns `null` the fallback is used.
|
||||
* Hydration mismatches between server-rendered HTML (default) and the
|
||||
* client-rendered tree (persisted) are accepted: React adapts the DOM in the
|
||||
* same hydration pass without a visible flicker for matching values.
|
||||
*/
|
||||
export function readLocalStoragePref<T>(
|
||||
key: string,
|
||||
parse: (raw: string) => T | null,
|
||||
fallback: T,
|
||||
): T {
|
||||
if (typeof window === 'undefined') return fallback
|
||||
const raw = window.localStorage.getItem(key)
|
||||
if (raw === null) return fallback
|
||||
return parse(raw) ?? fallback
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue