Розробка кастомних 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. Sanity очікує строго визначені формати. - Відсутність дебаунса при запитах до API — при кожному натисканні клавіші йде запит. Використовуйте
useDebounceабо AbortController.
Детальніше про створення кастомних компонентів читайте в офіційній документації Sanity.
Зв'яжіться з нами, щоб обговорити ваш проект. Ми допоможемо прискорити та покращити процес контент-менеджменту за допомогою кастомних Input Components.







