User Components
Easily extend your content page more interactive
Components let you easily reuse a piece of UI or styling consistently. You can use them not just in .astro files, but also in .mdx files.
For .astro, you can directly import and use components and use. An example will also shown in the first section.
Containers#
Card#
import { Card } from 'astro-pure/user'
<Card
as='a'
href='#card'
heading='Lorem ipsum'
subheading='Lorem ipsum dolor sit amet, vidit suscipit at mei.'
date='August 2021'
>
You can even contain a list here
</Card>jsx---
import { Card } from 'astro-pure/user'
---
<!-- ... -->
<Card
as='a'
href='#card'
heading='Lorem ipsum'
subheading='Lorem ipsum dolor sit amet, vidit suscipit at mei.'
date='August 2021'
>
You can even contain a list here
</Card>astroCard is a flexible content container for simple metadata blocks, profile sections, and project summaries.
Key props:
as?: change the rendered HTML taghref?: make the card clickable when used with anchorsheading?: primary titlesubheading?: supporting text below the headingdate?: small metadata pill shown on the rightimagePath?: local image path under/src/assets/**altText?: image alt textimageClass?: custom classes for the imageimageMode?:'inline' | 'background'imageBlur?: apply blur when using background modeoverlayClass?: customize the background overlaycontentClass?,headingClass?,subheadingClass?,dateClass?,bodyClass?: fine-grained styling hooks
Default behavior:
- If
imageModeis omitted, the image is rendered inline near the heading. - If
imageMode='background', the image fills the card background and can optionally be blurred withimageBlur.
Background Image Card#
Experience Highlight
Background media mode with softer visual treatment
2026
- Use this mode when the image should shape the mood of the card.
- Keep overlays light enough to preserve the image, but strong enough for readable text.
- Use
overlayClassand typography class props to tune the visual balance per page.
import { Card } from 'astro-pure/user'
<Card
heading='Experience Highlight'
subheading='Background media mode with softer visual treatment'
date='2026'
imagePath='/src/assets/projects/1.avif'
imageMode='background'
imageBlur={true}
headingClass='text-2xl'
subheadingClass='text-lg'
>
<ul>
<li>Use this mode when the image should shape the mood of the card.</li>
<li>Keep overlays light enough to preserve the image, but strong enough for readable text.</li>
<li>Use `overlayClass` and typography class props to tune the visual balance per page.</li>
</ul>
</Card>jsx---
import { Card } from 'astro-pure/user'
---
<Card
heading='Experience Highlight'
subheading='Background media mode with softer visual treatment'
date='2026'
imagePath='/src/assets/projects/1.avif'
imageMode='background'
imageBlur={true}
headingClass='text-2xl'
subheadingClass='text-lg'
>
<ul>
<li>Use this mode when the image should shape the mood of the card.</li>
<li>Keep overlays light enough to preserve the image, but strong enough for readable text.</li>
<li>Use `overlayClass` and typography class props to tune the visual balance per page.</li>
</ul>
</Card>astroCollapse#
import { Collapse } from 'astro-pure/user'
<Collapse title='Lorem ipsum'> Lorem ipsum dolor sit amet, vidit suscipit at mei. </Collapse>
<Collapse title='Lorem ipsum'>
<div slot='before' class='mt-2'>Are you sure you want to see?</div>
<div>Lorem ipsum dolor sit amet, vidit suscipit at mei.</div>
</Collapse>jsxAside#
import { Aside } from 'astro-pure/user'
<Aside>No type selected will default to 'note'. 😉</Aside>
<Aside type="tip">
Other content is also supported in aside! 😍
// ```js
// A code snippet, for example.
// ```
</Aside>
<Aside type='caution' title='You should know it!'>Is your code buggy again? 🤨</Aside>
<Aside type='danger'>Have you used `rm -rf` to clean your computer? 😡</Aside>jsxThis component also has a remark support version (which can directly use in .md), but not integrated in this theme. You can check packages/starlight/integrations/asides.ts ↗ for reference code.
:::tip
This theme author is a good guy.
:::mdTabs#
import { Tabs, TabItem } from 'astro-pure/user';
<Tabs>
<TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem>
<TabItem label="Moons">Io, Europa, Ganymede</TabItem>
</Tabs>jsxMDX Repl#
Hello
<p>Hello</p>htmlimport { MdxRepl } from 'astro-pure/user'
// Width is optional; using width parameter to set
// all elements inside the MDX Repl component.
// (slot desc is not included this parameter)
<MdxRepl width='100%'>
<p>Hello</p>
<Fragment slot='desc'>
```html
<p>Hello</p>
```
</Fragment>
</MdxRepl>jsxYou can combine any other components for the sclot desc. And <Fragment> will not be rendered as a parent html container tag.
List#
CardList#
A list
- Lorem ipsum
-
Dolor sit amet
import { CardList } from 'astro-pure/user'
<CardList title='A list' list={
[{title: 'I am hidden!'}]
} collapse />
<CardList title='A list' list={
[
{ title: 'Lorem ipsum', link: '#list' },
{ title: 'Dolor sit amet', children: [{
title: 'Vidit suscipit', link: '#'
}] }
]
} />jsxTimeline#
- August 2021Hello
- August 2022World!
import { Timeline } from 'astro-pure/user'
<Timeline events={
[
{ date: 'August 2021', content: 'Hello' },
{ date: 'August 2022', content: '<i>World!</i>' },
]
} />jsxSteps#
How to Yi Jian San Lian:
-
Dian Zan
-
Tou Bi
-
Shou Cang
Or GuanZhu sometimes.
import { Steps } from 'astro-pure/user'
How to Yi Jian San Lian:
<Steps>
1. Dian Zan
2. Tou Bi
3. Shou Cang
Or GuanZhu sometimes.
</Steps>jsxSimple Text Render#
Button#
import { Button } from 'astro-pure/user'
<div class='flex gap-x-2'>
<Button as='div' title='Simple' />
<Button as='a' href='#button' title='Link style' variant='ahead' class='not-prose' />
<Button as='div' title='Back' variant='back' />
<Button as='div' title='Pill style' variant='pill' />
<Button as='div' variant='pill'><i>Italic</i></Button>
</div>jsxSpoiler#
No one can find me. But I am exposed here.
import { Spoiler } from 'astro-pure/user'
<Spoiler>No one can find me.</Spoiler> But I am exposed here.jsxFormatted Date#
import { FormattedDate } from 'astro-pure/user'
<FormattedDate date={new Date('2077-01-01')} dateTimeOptions={{ month: 'short' }} />jsxLabel#
Hello
import { Label } from 'astro-pure/user'
<Label title='Hello' />jsxSVG Loader#
import { Svg } from 'astro-pure/user'
<Svg src={import('@/assets/icons/key.svg?raw')} />jsxResources#
Icon#
Single use:
Preview all icons available (click button to copy):
import { Icon } from 'astro-pure/user'
Single use: <Icon name='rss' class='inline' />
Preview all icons available (click button to copy):
import { Icons as allIcons } from 'astro-pure/libs'
import { Button } from 'astro-pure/user'
<div class='flex flex-wrap gap-2'>
{
Object.keys(allIcons).map(icon => {
const script = `navigator.clipboard.writeText('${icon}');document.dispatchEvent(new CustomEvent('toast',{detail:{message:'Copied "${icon}" to clipboard!'}}))`
return (
<Button as='button' type='button' class='cursor-pointer' onclick={script}>
<Icon slot='before' name={icon} />
<span>{icon}</span>
</Button>
)
})
}
</div>jsxThere’s also some Advanced Components, which may suit for you. Hope you enjoy using these components!