Системы проектирования с веб-компонентами
Мы рассмотрим принципы построения хорошего атомарного дизайна, как создавать веб-компоненты с помощью Stencil и, наконец (возможно, самое важное), как разрешить вашей компании создавать и внедрять систему проектирования.
Переворот сценария в системах проектирования
Недавно мне удалось пообщаться с некоторыми ключевыми сотрудниками Ionic, которые также создали Stencil набор инструментов для создания систем проектирования и прогрессивных веб-приложений. Мы долго говорили о том, что обычно компании обращаются к Ionic с командой дизайнеров и им нужна помощь в создании компонентов. Как разработчик я хотел сначала поговорить о веб-компонентах, которые используются в Системе проектирования. Это было изрядным сюрпризом, поэтому я решил рассказать, что такое система проектирования и почему не имеет значения, с какого конца вы начинаете, если у вас есть команды дизайнеров и разработчиков, работающие вместе над созданием вашей системы проектирования.
Принцип атомарного проектирования
На мой взгляд, Atomic Design Брэда Фроста - наиболее грамотно написанное руководство. Брэд разбирает атомарный дизайн, как будто он относится к химическим элементам. Главное в атомарном проектировании - помнить, что вы создаете из самого конечного компонента, пока не создадите полноценную страницу.
Атомарный дизайн состоит из 5 этапов:
- Атомы
- Молекулы
- Организмы
- Шаблоны
- Страницы
Исходя из моего (ограниченного) опыта, большинство интерфейсных разработчиков беспокоятся об атомах, молекулах и организмах. Дизайнеры пользовательского интерфейса/UX беспокоятся об организмах, шаблонах и страницах. Когда на самом деле им обоим необходимо учитывать все 5 этапов.
Атомы
Атомы - это мельчайшие детали хорошего дизайна, это такие вещи, как кнопки, текстовые элементы и изображения. Вы заметите, что даже в этих базовых атомах ваши разработчики захотят знать, насколько эффективно атомы визуализируют и реагируют. Например, в кнопке анимация “щелчка” должна оставаться очень быстрой как на настольных компьютерах, так и на мобильных устройствах. Ваши дизайнеры захотят разрешить цвет, шрифт, рамку и размещение значков. Мы уже начинаем понимать, что необходимо, чтобы обе роли согласовывали каждый из компонентов.
Молекулы
Молекулы представляют собой группировку этих атомов в логическую взаимосвязь. Например, мы могли бы использовать изображение аватара, текст метки и кнопку для создания молекулы avatar-item-nav
. Теперь у нас есть простой, функциональный, многоразовый компонент, который мы можем использовать в самых разных местах.
Организмы
Теперь организмы могут использовать как атомы, так и молекулы для создания сложных компонентов. Вы даже можете создать действительно мета-систему и заставить организмы использовать организмы! Мне нравится использовать карточки (возможно, даже чересчур), поэтому давайте воспользуемся нашими компонентами, описанными выше. Допустим, мы создаем систему оформления книг и хотим иметь карточку автора. Эта карточка автора будет иметь avatar-item-nav
, в которой будет отображаться аватар автора, имя автора и кнопка для перехода к биографии автора. Итак, давайте рассмотрим эту мета-мысль, мы можем взять эту карточку автора и поместить ее в более крупный компонент книжной карточки, содержащий компонент изображения книжного героя и название. Самое замечательное в этих организмах то, что мы можем легко повторить их на основе динамических данных.
Шаблоны
Это стандартизированный способ, которым мы внедряем все атомы, молекулы и организмы во все ваши различные технологии. Многие люди используют инструменты проектирования, такие как Sketch или мой любимый Figma, для верстки каждого из этих различных типов шаблонов. Это часто называют скелетом вашей страницы, где каждый из элементов будет размещен на разных типах страниц, таких как домашняя страница, страница продукта и страница контактов. Здесь важно получить правильную структуру, а не содержание.
Страницы
Теперь вы можете продолжать использовать эти системы проектирования для создания фактического контента в каждом шаблоне. На этом этапе “резина отправляется в путь” вы узнаете, сколько настроек потребуется для каждого шаблона, организма, молекулы и атома, чтобы использовать все компоненты во всех ваших различных системах.
Почему мы сказали перевернуть сценарий?
Кажется, все прямолинейно, разве не все так думают? Ну, вы, вероятно, разработчик, а не дизайнер. Мои друзья-дизайнеры сказали бы, что нам нужно настроить типографику, цвет и стили. Вот почему я сказал, что вам нужно работать вместе, чтобы создать все 5 этапов проектирования. Пока дизайнер создает, скажем, цвета, разработчик должен сделать CSS достаточно переносимым, чтобы позволить каждому отдельному компоненту использовать один источник для обновления этих цветов. Часто компании начинают с разработки нескольких страниц, а затем просят разработчиков просто выяснить, как их создавать. Вот почему я думаю, что вам следует “перевернуть сценарий”.
Веб-компоненты с Stencil
Итак, мы много говорили об атомарном принципе проектирования, но вы могли бы просто использовать его в любой системе и начать создавать. У вас могли бы быть компоненты Angular, React Components и Vue Components. Но если вы заметили, что они не так легко работают везде. Итак, решение заключается в использовании веб-компонентов, потому что современный браузер уже может понимать их, и тогда любой интерфейсный фреймворк сможет использовать эти компоненты. Вы можете использовать Electron для настольных компьютеров (Slack, VSCode), PWA как для Android, так и для iOS.
Это, естественно, позволяет таким инструментам, как Stencil, создавать веб-компоненты, которые можно размещать централизованно и обновлять. Это также означает, что затем вы можете использовать эти компоненты в любой среде или вообще без среды.
Создание Stencil компонентов
Сначала мы собираемся создать проект компонента Stencil
и приступить к созданию всех необходимых компонентов. Если вы знакомы с ReactJS или JSX, вы будете чувствовать себя очень комфортно. Аналогично тому, ion-core
для создания которого команда Ionic
использовала Stencil
, мы будем создавать <yourname>-core
, например, ajonp-core
.
npm init stencil
Выберите:
- Компонент
- Название проекта: ajonp-core
Теперь, если вы перейдете в каталог вашего проекта, вы увидите простую настройку, в которой есть components
каталог с начальной настройкой my-component
. Это базовый компонент, который возвращает <div>
с вашими именем, отчеством и фамилией, которые были переданы при использовании реквизитов.
Этот новый компонент можно использовать, просто поместив его на <html>
страницу. Вы можете видеть это в index.html
, в этом новом веб-компоненте он передает 2 реквизита.
<my-component first="Stencil" last="'Don't call me a framework' JS"></my-component>
Это может показаться волшебством, но это действительно своего рода волшебство! Если вы внимательно посмотрите на index.html
, вы заметите, что есть script
импортируемый<script src="/build/mycomponent.js"></script>
, который предоставляет необходимый javascript, используемый для вашего компонента.
Затем вы можете запустить этот проект и просмотреть его в своем браузере.
npm run start
Создание атомов
Для кнопки мы создадим простую синюю кнопку, которая занимает слот, позволяющий передавать дочерние компоненты. В нашем случае это будет просто текст.
import { Component } from '@stencil/core';
@Component({ tag: 'ajonp-button', styleUrl: 'ajonp-button.css', shadow: true })
export class AjonpButton {
render() {
return (
<button>
<slot />{' '}
</button>
);
}
}
button {
background: #5851ff;
color: white;
margin: 8px;
border: none;
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
padding: 16px 20px;
border-radius: 2px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08);
outline: 0;
letter-spacing: 0.04em;
transition: all 0.15s ease;
cursor: pointer;
}
button:hover {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);
transform: translateY(1px);
}
Это всего лишь текстовый элемент, который вы можете передать в шестнадцатеричном цветовом коде, чтобы изменить цвет, однако этот элемент всегда будет заглавным и иметь заранее определенный размер 13. Обратите внимание, что здесь мы вводим элемент.
import { Component, Prop } from '@stencil/core';
@Component({ tag: 'ajonp-label', styleUrl: 'ajonp-label.css', shadow: true })
export class AjonpLabel {
@Prop() color: any;
render() {
return (
<p style={{ color: this.color }}>
{' '}
<slot />{' '}
</p>
);
}
}
p {
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
}
<ajonp-label color="#4b0a75">AJonP Label</ajonp-label>
Это опять же очень простой atom
стиль компонента, который снова использует URL-адрес изображения с использованием реквизитов в атрибуте src и делает его круглым, как аватар.
import { Component, Prop } from '@stencil/core';
@Component({ tag: 'ajonp-avatar', styleUrl: 'ajonp-avatar.css', shadow: true })
export class AjonpAvatar {
@Prop() src: any;
render() {
return <img src={this.src} />;
}
}
img {
border-radius: 50%;
width: 50px;
height: 50px;
object-fit: cover;
overflow: hidden;
}
Теперь мы должны начать понимать, что все эти веб-компоненты могут легко отображаться на экране каждый раз, когда мы добавляем их в наш index.html
. Они ни в коем случае не готовы к производству, но вы получаете общее представление о том, что должен содержать состав Atom.
Вы должны увидеть что-то вроде этого, если запустите:
npm start
Создание молекул
Теперь мы можем взять три атома, которые мы построили выше, и создать единую молекулу для отображения трех элементов в строке.
import { Component, Prop } from '@stencil/core';
@Component({ tag: 'ajonp-item', styleUrl: 'ajonp-item.css', shadow: true })
export class AjonpItem {
@Prop() color: string;
@Prop() src: string;
@Prop() labelText: string;
@Prop() buttonText: string;
render() {
return (
<span>
{' '}
<div>
{' '}
<ajonp-avatar src={this.src} /> <ajonp-label color={this.color}>
{this.labelText}
</ajonp-label> <ajonp-button>{this.buttonText}</ajonp-button>{' '}
</div>{' '}
</span>
);
}
}
div {
display: flex;
align-items: center;
justify-content: center;
}
span {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px;
border-style: solid;
}
Создание организмов
Теперь, когда у нас есть молекула, мы можем использовать ее внутри организма, чтобы повторить молекулу несколько раз. Мы примем очень простую форму, которая позволит нам добавлять каждую из ajonp-item
молекул, но вы заметите, что мы также собираемся использовать ajonp-button
атом внутри этого организма.
Оглядываясь назад, возможно, мне следовало назвать это списком
Эта сетка начинает усложняться, поскольку она использует @Props, как и другие наши компоненты, но теперь мы вводим @State, чтобы наш компонент мог управлять внутренними данными этого компонента, в нашем случае всеми элементами, которые принадлежат сетке. Конечным свойством класса является @Element, которое позволяет нам получить доступ к главному HTMLElement, позволяя нам находить поля ввода формы и для каждого отдельного элемента ajonp-item-grid
.
import { Component, Element, Prop, State } from '@stencil/core';
import { Item } from '../../models/Item';
@Component({ tag: 'ajonp-item-grid', styleUrl: 'ajonp-item-grid.css' })
export class AjonpItemGrid {
// Incoming Property elements
@Prop() defaultColor: string;
@Prop() defaultSrc: string;
@Prop() defaultLabelText: string;
@Prop() defaultButtonText: string;
// State to track inside of the component
@State() items: Item[] = []; //Host Element to access the form data instead of looking at entire document
@Element() el: HTMLElement;
addItem() {
const item = new Item();
item.src = (this.el.querySelector('#src') as HTMLInputElement).value;
item.labelText = (this.el.querySelector('#labelText') as HTMLInputElement).value;
item.color = (this.el.querySelector('#color') as HTMLInputElement).value;
item.buttonText = (this.el.querySelector('#buttonText') as HTMLInputElement).value; //Add newly created Item to array non-mutated
this.items = [...this.items, item];
}
scratchItem(key: number) {
//Remove newly created Item to array non-mutated
this.items = [...this.items.slice(0, key), ...this.items.slice(key + 1)];
//Return an array from before the key and after the key.
}
render() {
return (
<div>
{' '}
<h3>Grid Items {this.items.length}</h3> <hr /> Avatar <input
type="text"
id="src"
value={this.defaultSrc}
/> <br /> Label <input type="text" id="labelText" value={this.defaultLabelText} /> <br /> Color{' '}
<input type="text" id="color" value={this.defaultColor} /> <br /> Button <input
type="text"
id="buttonText"
value={this.defaultButtonText}
/> <br /> <ajonp-button onClick={this.addItem.bind(this)}>Add Item</ajonp-button> {this.items.map(
(item: Item, key: number) => {
return (
<ajonp-item
src={item.src}
color={item.color}
label-text={item.labelText}
button-text={item.buttonText}
onClick={this.scratchItem.bind(this, key)}
/>
);
}
)}{' '}
</div>
);
}
}
input {
width: 100%;
}
ajonp-item {
display: flex;
}
Теперь, если вы присмотритесь, мы используем эти два элемента на нашей странице, но мы также могли бы использовать их 100 раз на любой из наших страниц!
<div style="display: flex; justify-content: space-around">
<ajonp-item-grid
default-src="https://placekitten.com/300/300"
default-label-text="Kitty"
default-color="#4b0a75"
default-button-text="Scratch"
></ajonp-item-grid>
<ajonp-item-grid
default-src="https://placedog.net/300/300"
default-label-text="Puppy"
default-color="#F97912"
default-button-text="Bark Away"
></ajonp-item-grid>
</div>
Шаблоны
Я не собираюсь углубляться во весь код, который потребовался бы для создания шаблона, реализации, но Ionic предложила надежное решение и для этого в своей функциональности Layout. Что здесь замечательно, так это то, что вы снова можете сотрудничать между вашей командой разработчиков и проектировщиков для быстрого создания каркаса Hi-Fi, который подойдет для ваших будущих компонентов. Я снова должен сказать, что люблю Figma, поскольку все, созданное с использованием веб-технологий, всегда будет занимать особое место в моем сердце. С учетом сказанного, простое решение этой распространенной задачи создания шаблонов можно найти в наборе для разработки продукта.
Что мы можем сделать очень быстро, так это настроить шаблон для нашей страницы, чтобы дизайнеры и разработчики могли обсудить разбивку всех компонентов и убедиться, что у вас есть шаблон для успешной работы.
Страницы
Итак, шаблоны позволяют нам видеть, что мы можем сразу же настроить наши компоненты. Мы видим, что в нашем ajonp-button
нужно будет учитывать как первичный, так и вторичный тип, поэтому мы должны обязательно обновить свойство, чтобы учесть это, а также радиус угла у всех кнопок должен быть одинаковым, поэтому нам следует обновить css. Цвета и контент не мешают, пока не придет время просматривать примеры страниц. Теперь мы можем начать видеть реальную страницу, поскольку пользователь будет взаимодействовать с ней ежедневно, но поскольку мы построили всю нашу систему на компонентах с нуля, мы можем настроить каждый атом, молекулу и организм, чтобы гарантировать идеальное соответствие нашей системе.
Таким образом, можно настроить такие простые параметры, как первичные и вторичные.
button.primary {
background: #4b0a75;
color: white;
}
button.secondary {
background: white;
color: #4b0a75;
}
Создание и внедрение корпоративной системы проектирования
Я видел, как многие великие компании тратили миллионы долларов на поддержание разрозненных систем только для того, чтобы пытаться успевать за темпами изменений в брендинге своих отделов маркетинга. Примером разрозненной компании могут быть сайты, созданные с использованием Sitefinity, Adobe AEM, Angular и React. Теперь для каждого из этих стеков, допустим, они создали 5 разных сайтов. Чтобы обновить только компонент button
в этих системах, в лучшем случае вам нужно будет изменить его в 4 местах, но, более чем вероятно, вам нужно будет обновить его в 20 местах, затем собрать, протестировать и развернуть каждую из этих систем.
Добавление центрального расположения
Для того чтобы внедрение состоялось, вам необходимо будет разместить свои компоненты в централизованном хранилище, таком как NPM. Поскольку вы так усердно работали над созданием этой системы, вы, скорее всего, захотите сохранить ее в личном реестре npm вашей компании.
Как добиться успеха
Вам нужно заручиться поддержкой обоих отделов и работать как единое целое, чтобы добиться по-настоящему успеха, но в конечном итоге вы сэкономите массу времени и денег!!!