Delightful Astro components

Astro components come in many shapes and sizes. This is one of my favourites.

The following <Example /> component has some interesting properties.

---
import { HTMLTag, Polymorphic } from "astro/types";
import { twMerge } from "tailwind-merge";
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }>;
const { as: Tag = "div", class: classes, ...props } = Astro.props;
---

<Tag class={twMerge("mx-auto max-w-2xl", classes)} {...props}>
  <slot />
</Tag>
  1. The outermost tag name can be customised
  2. The properties passed must conform to the corresponding tag
  3. Incoming Tailwind classes are merged intelligently with the list of omnipresent classes
  4. All remaining attributes are passed along

With a simple <Example /> we get the following HTML:

<div class="mx-auto max-w-2xl"></div>

And when we need to get a little more fancy passing in classes, a tag name, and some additional attributes:

<Example as="article" class="text-lg text-red-500" data-feeling="fabulous">
  <p>And just for good measure!</p>
</Example>

Astro will kindly generate us some appropriate HTML.

<article class="mx-auto max-w-2xl text-lg text-red-500" data-feeling="fabulous">
  <p>And just for good measure!</p>
</article>

The type annotations here aren’t particularly interesting, but once you have your own properties to pass around, they begin to shine.

interface Props extends HTMLAttributes<"a"> {
  title: string;
  description?: string;
}