Marigold v17.3.0
Spring is in full swing, and so is Marigold. v17.3.0 continues the navigation story we started with <Sidebar> and <TopNavigation> in v17.2.0 -- this time by giving you a ready-made shell to compose them into.
Components
AppShell (beta)
A new <AppShell> component provides a standardized App Shell layout using CSS Grid. You place <Sidebar>, <TopNavigation>, and <Page> directly as its children -- each owns its own named grid area, so the order doesn't matter -- composing the navigation primitives from v17.2.0 into a complete page chrome.
Before <AppShell>, teams had to hand-roll grid templates, 100dvh height containers, and sticky-header logic every time they wired <Sidebar> and <TopNavigation> together. Getting scroll behavior right (only the page area should scroll, sidebar and header stay put) was fiddly and easy to get subtly wrong. <AppShell> encapsulates that layout -- and absorbs the Sidebar.Provider for the common case -- so you can focus on content.
<AppShell defaultSidebarOpen>
<Sidebar>
<Sidebar.Header>{/* Logo */}</Sidebar.Header>
<Sidebar.Nav>{/* Navigation items */}</Sidebar.Nav>
</Sidebar>
<TopNavigation>
<TopNavigation.Start>
<Sidebar.Toggle />
</TopNavigation.Start>
<TopNavigation.Middle>{/* Breadcrumbs, search */}</TopNavigation.Middle>
<TopNavigation.End>{/* User menu */}</TopNavigation.End>
</TopNavigation>
<Page>{/* Page content */}</Page>
</AppShell>The grid fills 100dvh and the header is a fixed 3.5rem tall. The sidebar header height was also aligned with the <AppShell> header so logos and navigation items line up cleanly. See the new App Shell pattern for a step-by-step guide covering providers, responsive behavior, and where to place content.
System
Stable useToast callbacks
addToast, clearToasts, and removeToast from useToast are now wrapped in useCallback. Previously, these functions got a new identity on every render, which meant including them in a useEffect dependency array would trigger the effect on every render. Now the references are stable across renders and safe to use as dependencies.
const { addToast } = useToast();
useEffect(() => {
if (saveSucceeded) {
addToast({ title: 'Saved!', variant: 'success' });
}
}, [saveSucceeded, addToast]); // Safe now — addToast is stableDesign
- Replaced hardcoded values with semantic tokens across multiple theme files, including
<Tag>and<Slider>. Hardcoded values drift from the token system over time and make custom themes harder to override -- moving them into tokens keeps the design language consistent.
Bug fixes
- v17.2.1: Fixed a broken icon color inside
<Menu.Item>. A malformed Tailwind selector ([&_svg]:text-muted-foreground:opacity-60) collapsed two modifiers into one, so nested<svg>icons lost their muted color. Split into[&_svg]:text-muted-foreground [&_svg]:opacity-60.
Documentation
- Refactored the
<Calendar>documentation for clarity around the newvisibleDurationandpageBehaviorprops introduced in v17.0.0.
A small release that makes a big difference if you're building app shells. As always, feedback is welcome!