Skip to content

Custom Components

Learn how to create custom components for your documentation.

Creating a Component

Basic Component

Create a new file in src/components/:

---
// CustomCard.astro
interface Props {
  title: string;
  description: string;
}

const { title, description } = Astro.props;
---

<div class="custom-card">
  <h3>{title}</h3>
  <p>{description}</p>
</div>

<style>
  .custom-card {
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 1.5rem;
  }
</style>

Using Components

In Markdown

Import and use components in markdown:

---
title: "My Page"
---

import CustomCard from '../../components/CustomCard.astro';

# My Page

<CustomCard 
  title="Amazing Feature"
  description="This is an amazing feature!"
/>

Props and TypeScript

Typed Props

Define TypeScript interfaces for props:

---
interface Props {
  title: string;
  description?: string;
  variant?: 'primary' | 'secondary';
  isActive?: boolean;
}

const { 
  title, 
  description = 'Default description',
  variant = 'primary',
  isActive = false 
} = Astro.props;
---

Slots

Default Slot

---
// Container.astro
---

<div class="container">
  <slot />
</div>

Named Slots

---
// Card.astro
---

<div class="card">
  <div class="card-header">
    <slot name="header" />
  </div>
  <div class="card-body">
    <slot />
  </div>
  <div class="card-footer">
    <slot name="footer" />
  </div>
</div>

Usage:

<Card>
  <div slot="header">Header Content</div>
  Body content
  <div slot="footer">Footer Content</div>
</Card>

Styling

Scoped Styles

<style>
  .component {
    color: var(--color-text);
  }
</style>

Global Styles

<style is:global>
  .global-class {
    margin: 0;
  }
</style>

Tailwind Classes

<div class="bg-white dark:bg-gray-900 rounded-lg p-4">
  Content
</div>

Client-Side Interactivity

Script Tags

<button id="my-button">Click Me</button>

<script>
  document.getElementById('my-button')
    ?.addEventListener('click', () => {
      alert('Clicked!');
    });
</script>

Framework Components

Use React, Vue, or Svelte:

---
import Counter from './Counter.tsx';
---

<Counter client:load />

Best Practices

Component Organization

src/components/
├── ui/
│   ├── Button.astro
│   └── Card.astro
├── layout/
│   ├── Header.astro
│   └── Footer.astro
└── docs/
    └── CodeBlock.astro

Naming Conventions

  • Use PascalCase: CustomCard.astro
  • Be descriptive: FeatureCard.astro vs Card.astro
  • Group related components

Documentation

Document your components:

---
/**
 * A custom card component
 * @param {string} title - The card title
 * @param {string} description - The card description
 */
interface Props {
  title: string;
  description: string;
}
---