Links Importantes:
Quando fiz o desafio, não fiz bom uso do Styled-Components e o CSS não ficou bom. Mostro meu progresso no estudo do assunto nesse texto.
Design Tokens
Agora, o projeto tem uma pasta separada só para tokens de design. Por exemplo, esse é o arquivo colors.json
:
{
"items": {
"neutral0": "#fefefe",
"neutral50": "#f8fafc",
"neutral100": "#f1f5f9",
...
"neutral950": "#020617",
"primary50": "#eff6ff",
"primary100": "#dbeafe",
...
"primary950": "#172554"
}
}
Com a ajuda de alguns helpers, essas tokens de design formam o tema do projeto. Isso acontece no arquivo defaultTheme.ts
:
//parte do código omitida por brevidade
import {DefaultTheme} from 'styled-components';
import {colors, textSizes, spacing, fonts, viewports, others} from '@/styles/tokens/';
const textSizeTokens = tokensToStyledComponents(clampGenerator(textSizes.items));
const spacingTokens = tokensToStyledComponents(clampGenerator(spacing.items));
const fontTokens = tokensToStyledComponents(fonts.items);
export const sharedThemeValues = {
textSize: textSizeTokens,
spacing: spacingTokens,
font: fontTokens,
primitiveColors: colors.items,
gutter: spacingTokens['s-m'],
containerMaxWidth: `${viewports.max}px`,
...others.items
};
export const themeColors = {
...
};
export const lightTheme: DefaultTheme = {
colors: {...themeColors},
...sharedThemeValues
};
Componentes de Layout
Transformei as classes do web.dev em componentes React para compor o projeto. Por extrairem o máximo do Flexbox/Grid, não são necessárias media queries.
Um exemplo de componente de layout:
/*
AutoGrid
A flexible layout that will create an auto-fit grid with configurable grid item sizes.
CUSTOM PROPERTIES AND CONFIGURATION
--auto-grid-gap (theme.gutter): This defines the space between each item
--auto-grid-item-min-size (16rem): How large each item should be, as a minimum
---auto-grid-placement (auto-fit): Set either auto-fit or auto-fill to change how empty grid tracks are handled
*/
import styled, {DefaultTheme, useTheme} from 'styled-components';
function setProperties({placement, itemMinSize, gap}: StyleProps, theme: DefaultTheme) {
return {
'--auto-grid-placement': placement || 'auto-fit',
'--auto-grid-item-min-size': itemMinSize || '16rem',
'--auto-grid-gap': gap ? theme.spacing[gap] : theme.gutter
};
}
const AutoGrid = ({children, placement, itemMinSize, gap, ...props}: TAutoGrid) => {
const theme = useTheme();
const styles = setProperties({placement, itemMinSize, gap}, theme);
return (
<Wrapper style={styles} {...props}>
{children}
</Wrapper>
);
};
const Wrapper = styled.div`
display: grid;
grid-template-columns: repeat(
var(--auto-grid-placement),
minmax(min(var(--auto-grid-item-min-size), 100%), 1fr)
);
gap: var(--auto-grid-gap);
`;
export default AutoGrid;
Uso o AutoGrid
para fazer a galeria de vídeos. Antes, a galeria era feita assim:
& {
display: grid;
grid-template-columns: repeat(3, 360px);
gap: 2rem;
align-items: stretch;
}
@media (max-width: 1180px) {
& {
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}
}
@media (max-width: 1080px) {
& {
grid-template-columns: repeat(2, 360px);
gap: 2rem;
justify-content: center;
}
}
@media (max-width: 780px) {
& {
grid-template-columns: repeat(2, 1fr);
}
@media (max-width: 680px) {
grid-template-columns: repeat(1, 360px);
}
${({ theme }) => css`
@media (max-width: ${theme.breakpoints.phone}) {
grid-template-columns: repeat(1, 1fr);
}
}
/*total: 34 linhas*/
E depois, com o AutoGrid
:
& {
display: grid;
grid-template-columns: repeat(
var(--auto-grid-placement),
minmax(min(var(--auto-grid-item-min-size), 100%), 1fr)
);
gap: var(--auto-grid-gap);
}
/*total: 8 linhas*/
Esse exemplo mostra o salto de qualidade geral que meu projeto teve. O grid caiu de 34 linhas para 8!
Tipografia e espaços flúidos
Na primeira vez, errei ao seguir o design pixel a pixel, resultando em tamanhos de fonte e espaçamentos muito variados.
Agora, criei um número menor de tokens para ambos e uso clamp
para torná-los flúidos sem media queries: