component

Radio

A radio button component for single selection from a group. Supports three appearances: radio (default circular indicator), button (Panel-powered with full emphasis and tone), and tab (minimal underline tab — a 2px accent bar on the bottom edge, or the inline-start edge with orientation="vertical").

Default

---
// GENERATED from packages/demos/radio/default.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column" })}>
  <Radio id="astro-demo-def-1" name="astro-demo-default" value="option1">
    Option 1
  </Radio>
  <Radio
    id="astro-demo-def-2"
    name="astro-demo-default"
    value="option2"
    checked
  >
    Option 2
  </Radio>
  <Radio
    id="astro-demo-def-3"
    name="astro-demo-default"
    value="option3"
    disabled
  >
    Disabled
  </Radio>
</div>

Appearance

All four appearance variants side by side.

radio (default)

button

tab (horizontal)

tab (vertical)

---
// GENERATED from packages/demos/radio/appearance.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>radio (default)</h3>
    <div class={stack({ gap: "md", direction: "column" })}>
      <Radio id="astro-demo-app-r1" name="astro-demo-app-radio" value="app-r1">
        Option 1
      </Radio>
      <Radio
        id="astro-demo-app-r2"
        name="astro-demo-app-radio"
        value="app-r2"
        checked
      >
        Option 2
      </Radio>
    </div>
  </div>

  <div>
    <h3>button</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-app-b1"
        name="astro-demo-app-button"
        value="app-b1"
        appearance="button"
        checked
      >
        Option 1
      </Radio>
      <Radio
        id="astro-demo-app-b2"
        name="astro-demo-app-button"
        value="app-b2"
        appearance="button"
      >
        Option 2
      </Radio>
      <Radio
        id="astro-demo-app-b3"
        name="astro-demo-app-button"
        value="app-b3"
        appearance="button"
      >
        Option 3
      </Radio>
    </div>
  </div>

  <div>
    <h3>tab (horizontal)</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-app-th1"
        name="astro-demo-app-tab-h"
        value="app-th1"
        appearance="tab"
        checked
      >
        Tab 1
      </Radio>
      <Radio
        id="astro-demo-app-th2"
        name="astro-demo-app-tab-h"
        value="app-th2"
        appearance="tab"
      >
        Tab 2
      </Radio>
      <Radio
        id="astro-demo-app-th3"
        name="astro-demo-app-tab-h"
        value="app-th3"
        appearance="tab"
      >
        Tab 3
      </Radio>
    </div>
  </div>

  <div>
    <h3>tab (vertical)</h3>
    <div class={stack({ gap: "xs", direction: "column" })}>
      <Radio
        id="astro-demo-app-tv1"
        name="astro-demo-app-tab-v"
        value="app-tv1"
        appearance="tab"
        orientation="vertical"
        checked
      >
        Tab 1
      </Radio>
      <Radio
        id="astro-demo-app-tv2"
        name="astro-demo-app-tab-v"
        value="app-tv2"
        appearance="tab"
        orientation="vertical"
      >
        Tab 2
      </Radio>
    </div>
  </div>
</div>

Size

Three sizes are available across all appearances.

radio appearance

button appearance

---
// GENERATED from packages/demos/radio/size.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>radio appearance</h3>
    <div class={stack({ gap: "sm", direction: "row", align: "center" })}>
      <Radio
        id="astro-demo-size-sm"
        name="astro-demo-size-radio"
        value="size-sm"
        size="sm"
        checked
      >
        Small
      </Radio>
      <Radio
        id="astro-demo-size-md"
        name="astro-demo-size-radio"
        value="size-md"
        size="md"
      >
        Medium
      </Radio>
      <Radio
        id="astro-demo-size-lg"
        name="astro-demo-size-radio"
        value="size-lg"
        size="lg"
      >
        Large
      </Radio>
    </div>
  </div>

  <div>
    <h3>button appearance</h3>
    <div class={stack({ gap: "sm", direction: "row", align: "center" })}>
      <Radio
        id="astro-demo-sbtn-sm"
        name="astro-demo-size-button"
        value="sbtn-sm"
        appearance="button"
        size="sm"
        checked
      >
        Small
      </Radio>
      <Radio
        id="astro-demo-sbtn-md"
        name="astro-demo-size-button"
        value="sbtn-md"
        appearance="button"
        size="md"
      >
        Medium
      </Radio>
      <Radio
        id="astro-demo-sbtn-lg"
        name="astro-demo-size-button"
        value="sbtn-lg"
        appearance="button"
        size="lg"
      >
        Large
      </Radio>
    </div>
  </div>
</div>

Button

appearance="button" composes with Panel — use tone (primary, success, danger, warning, neutral) to control the surface.

Primary (default)

Danger

Warning

Success

---
// GENERATED from packages/demos/radio/button.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Primary (default)</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-btn-p1"
        name="astro-demo-btn-primary"
        value="btn-p1"
        appearance="button"
        checked
      >
        Option 1
      </Radio>
      <Radio
        id="astro-demo-btn-p2"
        name="astro-demo-btn-primary"
        value="btn-p2"
        appearance="button"
      >
        Option 2
      </Radio>
      <Radio
        id="astro-demo-btn-p3"
        name="astro-demo-btn-primary"
        value="btn-p3"
        appearance="button"
      >
        Option 3
      </Radio>
    </div>
  </div>

  <div>
    <h3>Danger</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-btn-d1"
        name="astro-demo-btn-danger"
        value="btn-d1"
        appearance="button"
        tone="danger"
        checked
      >
        Option 1
      </Radio>
      <Radio
        id="astro-demo-btn-d2"
        name="astro-demo-btn-danger"
        value="btn-d2"
        appearance="button"
        tone="danger"
      >
        Option 2
      </Radio>
    </div>
  </div>

  <div>
    <h3>Warning</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-btn-w1"
        name="astro-demo-btn-warning"
        value="btn-w1"
        appearance="button"
        tone="warning"
        checked
      >
        Option 1
      </Radio>
      <Radio
        id="astro-demo-btn-w2"
        name="astro-demo-btn-warning"
        value="btn-w2"
        appearance="button"
        tone="warning"
      >
        Option 2
      </Radio>
    </div>
  </div>

  <div>
    <h3>Success</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-btn-s1"
        name="astro-demo-btn-success"
        value="btn-s1"
        appearance="button"
        tone="success"
        checked
      >
        Option 1
      </Radio>
      <Radio
        id="astro-demo-btn-s2"
        name="astro-demo-btn-success"
        value="btn-s2"
        appearance="button"
        tone="success"
      >
        Option 2
      </Radio>
    </div>
  </div>
</div>

Emphasis

For appearance="button", the emphasis prop controls how the unchecked and checked states relate to each other. primary (default) keeps today’s filled-accent look. secondary rides the colorPalette.surface.* ramp and swaps to the opposite ramp position when checked. tertiary stays on a neutral surface with accent-colored text and a muted border. The background prop still picks the starting position; hover and active step through the ramp from there.

The border prop owns the resting border. Secondary and tertiary default to "muted" and promote to "default" on the checked state; primary defaults to "default" everywhere (and the accent ring on checked is part of primary’s filled identity). Pass border="none" to remove the resting border entirely (great with tertiary for a borderless segmented look) or border="bold" | "accent" to intensify it.

Primary (default)

Secondary

Tertiary

Secondary + tone

---
// GENERATED from packages/demos/radio/emphasis.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Primary (default)</h3>
    <div class={stack({ gap: "lg", direction: "row" })}>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-p1"
          name="astro-demo-ebtn-p"
          value="ebtn-p1"
          appearance="button"
          checked
        >
          Option 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-p2"
          name="astro-demo-ebtn-p"
          value="ebtn-p2"
          appearance="button"
        >
          Option 2
        </Radio>
      </div>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-pn1"
          name="astro-demo-ebtn-pn"
          value="ebtn-pn1"
          appearance="button"
          tone="neutral"
          checked
        >
          Neutral 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-pn2"
          name="astro-demo-ebtn-pn"
          value="ebtn-pn2"
          appearance="button"
          tone="neutral"
        >
          Neutral 2
        </Radio>
      </div>
    </div>
  </div>

  <div>
    <h3>Secondary</h3>
    <div class={stack({ gap: "lg", direction: "row" })}>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-s1"
          name="astro-demo-ebtn-s"
          value="ebtn-s1"
          appearance="button"
          emphasis="secondary"
          checked
        >
          Option 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-s2"
          name="astro-demo-ebtn-s"
          value="ebtn-s2"
          appearance="button"
          emphasis="secondary"
        >
          Option 2
        </Radio>
      </div>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-sn1"
          name="astro-demo-ebtn-sn"
          value="ebtn-sn1"
          appearance="button"
          emphasis="secondary"
          tone="neutral"
          checked
        >
          Neutral 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-sn2"
          name="astro-demo-ebtn-sn"
          value="ebtn-sn2"
          appearance="button"
          emphasis="secondary"
          tone="neutral"
        >
          Neutral 2
        </Radio>
      </div>
    </div>
  </div>

  <div>
    <h3>Tertiary</h3>
    <div class={stack({ gap: "lg", direction: "row" })}>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-t1"
          name="astro-demo-ebtn-t"
          value="ebtn-t1"
          appearance="button"
          emphasis="tertiary"
          checked
        >
          Option 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-t2"
          name="astro-demo-ebtn-t"
          value="ebtn-t2"
          appearance="button"
          emphasis="tertiary"
        >
          Option 2
        </Radio>
      </div>
      <div class={stack({ gap: "sm", direction: "row" })}>
        <Radio
          id="astro-demo-ebtn-tn1"
          name="astro-demo-ebtn-tn"
          value="ebtn-tn1"
          appearance="button"
          emphasis="tertiary"
          tone="neutral"
          checked
        >
          Neutral 1
        </Radio>
        <Radio
          id="astro-demo-ebtn-tn2"
          name="astro-demo-ebtn-tn"
          value="ebtn-tn2"
          appearance="button"
          emphasis="tertiary"
          tone="neutral"
        >
          Neutral 2
        </Radio>
      </div>
    </div>
  </div>

  <div>
    <h3>Secondary + tone</h3>
    <div class={stack({ gap: "sm", direction: "row" })}>
      <Radio
        id="astro-demo-ebtn-fbn"
        name="astro-demo-ebtn-fb"
        value="ebtn-fbn"
        appearance="button"
        emphasis="secondary"
        tone="neutral"
        checked
      >
        Neutral
      </Radio>
      <Radio
        id="astro-demo-ebtn-fbd"
        name="astro-demo-ebtn-fb"
        value="ebtn-fbd"
        appearance="button"
        emphasis="secondary"
        tone="danger"
      >
        Danger
      </Radio>
      <Radio
        id="astro-demo-ebtn-fbw"
        name="astro-demo-ebtn-fb"
        value="ebtn-fbw"
        appearance="button"
        emphasis="secondary"
        tone="warning"
      >
        Warning
      </Radio>
      <Radio
        id="astro-demo-ebtn-fbs"
        name="astro-demo-ebtn-fb"
        value="ebtn-fbs"
        appearance="button"
        emphasis="secondary"
        tone="success"
      >
        Success
      </Radio>
    </div>
  </div>
</div>

Tab

appearance="tab" renders a minimal underline tab: transparent surface and a 2px inset accent bar on the checked item. orientation picks the bar edge — "horizontal" (default, bottom edge) or "vertical" (inline-start edge). Use tone to change the accent color. Wrap tabs in a Group to get the 1px baseline track drawn for you, plus a selection bar that slides between tabs (CSS anchor positioning; without it, each tab keeps its own static bar). Navigation and Tab build their strips on this same appearance.

Tab rows are sized control rows on the Control Var Contract, like the button appearance: leading/trailing content (a <Stamp> icon, a <Badge> count) sizes itself to the row metrics. Tabs are transparent by default with the size-derived control radius on the free corners; pass background (a neutral surface token, e.g. "surface.peak") for an opt-in resting fill, and radius to retune or square the corners — hover, press, and the checked state keep moving only the bar and text, and the bar-edge corners always stay square so the accent bar sits seated on the track.

Tab

Tab — Vertical orientation

Tab — Danger tone

Tab — Background

Tab — Leading and trailing slots

---
// GENERATED from packages/demos/radio/tab.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import Badge from "@pindoba/astro-badge";
import Stamp from "@pindoba/astro-stamp";
import { GitBranch, Trash } from "@lucide/astro";
import { css } from "@pindoba/styled-system/css";
import { stack } from "@pindoba/styled-system/patterns";

const hTrack = `${stack({ gap: "sm", direction: "row" })} ${css({
  boxShadow: "0 -1px 0 0 token(colors.neutral.border) inset",
})}`;
const vTrack = `${stack({ gap: "xs", direction: "column" })} ${css({
  boxShadow: "1px 0 0 0 token(colors.neutral.border) inset",
  width: "max-content",
})}`;
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Tab</h3>
    <div class={hTrack}>
      <Radio
        id="astro-demo-tab-h1"
        name="astro-demo-tab-h"
        value="tab-h1"
        appearance="tab"
        checked
      >
        All
      </Radio>
      <Radio
        id="astro-demo-tab-h2"
        name="astro-demo-tab-h"
        value="tab-h2"
        appearance="tab"
      >
        Active
      </Radio>
      <Radio
        id="astro-demo-tab-h3"
        name="astro-demo-tab-h"
        value="tab-h3"
        appearance="tab"
      >
        Archived
      </Radio>
    </div>
  </div>

  <div>
    <h3>Tab — Vertical orientation</h3>
    <div class={vTrack}>
      <Radio
        id="astro-demo-tab-v1"
        name="astro-demo-tab-v"
        value="tab-v1"
        appearance="tab"
        orientation="vertical"
        checked
      >
        Dashboard
      </Radio>
      <Radio
        id="astro-demo-tab-v2"
        name="astro-demo-tab-v"
        value="tab-v2"
        appearance="tab"
        orientation="vertical"
      >
        Settings
      </Radio>
      <Radio
        id="astro-demo-tab-v3"
        name="astro-demo-tab-v"
        value="tab-v3"
        appearance="tab"
        orientation="vertical"
      >
        Profile
      </Radio>
    </div>
  </div>

  <div>
    <h3>Tab — Danger tone</h3>
    <div class={hTrack}>
      <Radio
        id="astro-demo-tab-hd1"
        name="astro-demo-tab-hd"
        value="tab-hd1"
        appearance="tab"
        tone="danger"
        checked
      >
        Errors
      </Radio>
      <Radio
        id="astro-demo-tab-hd2"
        name="astro-demo-tab-hd"
        value="tab-hd2"
        appearance="tab"
        tone="danger"
      >
        Warnings
      </Radio>
    </div>
  </div>

  <div>
    <h3>Tab — Background</h3>
    <div class={hTrack}>
      <Radio
        id="astro-demo-tab-b1"
        name="astro-demo-tab-bg"
        value="tab-b1"
        appearance="tab"
        background="surface.peak"
        checked
      >
        Inbox
      </Radio>
      <Radio
        id="astro-demo-tab-b2"
        name="astro-demo-tab-bg"
        value="tab-b2"
        appearance="tab"
        background="surface.peak"
      >
        Archive
      </Radio>
    </div>
  </div>

  <div>
    <h3>Tab — Leading and trailing slots</h3>
    <div class={hTrack}>
      <Radio
        id="astro-demo-tab-s1"
        name="astro-demo-tab-slots"
        value="tab-s1"
        appearance="tab"
        checked
      >
        <Stamp slot="leading" emphasis="ghost">
          <GitBranch />
        </Stamp>
        <Badge slot="trailing" size="sm">
          221
        </Badge>
        Active
      </Radio>
      <Radio
        id="astro-demo-tab-s2"
        name="astro-demo-tab-slots"
        value="tab-s2"
        appearance="tab"
        tone="danger"
      >
        <Stamp slot="leading" emphasis="ghost">
          <Trash />
        </Stamp>
        <Badge slot="trailing" size="sm" tone="danger">
          0
        </Badge>
        Deleted
      </Radio>
    </div>
  </div>
</div>

With Badge

Badges inside radio components scale with the component’s size via fontSize: 1rem.

radio appearance

button appearance

---
// GENERATED from packages/demos/radio/badge.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import Badge from "@pindoba/astro-badge";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>radio appearance</h3>
    <div class={stack({ gap: "sm", direction: "row", align: "center" })}>
      <Radio
        id="astro-demo-badge-radio-sm"
        name="astro-demo-badge-radio"
        value="badge-radio-sm"
        size="sm"
        checked
      >
        Small{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
      <Radio
        id="astro-demo-badge-radio-md"
        name="astro-demo-badge-radio"
        value="badge-radio-md"
        size="md"
      >
        Medium{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
      <Radio
        id="astro-demo-badge-radio-lg"
        name="astro-demo-badge-radio"
        value="badge-radio-lg"
        size="lg"
      >
        Large{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
    </div>
  </div>

  <div>
    <h3>button appearance</h3>
    <div class={stack({ gap: "sm", direction: "row", align: "center" })}>
      <Radio
        id="astro-demo-badge-btn-sm"
        name="astro-demo-badge-btn"
        value="badge-btn-sm"
        appearance="button"
        size="sm"
        checked
      >
        Small{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
      <Radio
        id="astro-demo-badge-btn-md"
        name="astro-demo-badge-btn"
        value="badge-btn-md"
        appearance="button"
        size="md"
      >
        Medium{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
      <Radio
        id="astro-demo-badge-btn-lg"
        name="astro-demo-badge-btn"
        value="badge-btn-lg"
        appearance="button"
        size="lg"
      >
        Large{" "}
        <Badge tone="primary" size="sm">
          3
        </Badge>
      </Radio>
    </div>
  </div>
</div>

Leading & Trailing slots

Use the leading and trailing slots to position icons, stamps, or badges at the start and end of the label. With emphasis="adaptive", badges and stamps follow the parent’s color in both unchecked and checked states. The trailing slot pins to the end of the row, which pairs well with fullWidth.

button appearance — both slots

button appearance — leading only

button appearance — trailing only

radio appearance

---
// GENERATED from packages/demos/radio/leading-trailing.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import Badge from "@pindoba/astro-badge";
import Stamp from "@pindoba/astro-stamp";
import { Mail } from "@lucide/astro";
import { stack } from "@pindoba/styled-system/patterns";

const sizes = ["sm", "md", "lg"] as const;
---

<div class={stack({ gap: "lg", direction: "column" })}>
  <div>
    <h3>button appearance — both slots</h3>
    <div class={stack({ gap: "sm", direction: "column" })}>
      {sizes.map((size) => (
        <Radio
          id={`astro-demo-lt-rbtn-${size}`}
          appearance="button"
          name="astro-demo-lt-demo-button"
          value={size}
          size={size}
          checked={size === "md"}
          fullWidth
        >
          <Stamp slot="leading" emphasis="adaptive" size="xs" shape="circle">
            <Mail />
          </Stamp>
          <Badge slot="trailing" emphasis="adaptive" size="sm">
            7
          </Badge>
          Unread
        </Radio>
      ))}
    </div>
  </div>

  <div>
    <h3>button appearance — leading only</h3>
    <div class={stack({ gap: "sm", direction: "column" })}>
      {sizes.map((size) => (
        <Radio
          id={`astro-demo-lt-rbtn-leading-${size}`}
          appearance="button"
          name="astro-demo-lt-demo-button-leading"
          value={size}
          size={size}
          checked={size === "md"}
          fullWidth
        >
          <Stamp slot="leading" emphasis="adaptive" size="xs" shape="circle">
            <Mail />
          </Stamp>
          Unread
        </Radio>
      ))}
    </div>
  </div>

  <div>
    <h3>button appearance — trailing only</h3>
    <div class={stack({ gap: "sm", direction: "column" })}>
      {sizes.map((size) => (
        <Radio
          id={`astro-demo-lt-rbtn-trailing-${size}`}
          appearance="button"
          name="astro-demo-lt-demo-button-trailing"
          value={size}
          size={size}
          checked={size === "md"}
          fullWidth
        >
          <Badge slot="trailing" emphasis="adaptive" size="sm">
            7
          </Badge>
          Unread
        </Radio>
      ))}
    </div>
  </div>

  <div>
    <h3>radio appearance</h3>
    <div class={stack({ gap: "sm", direction: "column" })}>
      {sizes.map((size) => (
        <Radio
          id={`astro-demo-lt-r-${size}`}
          name="astro-demo-lt-demo-radio"
          value={size}
          size={size}
          checked={size === "md"}
        >
          <Badge slot="trailing" emphasis="adaptive" size="sm">
            $9/mo
          </Badge>
          Pro plan
        </Radio>
      ))}
    </div>
  </div>
</div>

Custom Styling

The passThrough prop provides per-slot escape hatches: style accepts a Panda CSS SystemStyleObject merged with the base styles, and props forwards arbitrary HTML attributes onto the element.

Custom root style via passThrough

Custom input style via passThrough

Custom props via passThrough

---
// GENERATED from packages/demos/radio/custom.demo.tsx — edit the source, not this file.
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Custom root style via passThrough</h3>
    <div class={stack({ gap: "md", direction: "column" })}>
      <Radio
        id="astro-demo-cust-1"
        name="astro-demo-custom"
        value="cust-c1"
        checked
        passThrough={{
          root: {
            style: { gap: "lg", padding: "sm" },
          },
        }}
      >
        Extra padding
      </Radio>
    </div>
  </div>

  <div>
    <h3>Custom input style via passThrough</h3>
    <div class={stack({ gap: "md", direction: "column" })}>
      <Radio
        id="astro-demo-cust-2"
        name="astro-demo-custom"
        value="cust-c2"
        passThrough={{
          input: {
            style: { width: "2em", height: "2em" },
          },
        }}
      >
        Larger indicator
      </Radio>
    </div>
  </div>

  <div>
    <h3>Custom props via passThrough</h3>
    <div class={stack({ gap: "md", direction: "column" })}>
      <Radio
        id="astro-demo-cust-3"
        name="astro-demo-custom"
        value="cust-c3"
        passThrough={{
          root: {
            props: { "data-testid": "my-radio" },
          },
          input: {
            props: { "aria-label": "Custom radio button" },
          },
        }}
      >
        With data attributes
      </Radio>
    </div>
  </div>
</div>
  • Components
  • Blocks