Studio components provide the building blocks for creating custom Studio interfaces and extending the default Studio experience.
Studio
The root Studio component that renders the complete Sanity Studio interface.
import {Studio} from 'sanity'
import config from './sanity.config'
function App() {
return <Studio config={config} />
}
config
Config | Config[]
required
Studio configuration object or array of workspace configurations
Base path for the Studio when embedded in another application (e.g., '/admin')
scheme
'light' | 'dark' | 'system'
Color scheme to use. If provided without onSchemeChange, the appearance dropdown is hidden.
onSchemeChange
(scheme: StudioThemeColorSchemeKey) => void
Callback fired when user changes the color scheme in the appearance menu
Whether to inject global styles (default: true in standalone mode)
Custom router history implementation for controlling navigation
Disable authentication boundary (for custom auth implementations)
Example: Embedded Studio
import {Studio} from 'sanity'
import {usePrefersDark} from '@sanity/ui'
import {useState} from 'react'
function EmbeddedStudio() {
const prefersDark = usePrefersDark()
const [scheme, setScheme] = useState<'light' | 'dark' | 'system'>('system')
const resolvedScheme = scheme === 'system'
? (prefersDark ? 'dark' : 'light')
: scheme
return (
<div style={{colorScheme: resolvedScheme}}>
<AppHeader scheme={resolvedScheme} />
<Studio
config={config}
basePath="/admin"
scheme={scheme}
onSchemeChange={setScheme}
/>
</div>
)
}
StudioProvider
Provider component that wraps Studio functionality without rendering the layout. Use this when you need Studio context in a custom interface.
import {StudioProvider, StudioLayout} from 'sanity'
import config from './sanity.config'
function CustomStudio() {
return (
<StudioProvider config={config}>
<CustomHeader />
<StudioLayout />
</StudioProvider>
)
}
config
Config | Config[]
required
Studio configuration
scheme
'light' | 'dark' | 'system'
Color scheme
onSchemeChange
(scheme: StudioThemeColorSchemeKey) => void
Scheme change handler
Child components that need access to Studio context
StudioLayout
Renders the default Studio layout (navbar, tools, panels). Use with StudioProvider for custom Studio shells.
import {StudioProvider, StudioLayout} from 'sanity'
function CustomStudio() {
return (
<StudioProvider config={config}>
<CustomBanner />
<StudioLayout />
</StudioProvider>
)
}
Pane Components
Components for building custom panes and layouts within the Studio.
Pane
Container component for custom panes.
import {Pane} from 'sanity/structure'
function CustomPane() {
return (
<Pane id="custom-pane" title="My Custom Pane">
<div>Pane content</div>
</Pane>
)
}
Pane title displayed in the header
PaneContent
Scrollable content container for panes.
import {Pane, PaneContent} from 'sanity/structure'
function CustomPane() {
return (
<Pane id="custom" title="Custom">
<PaneContent>
<div>Scrollable content</div>
</PaneContent>
</Pane>
)
}
PaneLayout
Layout component for organizing pane content.
import {Pane, PaneLayout} from 'sanity/structure'
function CustomPane() {
return (
<Pane id="custom" title="Custom">
<PaneLayout>
<div>Organized content</div>
</PaneLayout>
</Pane>
)
}
Preview Components
Components for rendering document previews.
SanityDefaultPreview
Default preview component for documents.
import {SanityDefaultPreview} from 'sanity'
function DocumentItem({document}: Props) {
return (
<SanityDefaultPreview
value={document}
schemaType={schemaType}
layout="default"
/>
)
}
layout
'default' | 'card' | 'media' | 'detail'
Preview layout style
Dialog Components
Components for modal dialogs and confirmations.
ConfirmDeleteDialog
Confirmation dialog for document deletion.
import {ConfirmDeleteDialog} from 'sanity/structure'
function DeleteButton({document}: Props) {
const [open, setOpen] = useState(false)
return (
<>
<Button onClick={() => setOpen(true)}>Delete</Button>
{open && (
<ConfirmDeleteDialog
id={document._id}
type={document._type}
onCancel={() => setOpen(false)}
onConfirm={async () => {
await deleteDocument(document._id)
setOpen(false)
}}
/>
)}
</>
)
}
onConfirm
() => void | Promise<void>
required
Confirm handler
import {StudioProvider, Pane, PaneContent} from 'sanity'
import {Card, Stack, Heading} from '@sanity/ui'
function CustomTool() {
return (
<Pane id="custom-tool" title="Analytics">
<PaneContent>
<Card padding={4}>
<Stack space={4}>
<Heading>Document Statistics</Heading>
<DocumentStats />
</Stack>
</Card>
</PaneContent>
</Pane>
)
}