Quick start
Install the plugin, open the panel from your own button, and deep-link into it.
Install
pnpm add @10x-media/settings-overlay@betaimport { buildConfig } from 'payload'
import { settingsOverlay } from '@10x-media/settings-overlay'
export default buildConfig({
collections: [tags, redirects],
globals: [branding],
plugins: [
settingsOverlay({
overlays: [
{
id: 'system',
label: 'Settings',
items: [
{ type: 'collection', slug: 'tags' },
{ type: 'collection', slug: 'redirects' },
{ type: 'global', slug: 'branding' },
],
},
],
}),
],
})Then regenerate the import map:
pnpm payload generate:importmapWithout it the provider resolves to nothing and no panel appears.
tags, redirects and branding keep their nav entries and their own routes; the panel is a second way in, not a replacement. Set hideEntities: true on the overlay to make it the only way in, once you have read what drawer mode leaves out.
Open it
The plugin ships no button. Where a settings button belongs depends on your admin, so it gives you the hook and you place it:
'use client'
import { useSettingsOverlay } from '@10x-media/settings-overlay/client'
export const SettingsButton = () => {
const { toggle } = useSettingsOverlay()
return (
<button onClick={() => toggle('system')} type="button">
Settings
</button>
)
}admin: {
components: {
beforeNavLinks: ['./components/SettingsButton#SettingsButton'],
},
}There is also a ready-made button for the common case of opening the panel on something specific, from a field or a list action:
import { SettingsOverlayButton } from '@10x-media/settings-overlay/client'
<SettingsOverlayButton overlay="system" item="tags" id="abc">
Edit this tag
</SettingsOverlayButton>Link to it
Every overlay is addressable by default:
?settings=system the panel, on its first row
?settings=system/tags the tags list
?settings=system/tags/abc one tag
?settings=system/tags/new the create formA filtered list carries its query in a second parameter, ?settingsQuery=, so the page underneath keeps its own where[...] parameters untouched.
The panel writes the URL with the History API rather than the router, so it does not refetch the page under it.
By default every navigation in the panel is a history entry, as it would be between pages: opening it, switching rows, opening a document, returning to its list, and closing it again. The back button walks all of that in reverse, so pressing it after a close reopens the panel where you left it. A list's filters, search, sort and paging replace the current entry instead, as Payload's own list does on a page. Set history: 'replace' on an overlay and it adds no entries at all: the URL still names the panel, so a link keeps working, but the back button leaves the page, the way it does over one of Payload's drawers.
A stale link lands on something the reader can open rather than on an error: an item that no longer exists falls back to the first row, and a document that no longer exists to its list.
Set addressable: false on an overlay to keep it out of the URL entirely.
Try the rest
import { appearanceItem } from '@10x-media/settings-overlay/items'
items: [
appearanceItem(),
{ type: 'collection', slug: 'tags' },
{ type: 'component', slug: 'about', label: 'About', component: './About#About' },
{ type: 'view', slug: 'audit', label: 'Audit log', viewKey: 'auditLogs' },
{ type: 'link', slug: 'account', label: 'Account', href: '/account' },
]appearanceItem() is a bundled row for theme and language, the two controls Payload otherwise offers only on /admin/account. See Items for what each type is for.