Add custom text input option to predefined options list in Sanity Studio

6 replies
Last updated: Aug 7, 2020
Does anyone know how I might add a custom text input to the
options
list in Studio? For example, if a user wants to select from preset labels or enter their own.
{

name: 'label',

title: 'Label',

type: 'string',

options: {

list: ['First Name', 'Last Name', 'Company', 'Email', 'Message', 'Phone']

},
Thanks!
AI Update

I need to create a custom input component for this use case. While Sanity's string type with an options list gives you predefined choices, there's no built-in feature to automatically add a "custom text input" option to that list. The solution is to create a custom input component.

Here's how you can build this:

import { set, unset } from 'sanity'
import { Stack, Select, TextInput, Card, Text } from '@sanity/ui'
import { useState } from 'react'

const presetLabels = ['First Name', 'Last Name', 'Company', 'Email', 'Message', 'Phone']

function LabelInput(props) {
  const { value, onChange } = props
  const [useCustom, setUseCustom] = useState(
    value && !presetLabels.includes(value)
  )

  const handlePresetChange = (event) => {
    const newValue = event.currentTarget.value
    
    if (newValue === '__custom__') {
      setUseCustom(true)
      onChange(unset())
    } else {
      setUseCustom(false)
      onChange(newValue ? set(newValue) : unset())
    }
  }

  const handleCustomChange = (event) => {
    const newValue = event.currentTarget.value
    onChange(newValue ? set(newValue) : unset())
  }

  return (
    <Stack space={3}>
      <Select
        value={useCustom ? '__custom__' : (value || '')}
        onChange={handlePresetChange}
      >
        <option value="">Select a label...</option>
        {presetLabels.map((label) => (
          <option key={label} value={label}>
            {label}
          </option>
        ))}
        <option value="__custom__">Custom label...</option>
      </Select>
      
      {useCustom && (
        <Card border padding={3}>
          <Stack space={2}>
            <Text size={1} weight="semibold">Custom Label</Text>
            <TextInput
              value={value || ''}
              onChange={handleCustomChange}
              placeholder="Enter custom label"
            />
          </Stack>
        </Card>
      )}
    </Stack>
  )
}

// In your schema:
export default {
  name: 'myDocument',
  type: 'document',
  fields: [
    {
      name: 'label',
      title: 'Label',
      type: 'string',
      components: {
        input: LabelInput
      }
    }
  ]
}

This component gives users a dropdown with all your preset options plus a "Custom label..." option. When they select "Custom label...", a text input appears where they can type their own value.

Key points about this approach:

  1. The component uses Sanity's PatchEvent system with set() and unset() to properly update the field value
  2. It uses components from @sanity/ui to maintain visual consistency with the rest of Studio
  3. The value is still stored as a simple string, so it works seamlessly with queries and validation
  4. You can enhance this with validation to ensure custom values meet your requirements

If you want a simpler UI, you could also just show the dropdown and text input side-by-side, or use radio buttons for presets with an "Other" option that reveals the text input. The custom input component approach gives you complete control over the UX.

Show original thread
6 replies
Usually it’s either a select with options or a string field for custom input. However, what you could try is set up a conditional input field that only shows up if the user selects an option like
'Other'
.
For an example of how to set up conditional fields as a custom input component, here’s a snippet:
https://github.com/sanity-io/sanity-recipes/blob/39d2fb0d079fec3a60dc1f13d6abbf6f4e3ae037/snippets/conditionalFieldsCustomInputComponent.js
Let me know if you need more info based on the snippet
🙂
Cool, thanks for the quick reply Peter
Though to clarify, this is on the Studio side of things - I want to give our marketing team the ability to create a custom input field in addition to the pre set drop down that currently exisist
exists**
The snippet is for the Studio side of things: it lets you set up an extra field that is hidden or visible depending on the value of another field (for example when `label`’s value equals
'Other'
).
Alternatively, you could show the extra string field at all times, but this might be confusing to the editors. There’s currently no option to have a select + custom input on a single string field. You could decide to create such a field type as a custom input component as well I guess, but the conditional field route is probably faster.
Awesome, thanks!

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?