Overview
TimelinePanel provides a right-side panel for displaying ScopeTimeline on hub pages. It integrates with URL query parameters for bookmarkable state and PropertyPanel for consistent panel behavior including pin, expand, and minimize controls.
Key Features
- URL bookmark support via ?timeline=open query parameter
- Integrates with PropertyPanel for pin/expand/minimize controls
- Optional always-open mode for permanent timeline display
- Companion TimelineToggleButton component for PageHeader
- useTimelinePanel hook for programmatic control
- Automatic URL sync on browser back/forward navigation
Architecture
URL-Based State Management
TimelinePanel uses URL state for persistence and PropertyPanel for consistent panel behavior.
The panel state is stored in the URL via the ?timeline=open query parameter. This means users can bookmark pages with the timeline open, share links that open directly to the timeline view, and use browser back/forward to toggle the panel. The component automatically syncs with URL changes.
/program/project/hub/program/project/hub?timeline=openLayout Integration
The panel integrates with LayoutShell's rightPanel prop for proper layout coordination.
TimelinePanel is designed to work with LayoutShell's rightPanel prop. The LayoutShell handles the panel container positioning while TimelinePanel manages its visibility and content. Use TimelineToggleButton in the PageHeader actions for a consistent toggle experience.
Module Exports
TimelinePanel
The main panel component.
Renders the timeline as a togglable right panel. Pass programId and/or projectId to filter timeline events by scope. Use alwaysOpen for permanent display.
TimelineToggleButton
Self-contained toggle button.
A button that reads state from URL and toggles the timeline panel on click. Styled as outline when closed and secondary when open. Use in PageHeader actions for consistent positioning.
// In PageHeader actions
<PageHeader
title="Project Hub"
actions={<TimelineToggleButton />}
/>
// With custom styling
<TimelineToggleButton className="hidden md:flex" />useTimelinePanel
Hook for programmatic control.
Returns isOpen state and toggle/open/close functions for controlling the timeline panel programmatically. All operations sync with URL state.
import { useTimelinePanel } from '@/ui/components';
function MyComponent() {
const { isOpen, toggle, open, close } = useTimelinePanel();
// Check if timeline is currently open
if (isOpen) {
console.log('Timeline is visible');
}
// Toggle on button click
<Button onClick={toggle}>Toggle Timeline</Button>
// Open timeline programmatically
<Button onClick={open}>Show Timeline</Button>
// Close timeline programmatically
<Button onClick={close}>Hide Timeline</Button>
}Props Reference
TimelinePanel Props
| Prop | Type | Default | Description |
|---|---|---|---|
programId | string | - | Program ID for filtering timeline events (required for program/project scope) |
projectId | string | - | Project ID for filtering timeline events (required for project scope) |
alwaysOpen | boolean | false | When true, panel is always visible regardless of URL state |
TimelineToggleButton Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes for the button |
useTimelinePanel Return Value
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Whether the timeline panel is currently open |
toggle | () => void | Toggle the panel open/closed |
open | () => void | Open the panel (no-op if already open) |
close | () => void | Close the panel (no-op if already closed) |
Usage
import { TimelinePanel, TimelineToggleButton, useTimelinePanel } from '@/ui/components';
// In a hub page with LayoutShell
<LayoutShell
pageHeader={{
title: 'Project Hub',
actions: <TimelineToggleButton />,
}}
rightPanel={<TimelinePanel programId={programId} projectId={projectId} />}
>
{/* Page content */}
</LayoutShell>
// Always-open panel (no toggle behavior)
<TimelinePanel programId={programId} projectId={projectId} alwaysOpen />
// Programmatic control via hook
function MyComponent() {
const { isOpen, toggle, open, close } = useTimelinePanel();
return (
<Button onClick={toggle}>
{isOpen ? 'Hide Timeline' : 'Show Timeline'}
</Button>
);
}