@material-ui/system
Sistema de estilo & funções de estilo para a construção de sistemas de design poderosos.
Primeiros passos
O pacote @material-ui/system
fornece funções utilitárias de baixo nível, chamadas de "funções de estilo", para construir sistemas de design poderosos. Algumas das principais características:
- ⚛️ Acesso aos valores do tema diretamente nas propriedades do componente.
- 🦋 Incentivo a consistência da UI.
- 🌈 Escreva estilo responsivo sem esforço.
- 🦎 Trabalhe com qualquer objeto de tema.
- 💅 Trabalhe com as soluções CSS-in-JS mais populares.
- 📦 Menos que 4 KB gzipped.
- 🚀 Rápido o suficiente para não ser um gargalo em tempo de execução.
É importante entender que este pacote expõe funções de estilo puras (sem efeitos colaterais) com esta assinatura: ({ theme, ...style }) => style
, só isso.
Demonstração
No restante desta seção de Primeiros passos, estamos usando styled-components como exemplo de referência (para enfatizar a universalidade deste pacote). Como alternativa, você pode usar JSS. As demonstrações também são baseadas no valor padrão do objeto de tema do Material-UI.
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import NoSsr from '@material-ui/core/NoSsr';
import { createTheme } from '@material-ui/core/styles';
import { palette, spacing, typography } from '@material-ui/system';
const Box = styled.div`${palette}${spacing}${typography}`;
// or import Box from '@material-ui/core/Box';
const theme = createTheme();
export default function Demo() {
return (
<NoSsr>
<ThemeProvider theme={theme}>
<Box
color="primary.main"
bgcolor="background.paper"
fontFamily="h6.fontFamily"
fontSize={{ xs: 'h6.fontSize', sm: 'h4.fontSize', md: 'h3.fontSize' }}
p={{ xs: 2, sm: 3, md: 4 }}
>
@material-ui/system
</Box>
</ThemeProvider>
</NoSsr>
);
}
Instalação
// utilizando o npm
npm install @material-ui/system
// utilizando o yarn
yarn add @material-ui/system
Criando um componente
Para usar o componente Box
, você primeiro irá precisar criá-lo. Para começar, adicione uma função de spacing
e palette
para o argumento de estilo.
import styled from 'styled-components';
import { spacing, palette } from '@material-ui/system';
const Box = styled.div`${spacing}${palette}`;
export default Box;
Este componente Box agora suporta novas propriedades de espaçamento e propriedades de cor. Por exemplo, você pode fornecer uma propriedade de preenchimento: p
e uma propriedade de cor: color
.
<Box p="1rem" color="grey">Me dê algum espaço!</Box>
O componente pode ser estilizado, fornecendo quaisquer valores CSS válidos.
Temas
Mas na maioria das vezes, você deseja depender dos valores de um tema, para aumentar a consistência da interface do usuário. É preferível ter um conjunto predeterminado de valores de preenchimento e cor. Importe o provedor de temas de sua solução de estilo.
import React from 'react'
import { ThemeProvider } from 'styled-components'
const theme = {
spacing: 4,
palette: {
primary: '#007bff',
},
};
export default function App() {
return (
<ThemeProvider theme={theme}>
{/* componentes filhos */}
</ThemeProvider>
)
}
Agora, você pode fornecer um valor multiplicador de espaçamento:
<Box p={1}>4px</Box>
<Box p={2}>8px</Box>
<Box p={-1}>-4px</Box>
e uma cor primária:
<Box color="primary">azul</Box>
Tudo incluído
Para tornar o componente Box mais útil, estamos construindo uma coleção de funções de estilo, aqui está a lista completa:
Se você já estiver usando @material-ui/core
, poderá usar o componente Box (usando JSS internamente):
import Box from '@material-ui/core/Box';
Interoperabilidade
O pacote @material-ui/system
funciona com a maioria das bibliotecas CSS-in-JS, incluindo JSS, styled-components, e emotion.
Se você já estiver usando @material-ui/core
, nós recomendamos você a começar com a solução JSS, para diminuir o tamanho do pacote.
JSS
import React from 'react';
import { styled } from '@material-ui/core/styles';
import { compose, spacing, palette } from '@material-ui/system';
const Box = styled('div')(compose(spacing, palette));
export default function JSS() {
return (
<Box color="white" bgcolor="palevioletred" p={1}>
JSS
</Box>
);
}
import React from 'react';
import styled from 'styled-components';
import { palette, spacing } from '@material-ui/system';
import NoSsr from '@material-ui/core/NoSsr';
const Box = styled.div`
${palette}
${spacing}
`;
export default function StyledComponents() {
return (
<NoSsr>
<Box color="white" bgcolor="palevioletred" p={1}>
Styled components
</Box>
</NoSsr>
);
}
import React from 'react';
import styled from '@emotion/styled';
import { palette, spacing } from '@material-ui/system';
import NoSsr from '@material-ui/core/NoSsr';
const Box = styled.div`
${palette}
${spacing}
`;
export default function Emotion() {
return (
<NoSsr>
<Box color="white" bgcolor="palevioletred" p={1}>
Emotion
</Box>
</NoSsr>
);
}
Responsividade
Todas as propriedades são responsivas, oferecemos suporte para 3 diferentes APIs. Ela usa essa estrutura de tema com pontos de quebra padrão, mas é customizável:
const values = {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
};
const theme = {
breakpoints: {
keys: ['xs', 'sm', 'md', 'lg', 'xl'],
up: key => `@media (min-width:${values[key]}px)`,
},
};
Array
<Box p={[2, 3, 4]} />
/**
* Saídas:
*
* padding: 16px;
* @media (min-width: 600px) {
* padding: 24px;
* }
* @media (min-width: 960px) {
* padding: 32px;
* }
*/
Object
<Box p={{ xs: 2, sm: 3, md: 4 }} />
/**
* Saídas:
*
* padding: 16px;
* @media (min-width: 600px) {
* padding: 24px;
* }
* @media (min-width: 960px) {
* padding: 32px;
* }
*/
Colocação
Se você quiser agrupar valores de ponto de quebra, você pode usar o utilitário breakpoints()
.
import { compose, spacing, palette, breakpoints } from '@material-ui/system';
import styled from 'styled-components';
const Box = styled.div`
${breakpoints(
compose(
spacing,
palette,
),
)}
`;
<Box
p={2}
sm={{ p: 3 }}
md={{ p: 4 }}
/>
/**
* Saídas:
*
* padding: 16px;
* @media (min-width: 600px) {
* padding: 24px;
* }
* @media (min-width: 960px) {
* padding: 32px;
* }
*/
<Box xs={{ fontSize: 12 }} sm={{ fontSize: 18 }} md={{ fontSize: 24 }}>
Collocation API
</Box>
Propriedades de estilo customizadas
style(options) => style function
Use esta função utilitária para criar sua própria função de estilo.
Nem todas as propriedades CSS são suportadas. É possível que você queira suportar novas. Também é possível que você queira alterar o prefixo do caminho do tema.
Argumentos
options
(Object):options.prop
(String): A propriedade na qual a função de estilo será ativada.options.cssProperty
(String|Boolean [opcional]): Padrãooptions.prop
. A propriedade CSS usada. Você pode desativar esta opção fornecendofalse
. Quando desativado, o valor da propriedade será manipulado como um objeto de estilo próprio. Pode ser usado para variações de renderização.options.themeKey
(String [opcional]): O prefixo do caminho do tema.options.transform
(Function [opcional]): Aplique uma transformação antes de gerar um valor de CSS.
Retornos
style function
: A função de estilo criada.
Exemplos
Você pode criar um componente que suporte algumas propriedades CSS na grade, como um grid-gap
. Fornecendo spacing
como themeKey
, você pode reutilizar a lógica, permitindo o comportamento que vemos em outras propriedades de espaçamento, como padding
.
import styled from 'styled-components';
import { style } from '@material-ui/system';
import { Box } from '@material-ui/core';
const gridGap = style({
prop: 'gridGap',
themeKey: 'spacing',
});
const Grid = styled(Box)`${gridGap}`;
const example = <Grid display="grid" gridGap={[2, 3]}>...</Grid>;
Você também pode customizar o nome da propriedade adicionando ambos, prop
e cssProperty
e transformando o valor, adicionando uma função transform
.
import styled from 'styled-components';
import { style } from '@material-ui/system';
const borderColor = style({
prop: 'bc',
cssProperty: 'borderColor',
themeKey: 'palette',
transform: value => `${value} !important`,
});
const Colored = styled.div`${borderColor}`;
const example = <Colored bc="primary.main">...</Colored>;
compose(...style functions) => style function
Mesclar várias funções de estilo em uma.
Retornos
style function
: A função de estilo criada.
Exemplos
import { style, compose } from '@material-ui/system'
export const textColor = style({
prop: 'color',
themeKey: 'palette',
});
export const bgcolor = style({
prop: 'bgcolor',
cssProperty: 'backgroundColor',
themeKey: 'palette',
});
const palette = compose(textColor, bgcolor);
Variantes
A função utilitária style()
também pode ser usada para mapear propriedades para objetos de estilo no tema. Neste exemplo, a propriedade variant
suporta todas as chaves presentes em theme.typography
.
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import NoSsr from '@material-ui/core/NoSsr';
import { style, typography } from '@material-ui/system';
const variant = style({
prop: 'variant',
cssProperty: false,
themeKey: 'typography',
});
// ⚠ Text is already defined in the global context:
// https://developer.mozilla.org/en-US/docs/Web/API/Text/Text.
const Text = styled.span`
font-family: Helvetica;
${variant}
${typography}
`;
const theme = {
typography: {
h1: {
fontSize: 30,
lineHeight: 1.5,
},
h2: {
fontSize: 25,
lineHeight: 1.5,
},
},
};
export default function Variant() {
return (
<NoSsr>
<ThemeProvider theme={theme}>
<div>
<Text variant="h1" as="div">
variant=h1
</Text>
<Text variant="h1" fontWeight={300} as="div">
fontWeight=300
</Text>
<Text variant="h2" as="div">
variant=h2
</Text>
</div>
</ThemeProvider>
</NoSsr>
);
}
Propriedade CSS
Se você quiser suportar valores customizados de CSS, você pode usar o utilitário css()
. Ele irá processar a propriedade css
.
Como funciona
O styled-system fez um ótimo trabalho explicando como ele funciona. Ele pode ajudar a construir um modelo mental para esse conceito de "função de estilo".
Situações de uso no mundo real
Na prática, um componente do Box pode poupar muito tempo. Neste exemplo, demonstramos como reproduzir um componente Banner.
You have lost connection to the internet. This app is offline.
Técnica anterior
O pacote @material-ui/system
sintetiza ideias & APIs de várias fontes diferentes:
- Tachyons foi uma das primeiras bibliotecas CSS (2014) a promover o padrão de CSS atômico (ou CSS funcional).
- Tachyons foi mais tarde (2017) seguido por Tailwind CSS. Eles tornaram o CSS atômico mais popular.
- Twitter Bootstrap introduziu lentamente nomes de classes atômicas em v2, v3 e v4. A forma como agrupam suas "Classes utilitárias" foi usada como inspiração.
- No mundo React, Styled System foi um dos primeiros (2017) a promover as funções de estilo. Ele pode ser usado como um componente genérico do Box, substituindo os utilitários de CSS atômicos, bem como os utilitários para escrever novos componentes.
- Grandes empresas como Pinterest, GitHub e Segment.io estão usando a mesma abordagem em diferentes gostos:
- A implementação atual e a API responsiva de objetos foram inspiradas no sistema Smooth-UI.