Я автор бесплатного курса по основам работы в Framer Classic. И, получив инвайт на бету новой версии Framer, мне хочется поделиться с вами впечатлениями. Если же вы пропустили предыдущий разбор, то вот ссылка на него. В этой статье мы поговорим о код компонентах.
Содержание статьи
Перед стартом
Сразу отмечу, что здесь я смотрю уже не на Beta версию, а на версию, которую уже опубликовали официально. Изменения не значительны, поэтому можно продолжать обзор в том виде, в котором я его начал. Что касается изменений в интерфейсе, я, по возможности, приведу их в виде подсказок. Что же касается код компонентов, то здесь они будут рассмотрены в том виде, чтобы их могли понять на уровне концепции.
Framer X вышел…
Здесь сразу хочу сказать, что вам нужно знать javascript или react, чтобы сделать что-то своё. Если не знать javascript, react или не иметь за собой команду разработчиков — можно использовать те модули, что доступны в Store внутри Framer X. Они могут расширить ваши возможности и помочь решить какие-то продуктовые задачи. В противном случае Framer X —это n-инструмент для прототипирования (любой простенький инструмент).
Где взять Framer X: https://framer.com/
Понадобится установить VSCode: https://code.visualstudio.com/
Познакомиться с интерфейсом, инструментами, дизайн компонентами и небольшими различиями между другими инструментами для дизайна можно прочитав предыдущие две статьи:
Часть 1: https://goo.gl/fiVk5b
Часть 2: https://goo.gl/C1QAJV
Что нового в компонентах в целом
Начнем с дизайн компонентов ведь они работают как символы в Sketch или компоненты в Figma. Это блоки или элементы вашего дизайна, которые можно переиспользовать. Например, как карточки, кнопки и т.д. Ознакомиться с ними вы можете мо ссылкам выше, где я рассматриваю все инструменты и дизайн-компоненты подробнее. Ниже я расскажу о некоторых изменениях, которые успели появиться после Beta версии.
Обновлённая вкладка Components выглядит теперь следующим образом. Пожалуй зацикливаться на ней не будем. Хочу уточнить тот факт, что в тот момент, когда вы создаете дизайн компонент он становится Master (родителем). Он не перемещается на страницу Symbols как это происходит в Sketch. Будьте внимательны, он остается там, где вы его создали. Это поведение больше похоже на Figma.
Группировка дизайн компонентов.
Работает так:
- Называем дизайн компонент Button/Primary, и создаем еще один, но с именем Button/Secondary.
- Получаем на вкладке компонентов выпадающее меню, со списком дизайн компонентов, которые будут относиться к категории Button.
Ещё одна из особенностей дизайн компонентов заключена в их родителях (master). Если сделать линкование экранов на master дизайн компоненте, то эта связь продублируется на instance (дочерние, копии) дизайн компоненты на всех ваших экранах. Пример ниже, а на этом с обновлениями всё, переходим к код компонентам.
Код компоненты
Впечатления, мысли и опыт, которыми сейчас с вами поделюсь ставит много вопросов, поэтому скажу сразу, что мой опыт не позволяет ставить какие-либо точки и говорить о том, что всё прекрасно или плохо в инструменте. Также учтите мой опыт в js и react, который также оставляет желать лучшего. Опыт на то и опыт, чтобы им делиться. В общем, изрядно обдумав написание этой заключительной части разбора, я не буду рассматривать подробно написание код, а поделюсь общими впечатлениями.
Что будем делать
Кнопку, элемент списка, список, графики и т.д. Разобравшись с компонентами в итоге соберем простенький прототип. В финале выводы. Ух.. задачка. Поехали.
Что нужно
Установили Framer X и VSCode? Теперь нужен NodeJS:
Повторно отмечу то, что это не урок по тому, как настраивать окружение для разработки, а обзорная статья. С этим разобрались, теперь на сайте нажмите на кнопку «Recommended for most users», чтобы скачать nodejs. Затем пройдите все пункт по инструкции во время установки. На этом всё. Теперь у вас будет доступ к установке npm пакетов.
Чтобы проверить работу node и npm. Запустите terminal и проверьте версии node, и npm с помощью команд: node -v и npm -v.
Далее переходим в VSCode и установим расширения для редактора, которые упростят работу. Но можно и без них. Для установки нажмите на иконку чтобы вызвать панель, где находятся все расширения или сочетание клавиш: cmd + shift + x.
- Prettier — фоматирует js,ts, css
- vscode-styled-components — подсветка синтаксиса styled components
- Auto Rename Tag — при переименовании одного тега HTML, его парный тег автоматически подхватит новое название.
С окружением разобрались. Сделаем мы простой интерфейс в вакууме на код компонентах. Для нетерпеливых, ссылка на финальный прототип будет здесь.
Перед тем как продолжить прочитайте мой взгляд на варианты того, когда нужно браться за Framer X и подход к нему. Я могу быть не прав и готов выслушать мысли других. Итак, мы можем подойти к прототипированию в Framer X следующим образом:
- Вы дизайнер в небольшом или большом продукте/стартапе/компании/студии и т.д. Вы знаете js и react на уровне, при котором вы можете пушить на продакшен свои компоненты и т.д. с одобрения (проверки) разработчиков. Framer X вам не нужен.
- Вы дизайнер в небольшом или большом продукте и т.д. Вы не знаете js и react. Вам не нужен Framer X.
- Вы дизайнер в небольшом или большом продукте и т.д. Вы не знаете js и react, но хотите учиться. Тогда учите и разбирайтесь сами или просите помощи у разработчиков в тот момент, когда застреваете где-то по ходу обучения. Затем, разобравшись и получив нужные основные навыки, предлагайте новый подход к работе бизнесу. Тогда, при условии что бизнес готов развивать команду дизайнеров/дизайнера, Framer X вам нужен. Отмечу, что нужен будет до того момента, пока вы не дойдете, в навыках, до пункта 1.
- Вы дизайнер в небольшом или большом продукте и т.д. Вы знаете js и react в основах. У вас сложилась дизайн-система из компонентов в продукте. У дизайнеров они храняться в дизайн инструментах. У разработчиков используется react. Допустим, команда разработчиков адаптировала их в Framer X так, чтобы ничего не ломалось. Вы начали играться, залезли в код и что-то сломали, когда команда разработчиков на это посмотрела (установили левые модули, наговнокодили). Потратили уйму времени и денег. Framer X вам не нужен.
- Вы дизайнер в большом продукте или успешном стартапе и т.д. У вас достаточно времени (или оно появилось как-то :)), средств и людей для того, чтобы отладить процессы взаимодействия между дизайнерами и разработчиками, используя Framer X. В этом случае Framer X вам нужен.
Ухх… Я вовсе не пытаюсь сказать вам что новый Framer X не нужен. Нужен, но давайте будем отдавать отчет для кого и для чего. Это прекрасный инструмент для создания интерактивных прототипов, которые не просто выглядят или ощущаются как настоящие, но и в прямом смысле могут работать как настоящие приложения. Это действительно сдвиг в сторону концепции «дизайнеру надо бы знать код», поскольку без знаний js и react в Framer X будет трудно сделать что-то такое, что по затраченым усилиям будем интереснее любого n-инструмента.
Для тех кто не закрыл статью, после вброшенных мыслей. Продолжим. Открыли исходный файл. Теперь установим один пакет из Store для будущего прототипа. Он бы не понадобился, но для демонстрации лично мне он нужен, но об этом позже.
Вот пакет: https://store.framer.com/package/kasimir/iphone-x-kit
Жмем Install. Переходим на вкладку Components и добавляем на вкладке Components статус бар и home indicator на артборд.
Наконец-то код и компоненты.
Для начала разберемся как устанавливать npm пакеты в проект Framer X. Вам нужно перейти в меню File > Show Project Folder.
Вы попадете в папку container. Затем нужно кликнуть правой клавишей на этой папке, чтобы вызвать контекстное меню. Из контекстного меню выбрать следующее: Services — New Terminal at Folder. Откроется терминал, в котором уже указан путь к этой папке.
Далее установим два пакета:
- Styled-components — для работы с css.
- ReCharts — для работы с графиками.
Чтобы установить styled-components, введите в терминале следующие команды и нажмите Enter:
npm install --save styled-components
И затем recharts:
npm install —-save recharts
После этого, создайте код компонент с названием Chart. У вас автоматически откроется VSCode с кодом этого компонента.
import * as React from “react”;
import { PropertyControls, ControlType } from “framer”;
const style: React.CSSProperties = {
height: “100%”,
display: “flex”,
alignItems: “center”,
justifyContent: “center”,
textAlign: “center”,
color: “#8855FF”,
background: “rgba(136, 85, 255, 0.1)”,
overflow: “hidden”
};
// Define type of property
interface Props {
text: string;
}
export class Button extends React.Component{
// Set default properties
static defaultProps = {
text: “Hello World!”
};
// Items shown in property panel
static propertyControls: PropertyControls = {
text: { type: ControlType.String, title: “Text” }
};
render() {
return{this.props.text};
}
}
Удаляем следующий блок:
const style: React.CSSProperties = {
height: “100%”,
display: “flex”,
alignItems: “center”,
justifyContent: “center”,
textAlign: “center”,
color: “#8855FF”,
background: “rgba(136, 85, 255, 0.1)”,
overflow: “hidden”
};
И вместо этого:
{this.props.text};
Оставьте только это:
{this.props.text};
После импортируем следующие элементы из recharts:
import { LineChart, Line, CartesianGrid, ResponsiveContainer, Tooltip, Legend, XAxis, YAxis } from “recharts”;
Затем импортируем styled-components:
import styled from “styled-components”;
Сразу создадим обёртку для наших графиков. Пусть это будет span элемент. После придаем этому блоку стиль в соответствии с кодом ниже:
const Wrapper = styled.span`
font-size: 11px;
& .recharts-cartesian-axis-tick-line {
display: none;
}
& .recharts-cartesian-axis-line {
stroke: #f1f3f6;
}
`;
Далее в соответсвии с документацией этого пакета мы создаем данные к графику, а затем сам график.
Данные к графику должны храниться в виде массива с объектами:
const data = [
{ name: "Июн", uv: 10, pv: 2, amt: 2400 },
{ name: "Июл", uv: 20, pv: 11, amt: 2210 },
{ name: "Авг", uv: 10, pv: 5, amt: 2290 },
{ name: "Сент", uv: 12, pv: 20, amt: 2480 },
{ name: "Окт", uv: 8, pv: 15, amt: 2680 },
{ name: "Ноя", uv: 3, pv: 5, amt: 3200 },
{ name: "Дек", uv: 6, pv: 10, amt: 4000 }
];
После данных для графика, мы должны определить Props. Свойства, которые будем использовать для кастомизации компонента. Допустим, мы хотим менять название 1 и 2 значений у легенды, а также стиль линий.
Для этого мы сперва определяем тип Props. В нашем случае это будет всегда string — строка.
interface Props {
firstLineLegend: string;
secondLineLegend: string;
lineType: string;
}
Затем определяем значения этих Props по умолчанию.
export class Chart extends React.Component{
static defaultProps = {
firstLineLegend: “Легенда 1”,
secondLineLegend: “Легенда 2”,
lineType: “monotone”
};
Далее нам нужно контролировать эти значения с помощью панели справа непосредственно в Framer X:
static propertyControls: PropertyControls = {
firstLineLegend: { type: ControlType.String, title: “1st Legend” },
secondLineLegend: { type: ControlType.String, title: “2nd Legend” },
lineType: {
type: ControlType.Enum,
title: “Line type”,
options: [
“basis”,
“monotone”,
“basicClosed”,
“basicOpen”,
“linear”,
“linearClosed”,
“natural”,
“monotoneX”,
“monotoneY”,
“step”,
“stepBefore”,
“stepAfter”
]
}
};
Далее, используя наш Wrapper обёртку создаем наш график:
render() {
return (name={this.props.firstLineLegend}
type={this.props.lineType}
dataKey=”uv”
stroke=”red”
/>name={this.props.secondLineLegend}
type={this.props.lineType}
dataKey=”pv”
stroke=”green”
/>
);
}
}
Полный код смотрите в финальном файле. Таким нехитрым способом мы научились устанавливать нужные пакеты, использовать их и адаптировать их параметры для кастомизации через Framer X. Голопом по европам, но это обзор, а не урок. Но давайте создадим ещё один код компонент: Button.
Повторяем процедуру с удалением const style и далением div. Импортируем уже знакомый styled-components модуль.
И создаём простую кнопку:
import * as React from “react”;
import styled from “styled-components”;
import { PropertyControls, ControlType } from “framer”;
const StyledButton = styled.div`
height: 100%;
display: flex;
text-align: center;
justify-content: center;
align-items: center;
/* для того чтобы контролировать цвет текста */
color: ${props => props.textColor};
/* для того чтобы контролировать цвет фона */
background-color: ${props => props.bgColor};
border-radius: 44px;
transition: all 0.4s ease;
&:active {
opacity: 0.5;
}
`;
// Define type of property
interface Props {
text: string;
bgColor: string;
height: number;
width: number;
}
export class Button extends React.Component{
// Set default properties
static defaultProps = {
text: “Button”,
bgColor: “#FF5E31”,
textColor: “#fff”,
width: 335,
height: 44
};
// Items shown in property panel
static propertyControls: PropertyControls = {
text: { type: ControlType.String, title: “Text” },
bgColor: { type: ControlType.Color, title: “Background” },
textColor: { type: ControlType.Color, title: “Text color” }
};
render() {
return (bgColor={this.props.bgColor}
textColor={this.props.textColor}
>
{this.props.text}
);
}
}
Здесь основная разница в том, что тип контрола мы используем теперь Color. И протягиваем его (для управления цветом компонента) в styled-components. Обратите внимение как:
background-color: ${props => props.bgColor};
Теперь давайте попробуем сделать список из данных, которые хранятся в файле: data.tsx. В папке container/code создайте такой файл.
Выглядеть data.tsx файл будет следующим образом:
const data = {
items: [
{
id: "1",
title: "Google",
money: "-823$",
category: "Search",
date: "Today"
},
{
id: "2",
title: "Facebook",
money: "+2339$",
category: "Social Network",
date: "Yesterday"
},
{
id: "3",
title: "Wallmart",
money: "-200$",
category: "Shopping",
date: "27.09.18"
},
{
id: "4",
title: "Amazon",
money: "+2200$",
category: "Shopping",
date: "26.09.18"
}
]
};
export default data;
Создайте в этой папке компонент HistoryItem.tsx. Он будет элементом списка и выглядит так:
import * as React from "react";
import styled from "styled-components";
import { PropertyControls, ControlType } from "framer";
const CardWrapper = styled.div`
width: 100%;
padding: 16px 20px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(41, 54, 95, 0.15);
overflow: hidden;
& div {
display: flex;
flex-direction: column;
}
& div:last-child {
text-align: right;
`;
const Title = styled.span`
font-size: 17px;
color: #29365f;
`;
const Subtitle = styled.span`
font-size: 14px;
color: #8a94bb;
`;
// Define type of property
interface Props {
title: string;
money: string;
category: string;
date: string;
}
export default class HistoryItem extends React.Component{
// Set default properties
static defaultProps = {
title: "Item",
money: "100$",
category: "Entertainment",
date: "Today"
};
// Items shown in property panel
static propertyControls: PropertyControls = {
title: { type: ControlType.String, title: "Title" },
money: { type: ControlType.String, title: "Money" },
category: { type: ControlType.String, title: "Category" },
date: { type: ControlType.String, title: "Date" }
};
render() {
return ({this.props.title} {this.props.category} {this.props.money} {this.props.date}
);
}
}
Здесь ничего сложного, Мы используем styled-components чтобы стилизовать элемент списка. И props чтобы выводить данные в него. Эти props будут использованы в другом компноненте — HistoryList, в который мы будем выводить данные с помощью метода map и нашего файла data.tsx.
Затем создайте в Framer код компонент HistoryList. Тут нам практически ничего не потребуется поэтому удаляйте и приводите всё в соответствии с кодом ниже. Не забудьте импортировать HistoryItem компонент и Stack из framer библиотеки:
import * as React from "react";
import { Stack } from "framer";
import HistoryItem from "./HistoryItem";
import history from "./data";
// Define type of property
interface Props {
text: string;
width: number;
height: number;
}
export class HistoryList extends React.Component{
render() {
return (width={this.props.width}
height={this.props.height}
gap={16}
direction="vertical"
>
{history.items.map(item => (key={item.id}
title={item.title}
money={item.money}
category={item.category}
date={item.date}
/>
))}
);
}
}
В коде выше мы использовали Stack, для того, чтобы использовать наш компонент HistoryItem в качестве элемента Stack. Stack’у задали вертикальное направление (direction) и отбивку(gap) от каждого элемента равную 16. Также мы использовали map метод. В этом конкретном примере map проходится по каждому элементу нашего файла history в массиве items и возвращает новый массив с результатом функции для каждого элемента — наш HistoryItem.
Анимация с помощью Overrides
Теперь добавим анимацию в интерфейс. Анимировать будем появление небольшого попапа поверх интерфейса с затенением всего интерфейса.
Нам нужен слой (frame) который перекроет весь интерфейс с черным цветом с прозрачностью 70%. Сам же фрейм будет иметь прозрачность 0. Попам же является фреймом, внутри которого лежит наш компонент HistoryList. Этот фрейм в самом низу интерфейса. Скрыт за его пределами.
Чтобы не тратить время, вот весь код анимации с комментариями:
// чтобы понять откуда беруться настройки анимации нужно с зажатым cmd кликнуть на "framer" слово, после from. Там же можно найти много интересного если поискать по ключевым словам: draggable, springOption, momentum и прочим знакомум вещам
import { Data, animate, Override, Animatable } from "framer";
// настраиваем анимацию
const springOptions = { tension: 450, friction: 33 };
// начальные координаты и значения свойства opacity
const data = Data({
clickButton: false,
overlayOpacity: Animatable(0),
top: Animatable(820),
bottom: Animatable(0),
buttonOpacity: Animatable(1),
closeOpacity: Animatable(0)
});
// это применяем к кнопке BANK STATEMENT
export const ButtonOverride: Override = () => {
return {
onTap() {
// при тапе на кнопку переключаем состояние с false на true и обратно
data.clickButton = !data.clickButton;
// если тру появляется перекрытие и попап
if (data.clickButton) {
animate.spring(data.top, 88, springOptions);
animate.spring(data.bottom, 0, springOptions);
animate(data.overlayOpacity, 1);
animate(data.closeOpacity, 1);
animate(data.buttonOpacity, 0);
// иначе все элементы возвращаются в исходное положение
} else {
animate.spring(data.top, 820, springOptions);
animate.spring(data.bottom, 0, springOptions);
animate(data.overlayOpacity, 0);
animate(data.closeOpacity, 0);
animate(data.buttonOpacity, 1);
}
}
};
};
// этот Override применяем к слою который перекрывает интерфейс
export const OverlayOverride: Override = () => {
return {
// тут анимируем только прозрачность
opacity: data.overlayOpacity
};
};
// а этот к попапу
export const StatementOverride: Override = () => {
return {
// а тут положение top, bottom
top: data.top,
bottom: data.bottom
};
};
// применяем к фрейму с текстом Close
export const ClosePopOverride: Override = () => {
return {
opacity: data.closeOpacity,
onTap() {
animate.spring(data.top, 820, springOptions);
animate.spring(data.bottom, 0, springOptions);
animate(data.overlayOpacity, 0);
animate(data.closeOpacity, 0);
animate(data.buttonOpacity, 1);
}
};
};
// этот применяем к компоненту кнопки и к фрейме ChartWrapper
export const HideButtonOverride: Override = () => {
return {
opacity: data.buttonOpacity
};
};
Чтобы использовать каждую анимацию, нужно выделить элемент на артборде и нажать «+» в правой панели в разделе Code. Выбрать файл App.tsx и выбрать нужную анимацию (Code Override).
Итог в финальном файле: здесь
В этой статье, как вы поняли, я не собирался учить вас JS и React. Во-первых, это отнимет много времени. Во-вторых, я владею лишь основами. Ещё раз: вам нужно знать JS и React для работы с новым Framer X, чтобы создать что-то под себя или своё. Да, если вы уже знаете JS и React даже в основах, то вы будете задаваться вопросом зачем эти танцы с бубном и т.д., если вы уже можете без всего этого написать какой-то прототип. Вас всё это будет смущать при том факте, если ваши знания достаточны для того, чтобы пушить ваш код в продакшен (если вы уже это умеете, я пока что нет). Так что теперь быстро накидать что-то не получится. От слова — никак. Но что поделать.
Вместо выводов
Мы всё ещё попрежнему ждём api и в целом документацию по новому Framer X. Также можем тратить время на собственные поиски и подходы к прототипированию в этом инструменте. Но я бы ответил на два вопроса:
- Хотите изучить код? Тогда попробуйте это через Framer Classic или Framer X. Ведь сейчас это отличная возможность поиграться на более серьёзном уровне или изучайте сразу первоисточники: JS, React и т.д вместо ожиданий какие внедрения/изменения/шаги предпримут Framer команда в следующем обновлении.
- Бизнес будет тратить время(деньги) специалистов(дизайнеров и фронтендеров) на то, чтобы: 1) Дизайнеры игрались с кодом, когда нужно решать боли пользователей, бизнеса, и, в целом, работать над проектированием продукта? 2) Фронтендеры дописывали свои компоненты для того, чтобы что-то было доступно для перезаписи, переиспользования в фреймере?
Если вам понравился разбор, я продолжу. Если я где-то был не прав — напишите в комментариях. Также не забывайте о том, что есть мой курс по предыдущей версии Framer. Ссылка.
Источник: сайт designpub.ru