
Кто я и почему пишу
Привет, Хабр! Меня по-прежнему зовут Сергей Орлов, я разработчик в Dodo Engineering и лидер дизайн-системы Android в приложении Пиццы. Это моя прощальная статья в Додо – про то, как мы заводили дизайн-систему, где наступили себе на ногу и что из этого вышло.
Сразу предупрежу, чего в статье не будет. Это не гайд по токенизации проекта и не правила написания компонентов – такого добра в сети хватает. Это рассказ про грабли: какие мы нашли, как их обходили и что бы я сделал иначе.

До Додо я строил дизайн-системы в Мегафоне и Магните – причем с двух сторон: в одной компании пилил компоненты, в другой пользовался ими как клиент из фичевой команды. Опыт с обеих сторон баррикады оказался полезнее, чем я думал: половина проблем в ДС возникает ровно потому, что тот, кто делает компонент, не представляет, как с ним потом жить.
Поэтому на собеседовании в Додо я спросил, есть ли у них дизайн-система. Мне ответили, что нет.
Как выяснилось позже, ответ был не совсем точный. Но об этом чуть ниже.
Как мы дошли до жизни такой
Я пришел в Додо, когда готовился редизайн всего приложения. Честно говоря, он был нужен – просто посмотрите.

Меню приложения: слева до редизайна, справа сейчас
Если вам есть что сказать про дизайн приложения – велком в комментарии или в телеграм-канал наших дизайнеров designdodo. Троллей там тоже любят, так что не стесняйтесь.
Немного цифр для масштаба. В приложении Пиццы около 60 полноэкранных экранов, плюс порядка 40 диалогов и шторок. Считать элементы на всех этих layout’ах я не стал: боюсь, надоест, либо закончатся токены.
Перерисовать все это нужно было быстро, итерационно и так, чтобы к концу пути приложение оставалось однородным, а не превратилось в лоскутное одеяло из экранов разных эпох и локальных компонентов. Тут на сцену и выходит дизайн-система.
С чем мы столкнулись и что будет в этой статье
Почему общий модуль компонентов – это еще не дизайн-система. Разбор на примере соседней платформы, где модуль живет с 2020 года и спокойно содержит пять реализаций одного контрола.
Как отличить компонент дизайн-системы от компонента фичи. Мы не отличили – и получили две кнопки, которые подменяли друг друга по всему приложению.
Паспорта компонентов. Спека, где дизайн и разработка договариваются до того, как написана первая строка кода. Что в ней есть и почему это документ для разработчика, а не бюрократия дизайна.
Как раздать разработку компонентов всем командам. Когда на платформу приходится один человек с ДС и десять с фичами, других вариантов нет. Процесс, схема, что сломалось при внедрении.
Как объяснить бизнесу, что ускорение сначала тормозит. Работает не объяснение, а цена: компонент надо сделать дешевле в спринте.
Скриншот-тесты на компоненты. Что покрыли и почему для ДС они дешевле, чем кажется.
Генерация компонентов нейронкой и пять слоев защиты вокруг нее. Что скармливаем на вход, что она стабильно делает плохо, и почему без предыдущих шести пунктов это не работает.
Дальше будет код, схемы и признания в собственных косяках. Если такое заходит – я про это регулярно пишу в своем телеграм-канале https://t.me/orlovsdev
Почему просто вынести компоненты в общий модуль недостаточно
Первой моей задачей в Додо была фича «курьер на карте». Я открыл макет, открыл проект и понял, что собирать экран не из чего.

Точнее так: собирать было из чего, и в этом заключалась проблема. Чтобы понять масштаб, достаточно посчитать, сколько в проекте было кнопок. Один класс-наследник MaterialButton, две кастомные View с «Button» в имени, пять самостоятельных Compose-кнопок в разных модулях, 28 XML-стилей кнопок и 14 layout-файлов, где кнопка собрана руками из кликабельного контейнера и TextView.
Такая копипаста заводится не от лени, а от отсутствия дешевой альтернативы. Когда общего компонента нет, у разработчика два пути: собрать кнопку заново с нуля или скопировать ту, что уже работает в соседней фиче другой команды. Второй быстрее и надежнее – поэтому чаще предпочтительнее.
Так получилось, например, с экраном фидбека – кнопка, которая лежала в двух модулях побайтово одинаковая, а один блок разметки кнопки повторялся в семи файлах пяти модулей, отличаясь только id и text.
<Button android:id="@+id/buy_more_add_to_cart" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/buy_more_add_to_cart" style="@style/PrimaryButton" />
Цена такого решения заметна не сразу. Любое изменение кнопки приходится вносить в семи местах, предварительно найдя все ее копии – и ты никогда не уверен, что нашел все.
Второй путь – не копировать, а брать чужой компонент напрямую – выглядел правильнее, но выходил дороже. Пятнадцать кастомных View стояли на экранах чужих модулей. Рекордсмен – ExpandableFoodValueInfoIconView (раскрывающаяся плашка с составом продукта) из модуля order, он попал в восемь чужих экранов.
Берешь компонент соседней команды, через две недели владельцы правят его под свою задачу – и у тебя едет верстка на экране, о котором они не знали. Формально мы переиспользовали код. Фактически подписывались на чужие релизы.
Ни один из двух путей не ведет к системе. Копипаста позволяет команде не зависеть от чужого кода, но плодит копии одного и того же. Переиспользование чужого компонента убирает дублирование, но связывает команды общей реализацией. Иначе говоря: копипаста дает изоляцию без переиспользования, чужой компонент – переиспользование без изоляции. Дизайн-система нужна ровно затем, чтобы появился третий вариант: компонент, у которого есть владелец и контракт.

Онбординг стоит дороже, чем кажется
Compose меняется быстро и порой радикально – это все мы знаем. Из-за этого практики написания UI на проекте живут в головах, а не в коде.
Представьте нового человека на проекте, где есть Compose без ДС-обертки, а местами еще и View. Чтобы написать первый экран, ему нужно выяснить, как у вас принято собирать компоненты, найти похожие в коде, прочитать их реализацию и понять, какая из трех найденных версий правильная. Это не день и не два.
Задайте себе этот вопрос, когда будете думать про дизайн-систему. Именно про систему, а не просто про набор компонентов – почему второе тоже плохо, расскажу ниже.
У нас к этому добавлялось еще и то, что верстали мы на View. С каждым новым наймом было видно, как экспертиза в нем падает: люди приходили из проектов на Compose, для них наш основной инструмент был легаси. Мы не деградировали – просто нанимали в технологию, которая для рынка уже прошлое.
Модуль есть, системы нет
Копипаста, размазанная по пяти модулям, зависимость от чужих компонентов, неделя на экран, долгий онбординг – рано или поздно разработчики приносят это на синк и просят завести дизайн-систему. Но бизнес не всегда может дать добро сразу: нет людей, есть другой приоритет, причин много.
И тут возникает соблазн: сделать свой техпак с компонентами и заставить всех их использовать. Задайте себе вопрос – это решит проблему или замаскирует ее?
У коллег с iOS такой модуль был: живой, с 2020 года, много тысяч строк кода. При этом внутри него уживались пять реализаций одного сегмент-контрола, а карточка продукта существовала в трех вариантах. То же самое, что у нас на Android, только сложенное в один модуль вместо разбросанного по проекту.
Проблема не в компоненте. Он может быть идеальным, написанным по всем лекалам.
Дизайн-система – это не только код. Это еще и договоренность между людьми.
Если вы договорились внутри своей команды, но не сказали дизайнерам и не построили с ними общий процесс – вы обрекаете себя копировать с мелкими изменениями собственные же эталонные компоненты.
Как отличить компонент ДС от компонента фичи
У нас эта договоренность появилась. Дизайн и разработка сели вместе, дизайн-систему завели официально, первый компонент приехал в проект.
А через 24 дня мы сами же положили рядом с ним второй, который дизайн-системой не был.

Первый компонент
Первым нашим компонентом логично стал самый используемый элемент любого приложения – кнопка. Та самая оранжевая кнопка, которую вы можете видеть по всему нашему приложению.
@Composable fun DComposeButton( onClick: () -> Unit, text: String, buttonSize: ButtonSizesData, colors: ButtonColorsData, modifier: Modifier = Modifier, enabled: Boolean = true, isProgress: Boolean = false, imageData: ImageData? = null, )
Сразу оговорюсь: восемь параметров подряд – это нарушение нашего же правила. Компонент должен принимать data class с параметрами, чтобы расширяться через него, а не через правку сигнатуры. На старте мы этого не сделали – и за два года кнопка обросла параметрами до неприличия, пока мы не завезли DButtonState. Правило, кстати, родилось именно отсюда.
Три состояния, четыре размера, пять цветовых стилей. Архитектура сразу двухслойная: композабл плюс AbstractComposeView поверх – чтобы кнопку можно было ставить в существующие XML-лейауты и не переписывать экран целиком ради одной кнопки. Позже от этого подхода мы отказались, и сейчас так устроена только эта кнопка. В тот же день появился сторибук для нее, про него расскажу ниже.

Через 24 дня
Мы совершили ошибку, которая стоила нам дорого и до сих пор живет в проекте. Мы добавили ProductButton.

Я лично боролся с этим, но моих аргументов в тот момент оказалось мало. Не всегда один в поле воин, даже если дизайн-системой скроен.

Написали мы его не как обертку над DButton, а как самостоятельный компонент, который вызывает Button из Material3 напрямую:
val buttonSize = DButtonSizes.large.copy( contentPadding = PaddingValues(horizontal = 20.dp, vertical = 8.dp) ) Button( // material3, не DButton onClick = onClick, shape = RoundedCornerShape(percent = 50), colors = colors.getButtonColors(), ) { when (price) { is ProductPrice.SimplePrice -> { /* иконка + цена */ } is ProductPrice.PersonalPrice -> { /* старая цена дугой + новая */ } is ProductPrice.CoinsPrice -> { /* валюта + курсив + додокоины */ } is ProductPrice.EditedSimplePrice -> { /* заголовок + цена мельче */ } is ProductPrice.EditedCoinsPrice -> { /* заголовок + валюта и коины */ } } }
От ДС он взял ровно два объекта-токена – размер и цвета, причем размер тут же пропатчил через .copy().
И это было понятное решение. Часто время выигрывает у аргументов. В итоге с этой болью должны были столкнуться все, чтобы понять неверный путь этого компонента. ProductButton умел то, чего DButton не умел: зачеркнуть старую цену дугой, показать две строки, смешать типографику внутри одной подписи, вывести цену в рублях и додокоинах сразу. Подзаголовок в DButton появился только через девять месяцев.
Так у нас образовались две кнопки: одна из дизайн-системы, вторая из фичи, и вторая умела больше.
Чем это кончилось
Дальше произошло ровно то, что должно было. В макет просится DButton, но нужного состояния у него нет – а у ProductButton есть. Берем ProductButton. В компонент цены начинают доливать «просто текст»: состояние с произвольным заголовком, состояние с подписью под ценой.
Кончилось это вот таким кодом в конструкторе комбо:
if (screenState.selectedProduct != null) { ProductButton( modifier = Modifier.width(250.dp), productPrice = ProductPrice.PriceWithComment(/* ... */), ) } else { DButton( modifier = Modifier.size(width = 250.dp, height = 52.dp), ) }
Один слот на экране. Две разные кнопки. Выбор через if.
Правило, которое из этого выросло
Фича зависит от ДС, а не наоборот.
Если компоненту фичи не хватает состояния из дизайн-системы – это заявка на доработку компонента ДС, а не повод написать свой. Проверка простая: посмотрите, где лежит код и на что он ссылается. Компонент ДС не знает ничего о фиче. Компонент фичи может брать из ДС что угодно.
Проблема в том, что различить это надо до того, как написан код. Через восемь месяцев, когда компонент уже в проде и оброс состояниями, «просто переписать» стоит дороже, чем оставить как есть, – что мы и продемонстрировали.
И еще одна проблема, которая для меня оказалась важнее. Правило само по себе не работает, пока оно живет в голове одного человека. Нужен был механизм, который делает его общим и предъявляемым – не «мне кажется», а «смотрите, вот здесь не сходится».
Так у нас появились паспорта.
Паспорта компонентов и сторибук
Паспорт – это спецификация компонента, о которой дизайн и разработка договариваются до того, как написана первая строка кода. Название прижилось само.
Живет он в Figma, отдельной страницей на компонент, имея секции для дизайнеров и разработчиков. Внутри секции разработчиков живут подсекции для Android и iOS.


Зачем паспорт разработчику
Он дает готовый прообраз API, который удобно скормить в том числе нейронке, об этом ниже.
До паспортов все это выяснялось по ходу: сверстал, отдал на приемку, получил замечания, переделал. После – требования к компоненту известны до начала разработки.
Заполняет паспорт дизайнер, но принимаем мы вместе: на пятничном синке лиды ДС смотрят его и предлагают правки. Мы, как разработчики, приносим гайдлайны платформы, дизайнеры приносят замысел.
Помните спор про ProductButton, где у меня был правильный аргумент и не было инструмента? Мы просто положили рядом два паспорта – обычной кнопки и продуктовой – и увидели, что по составу это один и тот же компонент. Спорить стало не о чем: паспорт превращает мнение в аргумент.
Правила написания компонентов
Паспорт отвечает на вопрос «что делаем», правила разработки – на вопрос «как».
Правила лежат у нас во внутренней вики. Там зафиксировано, как должен быть устроен компонент:
только токены, никаких захардкоженных цветов и размеров;
состояние типизировано через sealed interface, а не через набор булевых флагов;
дефолты вынесены в отдельный объект;
компонент stateless и ничего не знает про заказ, корзину и тоглы;
опциональный контент передается слотом, а не тремя параметрами.
Антипример здесь – реальный код нашего DButton. Правило написано по следам собственной ошибки.
Сторибук: место, где компонент становится видимым
Паспорт живет в Figma, компонент – в коде, и между ними нужно место, где можно потрогать результат. У нас это сторибук: экран в дебажной сборке, где каждый компонент лежит отдельным пунктом и все его параметры переключаются прямо в UI.
Дизайнеру он нужен, чтобы не искать компонент по экранам приложения – приемка проходит именно там. Разработчику – чтобы увидеть, что уже сделано и в каком объеме.
Экран в сторибуке у нас обязательный шаг, а не опция: пока компонента нет в песочнице, следующий разработчик о нем не узнает и напишет свой.

Дизайнеры первое время забывали заполнять паспорта, разработчики не рвались делать компоненты вместо фичевых задач. Механизм появился, а привычки не было. Ни то ни другое документом не лечится – как чинили, дальше.
Нас двое на две платформы
Механизм появился, а рук не прибавилось. И я знал это с самого начала, так как опыт имелся. Дизайн-системой занимались два человека – я на Android и коллега на iOS. На двоих приходилось около 20 фичевых разработчиков на двух платформах, редизайн всего приложения и библиотека компонентов, которую надо было довести до кода целиком.
Вариант «мы вдвоем все напишем, а команды будут пользоваться» отпал сразу. Даже если бы мы успели – это ровно тот bus factor, из-за которого дизайн-системы и умирают: два человека уходят, и система остается без хозяина.
Поэтому мы сели вдвоем и накидали процесс, в котором компонент делает тот, кому он понадобился.

Логика простая. Когда в фиче появляется компонент дизайн-системы, разработчик проверяет паспорт: существует ли он вообще и описаны ли в нем нужные состояния. Если чего-то не хватает, додумывать поведение на месте нельзя – вопрос уходит в общий канал к владельцам ДС и ответственному дизайнеру.
Когда паспорт на месте, решение зависит от того, что уже есть в коде и сколько времени в спринте:
Ситуация | Кто делает | Что происходит |
|---|---|---|
Компонент реализован, состояний хватает | Разработчик фичи | Просто берет и использует |
Компонента нет или не хватает состояний, времени нет | Владельцы ДС | Задача передается им: актуализируют документацию, дописывают компонент и подключают его в фичу. Не «сделай как-нибудь у себя», а именно передача |
Компонента нет, но время есть | Разработчик фичи | Приходит к владельцу платформы, показывает фичу и свое решение – кодом или хотя бы мыслями. Владелец валидирует |
Если зафиналить общее решение не получилось, договариваетесь, как реализовать по месту. Важно, что это остается осознанным исключением – и осознанным техническим долгом, а не самодеятельностью.
Хвост процесса общий для всех веток: разработка по паспорту и требованиям из вики, обязательное добавление в сторибук, потом два ревью – владельца ДС со стороны разработки и дизайнера. Замечаний нет – раскатываешь фичу.
В итоге мы получили не только дополнительные руки. Компоненты перестали быть чьей-то личной территорией, а разработчики получили задачи вне фичевой рутины. Плюс каждый, кто прошел процесс хоть раз, дальше сам замечает в макете компонент ДС.
Фича важнее компонента
Первое время разработчики делали компонент не целиком. Прилетел макет, в нем нужны два состояния из семи – два и написали. Формально компонент в дизайн-системе есть, фактически он дырявый, и следующий человек снова упирается в «нужного состояния нет».

Это логичное поведение, а не саботаж: у разработчика в спринте фича, а не дизайн-система.
И тут мы уперлись в то, во что упирается любая ДС. Продуктовые задачи всегда важнее, потому что они приносят деньги сейчас. Компонент целиком стоил 3–5 сторипоинтов – это заметный кусок спринта, и его старались срезать до тех состояний, без которых фича не поедет.
Объяснить бизнесу, почему штука, которая должна ускорять разработку, сначала ее тормозит, – задача со звездочкой. Но суть любых переговоров – это найти компромисс. С моей стороны родилась идея сделать компонент дешевле. Как? Пишу ниже.
Как мы сделали компонент дешевле
Компонент стоил 3–5 сторипоинтов, и это была честная оценка. Написать восемь состояний, покрыть превью, добавить в сторибук, пройти два ревью – работы там действительно на несколько дней.
Значит, снижать нужно было не оценку, а объем ручной работы.
Прежде чем генерировать – научились проверять
Скриншот-тесты на ДС-компоненты мы завезли недавно, и поначалу это выглядело как обычная гигиена: ну покрыли, ну молодцы.
Механизм – Compose Preview Screenshot Testing: тест не описывает верстку сам, а переиспользует @Preview-функции из файла компонента.
class DButtonComposeScreenshotTests { @PreviewTest @Preview("Light") @Preview( "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL ) @Composable @VisibleForTesting private fun Preview1() { DButtonPreview() } }
Для дизайн-системы это почти бесплатное покрытие. Превью у компонентов и так обязательны по нашим же правилам, тесты гоняются на хосте без эмулятора, эталоны лежат рядом с кодом. Сейчас в ДС-модуле 23 файла тестов и 115 эталонных картинок.
Честно про цену: плагин до сих пор в статусе экспериментальной альфы, и мы это понимали, когда заводили.
Зачем эта сетка понадобилась на самом деле, стало понятно через полтора месяца.
А что, если бойлерплейт просто сгенерировать?
Я взял шторки – DBottomSheet и DContentBottomSheet – и попробовал сгенерировать их нейронкой.
Смысл был не в том, чтобы «ИИ написал за меня компонент». Смысл в том, что в компоненте дизайн-системы огромная доля работы – это бойлерплейт: разложить состояния, развесить токены, собрать Defaults, написать превью на каждый вариант. Все это выводится из паспорта механически.
Эксперимент получился. Дальше я рассказал о нем на общем синке команд – и подход разошелся по командам сам.
Нейронке нельзя оставлять выбор
Главный принцип: снять все вопросы до начала генерации, чтобы модели нечего было додумывать.
Макет из Figma через MCP, фреймами.
Паспорт компонента – состояния, размеры, стили, правила поведения.
Правила и ограничения из нашей вики – как писать компоненты на нашем проекте.
Эталонный компонент как образец стиля.
Все это упаковано в скилл, чтобы не собирать контекст руками каждый раз.
Отдельная работа шла на стороне дизайна. Мы договорились с дизайнером, отвечающим за ДС, что паспорта адаптируются под это: никаких скрытых компонентов, никаких неявных дизайнерских хуков, состояния проработаны детально – так, чтобы вопросов не было ни у человека, ни у машины. Неоднозначные места сначала были, мы их вместе вычистили.
Побочный эффект оказался приятным: паспорта от этого стали лучше и для людей тоже.

Что нейронка делает плохо
Переизобретает то, что уже есть. Внутри нового компонента пишет свою кнопку вместо готовой, хардкодит значение вместо токена – при том, что токены лежат в контексте.
Иногда лепит булевы флаги вместо типизированного состояния. Бывало нечасто, но бывало – то есть ровно та ошибка, из-за которой мы намучились с ProductButton, только теперь ее предлагает машина.
Превью не пишет вообще, пока не ткнешь носом. Для Compose это база, любой разработчик их пишет по умолчанию – а модель их пропускает, и ее приходится отдельно вести по всем состояниям из паспорта. И это не косметика: без полного набора превью не работают скриншот-тесты, то есть молча ломается покрытие.
Выедает токены на больших компонентах. ДС – не единственная тема на проекте, контекст приходится делить.
Требует перепроверки. Модель регулярно продолжает следовать своим представлениям о прекрасном, даже когда в контексте лежат ваши правила.
Ошибаться можно. Дорого ошибаться – нельзя
Именно поэтому генерация работает не сама по себе, а внутри всего, что мы построили до нее:
Паспорт – что именно должно получиться.
Правила и эталонный компонент – как это писать у нас.
Скриншот-тесты – регрессия ловится автоматически, а не глазами на ревью.
Сторибук – дизайнер принимает компонент руками.
Ревью – нейронкой и людьми. Состязательное ревью моделью работает неплохо: ошибается, но базу собирает хорошо. Поверх этого код смотрит разработчик, и я как лид отдельно прохожусь по компонентам. Здесь важно, что цена ошибки уже не та: если фича в проде, значит критических багов по ней нет, а поправить код компонента – не проблема. Все обложено тестами, и если новый компонент что-то сломает в фиче, мы это отловим.
Собственно, в этом и смысл всех пяти слоев. Не в том, чтобы нейронка не ошибалась, – она будет. А в том, чтобы ошибка стоила дешево и находилась до пользователя.
Нейронка убирает бойлерплейт. Знание, как это должно быть устроено, живет в разработчике.
Кстати, тут хорошо видно, как меняется работа программиста. Программировать все еще нужно уметь – иначе вы просто не заметите подставу. Но большая часть времени теперь уходит не на написание, а на проверку за машиной.
Выгода для бизнеса
Компонент стал стоить 2 сторипоинта стабильно вместо прежних 3–5.
Команды перестали срезать компоненты. Раньше в спринте выбирали между фичей и компонентом, теперь компонент помещается рядом с фичей – и его берут целиком.
Я не объяснял бизнесу, почему ускорение сначала тормозит. Я сделал компонент дешевле, и он объяснился сам.
Дальше стало возможным то, о чем раньше не заходила речь: мы поставили целью довести до кода все компоненты, уже готовые в Figma, и распределили их по командам – по тому, чьи модули и контуры они затрагивают и у кого какая загрузка.
Где мы сейчас
Цифры на август 2026 года:
34 компонента в дизайн-системе, 31 из них готов на Android – 91%
34 экрана компонентов в сторибуке плюс 5 экранов основ: типографика, цвета, градиенты, анимации, вибро
23 файла скриншот-тестов и 115 эталонных картинок в ДС-модуле
ДС-модуль импортируют 479 kt-файлов. На старте их было 29

Дашборд появился не сразу и оказался нужнее, чем ожидалось. Там видно готовность по обеим платформам и тренд по времени – без него вопрос «а это уже сделано?» решался поиском по коду и опросом коллег.
На скрине видно разрыв: Android 91%, iOS 53%. Дело не в том, что коллеги медленнее – им прилетело жидкое стекло, и это переписывание половины UI под новую систему оформления, а не «доделать компонент». Мы в это время спокойно шли по своему бэклогу. По графику тренда, кстати, хорошо видно, что кривая iOS не встала, а продолжает расти – просто с другим стартом.
Что можно сделать лучше
Дизайн-система растет вместе с проектом, и работы в ней всегда хватает. Что напрашивается дальше:
Структурированное версионирование. Сейчас версия живет в паспорте, со стороны разработки процесс еще не до конца обточен. Это связано с тем, что у нас еще молодая ДС.
Дашборд пошире. Хочется видеть покрытие глубже.
Больше скиллов и обвязки вокруг генерации, чтобы завести компонент стоило еще дешевле.
Это не список долгов, а нормальное состояние живой системы. Если бы делать было нечего – значит либо продукт не развивается, либо ДС от него отстала.
Вместо заключения
Дизайн-система остается. Не как код в репозитории, а как процесс, который работает без меня: есть паспорта, есть правила, есть люди в каждой команде, которые проходили этот путь и знают, как делать компонент.
Собственно, ради этого мы и раздавали разработку компонентов всем командам. Тогда bus factor был аргументом из презентации. Теперь он проверился на мне – и это, пожалуй, лучший результат из всех, что перечислены выше.
А я продолжаю писать про разработку в своем телеграм-канале – заходите, там про то, что происходит дальше: https://t.me/orlovsdev
Если у вас было по-другому – расскажите в комментариях. Особенно интересно, как это устроено у тех, кто заводил дизайн-систему в проекте с большим легаси.

