Three lower-sidebar panels are now wrapped in a shared Collapsible so mobile readers can fold away sections they're not actively using. New shared pieces: - lib/collapsible.ts — readOpen/writeOpen helpers backed by localStorage under 'panel-open:<name>'. Per-panel-name (not per-code) because the preference is a panel-level habit; users don't want different fold state for every symbol. - components/Collapsible.tsx — button-as-header + chevron + body. aria-expanded for AT. Body uses 'hidden' instead of conditional unmount so textarea text, partial alert form input, and RelatedStocks fetch results all survive collapse cycles. SSR-safe: useState(defaultOpen) then useEffect-sync to avoid React hydration mismatch when localStorage diverges from default. Panel refactors: - RelatedStocks: outer rounded div + header replaced with Collapsible; loading/error/empty/data states all rendered inside body (header stays visible so user can still toggle/recognize the section even while loading). - InvestmentNote: same swap. saved.updatedAt drives the subtitle. - AlertsPanel: same swap. current price drives the subtitle. Defaults are open=true everywhere; the surface area is the toggle itself, not a forced collapse. User's first interaction sets the sticky preference.
2.6 KiB
2.6 KiB