Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-sidebars-complete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/kumo": minor
---

Add sidebar open-change completion callbacks.
74 changes: 72 additions & 2 deletions packages/kumo-docs-astro/src/components/demos/SidebarDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,77 @@ export function SidebarAutoScrollDemo() {
}

// ---------------------------------------------------------------------------
// 7. Sliding Views — animated horizontal transitions between surfaces
// 7. Transition completion — run work after sidebar and collapsible animations
// ---------------------------------------------------------------------------

/** Run layout-dependent work after a sidebar or collapsible finishes transitioning. */
export function SidebarTransitionCompleteDemo() {
const [completion, setCompletion] = useState(
"No transition has completed yet.",
);

return (
<DemoContainer>
<Sidebar.Provider
contained
defaultOpen
className="h-full min-h-0!"
onOpenChangeComplete={(open) => {
setCompletion(`Sidebar ${open ? "opened" : "collapsed"}.`);
}}
>
<Sidebar>
<Sidebar.Content>
<Sidebar.Group>
<Sidebar.GroupLabel>Overview</Sidebar.GroupLabel>
<Sidebar.Menu>
<Sidebar.MenuButton icon={HouseIcon} active>
Home
</Sidebar.MenuButton>
<Sidebar.MenuItem>
<Sidebar.Collapsible
onOpenChangeComplete={(open) => {
setCompletion(
`Compute section ${open ? "opened" : "collapsed"}.`,
);
}}
>
<Sidebar.CollapsibleTrigger
render={
<Sidebar.MenuButton icon={CodeIcon}>
Compute
<Sidebar.MenuChevron />
</Sidebar.MenuButton>
}
/>
<Sidebar.CollapsibleContent>
<Sidebar.MenuSub>
<Sidebar.MenuSubButton>Workers</Sidebar.MenuSubButton>
<Sidebar.MenuSubButton>Pages</Sidebar.MenuSubButton>
</Sidebar.MenuSub>
</Sidebar.CollapsibleContent>
</Sidebar.Collapsible>
</Sidebar.MenuItem>
</Sidebar.Menu>
</Sidebar.Group>
</Sidebar.Content>
<Sidebar.Footer>
<Sidebar.Trigger />
</Sidebar.Footer>
</Sidebar>
<DemoMain>
<p aria-live="polite">{completion}</p>
<p>
Toggle the sidebar or open Compute to see the completion callback.
</p>
</DemoMain>
</Sidebar.Provider>
</DemoContainer>
);
}

// ---------------------------------------------------------------------------
// 8. Sliding Views — animated horizontal transitions between surfaces
// ---------------------------------------------------------------------------

/** Sidebar with animated sliding views between Account and Zone navigation. */
Expand Down Expand Up @@ -712,7 +782,7 @@ export function SidebarSlidingViewsDemo() {
}

// ---------------------------------------------------------------------------
// 8. Full — kitchen sink showcasing every subcomponent
// 9. Full — kitchen sink showcasing every subcomponent
// ---------------------------------------------------------------------------

/** Kitchen sink sidebar showcasing every subcomponent: header with account switcher, groups with labels, collapsible sections with nested expandable, badges, sliding views via Domains, and a footer trigger. */
Expand Down
38 changes: 38 additions & 0 deletions packages/kumo-docs-astro/src/pages/components/sidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SidebarRightDemo,
SidebarPeekingDemo,
SidebarAutoScrollDemo,
SidebarTransitionCompleteDemo,
SidebarSlidingViewsDemo,
SidebarMobileDemo,
SidebarFullScreenMobileDemo,
Expand Down Expand Up @@ -255,6 +256,43 @@ const { state, isPeeking } = useSidebar();
</ComponentExample>
</div>

<div>
<Heading level={3}>Transition Completion</Heading>
<p>
Use <code class="rounded bg-kumo-control px-1 py-0.5 text-xs">onOpenChangeComplete</code> when work must wait for a sidebar or collapsible transition to settle, such as measuring layout or scrolling newly revealed content. The callback receives the completed open state and also runs when reduced motion disables the transition.
</p>
<ComponentExample code={`const [completion, setCompletion] = useState("");

<Sidebar.Provider
defaultOpen
onOpenChangeComplete={(open) => {
setCompletion("Sidebar " + (open ? "opened." : "collapsed."));
}}
>
<Sidebar>
<Sidebar.Content>
<Sidebar.Menu>
<Sidebar.MenuItem>
<Sidebar.Collapsible
onOpenChangeComplete={(open) => {
setCompletion(
"Compute section " + (open ? "opened." : "collapsed."),
);
}}
>
<Sidebar.CollapsibleTrigger render={<Sidebar.MenuButton>Compute</Sidebar.MenuButton>} />
<Sidebar.CollapsibleContent>...</Sidebar.CollapsibleContent>
</Sidebar.Collapsible>
</Sidebar.MenuItem>
</Sidebar.Menu>
</Sidebar.Content>
<Sidebar.Footer><Sidebar.Trigger /></Sidebar.Footer>
</Sidebar>
</Sidebar.Provider>`}>
<SidebarTransitionCompleteDemo client:load />
</ComponentExample>
</div>

<div>
<Heading level={3}>Scroll to Item</Heading>
<p>
Expand Down
Loading
Loading