Русский
Русский
English
Статистика
Реклама

Figma

Перевод Создание опенсорсных инструментов и совершенствование рабочих процессов команды дизайнеров Discord

04.02.2021 12:07:48 | Автор: admin
В прошлом году вышел API Figma, предназначенный для разработки плагинов. Команда дизайнеров Discord увидела в этом событии потрясающую возможность для улучшения своих техпроцессов.

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

image

Для того чтобы получить гарантию работоспособности наших новых схем использования цветов, дизайнерам нужно было проектировать каждый новый элемент в двух вариантах. Значит приходилось делать двойную работу, что отнимало время, но обойтись без этого было нельзя.

Именно тогда и зажглась искра дизайн-инструментов. Мы задались вопросом о том, можем ли мы создать инструменты, способные нам помочь. Предупреждаю: спойлер. Мы могли создать такие инструменты, мы их создали, и получились они просто замечательными. С тех пор подобные инструменты стали важнейшей частью нашей работы.

Мы видим сильные стороны этих инструментов в следующем:

  • Меньше времени тратится на выполнение повторяющихся задач, больше времени остаётся на более важные дела.
  • Предотвращается возникновение дизайнерского долга.
  • Улучшается взаимодействие между разработчиками и дизайнерами.
  • Создание этих инструментов способствует формированию сообщества специалистов, занимающихся дизайн-инструментами. Другие люди могут, беря за основу наши наработки, создавать что-то своё.

Вот основные темы, которые будут подняты в этом материале:

  • Проблемы, которые мы хотели решить посредством дизайн-инструментов.
  • Методология и образ мыслей, которые мы задействовали при создании этих инструментов.
  • Рекомендации по использованию наших инструментов другими командами (ура опенсорсу!).

Экономия времени благодаря автоматизации рутинных задач


Инструменты для дизайнеров способны автоматизировать чёрную работу, действия, которые приходится выполнять по десять раз на дню. Например это одновременная замена текста во множестве текстовых полей, выбор всех экземпляра слоя, или, как в нашем случае, создание двух версий всех визуальных элементов наших проектов.

Плагин Auto Theme


Auto Theme это плагин для Figma, который мы создали для автоматического применения темы к различным элементам.


Плагин Auto Theme в действии

Вместо того, чтобы, имея некий компонент, оформленный в тёмной теме, вручную переключать каждый слой и каждый цвет на использование соответствующего цвета из светлой темы, мы можем просто запустить этот инструмент. Это значительно сокращает нагрузку на человека, связанную с проверкой дизайна двух вариантов компонента.

Например, недавно я работал над улучшением пользовательского опыта, связанного с экраном мобильного приложения для входа в систему. Мне хотелось убедиться в том, что и тёмный, и светлый варианты одинаково хороши. Плагин Auto Theme значительно облегчил мою работу.


Плагин Auto Theme, кроме прочего, заменяет системные компоненты, а это значит, что нам не нужно пытаться самостоятельно применять темы к чему-то вроде строки состояния iOS

Работа этого плагина основана на обходе выделенных слоёв. Далее, плагин определяет то, как нужно поменять цвет в зависимости от типа слоя. Это слой с текстом? Значит нужно воспользоваться основным цветом для заголовков. Этот слой представляет собой фигуру? Тогда нужно использовать основной фоновый цвет.

То, какой именно цвет плагин выбирает для того или иного слоя, определяет пользователь. В нашем случае мы один раз задали соответствующие настройки, после чего они применяются всей нашей командой.

В тех случаях, когда инструмент не знает о том, что ему нужно делать (предположим, он наткнулся на иллюстрацию) он помечает слой и показывает его в списке необработанных слоёв. Мы сами создали этот инструмент, но одним им мы не ограничились. Он лишь один из многих плагинов, которые мы используем для автоматизации наших повседневных задач.

Предотвращение накопления дизайнерского долга, улучшение взаимодействия дизайнеров и разработчиков


Уверен, большинство дизайнеров слышало такой вопрос: Ну что, готово это для передачи в разработку?. Хороший ответ на этот вопрос представлен в подписи к следующему рисунку.


Да, этот дизайн совершенен. С полной уверенностью можно говорить о том, в нём нет ошибок или чего-то подобного

Но дизайнеры это не сверхлюди. Ошибки, так или иначе, происходят. И это совершенно нормально. Особенно часто ошибки встречаются при проектировании некоего действия, реализованного путём перехода между несколькими экранами.

Плагин Design Lint


Design Lint это плагин для Figma, который осуществляет проверку дизайн-макетов и исправление найденных ошибок. Он позволяет обеспечить единообразие дизайна и возможность его поддержки в будущем, а так же готовность макета к передаче в разработку.


Приятный дизайн. А ещё, полагаю, стоит упомянуть о том, что плагин Design Lint можно установить в Figma уже сейчас

Дизайнеры часто встречаются с парой серьёзных вопросов: Готов ли этот макет для передачи в разработку? Не взвоет ли от ужаса новый дизайнер, который откроет этот файл?. Мы справляемся с этими вопросами посредством инструмента, который помогает нам искать ошибки в дизайн-макетах.

Линтинг это явление, получившее распространение в программировании. Линтеры помогают программистам искать ошибки в коде, позволяют поддерживать код в аккуратном состоянии. В определённый момент мы подумали о том, что файлы с дизайнерскими материалами, похоже, ничем особо не отличаются от файлов с программным кодом.

Design Lint проверяет файлы с макетами в поиске пропущенных стилей (так в Figma называются дизайн-токены или переменные). Используются ли тут шрифты, которых нет в дизайн-системе? Применяется ли где-то значение свойства border-radius, которое не предусмотрено принятыми стандартами? Представлен ли этот новый оттенок чёрного цвета переменной, которая уже есть в системе? Design Lint, если найдёт проблемы с чем-то подобным, укажет на них дизайнеру.


Design Lint позволяет выделять сразу несколько сообщений об ошибках и быстро все эти ошибки исправлять. Он выводит сведения об ошибках в контексте документа, что облегчает их исправление

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


Работа с Design Lint

Проверяя с помощью Design Lint всю нашу дизайн-систему, мы можем находить ошибки до того, как они попадут в файлы. Мы создали этот инструмент таким, чтобы им, только что его установив, мог бы пользоваться кто угодно, не настраивая его. Но, так как инструмент это опенсорсный, его можно гибко конфигурировать, создавая собственные правила линтинга.

Упрощение навигации по файлам для всех сотрудников Discord


Мы, продуктовая команда, столкнулись с одной проблемой. Она заключается в том, что перемещаться по файлам в Figma не особенно просто. Для того чтобы решить эту проблему, мы создали плагин, который называется Table of Contents.

Плагин Table of Contents


Плагин Table of Contents автоматически генерирует страницы, называемые таблицами содержимого. На этих страницах создаётся фрейм со списком всех страниц, имеющихся в файле, ссылки (их можно использовать для перехода к соответствующим материалам), туда же добавляется и дата.


Плагин Table of Contents помогает людям, не знакомым с Figma, находить то, что им нужно

Невозможность найти нужные материалы, особенно в больших проектах, представляла собой проблему, которая часто беспокоила людей, не относящихся к команде дизайнеров. Этот плагин рассчитан на решение проблемы поиска определённых материалов.

Table of Contents это опенсорсный плагин, его можно настроить в расчёте на использование шрифтов, используемых в конкретной компании. Он существует и в виде шаблона Figma.


Люди, работающие в компании, могу найти с помощью Table of Contents то, что им нужно

Разработка мета-плагинов для ускорения создания новых инструментов


Для того чтобы упростить создание и поддержку новых инструментов, мы создали соответствующий вспомогательный инструмент. Его можно назвать инструментом для разработки инструментов.

Плагин Inspector


Плагин Inspector это такой инструмент, работа которого проста, но вот объяснить то, как именно он работает, это уже задача более сложная.

Каждый слой в Figma содержит важную мета-информацию Это имя слоя, его ID, сведения о том, есть ли у него потомки (небольшой кружок и небольшой многоугольник, которые очень хорошо делают своё дело), данные о типе слоя (текст, изображение, фигура) и многое другое.

Inspector выводит эту мета-информацию для выделенного слоя. Это нечто вроде инструментов разработчика Chrome, но инструмент этот предназначен для Figma. Мы, кроме того, используем этот плагин как вспомогательное средство при обновлении цветов Auto Theme в ходе добавления в систему нового цвета.


Рад видеть вас, Username, я Дэниел

Опенсорс в Discord


Мы, сотрудники Discord, верим в ценности опенсорса. И наши инженеры, и дизайнеры часто используют опенсорсные библиотеки, фреймворки, ресурсы.

Мы хотим поделиться со всеми желающими тем полезным, что даёт нам создание и применение вышеописанных инструментов. Именно поэтому всем тем, о чём я рассказал здесь, могут совершенно бесплатно пользоваться те, кому это нужно.

Некоторые из вышеописанных инструментов можно установить прямо со страницы плагинов Figma. Но мы, всё равно, открыли код этих плагинов. Это позволит любому подстроить их под свои нужды.

Вот перечень наших плагинов с соответствующими ссылками:


Посмотреть наши опенсорсные дизайн-файлы можно здесь.

Нашей команде очень интересно наблюдать за развитием инструментов для дизайнеров. Увидим ли мы средства для автоматического форматирования кода, вроде prettier.js, но предназначенные для сферы дизайна? Появятся ли дизайнерские версии npm или yarn? Можно ли будет пользоваться интерактивной проверкой типов при использовании дизайн-токенов?

Нам до крайности любопытно увидеть новые инструменты, созданные силами сообщества дизайнеров. А вам, надеемся, пригодится то, что создали мы.

Какими плагинами для Figma вы пользуетесь?

Подробнее..

Боль фронтов, или что нам нужно от дизайнеров

12.02.2021 12:08:58 | Автор: admin

Вступление

Пройдя путь от верстальщика-стажёра до сеньора фронтенд-разработчика, я работал в разных командах и с разными дизайнерами. Независимо от количества человек и типа проекта, всегда были похожие проблемы: взаимное недоверие или даже предвзятое отношение между фронтендщиками и дизайнерами, непонимание макета или дизайн-системы, отсутствие коммуникации в команде и многое другое, что мешало работать. В этой статье я попробую разобрать часть проблем и дам свои рекомендации по их решению. Надеюсь, статья будет полезна как фронтендщикам, так и дизайнерам.

Мифы о UI/UX-дизайнерах

Вначале я хотел бы обратить внимание на предвзятое отношение и недоверие фронтендщиков к UI/UX-дизайнерам. Далее по тексту я опущу приставку UI/UX и буду писать просто дизайнер, подразумевая именно дизайнеров интерфейсов. Выделим несколько мифов, которые мешают в коммуникации.

Мой дизайнер ни за что не изменит свой макет. Это один из самых распространённых мифов. Многие разработчики думают, что макет для дизайнера это как картина для художника, он закончил её и больше ни за что не изменит. В реальности всё не так. Как программисты продолжают работать над кодом, устраняя технический долг и совершенствуя код, так и дизайнеры продолжают работу над макетами. Если команда большая, макет вообще может начать жить своей жизнью. В моей практике почти все дизайнеры шли мне навстречу, если я просил что-то изменить. Даже в самом глубоком энтерпрайзе, где макеты проходили несколько этапов согласований, мы всё равно находили возможность что-то подкорректировать. В любом случае изменения в макетах неизбежны, ведь не все из гипотез дизайнера проходят проверку на реальных пользователях. Если вы можете доходчиво объяснить причину предлагаемого изменения (например, ваш вариант позволяет сэкономить на времени разработки вдвое или есть готовая библиотека с нужным поведением, но немного отличается внешне), вы найдёте компромисс со своим коллегой. Он либо поправит макет по вашим предложениям, либо объяснит, почему его вариант важен для проекта.

Мой дизайнер самый ленивый. Этот миф возникает, когда приходишь несколько раз с одной и той же просьбой к своему дизайнеру, но он её упорно игнорирует. Зачастую дизайнеров меньше на проекте, и они всегда завалены работой и техдолгом как я уже упоминал выше, техдолг есть не только у разработчиков). Если работа простаивает без помощи дизайнера, лучше сходить к тимлиду возможно, есть задачи, которыми можно заняться в ожидании макета. Например, настроить инфраструктуру, среду для тестирования или что-нибудь ещё. Если тимлида нет, можно спросить дизайнера, чем он занимается, и помочь ему с расстановкой приоритетов. Объясните, какие экраны нужны в первую очередь, а какие могут подождать. Возможно, ваш дизайнер готовит дизайн-систему для проекта, тогда его лучше вообще не отвлекать, ведь как и у программистов, у них всегда есть важные задачи, при работе над которыми лучше не отвлекаться. Если вам действительно что-то очень нужно, объясните почему, спросите, когда у коллеги будет возможность заняться вашим вопросом, и до этого времени постарайтесь его не беспокоить.

Мой дизайнер только рисует макеты, откуда он знает, как лучше? Этот миф распространен у Junior-разработчиков. Специально для них объясню, что дизайнеры то люди, которые прорабатывают макет не только чтобы он смотрелся красиво и современно, но и чтобы им было удобно пользоваться. Они знают множество паттернов поведения пользователя, сочетания цветов и форм, о которых мы не догадываемся, поэтому лучший совет в этом пункте: больше доверяйте своему коллеге, он наверняка знает, что делает.

Мой дизайнер самый упёртый. Наверняка каждый фронтенд-разработчик слышал нет от дизайнера, отсюда и возникает этот миф. Опираясь на предыдущие мифы, первый совет поверьте ему на слово. Если не удаётся, попробуйте получить у него больше информации, почему он говорит нет, или обратиться к его менее загруженному коллеге за разъяснением (правда, таким образом можно обидеть своего дизайнера, будьте к этому готовы).

По правде говоря, мифов гораздо больше, но основная мысль, которую я хотел донести, звучит так: все дизайнеры тоже люди, с которыми лучше общаться и задавать вопросы. Многие, с кем я общался, научили меня некоторым тонкостям своего ремесла, которые пригодились мне в вёрстке.

Сложности с макетами

Начну с простого. В макетах не проработаны случаи горизонтального и вертикального переполнения. Часто приходится додумывать самому, что будет с длинным текстом внутри кнопки или в подзаголовке, или как будет осуществляться скролл: внутри контентной области либо на всей странице. Больше всего расстраивает, когда твоё решение не нравится дизайнеру или тестировщику, и приходится перевёрстывать под открытый баг, хотя это не является багом. Например, я прятал длинный текст под троеточием, но дизайнер потом заменил их на уход в прозрачность. Из рекомендаций могу предложить любые белые пятна разбирать в паре с дизайнером, наверняка он уже продумал эти кейсы, но не успел отобразить их на макетах.

Следующая проблема связана с высотой блоков и вертикальными отступами между ними. Бывало, делаешь всё по макету, а при проверке на pixel perfect видишь, что вертикальные отступы отличаются. В моём случае это возникло из-за беспорядка в стилях, определяющих высоту блока. В макете высота строки (line-height) была задана в пикселях и была меньше размера основного текста (font-size), а размер блока был задан через height. При вёрстке я не смотрел на высоту блока, потому что обычно она не задается, ведь это может сломать элемент при переносе строки, и такой блок сложнее адаптировать. Высота блока должна формироваться автоматически и состоять из внутренних отступов (padding), высоты строки (line-height) и ширины рамки (border-width), при этом высота строки должна быть больше либо равна размеру шрифта (font-size). Отступы от блока считаются от внешнего края его границы, поэтому чтобы отступы и размеры блока совпадали с макетом, внимательно проверяйте все свойства. Если в них есть проблемы, постарайтесь объяснить их важность своему дизайнеру и попросите его привести эти стили в порядок. На одном из проектов мы с дизайнером договорились, что все отступы в проекте должны быть кратны определённой величине, например, четырем или восьми пикселям, тогда в случае расхождения отступов на сайте и в макете предпочтение отдаётся ближайшей кратной величине. Этот подход решает много проблем, но важно донести его тестировщику, который может прийти с багами, что отступы отличаются от макетов. Ещё рекомендация: всегда просматривайте свою вёрстку в pixel perfect, чтобы знать, где у вас явные расхождения и где вы могли что-то упустить, а где сам макет расходится с дизайн-системой.

Подобная проблема возникает при вёрстке блоков с рамкой, ведь отступы внутри блока в figma считаются без его учёта. Особенно это заметно на кнопках. Приведу пример.

Рисунок 1 внутренние отступы на примере макета кнопкиРисунок 1 внутренние отступы на примере макета кнопки

В макете отступы внутри кнопки 8px от текста до верхнего края кнопки, но при вёрстке приходится уменьшать их на ширину бордера (border-width), потому что в браузере, как правило (если box-sizing: border-box), бордер входит в высоту и ширину элемента, и внутренний отступ (padding) считается именно от его внутреннего края. Похожая проблема наблюдается, когда кнопка в макете без обводки, но при ховере обводка появляется. Тогда, если делать один-в-один с макетом, наша кнопка будет прыгать, поэтому надо самому добавлять бордер с прозрачностью. Рекомендация только одна: всегда нужно удостовериться, что ваш элемент выглядит так, как нужно.

Следующая проблема связана с прелоадерами. В решении нам поможет теория конечных автоматов. Часто сами фронтендщики грешат тем, что задают одну булевую переменную (isFetching или isLoading) для отображения прелоадера, хотя состояний там гораздо больше. Например, в случае повторного перехода на страницу, на которой уже есть кэшированные данные, произойдёт отображение контента, а потом всё исчезнет и появится прелоадер, потому что пройдет обновление данных. Согласитесь, это не очень красиво. Такая проблема возникла потому, что мы смешали состояние первичной загрузки и обновления данных, а прелоадер использовали один и тот же в обоих случаях. Решить это можно, попросив вашего дизайнера продумать все состояния. Для этого лучше описать их, либо привести пример. При этом на фронтенде нужно будет задавать переменную не в булевом виде, а перечислением состояний, и обрабатывать каждое состояние отдельно.

Раз уж зашла речь о состояниях, хочу отметить, что часто в макетах не хватает всех состояний интерактивных элементов. А их, как правило, шесть:

  • Normal сообщает, что компонент интерактивен и включен.

  • Focus сообщает, что пользователь выделил элемент, используя клавиатуру или другой метод ввода.

  • Hover сообщает, когда пользователь навел курсор на интерактивный элемент.

  • Active активное или нажатое состояние сообщает о том, что пользователь нажал на кнопку.

  • Progress/Loading используется, когда действие не выполняется немедленно и сообщает, что компонент находится в процессе завершения действия.

  • Disabled сообщает, что компонент в настоящее время не является интерактивным, но может быть включен в будущем.

Часто про это забывают, и некоторые состояния сливаются. Сами фронтенд-разработчики иногда объединяют hover и focus в один стиль, что является ошибкой. Постарайтесь обсудить это со своим дизайнером до старта работ, потому что такие решения влияют на доступность вашего продукта. Самый жизненный пример вы кликнули на кнопку, а потом убираете с неё курсор, но она как будто остаётся в состоянии ховера.

О доступности можно написать отдельную статью, поэтому здесь обозначу свою основную боль. Почти во всех проектах, где я работал, дизайнер требовал убрать эту уродскую синюю обводку, которую мы просто отключаем, ничего не добавляя взамен. Речь идёт про outline. Отключая его и не давая ничего взамен, мы ломаем клавиатурную поддержку вашего сайта, потому что по сути мы отключаем у всех интерактивных элементов состояние focus. Вряд ли пользователи, которые пользуются вашим сайтом с клавиатуры, поблагодарят вас, а их немало.

Следующая сложность возникает, когда стайлгайд используется неправильно. Например, есть шрифты для десктопной версии Heading-1 и мобильной версии MobileHeading-1, но в макете Heading-1 в десктопе в мобильной версии неожиданно становится Heading-3. С этим очень сложно работать, потому что вся система, которую я делал на фронте по стайлгайду, начинает рушиться прямо в этом месте. Основной посыл: если есть стайлгайд или дизайн-система, старайтесь максимально ей соответствовать. Например, если дизайнер спрашивает, нужно ли добавлять в стайлгайд немного изменённую кнопку, однозначно говорите да.

Отдельно поговорим об адапативности. Как правило, вёрстка бывает адаптивная и резиновая. Адаптивная подстраивается под конкретные заданные разрешения экрана, а резиновая плавно изменяется, подстраиваясь под любую ширину экрана. На мой взгляд, резиновая вёрстка более современная и универсальная, а ее создание не вызывает трудностей, потому что в арсенале есть flex-box, grid, vw/vh, математические функции и прочее,. Однако, все давно привыкли к бутстраповским брекйпоинтам, и большинство макетов опираются именно на них. Хорошо, если в макете есть хотя бы три состояния: десктоп (как правило, 1440px), планшет (часто это 1024px или 768px) и телефон (320px или 375px). Именно с этого места обычно начинаются проблемы. Приходит заказчик и говорит, что на его моноблоке, у которого разрешение 2500px, сайт выглядит ужасно. Потом приходит аналитик и говорит, что сайт плохо выглядит на его ноутбуке, с разрешением в 1380px и так далее. Здесь описано сразу две проблемы.

Первая не проработан макет или принцип отображения сайта на больших мониторах. Об этом нельзя забывать, всегда просите дизайнера отобразить одну-две страницы на большом разрешении, чтобы был понятен принцип, как сайты должны себя вести на таких экранах. Повторю: приводить все страницы к такому разрешению не надо, достаточно одного-двух примеров.

Вторая проблема промежуточные состояния в макетах. Если размышлять адаптивно, а не резиново, все версии, отображаемые в макете, используются для состояний выше указанного, то есть макет на 1440px подходит для экранов шириной от 1440px и выше до следующего брейкпоинта (если он есть, конечно). Если ширина экрана меньше указанной в макете, должна отображаться версия для предыдущего брейкпоинта. Например, у вас в макете есть состояние на 1440px и 768px, на ширине в 1380px должна отображаться версия на 768px с ограничением ширины контентной области в соответствии с макетом. Выглядеть это будет не очень, мягко говоря. Худший сценарий, когда между брейкпоинтами большой разрыв. Например, дизайнер отобразил состояние на 1920px и на 768px. Тогда, следуя прямой логике, на 1440px включится состояние 768px, но так быть не должно. Суть проблемы в том, что, глядя на макеты в трёх разрешениях, фронтендщик не всегда понимает, какое состояние и в какой момент должно включиться. Если рассмотреть этот пример на резиновой вёрстке, на ширине экрана в 1380px должен отображаться макет для версии в 1440px, а на ширине 1110px версия для 1024px. Здесь возникают вопросы: в какой момент должна включаться какая из версий? До какой ширины экрана будет отображаться версия в 1024px? рассмотрим потенциальные варианты решений. Первый пойти к дизайнеру и описать проблему. Наверняка у него уже есть видение, как сайт должен меняться при сжатии и расширении экрана, он объяснит вам хотя бы на словах, однако это не всегда работает. Второй вариант отвязать свой разум от бутстраповских брейкпоинтов и рассматреть каждый блок как независимый. Потом я начинаю сжимать и разжимать каждый блок, наблюдая за его поведением, и определяю оптимальное разрешение для смены состояния. Многим верстальщикам такой подход не нравится и кажется избыточным. Основной аргумент возможно появление множества брейкпоинтов, но как показывает практика, этих состояний вряд ли будет больше шести, и все они будут инкапсулированы внутри своих блоков и ни на что не повлияют. Однако, ваш макет будет действительно резиновый и сможет подстраиваться под любое разрешение экрана.

Чем дизайнер может помочь фронтенд-разработчику

Здесь я собрал некоторые пункты, наличие которых в проекте помогло бы мне верстать.

  • Комментарии к макетам. Невозможно всё отобразить в макете, и в этом нет необходимости, но некоторую информацию лучше описать в комментариях. Конечно, можно передавать информацию устно, но если фронтенд-разработчиков много, будьте готовы объяснять каждому отдельно. Усложнится и процесс онбординга новых людей, потому что можно просто забыть, почему было принято то или иное решение.

  • История изменения макетов. Часто при работе над макетом неожиданно обновляются требования к продукту, и в макет вносят изменения. Фронтендщику ставят задачу на перевёрстку, но, на первый взгляд, все выглядит, как раньше. Только при более детальном исследовании выясняется, что поменялся, например, порядок иконок социальных сетей в футере, изменились некоторые отступы в контентной области или изменились некоторые тексты на странице. Чтобы это выяснить, приходится делать скриншот макета и сопоставлять его с текущей вёрсткой сайта. В Figma на данный момент нет системы контроля версий, поэтому всё ложится на плечи команды. И только коммуникация помогает решить данную проблему.

  • Стайлгайд проекта. Страница со всеми состояниями интерактивных элементов, страница с типографией, страница с формами и примерами их заполнения и прочее, что позволит атомарно подойти к блокам. Хорошо проработанный стайлгайд проекта залог успеха. Главное держать его в актуальном состоянии и не нарушать его.

  • Доступность интерфейса. Понимание дизайнером всей важности доступности вашего интерфейса и ее учет при проектировании очень важны. Сделать сейчас как есть, а потом задуматься о версии для слабовидящих или о режиме для чтения не получится. Внедрение доступности будет гораздо тяжелее, если вообще возможно.

  • Детально проработанная адаптивность. Полное понимание, как будет вести себя макет при его сжатии и расширении. Это решит проблему с промежуточными состояниями между брейкпоинтами и упростит создание любого типа верстки.

  • Структура проекта в Figma. Многие разработчики жаловались мне, что невозможно открыть Figma, потому что на одной вкладке отображаются все страницы проекта. Правильная структура хранения проекта облегчит работу с ним как дизайнеру, так и разработчику.

  • Названия у цветов и шрифтов. Когда у всех цветов и типов шрифтов есть имена, фронтенд разработчику не придётся их придумывать. Идеально, если имена содержат только буквы, цифры и знаки $ и _, при этом первый символ не является цифрой. Это необязательно, но позволит использовать названия прямо в коде, что облегчит их применение и поддержку в актуальном состоянии.

  • Консистентность между версиями. Это, скорее, просьба к дизайнерам. Разрабатывая макет мобильной версии сайта, старайтесь помнить, что это всё-таки сайт, а не мобильное приложение. Хочется видеть консистентность между десктопной и мобильной версиями. В некоторых проектах мобильная и десктопная версии настолько отличались, что приходилось делать разные версии с нуля, а это забирает в два раза больше времени на разработку.

Что следует знать дизайнерам о фронтенде

  • Вёрстку без практического опыта изучить невозможно, но было бы хорошо знать хотя бы основные правила, по которым формируется веб-страница. Это позволит дизайнеру понять, где верстальщику будет непонятна реализация, а где он скорее всего ошибётся.

    • box-sizing определяет, как вычисляется общая ширина и высота элемента;

    • margin определяет внешний отступ;

    • padding определяет внутренний отступ;

    • border отвечает за все персональные свойства границ;

    • overflow работает с переполнением;

    • flex/grid наиболее популярные типы отображения элементов.

  • Одна из основных методологий в CSS БЭМ. Дизайнеру она нужна, чтобы понять образ мыслей фронтендщика, который будет собирать страницу, и позволит хранить элементы проекта аналогично тому, как это будет делать фронтенд-разработчик.

  • Отличие блочных элементов от строчных. Это позволит глубже понять композицию веб-страницы.

  • Браузерные инструменты разработчика упростят процесс проведения авторского надзора и помогут проверить некоторые гипотезы непосредственно в рабочей среде.

Большинство дизайнеров никогда не верстали, поэтому им сложно понять, от чего верстальщик плачет. Не стесняйтесь делиться опытом, старайтесь чаще объяснять своему коллеге, как работают в браузере те или иные свойства, что вы можете легко сделать, а что будет гораздо сложнее.

Что следует знать фронтендщику о дизайне и не только

  • Сетка. Практически все макеты строятся на основе сетки. Зная её, верстать становится проще, а учитывая, что теперь у нас есть grid, это превращается в удовольствие.

  • Основы Figma. Говорить с дизайнером на одном языке и понимать особенности и отличия вёрстки в Figma и WEB-е.

  • БЭМ. Неважно, как вы верстаете, будь то CSS-in-JS или CSS-modules, методология позволяет навести порядок в голове и мыслить правильными категориями.

  • Наследование стилей. Многие CSS свойства наследуются от родительского блока, в Figma это отсутствует.Чтобы не переписывать все стили, не глядя , помните, какие свойства берутся от родителя, а какие объявляются в самом элементе.

  • Конечные автоматы. Понимать, сколько состояний может быть у того или иного элемента на странице.

Повторю мысль из предыдущих частей: если вам что-то непонятно или интересно к своему дизайнеру и задавайте вопросы, набирайтесь опыта в построении интерфейсов у профессионалов.

Заключение

В этой статье я осветил только часть того моста, который перекинут между двумя берегами фронтенда и UI/UX-дизайна. Надеюсь, мой опыт поможет фронтенд-разработчикам и дизайнерам чуть лучше понять друг друга.

Главное, что хочется вынести в заключение мы работаем с людьми, а значит, любой вопрос можно решить через общение и прийти к компромиссу. Уважайте своих коллег и чаще ставьте себя на их место.

P. S. (постскриптум)

За помощь в подготовке материала благодарю самого крутого из дизайнеров Олега Ровного.

Подробнее..

Figma делаем дизайн компонентов, пригодный для экспорта в код

15.02.2021 08:08:38 | Автор: admin

В этой статье я расскажу, о том, как сделать в Фигме компонент, который будет пригоден для экспорта в код. В Фигме можно будет выбрать наш компонент и при помощи плагина сгенерировать готовый код.

Начнём с простого

Нарисуем лист вью с иконкой, и сгенерируем вёрстку.

Так выглядит примерная структура нашего элемента списка - слева иконка, и далее текст.

Такую структуру будет иметь наш компонент - вертикальный набор элементов, который мы придумали выше.

Так, со структурой разобрались, поняли что нам примерно нужно сделать, теперь приступаем непосредственно к дизайну. Для этого мы возьмём один элемент, и сделаем его на основе компонентов Фигмы и применим к нему Auto layout. Сначала объединим текст и иконку, добавим отступы, сделаем выравнивание по высоте в середине, и по левому краю. Получится так

Далее нам нужно создать два элемента, расположить их друг под другом по высоте, и объединить их Auto layout. В целом всё кажется готовым, но на самом деле, если вы поменяете длинну текста, то элементы не будут гибко подстраиваться друг под друга.

Завершающим штрихом станет выставление автоматического растягивания элемента по ширине самого длинного элемента. Применяем это ко всем элементам списка, чтобы они могли адаптироваться к любой длине текста. Это делается при помощи вот этого инструмента.

В результате у нас должен получиться такой вот список.

Запускаем генератор кода.

Открывается плагин с генерацией кода. где мы можем выбрать необходимую нам технологию. Я буду использовать Tailwind 2. Далее выберем нужный нам элемент дизайна, и плагин выдаст нам готовую вёрстку.

Копируем в буфер и запускаем песочницу, для того чтобы проверить сгенерированный код и подправить пару нюансов.

Так, всё работает, кроме иконок, которые нам нужно копировать как SVG и вставить в наш код. Делается это вот так

Заменяем наши иконки в вёрстке (я вставил прям в разметку, но вы можете и так как вам удобно - по url на пример.).

Получаем результат, который идентичен нашему в Фигме.

Подробнее про Auto layout тут.

Результат тут.

Сложнее. Рисуем карточку товара.

Нашей целью будет сделать так, чтобы при генерации кода, наша карточка была выполнена на основе display: flex; - CSS модели, для построения гибких контейнеров.

Я нарисовал макет, как в прошлом примере, сделал дизайн, распределил блоки, и при помощи Auto layout выровнял всё так, как мне нужно. Сгенерировал код, подправил некоторые нюансы с картинками и иконками, в результате получил готовую карточку товара. Подробнее про Flexbox тут.

Моя сгенерированная разметка доступна по ссылке ниже. Вы можете посмотреть и попробовать сами.https://play.tailwindcss.com/2VhmQJIJDl

Надеюсь вам пригодится моя статья, и верстать станет в разы легче. Но если нет, то прошу не минусовать статью, а помочь мне ее доработать до удобоваримого вида - оставляя свои комментарии.

Подробнее..

Сердце, не познавшее боли разочарования, не знало и радости полёта

18.02.2021 14:23:54 | Автор: admin

The Host (Stephenie Meyer)


На этот пост меня вдохновила недавняя заметка Александра Pogman25 про боль фронтендеров и непростую историю любви и ненависти между фронтами и дизайнерами интерфейсов. История стара как мир, и основная причина боли действительно в отсутствии диалога и нежелании или неумении оказаться по другую сторону макета. Нежелание может быть следствием профэгоизма, неумение недостаточным скиллом. И с тем и с другим можно работать.



Думаю, в недалеком будущем No-Code/Low-Code продукты сделают свое дело, и UI/UX и фронтендеры уже не будут знать, что это такое, когда глаз дергается синхронно с кнопкой в веб-версии макета. А что сейчас? Чтобы дизайнеру и фронту было проще ужиться друг с другом, а их совместная работа упростилась, мы придумали Quarkly.



Сооснователи проекта Саша и Артем не понаслышке знакомы со всеми болячками, которые возникают во время коммуникации дизайнера и фронта. Александр фулстек-разработчик, Артем UI/UX. В данном случае, что называется, карты сошлись.


В Quarkly мы стремимся к пресловутому Low-Code и даже No-Code при сборке сайтов и веб-приложений, и когда мы запустим в релиз каталог-маркетплейс готовых компонентов, это станет в целом очень даже возможным.


По состоянию на февраль 2021 года маркетплейса у нас пока нет, но есть весь базовый набор инструментов как для дизайнера, привыкшего делать макеты/прототипы в популярных дизайн-инструментах (Figma, Framer), так и для разработчика.


Уже сейчас готовый макет из Figma не без труда, но довольно быстро можно перетащить в Quarkly, ниже оставляю туториал с русскими и английскими субтитрами:




За счет чего Quarkly поможет снять боль


Дизайнеры часто не могут понять боль фронтов, потому что создают макеты в инструментах, не позволяющих ощутить макет в динамике. Кроме того, с Quarkly процесс совместной работы занимает меньше времени.


Чтобы не считать длину рабочего цикла в слонах, мартышках и попугаях, давайте наглядно сравним две ситуации:


  1. Дизайнер и фронт работают, как они привыкли каждый это делать дизайнер создает макет в Figma, далее фронт переносит всё в код;
  2. Дизайнер и фронт совместно создают проект в Quarkly.

И не будем забывать, что помимо скорости нас также интересует, какие болевые точки можно при этом обойти. Опасные моменты я буду обозначать по шкале от 1 до 5 ударов мизинцем ноги о комод.



Хорошая спецификация в условиях работы на потоке (неважно при этом, большая это компания или маленькая студия) это очень важно. Хорошая спецификация не гарантия, но весомая заявка, что боли в процессе работы получится избежать.


Неполная спецификация бомба замедленного действия. Может быть, всё обойдется, если лунные циклы сойдутся, Марс в созвездии Овна не будет против, а дизайнер и разработчик поймут друг друга, как нужно.


Другой опасный момент когда макеты нарисованы дизайнером, не понимающим, что с ними будет дальше на следующем этапе. Вряд ли нужно пояснять, откуда и какая боль здесь может приключиться.


Наконец, самое печальное это когда такие макеты попадают к разработчику. Больно будет ему, больно будет дизайнеру, к которому он будет постоянно приходить с вопросами.



Макет дизайнера уже является кодом. Разработчику нужно лишь проверить сложные логики, с которыми не может справиться дизайнер.



Наш канал на YouTube, где можно найти полезные мануалы: смотреть


Наш чат в телеграме: https://t.me/quarklyapp

Подробнее..

Используйте ссылки и кнопки правильно. Пожалуйста

09.06.2021 14:20:05 | Автор: admin

При вёрстке макета не всегда понятно, что перед нами кнопка или ссылка. Внешне эти элементы могут быть очень похожи, но их функции различаются и браузер реагирует на них по-разному. Поэтому неправильный выбор может привести к ошибкам в работе сайта.

Почему возникает проблема

Ссылка это элемент навигации. Обычно она представляет собой текст, нажимая на который, пользователь переходит на другую страницу или перемещается к другому месту на текущей странице. То есть ссылка отвечает за взаимосвязь веб-ресурсов или разделов одного ресурса.

Ссылки создаются с помощью тега <a>.

<a href="http://personeltest.ru/aways/htmlacademy.ru">HTML Academy</a>

Кнопка это функциональный элемент. Она отвечает за выполнение определённой функции: добавить в корзину, купить, отправить, проголосовать и т. д.

Для кнопок используют тег <button>.

<button class="button">9 900 руб.</button>

Проблемы возникают, когда внешне кнопка очень похожа на ссылку текст без плашки, или ссылка напоминает кнопку текст расположен на фоне прямоугольной плашки.

Пример двух кнопок, где нижняя похожа на ссылкуПример двух кнопок, где нижняя похожа на ссылкуПример ссылки, похожей на кнопкуПример ссылки, похожей на кнопку

Что случится, если вместо ссылки сделать кнопку

Если URL-адрес обернуть не <а>, а тегом <button>, то при нажатии пользователя на правую кнопку мыши браузер предложит выполнить действия, которые положены при клике на кнопку. Адрес нельзя будет открыть в новой вкладке или отправить через контекстное меню.

Контекстное меню при клике правой кнопкой мыши на кнопкуКонтекстное меню при клике правой кнопкой мыши на кнопку

Такая кнопка не позволит открыть страницу в новой вкладке и через комбинацию клавиш Ctrl и левая кнопка мыши.

При наведении курсора на правильную ссылку её адрес появляется внизу окна браузера. URL-адрес, обёрнутый в <button>, не отобразится.

Адрес правильной ссылки в окне браузера при наведении на неё курсораАдрес правильной ссылки в окне браузера при наведении на неё курсора

Что произойдёт, если вместо кнопки сделать ссылку

Когда мы кликаем на ссылку правой кнопкой, браузер показывает, что можно сделать именно со ссылкой.

Контекстное меню при клике правой кнопкой мыши на ссылкуКонтекстное меню при клике правой кнопкой мыши на ссылку

Если функциональный элемент обернуть тегом <a>, то при клике правой кнопкой мыши всплывающее окно будет как у ссылки, но оно не будет иметь смысла. Такая ссылка не имеет корректного адреса, а значит открыть, сохранить, копировать её или поделиться ею невозможно.

<a href="javascript:;">На самом деле это кнопка</a>

При наведении курсора на псевдоссылку внизу окна браузера появится не адрес, а javascript:; или АдресТекущейСтраницы/#.

Как определить элемент по макету

Конкретные указания часто прописывают в техническом задании к макету. В стайлгайде самого макета можно посмотреть состояния элемента.

У ссылки должны быть стили для состояния покоя, при наведения курсора :hover, в момент нажатия :focus, активного :active и иногда состояния, когда пользователь уже посещал эту страницу :visited.

У кнопки нет состояния :visited, зато есть состояние блока :disabled.

Состояния ссылок в стайлгайде макетаСостояния ссылок в стайлгайде макета

Однако рассчитывать только на макет не нужно. У ссылки может не быть :visited, а у блока :disabled это может запутать.

Забудьте про div семантика спасёт интернет

Всё-таки кнопка или ссылка?

Если дизайнер по каким-то причинам не отрисовал состояния вообще, то придётся руководствоваться одной логикой.

Ссылка

Кнопка

За что отвечает

Навигация, т. е. пользователь перемещается на другую часть страницы или на новую страницу.

Выполнение какой-либо функции без перехода на другую страницу добавить в корзину, купить, отправить, проголосовать, войти и т. д.

Что видит пользователь

При наведении курсора на ссылку внизу окна браузера возникает её адрес.

Через меню по клику правой кнопкой мыши можно скопировать, отправить, открыть ссылку в новой вкладке.

При наведении курсора на ссылку внизу окна браузера не отображается адрес.

Через меню по клику правой кнопкой мыши нельзя скопировать адрес или поделиться им.

Пример, чтобы расставить всё по своим местам

На макете отрисована фраза Войти. Если клик по ней должен открывать окно для ввода регистрационных данных на этой же странице, это кнопка. Если при нажатии должна открываться отдельная страница для входа, это ссылка.

Другие великие противостояния


Ссылки ссылками, а промокод VESELO даст приятную скидку на любой профессиональный курс в HTML Academy. Например, на курс Анимации для фронтендеров можно записаться в любой момент, а пользы для карьеры будет целый вагон.

Подробнее..

Автоматизируем локализацию макетов в Figma

29.12.2020 14:10:26 | Автор: admin
В один прекрасный момент наши дизайнеры решили, что пора обновить обложки
нашего приложения в Apple Store и Google Play. На всех 17 языках.

Это история про то, как нырнуть в незнакомый язык программирования, незнакомую платформу и незнакомую задачу, собрать много всего интересного, помочь коллегам и оставить след в open source community.

мемасик



обложки

После подготовки макетов в Figma пришло осознание страшного факта: мы должны поддержать 17 различных языков! Причем максимально качественно и согласованно, так что автоматические переводы через Google Translate (или даже сервис Crowdin) нам не подходили. Что ж, задача была поручена ответственным людям, и вот через некоторое время у нас появилась табличка Google Sheets с переводами всех фраз.

таблица с переводами

Первая попытка ручной замены текстов в макетах привела к следующему:

  • было потрачено около 40 минут;
  • были допущены мелкие ошибки форматирования;
  • заменяющий вносил свои правки в переводы (потому что знал язык) и нигде это не фиксировал;
  • пропало желание повторять эту процедуру, а значит, и вносить какие-либо изменения.

И задача резко обрела пугающий объем и сложность. Требовалась автоматизация.

Конечно же, хотелось бы воспользоваться готовым решением. Однако из рассмотренных (Crowdin, Localize, Yandex.Translate) ни одно нас не устроило, так как они не позволяют использовать кастомизированные переводы и полностью игнорируют форматирование (подсветку, выделения). А в идеале решение должно было давать практически готовый результат, не требующий вмешательства человека.

Как известно, подобные проблемы лучше всего решаются за чашечкой чая в компании коллег-разработчиков на уютной офисной кухне. Несмотря на то, что в нашей команде нет разработчиков, хорошо знакомых с Figma и ее возможностями, никто не брезгует TypeScript'ом, и все способны написать на нем плагин по документации. Даже Golang и Kotlin разработчики заднего конца. Более того, небольшой опыт у некоторых уже имелся.

Написание плагинов для Figma


Figma предоставляет достаточно подробную документацию по созданию плагинов. Код плагина делится на клиентскую и серверную части, при этом только у последней есть доступ к структуре документа (названия условные, потому что обе выполняются локально). Клиентская часть отвечает за взаимодействие с пользователем через HTML-интерфейс. Возможности API так же хорошо описаны в соответствующей документации.

Разработка плагина ведется исключительно в десктоп-версии Figma, которая по сути является обычным WebView, поэтому разработчику доступна консоль JavaScript и прочие привычные инструменты.

После беглого осмотра стало ясно, что API поддерживает поиск нод, редактирование текста и стилей, то есть в теории позволяет нам осуществить задуманное.

Автоматический перевод по словарю


Автозамена


Было решено за полчасика сделать PoC, который будет в состоянии просто подменить все тексты в соответствии с табличкой. Пока с максимально примитивным UI, конечно же.

Итак, для начала нам нужно загрузить словарь. Поскольку заморачиваться с подключением сторонних модулей на первом этапе не хотелось, решил выбрать самый простой формат, в который можно выгрузить имеющуюся табличку из Google Sheets. Между CSV и TSV выбор пал на TSV: в текстах могли присутствовать запятые, это усложнило бы парсинг.

Парсим табличку
type Dictionary = {    header: string[];    rows: string[][];};async function parseDictionary(serializedDictionary: string): Promise<Dictionary> {    const table = serializedDictionary.split('\n').map(line => line.split('\t').map(field => field.trim()));    if (table.length === 0) {        throw {error: 'no header in the dictionary'};    }    // в заголовке будут языковые коды    const header = table[0];    const expectedColumnCount = header.length;    const rows = table.slice(1, table.length);    console.log('Dictionary:', {header, rows});    rows.forEach((row, index) => {        if (row.length != expectedColumnCount) {            throw {error: 'row ' + (index + 2) + ' of the dictionary has ' + row.length + ' (not ' + expectedColumnCount + ') columns'};        }    });    return {header, rows};}

Строим словарь для выбранной пары языков
type Mapping = {    [source: string]: string;};async function getMapping(dictionary: Dictionary, sourceLanguage: string, targetLanguage: string): Promise<Mapping> {    const sourceColumnIndex = dictionary.header.indexOf(sourceLanguage);    if (sourceColumnIndex == -1) {        throw {error: sourceLanguage + ' not listed in [' + dictionary.header + ']'};    }    const targetColumnIndex = dictionary.header.indexOf(targetLanguage);    if (targetColumnIndex == -1) {        throw {error: targetLanguage + ' not listed in [' + dictionary.header + ']'};    }    const result: Mapping = {};    dictionary.rows.forEach(row => {        const sourceString = row[sourceColumnIndex];        const targetString = row[targetColumnIndex];        if (targetString.trim() !== '') {            if (sourceString in result) {                throw {error: 'multiple translations for `' + sourceString + '` in the dictionary'};            }            result[sourceString] = targetString;        }    });    // крайне удобный способ отладки в случае с Figma    console.log('Extracted mapping:', result);    return result;}

Подставляем переводы во все текстовые ноды по прямому совпадению
type Replacement = null | {    // в какой ноде заменяем текст    node: TextNode;    // на что заменяем    translation: string;};type ReplacementFailure = {    // в какой ноде произошла ошибка    nodeId: string;    // описание самой ошибки    error: string;};type ReplacementAttempt = Replacement | ReplacementFailure;// Settings получаются элементарно из UIasync function translateSelection(settings: Settings): Promise<void> {    const dictionary = await parseDictionary(settings.serializedDictionary);    const mapping = await getMapping(dictionary, settings.sourceLanguage, settings.targetLanguage);    await replaceAllTexts(mapping);}async function replaceAllTexts(mapping: Mapping): Promise<void> {    const textNodes = await findSelectedTextNodes();    let replacements = (await Promise.all(textNodes.map(node => computeReplacement(node, mapping)))).filter(r => r !== null);    let failures = replacements.filter(r => 'error' in r) as ReplacementFailure[];    if (failures.length > 0) {        console.log('Failures:', failures);        throw {error: 'found some untranslatable nodes', failures};    }    replacements.forEach(replaceText);}async function findSelectedTextNodes(): Promise<TextNode[]> {    const result: TextNode[] = [];    figma.currentPage.selection.forEach(root => {        if (root.type === 'TEXT') {            // либо в выделение попала текстовая нода            result.push(root as TextNode);        } else if ('findAll' in root) {            // либо фрейм/группа,            // тогда в ней можно найти все текстовые подноды встроенной функцией findAll            (root as ChildrenMixin).findAll(node => node.type === 'TEXT').forEach(node => result.push(node as TextNode));        }    });    return result;}async function computeReplacement(node: TextNode, mapping: Mapping): Promise<ReplacementAttempt> {    // текст ноды может содержать лишние пробелы и переносы слов,    // и это не должно влиять на возможность перевода,    // поэтому предварительно нормализуем строки    const content = normalizeContent(node.characters);    if (!(content in mapping)) {        // не нашли перевод? жаль        return {nodeId: node.id, error: 'No translation for `' + content + '`'};    }    const result: Replacement = {        node,        translation: mapping[content],    };    console.log('Replacement:', result);    return result;}function normalizeContent(content: string): string {    // интересные факты из жизни Unicode:    //   \u2028  разделитель строк (но не \n)    //   \u202F  невидимый разделитель пробелов (?)    // по-хорошему, стоит добавить и прочие разделители,    // но они на практике пока не встречались    return content.replace(/[\u000A\u00A0\u2028\u202F]/g, ' ').replace(/ +/g, ' ');}async function replaceText(replacement: Replacement): Promise<void> {    const {node, translation} = replacement;    // интересная особенность Figma:    // перед тем, как менять что-либо в текстовой ноде, нужно предварительно    // загрузить все шрифты, которые в ней используются    await loadFontsForNode(node);    node.characters = translation;}async function loadFontsForNode(node: TextNode): Promise<void> {    await Promise.all(Array.from({length: node.characters.length}, (_, k) => k).map(i => {        // очень забавный момент, конечно:        // Figma позволяет узнать свойства любой секции текста в ноде,        // при этом если в секции оно неоднородно (например, используется несколько шрифтов),        // то возвращается специальный объект mixed        return figma.loadFontAsync(node.getRangeFontName(i, i + 1) as FontName);    }));}

Вся эта конструкция довольно быстро заработала, что порадовало и вселило уверенность.

базовая реализация

Исключения


При первом же запуске было обнаружено множество текстов, не требующих переводов. Потому они и не фигурировали в исходной табличке.

исключения

Имена собственные, числа, валюты, какие-то символы, эмодзи Не беда. Достаточно задать исключения в виде списка регулярок.

Учитываем исключения
async function translateSelection(settings: Settings): Promise<void> {    const dictionary = await parseDictionary(settings.serializedDictionary);    const mapping = await getMapping(dictionary, settings.sourceLanguage, settings.targetLanguage);    // дополнительно учитываем список исключений    const exceptions = await parseExceptions(settings.serializedExceptions);    await replaceAllTexts(mapping, exceptions);}async function parseExceptions(serializedExceptions: string): Promise<RegExp[]> {    return serializedExceptions.split('\n').filter(pattern => pattern !== '').map(pattern => {        try {            return new RegExp(pattern);        } catch (_) {            throw {error: 'invalid regular expression `' + pattern + '`'};        }    });}async function replaceAllTexts(mapping: Mapping, exceptions: RegExp[]): Promise<void> {    const textNodes = await findSelectedTextNodes();    // пробрасываем список в функцию вычисления подстановки    let replacements = (await Promise.all(textNodes.map(node => computeReplacement(node, mapping, exceptions)))).filter(r => r !== null);    let failures = replacements.filter(r => 'error' in r) as ReplacementFailure[];    if (failures.length > 0) {        console.log('Failures:', failures);        throw {error: 'found some untranslatable nodes', failures};    }    replacements.forEach(replaceText);}async function computeReplacement(node: TextNode, mapping: Mapping, exceptions: RegExp[]): Promise<ReplacementAttempt> {    const content = normalizeContent(node.characters);    // если содержимое подходит под одну из регулярок    if (keepAsIs(content, exceptions)) {        // то говорим, что заменять текст в этой ноде не нужно совсем        return null;    }    if (!(content in mapping)) {        // не нашли перевод? жаль        return {nodeId: node.id, error: 'No translation for `' + content + '`'};    }    const result: Replacement = {        node,        translation: mapping[content],    };    console.log('Replacement:', result);    return result;}function keepAsIs(content: string, exceptions: RegExp[]): boolean {    for (let regex of exceptions) {        if (content.match(regex)) {            return true;        }    }    return false;};

Форматирование


Теперь не хватало лишь вишенки на торте.

автоперевод без форматирования

Видно, что наивная подстановка текста переформатирует его в соответствии со стилем
самой первой буквы. Можем ли мы как-то сохранить сложное форматирование? Кажется, да. Можно дополнительно к основному тексту перевести отдельно выделенную часть. Затем в переводе основного текста найти перевод выделенной части и переформатировать его. Только вот далеко не всегда ясно, какая часть текста является выделенной. Но мы можем перебирать имеющиеся стили в поисках основного, мы же точно знаем, что он один.

Итого.

  1. Разбиваем исходный форматированный текст на непрерывные моностильные секции.
  2. Перебираем использующиеся в тексте стили, рассматривая каждый в качестве основного.

    • Пробуем перевести все секции других стилей.
    • Пробуем найти переводы секций других стилей внутри общего перевода (перевода всего текста).
    • Считаем, что нашли основной стиль, если предыдущие два пункта завершились успешно.

  3. Подставляем сначала общий перевод и применяем к нему основной стиль.
  4. Для каждого вычисленного выделения в переводе применяем соответствующий ему стиль.

алгоритм

При реализации пришлось учесть, что Figma не имеет какого-то общего объекта для описания стиля, только для отдельных его параметров, и дописать небольшую обертку для этого. При этом естественная посимвольная итеративная реализация пункта 1 становится крайне дорогой. Благо, существует довольно элегантный и эффективный рекурсивный алгоритм.

Разбиваем тексты на моностильные секции
type Style = {    // это поле будет хранить уникальный идентификатор    // так можно будет быстро сравнивать стили между собой    id: string;    fills: Paint[];    fillStyleId: string;    fontName: FontName;    fontSize: number;    letterSpacing: LetterSpacing;    lineHeight: LineHeight;    textDecoration: TextDecoration;    textStyleId: string;};type Section = {    // начало секции, включительно, индексация с 0    from: number;    // конец секции, не включительно, индексация с 0    to: number;    // стиль всей секции    style: Style;};function sliceIntoSections(node: TextNode, from: number = 0, to: number = node.characters.length): Section[] {    if (to == from) {        return [];    }    const style = getSectionStyle(node, from, to);    if (style !== figma.mixed) {        // это моностильная секция        return [{from, to, style}];    }    // разделяй и властвуй!    const center = Math.floor((from + to) / 2);    const leftSections = sliceIntoSections(node, from, center);    const rightSections = sliceIntoSections(node, center, to);    const lastLeftSection = leftSections[leftSections.length-1];    const firstRightSection = rightSections[0];    if (lastLeftSection.style.id === firstRightSection.style.id) {        firstRightSection.from = lastLeftSection.from;        leftSections.pop();    }    return leftSections.concat(rightSections);}function getSectionStyle(node: TextNode, from: number, to: number): Style | PluginAPI['mixed'] {    const fills = node.getRangeFills(from, to);    if (fills === figma.mixed) {        return figma.mixed;    }    const fillStyleId = node.getRangeFillStyleId(from, to);    if (fillStyleId === figma.mixed) {        return figma.mixed;    }    const fontName = node.getRangeFontName(from, to);    if (fontName === figma.mixed) {        return figma.mixed;    }    const fontSize = node.getRangeFontSize(from, to);    if (fontSize === figma.mixed) {        return figma.mixed;    }    const letterSpacing = node.getRangeLetterSpacing(from, to);    if (letterSpacing === figma.mixed) {        return figma.mixed;    }    const lineHeight = node.getRangeLineHeight(from, to);    if (lineHeight === figma.mixed) {        return figma.mixed;    }    const textDecoration = node.getRangeTextDecoration(from, to);    if (textDecoration === figma.mixed) {        return figma.mixed;    }    const textStyleId = node.getRangeTextStyleId(from, to);    if (textStyleId === figma.mixed) {        return figma.mixed;    }    const parameters = {        fills,        fillStyleId,        fontName,        fontSize,        letterSpacing,        lineHeight,        textDecoration,        textStyleId,    };    return {        id: JSON.stringify(parameters),        ...parameters,    };}

Сохраняем форматирование при подстановке текста
// придется немного расширить нашу структуру подстановкиtype Replacement = null | {    node: TextNode;    translation: string;    // тот самый "основной" стиль    baseStyle: Style;    // разметка translation на секции со стилями, отличными от основного    sections: Section[];};async function computeReplacement(node: TextNode, mapping: Mapping, exceptions: RegExp[]): Promise<ReplacementAttempt> {    const content = normalizeContent(node.characters);    if (keepAsIs(content, exceptions)) {        return null;    }    if (!(content in mapping)) {        return {nodeId: node.id, error: 'No translation for `' + content + '`'};    }    // режем на моностильные секции    const sections = sliceIntoSections(node);    // готовим результат    const result: Replacement = {        node,        translation: mapping[content],        baseStyle: null,        sections: [],    };    // формируем лог ошибок на случай безуспешных поисков    const errorLog = [        'Cannot determine a base style for `' + content + '`',        'Split into ' + sections.length + ' sections',    ];    // собираем множество задействованных стилей    const styles = [];    const styleIds = new Set<string>();    sections.forEach(({from, to, style}) => {        if (!styleIds.has(style.id)) {            styleIds.add(style.id);            styles.push({humanId: from + '-' + to, ...style});        }    });    for (let baseStyleCandidate of styles) {        const prelude = 'Style ' + baseStyleCandidate.humanId + ' is not base: ';        let ok = true;        // будем попутно собирать разметку для неосновных стилей        result.sections.length = 0;        for (let {from, to, style} of sections) {            if (style.id === baseStyleCandidate.id) {                continue;            }            const sectionContent = normalizeContent(node.characters.slice(from, to));            let sectionTranslation = sectionContent;            // либо мы должны уметь переводить секцию,            // либо она должна входить в список исключений            if (sectionContent in mapping) {                sectionTranslation = mapping[sectionContent];            } else if (!keepAsIs(sectionContent, exceptions)) {                errorLog.push(prelude + 'no translation for `' + sectionContent + '`');                ok = false;                break;            }            const index = result.translation.indexOf(sectionTranslation);            if (index == -1) {                errorLog.push(prelude + '`' + sectionTranslation + '` not found within `' + result.translation + '`');                ok = false;                break;            }            if (result.translation.indexOf(sectionTranslation, index + 1) != -1) {                errorLog.push(prelude + 'found multiple occurrencies of `' + sectionTranslation + '` within `' + result.translation + '`');                ok = false;                break;            }            result.sections.push({from: index, to: index + sectionTranslation.length, style});        }        if (ok) {            // нашли основной стиль!            result.baseStyle = baseStyleCandidate;            break;        }    }    if (result.baseStyle === null) {        return {nodeId: node.id, error: errorLog.join('. ')};    }    console.log('Replacement:', result);    return result;}async function replaceText(replacement: Replacement): Promise<void> {    // нет необходимости вызывать загрузку для каждого символа,    // когда мы уже получили разбиение по стилям    await loadFontsForReplacement(replacement);    const {node, translation, baseStyle, sections} = replacement;    node.characters = translation;    if (sections.length > 0) {        setSectionStyle(node, 0, translation.length, baseStyle);        for (let {from, to, style} of sections) {            setSectionStyle(node, from, to, style);        }    }}async function loadFontsForReplacement(replacement: Replacement): Promise<void> {    await figma.loadFontAsync(replacement.baseStyle.fontName);    await Promise.all(replacement.sections.map(({style}) => figma.loadFontAsync(style.fontName)));}function setSectionStyle(node: TextNode, from: number, to: number, style: Style): void {    node.setRangeTextStyleId(from, to, style.textStyleId);    node.setRangeFills(from, to, style.fills);    node.setRangeFillStyleId(from, to, style.fillStyleId);    node.setRangeFontName(from, to, style.fontName);    node.setRangeFontSize(from, to, style.fontSize);    node.setRangeLetterSpacing(from, to, style.letterSpacing);    node.setRangeLineHeight(from, to, style.lineHeight);    node.setRangeTextDecoration(from, to, style.textDecoration);}

Стоит сразу отметить, что много внимания теперь было уделено адекватным сообщениям
об ошибке. Алгоритм не совсем очевидный для непосвященного человека, и понятно сформулировать, что именно в алгоритме выше пошло не так крайне сложно.

Да и алгоритм при этом далеко не идеальный. Например, во фразе Отличное качество, все еще как новые еще слово еще встречается два раза, что при переводе на некоторые языки ведет к тому, что и в переводе оно встречается тоже в двух местах. В итоге наш алгоритм не в состоянии определить, какое из двух вхождений нужно выделить жирным. Такую ситуацию, к сожалению, невозможно исправить без прокачки формата входных данных. Еще может так произойти, что одно и то же слово используется в разных контекстах, при этом оно как-то выделено. В этом случае мы упадем еще на этапе обработки словаря, так как не поддерживаем несколько переводов для одного слова.

автоперевод с форматированием

На данном этапе мы уже сделали приятный интерфейс и могли переводить макеты на почти все языки одним нажатием на кнопку! Выглядело фантастически, честно говоря.

Сообщения об ошибках и отладка


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

Нас спас только развернутый список ошибок с интерактивными ссылками на ноды, в которых те возникли. В Figma это можно организовать посылкой специального сообщения в серверную часть плагина с таким обработчиком:

if (message.type === 'focus-node') {    // максимально приближаемся    figma.viewport.zoom = 1000.0;    // перемещаем viewport в положение, где нода видна целиком    figma.viewport.scrollAndZoomIntoView([figma.getNodeById(message.id)]);    // немного отдаляем для комфортного восприятия    figma.viewport.zoom = 0.75 * figma.viewport.zoom;}


В дальнейшем также оказалось полезным уметь формировать задания для переводчиков автоматически. Все, что необходимо для этого, мы, на самом деле, уже подготовили. Просто среди потенциальных основных стилей выберем тот, что охватывает наибольшее число символов.

Предлагаем доперевести некоторые фразы
function suggest(node: TextNode, content: string, sections: Section[], mapping: Mapping, exceptions: RegExp[]): string[] {    const n = content.length;    const styleScores = new Map<string, number>();    for (let {from, to, style} of sections) {        styleScores.set(style.id, n + to - from + (styleScores.get(style.id) || 0));    }    let suggestedBaseStyleId: string = null;    let suggestedBaseStyleScore = 0;    for (let [styleId, styleScore] of styleScores) {        if (styleScore > suggestedBaseStyleScore) {            suggestedBaseStyleId = styleId;            suggestedBaseStyleScore = styleScore;        }    }    const result: string[] = [];    if (!(content in mapping)) {        result.push(content);    }    for (let {from, to, style} of sections) {        if (style.id === suggestedBaseStyleId) {            continue;        }        const sectionContent = normalizeContent(node.characters.slice(from, to));        if (!keepAsIs(sectionContent, exceptions) && !(sectionContent in mapping)) {            result.push(sectionContent);        }    }    return result;}

ошибки


Казалось, все должно было прекрасно работать и с RTL языками, так как мы лишь выполнили замену вхождений по точному совпадению. Однако внезапно выяснилось, что Figma не умеет корректно отображать RTL тексты рендерит их слева направо. А лезть в дебри особенностей рендеринга RTL текстов последнее, чего бы хотелось.

Да, нашлось несколько плагинов для интерактивного ввода арабского текста и один разломанный плагин, пытающийся разворачивать RTL тексты, но все это не решило нашу проблему. Хотя бы потому, что при этом напрочь слетало форматирование.

Аппетит приходит во время еды. Пути назад уже не было. Была видна лишь возможность сделать из этого проекта действительно полнофункциональный плагин.

Что может быть сложного? Давайте просто развернем текст посимвольно.

наивный подход к RTL

Так. Теперь все рендерится справа налево, но Figma вставляет по привычке автопереносы строк так, словно это LTR текст. В итоге строки нужно читать снизу вверх. Беда. Факт расстановки автопереносов Figma не отражает в содержимом ноды, да и вообще, никак нигде не отражает Разве что Если нода имеет адаптивную высоту, то при возникновении автопереноса высота ноды изменяется!

Итак, план такой.

  1. Разворачиваем перевод, как раньше.
  2. Создаем невидимую текстовую ноду с адаптивной высотой и той же шириной (если, конечно, ширина исходной ноды тоже фиксирована).
  3. Разбиваем развернутый перевод на слова и начинаем добавлять их в скрытую ноду по одному (справа налево). Если вдруг высота скрытой ноды изменилась, откатываемся, вставляем разделитель строк и продолжаем.
  4. Получившееся разбиение на строки просто конкатенируем.
  5. Удаляем временную ноду.
  6. Инвертируем выравнивание текста (если было по левому краю, то делаем по правому, и наоборот).

Большая сложность заключается в том, что в процессе нужно внимательно следить за тем, как видоизменяются секции.

К тому же, на ровном месте возникло несколько подводных камней.

  • Большинство шрифтов из коробки не поддерживают арабский и иврит. Пришлось искать похожие по начертанию (а их не так много).
  • Нельзя просто брать и разворачивать текст, если он содержит, например, латиницу, цифры и т.п. Эти части должны писаться слева направо даже в RTL тексте.
  • От стиля зависит размер слов, так что внутри скрытой ноды текст нужно правильно форматировать.
  • Первое слово в очередной строке может не влезть по ширине, тогда это ошибка, о которой нужно сообщить.
  • Нашлись слова в арабском, которые в отсутствие пробела после них отображались в Figma некорректно.

Полный код поддержки RTL языков я здесь приводить не стану он доступен в репозитории.

Этот этап занял гораздо больше времени и сил, чем реализация базовой функциональности плагина, но результат был поистине впечатляющим!

автоперевод на арабский

На десерт.

  • Правильное обращение арабского текста куда более сложная задача, чем кажется, если учесть всевозможные примеси из других языков и специальные лигатуры.
  • Интерфейсы на RTL языках необходимо отразить по горизонтали, что пока приходится делать вручную, хотя потенциально и это автоматизируется.
  • Попутно нами был обнаружен и зарепорчен баг в Figma, из-за которого при добавлении латиницы в арабский текст лигатуры развязывались.

Конвертирование валют


Так уж случилось, что мы маркетплейс, и у нас есть товары. И товары имеют цену. Можно, конечно, отдать с десяток текстов вида 1 234 переводчикам и надеяться, что они правильно локализуют цены, использовав верные разделители, верные знаки валют и верное количество цифр после запятой Но зачем, если можно все это проделать автоматически, один раз настроив несложный конвертер?

Конвертируем валюты автоматически
type Currency = {    // уникальный код, у нас для удобства совпадает с языковым    code: string;    // схема, в которой 123 нужно заменить на нужную сумму в нужном формате, вроде "$123"    schema: string;    // разделитель тысяч    digitGroupSeparator: string;    // разделитель дробной части (обычно точка или запятая)    decimalSeparator: string;    // кол-во десятичных знаков в дробной части    precision: number;    // курс к некоторой базовой валюте (должна быть общей для всего конфига)    rate: number;};async function convertCurrencyInSelection(settings: Settings): Promise<void> {    const currencies = parseCurrencies(settings.serializedCurrencies);    console.log('Currencies:', currencies);    const sourceCurrency = currencies.filter(currency => currency.code === settings.sourceCurrencyCode)[0];    if (sourceCurrency === undefined) {        throw {error: 'unknown currency code `' + settings.sourceCurrencyCode + '`'};    }    const targetCurrency = currencies.filter(currency => currency.code === settings.targetCurrencyCode)[0];    if (targetCurrency === undefined) {        throw {error: 'unknown currency code `' + settings.targetCurrencyCode + '`'};    }    await replaceCurrencyInAllTexts(sourceCurrency, targetCurrency);}function parseCurrencies(serializedCurrencies: string): Currency[] {    const codeSet = new Set<string>();    return JSON.parse(serializedCurrencies).map((x: any, index: number) => {        const currency: Currency = {            code: null,            schema: null,            digitGroupSeparator: null,            decimalSeparator: null,            precision: null,            rate: null,        };        Object.keys(currency).forEach(key => {            if (x[key] === undefined || x[key] === null) {                throw {error: 'invalid currency definition: no `' + key + '` in entry #' + (index + 1)};            }            if (key === 'schema' && x[key].indexOf('123') === -1) {                throw {error: 'schema in entry #' + (index + 1) + ' should contain `123`'};            }            if (key === 'rate' && x[key] <= 0) {                throw {error: 'non-positive rate in entry #' + (index + 1)};            }            currency[key] = x[key];        });        if (currency.precision > 0 && currency.decimalSeparator === '') {            throw {error: 'entry #' + (index + 1) + ' must have a non-empty decimal separator'};        }        if (codeSet.has(currency.code)) {            throw {error: 'multiple entries for `' + currency.code + '`'};        }        codeSet.add(currency.code);        return currency;    });}async function replaceCurrencyInAllTexts(sourceCurrency: Currency, targetCurrency: Currency): Promise<void> {    const textNodes = await findSelectedTextNodes();    const escapedSchema = escapeForRegExp(sourceCurrency.schema);    const escapedDigitGroupSeparator = escapeForRegExp(sourceCurrency.digitGroupSeparator);    const escapedDecimalSeparator = escapeForRegExp(sourceCurrency.decimalSeparator);    const sourceValueRegExpString = '((?:[0-9]|' + escapedDigitGroupSeparator + ')+' + escapedDecimalSeparator + '[0-9]{' + sourceCurrency.precision + '})';    const sourceRegExp = new RegExp('^' + escapedSchema.replace('123', sourceValueRegExpString) + '$');    console.log('Source regular expression:', sourceRegExp.toString());    await Promise.all(textNodes.map(async node => {        const content = node.characters;        const match = content.match(sourceRegExp);        if (match !== null && match[1] !== null && match[1] !== undefined) {            const style = getSectionStyle(node, 0, node.characters.length);            if (style === figma.mixed) {                throw {error: 'node `' + content + '` has a mixed style'};            }            let sourceValueString = match[1].replace(new RegExp(escapedDigitGroupSeparator, 'g'), '');            if (sourceCurrency.decimalSeparator !== '') {                sourceValueString = sourceValueString.replace(sourceCurrency.decimalSeparator, '.');            }            const sourceValue = parseFloat(sourceValueString);            const targetValue = sourceValue * targetCurrency.rate / sourceCurrency.rate;            const truncatedTargetValue = Math.trunc(targetValue);            const targetValueFraction = targetValue - truncatedTargetValue;            const targetValueString = (                truncatedTargetValue.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,').replace(/,/g, targetCurrency.digitGroupSeparator) +                targetCurrency.decimalSeparator +                targetValueFraction.toFixed(targetCurrency.precision).slice(2)            );            await figma.loadFontAsync(style.fontName);            node.characters = targetCurrency.schema.replace('123', targetValueString);        }    }));}function escapeForRegExp(s: string): string {    return s.replace(/([[\^$.|?*+()])/g, '\\$1');}

конвертация валют

Публикация


Перед публикацией плагина был проделан ряд улучшений UX. Например, настройки в интерфейсе плагина сохранялись в localStorage (да, Figmа такое умеет!). Это позволяет не загружать словари каждый раз и быстро выполнять переводы на несколько языков. А чтобы интерфейс не зависал во время активных операций с документом, по рекомендации самой же Figma, была ограничена интенсивность асинхронных параллельных операций с помощью простой самописной функции mapWithRateLimit. На сдачу в плагин была добавлена возможность заменять шрифты.

Процедура публикации плагина заняла больше двух недель, но никаких проблем не возникло.

В заключение


Без плагина не обошлась и подготовка к Новому году.

новый год

Возможно, когда-нибудь мы расскажем, как в рамках той же задачи научились выгружать из Figma весь документ в виде одного структурированного архива из картинок.

Хочется поблагодарить Аню Ноджак, дизайн-директора Joom, за веру в мои силы. Очень рекомендую почитать ее взгляд на задачу.

Ссылки


Исходный код плагина Static Localizer на GitHub
Плагин Static Localizer на сайте Figma
Подробнее..

6 способов дополнительного дохода для дизайнеров и разработчиков

27.09.2020 12:08:21 | Автор: admin

Эта статья поможет как начинающим дизайнерам и разработчикам, так и опытным специалистам, мечтающим улучшить свое финансовое положение. Если у вас сейчас есть стабильная и высокооплачиваемая работа - всегда есть риск, что вы можете попасть под сокращение. Пандемия отлично показала, что сейчас очень важно иметь финансовую подушку безопасности и дополнительные источники дохода.

Запуская собственный side project, вы имеете все шансы сделать его основным вашим занятием. Иногда такие проекты даже становятся делом всей жизни. СайтSetproduct.comявляется тому живым доказательством. Он начинался как сторонний проект, который уже через 2 месяца стал основным источником дохода. Неплохо, учитывая, что автор не мечтал и не планировал становиться предпринимателем.

Все ниже перечисленные способы являются практичными и проверенными. Некоторые из них мы практикуем сами. Какие-то из них предполагают быстрый заработок, другие потребуют значительных затрат вашего времени. В любом случае беритесь за дело твердо веря в то, что вы приносите пользу людям. Создавайте ценность это самое главное.

Что нужно иметь ввиду перед тем, как начать?

Ваши навыки и анализ проблем рынка

Для начала, составьте список своих навыков. Вам нужно выявить в чем вы хороши, а в чем не очень. Будьте честны с собой. Такой список поможет вам определиться с тем, на что стоит делать упор, а на что не тратить свое время. Помимо навыков, вам будет необходимо провести анализ рынка.

Соберите все решаемые вами задачи за последние годы. Здесь важно умение определить какова самая частая проблема, и нет ли такой же проблемы у кого-то еще, помимо вас. Заходите во всевозможные дизайнерские ресурсы: Dribbble, Behance, Webdesignernews, Reddit и т.д. На этих ресурсах дизайнеры любят обмениваться мыслями и опытом. Среди похвалы и обычного обсуждения, можно встретить различные вопросы, типа: Как тебе удалось это сделать? или Где можно найти такой-то элемент?. Вот на такие вопросы и нужно обращать внимание. Нужно создавать проект, который будет отвечать на вопросы людей и решать их проблемы.

Поиск ниши и клиентов

Начните сужать направления, чтобы стать успешным в каком-то конкретном деле. Сегодня появляются небольшие рынки вокруг успешных приложений и это новые возможности. Взять, к примеру, Setproduct: мы создаем дизайн-системы и UI киты только для клиентов, работающих на Фигме.

Вы можете сосредоточиться на создании эффектных лендингов для различных кофе-шопов, медицинских центров, салонов красоты, персональных фитнес-инструкторов, если любите создавать сайты. Или вы можете специализироваться исключительно на создании приложений для iOS или Android. Рынок услуг очень разнообразен, и возможностей найти свое направление и неплохо заработать тоже очень много.

Создание своего сайта

После того, как вы определились со своими навыками и нишей, вам понадобится отлично оформленный сайт-портфолио или личный блог. Он будет эффективно сказываться на продвижении вас как бренда и узнаваемого специалиста. Если у вас нет навыков программирования ничего страшного. Сейчас очень много различных веб-конструкторов и no-code билдеров, таких как: Tilda, Wordpress, Wix, Webflow и т.д.

Например, сам сайт Setproduct базируется наTilda. Мы считаем, что этот конструктор лучше всего подходит для сборки вебсайта. Он легок в использовании, прекрасно интегрируется со множеством eCommerce сервисов (и не только), а также у платформы высокая скорость загрузки страниц.

Самореклама

Самореклама поможет вам найти своих клиентов. Бесплатная реклама это размещение своих работ на таких ресурсах как Dribbble, Behance, Pinterest, а также Facebook, Instagram, LinkedIn. Начинайте постить уже сейчас и эти методы рано или поздно дадут свои плоды вы будете наращивать аудиторию и прокачивать каналы для продвижения своих идей и продуктов. Поэтому мы рекомендуем пробовать, даже если вы раньше скептически относились к вышеперечисленным ресурсам.

Самоанализ(а также своих работ и метрик)

Если хотите быть успешным и оставаться на плаву, вам нужно будет постоянно работать над собой. Также вам необходимо будет исследовать аналитику вашего сайта и профилей в социальных платформах. Внимательно изучайте какие из ваших работ на сайте или шотов в Dribbble загружают и лайкают больше всего и почему. Наблюдайте, какие пины из Pinterest люди закрепляют у себя и с чем это может быть связано.

Теперь, когда база подготовлена, давайте переходить к списку. Обещаем, в нем много всего интересного!

Создание цифровых продуктов

Многие предприниматели создают онлайн-империи вокруг цифровых продуктов из-за их популярности и простоты распространения или запускают линейки цифровых продуктов в дополнение к физическим товарам или услугам, которые они предлагают.

Если вы UI/UX дизайнер, то начните создавать дизайн-системы, UI киты, шаблоны, презентации, иконки и т.д. (как это делаем мы).

Если вы графический дизайнер, вы можете выпускать 3D графику, шрифты, логотипы, кисти, иллюстрации и т.д.

Разработчики могут создавать темы и шаблоны для Wordpress, Bootstrap и других платформ.

Все вышеперечисленные продукты можно продавать на различных маркетплейсах, вродеUI8,EnvatoилиCreative Market.

Взять, к примеру, нас: мы с успехом создаем и продаем качественные дизайн-системы. Когда-то этот вид деятельности был лишь сторонним заработком. Но сейчасSetproduct- это растущая компания, в которой небольшой коллектив дизайнеров и разработчиков создает продукты для фрилансеров и корпораций.

Мы строим "бирюзовую" компанию и у нас меритократия идей. Мы любим создавать дизайн-системы и подавать их под соусом современных и стильных гайдлайнов.

Мы нацелены внести свой вклад в этот мир, создавая гибкие и современные компоненты в дизайне и коде. И именно таких увлеченных единомышленников мы сейчас ищем. Поэтому если вы готовы продемонстрировать свой высокий уровень, любовь к сетке и визуально аккуратным компонентам напишите нам.

Создание физических продуктов

У вас наверняка есть футболки, кружки, или какие-то иные аксессуары c интересными визуальными элементами: логотипами, броскими фразами или изображениями. А почему бы вам не попробовать создать что-то свое из печатной продукции и, этим самым, монетизировать свои идеи?

Handmade - замечательная творческая работа и самовыражение. Все, что вам нужно это создать свой уникальный дизайн, найти уступчивого производителя и проверить гипотезу на небольшой партии продукции (не забывая и о рисках).

Есть и другой способ создания печатных продуктов - вы можете работать с сервисами Print on Demand. Это маркетплейсы, в которых вы размещаете свои дизайны и при помощи программы наносите их на определенный инвентарь (к примеру, футболки). И когда люди закажут ваш продукт компания возьмет на себя печать и доставку товара, а вы получаете процент с продажи. Это беспроигрышный вариант. Главное знать тренды и выпускать то, что актуально сегодня.

Заняться блоггингом

Блог является отличной возможностью делиться опытом и знаниями с миром, собирая аудиторию и прокачивая свой собственный SMM-канал. Так вы даете вашим потенциальным клиентам более глубокое понимание вашей философии в области дизайна или разработки. Блог это большой простор для взаимодействия с миром! И да, при помощи своего блога вы можете начать зарабатывать. Здесь у вас есть несколько опций.

1-ая опция: вы можете вести свой собственный блог и зарабатывать с контекстной рекламы, например через Google AdSense. Если вы ведете блог о веб-дизайне, и вы только что опубликовали пост о плагинах для Фигмы, AdSense может показать рекламу о плагинах, Фигме и т.д. AdSense будет платить вам за то, что пользователь вашего сайта посмотрел объявление или взаимодействовал с ним.

Плюс ко всему, статьи, которые вы добавили в блог, могут быть продублированы в Medium. Да, вы можетеиметь доход и с этого ресурса. Medium зарабатывает деньги через членство по цене 5 долларов в месяц. Когда участники читают рассказ и нажимают на кнопку Clap (хлопая, аплодируя автору), часть этих денег по программе членства передается автору.

2-ая опция: вы можете работать копирайтером в компаниях, специализирующихся на дизайне и разработке. Таким компаниям довольно часто нужны люди, которые бы писали качественные и цепляющие тексты для их сайтов. Если у вас получается создавать интересный контент - смело регистрируйтесь во фриланс-ресурсах, либо напрямую связывайтесь с потенциальными работодателями и предлагайте свои услуги.

3-я опция: партнерский маркетинг. Если у вас уже есть определенная аудитория преданных последователей, которые любят ваше творчество, вы можете начать зарабатывать с партнерских программ, рекомендуя те или иные товары или услуги других компаний на своем сайте. Вы выступаете в роли посредника, рекламируя какой-то товар, и если кто-то его покупает, вы получаете свой процент от продажи.

Не пытайтесь просто заработать на своей аудитории. Рекламируйте только те товары или услуги, в которые вы сами верите и, желательно, которыми сами пользовались. Поверьте, люди очень быстро отвернутся от вас, если вами будет двигать лишь жажда наживы.

Выпуск онлайн-курсов

Онлайн-курсы это будущее в сфере обучения. И это даже не следствие коронавируса. Согласноисследованию, проведенному Исследовательской группой Babson Survey, выяснилось, что более 30 процентов студентов высших учебных заведений в США проходят по крайней мере один дистанционный курс. Эти цифры растут уже 14-ый год подряд.

И это замечательная новость для людей, которые хоть иногда задумывались над тем, чтобы создать свой собственный онлайн-курс.

Проблема лишь в том, что людям кажется будто их опыт будет мало кому полезен, и что мир уже всё знает. Но это далеко не так. В мире очень много людей, которым будут полезны ваши знания и опыт. Конечно, придется попотеть при создании материала, его организации и записи всего контента на видео. Но зато когда все будет сделано вы сможете получать неплохие дивиденды в виде постоянного пассивного дохода и вашей растущей популярности. Кроме того, это поможет систематизировать весь ваш предыдущий опыт и получить новые инсайты!

Стать дизайн-консультантом

Если у вас достаточно большой опыт в дизайне и вы являетесь экспертом в своей сфере, вы можете стать консультантом для компаний и бизнесов. Консультанты дают рекомендации и советы компаниям как с точки зрения правильного дизайна улучшить конверсии и привлечь больше клиентов в бизнес. Ваша роль будет заключаться в том, чтобы быть объективным и на ситуации сквозь сложности, которые компания не может преодолеть.

Прелесть такой работы заключена в том, что вам не нужно делать дизайны для компании. Вы даете советы и рекомендации, а дизайном будет заниматься штатный персонал из отдела дизайна.

Стать дизайн-консультантом также возможно благодаря ведению блога. Если ваши публикации интересны и полезны аудитории, вы сможете быстро стать экспертом в их глазах и получать заказы на консалтинг.

Написать книгу о дизайне или разработке

Если вам есть что сказать этому миру, вы грамотно излагаете свои мысли и имеете цель помогать людям своими знаниями - нужно обязательно пробовать себя в этом направлении.

Актуальность книг никуда не исчезает, скорее наоборот - людей, помешанных на саморазвитии становится все больше. Согласно Statista,продажи печатных книг в 2019 году только в США составили 689,45 млн. экземпляров.Эти данные показывают, что рынок печатных книг на удивление здоров. И это мы не говорим ещё об аудио и электронных книгах, популярность которых сейчас в самом разгаре.

Вам не обязательно быть уникальным писателем или иметь какой-то природный дар. Да, нужно будет поработать над навыком складно и интересно оформлять текст, это очень важный аспект. Но в большинстве случаев, книги о дизайне это собрание интересных и полезных статей, которые вы раньше публиковали в своем блоге. Поэтому если ваш блог пользуется популярностью и вы хорошо пишете статьи - вы вполне можете написать и книгу.

Надеемся, что этой статьей мы вдохновим многих людей и сподвигнем их начать собственные сторонние проекты. Если вы создадите продукт, и у вас не получится сделать его продающим - ничего страшного! Вы всегда можете сделать из него бесплатный ресурс и внести свою работу в портфолио. А уж следующий продукт, при учете всех предыдущих ошибок, точно выстрелит.

Пишите тексты, если раньше не делали этого! О работе, исследованиях, ваших экспериментах и выводах. Написание публикаций позволит систематизировать ваш профессиональный опыт и найти то, что можно развить в успешный side-project. И у вас есть все шансы превратить это в дело жизни...

Удачного старта! Дерзайте.

Подписывайтесьна Телеграм-канал Полезное дизайнеру, там будут анонсы следующих публикаций и много других полезных дизайн ресурсов.

Подробнее..

Friends of Figma Moscow

11.11.2020 18:11:34 | Автор: admin

Сразу скажу что это не рекламный пост, никакой продажи, платного контента в данной статье нет(заранее для администрации хабра).

Всем привет! Меня зовут Игорь, я ведущий Продуктовый дизайнер в ВТБ.

Что это за сообщество такое, для чего оно, и кому будет полезно! Начну с самого начала, отправил заявку на официальном сайте Figma, предоставил все материалы которые были необходимы для рассмотрения моей заявки вступить в сообщество и быть организатором(представителем) Figma сообщества в России. Буквально 2-3 недели и мою заявку рассмотрели, прислав письмо с поздравлениями.

Сразу после вступления в сообщество, необходимо было сделать под требования Фигмы логотип сообщества Friends of Figma Moscow и всевозможное оформление социальных сетей, подготовка графических баннеров по гайдам Figma.

Кому будет полезно:

Молодым специалистам которые только начинают свою карьеру в дизайне;

Разработчикам, которые хотят разговаривать на Т с дизайнерами, или хотят упростить процесс коммуникации;

Разработчикам которым интересно разрабатывать плагины для Фигмы;

Владельцам продукта - которые хотят понимать дизайнеров в проекции интерфейсов и дизайна;

Всем желающим!!!

Цели сообщества

Главная цель, которую так же транслирует и сама Figma - сделать большое комьюнити дизайнеров, проектировщиков в одно большое целое, где будет постоянный обмен опытом, лайфхаками, приемами в работе. Самое главное на данных мероприятиях основной упор будет на живой формат общения, в которых спикеры покажут как в жизни используют Фигму в своих повседневных задачах, так же не совсем стандартное использование Фигмы.

Что на данный момент уже сделано

готов список спикеров на первые мероприятия

составлена программа и темы на первые мероприятия

техническая часть проработана на треть

идут переговоры по форматам мероприятий

Когда? Где? Во сколько?

Совсем скоро уже будет вводное мероприятие, где расскажем о планах, целях и что вообще будет в сообществе. Все анонсы мероприятий буду на официальной странице сообщества ссылка, чтобы получать все письма с анонсами эвентов, нужно вступить в сообщество, и внутренний email- sender сайта Фигмы будет оповещать как только я размещаю событие на сайт.

Социальные сети:

facebook.com/fofmoscow

t.me/fof_moscow

instagram.com/fofmoscow

Есть желание делиться опытом?

Сообщество всегда будет радо если будет много талантливых людей, которым есть чем поделиться с молодыми специалистами, а так же с теми у кого большой опыт в дизайне. Если тебе есть чем поделиться, напиши мне в телеграм feedlike обсудим все моменты. Буду очень рад пообщаться, познакомиться. Любая обратная связь, пожелания, советы и критику так же прошу писать мне в личку.

Всем спасибо кто уже вступил в сообщество, и тем кто вступит в будущем!!!!!

http://personeltest.ru/aways/friends.figma.com/moscow/https://friends.figma.com/moscow/

Надеюсь администрация не удалит этот пост))))

Подробнее..

Как и почему мы стали делать UI в Figma вместо Photoshop

27.11.2020 12:11:35 | Автор: admin

По моему опыту, большинство игровых интерфейсов все еще делаются вAdobe Photoshopввиду их художественности и графической сложности, на которую не способны векторные редакторы. Однако и в игры пришел тренд плоских интерфейсов, и настало время пересесть с тяжелого Фотошопа на более простые редакторы интерфейсов, такие какFigma,Adobe XD,Sketchи прочие.

У таких инструментов есть немало преимуществ перед Фотошопом, таких как совместная работа, возможность создания интерактивного прототипа, плагины, автолейауты, варианты, и со временем их становится все больше. По этой причине интерфейсы на новых проектах лучше начинать делать сразу в таких редакторах. Но если так случилось, что ваш проект начинал вестись в Фотошопе, а затем он перестал вас устраивать, эта статья для вас.

Зачем это было нужно

В 2018 году, когда наш проект Dino Squad только стартовал, наша команда работала по такому пайплайну:

  1. Проектируем логику интерфейса и делаем черновые интерактивные прототипы в Figma;

  2. Создаем макеты в высоком разрешении в Photoshop, затем передаем их в верстку;

  3. Снова переносим картинки в растровом формате из Photoshop в Figma для создания чистовых прототипов, которые необходимы для презентаций и геймдизайн-документации.

Таким образом, мы перепрыгивали из одного инструмента в другой два раза:Figma Photoshop Figma. В какой-то момент стало очевидно, что от промежуточного шага можно избавиться. Тем более, перенос проекта полностью в Figma оказался не так трудозатратен и пугающ, как могло показаться сначала.

Было еще несколько моментов, которые, как нам казалось, ускорят работу и облегчат жизнь дизайнерам, если мы это сделаем.

Во-первых, в Photoshop не самая удобная для команды дизайнеров реализация библиотеки. Она долго синхронизируется из-за огромного веса файлов. В Figma же не нужно сохранять файлы, все изменения вносятся мгновенно, а макеты актуальны в каждый момент времени.

Во-вторых, в Photoshop слишком много функций, которые не нужны дизайнерам интерфейса. В этом плане Figma намного легковеснее и реже крашится, что сохраняет команде и время, и нервы.

Технические особенности перехода

Не для всех интерфейсов особенно игровых Figma подходит. Если в вашем проекте каждый элемент интерфейса это произведение искусства, то растровые редакторы, вероятно, подойдут куда больше. Интерфейс нашей игры довольно простой: большинство элементов плоские (иконки, подложки, кнопки), и их легко реализовать в векторном формате. Поэтому весь огромный функционал Photoshop нашему проекту был не нужен.

Еще одним плюсом для нас стало то, что стилистика интерфейса и большая часть его элементов уже были готовы не нужно было придумывать все с нуля. То есть, после переноса у нас уже будет готовый UI-kit для реализации новых фичей.

Что упростило задачу переноса

Процесс переноса окажется проще, если большая часть интерфейса будет представлена в векторном формате, так как Figma не поддерживает редактирование растровой графики.

Еще одним упрощающим переход фактором стало то, что все элементы подчинялись одной сетке. Мы выбрали не самую обычную сетку кратностью 7 (потому что могли). Во всех экранах присутствовала модульность, которую могли наследовать новые экраны, поэтому все элементы интерфейса органично вписывались и в последующие макеты.

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

Перенос проекта из Photoshop в Figma

Чтобы упростить задачу и не перерисовывать с нуля каждый экран, мы решили подойти к вопросу системно. Во-первых, переиспользование цветов, шрифтов и повторяющихся элементов сильно ускоряет процесс переноса. Во-вторых, созданная система в дальнейшем поможет разрабатывать новые экраны и фичи намного быстрее.

Для начала внутри проекта мы создали три файла:

  • В файлеTokensпредставлены все токены проекта;

  • ВLibraryхранятся все отрисованные элементы интерфейса и ассеты;

  • В файлеScreensнаходятся все актуальные экраны проекта.

Также отдельно мы создали проект с прототипами и проекты черновиков для каждого члена команды, подключив к ним библиотеки основного проекта.

Этап 1. Создание токенов

Начнем с базовых переменных нашей системы токенов, таких как цвета и шрифты.

Как устроена система токенов в Figma

Фигма позволяет создавать Color Styles, Text Styles и Effects Styles. Подробнее про стили можно почитатьтут.

Так как в нашем проекте уже устоялась некоторая палитра и шрифтовая схема, на первом этапе необходимо было определить все используемые в проекте цвета и шрифты и занести их в стили Figma. Теперь для использования цвета или шрифта не нужно пипеткой доставать цвет с другого элемента достаточно выбрать необходимый из стилей.

Цвета

В нашем проекте более сотни цветов и перекрасок, поэтому цвета одна из самых сложных частей переноса.

Для начала мы попытались собрать в один список все используемые в проекте оттенки. Мы не нашли способов автоматизировать этот процесс, поэтому просто перебирали слои в проекте Photoshop и копировали их HEX, затем создавали в Figma прямоугольник этого цвета. Таким образом мы получили некоторое множество разноцветных прямоугольников подобие нашей будущей палитры.

Так как цвета у нас есть повсеместно используемые или же несущие определенное значение например, цвета редкости или премиума, то так мы и разделили их на две группы. Кроме того, в первой группе мы разделили цвета по подгруппам каждого оттенка: серые, желтые, голубые и т. д. Во второй группе цвета разделились по семантическим группам: акции, редкости, премиум-подписка, боевой пропуск и прочее.

Со второй группой семантических цветов все понятно: ее мы оставляем такой, какая есть. В то же время общие цвета проекта необходимо упорядочить, удалить схожие и добавить недостающие. Для этого мы разложили их на подгруппы по оттенкам и упорядочили от темного к светлому. К каждой группе мы подобрали градиент цветов с определенным шагом светлоты, чтобы под каждый исходный цвет был найден подобный ему в новой палитре.

Шрифты

Шрифтовая схема в проекте была более-менее систематизирована. Так как мы использовали кратную 7 сетку, размеры шрифтов тоже должны были оказаться кратными 7. Поэтому для каждого используемого начертания мы создали линейку шрифтов с шагом 7: 28, 35, 42, ..., 84.

Этап 2. Загрузка ассетов и графического контента

На игровых проектах довольно много арта растровых ассетов, являющихся частью интерфейса. Например, иконки, портреты, медали, изображения.

Иконки

Иконки тот тип контента, который может быть использован в различном размере. Для этого мы перенесли все иконки (хайрезы или векторы) в Figma и вписали каждую во фрейм одного и того же размера с соблюдением необходимых отступов и правилам ресайза. Иконок оказалось не так много, поэтому мы обернули их в компоненты внутри одной группы. Теперь каждую иконку в любом используемом месте можно заменять другой за пару кликов.

Другие ассеты

Точно так же мы поступили и с остальными изображениями. Достаточно было вписать взаимозаменяемые ассеты во фреймы одинакового размера и обернуть в компоненты одной группы: либо сгруппировать в один фрейм, либо представить имя ассета в виде GroupName / AssetName.

Таким образом, в библиотеке ассеты будут храниться по следующему пути: Library / Assets / GroupName / AssetName.

Этап 3. Создание библиотеки компонентов

В Figma предусмотрен функционал компонентов (а теперь еще и вариантов), поэтому каждый элемент необходимо отрисовать во всех его состояниях, обернуть в компоненты и объединить в варианты. Получив такую систему, мы сможем с легкостью переключать состояния элементов в инспекторе, а также централизованно менять этот элемент во всем проекте.

Как создать элемент:

  1. Определить иерархию элементов и их состояний;

  2. Начать с элементов в самом низу иерархии, отрисовать сперва их и все их состояния;

  3. Далее продолжить отрисовку элементов на ступень выше, используя элементы, созданные на предыдущем шаге;

  4. Действовать так до тех пор, пока не получится исходный элемент.

Теперь у нас есть базовый компонент, состояния подкомпонентов которого можно менять, чтобы получить новое состояние самого компонента. Его мы использовать в макетах не будем, поэтому скроем его для библиотеки за счет _ в начале имени компонента:

Library / Cards / Lots / _BaseLot

Состояния элемента

Для отрисовки одного состояния мы берем базовый компонент, модифицируем элементы в нем под выбранное состояние, корректно именуем и оборачиваем в компонент. В библиотеке полученные состояния будут храниться в таком виде:

Library / Cards / Lots / LotHeart
Library / Cards / Lots / LotLeaf
Library / Cards / Lots / LotDrop

Как работать с состояниями элемента в проекте

Можно оставить состояния переключаемыми компонентами, как мы это делали до появления функции вариантов в Figma, и переключать их в инспекторе.

А можно объединить компоненты разных состояний в варианты и переключать в инспекторе разные состояния исходного компонента уже по свойствам.

Важное замечание

В Photoshop у нас был следующий паттерн хранения состояний элемента: все элементы хранились группами друг под другом скрытыми слоями и включались по необходимости. В Figma такого лучше избегать и использовать для этого варианты, а не скрытие.

Библиотека

Итак, мы перенесли из Photoshop все элементы интерфейса и собрали из них библиотеку элементов, которые можно использовать при создании новых экранов. Теперь не придется копировать элементы из старых макетов достаточно просто перенести элемент из библиотеки на фрейм.

Мы вынесли для себя несколько правил для масштабирования и дополнения библиотеки:

  • Одинаковые элементы не должны повторяться;

  • Переиспользовать все, что можно переиспользовать, и не плодить сущности;

  • Следить за тем, чтобы внутри компонентов, находящихся не в самом низу иерархии, были только компоненты. Это желательно, но не всегда обязательно;

  • Использовать фреймы вместо групп и расставлять Constraints для адаптивности при создании прототипов под разные девайсы;

  • Не использовать не занесенные в стили цвета и шрифты.

Возникшие проблемы

Дизайнерам оказалось сложно быстро пересесть с одного инструмента на другой, поскольку они не были достаточно мотивированы. К тому же, это требовало времени, которое сложно найти в плотном графике релизов. После переноса еще какое-то время команда продолжала рисовать макеты в Photoshop, потому что так было комфортнее и на тот момент быстрее. Важно обучить и замотивировать всю команду, иначе переход будет морально тяжелым и затянется на долгие месяцы. Это и стало нашей главной ошибкой, которая до сих пор приносит немало проблем. Поэтому, если вы готовы к такому переходу, необходимо провести курсы по Figma для всех сотрудников, которые будут с ней работать.

Еще одной проблемой стало то, что Figma не может повторить некоторые свойства слоев, которые предусмотрены в Photoshop. Пришлось придумывать костыли или копировать готовые решения уже из верстки. Идеального повторения, к сожалению, достичь не удалось. Из проблем, с которыми столкнулись мы:

  • Наложение в Photoshop действует внутри группы, а в Figma на все слои ниже в иерархии;

  • В Photoshop можно сделать внутреннюю обводку без наложения на заливку слоя, в Figma нет.

Как подружить Figma с Unity

Одним из самых больших сомнений перед переносом проекта на Figma было то, что могут возникнуть сложности с версткой в Unity. Но на деле это оказалось даже проще, чем подружить с Unity Photoshop.

Во-первых, Figma предоставляет API, чтобы файлы можно было легко спарсить в JSON. Бонусом вы получаете доступ к модификации самой Figma.

Во-вторых, Figma обладает функционалом, предназначенным специально для интерфейсов, что позволяет создать из JSON сразу что-то хорошее.

В-третьих, человеку, верстающему интерфейсы в Unity, даже не требуется установленная Figma и аккаунт в ней достаточно иметь токен UI-дизайнера и ссылку на файл.

В-четвертых, Figma поддерживает концепцию компонентов, которая очень схожа с концепцией Nested Prefabs в Unity.

Давайте разберемся, как получить из файла в Figma JSON. На сайте Figma есть подробнаяинструкция. Но, если разбираться в ней не очень хочется, можете просто скопировать код ниже. Благодаря нему с помощью токена и названия файла вы получите JSON с этим файлом.

using System.Net;using System.IO;using UnityEngine; ...private void FileRequest(){    var request = WebRequest.Create("<https://api.figma.com/v1/files/>" + /* file name */);    request.Headers["X-Figma-Token"] = /* figma token */;     var response = request.GetResponse();    var json = "";     using (var stream = response.GetResponseStream())    {        using (var reader = new StreamReader(stream))        {            string line;            while ((line = reader.ReadLine()) != null)            {                json += line;            }        }    }    Debug.Log(json);     response.Close();}

Получится примерно следующий JSON, который потом с помощью любой библиотеки, умеющей парсить JSON, можно разобрать на нужные классы, а затем из них и создать uGUI-префаб.

{  "components": {},  "document": {    "children": [      {        "backgroundColor": {          "a": 1,          "b": 0.8980392156862745,          "g": 0.8980392156862745,          "r": 0.8980392156862745        },        "children": [],        "exportSettings": [],        "id": "0:1",        "name": "Page 1",        "type": "CANVAS",        "visible": true      }    ],    "id": "0:0",    "name": "Document",    "type": "DOCUMENT",    "visible": true  },  "schemaVersion": 0}

Теперь разберемся, как получить имя файла и токен. Токен генерируется один раз и может быть найден вSettingsв Figma во вкладкеPersonal Access Tokens.

Название файла таится в его ссылке. То есть, если ссылка на файл выглядит вот так:www.figma.com/file/NNNN/FileName, его названием будетNNNN.

Вообще, перейдя на Figma, вы будете приятно удивлены, потому что Photoshop не предоставляет никакого API для парсинга psd-файлов. Разбираться же в бинарнике psd ну очень сложно: спецификация этого файла не полная и устаревшая.

Результат

После переноса проекта в Figma прошло уже 4 месяца, и все это время мы работаем по новому пайплайну. Одним из самых важных для нас результатов сталоускорение работыпримерно в 2 раза: мы избавились от проектирования на квадратах с рыбными текстами и переноса готовых экранов обратно в Figma: теперь мы сразу делаем прототипы из готовых экранов.

Проектирование с готовыми экранами упростилотестирование дизайнана коллегах: теперь они не задают вопросов, морща лоб, готовый ли это дизайн или просто набросок. Да и нам самим еще на этапе проектирования стало прощепредвидеть проблемы, которые могут возникнуть на этапе отрисовки UI.

Еще одним важным результатом переноса сталоприведение к единообразиюцветовой палитры, стилей и некоторых элементов дизайна. Теперь намного удобнее использовать готовые элементы, системно модифицировать их под новые фичи (без необходимости делать это на каждом готовом экране) и переключать состояния одного элемента за пару кликов. И все это благодаря системе компонентов и вариантов Figma.

Теперь вся команда работает в одном проекте и видит результаты своих и чужих изменений сразу. Это еще один аспект, который ускорил процесс синхронизации и актуализации макетов в проекте.

Подробнее..

Вспоминаем все важные события в UIUX дизайне за 2020-й

06.01.2021 20:05:30 | Автор: admin

2020-й миновал. Это был нестабильный год и многие выдохлись. Социальная дистанция, локдаун, удаленная работа, а для многих сокращения: все это стало новой реальностью.

Но несмотря на нестабильность, мировая сцена UI/UX и продуктового дизайна не стояла на месте. Ведь с новыми проблемами появились и новые решения. Компании выпускали новые продукты, а также обновляли существующие.

В этом выпуске мы подвели итоги 2020 года, где собрали для вас топовые события из мира дизайна. Новости отсортированы по значимости. Всё интересное в конце

10. ProtoPie укрепил позиции в мире прототипов

В 2020 году Protopie продолжал развиваться и набирать обороты. На настоящий момент у компании100 000 платных пользователей по всему миру, с крупными сделками с Microsoft, Google и другими известными технологическими компаниями. И прошлый год для них получился очень плодотворным. Было выпущено несколько интересных обновлений и улучшений, среди которых можно выделить следующее:

Появилось автозаполнение отправки и получения сообщений

Добавлена строка состояния системы

Добавлены библиотеки взаимодействия

Добавлена функция Поменять местами инстансы компонентов

Добавлена функция голосового прототипирования

Создан плагин ProtoPie для Figma

9. Notion на пути к улучшенной продуктивности

Notion заметно улучшили свой продукт, а также продолжили пополнять список своих шаблонов: в их базе уже90+ шаблонов, и в новом 2021 году их численность будет только расти. А вот какие были улучшения и нововведения в самом продукте:

Улучшена система поиска благодаря добавлению новых фильтров;

Мобильное приложение теперь запускается в 2 раза быстрее;

Появилась функция добавления неограниченного количества контента на бесплатной основе;

Добавлена функция Scribble для iPad, позволяющая делать заметки от руки;

При помощи новой функции Timeline View (Диаграмма Ганта), можно редактировать планы, проекты и задачи вашей команды в виде плана-графика.

8. Sketch - запуск Cloud Inspector и онлайн-коллаборации

В 2020 году Sketch запустилCloud Inspectorс бесплатным предоставлением разработчикам возможности использовать Sketch. Теперь процесс передачи дизайнов разработчикам и общее сотрудничество как внутри команд, так и между отдельными фрилансерами улучшено.

Но не эта функция была главной для Sketch в прошлом году

В октябре компания объявила о том, что в бета-режиме тестируетсярежим совместной работы в реальном времени. Cлегка запоздалое решение, учитывая прогресс Figma в данном аспекте. Но хардкорные пользователи Sketch были очень рады этой новости.

Эта функция появилась в новой бета-версии Sketch 71. Бета-версия доступна всем, у кого есть подписка на Teams, без дополнительной платы. Онлайн-коллаборация будет полностью запущена в начале 2021 года.

7. Сегмент 3D - один из самых популярных в 2020 году

И на его основе появились такие продукты, как Vectary и Spline.

Vectary- облачный инструмент, который позволяет создавать креативные 3D элементы, композиции и макеты. Их можно затем экспортировать в AR-приложения. Также с его помощью можно создавать 3D дизайн-системы в Figma.

Также в Vectary есть режим онлайн-коллаборации, что делает работу с вашей командой еще проще.

Spline очень достойный конкурент Vectary, который пока что только набирает обороты.

Он больше заточен на веб-приложения и с его помощью вы можете работать с 3D текстом, создавать геометрические фигуры, редактировать материалы, импортировать 3D-модели и многое другое.

Приложение работает на macOS, Windows и Linux.

6. Расцвет AR/VR

В 2020 году AR/VR приложения стали востребованы как никогда прежде. AR/VR технологии помогли многим компаниям адаптироваться к новым условиям и сохранить свои бизнесы.

Например, Amazon разработал приложениеRoom Decorator, позволяющее делать одновременное размещение сразу нескольких элементов мебели и других предметов перед покупкой.

Apple добавилиновые возможности в ARKit 4 был представлен Depth API, который создает новый способ доступа к углубленной информации на iPad Pro.

Google тоже не остался в стороне: к примеру,Google Shopping объединились с несколькими косметическими брендами, чтобы создатьAR-приложение, которое позволяет вам попробовать виртуальный макияж дома. Ну а если вы любитель музеев и галерей то команда Google Arts & Culture предоставила пользователям итакую возможность. Благодаря сочетанию картографии улиц и изображений в высоком разрешении любой может совершить виртуальную прогулку по лучшим культурным учреждениям мира.

Мы полагаем, что сфера AR/VR будет только наращивать свой потенциал, и в 2021 году обещает быть одним из главных трендов.

5. Apple - выпуск macOS Big Sur

Летом 2020 года Apple анонсировали скорый запуск новой версии для своей операционной системы macOS. Спустя 5 месяцев свет увиделBig Sur.

Новый дизайн одно из самых впечатляющих нововведений в Big Sur. Очевидно, что дизайнеры позаимствовали многие элементы у iPhone и iPad. Все элементы в интерфейсе занимают меньше места, углы их красиво закруглены, добавлены эффекты прозрачности и обновлены цветовые схемы.

Что касается функциональных изменений, у новой ОС появился целый ряд нововведений:

Появился интерактивный Центр уведомлений, объединяющий виджеты и уведомления в одной панели.

Настраиваемый Центр Управления позволяет контролировать Wi-Fi, Bluetooth, воспроизведение музыки, включение темного режима и т.д. элементы.

Обновлены приложения Карты, Почта и Фотографии. С новым функционалом Карт, вы сможете легко и быстро планировать свои поездки.

4. Framer вышел в веб и идет по стопам Figma

Framer в этом году вышел на новый уровень, сделав несколько крутых изменений. Теперь это не просто инструмент для прототипирования -они явно идут по пути Figma. Имея сильное прототипирование, останется лишь допилить то, что уже есть у Фигмы. Framer имеет смысл попробовать в 2021-м году.

Среди новинок, выделяем следующее:

Новый Раздел компонентов позволяет обозревать все ваши компоненты в проекте.

Новая функция Мультикомандное управление позволяет нескольким командам осуществлять работу во Framer.

В разделе Assets появился доступ к полезным дизайн-ресурсам. Теперь у вас под рукой есть готовые векторные элементы, включая Feather Icons, Material Icons, Hero Icons и Phosphor Icons + иллюстрации от Humaaans.

И самое интересное...добавлены Variants и Variables! С этими функциями можно создавать компоненты с собственными состояниями и настраиваемыми свойствами.

3. Miro инструмент для мозговых штурмов

Согласно исследованиямUX Tools Survey, в категории Мозговой штурм использование Miro выросло с 5% в 2019 году до 33% в 2020 году. А общее количество пользователей Miro по всему миру в 2020 году превысило10 миллионов человек.

Перечисляем новинки, которые помогли Miro добиться такого прогресса:

Stickies Captures перенос в электронный формат рукописного текста на стикерах при мозговых штурмах;

ВиджетMiro Grids- упорядочивание контента в визуальных таблицах;

Live Embed позволяет интегрировать доски в Coda, Jira, Microsoft Teams, Whereby и т.д.;

Добавлена функция совместного вайрфрейминга;

Ну и самое крутое:сотрудничество с Adobe и интеграция с Adobe XD. Отныне, рабочие процессы с этими программами будут в разы ускорены посредством:

проведения мозговых штурмов;

отправки фидбековв реальном времени;

запуска групповых дизайн-аудитов

быстрого принятия решений по прототипам;

отслеживания прогресса в дизайн-спринтах с помощьюKanban-досок

представления заказчикам финальных дизайнов.

2. Figma выбор года среди дизайн-инструментов

Figma провела мощный год. Во-первых, по результатамисследования UX Tools Survey, где приняли участие 4100 человек, Figma заняла лидирующие позиции в 6 из 8 категорий (User Flows, UI Дизайн, Прототипирование, Developer Handoff, Дизайн-системы, Управление Версиями).

Во-вторых, с сентября 2020 года создатели Figma внеслинесколько крутых измененийв функционал своей системы:

Добавлена функцияVariants, которая объединяет варианты компонентов в единый компонент с настраиваемыми свойствами и значениями;

Обновлён Auto Layout, предоставляющий еще большую гибкость для ресайзинга и работы сConstraints;

Обновленное менюInstance Swappingтеперь имеет функции превью и поиска компонентов;

Добавлена ПанельInspect Tab, которая позволяет разработчикам скопировать значения анимации и любую другую информацию;

Добавлена функцияоффлайн автосохранения.

С такими изменениями, Figma однозначно сохранит лидирующие позиции в 2021 году.

1. Creative Cloud выпустил новые продукты и обновил существующие

Лидером нашего списка стала компания Adobe, для которой 2020 год был очень насыщенным. Вот сводка по основным обновлениям компании:

Добавлена функция стриминга для Photoshop, Illustrator и Fresco;

Возможностьцентрализованно управлять плагинамив десктопном приложении Creative Cloud.

В InDesign появилась функция Share for Review, пользователям делиться своими работами и получать фидбек.

В Photoshop улучшено распознавание шрифтов, заливка и цветокоррекция, добавлена функция Select Subject Portrait с более легким выделением сложного объекта (например женщины с локонами) и заменить фон. А благодаря нейросетевым фильтрам на базе движка ИИ Adobe Sensei вы можете изменять портрет (разглаживать кожу, поменять возраст, направление глаз или головы, добавить эмоции и т.д.)

В After Effects оптимизирован режим работы с 3D;

Adobe XD тоже был круто прокачан благодаря следующим новым функциям:

Content-Aware Layout аналог фигмовского Auto Layout;

Stacksустанавливает интервал между объектами, который сохраняется при изменении вашего дизайна;

Scroll Groupsсоздает в режиме прототипирования прокручивающиеся элементы внутри артборда (списки, карусели, галереи);

Расширение Adobe XD для Visual Studio Code- совместная работа над дизайн-системой;

3D Transforms позволяет создавать AR-прототипы.


На этом всё. Дизайн в очередной раз показал миру свою силу и гибкость. Если понравилась статья и хочется ещё дизайн-годноты, то подпишись на каналПолезное дизайнерув Telegram. Там и новые инструменты, и ресурсы, шрифты и т.п..

Желаем вам не сбавлять оборотов, ведь новый 2021 год обещает быть очень крутым и плодотворным.

Подробнее..

Как я навел порядок страниц вФигме

09.03.2021 08:15:06 | Автор: admin

Наше основное рабочее пространство так же нуждается в чистоте и порядке, как и все остальные сферы нашей жизни. Каждый понимает эти слова по своему, поэтому в этой статье я поделюсь своим опытом, который практикую во всех своих проектах.

Проблема

Основная проблема заключается в том, что система страниц, которую мы пытаемся выстроить обязательно ломается о реальность. Это лишь вопрос ближайшего времени. Мы часто попадаем в ситуации, когда думать об этом нет возможности или просто не хочется. В итоге раз за разом делаем исключения и каша заваривается снова.

Я не раз проходил этот цикл, до тех пор пока не нашел систему, которой мне комфортно пользоваться в любых ситуациях и в самых разных проектах.

Она гибкая, наглядная и удобная с точки зрения ориентации в файле. И что самое важноеона очевидна для тех, кто заходит в файл впервые!

Решение

Применение системы на примере двух разных проектовПрименение системы на примере двух разных проектов

Система построена на разделении всех страниц на базовые типы. Каждый из типов имеет свой эмоджи для четкого визуального разделения:

  1. Продакшенитоговые макеты, готовые к разработке. Эмоджи:

Подробнее..

Figma плагины для продуктового дизайна. Локальный топчик с видео-инструкцией

25.05.2021 16:13:10 | Автор: admin

Для Figma написан целый легион плагинов навсе случаи жизни. Постоянно появляются рейтинги итоп-листы супер-пупер-мега-лучших. Ноэтот инструмент используют люди разных конфессий, решая разные свои задачки. Рыцари фриланса рисуют лендинги, студийные братья собирают промо-сайты, еретики даже визитки иплакаты пытаются делать вFigma. Идля всех есть свои плагины. Поэтому делать общий топ-100 пустое занятие.

Номожно накидать локальный местечковый топчик для продуктового дизайнера например. Внём небудет плагинов вдухе смотрите, какая любопытная идея или если вдруг вам когда-нибудь понадобится заменить все картинки нафото Николаса Кейджа. Только ежедневные трудяги. яуверен, этот список будет полезен нетолько UI-дизайнерам исочувствующим. Что-то полезное найдут для себя ивсе остальные фанаты Figma.

В конце статьи будет ссылка на видео-инструкцию.

Иерархия библиотек вOzon

Яслужу рядовым разработчиком интерфейсов вOzon, где наша маленькая, ногордая команда занимается внутренними продуктами компании. Всяческие админки иCRM-ки. Впрочем, идоосновного сайта мыдотягиваемся.

Работа внашей команде строится последующей схеме: для каждой Job или User Story мыделаем отдельный файл сэлементарным линейным сценарием. Там мысобираем экраны, пройдя которые пользователь решает свою задачу. Втаких сценариях, конечноже, появляются повторяющиеся паттерны, которые можно переиспользовать вдругих User Story иони достойны переноса вотдельную сценарную библиотеку. Этот подход позволяет нераздувать файлы, держать всю систему под контролем идостаточно свободно вносить правки, затрагивающие множество сценариев.

Сейчас унас вOzon есть несколько типов библиотек:

  • Атомарные токены дизайн-системы.

  • Молекулярные библиотеки сэлементами интерфейса. Изних собираются экраны сценариев.

  • Сценарные библиотеки, вкоторые попадают проектные организмы. Оттуда мыможем централизованно использовать ихвдругих сценариях. Повторюсь, разговор нетолько про сайт ozon.ru компании нашего масштаба имеют огромное количество внутренних продуктов, которые также подчиняются единой дизайн-системе.

Библиотечная иерархияБиблиотечная иерархия

Рабочие лошадки иудобные пони

Нохватит зауми! Вперёд кхит-параду. Ида, тут будут представлены иплатные сокровища, ночто значат деньги, когда дело касается Продукта иПродуктивности.

Master

Community

Этот плагин достоин носить джедайское звание Мастер. Сложно переоценить, сколько времени онсэкономил нашей команде. Яуже рассказывал онём насвоём YouTube-канале, асегодня подчеркну его полезность для продуктовой работы. Мало того, что онумеет перелинковывать инстансы кновому мастер-компоненту, сохраняя все оверрайды, так онещё может делать это сбиблиотечными компонентами.

Тут унас типичная ситуация. Форма собрана измолекулярных библиотечных компонентов. Спроектированы разные её состояния. Становится понятно, что она достойна быть добавленной всценарную библиотеку. Если делать это штатными средствами, придётся перенастраивать кучу экранов. Ноунас есть Master.

Копируем одну изформ ивставляем её всценарную библиотеку. Делаем компонент ипубликуем. Запускаем команду Pick Target Component изарсенала плагина Master. Возвращаемся вфайл сценария ивыделяем все наши формы. Запускаем команду Link Objects toTarget Component.

Дапребудет стобой сила, Master!

Design System Organizer

Community

ВнародеDSO. Крутейший комбайн поуправлению стилями икомпонентами. Кроме удобной системы организации стилей попапкам, переименованию идублированию, DSO умеет перелинковывать стили икомпоненты набиблиотечные. Причём непоодному компоненту, амассово. Может экспортировать иимпортировать стили между файлами. Всё это позволяет, достаточно безболезненно переезжать между версиями дизайн-системы, дублировать библиотеки ипроворачивать всякие эксперименты.

Тут унас локальные цветовые итипографские стили. Надо привязать ихктакимже библиотечным. Идём вбиблиотеку изапускаемDSO. Заходим вцветовые стили, выделяем нужную группу ивыбираем извыпадающего меню Set AsTarget. Возвращаемся внаш файл, запускаем DSO ивыбираем Relink Styles. Бум! Стили теперь тянуться изкомандной библиотеки. Такимже образом перелинковываем другие стили или компоненты.

Style Organizer

Community

Этот штепсель помогает неударять вгрязь лицом перед разработчиками. Проверяем, откуда тянутся стили. Ловим нестильные шейпы итексты. Чиним вручном или автоматическом режиме. Соответствуем высоким стандартам разработки Ozon иублажаем личного беса-перфекциониста.

Вот тут унас типичная ситуация. Наглазок всё впорядке, нотакли это? Стартуем Style Organizer. Ивидим, что один изчёрных квадратов имеет локальный стиль, второй библиотечный, атретий вообще без стиля. Можно пробежаться посписку ошибок вручном режиме, сшивая стили, аможно нажать Auto Fix Color иStyle Organizer будет действоватьсам.

Similayer

Community

Все знают обэтом замечательном плагине. Нонеупомянуть его былобы нечестно, ведь мыговорим олучших. Онможет выделить почти всё, что угодно помножеству признаков.

Давайте выделим слово Zen синего цвета, вне зависимости отстиля текста. Выделяем один синий Zen изапускаем Similayer. Выбираем параметры Fill Style иText Characters.

Удобненько!

Instance Finder

Community

Ищет ивыделяет только инстансы. Зато делает это шустрее Similayer иработает повсему документу, анепоодной странице.

Выделяем мастер или любой изинстансов изапускаем поиск. Можно сразу выделить все найденные настранице инстансы.

Select Layers

Community

Ещё один незаменимыйвыделятель. Чаще всего ловлю им слои по названию (он поддерживает частичное вхождение запроса). В отличииотSimilayer, SelectLayersне требует выделять образец для поиска соответствия и, что крайне важно, может искать только в выделенном.

Вот тут унас мега-вариант инпута. Выделяем поля пароля изапускаем плагин. Пишем название нужного слоя ивуаля! Можем поменять иконку, например.

Sorter

Community

Часто возникает необходимость пронумеровать экраны. Чтобы цифры шли попорядку, фреймы должны быть внужной последовательности впанели слоёв. Sorter может отсортировать ихпоположению налисте (инетолько). После чего ихможно переименовать штатными средствами.

Если попытаться пронумеровать экраны, нерасставив ихвпанели слоёв, получим хаос. Нуок. Выделяем все экраны, запускаем команду Sort Position ипосле этого уже штатный Rename Selection.

Порядочек.

Quantizer

Community

Расставляет элементы всетку сзаданным количеством колонок иотступами. Сильно помогает вработе над вариантами.

Выделяем, что нужно, истартуем Quantizer. Сделаем колонки сотступами по40px.

Кстати, вызнали, что можно таскать объекты всетке закруглые маркеры вцентре? Аменять отступ, хватаясь замаркеры между? Если делать это сShift, шаг будет кратен вашему Nudge Amount.

Swap

Community

Плагин, достойный горячей клавиши. Меняет между собой два любых объекта. Выставляет покоординатам верхнего левого угла.

Выделяем два объекта, запускаем команду Swap и, собственно, всё.

Layer Counter

Community

Карманный бухгалтер для ваших макетов. Подсчитает всё ився. Выделяем, запускаем. Наслаждаемся статистикой.

Если снять галку Include Nested Layers, увидим только количество выделенных фреймов.

Retextifier

Community

Может массово заменять текст ввыделенных блоках. Ноесть досадный недочёт при работе вWindows лишний перевод строки, скоторым можно бороться внешними средствами, заменив символ \n на\r или прогнав текст через сам плагин.

Замечательный инструмент, если умеешь импользоваться иутебя macOS.

НаmacOS: копируем текст, например, колонку изGoogle-таблицы. Выделяем целевые текстовые слои изапускаем плагин. Вставляем текст комбинацией Cmd+Shift+V.

Если увас Windows, действуем немного сложнее. Сначала вставляем скопированный текст вфайл Figma. Выделяем его, запускаем Retextifier, копируем итутже вставляем текст, жмём Change. Копируем изменённый текст, далее действуем как наmacOS. Надеюсь, автор плагина что-то придумает поповоду этого недоразумения.

Copy and Paste Text

Community

Вотличие отпредыдущего, этот плагин вставляет вовсе выделенные слои одинаковый текст избуфера. Безусловно полезно.

Копируем нужный текст, выделяем целевые слои, запускаем команду Paste Text

Find & Replace

Community

Поиск изамена потекстовым слоям споддержкой регулярных выражений (Regex). Для тех, кто умеет врегулярки ипонимает, как это круто.

Сейчас мыпоменяем местами буквы ицифры. Запускаем плагин, включаем поддержку Regex ипишем регулярное выражение. Найти (.*)-(.*) изаменить на$2-$1.

Мистика!

Nisa Text Splitter

Community

Разрезает текстовый блок настроки, сортирует, сшивает, расставляет буллиты имногое другое. Рекомендую.

Давайте расставим фильмы похронологии. Запускаем Nisa Text Splitter ирежем наш блок настрочки. Сортируем поалфавиту Sort byalphabet исшиваем обратно водин блок Join text. Внутри плагина ещё много другой годноты. Например, сразу делать Auto Layout изнарезанного текста.

Change Text to Layer Name

Community

Несамый необходимый штепсель, ночастенько выручает. Меняет текст наназвание слоя. Использую всвязке соштатным Rename Selection.

Выделяем текстовые блоки, применяем Rename Selection, оставляем старое название, добавляем кнему дефис иномер. Запускаем команду Change Text toLayer Name.

Математично!

Data Roulette

Community

Когда работаешь над продуктом, утебя есть постоянно используемые наборы данных. Эти наборы накапливаются икочуют изпродукта впродукт. Data Roulette позволяет хранить ихвGoogle-таблицах ирандомно заполнять ими макеты. Итекстами, ифотками.

Делаем Google-таблицу. Линк нанеё добавляем вData Roulette. Называем целевые слои всоответствии сназваниями колонок таблицы поставив вначало решётку. Можно сделать это вмастер-компоненте. Помере необходимости добавляем вGoogle-таблицу новые колонки.

Рулетка рулит!

Content Reel

Community

Для того, кому лень возиться сGoogle-таблицами, Microsoft наплагинил Content Reel. Только нужно залогиниться. Тогда можно будет создавать свои наборы данных.

Тут всё просто. Выделяем целевые слои, выбираем свой или чужой набор данных, вставляем.

Copypasta

Community

Очень часто нужно что-то добавить навсе экраны сценария. Водно итоже место. ИCopypasta прекрасно решает эту задачку.

Выделяем нужную деталь, запускаем Copypasta, жмём Save selection, выбираем целевые экраны, Duplicate Layers.

Шикарно.

Safely Delete Components

Community

Как ярассказал вначале, мыстараемся неоставлять локальных компонентов врабочем файле сценария. Всё должно тянуться избиблиотек. Заканчивая работу, нужно подчистить засобой.

Safely Delete Components удаляет неиспользуемые мастер-компоненты. Ноэтот плагин нужно использовать состорожностью. Нестоит запускать его вбиблиотеках.

После переноса компонентов всценарную библиотеку, выделяем компоненты локальные изапускаем Safe Delete.

SBOL-Typograph

Community

Незабываем оправильной типографике. Кавычках-ёлочках, длинных исредних тире. Вхорошем продукте всё должно быть прекрасно играмотно. Этот плагин работает сразу повсему документу, без выделения текстового слоя, чем ипримечателен.

Божечки-Ёжечки!

Хорошо, ногдеже тот самый плагин?

Конечно, это неполный список годноты. Янеставил абсолютно все плагины имог что-то упустить. Ксожалению, механизмы каталогизации исортировки вFigma Community оставляют желать лучшего. Посути ихинет вовсе. Поисковая строка даранжирование поколичеству установок. Апопулярность далеко невсегда результат качества. Поэтому ищите, ставьте, испытывайте иделитесь вашими рабочими лошадками вкомментариях.

Всем удачи напродуктовом фронте!

P.S.: Видео-версию статьи можете посмотреть намоём YouTube-канале.

P.P.S.: Ясерьёзно про комментарии.

Подробнее..

Единый UI-кит и синхронизация дизайна в Учи.ру. Часть 1

20.02.2021 10:19:11 | Автор: admin

Пожалуй, все, кто имел дело с развитием семейства сайтов, сталкивались с проблемой поддержания единого вида компонентов. Когда счет сервисов идет на десятки и сотни, когда над ними работает все больше независимых друг от друга команд, рассинхрон в дизайне и коде появляется обязательно. Мы попробовали справиться с этим с помощью единой базы компонентов. В серии постов я расскажу о нашем опыте разработки UI-кита, удобного как для разработчиков, так и для дизайнеров, подходящего для разных фреймворков и не слишком утяжеляющего сервисы. В первой части под катом рассказываю, как мы выбирали фреймфорки.

В монолитной системе работа с дизайном происходит централизованно, например, с помощью выделения локальных компонентов. При движении к микросервисной архитектуре неизбежно возникают проблемы с соответствием элементов интерфейса. Мы столкнулись с этим, когда вынесли часть функционала из монолита и потребовалось обеспечить единообразие и синхронное изменение элементов в случае обновления дизайна.

Давайте предположим, что нам нужно создать новый компонент, который будет отображать аватар пользователя. Он должен появиться на страницах абсолютно разных сервисов, которые разрабатываются разными командами. При классическом подходе мы бы сделали аватар в каждом сервисе независимо. И в тот момент, когда дизайнеры решили бы, что все аватарки должны иметь фиолетовую кайму, мы бы получили проблему. Переход на микрофронтенды сделал бы все еще хуже пользователи могли бы увидеть по-разному оформленные аватарки на одной странице.

Мы начали тратить слишком много ресурсов на разработку и поддержку однотипных элементов. Общая база, которую могли бы использовать все команды в своих проектах, позволила бы нам увеличить скорость работы, отображать нужные версии элементов, быстро их подгружать и менять, при этом быть уверенными, что каждый компонент соответствует дизайн-системе. Так мы решили разработать UI-кит.

И для разработчика, и для дизайнера

Создавая UI-кит, мы постарались сделать так, чтобы дизайнер мог участвовать в развитии интерфейса, не привлекая разработчиков. Он выбирает размер, цвет, шрифт, поведение компонентов прямо из Figma для этого там есть отдельная доска, на которой задаются дизайн-токены. Например, дизайнер может обозначить основной цвет (color-primary) как фиолетовый, тогда для визуальных компонентов будет использоваться именно он.

Разработчики применяют UI-кит при создании сервисов. Теперь не нужно писать компоненты заново достаточно обратиться к общей библиотеке.

Выбираем основу библиотеки

На сегодняшний день мы развиваем наш UI-кит на базе кросс-платформенного компилятора Stencil, используем частичную автоматизацию обновления компонентов и подтягиваем нужные параметры дизайна через токены из Figma. Это совершенно осознанное решение, так как у нас был ряд требований к фреймворку, на котором мы собирались формировать единую базу.

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

Также мы хотели оставить себе пространство для маневра, чтобы не быть привязанными к определенному фреймворку. Отчасти потому, что несколько решений уже развивались не на рекомендуемом в компании стеке (React). Но в большей степени из-за нежелания безусловно завязываться на одной технологии. Учитывая скорость развития отрасли, мы должны были обеспечить командам возможность экспериментировать с технологиями без отказа от базы готовых UI-элементов.

Библиотек и фреймворков для создания веб-компонентов много. Например, ресурс WebComponents.dev, кроме предоставления исчерпывающего списка вариантов, обновляет их и информацию об их характеристиках. Мы составили свой топ-3: связку lit-element + lit-html и фреймворки Stencil, Hybrids выделили наиболее значимые критерии и сравнили по ним. На момент выбора это было в начале июня 2020 года получили такую картину:

Критерии

Фреймворк/библиотека

lit-element + lit-html

Stencil

Hybrids

JavaScript ES3+

+

+ (при использовании полифиллов)

+

JavaScript ES6+

+

+

-

TypeScript

+

+

+

JSX

+

+

+

Выгрузка для React

-

+ (при использовании плагина)

-

Выгрузка для Vue

-

+ (при использовании плагина)

-

Поддержка работы без фреймворка

+

+

+

Поддержка IE11

+

+ (при использовании полифиллов)

-

Поддержка современных браузеров

+

+

+

Поддержка плагинов / возможности расширения

-

+

-

CSR

+

+

+

SSR

+ (при использовании доп. библиотеки)

+

-

Подключение ассетов и CSS как отдельных файлов

-

+

-

Хорошая документация

+

+

+

Развитое комьюнити

+

+

+

Что за выгрузка в React/Vue?

Возможно критерии Выгрузка для React и Выгрузка для Vue вам покажутся странными. Но мы искали инструмент, который сможет дать возможность работать с веб-компонентами как с обычными React и Vue компонентами.

На первый взгляд, lit-element + lit-html и Stencil показались почти равноценными. Первые не поддерживали плагины или не давали возможности расширения, соответственно не решали наш вопрос с выгрузкой, не поддерживали подключения ассетов и CSS как отдельных файлов, а со вторым на помощь пришли плагины. Для большей ясности мы ввели коэффициенты для каждого критерия и остановились на Stencil.

Если у вас похожий стек, можете посмотреть нашу таблицу.

Еще один важный фактор успеха это размер бандла. Ведь библиотека, которую мы подключаем в проект, тянет за собой определенное количество кода для браузера и для внутренних функций.

Когда мы выбирали инструменты, оценивали, насколько изменится размер бандла сайта и на React, и на Vue. Сначала все было не очень хорошо, потому что демосайт на React весил без библиотеки 2,5 Мбайт, а с библиотекой 5 Мбайт. Бандл оказался таким большим потому, что по умолчанию Stencil предоставляет библиотеку с полифилами с поддержкой старых браузеров. Чтобы уменьшить размер бандла, мы использовали решение для выгрузки компонентов в виде отдельных файлов, с которыми очень хорошо работают фреймворки. Также мы отдельно вынесли шрифты и подключаем их по URL так мы добились, чтобы с библиотекой на Stencil сайт весил 3 Мбайт. Это хорошо, хотя уже сейчас понятно, что можно еще поработать над размером дополнительных компонентов.

От Figma до готового компонента

Когда что-то меняется на доске в Figma дизайнеры добавляют новый компонент или корректируют старый изменения попадают в общую базу. Например, в случае смены цвета или шрифта отправляется автоматическое уведомление мейнтейнерам, и они обновляют соответствующие элементы библиотеки. Эта часть работы происходит вручную мы пока не стремимся к полной автоматизации, а то пришлось бы создавать нейронные сети для генерации кода. Впрочем, в наше время это вполне можно сделать, и наверняка кто-то уже пользуется подобными подходами.

Чтобы уменьшить влияние библиотеки на размер бандлов сервисов и по ряду других причин, мы решили распространять бандл библиотеки независимо от приложений. При этом схема подключения скрыта от конечного пользователя, поэтому, если мы решим в будущем изменить ее, это не потребует изменений в коде сервисов.

С другой стороны, нужно было разобраться с появлением одного компонента интерфейса в разных микрофронтендах на одной странице. Само по себе это не проблема, но давайте вернемся к примеру с аватаркой. Что произойдет, если в каждом из сервисов библиотека компонентов и, следовательно, аватарка будут разных версий? В текущей реализации мы подключим библиотеку только один раз, если версии совместимы, и покажем пользователю цельный и непротиворечивый интерфейс.

Для корректной работы такой схемы мы придерживаемся правил семантического версионирования и используем конвенцию именования коммитов для автоматизации создания версий.

Кстати, процесс окончательного релиза библиотеки мы тоже начали автоматизировать. Сначала выпускается релиз-кандидат (RC), после этого изменения проверяются на предмет совместимости (вдруг дизайнер что-то перепутал и отображение сломалось), и если все окей, то новшества вносятся в библиотеку, выпускается новая стабильная версия.

Для презентации UI-кита мы используем Storybook. Бандлы выкладываются сначала на внутренний ресурс. Дизайнер или менеджер может зайти, пощупать какой-то компонент, изучить особенности работы, почитать описания настроек. Например, можно сделать кнопку активной или неактивной и посмотреть, как это выглядит, еще до публикации бандла. Во второй вкладке таблицы вы найдете сравнение интерфейсов для UI-кита.

Мы работаем над тем, чтобы сделать триггеры и автоматизировать все процессы публикации. Но уже сейчас использование одной библиотеки гарантирует соответствие сайта концепции дизайна и единому стилю и позволяет разработчикам не верстать стандартные элементы каждый раз заново. Кстати, в качестве первого опыта мы уже запустили часть сайта в новой парадигме.


Расскажите в комментариях, используете ли вы в работе UI-киты. Может быть, у вас уже есть лайфхаки по дальнейшей оптимизации процессов дизайна и переходу на микрофронтенды? Приходилось ли вам более глубоко автоматизировать обновление компонентов в библиотеках? Насколько увеличивается размер бандла из-за использования общего UI-кита в вашем случае и удалось ли вам его оптимизировать? Интересно было бы узнать о вашем опыте.

Подробнее..

Как мы делали SM Lab Analyst Day первый митап по системной аналитике в Sportmaster Lab ( видео всех докладов)

25.03.2021 14:07:14 | Автор: admin

Всем привет. Меня зовут Кирилл Капранов, я руководитель направления системного анализа в компании Sportmaster Lab. 10 марта 2021 года мы с коллегами сделали первый митап по системному анализу, и я хочу поделиться с вами тем, как это было.

Что первым приходит в голову, когда слышишь фразу: "работаю в Спортмастере"? Уверен, у 90% людей промелькнет в голове: "Хм, наверное, продаёт кроссовки". Почему именно эти стереотипы?

Всё просто: в прошлом компания "Спортмастер" делала упор на развитие розничной сети, создание собственного производства, налаживание сети поставок, и, хотя ИТ в этом играло большую роль, знали об этом только внутри компании.

С каждым годом развивающая роль ИТ увеличивалась, но существующая структура компании не позволяла покрывать потребности бизнеса, и в компании началась цифровая трансформация. Внутри цифровой трансформации мы проделали и продолжаем делать большую работу, подробнее можно почитать тут и тут. Мне бы хотелось выделить 2 значимые вехи трансформации:

  • Создание продуктовых команд;

  • Создание центров компетенций.

Когда мы трансформировались, было сформировано отдельное ИТ-подразделение, которое получило название Sportmaster Lab. В это подразделение вошли центры компетенции разработки, системного анализа, QA и методологии.

На этом я подведу черту и перейду к теме статьи. Подробнее о трансформации и роли ЦК аналитики можете послушать в выступлении Сергея Павлова, руководителя направления системного анализа в Спортмастере.

Как мы делали SM Lab Analyst Day

Как появилась идея провести митап?

Центр компетенции (далее - ЦК) аналитики появился меньше года назад. За это время ЦК объединил больше сотни сотрудников из 30 разных команд. Мы выработали стандарты, процессы, подходы и до сих пор прорабатываем решения, которые помогают развивать сотрудников и поддерживать развитие компании.

Однажды мы задали себе вопрос : "А кто об этом знает?". Ответ был неприятный, но честный : "Никто, кроме нас".

Ну что ж, приняли. Пора действовать.

Как спланировали

Любая идея начинается с плана. Наш случай не исключение. Мы оформили план в виде следующего списка:

Цель митапа: Формат проведения: Продвижение: Целевое количество людей: Количество докладов: Тайминг: Этапы подготовки: Договоренности:

План готов, а что с ним делать дальше?

Подготовка к митапу

Для себя мы выделили такие этапы подготовки:

  • Анонс о проведении митапа на сотрудников ЦК, призыв к действию

    На данном этапе важно донести до сотрудников ценность проведения митапа, а также прояснить все оставшиеся вводные:

    • Формат проведения

    • Количество докладов

    • Дата проведения

    • TO-DO list

Эту активность провели в корпоративных чатах и на встречах с сотрудниками. А потом начался этап сбора заявок на выступление.

  • Сбор заявок на выступление

Часто бывает, что на старте подготовки к митапу докладов нет, а есть только идея и желание. Но как же понять суть доклада, его мессадж? Инструменты для выполнения этой задачи можно объединить в такие структурные блоки*:*

  • Идея доклада. Это опыт, трудности или факап, который вдохновил сделать эти выводы.

  • Описание. Краткое изложение материала.

  • Почему это интересно слушать.

Эта информация помогает получить представление о выступлении без подготовки доклада и презентации целиком.

В нашем случае удалось немного прочитерить :)

В SM Lab у нас регулярно проходят внутренние клубы, предназначенные для того, чтобы делиться опытом или показывать полезные инструменты, упрощающие жизнь. Поэтому на старте мы имели порядка 8 тем с готовыми докладами.

Ну всё: считай, дело сделано, расходимся! Но нет...

  • Отбор докладов

Когда хочешь пойти в кино, то вряд ли пойдёшь на фильм, которые тебе неинтересен, ведь так же?

То же самое происходит и при проведении ИТ мероприятий. Нужно заинтересовать своего слушателя.

О чем интересно слушать:

  • Улучшение процессов (с цифрами)

  • Как я могу переиспользовать полученную информацию

  • Практический опыт, разбор примера

  • Факапы и какие выводы из этого были сделаны

  • Как увеличить личную или командную эффективность

О чем слушать не хочется:

  • Мы придумали штуку, но мы её не попробовали

  • Я прочитал статью или книгу, теперь я вам её перескажу

  • Мы тут сделали у себя локальную штуку, послушайте

  • Я расскажу всем известную информацию

Мы взяли бритву Оккама и применили эти списки к своим 8 докладам. Таким образом, у нас осталось 6 докладов и 4 спикера. Так как у каждого из двух спикеров было по два доклада, то мы отдали право выбора им. Так получился тот список докладов, который решили рассказывать на нашем митапе. Теперь пора подумать о продвижении.

  • Начало продвижения

    Для продвижения любого мероприятия нужны деньги ... на самом деле, не cовсем :). Деньги нужны, но не так много, как вы могли бы подумать, особенно в 2021 году, в эру онлайна.

    Для продвижения мероприятия важно подсветить следующие пункты:

    • Где будет проходить запись на мероприятие

    • Целевая аудитория

    • Инструмент проведения мероприятия

    Для своего мероприятия мы выбрали площадкой Timepad. Сначала мы рассматривали его только как инструмент записи на мероприятие, но, изучив его, поняли, что Timepad идеально подходит для нашего мероприятия, так как позволяет делать трансляции на 500 человек.

    В качестве целевой аудитории выбрали профиль обычного системного аналитика специалиста с компетенцией в системном анализе, работающего в команде, не тимлида, не руководителя и не бизнес аналитика.

    И вот теперь, кажется, всё готово! Но нет...

    Заходя в анонс мероприятия, человек должен понимать, какую ценность он получит на выходе. Для этого необходимы тезисы краткие и емкие, отражающие суть доклада.

    Мы их сформулировали, теперь пора переходить к следующему этапу.

  • Тестовые прогоны

    Кажется, что тут всё просто: собирай встречи на спикеров и всех заинтересованных людей и проводи прогоны. Исправляй неточности, предлагай улучшения по презентации и докладу, задавай вопросы. Но много репетиций и правок совсем не гарант того, что финальный результат понравится публике. Мы посовещались и выбрали два прогона необходимым максимумом для митапа. И не прогадали.

Проведение митапа

Митап SM Lab analyst day состоялся 10 марта 2021 года. Пик слушателей составлял 200 человек. Среди участников митапа были cотрудники Сбербанка, Tinkoff, Райффайзенбанка, Альфа-Банка, МТС, EPAM, банка Открытие и РТЛабс и многих других компаний.

О чём мы рассказывали:

Пантелеева Елизавета -Работа в Спортмастере на примере проекта "Новый интернет магазин"

Лиза работает системным аналитиком в команде "Новый интернет магазин", которая состоит из 20 сотрудников (системные аналитики, бэкенд и фронтенд-разработчики, тестировщики).

В докладе Лиза затронула следующие моменты:

  • Как устроена работа продуктовой команды в компании Спортмастер

  • Как мы пришли к продуктовому подходу и какую проблему хотели решить

  • Кто и как проводит декомпозицию задач

  • Как задача переходит в работу и какие стадии она проходит

  • Какова роль системного аналитика

Полуян Артем -Практический кейс замещения аналитиками роли Тестировщик.

Когда ключевой сотрудник уходит из компании, это становится головной болью команды. Думаю, что многие из вас сталкивались с этой неприятной ситуацией. Появляются вопросы, требующие незамедлительного решения что же с этим делать, кто возьмёт на себя роль этого человека.

В докладе Артёма есть ответы на эти вопросы:

  • Как команда может остаться без одной из компетенций

  • Кто и каким образом может забрать на себя работу в момент поиска специалистов

  • Какие подходы в команде опробовали при замещении компетенции

  • Как происходил онбординг и обучение новых сотрудников

  • Какие выводы сделала команда и сам Артем

  • Практические советы по онбордингу нового сотрудника

Заев Артем -Ходим с разработчиками налево!Или Как уменьшить потери на пробелах в бизнес-постановках

Как мы знаем, cистемный аналитик выступает связующим звеном между бизнесом и командой, но зачастую аналитик смотрит на задачу верхнеуровнево и не может задать вопросы бизнесу, которые возникают из-за специфики слоев разработки. Системный аналитик становится "лишним звеном" в цепочке: бизнес-аналитик-разработчик. Как же построить прямой диалог?

Артем поделился кейсом о том, как смогли сначала наладить диалог между командой разработки и заказчика, а потом и уменьшить количество прямого общения c помощью интерактивных досок Miro. Он рассказал о функционале Miro применимо ко Спортмастеру, о том, как общаются с помощью инструмента участники команды, и о профитах от внедрения.

Хахарев Иван -Как мы пришли к Figma или зачем учиться готовить вкусно

Однажды к Ивану в команду пришли новые разработчики и сказали, что макеты это уже прошлый век, и будущее за прототипированием. Так как Ваня человек, который любит изучать новое, он загорелся идеей исследования инструментов прототипирования. В своем докладе он рассмотрел 3 популярных инструмента Axure, Adobe XD и Figma, сравнил их между собой, а также объяснил, почему он выбрал один из них. Бонусом Ваня устроил мини-воркшоп по созданию прототипа.

Заключение

Это был наш первый митап по системному анализу: не всё прошло гладко, как это бывает в первый раз, но мы получили классный опыт проведения подобных мероприятий и рассказали миру инсайдерской информации о системной аналитике в крупном спортивном ритейлере :)

На этом мы не заканчиваем. 20-21 мая мы участвуем в конференции Analyst Days, где выступим с докладами и пообщаемся с единомышленниками на стенде компании.

Нам нравится открыто рассказывать о своей работе. Увидимся на наших новых мероприятиях!

Подробнее..

Android-разработчикам как сократить время реализации тёмной темы с пары месяцев до недели

20.10.2020 14:07:37 | Автор: admin

Привет, меня зовут Влад Шипугин, я Android-разработчик в Redmadrobot. В этой статье я хочу поделится опытом реализации тёмной темы, создания удобного UI Kit, как для разработки, так и для дизайнеров. Я расскажу про использование Material Components и работу с Vector Drawable. Также вы узнаете, как быстро поддержать режим edge-to-edge с использованием Window Insets и познакомитесь с моей библиотекой edge-to-edge-decorator.

Где-то полгода назад мы начали разработку тёмной темы для приложения Ростелеком Ключ. Наши дизайнеры уже писали про ценность тёмной темы, как её спроектировать и передать в разработку. В этой статье я продолжу рассказ от лица разработчика, расскажу с какими проблемами мы столкнулись в процессе реализации тёмной темы, почему это заняло у нас 3 месяца и как реализовать тёмную тему всего за одну неделю.

Этой осенью Android 10 исполнился год, и именно такое время требуется, чтобы изучить все новинки, реализовать их и протестировать, поэтому в статье будет живой опыт из реальных проектов.

Не важно, давно ли вы начали разработку под Android или только делаете ваше первое приложение, думаю, вам будет интересно почитать эту статью, потому что в ней я поделился всем накопленным опытом и самым актуальным набором материалов по дизайну Android-приложений.

Как сделать удобный UI Kit

Изначально у нас был простой план: дизайнеры делают тёмную тему, а мы просто добавляем файл value-night/color.xml и всё. Но позже мы столкнулись с проблемами. И теперь, когда приложение давно опубликовано в сторе, я могу рассказать о решении этих проблем, чтобы вы никогда не наступали на наши грабли.

Проблема 1: сложность при выборе названий для палитры цветов

Первый вариант именования цветов использование названия цвета как есть: realblue, darkgrey и так далее.

Пример палитры цветов из ZeplinПример палитры цветов из Zeplin

Думаю, каждый сталкивается с проблемой, когда при использовании такого подхода, в будущем, при редизайне, получается, что realblue меняет свой hex на hex красного цвета или жёлтого. Это можно исправить, если переименовать цвет во всем приложении, но тогда возрастает вероятность ошибиться, а отлавливать такие ошибки крайне тяжело.

Второй вариант это абстрактные названия, мы решили использовать C1, C2 (С от слова Color) и так далее. Эта абстракция позволяет отвязать значение цвета от его названия. Сегодня это может быть красный, а потом желтый это не важно, и вам не нужно рефакторить всё приложение.

Пример палитры цветов из ZeplinПример палитры цветов из Zeplin

Но тут появляется другая проблема ты не можешь держать таблицу соответствий цветов в голове. Приходится всё время её открывать: при обсуждении с дизайнером или при разработке всегда нужно проверять конкретный цвет приложения.

Редко, когда удается запомнить конкретную цифру цвета. Какой тут должен быть цвет: С4 или С7? станет самым частым вопросом на обсуждениях дизайна. Мы долгое время пытались найти баланс между понятным названием цвета, таким как realblue и максимально абстрактным цветом для простоты рефакторинга и редизайна: С1, C2, C3 и так далее.

Есть и альтернативный, третий вариант когда названия цветов зависят от компонента, например, гайдлайны Material Design или Apple HIG.

material.iomaterial.io

Этот вариант казался самым логичным, но в нём было больше всего проблем:

  1. Цвета даёт дизайнер. И начинающим дизайнерам сложно придумывать названия цветов, а подключать всегда арт-директора для такой мелочи невыгодно.

  2. Некоторые цвета могут содержать одинаковый hex. В целом, в этом нет проблемы, но как оказалось, в палитре цветов Zeplin не может содержаться два цвета с одинаковым hex, но разными названиями.

  3. Сложно объединить рекомендации Material Design и Apple HIG в одну палитру, да и стандартных цветов может быть недостаточно для приложения.

Много встреч прошло за обсуждением названий цветов. Они должны были быть удобными для всех: Android- и iOS-разработчиков, и дизайнеров. Через некоторое время мы остановились на третьем варианте, но сформировали чёткие правила по наименованию цветов, чтобы не тратить много времени на придумывание названия. Также мы договорились добавлять цвета с одинаковым hex отличающимся на единицу.

Название цвета

iOS

Android

text/primary

textPrimary

text_primary

button/pressed

buttonPressed

button_pressed

Вот пример готовой палитры из Zeplin:

Пример финальной палитры из ZeplinПример финальной палитры из Zeplin

Позже мы отказались от Zeplin и перешли на Figma. Вот такая палитра в Figma у нас получилась. А подробнее про переход с Zeplin на Figma уже писал наш iOS разработчик Даниил Субботин @subdan в статье про утилиту экспорта UI Kit из Figma figma-export.

Проблема 2: непонятные стили шрифтов

Особых проблем в работе со штифтовыми стилями у нас не было. Дизайнеры обычно заносят все шрифтовые стили приложения в UI Kit, но их наличие не гарантирует, что в макетах будут использоваться только они. Периодически то там, то тут, Zeplin не определял указанный шрифт и приходилось отвлекать дизайнера, чтобы узнать какой именно шрифт необходимо использовать.

Сейчас в макетах всегда отображаются правильные стили шрифтов. Дизайнеры добились этого за счёт перехода со Sketch + Zeplin на Figma она лучше распознает шрифтовые стили.

Да, иногда ошибки встречаются, но это происходит крайне редко, потому что все шрифты прописаны в мастер-компонентах и UI Kit. Это уже ответственность дизайнеров. Если я находил ошибку, то оставлял комментарий и дизайнер всё исправлял.

Пример наших шрифтовых стилей можно посмотреть тут.

Проблема 3: дублирование иконок и трудности с их именованием

Пока дизайнеры переделывали палитру цветов, я столкнулся с новой проблемой иконки должны быть разных цветов в зависимости от выбранной пользователем темы. Самый простой вариант это добавить альтернативный набор иконок в директорию drawable-night. Но за простоту нужно платить:

  1. Количество иконок увеличивается в два раза, а значит, приложение весит больше. И App Bundle не поможет, потому что тема меняется динамически и все иконки должны находиться в итоговом APK.

  2. Названия иконок разных цветов должны всегда совпадать. Если дизайнер опечатался или изменил название, то вы добавите новую иконку рядом, а не замените старую. В таком случае искать ошибку придется вручную, а это сложно и долго.

  3. Всегда нужно помнить про альтернативные цвета иконок. Если добавляешь новую иконку, то нужно всегда добавлять её для темной темы, и на раннем этапе мы об этом часто забывали

Эти проблемы довольно существенны и такой вариант меня сразу не устроил. Позже я наткнулся на рекомендации Google и Apple. Они советуют использовать все иконки одного цвета: черного или белого, и перекрашивать их в нужный цвет в рантайме.

Мы сначала использовали иконки белого цвета, но потом столкнулись с проблемами их видимости. В Figma мы добавляли их на черный фон, а вот в операционной системе черный фон есть не везде, и иконок бывает просто не видно. Поэтому мы перешли на использование черных иконок.

Ещё одна проблема названия иконок придумывают дизайнеры и не всегда они совпадают с ходом мысли разработчиков: дизайнеры называют иконку исходя из визуальной составляющей, а разработчики исходя из предметной области. Поэтому разработчики переименовывают иконки у себя в проекте.

Ещё бывают моменты, когда дизайнер сам решает поменять название иконки и забывает сообщить об этом разработчикам. Все эти изменения приводят к тому, что при обновлении или добавлении иконок может появиться дублер иконки, но с другим названием. В таком случае много времени придется потратить на поиски одинаковых иконок.

Чтобы такого не было, следует сразу договориться о правильном именовании иконок. Мы остановились на таком варианте:

Название иконки

iOS

Android

ic/24/flash_on

ic24flashOn

ic_24_flash_on

ic/24/flash_off

ic24flashOff

ic_24_flash_off

Пример с нашим набором иконок можно посмотреть здесь.

Проблема 4: организация иллюстраций

Перекрашивать иконки удобно, но если картинка содержит больше одного цвета, то такой вариант не подходит. В данном случае остается добавить иллюстрацию альтернативного цвета в директорию drawable-night и попросить дизайнера подготавливать иллюстрации в альтернативной теме.

У нас были случаи, когда иллюстраций не хватало или они рендерились криво. Чтобы избежать ошибок, мы собрали все иллюстрации в одном удобном для QA месте, и включили их в ручное регрессионное тестирование. Позже этот процесс можно будет автоматизировать с помощью скриншотного тестирования.

Вот пример того, что у нас получилось.

Проблема 5: отсутствие базовых компонентов или неправильное их использование

При проектировании дизайна приложений дизайнер сначала делает экраны, а потом переносит основные компоненты в UI Kit. При этом не каждый дизайнер уделяет достаточно времени технической составляющей при описании этих компонентов. В UI Kit могут отсутствовать некоторые состояния, которые разработчик может встретить в процессе реализации экранов. Такой UI Kit создается неполным, и если дизайнер сразу не сделает хороший UI Kit, то после создания тот и вовсе перестает поддерживаться.

При данном подходе UI Kit не является единым источником правды. Можно сказать, что в данном случае это UI Kit для галочки, и так делать нельзя.

Но как только дизайн-макеты начинают передавать в разработку, то единственным источником правды должен стать UI Kit и мастер-компоненты в нем. Иначе UI Kit будет вам мешать и замедлять работу, а не ускорять её.

Ценность UI Kit в том, что вы реализуете все базовые компоненты, а потом из этих компонентов собираете экраны. Для этого можно использовать мастер-компоненты в Figma, и styles или CustomViews в Android. В таком случае UI Kit экономит вам много времени.

Вот пример с описанием кнопок приложения, а полный UI Kit можно посмотреть тут.

Пример описания кнопок приложенияПример описания кнопок приложения

Как правильно реализовать UI Kit

После создания дизайнерами UI Kit можно подключаться и разработчикам. Мой план по реализации UI Kit с учетом темной темы был такой:

  1. Привести цвета, тему приложения и стили компонентов в порядок.

    • сделать палитру цветов (color.xml);

    • описать тему приложения;

    • описать стили компонентов, которые отличаются от базовой темы.

  2. Заменить все иконки на черный и окрашивать их в нужный цвет в момент отрисовки.

  3. Добавить альтернативные цвета values-night/color.xml.

  4. Добавить выбор темы в настройках приложения.

Я уже писал выше про утилиту Figma-export и статью, в которой раскрыты подробности её реализации. Эта утилита помогает избежать проблем с экспортом цветов, иконок и иллюстраций из Figma. С её помощью экспорт компонентов происходит автоматически, что позволяет полностью исключить человеческий фактор из этого процесса.

Реализуем палитру цветов

С помощью Figma-export создание палитры цветов происходит одной командой:

./figma-export colors -i figma-export.yaml

После этого в вашем приложении добавится или изменится файл color.xml.

Реализуем тему приложения

Для реализации темы в Android-приложении следует использовать библиотеку material-components. Именно так я и поступил: создал палитру цветов в color.xml и начал делать тему приложения. Но после этого я столкнулся с проблемой toolbar, cardview и ещё пару компонентов имели не тот цвет.

Прописывать все цвета по месту использования компонента мне показалось плохим решением слишком много дублирования.

На тот момент, в библиотеке material-components, ещё не было документации по темам и стилям. Как и многие Android-разработчики, я не знал, как правильно описывать тему приложения. Разработчики из Google даже шутили про это на Android Dev Summit 2019.

Моя тема приложения была описана неправильно и материальные компоненты, такие как кнопки, иконки и текстовые поля, выглядели не так, как я планировал. Например, цвет toolbar использовал цвет primary для светлой темы и, почему-то, переключался на surface в темной.

Позже оказалось, что в теме приложения, по умолчанию, цвет toolbar принимает значение, равное атрибуту ?attr/colorPrimarySurface. Тогда, чтобы понять почему так происходит, мне пришлось ковыряться в исходниках материальных компонентов. Мне удалось понять, какой смысл вкладывали авторы в описание темы приложения, и потом статья про темы и стили в Android-приложениях подтвердила мои догадки.

Сейчас вы можете узнать интересные детали в новой статье по материальным компонентам от Google. Картинка из этой статьи наглядно показывает, как работает тема с атрибутом colorPrimarySurface.

Примеры работы PrimarySurface атрибутаПримеры работы PrimarySurface атрибута

При реализации темы приложения важно понять концепции цветов и атрибутов, а также различия темы и стилей. Сейчас проблем с документацией больше нет. Я не стану описывать эти вещи в данной статье, чтобы не повторяться.

Google представили подробную серию статей по материальным компонентам. Поэтому, я рекомендую их к прочтению. Они помогут вам полностью разобраться в создании темы для Android-приложений:

Доп. информацию по материальным компонентам можно найти тут и в конце статьи:

Также, при реализации темы приложения, следует подключить дизайнера, чтобы он помог создать описание темы приложения и сконвертировать удобную палитру цветов для дизайна, в тему материальных компонентов. Здесь на помощь приходит раздел материальных компонентов, MaterialThemeBuilder и примеры от Google:

В итоге, я остановился на таком варианте описания темы и стилей.

Структура организации ресурсов:

  1. colors.xml цвета приложения;

  2. type.xml шрифты приложения;

  3. shape.xml формы приложения;

  4. themes.xml темы приложения;

  5. styles_button.xml кнопки приложения;

  6. styles_text_input.xml текстовые поля;

  7. styles_list_item.xml элементы списков;

  8. styles.xml прочие стили виджетов.

Итоговая тема приложения
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">    <!-- Base color attributes -->    <item name="colorPrimary">@color/tint</item>    <item name="colorSecondary">@color/tint</item>    <item name="colorControlHighlight">@color/tint_ripple</item>    <item name="android:colorBackground">@color/background_primary</item>    <item name="colorSurface">@color/background_secondary</item>    <item name="colorError">@color/error</item>    <item name="colorOnPrimary">@color/text_primary</item>    <item name="colorOnSecondary">@color/text_primary</item>    <item name="colorOnBackground">@color/text_secondary</item>    <item name="colorOnError">@color/text_primary</item>    <item name="colorOnSurface">@color/text_secondary</item>    <item name="android:windowBackground">@color/background_primary</item>    <item name="android:statusBarColor">@android:color/black</item>    <item name="android:navigationBarColor">@android:color/black</item>    <item name="android:enforceNavigationBarContrast" tools:targetApi="q">false</item>    <item name="android:listDivider">@drawable/divider_horizontal_primary</item>    <!--Material shape attributes-->    <item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>    <item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent</item>    <item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.App.LargeComponent</item>    <!--Component styles-->    <item name="appBarLayoutStyle">@style/Widget.App.AppBarLayout</item>    <item name="toolbarStyle">@style/Widget.App.Toolbar</item>    <item name="drawerArrowStyle">@style/Widget.App.DrawerArrowToggle</item>    <item name="toolbarNavigationButtonStyle">@style/Widget.App.Toolbar.Button.Navigation.Tinted</item>    <item name="bottomNavigationStyle">@style/Widget.App.BottomNavigationView</item>    <item name="cardViewStyle">@style/Widget.App.CardView</item>    <item name="textInputStyle">@style/Widget.App.TextInputLayout</item>    <item name="editTextStyle">@style/Widget.App.TextInputEditText</item>    <item name="switchStyle">@style/Widget.App.Switch</item>    <item name="materialCalendarTheme">@style/ThemeOverlay.App.Calendar</item>    <item name="dialogTheme">@style/ThemeOverlay.App.Dialog</item></style>

Реализуем стили шрифтов

В теме приложения с material-components стандартным решением для реализации шрифтов является textAppearance. В нашем приложении используются в два раза меньше шрифтов и всего три цвета для текста. А ещё textAppearance можно описывать не все атрибуты например, там нет свойства android:lineSpacingMultiplier. Поэтому, я решил не использовать textAppearance, а использовал просто стили, которые прописывались каждому текстовому полю.

Например, мы нигде не использовали стиль Header2 и вместо него применяли унаследованный от него стиль с указанием цвета: Header2.Primary или Header2.Secondary. Такой вариант позволял сразу определить и цвет текстового поля и его шрифт.

Иногда приходилось делать исключения и использовать просто стиль, как Header2, с указанием цвета прямо в верстке экрана, например, для отображения ошибок, но таких мест всего 23 в приложении.

Стиль шрифта содержит следующие атрибуты:

  • textSize размер;

  • lineHeight межстрочный интервал, когда в текстовом поле две строки;

  • android:minHeight и android:gravity нужны, чтобы указать межстрочный интервал, когда в текстовом поле всего одна строка (да, lineHeight в таком случае игнорируется и приходится выкручиваться костылями :))

  • android:fontFamily начертание шрифта.

    Вот один из примерв описания шрифта:

<style name="Header2">    <item name="android:textSize">18sp</item>    <item name="lineHeight">24sp</item>    <item name="android:minHeight">24sp</item>    <item name="android:gravity">center_vertical</item>    <item name="android:fontFamily">@font/basis_grotesque_pro_bold</item></style><style name="Header2.Primary">    <item name="android:textColor">@color/text_primary</item></style><style name="Header2.Secondary">    <item name="android:textColor">@color/text_secondary</item></style>

Переиспользуем иконки при помощи окрашивания

Как я писал ранее, все иконки в приложении следует делать одного цвета, и потом их раскрашивать. Чтобы добавить все иконки из Figmа, вновь воспользуемся утилитой Figma-export:

./figma-export icons -i figma-export.yaml

После этого вы увидите, какие иконки удалятся, а какие добавятся или изменятся. Останется только покрасить их в нужный цвет.

В Android давно добавили поддержку перекрашивания иконок, это различные tint, но до сих пор это работает плохо и не на всех версиях Android, поэтому я написал extension для работы с drawable через drawable compat, и придерживался следующего алгоритма:

  1. Если можешь сделать tint в верстке делай tint.

  2. Если это кнопка или компонент с несколькими состояниями, то тут поможет selector.

  3. Если требуется программная смена цвета, то необходимо использовать DrawableCompat для корректной установки цвета, и обязательно нужно сделать mutate, иначе иконка закешируется, и поменяет цвет во всем приложении. Для этого я написал следующие extension-функции:

fun Drawable.withTint(context: Context, @ColorRes color: Int): Drawable {    return DrawableCompat.wrap(this).mutate().apply {        DrawableCompat.setTint(this, ContextCompat.getColor(context, color))    }}fun Int.toDrawableWithTint(context: Context, @ColorRes color: Int): Drawable {    return requireNotNull(AppCompatResources.getDrawable(context, this)).withTint(context, color)}

Добавляем иллюстрации

С добавлением иллюстраций тоже всё просто. В Figma-export есть нужная команда для их добавления в проект:

./figma-export images -i figma-export.yaml

Вызываем команду, и она добавляет иллюстрации в values и, если, вы поддерживаете тёмную тему, то и в values-night.

Реализуем стили компонентов

Я уже выше делился материалами по реализации темы приложения и стилей компонентов. Если вы их почитаете, то вопросов у вас возникнуть не должно.

Пример того, как я организовал стили компонентов кнопок в styles-button.xml
<resources>   <style name="Widget.AppTheme.Button" parent="Widget.MaterialComponents.Button.UnelevatedButton">       <item name="backgroundTint">@drawable/selector_button</item>       <item name="rippleColor">@color/button_ripple</item>       <item name="android:textAllCaps">false</item>       <item name="android:textAppearance">@style/Body1</item>       <item name="android:textColor">@color/button_text_color</item>       <item name="android:paddingStart">16dp</item>       <item name="android:paddingTop">12dp</item>       <item name="android:paddingEnd">16dp</item>       <item name="android:paddingBottom">12dp</item>       <item name="android:insetTop">0dp</item>       <item name="android:insetBottom">0dp</item>   </style>   <style name="Widget.AppTheme.Button.Secondary">       <item name="backgroundTint">@color/background_secondary</item>       <item name="rippleColor">@color/tint_ripple</item>       <item name="android:textColor">@color/button_secondary_text_color</item>   </style>   <style name="Widget.AppTheme.Button.Onboarding">       <item name="backgroundTint">@color/onboarding_button</item>       <item name="rippleColor">@color/tint_ripple</item>       <item name="android:textColor">@color/button_secondary_text_color</item>   </style>   <style name="Widget.AppTheme.Button.Accent">       <item name="backgroundTint">@color/accent</item>       <item name="rippleColor">@color/tint_ripple</item>   </style>   <style name="Widget.AppTheme.TextButton" parent="Widget.MaterialComponents.Button.TextButton">       <item name="rippleColor">@color/tint_ripple</item>       <item name="android:textAllCaps">false</item>       <item name="android:textAppearance">@style/Body1</item>       <item name="android:insetTop">0dp</item>       <item name="android:insetBottom">0dp</item>       <item name="android:paddingStart">16dp</item>       <item name="android:paddingEnd">16dp</item>   </style>   <style name="Widget.AppTheme.Button.TextButton.Dialog" parent="Widget.MaterialComponents.Button.TextButton.Dialog">       <item name="android:textAllCaps">true</item>       <item name="android:textAppearance">@style/Body1</item>       <item name="android:paddingStart">16dp</item>       <item name="android:paddingEnd">16dp</item>       <item name="rippleColor">@color/tint_ripple</item>   </style>   <style name="Widget.AppTheme.TextButton.Icon" parent="Widget.MaterialComponents.Button.TextButton.Icon">       <item name="rippleColor">@color/tint_ripple</item>       <item name="android:textAllCaps">false</item>       <item name="android:textAppearance">@style/Body1</item>       <item name="android:textColor">@color/tint</item>       <item name="android:insetTop">0dp</item>       <item name="android:insetBottom">0dp</item>       <item name="android:paddingStart">16dp</item>       <item name="android:paddingEnd">16dp</item>   </style>   <style name="Widget.AppTheme.ToolbarButton" parent="Widget.MaterialComponents.Button.TextButton">       <item name="rippleColor">@color/tint_ripple</item>       <item name="android:textAllCaps">false</item>       <item name="android:textAppearance">@style/Header1</item>       <item name="android:textColor">@color/toolbar_button_text_color</item>       <item name="android:paddingStart">16dp</item>       <item name="android:paddingEnd">16dp</item>   </style></resources>

Также стоит учитывать, что в верстке вы можете использовать просто Button или AppCompatButton, потому что есть такой компонент, как MaterialComponentsViewInflater, который автоматически будет переводить их в MaterialButton, если ваша тема наследуется от "material-components".

Вот кусочек кода из него:

@NonNull@Overrideprotected AppCompatButton createButton(    @NonNull Context context,     @NonNull AttributeSet attrs  ) {    if (shouldInflateAppCompatButton(context, attrs)) {    return new AppCompatButton(context, attrs);  }  return new MaterialButton(context, attrs);}

Как поддержать режимedge-to-edge

На этапе проектирования палитры цветов, нам очень сильно мешали цвета statusBar, да и в целом, окрашивание statusBar всегда вызывало проблемы на разных версиях Android. Раньше его цвет был равен colorPrimaryDark, а теперь Google отказались от этого варианта и рекомендуют использовать режим edge-to-edge. Кроме этого, мой OnePlus получил обновление до Android 10, поэтому я решил попробовать добавить поддержку режима edge-to-edge.

Режим edge-to-edge это новая концепция из материального дизайна, которая заключается в том, что вы отрисовываете контент под системными компонентами: statusBar и navigationBar и телефон становится визуально более безрамочным.

Отрисовка контента под statusBar позволяет добавить в ваше приложение поддержку челок и вырезов под камеру, а под navigationBar визуально улучшает работу с жестами из новой жестовой навигации в системе Android.

Для того, чтобы добавить поддержку режива edge-to-edge в ваше приложение нужно:

  1. Добавить поддержку системных отступов (insets).

  2. Активировать режим edge-to-edge для statusBar и navigationBar. По факту вам нужно сделать их прозрачными.

Добавляем поддержку Window Insets

Если простыми словами, то при работе с Window Insets, вы получаете размер системных компонентов и вставляете их как padding в верстку для ваших компонентов экрана AppBar или RootView. Insets поддерживается всеми версиями Android, что позволяет реализовать концепцию edge-to-edge для всех пользователей. Подробности можно почитать или посмотреть в докладе Константина Цховребова с AppsConf.

Сначала я использовал его решение, а потом, когда вышла новая версия библиотеки Insetter от Криса Бэйнса, перешел на неё. Вам предлагаю сразу использовать Insetter.

Также я собрал пару полезных статей, на случай, если вы захотите разобраться в этом детальнее:

Материалы по режиму edge-to-edge лежат тут и в конце статьи:

Окрашиваем statusBar и navigationBar

Эффект безрамочности в режиме edge-to-edge достигается за счет того, что вы отрисовываете контент под statusBar и navigationBar и делаете их прозрачными. При этом, нужно сохранять контрастность иконок в этих компонентах.

Тут существует одна проблема, которая находится глубоко в системе и исправить её после релиза OS уже нельзя. Это изменение цвета иконок в системных компонентах (statusBar и navigationBar) со светлого на темный. Поэтому, нужно учитывать следующие правила, в зависимости от версии Android:

  • до 6.0 версии Android иконки statusBar и navigationBar всегда светлые и перекрасить их в темный цвет нельзя. Флаг View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR доступен с 23 API. Если у вас контент всегда темного цвета, то проблем не будет. Но чтобы сохранить контрастность иконок на фоне контента, следует добавлять на системные компоненты наложение фона, например, черного фона с 50% прозрачности;

  • с версии Android 6.0 можно задать, какими будут иконки в statusBar: белыми или черными. Однако navigationBar будет вести себя как в предыдущих версиях, поэтому наложение можно убрать только для statusBar. Флаг View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR доступен с 26 API;

  • с версии Android 8.0 можно выбрать белый или черный цвет иконок для обоих компонентов. Поэтому наложения можно убрать полностью.

Я нашел интересный пример WindowPreferencesManager, который реализовывал эту логику в приложении-каталоге материальных компонентов. Но там было много лишнего и разбираться в этом, думаю, захочет не каждый, поэтому я сделал мини утилиту edge-to-edge-decorator. Она хорошо кастомизируется под ваши нужды и реализует логику окрашивания statusBar и navigationBar за вас. Подробнее про реализацию можно почитать в документации.

Пример работы библиотеки:

Android 5.0

(API level 21)

Android 7.1

(API level 25)

Android 9

(API level 28)

Android 11

(API level 30)

Добавляем тёмную тему приложения

Теперь, после того, как у вас готов UI Kit приложения и вы изучили и поддержали новый подход с использованием Material Components, можно вернуться к реализации темной темы в приложении.

Я рекомендую следовать согласно следующему алгоритму:

  1. Изучаем гайды и статьи по проектированию темной темы (ссылки лежат в конце статьи).

  2. Дизайнер готовит первый прототип и цветовую схему темной темы приложения.

  3. Создание полноценной темной палитры цветов.

  4. Добавляем альтернативную палитру цветов в приложениях и проверяем или кастомизируем тему, и стили компонентов для темной темы.

Если основная тема вашего приложения описана правильно, то добавление темной темы не создаст проблем: нужно просто добавить color.xml в values-night, как мы и планировали в самом начале (как же мы тогда ошибались :))

Сама активация темной темы хорошо описана в документации. Коротко, что нужно сделать:

1) Поменять базовую тему приложения на DayNight.

<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">

2) Установить нужный режим отображения через метод AppCompatDelegate.setDefaultNightMode.

В системе доступно 4 варианта темы:

  • всегда светлая: AppCompatDelegate.MODE_NIGHT_NO;

  • всегда тёмная: AppCompatDelegate.MODE_NIGHT_YES;

  • выбирается в зависимости от режима энергосбережения (Android 9 и ниже): AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY;

  • переключается в зависимости от настроек системы (Android 10 и выше): AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;

Добавляем выбор темы приложения

Светлая тема

Темная тема

После того, как вы реализовали тёмную тему, вишенкой на торте станет выбор темы в настройках приложения. Почему это важно? Потому что ресурсы values-night были добавлены ещё в API level 8, но включение темной темы на уровне системы реализовали только в Android 10. Чтобы темная тема работала у всех пользователей, необходимо добавить возможность её выбора в приложении.

Для удобного API я написал вот такой класс:
enum class NightModeType(   val customOrdinal: Int,   @NightMode val value: Int,   @StringRes val title: Int) {   MODE_NIGHT_NO(       0,       AppCompatDelegate.MODE_NIGHT_NO,       R.string.mode_night_no   ),   MODE_NIGHT_YES(       1,       AppCompatDelegate.MODE_NIGHT_YES,       R.string.mode_night_yes   ),   MODE_NIGHT_FOLLOW_SYSTEM(       2,       AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,       R.string.mode_night_follow_system   ),   MODE_NIGHT_AUTO_BATTERY(       2,       AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY,       R.string.mode_night_auto_battery   );   companion object {       fun fromValue(@NightMode value: Int) = values().firstOrNull { it.value == value } ?: getDefaultMode()       fun fromCustomOrdinal(ordinal: Int): NightModeType {           return if (ordinal == 2) {               getDefaultMode()           } else {               values().firstOrNull { it.customOrdinal == ordinal } ?: getDefaultMode()           }       }       fun getDefaultMode(): NightModeType {           return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {               MODE_NIGHT_FOLLOW_SYSTEM           } else {               MODE_NIGHT_AUTO_BATTERY           }       }   }}
А выбор темы можно реализовать таким образом:
private fun createNightModeChooserDialog(command: ShowNightModeChooserDialog): AlertDialog {   return AlertDialog       .Builder(ContextThemeWrapper(requireContext(), R.style.ThemeOverlay_AppTheme_AlertDialog))       .apply {           setTitle(getString(R.string.item_dark_theme_text_view_title_text))           val nightModes = arrayOf(               getString(NightModeType.MODE_NIGHT_NO.title),               getString(NightModeType.MODE_NIGHT_YES.title),               getString(NightModeType.getDefaultMode().title)           )           val selectedMode = command.selectedMode.customOrdinal           setSingleChoiceItems(nightModes, selectedMode) { dialog, which ->               val nightMode = NightModeType.fromCustomOrdinal(which)               persistentStorage.saveNightMode(nightMode.value)               AppCompatDelegate.setDefaultNightMode(nightMode.value)               dialog.dismiss()           }           setNegativeButton(               getString(R.string.fragment_dialog_night_mode_chooser_button_cancel_text),               null           )       }       .create()}

И тут тоже есть проблема: выбранная пользователем тема нигде не запоминается, поэтому её необходимо сохранять. Сделать это можно вот такой проверкой в методе onCreate у вашего activity:

override fun onCreate(savedInstanceState: Bundle?) {   checkNightMode()   setTheme(R.style.AppTheme)   super.onCreate(savedInstanceState)}private fun checkNightMode() {   val savedNightModeValue = persistentStorage.getSavedNightMode(AppCompatDelegate.MODE_NIGHT_UNSPECIFIED)   val selectedNightMode = NightModeType.fromValue(savedNightModeValue)   AppCompatDelegate.setDefaultNightMode(selectedNightMode.value)}

Заключение

Вместо пары недель на реализацию тёмной темы у нас ушло три месяца. Но мы не просто сделали тёмную тему на проекте Ростелеком Ключ, но и подняли дизайн приложения на новый уровень:

  • сформировали четкий и полный UI kit в Figma;

  • автоматизировали экспорт UI kit в Figma и опубликовали утилиту figma-export;

  • правильно реализовали все базовые компоненты в Android приложении;

  • поддержали новый режим edge-to-edge, и опубликовали библиотеку edge-to-edge-decorator, которая поможет быстро добавить режим edge-to-edge на других проектах.

Так сказать, мы вышли из зоны комфорта, ради темной темы, и поправили кучу моментов в основном процессе работы :)

Материалы для глубокого изучения

Все ссылки я оформил в виде gist, поэтому можете сохранить его себе поставив звездочку.

Подробнее..

Исправляем Госуслуги малой кровью добровольный редизайн мобильного приложения

15.03.2021 02:11:17 | Автор: admin

Допустим, создателям мобильного приложения не выделили отдельного дизайнера - бывает. Допустим, приложение версталось программистами без предположений о том, насколько Госуслуги огромны, и скорости роста их функций вширь.

Попытаемся исправить имеющийся результат без напряга - все предлагаемые изменения должны исполняться за смехотворное число человека-часов и не должны затрагивать архитектуру приложения.

Дисклеймер о Госуслугах

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

На это дело явно было положено не мало сил - начиная от человека, который решился протолкнуть идею цифровизации, заканчивая всеми дизайнерами, инженерами и разработчиками, которые смогли договориться и выпустить на рынок очень объемный и рабочий продукт.

Вопросов к продукту много, но это все правки к готовому проекту, которые мы все так любим получать.

Дисклеймер об авторе

Я мобильный разработчик. К дизайну имею лишь косвенное отношение - использую макеты, предоставленные дизайнерами на проект, и стараюсь всегда подмечать, где стоит чуть больше учесть специфику мобильных устройств, где пользователю будет больно каждый раз.

В фигме решил наконец разобраться специально для этой статьи, просто чтобы визуализировать мысли. Так что качество исполнения подстать качеству мыслей)

Сейчас

Если кто-то не заходит в Госуслуги каждый день, то напоминаю, как они выглядят сейчас:

Исправляем главный экран

Чаще всего будем видеть главный экран. Он состоит из нескольких блоков, о которых стоит поговорить.

Четыре кнопки оплаты

У нас есть 4 кнопки оплаты - квитанции, штрафы, налоги, судебные задолженности. Действительно, в первую очередь мне хотелось бы знать, нет ли у меня долгов перед государством. Во вторую - хочу тут же иметь возможность долги оплатить.

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

  • сделаем так, чтобы кнопки стало видно сразу

  • не будет вводить заблуждение пользователя - заменим иконку штрих-кода на QR-код, ведь именно его надо искать на квитанции

  • статус "Не найдено" - это ошибка, сервер не смог найти информацию, или у меня нет долгов? Заменим на "Отсутствуют"

  • если в какой-то категории у нас есть задолженность, то сразу отобразим количество штрафов и их общую сумму

Уведомления

Уведомления - новости, которые оповещают о событиях, касающихся лично нас. Новости хороши к обеду, но потом о них можно забыть. Никто не перечитывает три последних оповещения каждый раз, заходя в приложения.

Сделаем колокольчик, отображающих непрочитанные уведомления.

Услуги

Основная часть и смысл приложения - услуги (запись на посещения, получение справок, запрос информации и т.д).

Здесь видим грамотное решение - вынесены три функции, которыми чаще всего будет пользоваться человек, а все остальные спрятаны за кнопкой "все услуги".

Будем считать, что отображаемые услуги выбраны не случайно: или на основе общей статистики, или подстраиваются динамически под каждого пользователя. Но кнопку "все услуги" все-равно хочется сделать больше, а не как ссылку на новости.

Также уберем выбор региона на этом этапе. От выбора местоположения зависит функционирование только некоторых услуг - паспорт гражданина РФ он и во Владивостоке паспорт.

FAQ

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

Но мой жизненный опыт подсказывает мне, что в FAQ можно найти только информацию о пунктах доставки интернет-магазинов - все остальное там искать пустая трата времени. Возможно, Госуслуги исключение, но доверие к этому разделу потеряно безвозвратно.

Решение - заменяем все вопросы на умный поиск с подсказками. Умный - потому что неплохо было бы хранить синонимы и искать не только по точному совпадению. Это же не поисковик по всему интернету, на 130 вопросов можно такую систему.

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

Новости

Сначала возникает желание выкорчевать этот блок и выругаться: "Кому нужны новости вашей структуры кроме вас самих?". Но через секунду решаешься их прочитать - оказывается, там много чего интересного.

Неплохие скидки по карте Мир, информация о скидках на оплату штрафов, ссылка на раздел для жалоб на ямы - я бы не узнал, что это есть на Госуслугах, если бы не эти уведомления. Так что у нас первый блок, который мы решительно оставляем без изменений.

Исправляем список услуг

А тут все коротко. На сайте так много услуг, что единственный способ предоставит к ним удобный доступ с мобильного устройства - действительно умный поиск.

Предлагаю выводить группы услуг, а в описание перечислять подгруппы. Сейчас почти так и есть, только не понимаю отрицания существования списков.

Итого

Главная цель статьи - показать, что потратив совсем немного времени можно качественно улучшить отличный продукт. Обидно, когда мощная начинка не раскрывается из-за непродуманного дизайна.

Думаю, люди, разрабатывающие этот продукт, были просто слишком увлечены качеством бекенда и исправятся в ближайших обновлениях.

На правах....

dendolg.ru - сайт-портфолио-визитка, контакты для сотрудничества

t.me/dolgopolovd - личный блог, в котором подмечаю хороший и высказываю идеи по поводу плохого промышленного и цифрового дизайна. а иногда размышляю о программировании и прочей философии

Подробнее..

Дизайн-система что это, для чего и как создать

22.10.2020 12:07:47 | Автор: admin

Всем привет!

Я рад вернуться к вам, дорогие читатели сообщества, и поделиться опытом и знаниями, полученными благодаря работе в IT-компании Omega.

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

  • Что такое дизайн-система?

  • Для чего она нужна?

  • Как её создать?

Что такое дизайн-система?

Давайте разбираться по порядку. Дизайн-система представляет собой совокупность трех сущностей:

  1. Визуальный язык то, что мы видим.

  2. Framework библиотека визуального языка, его код.

  3. Guidelines правила, как должно все выглядеть и каким образом применяться.

Можно считать, что дизайн-система является отдельным продуктом внутри любого IT-продукта.

Визуальный язык

Визуальная составляющая дизайн-системы включает в себя множество элементов, основные из которых:

  • Цвета

  • Шрифты

  • Пространство

  • Формы объектов

  • Иконки

  • Изображения

  • Взаимодействия

  • Анимации

  • UI-компоненты

  • Звуки

Задача визуального языка передать ценности бренда потребителю. Например, чтобы передать домашнюю атмосферу, можно использовать теплые тона и соответствующие изображения. Чтобы передать какой-то другой характер бренда, например, строгость и честность, использовать определенные шрифты и формы.

Какой образ приходит вам в голову, когда слышите или видите названия таких банков, как Альфа-Банк, ВТБ, Сбербанк, Тинькофф и других? Какие эмоции вы испытываете? Визуальный язык является одним из фактором того, каким мы запомним тот или иной продукт.

Framework

Фреймворк это, по сути, код визуального языка. Благодаря нему все визуальные элементы можно взять из библиотеки и легко применить во всех своих продуктах.

Давайте представим простую ситуацию. Итак, у нас есть одна кнопка Оплатить счет. И тут нам нужно поставить точно такую же кнопку для другой страницы, только называться она будет Перевести деньги.

Что, если у нас фреймворка нет? Тогда данную кнопку необходимо создать заново, пусть даже путем копирования существующего. А если мы решили изменить цвет кнопки, то нам придется вручную менять цвет во всех подобных кнопках? А если таких кнопок десятки, сотни или больше?

Поэтому нужна централизованная библиотека элементов визуального языка, которая позволит создавать и переиспользовать каждую деталь продукта.

Guidelines

Чтобы все, кто взаимодействуют с дизайн-системой, разговаривали на одном языке, необходимо выработать правила.

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

Казалось бы, условностей много. Как описать все так, чтобы не запутаться в правилах? Опишите только то, что нужно для конкретного элемента:

  • Что это за элемент?

  • Где он используется?

  • Какие задачи решает?

Также для UI-компонентов можно описывать анатомию: обозначьте структуру и все параметры, из которых они строятся.

Таким образом, правила применения элементов дизайн-системы позволяют упорядочить процесс работы для всех. Они задают определенные рамки для полета фантазии и формируют понимание, что любое изменение дизайн-системы может затронуть множество экранов и сценариев взаимодействия пользователя в продукте. Это развивает чувство ответственности на каждом участке работы над любой, даже самой мелкой, деталью продукта.

Для чего нужна дизайн-система?

Как и для любого IT-продукта, важно ответить на вопрос: для чего нужна дизайн-система? Или, как говорят некоторые коллеги по цеху чтобы что?

Ответ на него даст понять ценность продукта. Отчасти ее уже можно увидеть из того, что я описывал выше. Но давайте разложим по полочкам и рассмотрим глубже.

Автоматизация

Автоматизация это самая очевидная ценность. Дизайн-система позволит автоматизировать процессы и выиграть время на другие задачи.

Например, дизайнеры смогут сформировать библиотеку компонентов в графическом редакторе Figma и применять их во всех необходимых макетах. Разработчики, в свою очередь, просто используют ранее реализованные компоненты из фреймворка.

Итеративность

Возможность наследования и автоматического применения изменений в элементах дизайн-системы является мощным инструментом для продуктовой команды. Вы можете легко внедрить косметические или даже серьезные правки в одном месте. Таким образом шаг за шагом можно улучшать продукт бесконечно.

Однако любое внесение изменений это большая ответственность. Поэтому любая коррекция должна быть сознательной и аргументированной.

Консистентность

Консистентность говорит о том, что объекты и сущности, которые мы используем в продукте и которые выполняют одну и ту же работу, должны стремиться к унификации, стремиться быть похожими.

Когда мы пользуемся в продукте похожими функциями, он становится привычным и удобным: мы знаем интуитивно, как работает и выглядит кнопка, где она расположена.

Синхронизация

Все элементы в IT-продукте должны обладать единым языком общения на основе четких правил.

С ними новые члены продуктовой команды выполняют задачи в рамках продукта, не теряя времени на раскачку: дизайнеры создают новые элементы на основе заданного визуального языка, а разработчики точно знают, каким образом их реализовать и использовать.

Больше времени на UX

Эта ценность является, по сути, совокупностью всех предыдущих преимуществ. Ручная работа с визуальным языком, на которую раньше тратилось много времени, становится максимально автоматизированной.

После создания дизайн-системы можно выделить больше времени на исследование и детальнее спроектировать user flow сценариев продукта (да, бывает, флоу не все делают и просто фигачат). Кстати, я писал подробно о user flow в предыдущей статье.

Скорость прототипирования

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

Недостатки дизайн-системы

Все вышеописанное можно отнести к плюсам дизайн-систем, но у них, конечно, есть минусы.

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

Если бренд сформулировал новые правила визуального и вербального взаимодействия с клиентами, то визуальный язык дизайн-системы необходимо адаптировать. Дизайн-система должна идти в ногу с бизнесом и нести правильную идеологию бренда, развиваясь и трансформируясь вместе с ним.

Однако хочется отметить, что поддержка дизайн-системы в какой-то степени упрощается благодаря использованию современных инструментов, например, редактора Figma. У него достаточно функционала, чтобы дизайнеры могли с комфортом формировать и развивать UI-kit. К тому же, с помощью Figma можно легко перенять опыт коллег по цеху, используя готовые библиотеки

Как создать дизайн-систему?

Есть множество подходов для создания дизайн-системы. Я рекомендую рассмотреть атомарную систему, главным преимуществом которой является наследуемость. Пожалуй, тема атомарной дизайн системы может потянуть на отдельную статью. Про это можно почитать в переводе статьи Брэда Фроста (Brad Frost) Atomic Web Design.

Примеры того, как сделаны дизайн системы:

После создания дизайн-системы немаловажно разобраться в том, как ее внедрить в практику компании. Во второй статье я расскажу о том, как пошагово выстроить процесс внедрения дизайн-системы в любой компании.

Я надеюсь, что каждый почерпнул для себя ценное из статьи. А я еще раз убедился в том, что работа над статьей структурирует знания и мотивирует на дополнительное изучение.

Спасибо за внимание!

Подробнее..

Figma выкатила новый Auto Layout

19.11.2020 20:15:16 | Автор: admin

Сегодня Фигма выкатила отличную Фичу которая упрощает в разы построение макетов для адаптации под устройства, переиспользование компонентов, и в работе в целом.

Файл с примерами:тут

Мануал:тут

Поле с Auto Layout теперь выглядит так:

Теперь с легкостью можно настраивать разное поведение вложенных компонентов, а так же разные отступы в компонентах, сделать их можно с помощью новых настроек:

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

Новые настройки по ресайзам компонентов:

Источник: https://figma.zoom.us/webinar/register/WN_XnLmGvmIT9uo7tbSTGFWJwИсточник: https://figma.zoom.us/webinar/register/WN_XnLmGvmIT9uo7tbSTGFWJw

Уже завтра (20 ноября) Фигма проводит разбор Фичи и использование нового Auto Layout Регистрация на мероприятие от Фигмы тут

Подробнее..

Перевод Один год удалённой работы в Figma

13.04.2021 16:13:10 | Автор: admin
image

Оптимизация удалённой работы


Перейдя на марте прошлого года на удалёнку, Figma, как и множество других компаний, начала искать способы организации сотрудничества и переноса офлайн-процессов и рабочих потоков в онлайн. Так как мы всё активнее использовали Figma в качестве виртуального дома для различных процессов, от мозгового штурма и исследований до тим-билдинга, то разработали гипотезу о способах изменения окружения: если мы разработаем, организуем и реализуем шаблоны сотрудничества, созданные специально для удалённой работы, то эффективность совместной работы повысится и это касается не только дизайна. Этот прогнозируемый рост эффективности сотрудничества означал бы, что шаблоны упрощают удалённую работу, и потенциально могут снизить напряжение некоторых болевых точек, на которые жаловались наши пользователи (да и мы сами!).

Отдел разработки быстро создал подборщик шаблонов, позволяющий пользователям создавать новые файлы из пустых пресетов или шаблонов, предназначенных для различных образцов удалённой работы. Мы провели эксперимент на части нашей пользовательской базы, предлагая подборщик шаблонов пользователям из экспериментальной группы. Задача заключалась в том, чтобы посмотреть, как коллективы будут использовать эти шаблоны (и будут ли вообще), а также оценить их конечное воздействие на сотрудничество.

image

Использованный в эксперименте подборщик шаблонов

Наши открытия


Мы выяснили, что пользователи, получившие подборщик шаблонов, имели показатель сотрудничества на 5% больше. Он измеряется как процент пользователей, вносящих правки или комментарии в общий файл. Кроме того, мы заметили, что при помощи подборщика шаблонов пользователи обнаруживали новые функции на 10% больше пользователей обнаружило пресеты кадров, а на 90% больше пользователей использовало в своём процессе творчества файлы Figma Community. Это относилось и к дизайнерам, и к их коллегам, не занимающимся дизайном в число наиболее популярных файлов вошли и специализированные дизайнерские шаблоны (для организации удалённых дизайнерских спринтов), и более общие, например, шаблоны whiteboarding и тим-билдинга.

Даже несмотря на то, что эксперимент проводился с частью нашей пользовательской базы, он не остался незамеченным. Мы получили положительные отзывы в социальных сетях и просьбы о добавлении в подборщик шаблонов документов для других сценариев использования. Рабочие коллективы не просто использовали этот контент, но и благодарили за него. Основная задача Figma Community объединять пользователей, чтобы они могли делиться, учиться и общаться. Это стало идеальным примером того, как мы можем находить способы сотрудничества в мире, где так важна стала удалёнка, полагаясь на работу друг друга.

Однако самым важным открытием стало то, что мы и так знали сотрудничество распространяется далеко за границы дизайна. И чем больше люди попадают в струю сотрудничества в рамках дизайна продуктов и UX, тем больше вероятность повышения качества их совместной работы и в других ситуациях.

Карта сотрудничества


Отметив положительную реакцию сообщества, мы решили оценить изменения количественно и сопоставить шаблоны с компаниями и регионами, особенно учитывая тот факт, что больше 80% пользователей Figma находится за пределами США. Мир движется в сторону удалённой работы, а мы наблюдаем рост сотрудничества между странами и часовыми поясами. На изображении ниже показаны приглашения и обмены файлами между пользователями в разных странах. Каждая связь обозначает обмен, а каждая страна раскрашена в соответствии с объёмом международного сотрудничества чем темнее страна, тем больше совместной работы.

image

Подробнее о том, что мы выяснили:

Между регионами


В 2020 году Европа была регионом с самым активным ростом международного сотрудничества: в феврале 2021 года количество обменов файлами удвоилось по сравнению с тем же месяцем прошлого года. На глобальном уровне количество файлов, над которыми работают совместно в разных часовых поясах в феврале 2021 года, по сравнению с тем же месяцем прошлого, выросло в 3,5 раза (а для всех файлов в целом рост составил 2,6 раза).

Между дизайнерами и их коллегами


В рамках команд мы наблюдаем тенденцию к тому, что всё больше недизайнеров присоединяется к дизайнерским рабочим пространствам своих коллективов и становятся частью процесса дизайна. В профессиональных коллективах и организациях соотношение дизайнеров и недизайнеров выросло с февраля 2020 года по февраль 2021 года, и на каждого дизайнера в коллективе стало приходиться на 25% больше недизайнеров. С ростом необходимости асинхронных коммуникаций дизайнеры делятся своими файлами в режиме только просмотр с коллегами, чтобы получать обратную связь в реальном времени. Эта тенденция отражается и в росте количества файлов, к которым дизайнеры открывают доступ для своих коллег-недизайнеров (+140%), и в увеличении отношения редактирующий/просматривающий (+12%), произошедших за последний год.

В рамках дизайнерского процесса


Также мы заметили, что большее количество коллективов начало сотрудничать в Figma на более ранних этапах жизненного цикла файлов. В течение 90 дней мы замеряли метрику время до начала сотрудничества измеряемую как количество дней, прошедшее между датой создания файла и первым случаем открытия файла другим сотрудником (не тем, кто создал файл). Среднее время до начала сотрудничества упало на 11% с периода перед началом пандемии COVID до второго квартала года (когда большинство компаний начало работать удалённо), и оставалось стабильным до конца 2020 года.

image

Перенос офлайн-процессов в онлайн


Изучая полученные данные (в дополнение к своему опыту удалённой работы в Figma), мы обратили внимание, что дизайнеры всё активнее делятся файлами со своими коллегами из смежных отраслей, и что это сотрудничество более гибко перетекло в структуры организаций и коллективов. Мы связались с представителями Atlassian и Dropbox, чтобы ознакомиться с их наблюдениями и сопоставить статистику сотрудничества до и после COVID.

Сотрудничество между людьми разных профессий в Atlassian


В начале марта 2020 года Atlassian активно начал использовать Figma сразу после того, как закрыл свои офисы из-за пандемии. Дизайнер Джейк Миллер сказал нам, что переход к работе над файлом в Figma сильно напомнил ему ощущения от работы в офисе с коллегами. Наблюдение за тем, как движутся курсоры, вселяет в тебя ощущение сотрудничества, а не просто сдачи готовой работы по частям, говорит Джейк. Процесс дизайна становится социализированным. И такой уровень сотрудничества выходит за рамки команды дизайнеров, он междисциплинарен. Благодаря использованию файлов Figma в Confluence, каждый становится частью процесса дизайна, рассказывает Джейк. Никто не остаётся исключённым из цикла.

Что важнее всего, возможность совместной работы в одном файле меньше похожа на удалёнку, и больше напоминает командный труд. Мы даже не осознавали, что теряем в процессе дизайна. Благодаря этому удалёнка снова стала похожа на командную работу.

image

Граф сотрудничества команды Atlassian в Figma до и после появления COVID

Асинхронность в первую очередь в Dropbox


В качестве одной из частей перехода на модель, основой которой является виртуальная работа, Dropbox перенёс ту долю сотрудничества, которая реализовывалась на совещаниях, в формат работы на основе файлов, выбрав модель асинхронности по умолчанию.

Хотя сотрудники, естественно, стремились решать рабочие вопросы через видеозвонки, это приводило к усталости от Zoom, перегруженности коммуникациями, постоянным контактам и нехватке времени для фокусировки на стратегической и творческой работе, рассказывает вице-президент Dropbox по дизайну Алистер Симпсон.

image

Граф сотрудничества команды Dropbox в Figma до и после появления COVID

Вместо того, чтобы полагаться на совещания, команда дизайнеров Dropbox перенесла основной объём работы на совместные файлы. Алистер говорит, что этот новый способ работы экономит самые важные ресурсы команды: время и энергию. При асинхронной работе паузы между сообщениями и вербальной коммуникацией не только приемлемы, но и предпочтительны. Они создают пространство для совершенствования работы и повышают значимость проводимого вместе времени, рассказывает Алистер.

Также команда стремится к как можно более открытому обмену, что приводит к демонстрации работы более широкой аудитории. Вместо проведения масштабного совещания мы начали записывать результаты анализа дизайна и делиться ими через заметки, которые сотрудники могут просматривать в нужное им время, говорит Алистер. Такие практики позволяют нам уравнять возможности и стать более гибкими дизайнерами

За последний год очень многие компании фундаментально изменили способ своей работы, а то и в корне поменяли свою бизнес-модель. Хотя удалённая работа в какой-то степени определённо была усовершенствованием, мы надеемся, что часть таких изменений открытое взаимодействие, более широкая включённость сотрудников в процессы и обмен между разными командами останутся и после неё.
Подробнее..

Поговорим про градиенты в Unity

14.01.2021 02:12:21 | Автор: admin

Всём привет. Меня зовут Григорий Дядиченко. Я в Unity разработке около 7 лет, и за это время повидал многое. Одна из основных проблем, которая встречается, когда забираешь у неопытных ребят проект - градиенты в интерфейсах. В целом ошибки в разработке интерфейсов не редкость. Вроде того же неумения пользоваться найн слайсом, атласами, понимания батчинга. Но градиенты стоят немного особняком, так как они либо раздувают вес билда до невообразимых размеров, либо рисуются в интерфейсе со стрёмными артефактами компрессии. Давайте обсудим почему так происходит, и что с этим можно сделать, как вариант решения. Кому данная тема интересна - добро пожаловать под кат.

Из чего в целом состоит интерфейс? В хорошем проекте он обычно состоит из кружков (либо шейдера для кнопок со скруглёнными углами), градиентов и иконок. Градиенты нужны, конечно, не в каждом интерфейсе, но они используются достаточно часто.

Плюсы и минусы градиентов в виде спрайтов

Тут есть некоторые нюансы. Но общей проблемой, пожалуй, всех являются артефакты сжатия. По умолчанию градиенты на том же Android жмутся не очень хорошо и появляются хорошо заметные артефакты. Можно отключить компрессию, но тогда градиенты значимо увеличат вес билда, что тоже не вариант.

В случае простых градиентов в плане веса текстур есть, конечно, хитрость. Сделать текстуру в 1 пиксель на высоту градиента, и тогда проблема отпадает. Но это подходит в основном для простых линейных градиентов.

В чём же плюс градиентов в виде спрайтов? Он, по сути, всего один - батчинг. Используя градиент в атласе с остальными спрайтами можно отрисовать весь интерфейс в один draw call, что, несомненно, является плюсом, но не всегда настолько значимым.

Альтернативное решение

Шейдеры и генерация текстуры в один пиксель шириной. В целом можно обойтись и без генерации, но тогда придётся писать уникальный шейдер под каждый конкретный случай, что не очень удобно. Таким имеет смысл заниматься только в случае крайней необходимости в плане оптимизации. Но для удобного управления градиентом и переноса его из той же фигмы лучше написать более общее решения, где массив наших цветов передаётся текстурой.

Тут стоит сказать о том, как в юнити рендерятся интерфейсы. Возьмём для примера тот же Image в режиме Simple и без флага Use Sprite Mesh в них всё немного сложнее. Image - это наследник Maskable Graphic, который в режиме Simple генерирует quad. По умолчанию при обработке меша наследники класса Graphic записывают цвет, указываемый в параметр color у vertex. И то поле, которое в Image отвечает за Sprite передаёт текстуру в _MainTex шейдера SpriteDefault. Шейдер умножает картинку на цвет, записанный в вершинах, и мы получаем компонент Image. Дальше этот меш с данным шейдером отрисовывает CanvasRenderer. Всё довольно просто.

Что же нам это даёт? Так как в юнити в интерфейсах мы можем:


1) Генерировать меши
2) Переписывать параметры вершин


То все необходимые для шейдера градиента параметры мы можем передать в генерируемый меш, написав своё расширения класса MaskableGraphic. В целом данные подходы можно использовать для реализация огромного числа кастомных компонент в UI.

Но есть один нюанс. Важным атрибутом в случае UI является [PerRendererData], так как на нём завязан батчинг интерфейсов, да и в целом удобство использования. Так как нам не хочется создавать по материалу под каждый градиент, то удобнее передавать все параметры в один материал, либо записывать в меш, но где уже каждый отдельный рендерер будет решать, что именно надо отобразить и какие параметры он использует.

На разных градиентах, артефакты выглядят по-разному, и на некоторых они почти незаметны. Возьмём за основу градиенты, которые поддерживаются той же Figma. Их 4 типа: линейный, конический, сферический и ромбовидный. Давайте про них и поговорим.

Генерация текстуры градиента

Для начала нам необходимо научиться генерировать текстуру градиента. В целом текстуры в юнити генерируются достаточно просто. Но, помимо этого, в Unity реализован замечательный сериализуемый класс Gradient, который позволит нам сразу получить удобный интерфейс для редактирования нашего градиента.

public Texture2D GenerateTexture(bool makeNoLongerReadable = false){    Texture2D tex = new Texture2D(1, (int)_GradientResolution, TextureFormat.ARGB32, false, true);    tex.wrapMode = WrapMode;    tex.filterMode = FilterMode.Bilinear;    tex.anisoLevel = 1;    Color[] colors = new Color[(int)_GradientResolution];    float div = (float)(int)_GradientResolution;    for (int i = 0; i < (int)_GradientResolution; ++i)    {      float t = (float)i/div;      colors[i] = _Gradient.Evaluate(t);    }    tex.SetPixels(colors);    tex.Apply(false, makeNoLongerReadable);    return tex;}

Параметры filter mode и wrap mode зависят в целом от удобства использования в конкретном шейдере. Gradient Resolution это параметр, отвечающий за высоту нашей текстуры градиента. С помощью него можно регулировать какая именно текстура нас устраивает, чтобы как можно меньше терять в качестве.

Текстуру мы сгенерировали, теперь пора перейти к шейдерам.

Линейный градиент

unity figma gradient - градиент сделанный шейдером, остальные текстурамиunity figma gradient - градиент сделанный шейдером, остальные текстурами

Пожалуй самый простой в реализации градиент. Единственная математика, которая в нём потребуется это поворот uv координат через матрицу поворота в вертексной части шейдера. Угол поворота мы будем передавать, записав его в uv1 канал меша.

v2f vert (appdata v){  const float PI = 3.14159;  v2f o;  o.vertex = UnityObjectToClipPos(v.vertex);  o.color = v.color;  o.uv = TRANSFORM_TEX(v.uv, _MainTex);  o.uv.xy -= 0.5;  float s = sin (2 * PI * (-v.uv2.x) /360);  float c = cos (2 * PI * (-v.uv2.x) /360);  float2x2 rotationMatrix = float2x2( c, -s, s, c);  rotationMatrix *=0.5;  rotationMatrix +=0.5;  rotationMatrix = rotationMatrix * 2-1;  o.uv.xy = mul (o.uv.xy, rotationMatrix );  o.uv.xy += 0.5;  return o;}

В фрагментной части мы просто отображаем текстуру с нашими модифицированными uv координатами. Функция SampleSpriteTexture - это вспомогательная функция необходимая для поддержки ряда внутренних функций Unity UI.

fixed4 SampleSpriteTexture (float2 uv){fixed4 color = tex2D (_MainTex, uv);#if UNITY_TEXTURE_ALPHASPLIT_ALLOWEDif (_AlphaSplitEnabled)color.a = tex2D (_AlphaTex, uv).r;#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWEDreturn color;}fixed4 frag (v2f i) : SV_Target{fixed4 col = SampleSpriteTexture ( i.uv) * i.color;return col;}

Вот и линейный градиент готов. Все шейдеры в данном случае получаются однопроходные и довольно легковесные. По этой причине особого влияния на производительность с точки зрения шейдера не будет.

Конический градиент

По своей сути конический градиент это завёрнутая в кольцо лента текстуры градиента. Так как по необходимому функционалу мы опираемся на фигму. То помимо самого угла поворота, от которого наш градиент начинается, нам нужно передать внутрь шейдера центр этой свёрнутой ленты. Так как любые вертексные параметры мы можем использовать, как угодно. Их название не играет никакой роли в работе шейдера. И так как нам нужно теперь три значения: две координаты для центра и угол, то запишем его в нормаль.

Итоговый шейдер, так же получается достаточно простой. Из любопытной математики тут, пожалуй, только правильный расчёт угла со знаком.

v2f vert (appdata v){  v2f o;  o.vertex = UnityObjectToClipPos(v.vertex);  o.color = v.color;  o.uv = TRANSFORM_TEX(v.uv, _MainTex);  o.center = v.center;  return o;}fixed4 frag (v2f i) : SV_Target{  const float PI = 3.14159;  float x =  (i.uv.x - i.center.x);  float y =  (i.uv.y - i.center.y);  float angle = acos(dot(float2(0, 1),normalize(float2(x, y))));  float sign = (x) / abs(x);  float TwoPI = PI * 2;  float2 uv = ( sign*angle - i.center.z / 360 * TwoPI) / TwoPI;  fixed4 col = SampleSpriteTexture (uv) * i.color;   return col;}

Если идти по шагам, что мы сделали в преобразовании uv координат. Перенесли центр координат и дальше использовали угол между вектором up и вектором из нашего центра до соответствующей uv координаты в качестве uv маппинга. Может звучать достаточно сложно для тех, кто не так много сталкивался с шейдерами. Но написав 5-10 шейдеров с таким принципом и покрутив его параметры - начинаешь понимать в чём смысл.

Сферический/радиальный градиент

Все градиенты по своей математике довольно просты. Для того, чтобы сделать сферический градиент нам понадобится только каноническое уравнение эллипса. Кроме того, теперь мы в шейдер будет передавать целых 5 параметров помимо текстуры для лучшего контроля. Центр нашего эллипса, радиус по оси х и по оси у и его поворот. Все функции можно будет подробно посмотреть в репозитории в конце статьи, так что я укажу только код самого шейдера.

v2f vert (appdata v){  const float PI = 3.14159;  v2f o;  o.vertex = UnityObjectToClipPos(v.vertex);  o.color = v.color;  o.uv = TRANSFORM_TEX(v.uv, _MainTex);  float s = sin (2 * PI * (-v.params.z) /360);  float c = cos (2 * PI * (-v.params.z) /360);  float2x2 rotationMatrix = float2x2( c, -s, s, c);  rotationMatrix *=0.5;  rotationMatrix +=0.5;  rotationMatrix = rotationMatrix * 2-1;  o.uv.xy = mul (o.uv.xy - v.center.xy, rotationMatrix );  o.params = v.params;  o.center = v.center;  return o;}fixed4 frag (v2f i) : SV_Target{float x =  i.uv.x;float y =  i.uv.y;float r1 = i.params.x / 2;float r2 = i.params.y / 2; float2 uv = sqrt(x * x / r1 + y * y / r2);fixed4 col = SampleSpriteTexture (uv) * i.color; return col;}

Поворот координат мы используем из нашего линейного градиента, только не смещая центр системы координат. А в фрагментной части у нас просто уравнение эллипса.

Ромбовидный градиент

Про него не хочется особо много писать, так как это тот же сферический градиент. Только вместо уравнения эллипса мы используем модули значений координат, чтобы получить ромб.

fixed4 frag (v2f i) : SV_Target{float x =  i.uv.x;float y =  i.uv.y;float r1 = i.params.x / 2;float r2 = i.params.y / 2;float2 uv = abs(x) / r1 + abs(y) / r2;fixed4 col = SampleSpriteTexture (uv) * i.color; return col;}

Собственно вот и все шейдеры, которые необходимы для отрисовки градиентов из Figma в интерфейсах.

Заключение

Мне очень хотелось бы, чтобы люди перестали использовать огромные битые градиенты в своих проектах, так как преимущества решения через шейдеры перевешивают все его недостатки. В целом его можно ещё оптимизировать и сделать немного элегантнее, но тем не менее это тот вид решения, которые уже несколько лучше, чем просто выгружать из дизайна в figma png от дизайнеров. Полностью реализованное решение, а также примеры использования вы можете найти в репозитории по ссылке.

Спасибо за внимание, надеюсь статья была для вас полезна!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru