Files
PaperClipAI/ui/src/components/RequestCollapsedSidebar.tsx
T
DottaandClaude Opus 4.8 b0199e5951 feat(ui): RequestCollapsedSidebar route-request component (PAP-10645)
Task 5 of the collapsible sidebar plan (PAP-10638, plan §7).

Add the generic route-requested collapse mechanism on top of the state
model from PAP-10642. <RequestCollapsedSidebar/> is an effect-only
component: while mounted it sets routeRequestsCollapsed in SidebarContext,
defaulting the app sidebar to collapsed (still peek-able) — the "this
route brings its own sidebar, keep the app one out of the way" case.

- Precedence is enforced by SidebarContext: an explicit user pin
  (collapsed or expanded) always wins over the route request.
- Unmounting (navigating away from the route) clears the request via the
  effect cleanup, restoring the global default. A user pin persists.

Chose the effect-component form over route `handle` metadata because the
app uses JSX <Routes>/<Route> rather than object route config, so a
component drops cleanly into any page/plugin route's element tree.

Out of scope (follow-up): showing the plugin routeSidebar and the
collapsed app rail simultaneously — Layout still shows one or the other.

Component test covers: requests collapsed while mounted, user pin
overrides, unmount restores default, and pin persists across navigation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 16:35:10 +00:00

37 lines
1.1 KiB
TypeScript

import { useEffect } from "react";
import { useSidebar } from "../context/SidebarContext";
/**
* Effect-only component (renders nothing). While mounted, it asks the app
* sidebar to default to **collapsed** (still peek-able) — the generic
* "this route brings its own sidebar, keep the app one out of the way" case.
*
* Precedence is enforced by {@link SidebarContext}: an explicit user pin
* (collapsed *or* expanded) always wins over this route request. When the
* component unmounts — e.g. navigating away from the route that rendered it —
* the cleanup clears the request and the global default is restored.
*
* Drop it anywhere inside a route's element tree:
*
* ```tsx
* function MyPluginPage() {
* return (
* <>
* <RequestCollapsedSidebar />
* …
* </>
* );
* }
* ```
*/
export function RequestCollapsedSidebar() {
const { setRouteRequestsCollapsed } = useSidebar();
useEffect(() => {
setRouteRequestsCollapsed(true);
return () => setRouteRequestsCollapsed(false);
}, [setRouteRequestsCollapsed]);
return null;
}