mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-02 17:08:39 +00:00
refactor(sidebar): improve setOpen callback logic (#5593)
* refactor(sidebar): improve setOpen callback logic - Simplify state handling - Ensure consistent cookie setting - Added ability for users to persist sidebar state via cookies - Update sidebar.mdx doc with SSR persistence instructions - Run pnpm registry:build to update component * docs: updates --------- Co-authored-by: shadcn <m@shadcn.com>
This commit is contained in:
@@ -406,6 +406,40 @@ You can change the keyboard shortcut by updating the `SIDEBAR_KEYBOARD_SHORTCUT`
|
||||
const SIDEBAR_KEYBOARD_SHORTCUT = "b"
|
||||
```
|
||||
|
||||
### Persisted State
|
||||
|
||||
The `SidebarProvider` supports persisting the sidebar state across page reloads and server-side rendering. It uses cookies to store the current state of the sidebar. When the sidebar state changes, a default cookie named `sidebar:state` is set with the current open/closed state. This cookie is then read on subsequent page loads to restore the sidebar state.
|
||||
|
||||
To persist sidebar state in Next.js, set up your `SidebarProvider` in `app/layout.tsx` like this:
|
||||
|
||||
```tsx showLineNumbers title="app/layout.tsx"
|
||||
import { cookies } from "next/headers"
|
||||
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
|
||||
export async function Layout({ children }: { children: React.ReactNode }) {
|
||||
const cookieStore = await cookies()
|
||||
const defaultOpen = cookieStore.get("sidebar:state")?.value === "true"
|
||||
|
||||
return (
|
||||
<SidebarProvider defaultOpen={defaultOpen}>
|
||||
<AppSidebar />
|
||||
<main>
|
||||
<SidebarTrigger />
|
||||
{children}
|
||||
</main>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
You can change the name of the cookie by updating the `SIDEBAR_COOKIE_NAME` variable in `sidebar.tsx`.
|
||||
|
||||
```tsx showLineNumbers title="components/ui/sidebar.tsx"
|
||||
const SIDEBAR_COOKIE_NAME = "sidebar:state"
|
||||
```
|
||||
|
||||
## Sidebar
|
||||
|
||||
The main `Sidebar` component used to render a collapsible sidebar.
|
||||
@@ -1323,7 +1357,30 @@ You can find more tips on using states for styling in this [Twitter thread](http
|
||||
|
||||
## Changelog
|
||||
|
||||
### 2024-10-21
|
||||
### 2024-10-30 Cookie handling in setOpen
|
||||
|
||||
- [#5593](https://github.com/shadcn-ui/ui/pull/5593) - Improved setOpen callback logic in `<SidebarProvider>`.
|
||||
|
||||
Update the `setOpen` callback in `<SidebarProvider>` as follows:
|
||||
|
||||
```tsx showLineNumbers
|
||||
const setOpen = React.useCallback(
|
||||
(value: boolean | ((value: boolean) => boolean)) => {
|
||||
const openState = typeof value === "function" ? value(open) : value
|
||||
if (setOpenProp) {
|
||||
setOpenProp(openState)
|
||||
} else {
|
||||
_setOpen(openState)
|
||||
}
|
||||
|
||||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
},
|
||||
[setOpenProp, open]
|
||||
)
|
||||
```
|
||||
|
||||
### 2024-10-21 Fixed `text-sidebar-foreground`
|
||||
|
||||
- [#5491](https://github.com/shadcn-ui/ui/pull/5491) - Moved `text-sidebar-foreground` from `<SidebarProvider>` to `<Sidebar>` component.
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -76,16 +76,15 @@ const SidebarProvider = React.forwardRef<
|
||||
const open = openProp ?? _open
|
||||
const setOpen = React.useCallback(
|
||||
(value: boolean | ((value: boolean) => boolean)) => {
|
||||
const openState = typeof value === "function" ? value(open) : value
|
||||
if (setOpenProp) {
|
||||
return setOpenProp?.(
|
||||
typeof value === "function" ? value(open) : value
|
||||
)
|
||||
setOpenProp(openState)
|
||||
} else {
|
||||
_setOpen(openState)
|
||||
}
|
||||
|
||||
_setOpen(value)
|
||||
|
||||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
},
|
||||
[setOpenProp, open]
|
||||
)
|
||||
|
||||
@@ -76,16 +76,15 @@ const SidebarProvider = React.forwardRef<
|
||||
const open = openProp ?? _open
|
||||
const setOpen = React.useCallback(
|
||||
(value: boolean | ((value: boolean) => boolean)) => {
|
||||
const openState = typeof value === "function" ? value(open) : value
|
||||
if (setOpenProp) {
|
||||
return setOpenProp?.(
|
||||
typeof value === "function" ? value(open) : value
|
||||
)
|
||||
setOpenProp(openState)
|
||||
} else {
|
||||
_setOpen(openState)
|
||||
}
|
||||
|
||||
_setOpen(value)
|
||||
|
||||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
},
|
||||
[setOpenProp, open]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user