Repo

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:

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;
}

Theme

Copy this CSS to your project: