<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Мыслью по древу</title><generator>teletype.in</generator><description><![CDATA[Мысли про дизайн, технологии в дизайне, управление дизайнерами, около-дизайн и совсем не дизайн. 

Автор канала: Сергей Мухин. Арт-директор.]]></description><image><url>https://img2.teletype.in/files/11/79/1179707e-2f61-4006-96cd-543225b43b31.png</url><title>Мыслью по древу</title><link>https://teletype.in/@uxflow</link></image><link>https://teletype.in/@uxflow?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=uxflow</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/uxflow?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/uxflow?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sat, 27 Jun 2026 11:19:58 GMT</pubDate><lastBuildDate>Sat, 27 Jun 2026 11:19:58 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@uxflow/Yie_nNZKaYF</guid><link>https://teletype.in/@uxflow/Yie_nNZKaYF?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=uxflow</link><comments>https://teletype.in/@uxflow/Yie_nNZKaYF?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=uxflow#comments</comments><dc:creator>uxflow</dc:creator><title>Наследуемые свойства в SDUI платформе ВкусВилл. Часть 2: Активность</title><pubDate>Mon, 01 Apr 2024 12:34:21 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/aa/37/aa374d06-8bab-446a-a504-2552a1e66970.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/dc/7f/dc7fb4d8-0998-4faf-9c90-b0faa09458e5.png"></img>В предыдущей части я пытался разобрать с проблему сокращения контракта в SDUI приложении, а также поговорить о контекстах — одном из наследуемых свойств нашей платформы для дизайна, которое призвано решить эту проблему. Теперь же настала очередь ещё одной группы наследуемых свойств, которые кардинально меняют подход к работе с состояниями и отвечают за активность виджетов.]]></description><content:encoded><![CDATA[
  <figure id="6sHq" class="m_column">
    <img src="https://img2.teletype.in/files/dc/7f/dc7fb4d8-0998-4faf-9c90-b0faa09458e5.png" width="772" />
  </figure>
  <p id="Hwpu">В <a href="https://teletype.in/@uxflow/MangoContext" target="_blank">предыдущей части </a>я пытался разобрать с проблему сокращения контракта в SDUI приложении, а также поговорить о контекстах — одном из наследуемых свойств нашей платформы для дизайна, которое призвано решить эту проблему. Теперь же настала очередь ещё одной группы наследуемых свойств, которые кардинально меняют подход к работе с состояниями и отвечают за активность виджетов.</p>
  <p id="AKtC">Но сначала хотелось бы отступить чуть назад. После выхода предыдущей части я получил обратную связь, что тема слишком сложна и не всё достаточно полно удалось раскрыть, поэтому давайте сделаем ещё сложнее 😁</p>
  <h2 id="dBgt">Из чего состоят виджеты платформы</h2>
  <p id="65ru">Для начала сразу определимся, что типичные атомарные структуры, такие как атом, молекула и организм, мы оставим для дизайн-системы. Сейчас мы поговорим о составе виджетов в контексте нашей дизайн-платформы. На основе этих виджетов уже можно создать более-менее традиционную дизайн-систему с кнопками и панелями. Наша платформа не использует такие термины, и понятия “кнопка” еще не существует на данном уровне абстракции.</p>
  <p id="qTCb">А что есть? А есть платформенные виджеты. В нашем случае существует четыре категории таких виджетов:</p>
  <ol id="QOJ7">
    <li id="g2R1"><strong>Примитивы </strong>— Суперпростые нефункциональные виджеты. Сюда входят вывод текста, иконки, картинки, свитчер слайдер и т. д.</li>
    <li id="CxIR"><strong>WidgetWrapper </strong>— это по сути аналог frame из фигмы. Умеет как верстать виджеты внутри себя, задавать отступы, gap и т. п., так и окрашивать себе фон, обводку, менять скругления углов, управлять собственным позиционированием.</li>
    <li id="aQYK"><strong>Пресеты</strong> на клиенте. Это те сущности, которые по каким-то причинам нельзя «собрать» на виджетах из пункта 1 и 2. Например, контейнеры всплывающих окон, карта, списки и сетки, контейнер webview.</li>
    <li id="PimW"><strong>Экран </strong>— контейнер со спец. слотами, всегда является корневым для верстки экрана приложения.</li>
  </ol>
  <p id="GFUL"><strong>Важные особенности:</strong></p>
  <p id="JwDo">— За взаимодействие всегда отвечает WidgetWrapper. Он поддерживает различные типы взаимодействия, такие как: “статичный” (без взаимодействия), “нажми на меня” (фактически превращает в кнопку), “выдели меня” (checkbox), “выбери один из” (radio).</p>
  <p id="kpCY">— Виджеты из 1-й группы не являются интерактивными сами по себе. Например, чтобы тот же переключатель мог переключаться, его необходимо обязательно поместить в WidgetWrapper с подходящим типом интерактивности.</p>
  <p id="3T4g">— Визуализация взаимодействия также осуществляется WidgetWrapper, причем универсальным методом (пока это наложение цвета). Т. е. далее в виджетах нам не нужно прорисовывать hover, press и disable, всё делается платформой автоматически.</p>
  <p id="FDti">— Все свойства настраиваются прямо в фигме. <strong>Верстка выгружается в приложение автоматически. </strong>Разработчику остается только приделать бизнес-логику к готовым шаблонам.</p>
  <h2 id="AD4B">Свойство active</h2>
  <p id="QoPz">Важно запомнить, что это не то же самое, что и одноименные псевдокласс и свойство в CSS. В этом случае имеется в виду абстрактная “активность”. Активный виджет может быть интерпретирован по-разному: выбранный checkbox, активная вкладка, кнопка фильтров с активными фильтрами..</p>
  <p id="07sE"><strong>Как это работает</strong></p>
  <p id="FKnH">У WidgetWrapper и примитивов есть свойство active, которое может принимать значения true или false. Также существует логическое свойство active-inherit, которое, если установлено в true, делает свойство active данного виджета наследуемым от родителя.</p>
  <p id="SRGw">У свойства active есть зависимые свойства. Например, active-background у враппера, active-icon у примитива IconBox и т.п. Даже есть active-context (привет<a href="https://teletype.in/@uxflow/MangoContext" target="_blank">первой части</a>).</p>
  <p id="6O1q">Тут также важно сказать, что хоть дизайнер и настраивает все эти свойства, active управляется не из макета (верстки) а бизнес-логикой (с сервера).</p>
  <h2 id="qkrR">Примеры</h2>
  <p id="wKWt">Ну что, достаточно теории, давайте посмотрим, как всё это работает на практике.</p>
  <p id="hipC"><strong>Пример1. Кнопка</strong></p>
  <p id="l9W0">Чтобы собрать кнопку, нам потребуется WidgetWrapper, виджет иконки и виджет текста. Собираем, настраиваем параметры, ставим тип интерактивности — press и получаем кнопку.</p>
  <figure id="Ezsa" class="m_original">
    <img src="https://leonardo.osnova.io/c38705cc-389e-5cfe-b575-a943ab42ce59/-/preview/1300/-/format/webp/" width="646" />
    <figcaption>Как выглядит кнопка после предварительной сборки</figcaption>
  </figure>
  <figure id="stZ1" class="m_original">
    <img src="https://leonardo.osnova.io/d75b99cb-a58c-5226-b64d-6f039d2370d6/-/preview/1000/-/format/webp/" width="516" />
    <figcaption>Структура кнопки</figcaption>
  </figure>
  <p id="MD7A">Теперь, допустим, мы хотим из этого шаблона получить зеленую кнопку «Фильтры». Меняем текст и иконку и выбираем нужный контекст (context=green).</p>
  <figure id="Bhcn" class="m_retina">
    <img src="https://leonardo.osnova.io/1c52046b-4fa9-5068-a1f4-e5bafc9543a7/-/preview/1300/-/format/webp/" width="322" />
    <figcaption>Кнопка с зеленым контекстом</figcaption>
  </figure>
  <p id="plzW">А теперь последний штрих — настроим активные и обычные значения токенов и выберем активную иконку. И привяжем active к состоянию есть\нет активные фильтры.</p>
  <figure id="HxU9" class="m_retina">
    <img src="https://leonardo.osnova.io/e8c696f6-eddf-5856-bce8-0a9d983dfc44/-/preview/2100/-/format/webp/" width="635" />
  </figure>
  <p id="LHI9"><strong>Пример2. Checkbox &amp; Radiobutton</strong></p>
  <p id="BKE8">Структура очень похожая на кнопку. Также враппер, иконка, текст. Но тип интерактивности уже выставить нужно check. Так с каждым нажатием на враппер будет переключаться собственное свойство active.</p>
  <figure id="YzFR" class="m_retina">
    <img src="https://leonardo.osnova.io/173a9557-3907-582f-b98d-374acf9722a7/-/preview/1100/-/format/webp/" width="267" />
    <figcaption>Структура чекбокса</figcaption>
  </figure>
  <p id="RCXH">Получаем шаблон чекбокса.</p>
  <figure id="bAJr" class="m_retina">
    <img src="https://leonardo.osnova.io/2047e54c-3013-5778-9ac8-303e3c7e6489/-/preview/1300/-/format/webp/" width="440" />
  </figure>
  <p id="Hvsr">Но теперь нам хочется, чтобы активный чекбокс был акцентным цветом. Для этого нужно поменять active-context у виджета иконки на green-accent. Получаем вот такое поведение.</p>
  <figure id="Bsxi" class="m_retina">
    <img src="https://leonardo.osnova.io/c8bdfe74-b5e7-5fe4-9f72-18b703d5ef09/-/preview/1300/-/format/webp/" width="478.5" />
  </figure>
  <p id="qdvx">Чтобы чекбокс превратился в Radiobutton, нужно поменять иконку на подходящую а также изменить тип интерактивности на radio. Теперь если, скажем, три таких виджета объединить во враппер, они будут работать как привычная всем группа радио-кнопок.</p>
  <figure id="2q6J" class="m_retina">
    <img src="https://leonardo.osnova.io/a307ccf2-c2c2-5c2c-955a-b982a686a339/-/preview/1000/-/format/webp/" width="337" />
  </figure>
  <p id="i7xB"><strong>Пример 3. Segment control.</strong></p>
  <figure id="kO9T" class="m_column">
    <img src="https://leonardo.osnova.io/7a99e1c1-5fcc-55ff-8080-401a0dd894cb/-/preview/2100/-/format/webp/" width="1195" />
  </figure>
  <p id="0gBK">Чтобы сделать такую панель, нам просто нужно использовать знания из прошлых примеров. Собираем сегмент из враппера, иконки и текста.</p>
  <figure id="xtMn" class="m_column">
    <img src="https://leonardo.osnova.io/e669018c-e829-555c-a825-3fe04c9a0159/-/preview/2100/-/format/webp/" width="1928" />
  </figure>
  <p id="7xNu">Всё как в кнопке, только с чуть другими стилями. И тип взаимодействия — radio. Оборачиваем в ещё один враппер, чтобы сегменты переключались в рамках группы, и получаем необходимый виджет. А переключая контексты, можем раскрашивать, как нам нравится.</p>
  <figure id="yQr3" class="m_column">
    <img src="https://leonardo.osnova.io/68b902be-9aeb-5ebd-9dfd-4e48eea0019b/-/preview/1300/-/format/webp/" width="986" />
  </figure>
  <h2 id="wQqd">Неактивность (disable)</h2>
  <figure id="Djzh" class="m_column">
    <img src="https://leonardo.osnova.io/ef6fe1ea-a41a-5b93-b532-a14e903f52c1/-/preview/2100/-/format/webp/" width="2099" />
  </figure>
  <p id="Ri8a">Хотелось бы упомянуть, как в нашей системе реализовано свойство disable. Это отдельный наследуемый параметр, с несколько особенной логикой наследования. При установке параметра disable=true блокируется интерактивность у выбранного виджета и всех его «детей». Однако, значение их собственного свойства disable не перезаписывается. А для визуального отображения используется специальный контекст — <strong>inactive</strong>.</p>
  <figure id="6NSF" class="m_column">
    <img src="https://leonardo.osnova.io/65b3ee65-b777-5f46-9db3-2fa865f9e1d5/-/preview/2100/-/format/webp/" width="1052" />
  </figure>
  <p id="zIDa">Это все наследуемые свойства на текущий момент. Другие интересные функции нашей дизайн-платформы я постараюсь описать в следующих статьях. Но вы можете не ждать выхода большого текста, а подписаться на мой телеграм-канал, и узнавать больше о развитии дизайнерской платформы ВкусВилл, SDUI, а также анонсы выступлений на митапах. <a href="https://t.me/uxflow" target="_blank">https://t.me/uxflow</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@uxflow/MangoContext</guid><link>https://teletype.in/@uxflow/MangoContext?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=uxflow</link><comments>https://teletype.in/@uxflow/MangoContext?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=uxflow#comments</comments><dc:creator>uxflow</dc:creator><title>Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст</title><pubDate>Tue, 13 Feb 2024 07:21:26 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/aa/37/aa374d06-8bab-446a-a504-2552a1e66970.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/dc/7f/dc7fb4d8-0998-4faf-9c90-b0faa09458e5.png"></img>Концепция была разработана в рамках работы над дизайн-платформой для SDUI приложения ВкусВилл , и основной задачей было сократить количество параметров и возможных состояний виджетов, уменьшив таким образом дерево объектов, но при этом сохранить вариативность и управляемость. В дальнейшем, под платформой понимается решение, которое обеспечивает реализацию всех SDUI функций, т.е. технологии, а под дизайн-системой - решение по структурированию, иерархизации и оформлению пользовательских виджетов (пресетов).]]></description><content:encoded><![CDATA[
  <figure id="7FXR" class="m_column">
    <img src="https://img2.teletype.in/files/dc/7f/dc7fb4d8-0998-4faf-9c90-b0faa09458e5.png" width="772" />
  </figure>
  <p id="SBSg">Концепция была разработана в рамках работы над дизайн-платформой для SDUI приложения ВкусВилл , и основной задачей было сократить количество параметров и возможных состояний виджетов, уменьшив таким образом дерево объектов, но при этом сохранить вариативность и управляемость. В дальнейшем, под платформой понимается решение, которое обеспечивает реализацию всех SDUI функций, т.е. технологии, а под дизайн-системой - решение по структурированию, иерархизации и оформлению пользовательских виджетов (пресетов).</p>
  <p id="T7jj">О том, как применить подобный подход к цветовой семантике без SDUI на примере текущего приложения “ВкусВилл”, я писал в своем <a href="https://t.me/uxflow/33" target="_blank">телеграм-канале.</a></p>
  <h2 id="9J7I">Зачем нужны наследуемые свойства</h2>
  <p id="tX3B">Чтобы ответить на этот вопрос, нужно сначала разобраться, что такое SDUI. SDUI (Server Driven User Interface) - это концепция пользовательского интерфейса, управляемого сервером. Основная часть этой концепции относится не столько к дизайну, сколько к работе с данными и обработке действий пользователя. В традиционных приложениях вся обработка происходит на стороне клиента, включая большую часть бизнес-логики.</p>
  <p id="dgI4">В SDUI-приложении клиент настолько “тупой”, что виджетам остается только отправлять события на сервер (например, “На меня нажали”) и ждать от него инструкций о том, как должен измениться интерфейс после этого действия. Вся бизнес-логика в этом случае выносится на серверную сторону.</p>
  <p id="cMtV">А клиент умеет только работать с контрактом. Контракт - это чаще всего JSON-дерево объектов и их параметров. Такой подход позволяет вносить изменения на клиенте без выпуска новых версий приложения в магазины приложений. Чем более вариативен отрисовщик и чем более управляем интерфейс, тем больше видов изменений можно внести без выпуска новой версии.</p>
  <figure id="g0wk" class="m_column">
    <img src="https://img4.teletype.in/files/37/86/3786aa00-c361-420c-8e1b-a19589e938ed.png" width="1280" />
  </figure>
  <p id="FKna">Если каждый раз при изменении передавать все параметры измененных виджетов, используя классические настройки, потребуется передавать большое количество данных дерева объектов и их параметров для обновления интерфейса. Именно для оптимизации этого процесса, ускорения реакции интерфейса на изменения и была разработана концепция наследуемых свойств.</p>
  <p id="K9UF"><strong>Контракт</strong></p>
  <p id="haBd">Контракт - это JSON, который передается с серверной части приложения на клиентскую и содержит параметры виджетов, которые на клиентской стороне преобразуются в элементы интерфейса.</p>
  <p id="C5f6">Возьмем простой контракт из консервативного SDUI-приложения: кнопка с иконкой будет выглядеть следующим образом:</p>
  <figure id="yz4O" class="m_column">
    <img src="https://img2.teletype.in/files/5e/fe/5efe1d1f-14ee-4b9d-a6d8-03587366ce91.png" width="524" />
  </figure>
  <p id="eedE">В целом, все достаточно компактно и понятно. Но что, если мы захотим изменить кнопку, изменить ее внешний вид и содержание? Нам придется охватить все параметры и, конечно же, выпустить новую версию приложения в магазинах. Мы же хотим избежать этого как можно дольше. Если мы возьмем, к примеру, JSON-макет простой страницы в Figma, а файлы Figma, как ни странно, в формате JSON, там будет более 800 тысяч строк 🤯.</p>
  <figure id="PLiz" class="m_column">
    <img src="https://img1.teletype.in/files/ca/ae/caaea7a4-800c-45fc-ba77-19a744cad7a6.png" width="884" />
  </figure>
  <p id="2YyY">Так насколько же наследуемые стили позволяют сократить размер контракта? Тот же экран, но уже оптимизированный под нашу платформу в формате JSON имеет всего около 1200 строк. Примерно так выглядит кнопка с иконкой и текстом в этом формате:</p>
  <figure id="H0iN" class="m_column">
    <img src="https://img4.teletype.in/files/77/26/77266039-46f6-4693-a0b9-0781a1d37e6c.png" width="497" />
  </figure>
  <p id="PUzg">Значительно больше строк, чем в первом примере, но все еще читаемо, и внутри может быть все, что угодно. Мы не ограничены заранее определенными параметрами виджета кнопки. Таким образом нам удалось достичь вариативности макета как в Figma и в то же время существенно оптимизировать данные дерева объектов и их параметры.</p>
  <h2 id="o8lk">Контекст (микротема)</h2>
  <p id="T5ZI">Обычная структура семантического токена цвета в теме примерно следующая:</p>
  <p id="5o2J"><em>light-theme. background-brand-accent</em></p>
  <p id="ySVf">Иногда к этому добавляется еще уровень токенов компонентов. Все имя токена полностью “лежит” в каком-либо параметре, например “button-background”. Цвет текста отдельно в свойствах “icon-color” и “label-color”, что-то вроде <em>light-theme.text-color-on-accent.</em></p>
  <p id="asyT">В результате получаем зеленую кнопку.</p>
  <figure id="maT1" class="m_original">
    <img src="https://img2.teletype.in/files/16/02/1602dd77-6546-40ae-924f-604e8e114bc1.png" width="452" />
  </figure>
  <p id="8LkU">Но контекст добавляет к этой картине новое измерение</p>
  <figure id="sFTf" class="m_original">
    <img src="https://img4.teletype.in/files/36/44/3644e2ec-3539-4592-9e82-733af5183fe9.png" />
    <figcaption>структура имени токена цвета в платформе Манго.</figcaption>
  </figure>
  <p id="Wohn">За цвет в такой системе отвечают два свойства: одно для токена цвета и одно для его контекста. Значение контекста указывается в свойстве “context”, а в самом токене указывается только цвет. Например, в свойстве background указывается значение “primary”, а в свойствах text-color и icon-color указывается значение “on-primary”. По умолчанию значение свойства context равно “inherit”. Это означает, что виджет наследует значение контекста от родительского виджета. Если мы хотим, чтобы кнопка была зеленой, мы должны установить значение контекста на “green-accent”.</p>
  <p id="Ff0q">Контексты и цветовые токены в библиотеке Figma представлены в виде стилей и визуализируются в виде модулей:</p>
  <figure id="9WBs" class="m_column">
    <img src="https://img3.teletype.in/files/27/95/2795a3ad-45fa-4eae-ac1b-594117ffc423.png" width="3344" />
    <figcaption>нейтральный контекст</figcaption>
  </figure>
  <figure id="OEMe" class="m_column">
    <img src="https://img2.teletype.in/files/db/40/db404728-c9b8-4044-8f8f-bf4596e85bbe.png" width="3952" />
    <figcaption>пример групп контекстов</figcaption>
  </figure>
  <p id="5ZlQ">Таким образом, правильное управление наследованием свойств позволяет легко управлять внешним видом компонента в коде, используя всего один параметр.</p>
  <figure id="WBDB" class="m_column">
    <img src="https://img3.teletype.in/files/aa/5c/aa5cc4c1-c276-4599-b103-4a97835f3858.png" width="1309" />
    <figcaption>пример смены контекста для виджета тизера товара</figcaption>
  </figure>
  <p id="Cbl0">Как видно из приведенного выше примера, кнопка &quot;В корзину&quot; не меняет свой цвет, потому что у нее задан определенный контекст “green-accent”, а не “inherit”, и поэтому она не наследует контекст от своего родительского виджета.</p>
  <h2 id="28mb">Контексты в фигме</h2>
  <p id="nfAM">В коде с такими сложными механиками более менее все понятно, но как это реализовать в Figma? К сожалению, идеального решения не существует, даже с использованием новых variables. Сейчас у нас цвета на стилях, и даже если перейти на переменные, то без тарифа Enterprise картина кардинально не изменится. Теоретически, можно было бы попытаться создать mode для каждого контекста и разные коллекции для разных тем. Возможно, это сработало бы, но это очень затратно. Кроме того, в нашей платформе виджеты автоматически выгружаются на фронтенд, а это значит, что параметр также необходимо передавать.</p>
  <figure id="AfG3" class="m_column">
    <img src="https://img1.teletype.in/files/cb/e3/cbe3e7f0-5bd9-4795-8fb5-e2dd4717d0b6.png" width="991" />
    <figcaption>Контекст для автоматики хранится в специальном служебном слое в свойстве компонента.</figcaption>
  </figure>
  <p id="6G6N">Получается что контекст надо выставлять дважды: один раз для автоматики, второй раз для отображения в фигме руками через замену стилей. Это не так страшно, как кажется, через поиск это делается довольно быстро. Однако, даже у этой проблемы есть решение. Сейчас мы работаем над собственным редактором для экранов платформы. Но о нём и о других наследуемых свойствах в следующих статьях и в моём <a href="https://t.me/uxflow" target="_blank">телеграм канале.</a></p>

]]></content:encoded></item></channel></rss>