Промптинг для согласованного UI в React: как задать design tokens и правила компонентов, чтобы экраны генерировались с одинаковыми отступами, шрифтами и формами.

Когда вы просите модель сгенерировать новый экран, она каждый раз заново «угадывает» детали оформления. Идея и логика могут быть правильными, но внешний вид легко начинает напоминать другой проект. Причина простая: без общей системы правил модель опирается на типовые паттерны из обучающих данных, а не на стиль именно вашего продукта.
Расхождения обычно начинаются с мелочей, которые на одном экране почти незаметны, но рядом выглядят странно. На одном заголовок 24px и жирный, на другом - 20px и полужирный. Где-то радиус инпута 8px, где-то 12px. Кнопки «едут» по высоте, отступы между блоками становятся то 12, то 16, то 20.
Обычно расползание видно по таким признакам:
Проблема усиливается с ростом проекта. На 2-3 экранах можно «подровнять» вручную. На 10-20 экранах несоответствия множатся: вы копируете уже несовпадающие решения, правки расходятся по разным файлам, и через пару итераций команда спорит не о продукте, а о том, почему в одном месте кнопка 40px, а в другом 44px.
Хорошая новость: это реально стандартизировать так, чтобы не вычищать каждый файл руками. Для согласованного UI в React обычно достаточно зафиксировать две вещи: набор дизайн-токенов (масштаб отступов, типографика, радиусы, цвета) и правила использования компонентов (какие пропсы разрешены, какие состояния обязательны, какие размеры по умолчанию). Тогда при генерации нового экрана модель не «придумывает стиль», а следует источнику правды.
Если вы генерируете React-приложение в TakProsto, удобно держать эти правила рядом с проектом и каждый новый экран запрашивать с явной привязкой к ним. Так результат с первого раза будет ближе к вашему продукту.
Если генерировать React-экраны по отдельности, UI быстро начинает расходиться: отступы плавают, кнопки похожие, но не одинаковые, формы ведут себя по-разному. Надежнее держать два слоя контроля: сначала токены (что считается «нормой»), потом правила компонентов (как эту норму применять).
Design tokens - единый источник правды для базовых решений. Их удобно хранить рядом с темой (theme) и использовать и в CSS, и в компонентах. Обычно хватает токенов для цветов (primary/success/danger/text/background/border), типографики (семейство, размеры, жирность, высота строки), отступов и радиусов (шаг и набор значений), размеров контролов (высота input/button, брейкпоинты), теней и слоев.
Но одних токенов мало. Нужны правила компонентов: что можно делать, а что нельзя, чтобы никто не создавал новые варианты «по ситуации». Пример: кнопка не принимает произвольный padding, только size; поле ввода не меняет border-color напрямую, только через state.
Обычно фиксируют:
Третий элемент, который связывает все вместе, - шаблон экрана: контейнер, сетка, секции, заголовки. В промпте можно закрепить, например: «Используй PageLayout: maxWidth 1200, gap 24, заголовок H1 24/32, секции с H2 20/28, между секциями 32».
Отдельно стоит зафиксировать поведение форм: когда показываем ошибку, где текст подсказки, как выглядит disabled, как ведет себя loading. Практичный вариант: ошибка появляется после blur или submit; у поля один источник истины (react-hook-form или аналог); кнопка Save блокируется и показывает спиннер.
Если вы делаете генерацию в TakProsto, это удобно оформить как постоянный блок требований: сначала токены, затем список разрешенных компонентов и строгие правила состояний. Тогда промптинг для согласованного UI в React начинает работать как защита от «разных» экранов.
Когда экраны генерируются частями, UI часто расползается из-за мелких решений: тут отступ 14px, там 16px, где-то другой радиус и тень. Проще заложить компактный набор design tokens и запретить все остальное.
Начните с набора, который покрывает большую часть интерфейса и редко меняется:
С цветами не усложняйте. Достаточно нейтральной шкалы (gray-50…gray-900) и семантических цветов для статусов: success, warning, danger, info. Тогда кнопка «Удалить» и ошибка в форме будут одного «красного», даже если экран сгенерирован в другой день.
Полезно отдельно задать z-index и фиксированные высоты. Это быстро снимает конфликты между хедером, модалкой и тостами: у каждого слоя свой диапазон, а не случайные числа.
Смысл токенов в ограничениях. Если значений слишком много, генерация снова начнет придумывать свои размеры.
Простой пример, который удобно вставлять в промпт генерации экрана (и в конфиг темы):
export const tokens = {
space: { 0: 0, 1: 4, 2: 8, 3: 12, 4: 16, 5: 24, 6: 32 },
text: { sm: 12, md: 14, lg: 16 },
radius: { sm: 8, md: 12 },
z: { header: 10, modal: 100, toast: 200 }
};
Если вы генерируете React-экраны в TakProsto, такой блок токенов лучше держать «эталоном» и каждый раз просить использовать только эти значения. Тогда новые экраны будут выглядеть как один продукт, без ручной чистки.
Чтобы промптинг для согласованного UI в React работал без постоянной правки, библиотека компонентов должна быть не просто набором файлов, а набором правил. Иначе и модель, и человек будут «уточнять» стиль по-своему.
Начните с базового набора, который закрывает большинство экранов: Button, Input, Select, TextArea, Checkbox. Важно, чтобы они были единственным способом собирать формы и основные действия. Если в проекте есть два разных Input, согласованности не будет.
Дальше зафиксируйте варианты через пропсы, а не через новые компоненты. Обычно достаточно size (sm/md/lg) и variant (primary/secondary/danger). Вместо расплывчатого «сделай кнопку чуть меньше и темнее» у вас появляется конкретное: <Button size="sm" variant="secondary" />.
Обязательно пропишите состояния. Не только hover и disabled, но и focus, loading, error. Именно на них чаще всего «едет» визуальная система: разные спиннеры, разные подсветки фокуса, разные тексты ошибок.
Ключевое правило: внутри компонентов не пишем инлайн-стили для отступов и шрифтов. Ни style={{ padding: ... }}, ни случайные классы ради «подвинуть на 4px». Отступы и типографика идут из токенов и заранее разрешенных классов.
Документацию можно держать максимально простой: короткий файл с правилами лежит рядом с компонентом и читается за минуту. В TakProsto это удобно закреплять прямо в промпте генерации: «используй только компоненты из ui-kit и только разрешенные пропсы, без инлайн-стилей».
Перед тем как мерджить новые экраны, помогает короткий внутренний чеклист:
Когда экраны генерируются по отдельности, UI часто расползается не из-за цветов, а из-за ширины контента, случайных отступов и разной типографики. Поэтому полезно заранее зафиксировать базовую геометрию: контейнер, сетку и правила для повторяемых секций.
Начните с одного контейнера для всех экранов. Он задает max-width, боковые padding и базовый вертикальный шаг, из которого собираются отступы между блоками. Тогда новый экран не превращается в «другую верстку», даже если его делает другой человек или он сгенерирован в разные дни.
Чтобы генерация не придумывала размеры, удобно прямо назвать токены, которыми можно пользоваться. Например:
layout.containerMaxWidth = 1200px
layout.pagePaddingX = 24px
layout.sectionGap = 32px
layout.blockGap = 16px
grid.columns = 12
grid.gap = 16px
radius.card = 12px
shadow.card = md
Дальше добавьте простое правило: «Любой экран = контейнер + секции. Между секциями только layout.sectionGap, внутри секции только layout.blockGap».
Типографика должна быть одной шкалой размеров и одним набором правил жирности. Например: один размер для H1, один для H2, один для основного текста, один для подписей, и фиксированные веса (например, 600 для заголовков и 400 для текста). Запретите «полужирный где захотелось» и «+2px чтобы влезло».
Карточки и секции тоже лучше описать как стандарт: одинаковые радиусы, одинаковая тень (или ее отсутствие), одинаковые внутренние padding. Тогда разные по смыслу страницы выглядят как части одного продукта.
Для таблиц и списков заранее задайте единый стиль строк и пустых состояний. Достаточно договориться о высоте строки и вертикальных padding (только из токенов), одном типе разделителей, фиксированном hover/selected, и стандарте пустого состояния (заголовок, короткое объяснение, одно основное действие).
Если эти правила есть в промпте, модель реже изобретает новую сетку и типографику под каждый экран, а вы получаете предсказуемые макеты без ручной доводки.
Формы чаще всего «выдают» несогласованный UI: разные подписи, разные ошибки, разные состояния кнопок. Чтобы промптинг для согласованного UI в React работал без ручной правки, договоритесь о правилах формы так же строго, как о цветах и отступах.
Сначала зафиксируйте состав элементов поля. У каждого инпута всегда есть label (сверху), placeholder (только пример формата, не вместо label), helper text (под полем, когда все хорошо) и error text (в том же месте, заменяет helper). Если поле необязательное, это явно отмечается в label.
Дальше решите, когда показывать ошибки. Практичный вариант: до первого submit ошибки не показываем; после submit показываем для всех невалидных полей; затем для «тронутых» полей обновляем ошибку на onBlur. Так пользователь не видит красный экран с первой секунды, но и не теряется после отправки.
Формат сообщений тоже лучше унифицировать. Одна ошибка - одна короткая фраза без точек и без смены стиля: «Заполните поле», «Введите минимум 8 символов», «Неверный формат email».
Маски и форматы стоит описать заранее, иначе генерация будет плясать. Например: телефон хранится в E.164, но вводится как +7 (999) 999-99-99; деньги вводятся без копеек или с копейками (выберите одно); дата всегда ДД.ММ.ГГГГ и парсится в ISO.
Кнопка отправки должна вести себя одинаково: disabled, пока форма невалидна (после попытки submit) или пока идет запрос. При загрузке показывайте спиннер и сохраняйте текст кнопки, чтобы не «прыгала» ширина.
Серверные ошибки разделите на две группы: ошибки по полям (попадают в конкретное поле) и общая ошибка формы (плашка над кнопкой, одна строка). Например, «Неверный пароль» - у поля, а «Не удалось отправить, попробуйте позже» - общая.
Чтобы генератор экрана не ошибался, вставляйте в промпт короткий блок правил:
На TakProsto это удобно: один раз описали поведение, и дальше новые формы получаются похожими друг на друга без долгой «косметики».
Чтобы новый экран выглядел частью одного продукта, модели нужны два якоря: токены (цвета, типографика, отступы) и правила библиотеки компонентов. Это важнее, чем подробно расписывать тексты на странице.
Соберите ввод в три коротких блока: (1) токены, (2) правила компонентов, (3) структура экрана. Чем компактнее и конкретнее, тем меньше шансов, что модель начнет «творить» свои размеры.
ЗАДАЧА: сгенерируй один React-экран <ScreenName>.
1) DESIGN TOKENS (используй только их значения)
- colors: bg=..., surface=..., text=..., primary=..., danger=...
- spacing: xs=4, sm=8, md=16, lg=24, xl=32
- radius: sm=8, md=12
- typography: h1=24/32/600, h2=20/28/600, body=14/20/400
2) COMPONENT RULES (используй только готовые компоненты)
- Layout: <Page>, <Header>, <Section>, <Footer>
- Inputs: <TextField>, <Select>, <Checkbox>, <Button>
- Feedback: <Alert>, <InlineError>, <Spinner>
Правила: новые компоненты не создавать. Инлайн-стили не использовать.
3) SCREEN STRUCTURE (вертикальные отступы и порядок)
- Header: заголовок + вторичное действие справа
- Content: 2-3 секции, отступ между секциями = spacing.lg
- Footer: основная кнопка справа, вторичная слева
ОГРАНИЧЕНИЯ: без новых цветов, без произвольных размеров, без новых шрифтов.
ВЫВОД:
A) код одного экрана
B) список использованных компонентов и токенов
Чтобы снизить ручную чистку, заранее зафиксируйте запреты:
Пример: вы просите экран «Создать проект». В структуре указываете: хедер с названием, в контенте секция с названием проекта и выбором шаблона, ниже секция с доменом, в футере кнопки «Отмена» и «Создать». При таком промпте даже разные генерации будут держаться одной сетки, одинаковых отступов и одинакового поведения полей.
Даже если вы один раз настроили стиль, UI часто начинает расползаться после пары новых экранов. Обычно проблема не в модели, а в том, что правила допускают слишком много свободы.
Первая ловушка - слишком широкий набор значений. Если в токенах есть десятки размеров отступов, радиусов и шрифтов, на каждом новом экране появляются новые сочетания. В итоге расстояния между одинаковыми блоками начинают отличаться на 2-6px, и это заметно.
Вторая ошибка - отсутствие единых правил для форм. Когда не закреплены размеры полей, вид ошибок, подсказок и состояний (disabled, loading), один экран показывает ошибку под полем красным текстом, другой - рамкой и тултипом. Пользователь считывает это как разные продукты.
Третья проблема - компоненты без жестких вариантов. Если у Button, Input или Card нет ограниченного списка variant/size, модель начинает придумывать новые props и стили. Это особенно заметно, когда экраны генерируются кусками и «память» о прошлых решениях слабее.
Еще два источника хаоса:
Небольшой пример: вы сгенерировали страницу профиля и страницу настроек. На профиле кнопки 40px высотой, в настройках 44px, а в форме входа вообще 38px, потому что там «так лучше смотрелось». Через неделю вы правите это вручную в трех местах.
Чтобы это не повторялось, держите правило простым: у каждого базового компонента есть только несколько размеров и вариантов, а все состояния форм описаны заранее. В TakProsto удобно хранить это как короткий блок требований в промпте и обновлять его вместе с библиотекой компонентов, а не на каждом экране отдельно.
Перед мерджем полезно потратить 5 минут на осмотр UI. Это быстрее, чем потом вычищать «случайные» стили по всему проекту.
Проверьте экран по короткому списку:
Если нашли расхождение, не лечите симптом в конкретном экране. Сначала определите, где это должно жить: токен, вариант компонента или правило использования.
Пример: на новом экране поле ввода получилось высотой 44px, а в остальных 40px. Это почти всегда не «особенность экрана», а неправильный size или обход компонента. Поправьте usage и закрепите правило, чтобы следующий экран не повторил ошибку.
Представим три экрана: регистрация, профиль и список заказов. При генерации каждый из них часто получается «сам по себе»: где-то поля плотные, где-то растянутые, где-то кнопка круглая, а где-то прямоугольная. Исправлять руками долго, поэтому лучше заранее закрепить визуальный язык.
Для одинаковых отступов обычно хватает одного правила: используем только шкалу spacing из токенов и не придумываем новые значения. Например, между секциями всегда 24px, между полями 12px, внутри карточки 16px. Тогда регистрация, профиль и список заказов автоматически «склеятся» по ритму: заголовок, блок, поля, действия будут стоять одинаково.
С ошибками важно договориться один раз и повторять везде. Хороший паттерн: под полем показываем одно короткое сообщение (одна строка, один цвет, одинаковый размер шрифта), а общую ошибку формы (например, сервер не отвечает) показываем тостом. Так пользователю понятно, где исправлять, и UI не превращается в набор случайных предупреждений.
Кнопки Submit тоже должны быть одинаковыми: одна высота, один радиус, один вариант (например, primary), одна логика состояний (loading, disabled). Если на регистрации «Создать аккаунт» выглядит иначе, чем «Сохранить» в профиле, продукт воспринимается как собранный из разных частей.
Что прямо попросить в промпте, чтобы модель не меняла стиль (то, что обычно и подразумевают под промптингом для согласованного UI в React):
Если вы генерируете эти экраны в TakProsto, добавьте требование «не создавать новые компоненты и не менять токены». Тогда модель собирает интерфейс из уже согласованных деталей, а не из случайных решений.
Если токены и правила компонентов уже определены, следующий шаг - зафиксировать их так, чтобы команда (и генератор) не гадали каждый раз заново. Иначе согласованность снова будет держаться на внимательности и ручной правке.
Соберите все в один короткий документ на 1-2 страницы: какие токены есть, как их называть, какие компоненты можно использовать и какие состояния обязательны. Такой документ реально читать и обновлять.
Дальше введите правило процесса: новые экраны появляются только через единый шаблон промпта. В нем должны быть токены, список разрешенных компонентов и несколько четких запретов (не задавать отступы числами, не использовать произвольные шрифты, не добавлять новые цвета).
Минимальный план на ближайшие 1-2 дня:
Чтобы токены не разрастались, полезна короткая ревизия, например раз в две недели: удаляйте дубликаты, объединяйте близкие значения, добавляйте новые только при реальной необходимости. Хороший признак - вы чаще переиспользуете существующее, чем добавляете новое.
Если вы ведете проект в TakProsto (takprosto.ai), удобно закрепить токены и правила как базовые требования в planning mode: вы обновляете стандарт один раз, а затем просите генерацию следовать ему для всех новых экранов. При необходимости изменения можно проводить через план, а откат делать через snapshots и rollback.
Чаще всего потому, что у модели нет «источника правды»: на каждом экране она заново выбирает размеры, отступы и варианты компонентов.
Самые заметные причины:
Достаточно закрепить два слоя:
Если эти два блока всегда присутствуют в запросе на генерацию, новый экран перестает «изобретать стиль» и начинает повторять систему.
Хороший стартовый минимум:
Пиксели «на глаз» почти всегда становятся источником расхождений (14/18/22 и т. п.).
Практичный запрет:
tokens.spacetokens.typographytokens.radius/tokens.shadowЕсли нужно «чуть больше/меньше», добавляйте новый токен осознанно (и лучше редкими крупными шагами, чем десятками значений).
Зафиксируйте для каждого базового компонента:
И отдельно правило использования:
Один понятный стандарт закрывает 90% случаев:
Шаблон экрана — это фиксация геометрии:
Когда в запросе явно указано: «экран = контейнер + секции; между секциями только X; внутри секции только Y», генерация реже меняет ширины, гэпы и размеры заголовков.
Удобный порядок такой:
И добавьте явные запреты: «без новых цветов», «без произвольных px», «без новых шрифтов». Чем короче и конкретнее — тем стабильнее результат.
Чеклист на 5 минут:
Если нашли расхождение — фиксите не экран, а правило: токен, вариант компонента или usage-гайд.
В TakProsto удобно сделать так:
Так вы быстрее получаете экраны, которые выглядят согласованно, и меньше тратите время на ручную косметику.
Главное правило — не добавлять «почти такие же» значения.
Тогда любой экран собирается из ограниченного набора деталей и не расползается.
Это снимает хаос, когда на разных экранах ошибки «живут» в разных местах и выглядят по-разному.