Pular para o conteúdo

🎉 Material UI v5 is out now! Check out the announcement blog post

@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

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>
  );
}

Styled components

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>
  );
}

Emotion

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;
 * }
 */
Collocation API
<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

  1. options (Object):
    • options.prop (String): A propriedade na qual a função de estilo será ativada.
    • options.cssProperty (String|Boolean [opcional]): Padrão options.prop. A propriedade CSS usada. Você pode desativar esta opção fornecendo false. 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.

⚠️ Missing demo `pages/system/basics/CssProp.js` ⚠️

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.