How to add and access options in Sanity custom type definitions?

3 replies
Last updated: Jan 3, 2022
If I'm creating a new custom type - like
localeBlock
- how can I add options to this type, and then access them inside of my definition?
Code in thread.
AI Update

When creating custom types in Sanity, you can add options to your type definition and access them within your schema. Here's how it works:

Adding Options to Custom Types

Options are defined within an options object in your schema definition. For example:

{
  type: 'object',
  name: 'localeBlock',
  title: 'Localized Block',
  options: {
    collapsible: true,
    collapsed: false,
    columns: 2,
    modal: {
      type: 'dialog',
      width: 'medium'
    }
  },
  fields: [
    // your fields here
  ]
}

Common Options for Objects

According to the object type documentation, you can use these options:

  • collapsible: Set to true to make fields collapsible (default at depth 3)
  • collapsed: Set to true to start with fields collapsed (requires collapsible: true)
  • columns: Number of columns in a grid layout for inputs
  • modal: Controls modal rendering with type ('dialog' or 'popover') and width properties

Accessing Options in Your Definition

If you need to access options programmatically within custom components or input components, you can access them through the schema type context:

// In a custom input component
const MyCustomInput = (props) => {
  const options = props.schemaType.options
  
  // Access specific options
  const isCollapsible = options?.collapsible
  const columnCount = options?.columns
  
  // Use them in your component logic
  return (
    // your component JSX
  )
}

Field-Level vs Type-Level Options

Remember that options can be defined at both the type level (affecting all instances) and when you use the type in a field:

// In your schema
fields: [
  {
    name: 'myLocaleBlock',
    type: 'localeBlock',
    options: {
      // These override the type-level options for this specific field
      collapsed: true
    }
  }
]

The field-level options will override type-level options when both are present. This gives you flexibility to set defaults at the type level while customizing behavior for specific field instances.

Show original thread
3 replies
I want to create a new custom type for portable text, which supports localization. Right now, it looks like this:

export const localeBlock = {
  title: "Localized content",
  name: "localeBlock",
  type: "object",
  fields: supportedLanguages.map((language) => ({
    name: language.id,
    title: language.name,
    type: "array",
    of: [{ type: "block" }, { type: "customType" }],
  })),
};
Now, whenever I want localized block content, I can simply specify
{ type: "localeBlock" }
in my schemas:

{
  type: "document",
  name: "product",
  title: "Product",
  fields: [
    { name: 'description', type: 'localeBlock' }
  ],
}
Now, I want to be able to specify what types of custom block content I want to have in this
description
field. Perhaps I want images, perhaps I want a custom section or whatever. So I want to specify what's in the
of
array of the
localeBlock
content type, by specifying it like so:

{
  type: "document",
  name: "product",
  title: "Product",
  fields: [
    { name: 'description', type: 'localeBlock', of: [{ type: 'image' }, { type: 'customSection' }] }
  ]
}
But how can I specify that the content of the
of
section should be put into the
of
block in the first code example above? Is this even possible?
Ah, turns out this can be solved by using plain ol' JavaScript!
Instead of specifying a custom type, I created a function that inlines the type for me.


{
  type: "document",
  name: "product",
  title: "Product",
  fields: [
    createLocaleBlock({ 
      name: 'description', 
      of: [
        { type: 'block' }, 
        { type: 'image' }, 
        { type: 'customSection' }
      ]
    }
  ]
}
And the function itself looks like this:

export const createLocaleBlock = ({
  of,
  name,
  title,
  description,
  validation,
}) => ({
  title,
  name,
  description,
  type: "object",
  fields: supportedLanguages.map((language) => ({
    name: language.id,
    title: language.name,
    type: "array",
    of,
  })),
  validation,
});

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?