Integração do Material UI com ReactJS
Algo que acontece com muitos Devs é não ter alguma aptidão ou mesmo não ter tempo hábil para fazer os Designs e Layouts de suas aplicações, mas quem não gosta de um front-end bonitinho?
Para ajudar a todos, existem muitas bibliotecas com padrões de Design e Layout bem definidos, e é sobre uma delas que falaremos hoje, o Material UI.
Não falaremos do Material UI em si, mas sim da junção dele com o nosso queridíssimo ReactJS criando uma interface semelhante ao do WhatsApp Web. Então pegue o seu guarda-chuva pois virá uma chuva de códigos abaixo.
/!\ WARNING /!\
Se você não conhece o JavaScript ou suas novas features com o ES6+ veja nossos cursos gratuitos starter: javascript e ES6+!!
Configurando o ambiente
Vamos começar criando um App React com o CLI do create-react-app, que já configura o webpack, eslint e outras cozitas a mais.
create-react-app material-app
Depois no diretório do seu projeto vamos instalar o Material UI:
npm install @material-ui/core
Caso queiramos adicionar os componentes ícones:
npm install @material-ui/icons
E também, no arquivo public/index.html
adicionaremos os links das fonts Roboto e Fonts Icon:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
Isso já é o suficiente para você utilizar o ReactJS com o Material UI. Logicamente não vou deixar você brincar sozinho com isso, então bora fazer alguma coisa!!!
Configuração inicial
Vamos, a princípio, limpar alguns arquivos que não nos interessam e ajustar o que é preciso. Então vamos deixar apenas os arquivos:
// No src ficará apenas
src/App.js
src/index.js
src/index.css
Uma pequena limpeza no index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Uma enxugada no index.html
:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>React + Material | RocketSeat</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
<div id="root"></div>
</body>
</html>
E por fim, um fundo acinzentado no body, no index.css
:
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: "#dfdfdf";
}
Pronto!! Agora vamos sem medo fazer nosso App.
Aplicação
Para ficar mais fácil, aqui quebrei em diversas partes o nosso código para ir comentando.
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import MoreVertIcon from "@material-ui/icons/MoreVert";
import { Paper, Typography, Grid, Card, CardHeader, CardContent, Avatar, List, ListItem, ListItemText, IconButton } from "@material-ui/core";
A função withStyles
servirá para injetamos um CSS customizado dentro do nosso componente principal e com ela podemos pegar informações do Material UI e assim criar algumas classes CSS que serão necessárias.
Como importamos o Fonts Icon, é através do @material-ui/icons
que pegamos os ícones que queremos. E pelo @material-ui/core
importamos os componentes já estilizados e padronizados do Material UI. Você pode olhar todos os componente aqui.
Para montarmos nosso estilo utilizaremos uma Arrow Function que retorna um objeto (as nossas classes).
const styles = () => ({
root: {
padding: "50px 100px",
zIndex: 999,
position: "absolute"
},
card: {
display: "flex",
height: "calc(100vh - 100px)"
},
rightBorder: {
borderRight: "solid #d0D0D0 1px"
},
content: {
marginTop: 0
},
background: {
position: "absolute",
height: 200,
width: "100%",
top: 0,
background: "#7159C1"
},
rightContainer: {
background:
"url(https://hdwallsource.com/img/2014/8/my-neighbor-totoro-wallpaper-27981-28703-hd-wallpapers.jpg) center center",
flex: 1
},
heightAdjust: {
display: "flex",
flexDirection: "column"
},
paper: {
background: "#9de1fe",
padding: 20
},
information: {
color: "#444"
}
});
Como podemos ver, no código abaixo utilizamos o componente Grid, um sistema de colunas que vai de 1 a 12 representando a porcentagem de uma div. Isso acontece dentro de uma div container, e as colunas são “itens” desse container.
Por isso, passamos a propriedade container
na nossa primeira Grid e a Grid filha com a propriedade item
para ser uma coluna. Nada impede de uma Grid item ter outra container.
const App = ({ classes }) => (
<div>
<div className={classes.background} />
<Grid container className={classes.root}>
<Grid item xs={12}>
<Card className={classes.card}>
<Grid container>
<LeftContainer classes={classes} />
<RightContainer classes={classes} />
</Grid>
</Card>
</Grid>
</Grid>
</div>
);
Observe a propriedade xs
, ela indica que em telas muito pequenas aquela Grid será representada com 12 colunas ou seja 100% de width. Isso acontece por que as Grids são responsivas.
Existem outras propriedades como xs, sm, md, lg, e xl, assim você pode configurar para que em telas grandes seja representada por 6 colunas e nas pequenas 12 por exemplo. Para saber mais.
Card
Nosso componente principal será um grande Card que forçamos ter o tamanho da nossa tela subtraindo os paddings
de 50px
do topo e rodapé. Nele dividiremos em duas colunas que separamos em dois componentes stateless o LeftContainer
e RightContainer
.
const list = [
{ id: 1, name: "Diego", text: "Lorem ipsum", image: <ImageIcon /> },
{ id: 2, name: "Robson", text: "Lorem ipsum", image: <WorkIcon /> },
{ id: 3, name: "Cleiton", text: "Lorem ipsum", image: <BeachAccessIcon /> }
];
const LeftContainer = ({ classes }) => (
<Grid item xs={3}>
<CardHeader
className={classes.rightBorder}
avatar={
<Avatar aria-label="Recipe" className={classes.avatar}>
H
</Avatar>
}
/>
<Paper className={classes.paper} elevation={0}>
<Typography className={classes.information} variant="subheader">
Acesse nossa comunidade no Discord e fique por dentro das novidades!
</Typography>
</Paper>
<List>
{list.map(item => (
<ListItem>
<Avatar>{item.image}</Avatar>
<ListItemText primary={item.name} secondary={item.text} />
</ListItem>
))}
</List>
</Grid>
);
Começamos com a Grid que representa a porcentagem de 3 colunas do nosso Grid container
. Os demais componentes são todos do Material UI que possuem várias propriedades. Adicionei algumas classes para deixar a parada bacana.
const RightContainer = ({ classes }) => (
<Grid className={classes.heightAdjust} item xs={9}>
<CardHeader
avatar={
<Avatar aria-label="Recipe" className={classes.avatar}>
<ImageIcon />
</Avatar>
}
action={
<IconButton>
<MoreVertIcon />
</IconButton>
}
title="Diego"
/>
<CardContent className={[classes.rightContainer, classes.content]} />
</Grid>
);
Aqui definimos uma Grid maior com a porcentagem de 9 colunas. Repara que juntando com o LeftContainer
temos 100% da Grid pai preenchida. E como anteriormente todos os demais componentes do Material UI e é só dar aquele bisu no site deles para esclarecer alguma propriedade.
Por fim, vamos exportar o nosso App.
Perceba que usamos o withStyles
passando como argumento o nosso styles
, ela nos retorna uma outra função que injeta a propriedade classes
que usamos dentro do nosso App.
export default withStyles(styles)(App);
Conclusão
É nítido que não há limites com o que você pode fazer com o Material UI em pouco tempo e com pouco trabalho!!!
O que eu fiz foi apenas uma demonstração. E que tal você fazer algo e mostrar para gente!??
Código completo no github: https://github.com/Rocketseat/blog-react-material-ui
Não esquece de deixar seu comentário dizendo o que achou e compartilhar com seus amigos. ;P