Astro Integration
@andersseen/astro removes the boilerplate of manually importing and defining
every custom element, and automatically registers the icons they use. This docs
site is itself built with it — see it in
apps/docs/astro.config.mjs.
Install
Section titled “Install”pnpm add @andersseen/astro @andersseen/web-components @andersseen/iconimport { defineConfig } from 'astro/config';import andersseen from '@andersseen/astro';
export default defineConfig({ integrations: [andersseen()],});This is equivalent to adding the following client script to every page:
import { defineAllCustomElements } from '@andersseen/web-components';defineAllCustomElements();
import { registerAllIcons } from '@andersseen/icon';registerAllIcons();Options
Section titled “Options”Tree-shake components
Section titled “Tree-shake components”Register only the components you actually use:
andersseen({ components: ['and-button', 'and-navbar', 'and-badge'],});Skip automatic icon registration
Section titled “Skip automatic icon registration”andersseen({ icons: false,});Using components in .astro files
Section titled “Using components in .astro files”Once the integration is installed, use the custom elements directly:
---import type { NavbarProps } from '@andersseen/web-components';
const navItems: NavbarProps['items'] = [ { label: 'Home', href: '/' }, { label: 'Docs', href: '/docs' },];---
<and-navbar items={navItems}> <and-button variant="outline" slot="actions">Login</and-button></and-navbar>Complex props such as items are still serialized to the DOM as attributes. The
integration doesn’t remove that requirement, but it does expose TypeScript types
so you get autocompletion and avoid manual JSON.stringify.
A more complete example
Section titled “A more complete example”A small profile form — Input, Select, and Button driving an imperative Toast call — laid out with Layout attributes instead of custom CSS:
---import type { SelectOption } from '@andersseen/web-components';
const roles: SelectOption[] = [ { value: 'admin', text: 'Admin' }, { value: 'editor', text: 'Editor' }, { value: 'viewer', text: 'Viewer' },];---
<div and-layout="vertical gap:sm" style="max-width: 22rem;"> <and-input id="profile-name" label="Display name" name="name"></and-input> <and-select id="profile-role" label="Role" options={roles}></and-select> <and-button id="profile-save">Save changes</and-button></div><and-toast id="profile-toast" position="bottom-right"></and-toast>
<script> // Astro's client scripts run after custom elements upgrade, so plain DOM // lookups, `.value` reads, and `.present()` (a @Method()) all work directly // — no framework runtime needed for this kind of interaction. const name = document.getElementById('profile-name') as HTMLAndInputElement; const role = document.getElementById('profile-role') as HTMLAndSelectElement; const toast = document.getElementById('profile-toast') as HTMLAndToastElement;
document.getElementById('profile-save')?.addEventListener('click', () => { toast.present(`Saved ${name.value || 'Unnamed'} as ${role.value || 'no role'}`, 'success', 3000); });</script>options={roles} here follows the same rule as items={navItems} above: Astro
serializes the array to the options attribute as JSON, and
Select’s options prop accepts a JSON string directly —
so no customElements.whenDefined() dance is needed, unlike
Dropdown’s items, which is property-only.