30 May 2025

Release 3.0.0

Intent UI v3 rewrites most components and updates sizing, form labels, charts, and component composition.

Introduction

Intent UI v3 rewrites most components with more consistent APIs and more compact layouts, including changes for mobile devices.

New components

What changed

  • Updated React Aria Components and Tailwind CSS.
  • Removed legacy size values (square-petite, extra-small, small, medium, large) from the size prop in Button and Toggle. Use xs, sm, md, lg, or the square sizes sq-xs, sq-sm, sq-md, and sq-lg.
  • Removed legacy size values (small, medium, large, extra-large) from the size prop in Avatar. Use xs, sm, md, lg, or xl.
  • Removed the shape prop from Button, Badge, Tag, and Toggle. Use the isCircle prop instead.
  • Removed the unused focusRing and focusStyles exports from primitive.ts.
  • Removed classNames from Sheet and Modal. Use className on Modal.Content and Sheet.Content to customize their styles.
  • Changed the Choicebox defaults to gap={0} and columns={1}.
  • Added a Loader to FileTrigger during the pending state.
  • Replaced the Tabs dot-notation API with separate Tabs, TabList, Tab, and TabPanel components.
  • Removed motion from Tabs. Add your own animation library if needed.
  • Rewrote Chart to use Recharts v3.

Toggle Group

The new ToggleGroup component supports single and multiple selection.

Loading...

Button

Replace the Button shape prop with isCircle, and update the size values as shown below.

// Before
<Button size="small" shape="circle">Press me</Button>

// After
<Button size="sm" isCircle>Press me</Button>

// ---

// Before
<Button size="square-petite">Press me</Button>

// After
<Button size="sq-sm">Press me</Button>
Loading...

Toggle

Update Toggle size values and replace shape with isCircle, as shown below.

// Before
<Toggle size="small" shape="circle">Toggle me</Toggle>

// After
<Toggle size="sm" isCircle>Toggle me</Toggle>

// ---

// Before
<Toggle size="square-petite" shape="circle">Toggle me</Toggle>

// After
<Toggle size="sq-sm" isCircle>Toggle me</Toggle>

Checkbox and Radio

Checkbox, CheckboxGroup, and RadioGroup now accept labels and descriptions as children. Use Label for group labels and CheckboxLabel or RadioLabel for item labels.

<CheckboxGroup>
  <Label>User Permissions</Label>
  <Description>Select the permissions you want to grant to the user.</Description>
  <Checkbox value="read">
    <CheckboxLabel>Read</CheckboxLabel>
    <Description>Can view content but cannot make changes.</Description>
  </Checkbox>
  <Checkbox value="write">
    <CheckboxLabel>Write</CheckboxLabel>
    <Description>Can create and modify existing content.</Description>
  </Checkbox>
</CheckboxGroup>
<RadioGroup name="billing">
  <Label>Billing Cycle</Label>
  <Description>Select how often you'd like to be billed</Description>

  <Radio value="monthly">
    <RadioLabel>Monthly</RadioLabel>
    <Description>Billed every month</Description>
  </Radio>
  <Radio value="quarterly">
    <RadioLabel>Quarterly</RadioLabel>
    <Description>Billed every 3 months</Description>
  </Radio>
  <Radio value="yearly">
    <RadioLabel>Yearly</RadioLabel>
    <Description>Billed once per year with a discount</Description>
  </Radio>
</RadioGroup>

Component "controls/checkbox-group/switch-description-example" not found in the registry.

Switch

Switch now supports descriptions through the label and description props or through Label and Description children.

<Switch
  label="Enable Notifications"
  description="Receive updates and alerts via email"
/>

<Switch>
  <Label>Enable Notifications</Label>
  <Description>Receive updates and alerts via email</Description>
</Switch>
Loading...

Charts

Charts now use Recharts v3, with dedicated AreaChart, BarChart, LineChart, and PieChart components.

Area Chart

Loading...

Bar Chart

Loading...

Line Chart

Loading...

Pie Chart

Loading...

Primitive

composeTailwindRenderProps now accepts ClassNameValue. Update your local copy if your project already includes this utility.

"use client"

import { composeRenderProps } from "react-aria-components"
import { type ClassNameValue, twMerge } from "tailwind-merge"

function composeTailwindRenderProps<T>(
  className: string | ((v: T) => string) | undefined,
  tailwind: ClassNameValue,
): string | ((v: T) => string) {
  return composeRenderProps(className, (className) => twMerge(tailwind, className))
}

export { composeTailwindRenderProps }