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
- Legibilidade: O código deve ser fácil de ler e entender
- Consistência: Siga os mesmos padrões em todo o projeto
- Simplicidade: Prefira soluções simples e diretas
- Manutenibilidade: Escreva código pensando em quem vai mantê-lo
Astro
---// Imports organizados por tipo e em ordem alfabéticaimport 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 descritivosconst 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 apropriadoconst { 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
-
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
-
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
-
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 fixosconst MAX_ITEMS = 100;const DEFAULT_THEME = 'light';
// Funções nomeadas com camelCasefunction calculateTotal(items) { return items.reduce((sum, item) => sum + item.price, 0);}
// Classes com PascalCaseclass 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 arquivoexport { ShoppingCart, calculateTotal };Diretrizes para JavaScript
-
Nomenclatura
camelCasepara variáveis, funções e métodosPascalCasepara classes e componentesSNAKE_CASE_MAIÚSCULOpara constantes- Nomes descritivos que indicam propósito
-
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
-
Módulos
- Um módulo por arquivo
- Exportações nomeadas em vez de default quando possível
- Agrupe exportações relacionadas
-
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
-
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
-
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>- Componentes Personalizados
- Use
@applyem arquivos CSS para componentes reutilizáveis - Mantenha consistência com o design system
- Documente componentes personalizados
- Use
@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
| Tipo | Convenção | Exemplo |
|---|---|---|
| Componentes Astro | PascalCase.astro | Button.astro, ProductCard.astro |
| Layouts | PascalCase.astro | BaseLayout.astro, BlogLayout.astro |
| Páginas | kebab-case.astro | about-us.astro, privacy-policy.astro |
| Rotas dinâmicas | [param].astro ou […param].astro | [slug].astro, [...path].astro |
| JavaScript/TypeScript | camelCase.js/ts | formatDate.js, apiClient.ts |
| Estilos | kebab-case.css | variables.css, typography.css |
| Pastas | kebab-case | blog-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
ProviderouContainer(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-ouhas-(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çãoconst 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
- Consistência: Use classes consistentes para elementos similares
- Reutilização: Extraia padrões comuns para componentes
- Responsividade: Design mobile-first com breakpoints apropriados
- Acessibilidade: Garanta contraste adequado e interações acessíveis
Organização de Classes Tailwind
Recomendamos organizar classes Tailwind na seguinte ordem:
- Layout (display, position, z-index)
- Box Model (width, height, margin, padding)
- Flexbox/Grid (flex, grid, gap)
- Tipografia (font, text)
- Aparência (background, border, shadow)
- Transições e Animações
- Interações (hover, focus, active)
- 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:
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:
@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:
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:
{ "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:
- Design System: Sistema visual e componentes base
- Componentes: Biblioteca de componentes reutilizáveis
- Integração com Astro: Recursos específicos do Astro
Última atualização: 21 de março de 2025