Componentes Utilitários para Composição de Layouts

alanpinhel

Alan Pinhel

Posted on February 17, 2024

Componentes Utilitários para Composição de Layouts

É comum em bibliotecas de componentes conhecidas, a disponibilização de componentes utilitários que facilitam na composição de componentes maiores e consequentemente aumentam a produtividade na construção de interfaces. Por exemplo:

No entanto, também é comum ver projetos com a utilização de CSS-in-JS, desta forma:

import * as S from "./styles";

() => (
  <S.Layout>
    <S.HeaderContent>
      <S.Content>
        <S.Image />
      </S.Content>

      <S.HeaderTitleContent>
        <S.PageTitle>...</S.PageTitle>
        <S.PageDescription>...</S.PageDescription>
        <S.MoreDetailsLink>...</S.MoreDetailsLink>
      </S.HeaderTitleContent>
    </S.HeaderContent>

    <S.ClassSelection>...</S.ClassSelection>

    <S.ClassesList>
      <S.ButtonBox>
        <S.Button>...</S.Button>
      </S.ButtonBox>
    </S.ClassesList>

    <Divider full position="horizontal" />

    <div>
      <S.DynamicInformation>...</S.DynamicInformation>

      <Divider full position="horizontal" />

      <div>
        <S.DynamicContent>
          <S.Data>
            <S.Day>...</S.Day>
            <S.Month>...</S.Month>
            <S.Year>...</S.Year>
          </S.Data>
          <S.Content>
            <S.ContentLastChild>
              <S.ContentTitle>...</S.ContentTitle>
              <S.ContentDescription>...</S.ContentDescription>
            </S.ContentLastChild>
          </S.Content>
        </S.DynamicContent>

        <Divider full position="horizontal" />
      </div>
    </div>

    <S.Help>...</S.Help>
  </S.Layout>
);
Enter fullscreen mode Exit fullscreen mode

Cada componente do grupo S tem um arquivo que exporta um Styled Component. Veja abaixo:

import { styled } from "@/stitches";

const Layout = styled("div", {
  padding: "$spacing2xl",
  maxWidth: "51.125rem", // 818px
  minWidth: "21.563rem", // 345px
});

export default Layout;
Enter fullscreen mode Exit fullscreen mode
import { styled } from "@/stitches";

const HeaderContent = styled("div", {
  display: "flex",
  gap: "$spacingLg",
  marginBottom: "$spacingXl",
  flexDirection: "column",

  "@md": {
    flexDirection: "row",
  },
});

export default HeaderContent;
Enter fullscreen mode Exit fullscreen mode
import { styled } from "@/stitches";

const Content = styled("div", {
  width: "17.813rem", // 285px
});

export default Content;
Enter fullscreen mode Exit fullscreen mode

Enfim... (cansei, não vai rolar listar todos 😅). É possível notar que:

  • Há um gasto de esforço desnecessário (dar nome, criar um arquivo, exportar/importar, tudo isso para as vezes definir APENAS um atributo CSS. Isso não me parece prático).
  • Existe muito código repetido, é comum ver vários arquivos definindo tipografia, flex box, grid e espaçamento.
  • Dar nome para coisas abstratas é difícil e o resultado é algo como: XxxxContent, XxxxData, XxxxBox, XxxxWrapper e XxxxInfo.
  • Deduzir o que o código renderiza é bem trabalhoso, os estilos estão longes entre-si, longe do markup e com nomes não óbvios.

Veja um exemplo, de como ficaria a reescrita do código acima, utilizando componentes utilitários para isso:

import { Box, Flex, Text } from "@foo/components";

() => (
  <Box padding="2xl" css={{ maWidth: "51.125rem", minWidth: "21.563rem" }}>
    <Flex gap="lg" direction={{ "@initial": "column", "@md": "row" }}>
      <Box css={{ width: "17.813rem" }}>
        <Box as="img" css={{ width: "100%" }} />
      </Box>

      <Flex direction="column" justify="space-between">
        <Text as="h1" font="headingLgBold">
          ...
        </Text>
        <Text as="p" font="labelRegular">
          ...
        </Text>
        <Text as="p" font="captionRegular">
          ...
        </Text>
      </Flex>
    </Flex>

    <Text as="h3" font="labelBold" gutterBottom>
      ...
    </Text>

    <Flex wrap="wrap" gap="md">
      <Box css={{ width: "3.125rem" }}>
        <Button>...</Button>
      </Box>
    </Flex>

    <Divider full position="horizontal" />

    <Box css={{ marginBottom: "$spacingLg" }}>
      <Text as="p" font="titleRegular" gutterBottom>
        ...
      </Text>

      <Divider full position="horizontal" />

      <div>
        <Flex gap="lg" align="start" css={{ padding: "$spacingMd 0" }}>
          <Flex direction="column" align="center">
            <Text font="headingLgBold">...</Text>
            <Text font="headingSmRegular" transform="capitalize">
              ...
            </Text>
            <Text font="bodyRegular">...</Text>
          </Flex>

          <Flex direction="column">
            <Text as="p" font="labelBold" gutterBottom>
              ...
            </Text>
            <Text font="captionRegular">...</Text>
          </Flex>
        </Flex>

        <Divider full position="horizontal" />
      </div>
    </Box>

    <Text font="labelRegular">...</Text>
  </Box>
);
Enter fullscreen mode Exit fullscreen mode

Consegue perceber como reaproveitamos mais código? Além disso, fica mais rápido compor o layout e facilita em manutenções futuras, pois é mais fácil de deduzir.

Gostou? Não concorda? Deixe suas experiências e dicas nos comentários.

💖 💪 🙅 🚩
alanpinhel
Alan Pinhel

Posted on February 17, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related