- PublicGardenPage had the same 100vh mobile bug I fixed in the editor — 100dvh there too, so the fix is consistent across both full-height pages. - Cap the toast stack at 4 (drop oldest). Now that error toasts don't auto- dismiss, a burst of failures could otherwise grow the stack unbounded and push the newest — the one that just happened — off-screen. - Hoist the From/To date-input styling to a shared dateInputClass const so the two don't drift. Not taken: reusing safeRedirectPath for the 401 redirect (it validates an incoming redirect param, it doesn't build the outgoing one — the two uses don't overlap), and refactoring the three-branch filter spread (it's clear at three fields; a helper earns its keep when there are more). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
This commit is contained in:
@@ -17,9 +17,16 @@ interface ToastState {
|
||||
|
||||
let nextId = 1
|
||||
|
||||
// Error toasts no longer auto-dismiss (#85), so a burst of failures could grow
|
||||
// the stack without bound and push older ones off-screen. Cap it: keep the most
|
||||
// recent MAX_TOASTS and drop the oldest, so the newest — the one that just
|
||||
// happened — is always visible.
|
||||
const MAX_TOASTS = 4
|
||||
|
||||
export const useToastStore = create<ToastState>((set) => ({
|
||||
toasts: [],
|
||||
push: (message, tone = 'info') => set((s) => ({ toasts: [...s.toasts, { id: nextId++, message, tone }] })),
|
||||
push: (message, tone = 'info') =>
|
||||
set((s) => ({ toasts: [...s.toasts, { id: nextId++, message, tone }].slice(-MAX_TOASTS) })),
|
||||
dismiss: (id) => set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) })),
|
||||
}))
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ import {
|
||||
import type { EditorObject } from './types'
|
||||
import { objectDisplayName } from './kinds'
|
||||
|
||||
// Shared styling for the small From/To date inputs, so the two stay in step and
|
||||
// don't drift from each other.
|
||||
const dateInputClass =
|
||||
'rounded-md border border-border bg-surface px-1.5 py-1 text-fg outline-none focus-visible:ring-2 focus-visible:ring-accent/40'
|
||||
|
||||
/**
|
||||
* The garden's journal: write an entry, read the season back.
|
||||
*
|
||||
@@ -86,7 +91,7 @@ export function JournalPanel({
|
||||
value={from}
|
||||
max={to || undefined}
|
||||
onChange={(e) => setFrom(e.target.value)}
|
||||
className="rounded-md border border-border bg-surface px-1.5 py-1 text-fg outline-none focus-visible:ring-2 focus-visible:ring-accent/40"
|
||||
className={dateInputClass}
|
||||
/>
|
||||
</label>
|
||||
<label className="flex items-center gap-1">
|
||||
@@ -96,7 +101,7 @@ export function JournalPanel({
|
||||
value={to}
|
||||
min={from || undefined}
|
||||
onChange={(e) => setTo(e.target.value)}
|
||||
className="rounded-md border border-border bg-surface px-1.5 py-1 text-fg outline-none focus-visible:ring-2 focus-visible:ring-accent/40"
|
||||
className={dateInputClass}
|
||||
/>
|
||||
</label>
|
||||
{(from || to) && (
|
||||
|
||||
@@ -53,7 +53,7 @@ export function PublicGardenPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-[calc(100vh-8rem)] flex-col gap-3">
|
||||
<div className="flex h-[calc(100dvh-8rem)] flex-col gap-3">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h1 className="truncate text-lg font-semibold tracking-tight" title={garden.name}>
|
||||
{garden.name}
|
||||
|
||||
Reference in New Issue
Block a user