62 components · precompiled CSS · React 19
A React component library on semantic tokens — one brand color restyles everything at runtime. Try it: this whole section is listening.
Recolored by the swatches — no rebuild
Every cell below is live — the same components and tokens you'd ship.
Semantic tokens flip with one class on the root. Flip it now:
One accent channel recolors any component — no per-hue CSS.
Precompiled CSS. No plugins, no config — your bundler just serves a stylesheet.
pnpm add astralis-uiBreakpoint maps on every style prop — resize the window.
Named roles resolve per theme; components never see a hex.
Nothing below is a screenshot — hover to pause, then go meet them in the docs.
pnpm add astralis-uiEach snippet is the literal source of the preview beside it — the same guarantee every docs page makes.
One invalid flag restyles the field and swaps the message.
"use client";
import { useState } from "react";
import { Field, Input, Switch, VStack } from "astralis-ui";
export function FieldError() {
const [invalid, setInvalid] = useState(true);
return (
<VStack gap="5" alignItems="stretch" w="full" maxW="xs">
<Switch checked={invalid} onChange={(e) => setInvalid(e.target.checked)} size="sm">
Simulate a validation error
</Switch>
{/* One `invalid` flag restyles the input and swaps the message. */}
<Field invalid={invalid} required>
<Field.Label>Username</Field.Label>
<Input placeholder="astro_naut" />
{invalid ? (
<Field.ErrorText>That username is already taken.</Field.ErrorText>
) : (
<Field.HelpText>Letters, numbers and underscores only.</Field.HelpText>
)}
</Field>
</VStack>
);
}That username is already taken.
"use client";
import { useState } from "react";
import { Button, HStack } from "astralis-ui";
export function ButtonLoading() {
const [saving, setSaving] = useState(false);
const save = () => {
setSaving(true);
setTimeout(() => setSaving(false), 2000);
};
return (
<HStack gap="3" wrap="wrap" justifyContent="center">
<Button loading>Loading</Button>
<Button variant="outline" loading loadingText="Submitting…" />
<Button variant="subtle" loading loaderPlacement="end" loadingText="Uploading" />
<Button onClick={save} loading={saving} loadingText="Saving…">
Click to save
</Button>
</HStack>
);
}import { Grid, Center, Text } from "astralis-ui";
export function GridResponsive() {
return (
/* 1 column on mobile, 2 from md, 3 from lg. */
<Grid columns={{ base: "1", md: "2", lg: "3" }} gap="3" w="full" maxW="md">
{["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn"].map((planet) => (
<Center key={planet} bg="blue-subtle" p="4" rounded="lg">
<Text size="sm">{planet}</Text>
</Center>
))}
</Grid>
);
}Mercury
Venus
Earth
Mars
Jupiter
Saturn
Install the package, wrap your app in the provider, and every component on this site is yours.