Rambler UI

Опыт разработки кросспроектной библиотеки

компонентов на React.JS

дратути

 

  • Общий профиль пользователя ID Rambler&Co
  • Админки: CRM, Комментарии, Опросы
  • Виджеты: Комментарии, Опросы/Квизы, Платежка, Соц. шарилка

Сергей Перескоков, frontend

Платформa Rambler&Co - кросспроектные сервисы

Какую проблему ты пытаешься решить?

  • Переиспользование верстки
  • Переиспользование js-кода контролов
  • Одинаковый дизайн на всех проектах
  • Простой старт новых проектов
  • Одинаковый дизайн на всех сервисах
  • Code-reuse
  • Не нужно верстать и программировать контролы
  • Автообновление дизайна
  • Разделение разработки на продуктовую и интерфейсную

 🛠 Компонентный подход

Соберем требования

  • Поддержка React.js

  • 🔞 Соблюдение наших design-guides

  • Простая установка для webpack/browserify

  • Желательно через npm/yarn

  • Поддержка тем (нескольких и в рантайм)

  • Поддержка модульности (только нужные CSS и JS)

6 years ago

Twitter Bootstrap

  • Since 2011
  • Готовая верстка (forms, modals, grid, etc.)
  • Возможность кастомизации (LESS/SASS или 💩хардкод)
  • Интеграция с JQuery
  • Прекрасный сайт с документацией
  • Набор элементов и API почти не меняется
  • Есть библиотека для React

Bootstrap Skin?

  • ✅ Есть готовые компоненты на React.js
  • ✅ Настройка тем при сборке (через LESS переменные)
  • ⚠️ Global-scoped CSS
  • ⚠️ Переписывание и дополнение CSS-стилей при рескине не надежно, т.к. это не API для кастомизации
  • ⛔️ Не все состояния из design-guides есть в bootstrap
  • ⛔️ Монолитный CSS для react-библиотеки
  • ⛔️ Нет поддержки нескольких тем и тем в рантайме

Bootstrap Skin?

Google Material Design

  • Since 2014
  • Design guides прежде всего
  • Mobile-first
  • Компонентный подход
  • Оф. реализация на Angular
  • Есть рескины bootstrap (WTF?!)
  • material-ui.com на React.js

Material Design Reuse

  • ✅ Реализация на React.js
  • ✅ Модульный подход
  • ✅ Использование тем в рантайм
  • ✅ Строгий API для кастомизации
  • ⛔️ Не все наши design-guides переносятся в набор компонент material-ui

Google Material Design

Делаем свою библиотеку

Button Component

  • JS
  • HTML (JSX)
  • CSS
  • Props
  • Theme
  • Documentation
  • Examples
  • Tests
import Button from 'rambler-ui/Button'

class MyComponent extends React.Component {

  render() {
    return <div><Button>Hello</Button></div>
  }

}

CSS

  • Препроцессоры + компиляция .css
  • Препроцессоры + сборка у пользователя .sass/.less/.styl
  • 👊 CSS in JS

CSS in JS

Стили создаются в рантайме и добавляются в документ через тег <style> или атрибут style="..."

CSS in JS - решения

  • props.style
  • Radium
  • StyledComponents
  • JSS

Inline Styles

  • Поддержка ReactNative
  • Работают быстрее

<Style> tag

  • Привычные селекторы
  • Поддержка псевдоклассов
  • Специфичность селектора - css-класс

StyledComponents

  • Тег + CSS-класс = <Component>
  • <Style> остается в DOM навсегда
  • Поддержка ReactNative
const Button = styled.button`
	border-radius: 3px;
	padding: 0.25em 1em;
	margin: 0 1em;
	background: transparent;
	color: palevioletred;
	border: 2px solid palevioletred;

	${props => props.primary && css`
		background: palevioletred;
		color: white;
	`}
`

render(
	<div>
		<Button>Normal Button</Button>
		<Button primary>Primary Button</Button>
	</div>
)

JSS

  • Привычные CSS-классы
  • Поддержка JS-object кода (легко писать миксины)
  • Тег <style> добавляется в дерево при маунте компонента и удаляется при анмаунте
  • Если на странице несколько инстансов одного и то же компонента с одной и той же темой, <style> будет добавлен один раз

JSS + themed-react-jss

@injectSheet((theme) => ({

  container: {
    display: 'inline-block',
    fontSize: 12,
    color: theme.button.fontColor,
    background: theme.button.backgroundColor
  },

  icon: {
    paddingRight: 15
  }

}))
class Button extends Component {
  render() {
    const css = this.props.sheet.classes
    return <div className={css.container}>
      <Icon className={css.icon} />
      {this.props.children}
    </div>
  }
}

render(
  <ApplyTheme theme={{button: {fontColor: '#fff', backgroundColor: '#000'}}}>
    <Button>Hello<Button>
  </ApplyTheme>
)

Поддержка нескольких тем

render(
  <div>
      <ApplyTheme theme={{button: {fontColor: '#fff', backgroundColor: '#000'}}}>
          <ApplyTheme theme={{button: {fontColor: 'yellow'}}}>
            <Button>Hello<Button>
          </ApplyTheme>
          <ApplyTheme theme={{button: {backgroundColor: 'blue'}}}>
            <Button>Hello<Button>
          </ApplyTheme>
      </ApplyTheme>
  </div>
)

StyledComponents

JSS

Требования к документации

  • Мультиверсионность
  • Возможность редактировать код
  • Скопированный код будет сразу работать
  • Таблица со свойствами компонента
  • Кастомное дерево компонентов
  • Кастомизация сайта с документацией
  • Полноценная песочница

React StyleGuidist

React StyleGuidist

  • Нет полноценной песочницы
  • Все компоненты выводятся сразу (тормозит)

Делаем свою документацию

  • react-docgen

  • codemirror

  • ( highlight.js )

Делаем свою документацию

import React from 'react'
import Avatar from 'rambler-ui/Avatar'
import { ApplyTheme } from 'rambler-ui/theme'

export default function AvatarExample() {
  const props = {
    style: {
      marginLeft: 10
    },
    src: '//api.adorable.io/avatars/face/eyes4/nose5/mouth7/8e8895/'
  }

  return (
    <div>
      <ApplyTheme>
        <div>
          <div style={{ display: 'inline-block', width: '33%' }}>
            Circle
            <Avatar {...props} profileType="facebook" />
            <Avatar {...props} size={20} />
            <Avatar {...props} size={60} />
          </div>
        </div>
      </ApplyTheme>
    </div>
  )
}

DEMO

git.io/rambler-ui

Profit.

RamblerUI используется в проектах:

  • Комментарии
  • CRM
  • QUIZ
  • Профиль пользователя ID Rambler&Co
  • Рамблер/Почта

Что дальше?

  • Покрытие тестами
  • Расширение набора компонент
  • Налаживание процессов разработки
  • Дистрибуция 🚀

✌️Спасибо.

Список ресурсов и баззвордов:

  • JSS
  • StyledComponents
  • themed-react-jss
  • rambler-ui

deck

By Sergey Pereskokov

Loading comments...

More from Sergey Pereskokov