Разработка кастомных Input Components для Sanity Studio
Редактор вводит hex-код цвета, но вместо #FF5733 отправляет rgb(255,87,51). Поле тегов заполняется дубликатами, а выбор региона заставляет каждый раз вручную вбивать название из памяти. Знакомо? Мы решаем эти проблемы с помощью кастомных Input Components для Sanity Studio. Стандартные String и Array поля не валидируют формат и не подсказывают варианты. Наши компоненты предотвращают ошибки ввода на 80–90% и ускоряют заполнение контента в 3–4 раза. Опыт показывает, что редакторы тратят на 30% меньше времени на ввод данных после внедрения кастомных полей.
Какие проблемы решаем
Первая проблема — неоднозначность ввода. Редактору нужно выбрать цвет бренда. Без ограничений он может вписать #FF5733, rgb(255,87,51) или даже red. Результат — разнобой данных, который ломает отображение на сайте. Наш кастомный компонент с палитрой пресетов и валидацией формата решает это на уровне интерфейса. Ошибки ввода снижаются на 80–90%.
Вторая — отсутствие связности. Теги, категории, метки часто нужны с автодополнением, чтобы избежать дублей. Стандартный массив строк этого не умеет. Наш TagInput предлагает существующие теги, фильтрует по вводу и добавляет новые контролируемо. Скорость заполнения тегов возрастает в 3–4 раза.
Третья — динамические данные. Выбор региона, валюты или товара часто подгружается из внешнего API. Встроенные поля не поддерживают асинхронную подгрузку. Компонент с useEffect и вызовом API решает это за пару десятков строк. Мы гарантируем, что в компонентах учтены состояния загрузки и ошибок.
Как создать кастомный компонент?
Каждый компонент инкапсулирует свою логику: отображение, управление состоянием через патчи Sanity, работу с readOnly и ошибками. Рассмотрим кейс с ColorPickerInput.
ColorPickerInput: палитра пресетов
Компонент отображает набор цветных кружков, при клике записывает hex-код в поле. Дополнительно есть текстовый инпут для произвольного ввода. Используем функции set и unset из Sanity, чтобы правильно мутировать значение. Код:
// components/studio/ColorPickerInput.tsx import { useCallback } from 'react' import { set, unset } from 'sanity' import type { StringInputProps } from 'sanity' const PRESET_COLORS = ['#FF5733', '#33FF57', '#3357FF', '#FF33A8', '#FFAA00', '#00AAFF', '#9B59B6', '#1ABC9C'] export function ColorPickerInput(props: StringInputProps) { const { value, onChange, readOnly, elementProps } = props const handleSelect = useCallback( (color: string) => { onChange(color ? set(color) : unset()) }, [onChange] ) return ( <div> <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 8 }}> {PRESET_COLORS.map(color => ( <div key={color} title={color} onClick={() => !readOnly && handleSelect(color)} style={{ width: 28, height: 28, borderRadius: '50%', background: color, cursor: readOnly ? 'default' : 'pointer', border: value === color ? '3px solid var(--card-focus-ring-color)' : '2px solid transparent', outline: value === color ? '2px solid white' : 'none', boxSizing: 'border-box', }} /> ))} </div> <input {...elementProps} type="text" value={value || ''} onChange={e => handleSelect(e.target.value)} placeholder="#000000 или rgb(0,0,0)" style={{ width: '100%' }} /> {value && ( <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 }}> <div style={{ width: 20, height: 20, background: value, borderRadius: 3 }} /> <span style={{ fontSize: 12 }}>{value}</span> </div> )} </div> ) } // Подключение в схеме defineField({ name: 'brandColor', type: 'string', components: { input: ColorPickerInput, }, }) Пример другого компонента: TagInput с автодополнением
Компонент предлагает уже добавленные теги, фильтрует по вводу и добавляет новые через кнопку Enter. Использует Patcher для гибкой работы с массивами: set, insert, unset. Поддерживает асинхронный поиск по API при дебаунсе 300 мс.
Почему кастомные Input Components лучше стандартных?
Кастомный компонент сокращает количество ошибок ввода на 80–90% по сравнению со строковым полем — редактор физически не может ввести некорректный цвет. TagInput с автодополнением ускоряет заполнение тегов в 3–4 раза. Кроме того, такие компоненты повышают удовлетворенность редакторов: они видят именно то, что ожидает система.
| Тип компонента | Пример поля | Сложность | Срок разработки |
|---|---|---|---|
| ColorPickerInput | brandColor |
Простая | 1 час |
| TagInput | tags |
Средняя | 3 часа |
| SlugWithPreview | slug |
Средняя | 2 часа |
| RegionSelect | region |
Высокая (API) | 5 часов |
| Требование | Стандартное поле | Кастомный Input |
|---|---|---|
| Валидация формата | Нет | Встроенная |
| Автодополнение | Нет | Да (через API) |
| Подсказки при вводе | Нет | Да |
| Скорость ввода | Медленно | Быстро |
Что входит в работу
- Разработка кастомных компонентов по вашему техническому заданию.
- Интеграция с существующей схемой Sanity.
- Документация по установке и использованию компонентов.
- Обучение редакторов работе с новыми полями.
- Поддержка в течение 2 недель после деплоя.
Наши инженеры имеют 10+ лет опыта с React и Sanity, поэтому каждый компонент проходит код-ревью и покрывается unit-тестами. Получите консультацию для оценки ваших задач.
Процесс работы
- Аналитика — определяем, какие типы ввода нужны, собираем требования к UI и валидации.
- Проектирование — рисуем прототип компонента, согласовываем с контент-менеджером.
-
Реализация — пишем React-компонент с использованием Sanity патчей (
set,insert,unset), тестируем на изолированном поле. - Интеграция — подключаем компонент к схеме, настраиваем стили под тему Studio.
- Тестирование — проверяем все состояния: пустое, заполненное, readOnly, ошибки.
- Деплой — компонент входит в сборку Studio, редакторы сразу видят новый интерфейс.
Сроки ориентировочно
Разработка 3–5 кастомных input компонентов — 2–3 дня. Срок может варьироваться в зависимости от сложности интеграции с внешними данными и необходимости анимаций. Стоимость рассчитывается индивидуально после анализа требований. Мы гарантируем прозрачное ценообразование без скрытых платежей.
Типичные ошибки и как их избежать
- Неправильная работа с readOnly — забывают проверять
readOnlyи позволяют редактирование. Решение: всегда оборачивайте обработчики вif (!readOnly). - Игнорирование патчей — используют
onChangeс произвольными значениями вместоset/unset. Санти ожидает строго определённые форматы. - Отсутствие дебаунса при запросах к API — при каждом нажатии клавиши уходит запрос. Используйте
useDebounceили AbortController.
Подробнее о создании кастомных компонентов читайте в официальной документации Sanity.
Свяжитесь с нами, чтобы обсудить ваш проект. Мы поможем ускорить и улучшить процесс контент-менеджмента с помощью кастомных Input Components.







