import * as React from 'react'; /** Where the collapsed/expanded choice is remembered between visits. */ const RAIL_KEY = 'cbar-showcase:rail'; /** * Is the desktop rail on screen? * * Deliberately **not** in the hash, unlike `theme` and `lang`. Those describe * the view being shared; whether the person sending the link happened to have * the rail collapsed is not something the person opening it should inherit — * the same reasoning `Sidebar` already applies to the drawer's `open`. * * But it is a preference rather than a gesture: someone who collapses the rail * to read a wide matrix means it for the session and the next one, not for one * page. That is why this is the showcase's first piece of `localStorage` * (`use-tour.ts` follows it), and why it lives here rather than being * re-derived per component. Every access is wrapped, because storage throws * outright in a Safari private window rather than returning null. * * Its own file rather than `sidebar.tsx` because its only consumer is * `app.tsx` — the shell owns the layout, `Sidebar` only draws inside it. */ export function useRailVisible(): [boolean, () => void] { const [visible, setVisible] = React.useState(() => { try { return window.localStorage.getItem(RAIL_KEY) !== 'hidden'; } catch { return true; } }); /* In an effect rather than inside the updater: React runs an updater twice under StrictMode, and a write is not the sort of thing to do twice. */ React.useEffect(() => { try { window.localStorage.setItem(RAIL_KEY, visible ? 'shown' : 'hidden'); } catch { /* No storage — the toggle still works, it just forgets. */ } }, [visible]); const toggle = React.useCallback(() => setVisible((current) => !current), []); return [visible, toggle]; }