Pular para o conteúdo

3. Style Guide

Este documento estabelece convenções de código, nomenclatura e formatação para garantir consistência e qualidade em projetos desenvolvidos com Astro 5, Tailwind CSS e JavaScript vanilla.

Convenções de Código

Princípios Gerais

  1. Legibilidade: O código deve ser fácil de ler e entender
  2. Consistência: Siga os mesmos padrões em todo o projeto
  3. Simplicidade: Prefira soluções simples e diretas
  4. Manutenibilidade: Escreva código pensando em quem vai mantê-lo

Astro

---
// Imports organizados por tipo e em ordem alfabética
import BaseLayout from '../layouts/BaseLayout.astro';
import Button from '../components/ui/Button.astro';
import Card from '../components/ui/Card.astro';
import { formatDate } from '../utils/date';
import { getCollection } from 'astro:content';
// Constantes e variáveis com nomes descritivos
const pageTitle = 'Blog';
const posts = await getCollection('blog');
const recentPosts = posts
.sort((a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime())
.slice(0, 5);
// Props com valores padrão quando apropriado
const { showRecent = true } = Astro.props;
---
<!-- Template com indentação consistente -->
<BaseLayout title={pageTitle}>
<main class="container mx-auto py-8">
<h1 class="text-3xl font-bold mb-6">{pageTitle}</h1>
{showRecent && (
<section class="mb-12">
<h2 class="text-2xl font-semibold mb-4">Posts Recentes</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{recentPosts.map((post) => (
<Card>
<h3 class="text-xl font-medium">{post.data.title}</h3>
<p class="text-gray-600 text-sm">
{formatDate(post.data.publishDate)}
</p>
<p class="mt-2">{post.data.excerpt}</p>
<div class="mt-4">
<Button href={`/blog/${post.slug}`}>Ler mais</Button>
</div>
</Card>
))}
</div>
</section>
)}
<!-- Comentários para seções complexas -->
<!-- Lista completa de posts organizada por ano -->
<section>
<!-- Conteúdo adicional... -->
</section>
</main>
</BaseLayout>

Diretrizes para Componentes Astro

  1. Frontmatter

    • Organize imports por tipo e em ordem alfabética
    • Coloque lógica complexa em funções nomeadas
    • Use comentários para explicar lógica não óbvia
  2. Template

    • Use indentação de 2 espaços
    • Quebre linhas para melhorar legibilidade
    • Use parênteses para expressões condicionais complexas
    • Prefira expressões ternárias para condicionais simples
  3. Slots

    • Use slots nomeados para conteúdo variável
    • Forneça conteúdo padrão para slots quando apropriado
---
// Exemplo de uso de slots
---
<div class="card">
<div class="card-header">
<slot name="header">
<!-- Conteúdo padrão se nenhum slot for fornecido -->
<h2>Título Padrão</h2>
</slot>
</div>
<div class="card-body">
<slot />
</div>
<div class="card-footer">
<slot name="footer" />
</div>
</div>

JavaScript

// Constantes em SNAKE_CASE_MAIÚSCULO para valores fixos
const MAX_ITEMS = 100;
const DEFAULT_THEME = 'light';
// Funções nomeadas com camelCase
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Classes com PascalCase
class ShoppingCart {
// Propriedades privadas com #
#items = [];
constructor(initialItems = []) {
this.#items = [...initialItems];
}
addItem(item) {
if (!item.id) {
throw new Error('Item must have an id');
}
this.#items.push(item);
}
get total() {
return calculateTotal(this.#items);
}
}
// Exportações no final do arquivo
export { ShoppingCart, calculateTotal };

Diretrizes para JavaScript

  1. Nomenclatura

    • camelCase para variáveis, funções e métodos
    • PascalCase para classes e componentes
    • SNAKE_CASE_MAIÚSCULO para constantes
    • Nomes descritivos que indicam propósito
  2. Funções

    • Funções pequenas com propósito único
    • Máximo de 3 parâmetros (use objetos para mais)
    • Documente parâmetros e retorno para funções complexas
  3. Módulos

    • Um módulo por arquivo
    • Exportações nomeadas em vez de default quando possível
    • Agrupe exportações relacionadas
  4. Comentários

    • Comente o “porquê”, não o “como”
    • Use JSDoc para documentar funções públicas
    • Evite comentários óbvios
/**
* Calcula o preço total com desconto baseado na quantidade
* @param {number} price - Preço unitário do produto
* @param {number} quantity - Quantidade de itens
* @param {number} [discountRate=0] - Taxa de desconto (0-1)
* @returns {number} Preço total com desconto aplicado
*/
function calculateDiscountedPrice(price, quantity, discountRate = 0) {
// Validação de entrada
if (price < 0 || quantity < 1 || discountRate < 0 || discountRate > 1) {
throw new Error('Invalid input parameters');
}
const subtotal = price * quantity;
// Aplica desconto progressivo para quantidades maiores
// para incentivar compras em volume
let effectiveDiscount = discountRate;
if (quantity > 10) {
effectiveDiscount += 0.05;
}
return subtotal * (1 - effectiveDiscount);
}

Tailwind CSS

<!-- Organização de classes Tailwind -->
<button
class="
/* Layout */
inline-flex items-center justify-center
/* Dimensões */
px-4 py-2 w-full sm:w-auto
/* Aparência */
bg-blue-600 hover:bg-blue-700 text-white
rounded-md shadow-sm
/* Tipografia */
font-medium text-sm
/* Transições */
transition-colors duration-200
/* Estado */
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
disabled:opacity-50 disabled:cursor-not-allowed
"
>
<svg class="w-4 h-4 mr-2" viewBox="0 0 24 24"><!-- ... --></svg>
<span>Botão de Ação</span>
</button>

Diretrizes para Tailwind CSS

  1. Organização de Classes

    • Agrupe classes por categoria (layout, dimensões, aparência, etc.)
    • Use comentários para separar grupos em elementos complexos
    • Mantenha ordem consistente entre elementos similares
  2. Responsividade

    • Comece com mobile-first (sem prefixo)
    • Adicione variantes de breakpoint em ordem crescente (sm, md, lg, xl)
    • Agrupe classes responsivas relacionadas
<!-- Exemplo de classes responsivas organizadas -->
<div class="
/* Base (mobile) */
grid grid-cols-1 gap-4 p-4
/* Tablet */
sm:grid-cols-2 sm:gap-6 sm:p-6
/* Desktop */
lg:grid-cols-3 lg:gap-8 lg:p-8
">
<!-- Conteúdo -->
</div>
  1. Componentes Personalizados
    • Use @apply em arquivos CSS para componentes reutilizáveis
    • Mantenha consistência com o design system
    • Documente componentes personalizados
src/assets/styles/components.css
@layer components {
.btn {
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-colors;
}
.btn-primary {
@apply bg-blue-600 text-white hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2;
}
.btn-secondary {
@apply bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-2 focus:ring-gray-500 focus:ring-offset-2;
}
}

Convenções de Nomenclatura

Arquivos e Pastas

TipoConvençãoExemplo
Componentes AstroPascalCase.astroButton.astro, ProductCard.astro
LayoutsPascalCase.astroBaseLayout.astro, BlogLayout.astro
Páginaskebab-case.astroabout-us.astro, privacy-policy.astro
Rotas dinâmicas[param].astro ou […param].astro[slug].astro, [...path].astro
JavaScript/TypeScriptcamelCase.js/tsformatDate.js, apiClient.ts
Estiloskebab-case.cssvariables.css, typography.css
Pastaskebab-caseblog-posts/, product-images/

Componentes

  • Componentes UI: Nomes que descrevem o elemento visual (Button, Card, Modal)
  • Componentes de Layout: Prefixo que indica função (PageHeader, SectionContainer)
  • Componentes de Feature: Nome que descreve a funcionalidade (ProductGallery, CheckoutForm)
  • Componentes HOC: Sufixo Provider ou Container (ThemeProvider, CartContainer)

CSS

  • Classes Utilitárias: Nomes descritivos e específicos (text-center, flex-grow)
  • Componentes: Nomes de substantivos (card, button, modal)
  • Modificadores: Prefixo com hífen (card--featured, button--large)
  • Estados: Prefixo com is- ou has- (is-active, has-error)

Regras de Formatação

Indentação e Espaçamento

  • Use 2 espaços para indentação (não tabs)
  • Limite linhas a 80-100 caracteres
  • Use linhas em branco para separar blocos lógicos
  • Não use múltiplas linhas em branco consecutivas
  • Use espaço após palavras-chave (if, for, function)
  • Use espaço ao redor de operadores (=, +, *)

Pontuação e Sintaxe

  • Use ponto e vírgula (;) no final das declarações JavaScript
  • Use aspas simples (') para strings em JavaScript
  • Use aspas duplas (") para atributos HTML
  • Adicione vírgula no último item de arrays e objetos multilinhas
  • Use parênteses em expressões complexas para clareza
// Exemplo de formatação
const config = {
theme: 'light',
features: [
'darkMode',
'responsiveDesign',
'accessibility',
],
limits: {
maxItems: 100,
maxUsers: 50,
},
};
function processData(data, options = {}) {
const {
filter = 'all',
sort = 'name',
limit = 10,
} = options;
// Lógica de processamento...
return result;
}

Ordenação

  • Imports: Agrupados por tipo (built-in, externos, internos) e em ordem alfabética
  • Props: Ordem alfabética ou agrupados por função
  • Classes CSS: Agrupadas por categoria (layout, dimensões, aparência, etc.)
  • Métodos de Classe: Construtor, getters/setters, métodos públicos, métodos privados

Boas Práticas para CSS/Tailwind

Princípios

  1. Consistência: Use classes consistentes para elementos similares
  2. Reutilização: Extraia padrões comuns para componentes
  3. Responsividade: Design mobile-first com breakpoints apropriados
  4. Acessibilidade: Garanta contraste adequado e interações acessíveis

Organização de Classes Tailwind

Recomendamos organizar classes Tailwind na seguinte ordem:

  1. Layout (display, position, z-index)
  2. Box Model (width, height, margin, padding)
  3. Flexbox/Grid (flex, grid, gap)
  4. Tipografia (font, text)
  5. Aparência (background, border, shadow)
  6. Transições e Animações
  7. Interações (hover, focus, active)
  8. Responsividade (sm, md, lg, xl)
<!-- Exemplo de organização de classes -->
<div class="
/* Layout */
relative flex overflow-hidden
/* Box Model */
w-full max-w-md p-4 m-auto
/* Aparência */
bg-white rounded-lg shadow-md
/* Responsividade */
sm:p-6 md:p-8
">
<!-- Conteúdo -->
</div>

Customização do Tailwind

Personalize o Tailwind no arquivo tailwind.config.js para alinhar com o design system:

tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
colors: {
primary: {
50: '#f0f9ff',
// ... outras tonalidades
600: '#0284c7',
// ... outras tonalidades
},
// ... outras cores
},
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
display: ['Lexend', ...defaultTheme.fontFamily.sans],
},
spacing: {
// Extensões de espaçamento personalizado
},
borderRadius: {
// Raios de borda personalizados
},
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
};

Componentes Personalizados

Para padrões frequentemente usados, crie componentes CSS personalizados:

src/assets/styles/components.css
@layer components {
/* Componentes de layout */
.container-narrow {
@apply max-w-3xl mx-auto px-4 sm:px-6 lg:px-8;
}
.container-wide {
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
}
/* Componentes de UI */
.card {
@apply bg-white rounded-lg shadow-md overflow-hidden;
}
.card-header {
@apply px-4 py-3 border-b border-gray-200 bg-gray-50;
}
.card-body {
@apply p-4;
}
/* Tipografia */
.heading-1 {
@apply text-3xl font-bold text-gray-900 sm:text-4xl;
}
.heading-2 {
@apply text-2xl font-bold text-gray-900 sm:text-3xl;
}
.body-text {
@apply text-base text-gray-700 leading-relaxed;
}
}

Ferramentas de Formatação e Linting

Recomendamos as seguintes ferramentas para manter a consistência do código:

ESLint

Configuração básica para ESLint:

.eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:astro/recommended',
],
overrides: [
{
files: ['*.astro'],
parser: 'astro-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.astro'],
},
rules: {
// Regras específicas para arquivos Astro
},
},
{
files: ['*.js'],
rules: {
// Regras específicas para JavaScript
},
},
],
rules: {
// Regras globais
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
};

Prettier

Configuração recomendada para Prettier:

.prettierrc
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "avoid",
"plugins": ["prettier-plugin-astro"],
"overrides": [
{
"files": "*.astro",
"options": {
"parser": "astro"
}
}
]
}

Conclusão

Seguir estas convenções de código, nomenclatura e formatação garantirá consistência e qualidade em todo o projeto. Estas diretrizes devem ser consideradas como um guia vivo que pode evoluir com as necessidades do projeto e as melhores práticas da indústria.

Os próximos documentos detalharão outros aspectos do desenvolvimento:


Última atualização: 21 de março de 2025