Небольшая преамбула. Наш проект Quarkly — это микс графического редактора (вроде Figma, Sketch) и конструктора сайтов (по типу Webflow) с добавлением функционала, присущего классическим IDE. Про Quarkly мы обязательно напишем отдельный пост, там есть про что рассказать и что показать, ну а сегодня речь пойдет про упомянутый выше Atomize.
Atomize лежит в основе всего проекта и позволяет нам решать задачи, которые было бы невозможно или трудно решить с помощью Styled-System и Rebass. Как минимум, решение было бы гораздо менее изящным.
Если мало времени, чтобы осилить весь пост сейчас, то более лаконично ознакомиться с Atomize можно у нас на GitHub.
А чтобы знакомство было приятнее, мы запускаем конкурс по сборке react-компонентов с использованием Atomize. Подробнее об этом в конце поста.
С чего всё началось
Начиная разрабатывать Quarkly, мы условились, что хотим дать нашему пользователю возможность верстать на компонентах, но без необходимости использовать отдельный CSS-файл. Чтобы код был максимально минималистичен, но сохранял все возможности CSS, в отличие от инлайновых стилей.
Задача не инновационная и, на первый взгляд, вполне решаемая с помощью Styled-System и Rebass. Но этой функциональности нам оказалось недостаточно, а кроме того мы столкнулись со следующими проблемами:
- неудобная работа с брейкпоинтами;
- отсутствие возможности писать стили на состояние hover, focus etc;
- механизм работы с темами показался нам недостаточно гибким.
Что представляет собой Atomize (кратко)
Из ключевых особенностей Atomize мы можем выделить следующие:
- возможность использования переменных из темы в составных css-свойствах;
- поддержка hover и любых других псевдоклассов;
- короткие алиасы на каждое свойство (как в emmet);
- возможность указывать стили на конкретный брейкпоинт, сохраняя при этом читаемость разметки;
- минималистичный интерфейс.
При этом у Atomize есть два основных предназначения:
- создание компонентов с поддержкой атомарного CSS и тем;
- создание виджетов для интерактивного редактирования в проекте Quarkly.
Atomize, инструкция по применению
Перед началом работы необходимо установить зависимости:
npm i react react-dom styled-components @quarkly/atomize @quarkly/theme
Atomize является оберткой вокруг styled-component и имеет похожий API. Достаточно вызвать метод с именем необходимого элемента:
import atomize from '@quarkly/atomize'; const MyBox = atomize.div();
На выходе мы получаем react компонент, способный принимать любые CSS в виде пропсов.
Для удобства использования была разработана система алиасов свойств. К примеру bgc === backgroundColor
ReactDOM.render(<MyBox bgc="red" />, root);
С полным списком свойств и алиасов можно ознакомиться здесь.
Также предусмотрен механизм наследования в React:
const MySuperComponent = ({ className }) => { // some logic here return <div className={className} />; }; const MyWrappedComponent = atomize(MySuperComponent);
Работа с темами
Про это, как мне представляется, следует рассказать подробнее. Темы в Quarkly базируются на CSS-переменных. Ключевой особенностью является возможность переиспользования переменных из тем как в пропсах, так и в самой теме, без необходимости использования дополнительных абстракций в виде template-функций и последующей дополнительной обработки со стороны пользователя.
Чтобы использовать переменные из темы, достаточно описать свойство в теме и обратиться к этому свойству, используя префикс "—".
Переменные можно использовать как в JSX:
import Theme from "@quarkly/theme"; const theme = { colors: { dark: "#04080C", }, }; export const MyComp = () => ( <Theme> <Box bgc="--colors-dark" height="100px" width="100px" /> </Theme> );
(Цвет #04080C доступен через свойство —colors-dark)
Так и в самой теме:
import Theme from "@quarkly/theme"; const theme = { colors: { dark: "#04080C", }, borders: { dark: "5px solid --colors-dark", }, }; export const MyComp = () => ( <Theme> <Box border="--borders-dark" height="100px" width="100px" /> </Theme> );
(Мы переиспользовали переменную из цветов, подключив её в тему borders)
Для цветов в JSX-разметке предусмотрен упрощенный синтаксис:
import Theme from "@quarkly/theme"; const theme = { colors: { dark: "#04080C", }, }; export const MyComp = () => ( <Theme> <Box bgc="--dark" height="100px" width="100px" /> </Theme> );
Для работы с медиа-выражениями в темах предусмотрен breakpoint.
К любому свойству можно добавить префикс в виде имени ключа breakpoint’а.
import Theme from "@quarkly/theme"; const theme = { breakpoints: { sm: [{ type: "max-width", value: 576 }], md: [{ type: "max-width", value: 768 }], lg: [{ type: "max-width", value: 992 }], }, colors: { dark: "#04080C", }, borders: { dark: "5px solid --colors-dark", }, }; export const MyComp = () => ( <Theme> <Box md-bgc="--dark" border="--borders-dark" height="100px" width="100px" /> </Theme> );
С исходным кодом тем можно ознакомиться здесь.
Эффекты
Основным отличием Atomize от Styled-System являются «effects». Что это и зачем это нужно?
Давайте представим, что вы создаете компонент Button, меняете у него color и border, но как назначить стили на hover, focus etc? Тут на помощь приходят эффекты.
При создании компонента достаточно передать объект с конфигурацией:
const MySuperButton = atomize.button({ effects: { hover: ":hover", focus: ":focus", active: ":active", disabled: ":disabled", }, });
Ключом является префикс в имени пропса, а значением — CSS-селектор. Таким образом мы закрыли потребность во всех псевдо-классах.
Теперь если мы укажем префикс hover к любому CSS-свойству, то оно будет применено при определенном эффекте. Например, при наведении курсора:
ReactDOM.render(<MySuperButton hover-bgc="blue" />, root);
Также эффекты можно сочетать с медиа-выражениями:
ReactDOM.render(<MySuperButton md-hover-bgc="blue" />, root);
Несколько примеров
Чтобы визуализировать информацию выше, давайте теперь соберем какой-нибудь интересный компонент. Мы приготовили два примера:
- простой компонент, который показывает все возможности библиотеки;
- более сложный пример с карточкой покемона.
Во втором примере мы задействовали большую часть функционала, а также внешний API.
Но это не всё
Второе предназначение Atomize, как вы упомянули выше, это создание виджетов в Quarkly на основе пользовательских react-компонентов.
Для этого достаточно обернуть ваш компонент в Atomize и описать его конфигурацию, чтобы Quarkly смог понять, какие свойства можно интерактивно редактировать:
export default atomize(PokemonCard)( { name: "PokeCard", effects: { hover: ":hover", }, description: { // past here description for your component en: "PokeCard — my awesome component", }, propInfo: { // past here props description for your component name: { control: "input", }, }, }, { name: "pikachu" } );
Поля конфигурации для компонента выглядят так:
- effects — определяет браузерные псевдоклассы (hover, focus, etc);
- description — описание компонента, которое будет появляться при наведении курсора на его название;
- propInfo — конфигурация контролов, которые будут отображаться в правой панели (вкладка props).
Как определить пропсы, которые будут выводиться на правой панели (вкладка props):
propInfo: { yourCustomProps: { // имя свойства description: { en: "test" }, // описание с учетом локализации control: "input" // тип контрола } }
Возможные варианты контролов:
- input,
- select,
- color,
- font,
- shadow,
- transition,
- transform,
- filter,
- background,
- checkbox-icon,
- radio-icon,
- radio-group,
- checkbox.
Ещё один пример. Здесь мы добавили свой компонент в систему и теперь можем редактировать его интерактивно:
Спасибо тем, кто осилил материал до конца! Заранее извиняюсь за сумбур, это первый опыт написания такого рода статей. Буду благодарен за критику.
А теперь конкурс!
Дабы слегка подогреть интерес сообщества к более тесному знакомству с Atomize, мы решили пойти по простому и понятному (как и сам Atomize) пути — мы запускаем конкурс!
Вся информация о сроках, правилах и призах доступна на официальном сайте конкурса.
Если коротко: для участия и победы необходимо придумать (или найти готовый) интересный и полезный компонент на React и адаптировать его под требования Atomize. Мы выберем и наградим победителей сразу в нескольких номинациях. Дополнительные призы от нашей команды в случае добавления вашего компонента в Quarkly гарантированы.
ссылка на оригинал статьи https://habr.com/ru/company/quarkly/blog/504064/
Добавить комментарий