Link to documents and tools from a custom component
Use IntentLink, StateLink, and useIntentLink from sanity/router to navigate your studio from custom React components, so links behave like links.
Sanity Studio routes every view to a URL: each tool, each pane, and each open document. When a custom component sends someone elsewhere in the studio, going through that routing is what makes the result behave like a link. Command+click opens it in a new tab, and the address is there to copy.
This guide shows how to link to a document, a new document form, or another tool from your own React components, using IntentLink, StateLink, and useIntentLink from sanity/router.
Prerequisites
- Sanity Studio v3.0.0 or later.
IntentLink,StateLink, anduseIntentLinkhave all been exported fromsanity/routersince v3.0.0. - Familiarity with writing React components.
- A custom component or tool to render the link in. See Create a custom Studio tool.
Use a link, not a click handler
IntentLink and StateLink render an <a> element with a resolved href, then handle the click themselves only when the browser would have navigated in the same tab anyway. Everything else falls through to the browser:
- Command+click, Control+click, Shift+click, and Option+click
- Any click that isn't a primary-button click, including middle-click
- Any link with
targetset, such astarget="_blank"
A <button> with an onClick handler gives you none of that. It has no href, so there is nothing for the browser to open in a new tab and no address to copy, and assistive technology announces it as a button rather than as a link.
Don't build the href by hand
Link passes its href to the router unchanged, so the value has to be a full path that already includes your studio's base path. A studio served at /studio needs /studio/vision, not /vision. IntentLink and StateLink resolve the base path for you. Reach for Link only when you already have a resolved path, such as one returned by useRouter().resolveIntentLink().
Link to a document
IntentLink navigates by intent instead of by path. An edit intent names the document you want opened, and Studio resolves it to whichever pane in your structure handles that document type. The document opens where your editors expect it rather than in a bare editor outside your structure.
id is required. type is optional, but pass it when you know it — without it, Studio fetches the document first to find out its type.
import {IntentLink} from 'sanity/router'
export function PostLink(props: {postId: string; title: string}) {
return (
<IntentLink intent="edit" params={{id: props.postId, type: 'post'}}>
{props.title}
</IntentLink>
)
}If a link opens a bare editor whose pane ID starts with __edit__, the list you expected to catch the intent isn't declaring intent handling. See Handle intents in the Structure Tool.
Link to a new document form
A create intent opens the form for a new document. type is required, and Studio generates the document ID. Add template to start the document from an initial value template.
import {IntentLink} from 'sanity/router'
export function NewPostLink() {
return (
<IntentLink intent="create" params={{type: 'post'}}>
New post
</IntentLink>
)
}Link to another tool
Tools are reached by router state rather than by intent. StateLink takes the state you want and resolves it to a path, base path included. Set tool to the tool's name from your studio configuration, and clear that tool's own state so it opens at its root instead of wherever it was last left.
import {StateLink} from 'sanity/router'
export function VisionToolLink() {
return (
// Clearing the tool's own state opens it at its root
<StateLink state={{tool: 'vision', vision: undefined}}>Open the Vision Tool</StateLink>
)
}To link to the studio's root, pass toIndex instead of state. Passing both throws an error.
Use the useIntentLink hook for custom elements
useIntentLink does the same resolution and the same click handling as IntentLink, without rendering anything itself. Reach for it when the element is already something else: a Sanity UI Button, a card, a table row. It returns an href and an onClick.
import {Button} from '@sanity/ui'
import {useIntentLink} from 'sanity/router'
export function EditPostButton(props: {postId: string}) {
const {href, onClick} = useIntentLink({
intent: 'edit',
params: {id: props.postId, type: 'post'},
})
return <Button as="a" href={href} onClick={onClick} mode="ghost" text="Edit post" />
}Apply both. href is what the browser uses for modifier-key clicks and for the link's address; onClick is what routes inside the studio on a plain click. Set one without the other and half the behavior goes missing.
useStateLink returns the same pair for router-state links, including links to another tool.
Next steps
Handle intents in the Structure Tool
Declare intent handling so the links you build resolve to the right pane.
Create a custom Studio tool
Build the tool that renders these links.
Custom components for Sanity Studio
Override parts of the Studio UI with your own React components.
Studio API reference
Generated reference for sanity/router, including Link, IntentLink, and useIntentLink.