Você sabe o que é um design system e a importância dele para nós desenvolvedores? E como implementar em um projeto?
O que é Design System?
Design System é um documento vivo com todos os componentes e suas variações de um produto ou serviço, para facilitar tanto a comunicação entre times como o desenvolvimento final do produto.
Ele facilita a manter a constância do design do produto. A ideia é que esse sistema seja utilizado para consulta, para se tomar decisões como novas features, novas interfaces e novas propriedades do produto.
Ele pode conter itens básicos como cores, tipografia, marca e até mesmo pedaços de códigos.
O Design System não é um documento estático, ele pode sofrer constantes mudanças ao longo do tempo, e essa é a ideia desse sistema, ser completamente customizável para se encaixar de diversas formas sem perder sua consistência do design.

“Design system isn’t a project, it’s a product serving products”. — Nathan Curtis
Quem usa Design System?
As principais empresas da atualidade utilizam um sistema de Design System em seus produtos. Empresas como:

“69% das empresas corporativas usam ativamente um Design System ou estão trabalhando em um!” — UXPin
Agora, vamos ao objetivo desse post

Existem algumas formas de criar um Design System para sua aplicação Frontend. Hoje vou te mostrar como criar uma biblioteca para seu Design System utilizando React.
Tecnologias que vamos utilizar:
TypeScript TypeScript fornece segurança de tipo sobre suas funções (e componentes). Construir a biblioteca de componentes usando o TypeScript permite agrupar facilmente os tipos de seus componentes sem nenhum trabalho extra. E facilita a utilização do usuário final.
Rollup Rollup é um empacotador de módulos para JavaScript que compila pequenos pedaços de código em algo maior e mais complexo, como uma biblioteca ou aplicativo. Ele usa o novo formato padronizado para módulos de código incluídos na revisão ES6 do JavaScript, em vez de soluções idiossincráticas anteriores, como CommonJS e AMD. Os módulos ES permitem combinar livre e perfeitamente as funções individuais mais úteis de suas bibliotecas favoritas.
Use o Webpack para aplicativos e o Rollup para bibliotecas. — Rich Harris WebWebpack and Rollup: the same but different — Medium post by Rich Harris
Vamos para o código 🤓
Primeiro vamos inicializar nosso projeto:
$ npm init
Você pode usar as opções padrões para todos os valores, vamos editá-los depois.
Em seguida, adicionaremos as ferramentas necessárias para criar nossos componentes:
$ npm install react typescript @types/react --save-dev
Configurando o TypeScript
Vamos começar configurando o TypeScript dentro da nossa biblioteca, e para fazer isso é bem simples basta rodar o comando: $ npx tsc --init
Após a finalização do comando, vai ser criado um arquivo chamado tsconfig.json e é nele que vai ficar toda a configuração do TypeScript.
Nesse arquivo vamos fazer uma pequena alteração:
1{
2"compilerOptions": {
3 "target": "es5",
4 "esModuleInterop": true,
5 "forceConsistentCasingInFileNames": true,
6 "strict": true,
7 "skipLibCheck": true,
8
9 // Vamos adicionar as linhas abaixo
10 "jsx": "react",
11 "module": "ESNext",
12 "declaration": true,
13 "declarationDir": "types",
14 "sourceMap": true,
15 "outDir": "dist",
16 "moduleResolution": "node",
17 "allowSyntheticDefaultImports": true,
18 "emitDeclarationOnly": true
19}
20}Explicando o código adicionado:
- jsx: “react” — Transforma JSX em código React
- module: “ESNext” — Gera módulos JS modernos para nossa biblioteca
- declaration: true — Gera um arquivo .d.ts para os types da biblioteca
- declarationDir: “types” — Onde vai ficar os arquivos .d.ts
- sourceMap: true — Mapeando o código JS de volta às origens do arquivo TS para depuração
- outDir: “dist” — Diretório onde o projeto será gerado
- moduleResolution: “node” — Siga as regras do node.js para encontrar módulos
- allowSyntheticDefaultImports: true — Assume exportações padrão se nenhuma for criada manualmente
- emitDeclarationOnly: true — Não gera JS (o Rollup fará isso) apenas exporta declarações de tipo
Configurando o Rollup
Agora vamos configurar o grande protagonista por fazer a nossa biblioteca funcionar!
E para começar, vamos fazer as instalações necessárias:
$ npm install rollup @rollup/plugin-node-resolve @rollup/plugin-typescript @rollup/plugin-commonjs rollup-plugin-dts --save-devApós a instalação, vamos fazer as configurações necessárias para o Rollup funcionar. Vamos criar um arquivo chamado rollup.config.js e adicionar o seguinte código:
1import resolve from "@rollup/plugin-node-resolve";
2import commonjs from "@rollup/plugin-commonjs";
3import typescript from "@rollup/plugin-typescript";
4import dts from "rollup-plugin-dts";
5
6const packageJson = require("./package.json");
7
8export default [
9{
10 input: "src/index.ts",
11 output: [
12 {
13 file: packageJson.main,
14 format: "cjs",
15 sourcemap: true,
16 },
17 {
18 file: packageJson.module,
19 format: "esm",
20 sourcemap: true,
21 },
22 ],
23 plugins: [
24 resolve(),
25 commonjs(),
26 typescript({ tsconfig: "./tsconfig.json" }),
27 ],
28},
29{
30 input: "dist/esm/types/index.d.ts",
31 output: [{ file: "dist/index.d.ts", format: "esm" }],
32 plugins: [dts()],
33},
34];Nesse arquivo, vamos importar os plugins que instalamos, e também o nosso package.json e vamos usar essa variável para fazer referência de alguns valores como main e module que vamos definir em breve.
A primeira coisa que vamos configurar é o nosso input, ou seja o primeiro arquivo que , que é o nosso arquivo inicial da biblioteca. Esse arquivo é o responsável por exportar tudo o que temos na biblioteca.
E também vamos iniciar três plugins, o resolve, commonjs e o typescript.
O segundo objeto de configuração define como nossos types da bibliotecas são distribuídos e usa o dts plugin para fazer isso.
E por último, precisamos definir alguns valores dentro do arquivo package.json:
1{
2 "name": "lib",
3 "version": "1.0.0",
4 "description": "",
5 "scripts": {
6 "build": "rollup -c"
7 },
8 "author": "",
9 "license": "ISC",
10 "devDependencies": {
11 "@rollup/plugin-commonjs": "^21.0.2",
12 "@rollup/plugin-node-resolve": "^13.1.3",
13 "@rollup/plugin-typescript": "^8.3.1",
14 "@types/react": "^17.0.42",
15 "react": "^17.0.2",
16 "rollup": "^2.70.1",
17 "rollup-plugin-dts": "^4.2.0",
18 "typescript": "^4.6.2"
19 },
20 "main": "dist/cjs/index.js",
21 "module": "dist/esm/index.js",
22 "files": [
23 "dist"
24 ],
25 "types": "dist/index.d.ts"
26}Vamos começar criando o script de build da nossa biblioteca: "build": "rollup -c" onde o -c fala para o rollup usar o nosso arquivo de configuração que criamos anteriormente.
E depois vamos adicionar as seguintes linhas:
- main — Definimos o caminho de saída para os módulos CommonJS.
- module — Definimos o caminho de saída para os ES6Modules.
- files — Definimos o diretório de saída para a biblioteca.
- types — Definimos o local para os types da biblioteca.
E pronto, o Rollup já está configurado para criar o build da nossa biblioteca.
Criando nosso primeiro componente:
Vamos criar o nosso primeiro componente do Design System, vamos criar uma pasta src dentro da raiz do projeto que vai conter a estrutura:
1├── src
2│ ├── lib
3│ │ ├── TextField
4│ │ │ ├── TextField.tsx
5│ │ │ └── index.ts
6│ │ └── index.ts
7│ └── index.ts
8└── package.json⚠️ Os arquivos index.ts são extremamente úteis para a nossa biblioteca, eles vão facilitar as importações na hora de consumir a biblioteca. Então não se esqueça deles!
Dentro do arquivo TextField.tsx vamos ter o seguinte código:
1import React, { InputHTMLAttributes } from "react";
2
3export interface Props extends InputHTMLAttributes<HTMLInputElement> {
4label: string;
5}
6
7function TextField(props: Props) {
8return (
9 <div>
10 <span>{props.label}</span>
11 <input {...props} />
12 </div>
13);
14}
15
16export default TextField;No arquivo src/lib/TextField/index.ts
1export { default } from "./TextField";Em seguida, exportamos esse botão do diretório de componentes src/lib/index.ts
1export { default as TextField } from "./TextField";E, finalmente, exportaremos todos os nossos componentes do diretório src base:
1export * from './lib';Criando o build da biblioteca
Agora vamos utilizar o Rollup para criar o build da nossa biblioteca de Design System. A nossa estrutura de pasta deve ser algo parecido com:
1├── src
2│ ├── lib
3│ │ ├── TextField
4│ │ │ ├── TextField.tsx
5│ │ │ └── index.ts
6│ │ └── index.ts
7│ └── index.ts
8├── package.json
9├── tsconfig.json
10└── rollup.config.jsE para criar o build, é simples, basta rodar o comando $ npm run build ou $ yarn build e é só aguardar…
Apos o build concluir, vai ser criado uma pasta dist que vai ficar mais ou menos assim:

E se tudo ocorreu bem, temos a nossa primeira versão da biblioteca pronta para ser publicada!
Publicando a biblioteca
Agora que a nossa biblioteca de Design System “está pronta”, precisamos publicar ela para outras pessoas poderem utilizar. Para publicar ela no NPM vamos utilizar o GitHub como hospedagem.
Então antes de mais nada, você precisa subir a sua biblioteca para um repositório no GitHub. Vou pular essa parte no post por ser uma etapa mais simples, mas caso você não souber como fazer isso da uma olhada nesse link.
Depois de ter criado o repositório, vamos criar o token no GitHub para permitir a publicação da nossa lib, e para fazer isso é bem simples:
Vá para o seu perfil do Github: Configurações -> Configurações do desenvolvedor -> Tokens de acesso pessoal. Ou basta clicar neste link
Clique em Gerar novo token. O mais importante aqui é selecionar a opção write:packages. Isso dará ao seu token permissão para ler e gravar pacotes em sua conta do Github, que é o que precisamos no momento:

Quando terminar, você pode clicar para criar o token. O Github só mostrará o token uma única vez, Então certifique-se de copiá-la para um local seguro.
Agora vamos para uma parte bem importante, precisamos configurar o nosso NPM local para publicar a nossa biblioteca.
Para fazer isso precisamos usar o arquivo .npmrc, esse é um arquivo GLOBAL, então ele não fica na raiz do nosso projeto. (Mas se você preferir, é possível deixar na raiz do projeto)
Para usuários de Mac/Linux, ele vai estar em seu diretório pessoal: ~/.npmrc
Para usuários do Windows, ele também vai para o seu diretório pessoal, embora a sintaxe seja diferente: C:\Users{YOUR_WINDOWS_USERNAME}
Para saber mais sobre este arquivo de configuração clique aqui.
Depois de cria o arquivo, vamos colocar algumas informações nele:
1registry=https://registry.npmjs.org/
2@GITHUB_USERNAME:registry=https://npm.pkg.github.com/
3//npm.pkg.github.com/:_authToken=GITHUB_TOKENPrecisamos alterar duas informações nesse arquivo, a primeira é o GITHUB_USERNAME onde você deve colocar o seu usuário do GitHub. A segunda informação é o GITHUB_TOKEN que é o token que geramos no GitHub.
E por último, precisamos fazer uma última alteração no arquivo de package.json. Vamos alterar o nome do nosso projeto e adicionar mais uma linha de configuração:
1{
2"name": "@GITHUB_USERNAME/YOUR_REPOSITORY_NAME",
3"publishConfig": {
4 "registry": "https://npm.pkg.github.com/GITHUB_USERNAME"
5},
6...
7}Feito isso, nossa biblioteca já está pronta para ser publicada!
Agora é só rodar o comando npm publish e se tudo ocorrer bem, você terá sua primeira biblioteca! 🥳
Você pode conferir se tudo ocorreu bem no seu perfil do GitHub:

