Skip to main content
astrocraft-ui/ components · 101

Radio Group

Free · MIT

Headless, accessible, and styled entirely through the attribute surface below — bring your own CSS system, or start from the reference theme.

Install

Without a flag you get no styling at all — plain HTML carrying the attribute surface below. --theme copies the same theme in two dialects;--bridge lumos re-points either one onto Lumos for Astro's tokens (it needs a theme to re-point, and Lumos itself, already in your project).

Unstyled — behavior only, you write the CSS

Install command
npx astrocraft-ui add forms/radio-group

Plain-CSS theme — no build step

Install command
npx astrocraft-ui add forms/radio-group --theme css

Tailwind theme — needs Tailwind v4

Install command
npx astrocraft-ui add forms/radio-group --theme tailwind

Plain-CSS theme, re-pointed onto Lumos tokens

Install command
npx astrocraft-ui add forms/radio-group --theme css --bridge lumos

Tailwind theme, re-pointed onto Lumos tokens

Install command
npx astrocraft-ui add forms/radio-group --theme tailwind --bridge lumos

Live demo

RadioGroup & CheckboxGroup

Both are real fieldsets, so the legend names the group. The checkbox group’s first box is the select-all — tick one child and it goes indeterminate, the state HTML has no attribute for.

Plan
Billing period
Notifications

Attribute surface

With no class-merging machinery, these attributes are the whole extension point. State is a data-attribute or a native attribute; visibility is the hiddenattribute. Generated from source by pnpm slots.

ComponentSlotsVariantsRuntime stateNative state
`RadioGroup.astro``radio-group` `radio-group-label``data-orientation`: `vertical` · `horizontal`——
`RadioGroupIndicator.astro``radio-dot`———
`RadioGroupItem.astro``radio-group-item` `radio-group-item-label`———

Source

What the command copies — 4 files, alias-free so the copy lands standing alone. This is the whole component, shown without its comments; the files you install keep them, with the reasoning behind every rule.

src/components/ui/forms/radio-group/RadioGroup.astro
---
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"fieldset"> & {
  label?: string;
  orientation?: "vertical" | "horizontal";
};

const { label, orientation = "vertical", class: className, ...rest } = Astro.props;
---

<fieldset
  class={className}
  role="radiogroup"
  data-slot="radio-group"
  data-orientation={orientation}
  {...rest}
>
  {label && <legend data-slot="radio-group-label">{label}</legend>}
  <slot />
</fieldset>
src/components/ui/forms/radio-group/RadioGroupIndicator.astro
---
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"span">;

const { class: className, ...rest } = Astro.props;
---

<span class={className} data-slot="radio-dot" aria-hidden="true" {...rest}></span>
src/components/ui/forms/radio-group/RadioGroupItem.astro
---
import type { HTMLAttributes } from "astro/types";

import Radio from "../../forms/radio";

type Props = HTMLAttributes<"input"> & { name: string; value: string };

const { name, value, class: className, ...rest } = Astro.props;
---

<label data-slot="radio-group-item">
  <Radio name={name} value={value} class={className} {...rest} />
  <span data-slot="radio-group-item-label"><slot /></span>
</label>
src/components/ui/forms/radio-group/index.ts
import RadioGroup from "./RadioGroup.astro";
import RadioGroupIndicator from "./RadioGroupIndicator.astro";
import RadioGroupItem from "./RadioGroupItem.astro";

export { RadioGroup, RadioGroupIndicator, RadioGroupItem };
export default RadioGroup;

What you get

The component source, copied into your project by npx astrocraft-ui add forms/radio-group — no package dependency, no CSS to fight. Whatever the paid blocks compose, this is it.