I’m building a component library in Astro, and one of the things I needed to do was to build a component that could render as either a button or an anchor tag. Here’s an example of the outcome I wanted to achieve:
// renders an <a> tag
<Button href="https://some-link">This is an anchor tag</Button>
// renders a <button> tag
<Button type="button">Submit</Button>
With Astro you’re writing the best parts of JSX there could be; for example, there are no abstraction leaks like having to add `key`s to iterables. But also what you’re writing is very obviously much closer to HTML than JSX is, there not being a virtual DOM, or styled components, so this puzzled me for a while. I could either have 2 components and duplicate my styles, or find a way to render either depending on the use case.
Thankfully with some clever prop handling, we can have the best of both worlds:
// button.astro
const { href } = Astro.props
---
<>
{
href ? (
<a href={href}><slot /></a>
) : (
<button
type="button"
>
<slot />
</button>
)
}
</>
With this code, the default output is a