Using with Astro
ZUI provides native Astro components that render at build time with zero client-side JavaScript.
Setup
Install ZUI and import the CSS in your layout:
---
// src/layouts/Layout.astro
import '@mrmartineau/zui/css'
---
<html lang="en">
<body>
<slot />
</body>
</html>
Then import components from @mrmartineau/zui/astro:
---
import { Button, Badge, Input } from '@mrmartineau/zui/astro'
---
You can also import individual components directly:
---
import Button from '@mrmartineau/zui/astro/Button.astro'
---
Available components
All components are exported from @mrmartineau/zui/astro:
- Button — with
variant,accent,size,shape, andiconprops - Badge — with
variantandcolor, andshapeprops - Card, CardHeader, CardTitle, CardDescription, CardBody —
shapeon Card - Input, Textarea, Select — with a
shapeprop - Label, Checkbox, Radio
- Text, Link, Code, Pre, Prose
Every component accepts a class prop and forwards all standard HTML attributes.
Component examples
Button
---
import { Button } from '@mrmartineau/zui/astro'
---
<Button variant="fill" accent="theme">Save</Button>
<Button variant="outline" accent="accent">Cancel</Button>
<Button variant="ghost" size="sm">Settings</Button>
<Button variant="subtle" accent="destructive">Delete</Button>
<Button href="/about">About (renders as anchor)</Button>
Button variants: fill, subtle, outline, ghost, link
Accents: theme, accent, destructive
Sizes: xs, sm, md (default), lg, xl
Shapes: default, hard, soft, squircle
Badge
---
import { Badge } from '@mrmartineau/zui/astro'
---
<Badge color="green">Active</Badge>
<Badge variant="fill" color="red">Error</Badge>
<Badge variant="outline" color="blue">Info</Badge>
Card
---
import { Card, CardHeader, CardTitle, CardDescription, CardBody } from '@mrmartineau/zui/astro'
---
<Card>
<CardHeader>
<CardTitle>John Doe</CardTitle>
<CardDescription>Software Engineer</CardDescription>
</CardHeader>
<CardBody>
<p>Card content goes here.</p>
</CardBody>
</Card>
Pass an href prop to make the card an interactive link:
<Card href="/users/1">
<CardBody>Clickable card</CardBody>
</Card>
Forms
---
import { Label, Input, Textarea, Select, Checkbox, Radio, Button } from '@mrmartineau/zui/astro'
---
<form>
<Label for="name">Name</Label>
<Input id="name" type="text" placeholder="Your name" />
<Label for="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
<Label for="message">Message</Label>
<Textarea id="message" rows={4} placeholder="Your message" />
<Label for="role">Role</Label>
<Select id="role">
<option value="dev">Developer</option>
<option value="design">Designer</option>
</Select>
<Checkbox id="terms" />
<Label for="terms">I agree to the terms</Label>
<Radio name="plan" value="free" id="free" />
<Label for="free">Free</Label>
<Radio name="plan" value="pro" id="pro" />
<Label for="pro">Pro</Label>
<Button type="submit">Submit</Button>
</form>
Typography
---
import { Text, Link, Code, Prose } from '@mrmartineau/zui/astro'
---
<Prose>
<Text size="lg">Large text</Text>
<Text size="sm">Small text</Text>
<p>
Visit the <Link href="/docs">documentation</Link> for more info.
</p>
<p>
Run <Code>npm install @mrmartineau/zui</Code> to get started.
</p>
</Prose>
Using in MDX
ZUI Astro components work in .mdx files:
---
layout: ../layouts/Layout.astro
title: My Page
---
import { Badge, Button } from '@mrmartineau/zui/astro'
# My Page
Status: <Badge color="green">Live</Badge>
<Button href="/contact">Get in touch</Button>
Using CSS classes directly
You can always use the underlying CSS classes without importing components — useful in plain .astro templates or HTML:
<button class="zui-button zui-button-variant-fill zui-button-color-theme">
Save
</button>
<span class="zui-badge zui-badge-color-green">
Active
</span>
Mixing with client-side frameworks
Astro's islands architecture lets you use ZUI's React components alongside the Astro components for interactive islands:
---
import { Card, CardBody } from '@mrmartineau/zui/astro'
import InteractiveForm from '../components/InteractiveForm.tsx'
---
<Card>
<CardBody>
<!-- Static Astro shell, interactive React island -->
<InteractiveForm client:visible />
</CardBody>
</Card>
Inside InteractiveForm.tsx, use the React components:
import { Input, Button } from '@mrmartineau/zui/react'
export default function InteractiveForm() {
return (
<form onSubmit={(e) => { e.preventDefault(); /* handle */ }}>
<Input type="email" placeholder="you@example.com" />
<Button type="submit">Subscribe</Button>
</form>
)
}
Shapes and squircles
Most components have a shape prop: default, hard, squircle, and on small components soft (a pill). Large boxes such as Card, Dialog, Popover, Menu, Accordion and Collapsible have no soft.
---
import { Card, Dialog, Input } from '@mrmartineau/zui/astro'
---
<Input shape="squircle" />
<Card shape="hard">…</Card>
<Dialog shape="squircle">…</Dialog>
To make squircle the default shape for every component, add zui-squircle-all to <html>. A hard or soft shape prop still wins. See Squircle for the full list of components and shapes.
Theming
ZUI themes are pure CSS. Override custom properties in your layout's stylesheet. See the Theming page for full details.
:root {
--color-theme: light-dark(var(--color-violet-600), var(--color-violet-400));
--radius-scale: 1.5;
}