Skip to content

Components and Layouts

FlowerCA77 edited this page Sep 21, 2025 · 1 revision

Components & Layouts

Chinese version: 组件与布局(中文).

This guide explains how UI is composed with Astro components, React islands, and layouts.

Concepts

  • Astro components (.astro): Server-first, zero-JS by default.
  • React components (.tsx): Client islands for interactivity (enabled via @astrojs/react).
  • Layouts: Page wrappers that provide shared chrome (header/footer/meta) and render page content via <slot />.

Minimal Layout Example

---
// src/layouts/BaseLayout.astro
const { title = 'Site' } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>{title}</title>
  </head>
  <body class="min-h-dvh bg-primary text-text-primary">
    <header class="border-b border-border py-4">My Site</header>
    <main class="mx-auto max-w-3xl p-4">
      <slot />
    </main>
    <footer class="border-t border-border py-4 text-sm"{new Date().getFullYear()}</footer>
  </body>
</html>

Use the layout in a page:

---
// src/pages/about.astro
import BaseLayout from "../layouts/BaseLayout.astro";
const title = 'About';
---
<BaseLayout {title}>
  <h1 class="text-2xl font-bold">About</h1>
  <p>This page uses the base layout.</p>
</BaseLayout>

React Islands Example

// src/components/Counter.tsx
import { useState } from 'react';
export default function Counter() {
  const [n, setN] = useState(0);
  return (
    <button className="px-3 py-1 border rounded" onClick={() => setN(n+1)}>
      Count: {n}
    </button>
  );
}
---
import Counter from "../components/Counter";
---
<Counter client:load />

Composition Diagram

flowchart LR
  A[Route Request] --> B[Astro Page in src/pages]
  B --> C[Load Content Collections]
  B --> D[Import Layout]
  D --> E[Render <slot/>]
  E --> F[Astro/React Components]
  F --> G[Static HTML + optional island JS]
Loading

Patterns

  • Shared chrome: Base layout with header/footer, SEO tags, global styles import.
  • Content pages: Article layout (title, meta, TOC, prev/next). Pass collection entry as props.
  • UI building blocks: Card, Badge, Button, Tag list; compose in list and detail pages.
  • Dark mode: Toggle dark class on the root; prefer keeping state in localStorage.

Tips & Pitfalls

  • Import Tailwind entry once globally (commonly from the top layout) to avoid duplication.
  • Keep React islands minimal; prefer Astro for static rendering.
  • Validate props early in components; handle optional fields like description or tags.
  • For long lists, consider pagination and astro:slot patterns.

Clone this wiki locally