Open document in new pane from custom component with multiple types

4 replies
Last updated: Nov 30, 2025
Hi all. I have a question about editing a document in a new pane from a custom component. I have setup the custom component in the following (simplified) desk structure:
S.list()
    .title('Content')
    .items([
      S.listItem().title('Page tree').child(
        S.component(CustomComponent).id('CustomComponent').title('Custom component'),
      ),
...
In this view I have a listening query for a set of documents and want to render those as buttons with links to open the target document in a new pane.
I have tried:

<IntentLink />
from
usePaneRouter
• The same approach as is done in
Documents Pane plugin • The same approach as is done in
Document internationalization plugin I keep getting a warning that the desk structure child was not found, but I cannot (or do not know how to) express a specific document type as a child of the structure, as it can be multiple types. This works:

S.component(CustomComponent).id('CustomComponent').title('Custom component').child(S.document().schemaType('typeA')),
but only (correctly) for a document of
typeA
and not
typeB
I want similar behaviour for panes as is done in the
documentList
.
Does anyone have experience doing this and/or can help with this? Thanks!
AI Update

I've dealt with this exact issue! The problem you're encountering is that when you define a custom component in your Structure, Sanity doesn't know what child panes to expect until a user actually clicks on something. The warning about "desk structure child was not found" happens because the Structure builder can't resolve the navigation path ahead of time.

The solution that works is actually documented in this community answer. You need to use Object.assign() to serialize a documentList and then override it with your custom component properties:

S.listItem()
  .title("Page tree")
  .child(
    Object.assign(
      S.documentList()
        .filter('_type in ["typeA", "typeB"]')
        .title("Page tree")
        .serialize(), 
      {
        __preserveInstance: true,
        key: 'pageTree',
        id: 'pageTree',
        type: 'component',
        component: CustomComponent,
      }
    ),
  )

This approach works because internally it's still a document list from the Structure builder's perspective, which means the pane router knows how to handle document navigation properly. When users click links in your custom component to open documents, the Structure tool will correctly open them in new panes.

The key insight here is that you're not trying to define .child(S.document().schemaType('typeA')) for each type. Instead, you're letting the document list handle multiple types through its filter, while your custom component just provides the visual representation.

This pattern is used by plugins like the orderable-document-list plugin, which renders custom components for list items while maintaining proper pane navigation behavior.

Once you have this structure in place, the <IntentLink /> from usePaneRouter should work as expected, because the Structure builder now understands that this is a document list that can have document children, even though it's rendering through your custom component.

Show original thread
4 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?