refactor(toggles): explicit composition for radio, checkbox & switch (#6614)
* refactor(toggles): explicit composition for radio, checkbox & switch Migrate Radio, Checkbox and Switch from child-partitioning to an explicit, React Server Components-safe compound composition. - Add `<X.Button>` (React Aria *Button) as the clickable label wrapping the control + `Label`; remove the child-type inspection that broke under RSC. - Drop `<X.Content>`; `Description`/`FieldError` become siblings of `X.Button` and are exposed via `aria-describedby` for a cleaner accessible name. - Keep a context-based control-only fallback for Checkbox/Switch so label-less usages (e.g. table selection) are unchanged. - Fix Label context bleed inside toggle buttons; retire partition-toggle-field-children. - Update styles, stories, EN/CN demos, component docs and migration guides. BREAKING CHANGE: Radio, Checkbox and Switch no longer expose `*.Content`. Wrap the control and `Label` in `*.Button`, and place `Description`/`FieldError` as siblings of `*.Button`. Control-only checkboxes and switches are unaffected. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(releases): add v3.2.0 release notes Calendar week/day views + multiple selection demos, React Aria 1.18 notes, rolled-in v3.1.1 patch fixes, and the Radio/Checkbox/Switch *.Content -> *.Button breaking-change migration guide (EN + CN). Updates releases index, meta, home release badge, and dictionaries. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(docs): rotating release badges on home hero Replace the single hardcoded release badge with a curated, per-locale releaseBadges list rendered by a Motion-powered carousel: popLayout spring swap, auto-advancing accent progress segments (transform-only scaleX with a soft gradient fade), pause on hover/focus, reduced-motion fallback, and a plain-badge fallback for a single entry. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(releases): point v3.2.0 contributors to PR #6616 Co-authored-by: Cursor <cursoragent@cursor.com> * docs(releases): fix v3.2.0 release PR link to #6616 Co-authored-by: Cursor <cursoragent@cursor.com> * fix(docs): remove release badge progress indicators Drop the carousel segment bars under the home hero release badge. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(releases): add tooltip delay CSS vars to v3.2.0 notes Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(toggles): rename Button to Content and simplify label composition (#6618) Rename Checkbox/Radio/Switch.Button to .Content, remove toggle-specific Label auto-wiring, and update docs, demos, styles, and v3.2.0 release notes. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Junior <jrgarciadev@gmail.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Button 按钮
|
||||
description: 可点击的按钮组件,支持多种变体与状态。
|
||||
icon: updated
|
||||
links:
|
||||
rac: Button
|
||||
source: button/button.tsx
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: Switch 开关
|
||||
description: 用于布尔状态的开关组件。
|
||||
icon: updated
|
||||
links:
|
||||
rac: Switch
|
||||
rac: SwitchField
|
||||
source: switch/switch.tsx
|
||||
styles: switch.css
|
||||
storybook: Components/Controls/Switch
|
||||
@@ -26,19 +27,20 @@ import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
引入 Switch 组件,并通过点语法访问各部分。
|
||||
|
||||
```tsx
|
||||
import { Switch, Label, Description } from '@heroui/react';
|
||||
import { Switch, Description, FieldError } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon/> {/* Optional */}
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon /> {/* 可选 */}
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
Label {/* 纯文本 —— 可点击的标签,同时作为无障碍名称 */}
|
||||
</Switch.Content>
|
||||
<Description /> {/* 可选 — 字段级帮助文本 */}
|
||||
<FieldError /> {/* 可选 — 校验错误信息 */}
|
||||
</Switch>
|
||||
);
|
||||
```
|
||||
@@ -51,16 +53,20 @@ import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
export default () => (
|
||||
<SwitchGroup>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 1
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 2
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
);
|
||||
@@ -173,7 +179,7 @@ function CustomSwitch() {
|
||||
className={`size-[27px] bg-white shadow-sm ${isSelected ? "translate-x-5 shadow-lg" : ""}`}
|
||||
/>
|
||||
</Switch.Control>
|
||||
<Label>Custom Switch</Label>
|
||||
Custom Switch
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
@@ -190,16 +196,20 @@ function CustomSwitchGroup() {
|
||||
return (
|
||||
<SwitchGroup className="gap-8" orientation="horizontal">
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 1
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 2
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
);
|
||||
@@ -226,7 +236,7 @@ function CustomSwitchGroup() {
|
||||
}
|
||||
|
||||
.switch__content {
|
||||
@apply flex flex-col gap-1;
|
||||
@apply items-center gap-3;
|
||||
}
|
||||
|
||||
.switch__icon {
|
||||
@@ -243,8 +253,8 @@ HeroUI 遵循 [BEM](https://getbem.com/) 方法论,确保组件变体与状态
|
||||
|
||||
Switch 组件使用以下 CSS 类([查看源码样式](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch.css)):
|
||||
|
||||
- `.switch` - Switch 根容器
|
||||
- `.switch__content` - 可选内容容器
|
||||
- `.switch` - Switch 根容器(字段)
|
||||
- `.switch__content` - 包裹控件与标签文本的可点击 label
|
||||
- `.switch__control` - Switch 轨道
|
||||
- `.switch__thumb` - 可移动的滑块
|
||||
- `.switch__icon` - 滑块内可选图标
|
||||
@@ -266,16 +276,16 @@ SwitchGroup 组件使用以下 CSS 类([查看源码样式](https://github.com
|
||||
该 Switch 同时支持 CSS 伪类与 data 属性,以提供更灵活的状态控制:
|
||||
|
||||
- **已选中**:`[data-selected="true"]`(滑块位置与背景色变化)
|
||||
- **悬停**:`:hover` 或 `[data-hovered="true"]`
|
||||
- **聚焦**:`:focus-visible` 或 `[data-focus-visible="true"]`(显示焦点环)
|
||||
- **禁用**:`:disabled` 或 `[aria-disabled="true"]`(降低透明度,禁用指针事件)
|
||||
- **悬停**:`:hover` 或 `[data-hovered="true"]`(作用于 `Switch.Control` / 按钮)
|
||||
- **聚焦**:`:focus-visible` 或 `[data-focus-visible="true"]`(在按钮上显示轨道焦点环)
|
||||
- **禁用**:`[data-disabled="true"]`(降低透明度,包括帮助文本)
|
||||
- **按压**:`:active` 或 `[data-pressed="true"]`
|
||||
|
||||
## API 参考
|
||||
|
||||
### Switch Props
|
||||
|
||||
继承自 [React Aria Switch](https://react-spectrum.adobe.com/react-aria/Switch.html)。
|
||||
继承自 [React Aria SwitchField](https://react-spectrum.adobe.com/react-aria/Switch.html)。
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
@@ -283,27 +293,43 @@ SwitchGroup 组件使用以下 CSS 类([查看源码样式](https://github.com
|
||||
| `isSelected` | `boolean` | `false` | Switch 是否打开。 |
|
||||
| `defaultSelected` | `boolean` | `false` | 默认是否打开(非受控)。 |
|
||||
| `isDisabled` | `boolean` | `false` | Switch 是否禁用。 |
|
||||
| `isInvalid` | `boolean` | `false` | Switch 是否无效。 |
|
||||
| `isReadOnly` | `boolean` | `false` | Switch 是否只读。 |
|
||||
| `isRequired` | `boolean` | `false` | Switch 是否必须打开。 |
|
||||
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | 自定义校验函数。 |
|
||||
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | 使用原生 HTML 校验或 ARIA 校验。 |
|
||||
| `name` | `string` | - | 输入元素名称,用于提交 HTML 表单。 |
|
||||
| `value` | `string` | - | 输入元素值,用于提交 HTML 表单。 |
|
||||
| `onChange` | `(isSelected: boolean) => void` | - | Switch 值变化时的事件处理函数。 |
|
||||
| `onPress` | `(e: PressEvent) => void` | - | Switch 被按下时的事件处理函数。 |
|
||||
| `children` | `React.ReactNode \| (values: SwitchRenderProps) => React.ReactNode` | - | Switch 内容或渲染 prop。 |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|
|
||||
| `children` | `React.ReactNode \| (values: SwitchFieldRenderProps) => React.ReactNode` | - | Switch 内容或字段级渲染 prop。 |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchFieldRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|
|
||||
|
||||
### SwitchRenderProps
|
||||
### Switch.Content Props
|
||||
|
||||
使用渲染 prop 模式时,会提供以下值:
|
||||
包裹控件与标签文本的可点击 `<label>`。请把 `Switch.Control` 与 `Label` 放在它内部;`Description`/`FieldError` 作为 `Switch.Content` 的兄弟节点。对于没有标签的 switch,省略 `Label` 并在 `Switch` 上传入 `aria-label`。
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
| `children` | `React.ReactNode \| (values: SwitchButtonRenderProps) => React.ReactNode` | - | 按钮内容(控件 + 标签),或按钮级渲染 prop |
|
||||
| `className` | `string \| (values: SwitchButtonRenderProps) => string` | - | 应用到可点击 label 的类名 |
|
||||
|
||||
### SwitchFieldRenderProps
|
||||
|
||||
在根 `Switch` 上使用渲染 prop 时,提供以下字段级值:
|
||||
|
||||
| Prop | 类型 | 描述 |
|
||||
|------|------|------|
|
||||
| `isSelected` | `boolean` | Switch 当前是否打开。 |
|
||||
| `isHovered` | `boolean` | Switch 是否处于悬停状态。 |
|
||||
| `isPressed` | `boolean` | Switch 当前是否被按压。 |
|
||||
| `isFocused` | `boolean` | Switch 是否聚焦。 |
|
||||
| `isFocusVisible` | `boolean` | Switch 是否处于键盘聚焦状态。 |
|
||||
| `isDisabled` | `boolean` | Switch 是否禁用。 |
|
||||
| `isReadOnly` | `boolean` | Switch 是否只读。 |
|
||||
| `state` | `-` | Switch 的状态。 |
|
||||
| `isInvalid` | `boolean` | Switch 是否无效。 |
|
||||
| `isRequired` | `boolean` | Switch 是否必填。 |
|
||||
| `state` | `ToggleState` | Switch 的状态。 |
|
||||
|
||||
### SwitchButtonRenderProps
|
||||
|
||||
`Switch.Control` 使用按钮级渲染 prop(`isHovered`、`isPressed`、`isFocusVisible` 等)。将函数作为 `Switch.Control` 的子元素即可访问。
|
||||
|
||||
### SwitchGroup Props
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Badge 徽标
|
||||
description: 展示相对其他元素定位的小型指示器,常用于未读数、状态点与标签等场景。
|
||||
icon: updated
|
||||
links:
|
||||
source: badge/badge.tsx
|
||||
styles: badge.css
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Chip 标签
|
||||
description: 用于展示标签、状态与分类等信息的小型徽标。
|
||||
icon: updated
|
||||
links:
|
||||
source: chip/chip.tsx
|
||||
styles: chip.css
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Calendar 日历
|
||||
description: 基于 React Aria Calendar 的可组合日期选择器,包含月份网格、导航与年份选择器支持。
|
||||
icon: updated
|
||||
links:
|
||||
rac: Calendar
|
||||
source: calendar/calendar.tsx
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: CheckboxGroup 复选框组
|
||||
description: 用于管理多项复选框选择的 CheckboxGroup 组件。
|
||||
icon: updated
|
||||
links:
|
||||
rac: CheckboxGroup
|
||||
source: checkbox-group/checkbox-group.tsx
|
||||
@@ -32,13 +33,13 @@ export default () => (
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox value="option1">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Label {/* 纯文本 —— 可点击的标签 */}
|
||||
</Checkbox.Content>
|
||||
<Description /> {/* 可选:单个复选框的帮助文本 */}
|
||||
</Checkbox>
|
||||
<FieldError /> {/* Optional */}
|
||||
</CheckboxGroup>
|
||||
@@ -110,11 +111,11 @@ function CustomCheckboxGroup() {
|
||||
return (
|
||||
<CheckboxGroup className="gap-4" name="custom">
|
||||
<Checkbox value="option1">
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Option 1</Label>
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
Option 1
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: Checkbox 复选框
|
||||
description: 复选框允许用户从多个独立选项中选择多项,或将单个独立选项标记为已选。
|
||||
icon: updated
|
||||
links:
|
||||
rac: Checkbox
|
||||
rac: CheckboxField
|
||||
source: checkbox/checkbox.tsx
|
||||
styles: checkbox.css
|
||||
storybook: Components/Forms/Checkbox
|
||||
@@ -12,7 +13,7 @@ links:
|
||||
## 引入
|
||||
|
||||
```tsx
|
||||
import { Checkbox, Label } from '@heroui/react';
|
||||
import { Checkbox } from '@heroui/react';
|
||||
```
|
||||
|
||||
### 用法
|
||||
@@ -26,17 +27,18 @@ import { Checkbox, Label } from '@heroui/react';
|
||||
引入 Checkbox 后,可通过点语法访问各个部分。
|
||||
|
||||
```tsx
|
||||
import { Checkbox, Label, Description } from '@heroui/react';
|
||||
import { Checkbox, Description, FieldError } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Checkbox>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Label {/* 纯文本 —— 可点击的标签,同时作为无障碍名称 */}
|
||||
</Checkbox.Content>
|
||||
<Description /> {/* 可选 — 字段级帮助文本 */}
|
||||
<FieldError /> {/* 可选 — 校验错误信息 */}
|
||||
</Checkbox>
|
||||
);
|
||||
```
|
||||
@@ -65,10 +67,10 @@ export default () => (
|
||||
name="checkbox-indeterminate"
|
||||
/>
|
||||
|
||||
### 带标签
|
||||
### 外部标签
|
||||
|
||||
<ComponentPreview
|
||||
name="checkbox-with-label"
|
||||
name="checkbox-external-label"
|
||||
/>
|
||||
|
||||
### 带说明
|
||||
@@ -136,11 +138,11 @@ import { Checkbox, Label } from '@heroui/react';
|
||||
function CustomCheckbox() {
|
||||
return (
|
||||
<Checkbox name="custom">
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Custom Checkbox</Label>
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
Custom Checkbox
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
@@ -182,7 +184,7 @@ function CustomCheckbox() {
|
||||
}
|
||||
|
||||
.checkbox__content {
|
||||
@apply flex flex-col gap-1;
|
||||
@apply items-center gap-3;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -194,9 +196,9 @@ HeroUI 遵循 [BEM](https://getbem.com/) 方法论,确保组件变体与状态
|
||||
Checkbox 使用以下 CSS 类([查看源码样式](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/checkbox.css)):
|
||||
|
||||
- `.checkbox` - Checkbox 根容器
|
||||
- `.checkbox__content` - 包裹控件与标签文本的可点击 label
|
||||
- `.checkbox__control` - Checkbox 控件方框
|
||||
- `.checkbox__indicator` - Checkbox 勾选指示器
|
||||
- `.checkbox__content` - 可选内容容器
|
||||
|
||||
### 交互状态
|
||||
|
||||
@@ -205,16 +207,16 @@ Checkbox 同时支持 CSS 伪类与 data 属性,以获得更好的灵活性:
|
||||
- **选中**:`[data-selected="true"]` 或 `[aria-checked="true"]`(显示勾选与背景色变化)
|
||||
- **不定**:`[data-indeterminate="true"]`(以横线表示不定状态)
|
||||
- **无效**:`[data-invalid="true"]` 或 `[aria-invalid="true"]`(以危险色显示错误状态)
|
||||
- **悬停**:`:hover` 或 `[data-hovered="true"]`
|
||||
- **焦点**:`:focus-visible` 或 `[data-focus-visible="true"]`(显示焦点环)
|
||||
- **禁用**:`:disabled` 或 `[aria-disabled="true"]`(降低透明度并禁用指针事件)
|
||||
- **悬停**:`:hover` 或 `[data-hovered="true"]`(交互状态在 `Checkbox.Control` / 按钮上)
|
||||
- **焦点**:`:focus-visible` 或 `[data-focus-visible="true"]`(显示焦点环,作用于按钮)
|
||||
- **禁用**:`[data-disabled="true"]`(降低透明度并禁用指针事件)
|
||||
- **按下**:`:active` 或 `[data-pressed="true"]`
|
||||
|
||||
## API 参考
|
||||
|
||||
### Checkbox Props
|
||||
|
||||
继承自 [React Aria Checkbox](https://react-spectrum.adobe.com/react-aria/Checkbox.html)。
|
||||
继承自 [React Aria CheckboxField](https://react-spectrum.adobe.com/react-aria/Checkbox.html)。
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
@@ -224,24 +226,38 @@ Checkbox 同时支持 CSS 伪类与 data 属性,以获得更好的灵活性:
|
||||
| `isDisabled` | `boolean` | `false` | Checkbox 是否禁用 |
|
||||
| `isInvalid` | `boolean` | `false` | Checkbox 是否无效 |
|
||||
| `isReadOnly` | `boolean` | `false` | Checkbox 是否只读 |
|
||||
| `isRequired` | `boolean` | `false` | Checkbox 是否必须选中 |
|
||||
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | 自定义校验函数 |
|
||||
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | 使用原生 HTML 校验或 ARIA 校验 |
|
||||
| `variant` | `"primary" \| "secondary"` | `"primary"` | 组件的视觉变体。`primary` 为默认带阴影样式。`secondary` 为弱强调、无阴影变体,适合用于 surface 上。 |
|
||||
| `name` | `string` | - | input 元素的 name,用于提交 HTML 表单 |
|
||||
| `value` | `string` | - | input 元素的 value,用于提交 HTML 表单 |
|
||||
| `onChange` | `(isSelected: boolean) => void` | - | Checkbox 值变化时调用 |
|
||||
| `children` | `React.ReactNode \| (values: CheckboxRenderProps) => React.ReactNode` | - | Checkbox 内容或渲染 prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, CheckboxRenderProps>` | - | 通过自定义渲染函数覆盖默认的 DOM 元素。 |
|
||||
| `children` | `React.ReactNode \| (values: CheckboxFieldRenderProps) => React.ReactNode` | - | Checkbox 内容或字段级渲染 prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, CheckboxFieldRenderProps>` | - | 通过自定义渲染函数覆盖默认的 DOM 元素。 |
|
||||
|
||||
### CheckboxRenderProps
|
||||
### Checkbox.Content Props
|
||||
|
||||
使用渲染 prop 模式时,会提供以下值:
|
||||
包裹控件与标签文本的可点击 `<label>`。请把 `Checkbox.Control` 与 `Label` 放在它内部;`Description`/`FieldError` 作为 `Checkbox.Content` 的兄弟节点。对于没有标签的 checkbox,省略 `Label` 并在 `Checkbox` 上传入 `aria-label`。
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
| `children` | `React.ReactNode \| (values: CheckboxButtonRenderProps) => React.ReactNode` | - | 按钮内容(控件 + 标签),或按钮级渲染 prop |
|
||||
| `className` | `string \| (values: CheckboxButtonRenderProps) => string` | - | 应用到可点击 label 的类名 |
|
||||
|
||||
### CheckboxFieldRenderProps
|
||||
|
||||
在根 `Checkbox` 上使用渲染 prop 时,提供以下字段级值:
|
||||
|
||||
| Prop | 类型 | 描述 |
|
||||
|------|------|------|
|
||||
| `isSelected` | `boolean` | Checkbox 当前是否选中 |
|
||||
| `isIndeterminate` | `boolean` | Checkbox 是否处于不定状态 |
|
||||
| `isHovered` | `boolean` | Checkbox 是否处于悬停状态 |
|
||||
| `isPressed` | `boolean` | Checkbox 当前是否处于按下状态 |
|
||||
| `isFocused` | `boolean` | Checkbox 是否聚焦 |
|
||||
| `isFocusVisible` | `boolean` | Checkbox 是否处于键盘可见焦点状态 |
|
||||
| `isDisabled` | `boolean` | Checkbox 是否禁用 |
|
||||
| `isReadOnly` | `boolean` | Checkbox 是否只读 |
|
||||
| `isInvalid` | `boolean` | Checkbox 是否无效 |
|
||||
| `isRequired` | `boolean` | Checkbox 是否必填 |
|
||||
|
||||
### CheckboxButtonRenderProps
|
||||
|
||||
`Checkbox.Control` 与 `Checkbox.Indicator` 使用按钮级渲染 prop(`isHovered`、`isPressed`、`isFocusVisible` 等)。将函数作为 `Checkbox.Control` 或 `Checkbox.Indicator` 的子元素即可访问。
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: RadioGroup 单选框组
|
||||
description: 用于从列表中选择单个选项的单选组。
|
||||
icon: updated
|
||||
links:
|
||||
rac: RadioGroup
|
||||
rac: RadioField
|
||||
source: radio-group/radio-group.tsx
|
||||
styles: radio-group.css
|
||||
storybook: Components/Forms/RadioGroup
|
||||
@@ -20,7 +21,6 @@ import { RadioGroup, Radio } from '@heroui/react';
|
||||
name="radio-group-basic"
|
||||
/>
|
||||
|
||||
|
||||
### 组件结构
|
||||
|
||||
导入 RadioGroup 组件后,可通过点号访问各个子部分。
|
||||
@@ -33,17 +33,18 @@ export default () => (
|
||||
<Label />
|
||||
<Description />
|
||||
<Radio value="option1">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
<span>✓</span> {/* Custom indicator (optional) */}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label />
|
||||
<Description />
|
||||
<Radio.Content> {/* 可点击区域:control + label */}
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
<span>✓</span> {/* Custom indicator (optional) */}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
Label {/* 纯文本 —— 可点击的标签 */}
|
||||
</Radio.Content>
|
||||
<Description /> {/* 兄弟节点 — 位于按钮外部(通过 aria-describedby 关联) */}
|
||||
<FieldError /> {/* 可选 — 单选项校验错误信息 */}
|
||||
</Radio>
|
||||
<FieldError />
|
||||
<FieldError /> {/* 可选 — 组级校验 */}
|
||||
</RadioGroup>
|
||||
)
|
||||
```
|
||||
@@ -111,7 +112,6 @@ RadioGroup 支持两种视觉变体:
|
||||
name="radio-group-delivery-and-payment"
|
||||
/>
|
||||
|
||||
|
||||
<RelatedShowcases component="RadioGroup" />
|
||||
|
||||
<RelatedComponents component="radiogroup" />
|
||||
@@ -238,8 +238,8 @@ RadioGroup 使用以下 CSS 类([查看源码样式](https://github.com/heroui
|
||||
| `value` | `string` | - | 单选项的值 |
|
||||
| `isDisabled` | `boolean` | `false` | 是否禁用该单选项 |
|
||||
| `name` | `string` | - | 单选项名称,用于提交 HTML 表单 |
|
||||
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | 单选内容或渲染 prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|
|
||||
| `children` | `React.ReactNode \| (values: RadioFieldRenderProps) => React.ReactNode` | - | 单选内容或字段级渲染 prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioFieldRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|
|
||||
|
||||
### Radio.Control Props
|
||||
|
||||
@@ -255,27 +255,28 @@ RadioGroup 使用以下 CSS 类([查看源码样式](https://github.com/heroui
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | 可选内容或接收当前单选状态的渲染 prop。 |
|
||||
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | 可选内容或接收当前单选按钮状态的渲染 prop。 |
|
||||
|
||||
### Radio.Content Props
|
||||
|
||||
继承 `React.HTMLAttributes<HTMLDivElement>`。
|
||||
单选项的可点击区域(包裹隐藏 input 的 `<label>`)。请将 `Radio.Control` 与 `Label` 放在其中。`className` 支持接收 `RadioButtonRenderProps` 的渲染函数。
|
||||
|
||||
| Prop | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
| `children` | `React.ReactNode` | - | 内容包裹层内要渲染的内容(通常为 Label 与 Description) |
|
||||
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | 可点击内容(通常为 Radio.Control 与 Label) |
|
||||
|
||||
### RadioRenderProps
|
||||
### RadioFieldRenderProps
|
||||
|
||||
使用渲染 prop 模式时,会提供以下值:
|
||||
在根级 `Radio` 上使用渲染 prop 时,会提供以下字段级值:
|
||||
|
||||
| Prop | 类型 | 描述 |
|
||||
|------|------|------|
|
||||
| `isSelected` | `boolean` | 单选项是否已选中 |
|
||||
| `isHovered` | `boolean` | 是否悬停 |
|
||||
| `isPressed` | `boolean` | 是否按下 |
|
||||
| `isFocused` | `boolean` | 是否聚焦 |
|
||||
| `isFocusVisible` | `boolean` | 是否为键盘可见焦点 |
|
||||
| `isDisabled` | `boolean` | 是否禁用 |
|
||||
| `isReadOnly` | `boolean` | 是否只读 |
|
||||
| `isInvalid` | `boolean` | 是否无效 |
|
||||
| `isRequired` | `boolean` | 是否必填 |
|
||||
|
||||
### RadioButtonRenderProps
|
||||
|
||||
`Radio.Control` 和 `Radio.Indicator` 使用按钮级渲染 prop(`isHovered`、`isPressed`、`isFocusVisible` 等)。将函数作为 `Radio.Control` 子节点或传给 `Radio.Indicator` 即可访问它们。
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: TextField 文本输入框
|
||||
description: 便于组合的文本字段,包含标签、说明与内联校验。
|
||||
icon: updated
|
||||
links:
|
||||
rac: TextField
|
||||
source: textfield/textfield.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Autocomplete 自动完成
|
||||
description: 自动完成将选择与过滤结合,让用户可以搜索并从选项列表中选择。
|
||||
icon: updated
|
||||
links:
|
||||
rac: Select
|
||||
source: autocomplete/autocomplete.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Typography 排版
|
||||
description: 面向标题、正文与行内代码的语义化排版原语,基于 React Aria Components 的 Text 构建。
|
||||
icon: new
|
||||
links:
|
||||
source: typography/typography.tsx
|
||||
styles: typography.css
|
||||
|
||||
@@ -35,27 +35,27 @@ export default function App() {
|
||||
<CheckboxGroup name="interests">
|
||||
<Label>Select interests</Label>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Coding</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Coding
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Design</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Design
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Writing</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Writing
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -78,7 +78,7 @@ export default function App() {
|
||||
### 3. Checkbox 结构
|
||||
|
||||
**v2:** 简单的 Checkbox 组件,子节点直接作为标签
|
||||
**v3:** 复合 Checkbox 组件,由 `Checkbox.Control`、`Checkbox.Indicator` 与 `Checkbox.Content` 组成
|
||||
**v3:** 复合 Checkbox 组件,由 `Checkbox.Content`、`Checkbox.Control` 与 `Checkbox.Indicator` 组成
|
||||
|
||||
### 4. 事件处理函数
|
||||
|
||||
@@ -126,27 +126,27 @@ export default function App() {
|
||||
>
|
||||
<Label>Select interests</Label>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Coding</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Coding
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Design</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Design
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Writing</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Writing
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -157,7 +157,7 @@ export default function App() {
|
||||
## 总结
|
||||
|
||||
- 继续使用 `CheckboxGroup`;用 `Label` 子组件取代 `label` prop
|
||||
- 将 Checkbox 子项更新为复合组件结构(`Checkbox.Control`、`Checkbox.Indicator`、`Checkbox.Content`)
|
||||
- 将 Checkbox 子项更新为复合组件结构(`Checkbox.Content`、`Checkbox.Control`、`Checkbox.Indicator`)
|
||||
- 将 `onValueChange` 改为 `onChange`
|
||||
- 添加 `name` prop 以便集成到表单中
|
||||
- 基于 React Aria Components 构建,更易实现无障碍
|
||||
|
||||
@@ -27,11 +27,11 @@ import { Checkbox, Label } from "@heroui/react";
|
||||
export default function App() {
|
||||
return (
|
||||
<Checkbox defaultSelected id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
@@ -43,12 +43,12 @@ export default function App() {
|
||||
### 1. 组件结构
|
||||
|
||||
**v2:** 简单组件,`children` 即标签
|
||||
**v3:** 复合组件:`Checkbox.Control`、`Checkbox.Indicator`、`Checkbox.Content`
|
||||
**v3:** 复合组件:`Checkbox.Content`、`Checkbox.Control`、`Checkbox.Indicator`
|
||||
|
||||
### 2. 标签处理
|
||||
|
||||
**v2:** 标签直接作为 `children` 传入 `Checkbox`
|
||||
**v3:** 标签须放在 `Checkbox.Content` 内,并使用 `Label` 组件
|
||||
**v3:** 标签放在 `Checkbox.Content`(可点击的标签)内;`Description` / `FieldError` 是 `Checkbox.Content` 的同级节点
|
||||
|
||||
### 3. Prop 变更
|
||||
|
||||
@@ -95,11 +95,11 @@ export default function App() {
|
||||
const [isSelected, setIsSelected] = useState(false);
|
||||
|
||||
<Checkbox id="subscribe" isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="subscribe">Subscribe</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Subscribe
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -123,13 +123,13 @@ export default function App() {
|
||||
import { Checkbox, Label, Description } from "@heroui/react";
|
||||
|
||||
<Checkbox id="option" defaultSelected>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Description>Description text</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
<Description>Description text</Description>
|
||||
</Checkbox>
|
||||
```
|
||||
</Tab>
|
||||
@@ -157,27 +157,27 @@ export default function App() {
|
||||
<Label>Select cities</Label>
|
||||
<Description>Choose all that apply</Description>
|
||||
<Checkbox value="buenos-aires">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Buenos Aires</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Buenos Aires
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="sydney">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Sydney</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Sydney
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="san-francisco">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>San Francisco</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
San Francisco
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -201,21 +201,21 @@ export default function App() {
|
||||
```tsx
|
||||
{/* Colors - use Tailwind classes */}
|
||||
<Checkbox defaultSelected id="primary">
|
||||
<Checkbox.Control className="data-[selected=true]:bg-primary data-[selected=true]:border-primary">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="primary">Primary</Label>
|
||||
<Checkbox.Control className="data-[selected=true]:bg-primary data-[selected=true]:border-primary">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Primary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
{/* Sizes - use Tailwind classes */}
|
||||
<Checkbox defaultSelected id="medium">
|
||||
<Checkbox.Control className="size-5">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="medium">Medium</Label>
|
||||
<Checkbox.Control className="size-5">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Medium
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -235,13 +235,13 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Checkbox defaultSelected id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) => isSelected ? <HeartIcon /> : null}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) => isSelected ? <HeartIcon /> : null}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -255,21 +255,21 @@ v3 引入 `variant` prop,可选 `"primary"`(默认)与 `"secondary"`:
|
||||
```tsx
|
||||
{/* Primary variant (default) */}
|
||||
<Checkbox variant="primary" id="primary-option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="primary-option">Primary</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Primary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
{/* Secondary variant - lower emphasis, suitable for Surface components */}
|
||||
<Checkbox variant="secondary" id="secondary-option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="secondary-option">Secondary</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Secondary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -285,11 +285,11 @@ v3 引入 `variant` prop,可选 `"primary"`(默认)与 `"secondary"`:
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Checkbox isIndeterminate id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -304,13 +304,13 @@ v3 Checkbox 支持渲染 prop,用于暴露状态信息:
|
||||
<Checkbox id="terms">
|
||||
{({isSelected, isIndeterminate, isHovered, isPressed, isFocused, isDisabled}) => (
|
||||
<>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="terms">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
|
||||
{isSelected ? "Terms accepted" : "Accept terms"}
|
||||
</Label>
|
||||
|
||||
</Checkbox.Content>
|
||||
</>
|
||||
)}
|
||||
@@ -321,15 +321,15 @@ v3 Checkbox 支持渲染 prop,用于暴露状态信息:
|
||||
|
||||
```tsx
|
||||
<Checkbox id="custom">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected, isIndeterminate}) =>
|
||||
isIndeterminate ? <MinusIcon /> : isSelected ? <CheckIcon /> : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="custom">Custom indicator</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected, isIndeterminate}) =>
|
||||
isIndeterminate ? <MinusIcon /> : isSelected ? <CheckIcon /> : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
Custom indicator
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -364,13 +364,13 @@ v3 Checkbox 支持渲染 prop,用于暴露状态信息:
|
||||
|
||||
```tsx
|
||||
<Checkbox className="custom-base" id="option">
|
||||
<Checkbox.Control className="custom-control">
|
||||
<Checkbox.Indicator className="custom-indicator" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content className="custom-content">
|
||||
<Label htmlFor="option" className="custom-label">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control className="custom-control">
|
||||
<Checkbox.Indicator className="custom-indicator" />
|
||||
</Checkbox.Control>
|
||||
|
||||
Option
|
||||
</Label>
|
||||
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -381,17 +381,18 @@ v3 Checkbox 的结构如下:
|
||||
|
||||
```
|
||||
Checkbox (Root)
|
||||
├── Checkbox.Control
|
||||
│ └── Checkbox.Indicator
|
||||
└── Checkbox.Content (optional)
|
||||
├── Label (required if using Content)
|
||||
└── Description (optional)
|
||||
├── Checkbox.Content (the clickable label)
|
||||
│ ├── Checkbox.Control
|
||||
│ │ └── Checkbox.Indicator
|
||||
│ └── Label
|
||||
├── Description (optional, sibling)
|
||||
└── FieldError (optional, sibling)
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
1. **组件结构**:必须使用复合组件(`Control`、`Indicator`、`Content`)。
|
||||
2. **标签处理**:标签须使用 `Label`,并放在 `Checkbox.Content` 内。
|
||||
1. **组件结构**:必须使用复合组件(`Button`、`Control`、`Indicator`)。
|
||||
2. **标签处理**:标签放在 `Checkbox.Content` 内。
|
||||
3. **`onValueChange` → `onChange`**:事件处理函数 prop 已重命名。
|
||||
4. **颜色已移除**:请在 `Checkbox.Control` 上使用 Tailwind CSS 类。
|
||||
5. **尺寸已移除**:请在 `Checkbox.Control` 上使用 Tailwind CSS 类。
|
||||
|
||||
@@ -35,28 +35,28 @@ export default function App() {
|
||||
<RadioGroup name="city">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Description>Capital of Japan</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
<Description>Capital of Japan</Description>
|
||||
</Radio>
|
||||
<Radio value="paris">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Paris</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Paris
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -74,12 +74,12 @@ export default function App() {
|
||||
### 2. Radio 结构
|
||||
|
||||
**v2:** 简单的 Radio 组件,子节点直接作为标签
|
||||
**v3:** 复合 Radio 组件,由 `Radio.Control`、`Radio.Indicator` 与 `Radio.Content` 组成
|
||||
**v3:** 复合 Radio 组件,由 `Radio.Content`、`Radio.Control` 与 `Radio.Indicator` 组成
|
||||
|
||||
### 3. 描述处理
|
||||
|
||||
**v2:** 在单个 `Radio` 组件上使用 `description` prop
|
||||
**v3:** 在 `Radio.Content` 内部使用 `Description` 组件
|
||||
**v3:** 将 `Description` 组件作为 `Radio.Content` 的兄弟节点使用
|
||||
|
||||
### 4. 事件处理函数
|
||||
|
||||
@@ -118,22 +118,22 @@ export default function App() {
|
||||
<RadioGroup name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Description>Basic features</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
<Description>Basic features</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Pro</Label>
|
||||
<Description>All features</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Pro
|
||||
</Radio.Content>
|
||||
<Description>All features</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
```
|
||||
@@ -160,11 +160,11 @@ export default function App() {
|
||||
<RadioGroup variant="primary" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -173,11 +173,11 @@ export default function App() {
|
||||
<RadioGroup variant="secondary" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -194,19 +194,19 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
<RadioGroup isReadOnly defaultValue="basic" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Pro</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Pro
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -238,19 +238,19 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
<RadioGroup name="city" value={value} onChange={setValue}>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -262,7 +262,7 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
|
||||
- 用 `Label` 子组件取代 `label` prop
|
||||
- 将 Radio 子项更新为复合组件结构
|
||||
- 用 `Radio.Content` 内部的 `Description` 组件取代 Radio 的 `description` prop
|
||||
- 将 `Description` 组件作为 `Radio.Content` 的兄弟节点,取代 Radio 的 `description` prop
|
||||
- 将 `onValueChange` 改为 `onChange`
|
||||
- 添加 `name` prop 以便集成到表单中
|
||||
- 新增 `variant` prop:`"primary"`(默认)或 `"secondary"`,用于较弱的视觉强调
|
||||
|
||||
@@ -34,21 +34,21 @@ export default function App() {
|
||||
<RadioGroup>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Description>Capital of Japan</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
<Description>Capital of Japan</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
@@ -60,7 +60,7 @@ export default function App() {
|
||||
### 1. 组件结构
|
||||
|
||||
**v2:** 简单的 Radio,`children` 作为标签文案
|
||||
**v3:** 复合组件:`Radio.Control`、`Radio.Indicator`、`Radio.Content`
|
||||
**v3:** 复合组件:`Radio.Content`、`Radio.Control`、`Radio.Indicator`
|
||||
|
||||
### 2. Prop 变更
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function App() {
|
||||
| --- | --- | --- |
|
||||
| `onValueChange` | `onChange` | 事件处理函数已重命名 |
|
||||
| `label`(在 RadioGroup 上) | — | 使用 `Label` 组件 |
|
||||
| `description`(在 Radio 上) | — | 在 `Radio.Content` 内使用 `Description` 组件 |
|
||||
| `description`(在 Radio 上) | — | 将 `Description` 组件作为 `Radio.Content` 的兄弟节点使用 |
|
||||
| `size` | — | 已移除(请改用 Tailwind CSS) |
|
||||
| `color` | — | 已移除(请改用 Tailwind CSS) |
|
||||
| `classNames` | — | 在各子组件上使用 `className` prop |
|
||||
@@ -108,13 +108,13 @@ export default function App() {
|
||||
<RadioGroup>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Description>Capital of England</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
<Description>Capital of England</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
@@ -122,11 +122,11 @@ export default function App() {
|
||||
<RadioGroup isInvalid>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<FieldError>Please select an option</FieldError>
|
||||
@@ -162,19 +162,19 @@ export default function App() {
|
||||
<RadioGroup value={selected} onChange={setSelected}>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -198,19 +198,19 @@ export default function App() {
|
||||
<RadioGroup orientation="horizontal">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -227,11 +227,11 @@ v3 在 `RadioGroup` 上新增 `variant` prop,可选 `"primary"`(默认)与
|
||||
<RadioGroup variant="primary">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -240,11 +240,11 @@ v3 在 `RadioGroup` 上新增 `variant` prop,可选 `"primary"`(默认)与
|
||||
<RadioGroup variant="secondary">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -258,19 +258,19 @@ v3 支持在 `RadioGroup` 上使用 `isReadOnly`:在保持组合可聚焦的
|
||||
<RadioGroup isReadOnly defaultValue="london">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -284,19 +284,19 @@ v3 的 Radio 结构如下:
|
||||
RadioGroup (Root)
|
||||
├── Label (optional)
|
||||
├── Radio
|
||||
│ ├── Radio.Control
|
||||
│ │ └── Radio.Indicator
|
||||
│ └── Radio.Content
|
||||
│ ├── Label
|
||||
│ └── Description (optional)
|
||||
│ ├── Radio.Content (the clickable label)
|
||||
│ │ ├── Radio.Control
|
||||
│ │ │ └── Radio.Indicator
|
||||
│ │ └── Label
|
||||
│ └── Description (optional, sibling)
|
||||
└── FieldError (optional)
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
1. **组件结构**:必须使用复合组件(`Radio.Control`、`Radio.Indicator`、`Radio.Content`)。
|
||||
1. **组件结构**:必须使用复合组件(`Radio.Content`、`Radio.Control`、`Radio.Indicator`)。
|
||||
2. **标签**:已移除 `label` prop,请使用 `Label` 组件。
|
||||
3. **描述**:已移除 `description` prop,请在 `Radio.Content` 内使用 `Description` 组件。
|
||||
3. **描述**:已移除 `description` prop,请将 `Description` 组件作为 `Radio.Content` 的兄弟节点使用。
|
||||
4. **事件处理函数**:`onValueChange` → `onChange`。
|
||||
5. **样式相关 prop 已移除**:`size`、`color` 等请改用 Tailwind CSS。
|
||||
6. **`classNames` 已移除**:在各子组件上使用 `className` prop。
|
||||
|
||||
@@ -27,11 +27,11 @@ import { Switch, Label } from "@heroui/react";
|
||||
export default function App() {
|
||||
return (
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
);
|
||||
@@ -43,7 +43,7 @@ export default function App() {
|
||||
### 1. 组件结构
|
||||
|
||||
**v2:** children 作为标签的简单 Switch
|
||||
**v3:** 复合组件(`Switch.Control`、`Switch.Thumb`、`Switch.Content`)与 `Label` 组件
|
||||
**v3:** 复合组件(`Switch.Content`、`Switch.Control`、`Switch.Thumb`)与 `Label` 组件
|
||||
|
||||
### 2. Prop 变更
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function App() {
|
||||
### 3. 新组件
|
||||
|
||||
- `SwitchGroup` — 用于将多个 Switch 成组
|
||||
- `Switch.Content` — 标签与描述的容器
|
||||
- `Switch.Content` — 可点击的标签,包裹控件与 `Label`
|
||||
- `Switch.Icon` — 拇指(Thumb)内的图标
|
||||
|
||||
## 迁移示例
|
||||
@@ -88,11 +88,11 @@ export default function App() {
|
||||
const [isSelected, setIsSelected] = useState(true);
|
||||
|
||||
<Switch isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Airplane mode</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Airplane mode
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -110,9 +110,11 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch defaultSelected aria-label="Automatic updates">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
</Tab>
|
||||
@@ -129,15 +131,15 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon>
|
||||
<CheckIcon />
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon>
|
||||
<CheckIcon />
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -160,13 +162,13 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch>
|
||||
<Switch.Control className="flex items-center gap-2">
|
||||
<SunIcon />
|
||||
<Switch.Thumb />
|
||||
<MoonIcon />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Dark mode</Label>
|
||||
<Switch.Control className="flex items-center gap-2">
|
||||
<SunIcon />
|
||||
<Switch.Thumb />
|
||||
<MoonIcon />
|
||||
</Switch.Control>
|
||||
Dark mode
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -188,13 +190,13 @@ export default function App() {
|
||||
import { Switch, Label, Description } from "@heroui/react";
|
||||
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Description>You will receive notifications for all activity</Description>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
<Description>You will receive notifications for all activity</Description>
|
||||
</Switch>
|
||||
```
|
||||
</Tab>
|
||||
@@ -223,54 +225,54 @@ export default function App() {
|
||||
{/* Sizes */}
|
||||
<div className="flex gap-4">
|
||||
<Switch size="sm">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Small</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Small
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch size="md">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Medium</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Medium
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch size="lg">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Large</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Large
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
{/* Colors - Use Tailwind CSS classes */}
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-accent">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Primary</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-accent">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Primary
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-success">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Success</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-success">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Success
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-danger">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Danger</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-danger">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Danger
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -295,19 +297,19 @@ export default function App() {
|
||||
|
||||
<SwitchGroup>
|
||||
<Switch name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Allow Notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Allow Notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Marketing emails</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Marketing emails
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
@@ -321,12 +323,13 @@ v3 `Switch` 的结构如下:
|
||||
|
||||
```
|
||||
Switch (Root)
|
||||
├── Switch.Control
|
||||
│ └── Switch.Thumb
|
||||
│ └── Switch.Icon (optional)
|
||||
└── Switch.Content (optional)
|
||||
├── Label (optional)
|
||||
└── Description (optional)
|
||||
├── Switch.Content (the clickable label)
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ │ └── Switch.Icon (optional)
|
||||
│ └── Label
|
||||
├── Description (optional, sibling)
|
||||
└── FieldError (optional, sibling)
|
||||
```
|
||||
|
||||
分组时:
|
||||
@@ -334,17 +337,17 @@ Switch (Root)
|
||||
```
|
||||
SwitchGroup
|
||||
├── Switch
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ └── Switch.Content
|
||||
│ ├── Label
|
||||
│ └── Description (optional)
|
||||
│ ├── Switch.Content
|
||||
│ │ ├── Switch.Control
|
||||
│ │ │ └── Switch.Thumb
|
||||
│ │ └── Label
|
||||
│ └── Description (optional)
|
||||
└── Switch
|
||||
├── Switch.Control
|
||||
│ └── Switch.Thumb
|
||||
└── Switch.Content
|
||||
├── Label
|
||||
└── Description (optional)
|
||||
├── Switch.Content
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ └── Label
|
||||
└── Description (optional)
|
||||
```
|
||||
|
||||
## 说明
|
||||
@@ -357,7 +360,7 @@ SwitchGroup
|
||||
### 标签
|
||||
|
||||
- **v2:** children 作为标签
|
||||
- **v3:** 在 `Switch.Content` 内使用 `Label`;可并列添加 `Description`
|
||||
- **v3:** `Label` 放在 `Switch.Content`(可点击的标签)内;`Description` / `FieldError` 作为 `Switch.Content` 的同级元素
|
||||
|
||||
### 图标
|
||||
|
||||
@@ -366,11 +369,11 @@ SwitchGroup
|
||||
|
||||
## 总结
|
||||
|
||||
1. **组件结构**:必须使用复合组件(`Switch.Control`、`Switch.Thumb`、`Switch.Content`)
|
||||
2. **内容容器**:用 `Switch.Content` 包裹 `Label` 与 `Description`,以保证布局正确
|
||||
1. **组件结构**:必须使用复合组件(`Switch.Content`、`Switch.Control`、`Switch.Thumb`)
|
||||
2. **可点击的标签**:用 `Switch.Content` 包裹 `Switch.Control` 与 `Label`;将 `Description` / `FieldError` 作为 `Switch.Content` 的同级元素
|
||||
3. **标签**:不再用 children 作为标签 — 请在 `Switch.Content` 内使用 `Label`
|
||||
4. **事件处理函数**:`onValueChange` → `onChange`
|
||||
5. **样式相关 prop 已移除**:`color` — 请使用 Tailwind CSS
|
||||
6. **图标相关 prop 已移除**:`thumbIcon`、`startContent`、`endContent` — 请用子组件或直接自定义
|
||||
7. **`classNames` 已移除**:请在各子组件上使用 `className` prop
|
||||
8. **新组件**:`SwitchGroup` 用于成组;`Switch.Content` 作为标签 / 描述容器
|
||||
8. **新组件**:`SwitchGroup` 用于成组;`Switch.Content` 作为可点击的标签,包裹控件与 `Label`
|
||||
|
||||
@@ -9,6 +9,16 @@ description: HeroUI v3 的所有更新与变更,包含新功能、修复以及
|
||||
|
||||
## 最新版本
|
||||
|
||||
### v3.2.0
|
||||
|
||||
**2026 年 6 月 6 日**
|
||||
|
||||
基于 React Aria 1.18 的 Calendar 周/日视图、重做的年份选择器与范围日历演示,新增 Tooltip 延迟主题变量,并纳入随之发布的补丁修复。破坏性变更:`Radio`、`Checkbox`、`Switch` 改为显式的 `*.Content` 组合(控件嵌套进 `*.Content`,标签为纯文本、不嵌套 `<Label>`,帮助文本变为兄弟节点)。
|
||||
|
||||
[阅读完整发布说明 →](/docs/react/releases/v3-2-0)
|
||||
|
||||
---
|
||||
|
||||
### v3.1.0
|
||||
|
||||
**2026 年 5 月 25 日**
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"---概述---",
|
||||
"index",
|
||||
"---版本列表---",
|
||||
"v3-2-0",
|
||||
"v3-1-0",
|
||||
"v3-0-5",
|
||||
"v3-0-4",
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: v3.2.0
|
||||
description: 基于 React Aria 1.18 的 Calendar 周/日视图与年份选择器,以及 Radio、Checkbox、Switch 的破坏性组合方式变更。
|
||||
github:
|
||||
pull: 6616
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-muted">2026 年 6 月 6 日</span>
|
||||
</div>
|
||||
|
||||
Calendar 新增周视图与日视图、重做的年份选择器,以及基于 React Aria 1.18 的范围日历演示。[Tooltip](/docs/components/tooltip) 新增用于全局显示与隐藏延迟的主题变量。Radio、Checkbox、Switch 迁移到 React Aria 的 `*Field` + `*Button` 组合方式。本次发布同时纳入了随 React Aria 1.18 一起发布的补丁修复(`Table.SortableColumnHeader`、Toast 与 Fieldset 修复、滚动与 RTL 样式修复)。
|
||||
|
||||
⚠️ **破坏性变更**:`Radio`、`Checkbox`、`Switch` 改为显式的 `*.Content` 组合 —— `*.Control` 嵌套进 `*.Content`,标签变为 `*.Content` 内的纯文本(不嵌套 `<Label>`),`Description`/`FieldError` 变为 `*.Content` 的兄弟节点。详见[破坏性变更](#-breaking-changes)。
|
||||
|
||||
## 安装
|
||||
|
||||
升级到最新版本:
|
||||
|
||||
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
|
||||
<Tab value="npm">
|
||||
```bash
|
||||
npm i @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="pnpm">
|
||||
```bash
|
||||
pnpm add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="yarn">
|
||||
```bash
|
||||
yarn add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="bun">
|
||||
```bash
|
||||
bun add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Callout type="info">
|
||||
**正在使用 AI 助手?** 对它说「Hey Cursor,把 HeroUI 升级到最新版本」。它会对比版本并应用必要变更。了解更多请参阅 [HeroUI MCP 服务器](/docs/ui-for-agents/mcp-server)。
|
||||
</Callout>
|
||||
|
||||
## 新增内容
|
||||
|
||||
### Calendar
|
||||
|
||||
`Calendar` 与 `RangeCalendar` 新增周视图与日视图,以及来自 React Aria 1.18 的新日历属性。
|
||||
|
||||
- **周视图 / 日视图**:通过 `visibleDuration` 渲染多周或单日布局
|
||||
- **多选**:在单个 `Calendar` 中选择多个日期
|
||||
- **React Aria 1.18 属性**:`weeksInMonth` 与用于范围选择的 `isDateUnavailable(date, anchorDate)`
|
||||
- **内部实现**:月份标题使用 React Aria 的 `CalendarHeading`,年份选择器基于 React Aria calendar hooks 重建
|
||||
|
||||
**周视图:**
|
||||
|
||||
<ComponentPreview name="calendar-week-view" />
|
||||
|
||||
**日视图:**
|
||||
|
||||
<ComponentPreview name="calendar-day-view" />
|
||||
|
||||
**多选:**
|
||||
|
||||
<ComponentPreview name="calendar-multiple-selection" />
|
||||
|
||||
**多选:**
|
||||
|
||||
<ComponentPreview name="calendar-multiple-selection" />
|
||||
|
||||
### Table.SortableColumnHeader
|
||||
|
||||
`Table.SortableColumnHeader` 用于渲染 sortable 列标题和可选的升降序指示器。放在 `Table.Column` render prop 中,并传入 `sortDirection` ([#6588](https://github.com/heroui-inc/heroui/pull/6588))。
|
||||
|
||||
```tsx
|
||||
<Table.Column allowsSorting>
|
||||
{({sortDirection}) => (
|
||||
<Table.SortableColumnHeader sortDirection={sortDirection}>
|
||||
Name
|
||||
</Table.SortableColumnHeader>
|
||||
)}
|
||||
</Table.Column>
|
||||
```
|
||||
|
||||
- **默认指示器**:存在排序方向时显示 chevron
|
||||
- **自定义指示器**:传入 `indicator`,或用 `showIndicator={false}` 隐藏
|
||||
- **样式插槽**:`.table__sortable-column-header` + `.table__sortable-column-indicator`
|
||||
|
||||
<ComponentPreview name="table-sorting" />
|
||||
|
||||
### Tooltip 延迟主题变量
|
||||
|
||||
[Tooltip](/docs/components/tooltip) 现在会从主题 CSS 变量读取默认的显示与隐藏延迟 ([#6617](https://github.com/heroui-inc/heroui/pull/6617)):
|
||||
|
||||
- `--tooltip-delay` — 显示 Tooltip 前的延迟(默认:`1500ms`)
|
||||
- `--tooltip-close-delay` — 隐藏 Tooltip 前的延迟(默认:`500ms`)
|
||||
|
||||
全局覆盖示例:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--tooltip-delay: 700ms;
|
||||
--tooltip-close-delay: 0ms;
|
||||
}
|
||||
```
|
||||
|
||||
单个 Tooltip 上的 `delay` 和 `closeDelay` 属性仍会覆盖这些值。
|
||||
|
||||
<Callout type="warning">
|
||||
**行为变更:** 使用默认 HeroUI 主题时,Tooltip 延迟现在默认为 `1500ms` / `500ms`,而不是之前的 React Aria 默认值 `700ms` / `0ms`。如需保留旧行为,请显式设置 CSS 变量或 props。
|
||||
</Callout>
|
||||
|
||||
## 组件修复
|
||||
|
||||
- **Toast**:Toast 队列会串行化 ViewTransition 更新,避免在 `toast.promise()` 关闭 loading toast 并打开成功/失败反馈时出现被跳过的过渡和 AbortError ([#6511](https://github.com/heroui-inc/heroui/pull/6511))。
|
||||
- **Fieldset**:`disabled` 会传递到 React Aria 的 Button、CheckboxGroup、Link、RadioGroup、Slider、ToggleButton 和 ToggleButtonGroup 上下文 ([#6596](https://github.com/heroui-inc/heroui/pull/6596))。
|
||||
|
||||
## 样式修复
|
||||
|
||||
- **Modal / AlertDialog**:`scroll-inside` 对话框通过 `max-h-full min-h-0` 限制高度,使内容区域滚动而非溢出 ([#6597](https://github.com/heroui-inc/heroui/pull/6597))。
|
||||
- **ScrollShadow**:渐隐遮罩通过 `--scroll-shadow-scrollbar-size` 为可见的原生滚动条预留空间 ([#6598](https://github.com/heroui-inc/heroui/pull/6598))。
|
||||
- **Table RTL**:列分隔线与拖拽手柄在 RTL 下使用逻辑属性 `end-0` 定位 ([#6606](https://github.com/heroui-inc/heroui/pull/6606))。
|
||||
|
||||
## 依赖
|
||||
|
||||
- **React Aria Components**:`1.17.0` → `1.18.0` ([#6586](https://github.com/heroui-inc/heroui/pull/6586))。1.18 引入了 toggles 所采用的 `*Field` + `*Button` 组合方式、`CalendarHeading`,以及 `isDateUnavailable(date, anchorDate)`。
|
||||
- **@internationalized/date**:`3.12.1` → `3.12.2`
|
||||
- **React Aria / Stately 辅助包**:`@react-aria/*`、`@react-stately/*` 与 `@react-types/shared` 补丁更新
|
||||
|
||||
## ⚠️ Breaking Changes
|
||||
|
||||
### Radio、Checkbox 与 Switch:显式 `*.Content` 组合
|
||||
|
||||
这些组件现在在底层使用 React Aria 的 `*Field` + `*Button` 组合方式。`X.Content` 现在是**可点击的 label**(React Aria 的 `*Button`)。共有三点变化:
|
||||
|
||||
- **`X.Control` 移进 `X.Content`** —— 它们以前是兄弟节点。
|
||||
- **标签是 `X.Content` 内部的纯文本** —— `X.Content` 渲染的是 `<label>` 元素,所以不要嵌套 `<Label>` 组件(嵌套的 `<label>` 是无效 HTML)。若要使用独立的 `Label`,请把它放在**外部**,并用 `htmlFor` + 组件 `id` 关联。
|
||||
- **`Description`/`FieldError` 移到外部**,作为 `X.Content` 的兄弟节点,这样它们会通过 `aria-describedby` 朗读,而不会被并入无障碍名称。
|
||||
|
||||
**Checkbox**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Checkbox>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Accept terms</Label>
|
||||
<Description>You agree to our terms</Description>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
// v3.2
|
||||
<Checkbox>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Accept terms
|
||||
</Checkbox.Content>
|
||||
<Description>You agree to our terms</Description>
|
||||
</Checkbox>
|
||||
```
|
||||
|
||||
**Radio**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Radio value="a">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Option A</Label>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
|
||||
// v3.2
|
||||
<Radio value="a">
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Option A
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
```
|
||||
|
||||
**Switch**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
|
||||
// v3.2
|
||||
<Switch>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
|
||||
**迁移对照**
|
||||
|
||||
| v3.1 | v3.2 |
|
||||
|------|------|
|
||||
| `X.Control` 与 `X.Content` 为兄弟节点 | `X.Control` 嵌套进 `X.Content` |
|
||||
| `X.Content` 是包裹 `Label` + 帮助文本的布局 `<div>` | `X.Content` 是包裹 `X.Control` + 标签文本的可点击 `<label>` |
|
||||
| 通过 `X.Content` 内的 `<Label>` 提供标签 | 标签是 `X.Content` 内的**纯文本**(不嵌套 `<Label>`) |
|
||||
| `Description` / `FieldError` 位于 `X.Content` 内 | `Description` / `FieldError` 作为 `X.Content` 的兄弟节点 |
|
||||
|
||||
**外部标签** —— 若要使用独立的 `Label`,请把它放在组件外部,并用 `htmlFor` + 组件 `id` 关联:
|
||||
|
||||
```tsx
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="terms">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label htmlFor="terms">Accept terms</Label>
|
||||
</div>
|
||||
```
|
||||
|
||||
**仅含控件的 Checkbox 和 Switch**(没有标签,例如表格行选择或图标开关)仍需用 `X.Content` 作为可点击包装。请把 `Checkbox.Control` / `Switch.Control` 放进 `X.Content`,省略标签,并在根组件上传入 `aria-label`。
|
||||
|
||||
各组件完整迁移指南:[Checkbox](/docs/react/migration/checkbox)、[Checkbox Group](/docs/react/migration/checkbox-group)、[Radio](/docs/react/migration/radio)、[Radio Group](/docs/react/migration/radio-group)、[Switch](/docs/react/migration/switch)。
|
||||
|
||||
## 链接
|
||||
|
||||
- [Calendar 文档](/docs/react/components/calendar)
|
||||
- [Tooltip 文档](/docs/react/components/tooltip)
|
||||
- [Checkbox 文档](/docs/react/components/checkbox)
|
||||
- [Radio Group 文档](/docs/react/components/radio-group)
|
||||
- [Switch 文档](/docs/react/components/switch)
|
||||
- [组件文档](/docs/react/components)
|
||||
- [GitHub 仓库](https://github.com/heroui-inc/heroui)
|
||||
- [GitHub PR #6616](https://github.com/heroui-inc/heroui/pull/6616)
|
||||
|
||||
## 贡献者
|
||||
|
||||
感谢所有为本次发布做出贡献的人!
|
||||
|
||||
<PRContributors />
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Button
|
||||
description: A clickable button component with multiple variants and states
|
||||
icon: updated
|
||||
links:
|
||||
rac: Button
|
||||
source: button/button.tsx
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: Switch
|
||||
description: A toggle switch component for boolean states
|
||||
icon: updated
|
||||
links:
|
||||
rac: Switch
|
||||
rac: SwitchField
|
||||
source: switch/switch.tsx
|
||||
styles: switch.css
|
||||
storybook: Components/Controls/Switch
|
||||
@@ -26,19 +27,20 @@ import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
Import the Switch component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Switch, Label, Description } from '@heroui/react';
|
||||
import { Switch, Description, FieldError } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon/> {/* Optional */}
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon /> {/* Optional */}
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
Label {/* plain text — the clickable label + accessible name */}
|
||||
</Switch.Content>
|
||||
<Description /> {/* Optional — field-level help text */}
|
||||
<FieldError /> {/* Optional — validation message */}
|
||||
</Switch>
|
||||
);
|
||||
```
|
||||
@@ -51,16 +53,20 @@ import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
export default () => (
|
||||
<SwitchGroup>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 1
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 2
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
);
|
||||
@@ -173,7 +179,7 @@ function CustomSwitch() {
|
||||
className={`size-[27px] bg-white shadow-sm ${isSelected ? "translate-x-5 shadow-lg" : ""}`}
|
||||
/>
|
||||
</Switch.Control>
|
||||
<Label>Custom Switch</Label>
|
||||
Custom Switch
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
@@ -190,16 +196,20 @@ function CustomSwitchGroup() {
|
||||
return (
|
||||
<SwitchGroup className="gap-8" orientation="horizontal">
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 1
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Option 2
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
);
|
||||
@@ -226,7 +236,7 @@ To customize the Switch component classes, you can use the `@layer components` d
|
||||
}
|
||||
|
||||
.switch__content {
|
||||
@apply flex flex-col gap-1;
|
||||
@apply items-center gap-3;
|
||||
}
|
||||
|
||||
.switch__icon {
|
||||
@@ -243,8 +253,8 @@ HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component va
|
||||
|
||||
The Switch component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch.css)):
|
||||
|
||||
- `.switch` - Base switch container
|
||||
- `.switch__content` - Optional content container
|
||||
- `.switch` - Base switch container (the field)
|
||||
- `.switch__content` - Clickable label wrapping the control and label text
|
||||
- `.switch__control` - Switch control track
|
||||
- `.switch__thumb` - Switch thumb that moves
|
||||
- `.switch__icon` - Optional icon inside the thumb
|
||||
@@ -266,16 +276,16 @@ The SwitchGroup component uses these CSS classes ([View source styles](https://g
|
||||
The switch supports both CSS pseudo-classes and data attributes for flexibility:
|
||||
|
||||
- **Selected**: `[data-selected="true"]` (thumb position and background color change)
|
||||
- **Hover**: `:hover` or `[data-hovered="true"]`
|
||||
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
|
||||
- **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
|
||||
- **Hover**: `:hover` or `[data-hovered="true"]` on `Switch.Control` (button)
|
||||
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on the button (shows focus ring on track)
|
||||
- **Disabled**: `[data-disabled="true"]` on the field (reduced opacity, including help text)
|
||||
- **Pressed**: `:active` or `[data-pressed="true"]`
|
||||
|
||||
## API Reference
|
||||
|
||||
### Switch Props
|
||||
|
||||
Inherits from [React Aria Switch](https://react-spectrum.adobe.com/react-aria/Switch.html).
|
||||
Inherits from [React Aria SwitchField](https://react-spectrum.adobe.com/react-aria/Switch.html).
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
@@ -283,27 +293,43 @@ Inherits from [React Aria Switch](https://react-spectrum.adobe.com/react-aria/Sw
|
||||
| `isSelected` | `boolean` | `false` | Whether the switch is on |
|
||||
| `defaultSelected` | `boolean` | `false` | Whether the switch is on by default (uncontrolled) |
|
||||
| `isDisabled` | `boolean` | `false` | Whether the switch is disabled |
|
||||
| `isInvalid` | `boolean` | `false` | Whether the switch is invalid |
|
||||
| `isReadOnly` | `boolean` | `false` | Whether the switch is read only |
|
||||
| `isRequired` | `boolean` | `false` | Whether the switch must be selected |
|
||||
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | Custom validation function |
|
||||
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA |
|
||||
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
|
||||
| `value` | `string` | - | The value of the input element, used when submitting an HTML form |
|
||||
| `onChange` | `(isSelected: boolean) => void` | - | Handler called when the switch value changes |
|
||||
| `onPress` | `(e: PressEvent) => void` | - | Handler called when the switch is pressed |
|
||||
| `children` | `React.ReactNode \| (values: SwitchRenderProps) => React.ReactNode` | - | Switch content or render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
| `children` | `React.ReactNode \| (values: SwitchFieldRenderProps) => React.ReactNode` | - | Switch content or field render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchFieldRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
|
||||
### SwitchRenderProps
|
||||
### Switch.Content Props
|
||||
|
||||
When using the render prop pattern, these values are provided:
|
||||
The clickable `<label>` that wraps the control and label text. Put `Switch.Control` and the `Label` inside it; keep `Description`/`FieldError` as siblings of `Switch.Content`. For a switch with no label, omit the `Label` and pass an `aria-label` on `Switch`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode \| (values: SwitchButtonRenderProps) => React.ReactNode` | - | Button content (control + label), or a button render prop |
|
||||
| `className` | `string \| (values: SwitchButtonRenderProps) => string` | - | Classes applied to the clickable label |
|
||||
|
||||
### SwitchFieldRenderProps
|
||||
|
||||
When using a render prop on the root `Switch`, these field-level values are provided:
|
||||
|
||||
| Prop | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `isSelected` | `boolean` | Whether the switch is currently on |
|
||||
| `isHovered` | `boolean` | Whether the switch is hovered |
|
||||
| `isPressed` | `boolean` | Whether the switch is currently pressed |
|
||||
| `isFocused` | `boolean` | Whether the switch is focused |
|
||||
| `isFocusVisible` | `boolean` | Whether the switch is keyboard focused |
|
||||
| `isDisabled` | `boolean` | Whether the switch is disabled |
|
||||
| `isReadOnly` | `boolean` | Whether the switch is read only |
|
||||
| `state` | `-` | State of the switch. |
|
||||
| `isInvalid` | `boolean` | Whether the switch is invalid |
|
||||
| `isRequired` | `boolean` | Whether the switch is required |
|
||||
| `state` | `ToggleState` | State of the switch |
|
||||
|
||||
### SwitchButtonRenderProps
|
||||
|
||||
`Switch.Control` uses button-level render props (`isHovered`, `isPressed`, `isFocusVisible`, etc.). Pass a function as `Switch.Control` children to access them.
|
||||
|
||||
### SwitchGroup Props
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: Badge
|
||||
icon: updated
|
||||
description: Displays a small indicator positioned relative to another element, commonly used for notification counts, status dots, and labels
|
||||
links:
|
||||
source: badge/badge.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Chip
|
||||
description: Small informational badges for displaying labels, statuses, and categories
|
||||
icon: updated
|
||||
links:
|
||||
source: chip/chip.tsx
|
||||
styles: chip.css
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Calendar
|
||||
description: Composable date picker with month grid, navigation, and year picker support built on React Aria Calendar
|
||||
icon: updated
|
||||
links:
|
||||
rac: Calendar
|
||||
source: calendar/calendar.tsx
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: CheckboxGroup
|
||||
description: A checkbox group component for managing multiple checkbox selections
|
||||
icon: updated
|
||||
links:
|
||||
rac: CheckboxGroup
|
||||
source: checkbox-group/checkbox-group.tsx
|
||||
@@ -32,13 +33,13 @@ export default () => (
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox value="option1">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Label {/* plain text — the clickable label */}
|
||||
</Checkbox.Content>
|
||||
<Description /> {/* Optional per-checkbox help text */}
|
||||
</Checkbox>
|
||||
<FieldError /> {/* Optional */}
|
||||
</CheckboxGroup>
|
||||
@@ -110,11 +111,11 @@ function CustomCheckboxGroup() {
|
||||
return (
|
||||
<CheckboxGroup className="gap-4" name="custom">
|
||||
<Checkbox value="option1">
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Option 1</Label>
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
Option 1
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: Checkbox
|
||||
description: Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.
|
||||
icon: updated
|
||||
links:
|
||||
rac: Checkbox
|
||||
rac: CheckboxField
|
||||
source: checkbox/checkbox.tsx
|
||||
styles: checkbox.css
|
||||
storybook: Components/Forms/Checkbox
|
||||
@@ -12,7 +13,7 @@ links:
|
||||
## Import
|
||||
|
||||
```tsx
|
||||
import { Checkbox, Label } from '@heroui/react';
|
||||
import { Checkbox } from '@heroui/react';
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -26,17 +27,18 @@ import { Checkbox, Label } from '@heroui/react';
|
||||
Import the Checkbox component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Checkbox, Label, Description } from '@heroui/react';
|
||||
import { Checkbox, Description, FieldError } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Checkbox>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label />
|
||||
<Description /> {/* Optional */}
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Label {/* plain text — the clickable label + accessible name */}
|
||||
</Checkbox.Content>
|
||||
<Description /> {/* Optional — field-level help text */}
|
||||
<FieldError /> {/* Optional — validation message */}
|
||||
</Checkbox>
|
||||
);
|
||||
```
|
||||
@@ -65,10 +67,10 @@ export default () => (
|
||||
name="checkbox-indeterminate"
|
||||
/>
|
||||
|
||||
### With Label
|
||||
### External Label
|
||||
|
||||
<ComponentPreview
|
||||
name="checkbox-with-label"
|
||||
name="checkbox-external-label"
|
||||
/>
|
||||
|
||||
### With Description
|
||||
@@ -131,16 +133,16 @@ The Checkbox component supports two visual variants:
|
||||
You can customize individual Checkbox components:
|
||||
|
||||
```tsx
|
||||
import { Checkbox, Label } from '@heroui/react';
|
||||
import { Checkbox } from '@heroui/react';
|
||||
|
||||
function CustomCheckbox() {
|
||||
return (
|
||||
<Checkbox name="custom">
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Custom Checkbox</Label>
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
Custom Checkbox
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
@@ -182,7 +184,7 @@ To customize the Checkbox component classes, you can use the `@layer components`
|
||||
}
|
||||
|
||||
.checkbox__content {
|
||||
@apply flex flex-col gap-1;
|
||||
@apply items-center gap-3;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -193,10 +195,10 @@ HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component va
|
||||
|
||||
The Checkbox component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/checkbox.css)):
|
||||
|
||||
- `.checkbox` - Base checkbox container
|
||||
- `.checkbox` - Base checkbox container (the field)
|
||||
- `.checkbox__content` - Clickable label wrapping the control and label text
|
||||
- `.checkbox__control` - Checkbox control box
|
||||
- `.checkbox__indicator` - Checkbox checkmark indicator
|
||||
- `.checkbox__content` - Optional content container
|
||||
|
||||
### Interactive States
|
||||
|
||||
@@ -205,16 +207,16 @@ The checkbox supports both CSS pseudo-classes and data attributes for flexibilit
|
||||
- **Selected**: `[data-selected="true"]` or `[aria-checked="true"]` (shows checkmark and background color change)
|
||||
- **Indeterminate**: `[data-indeterminate="true"]` (shows indeterminate state with dash)
|
||||
- **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` (shows error state with danger colors)
|
||||
- **Hover**: `:hover` or `[data-hovered="true"]`
|
||||
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` (shows focus ring)
|
||||
- **Disabled**: `:disabled` or `[aria-disabled="true"]` (reduced opacity, no pointer events)
|
||||
- **Hover**: `:hover` or `[data-hovered="true"]` on `Checkbox.Control` (button)
|
||||
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on the button (shows focus ring on control)
|
||||
- **Disabled**: `[data-disabled="true"]` on the field (reduced opacity, including help text)
|
||||
- **Pressed**: `:active` or `[data-pressed="true"]`
|
||||
|
||||
## API Reference
|
||||
|
||||
### Checkbox Props
|
||||
|
||||
Inherits from [React Aria Checkbox](https://react-spectrum.adobe.com/react-aria/Checkbox.html).
|
||||
Inherits from [React Aria CheckboxField](https://react-spectrum.adobe.com/react-aria/Checkbox.html).
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
@@ -224,24 +226,38 @@ Inherits from [React Aria Checkbox](https://react-spectrum.adobe.com/react-aria/
|
||||
| `isDisabled` | `boolean` | `false` | Whether the checkbox is disabled |
|
||||
| `isInvalid` | `boolean` | `false` | Whether the checkbox is invalid |
|
||||
| `isReadOnly` | `boolean` | `false` | Whether the checkbox is read only |
|
||||
| `isRequired` | `boolean` | `false` | Whether the checkbox must be selected |
|
||||
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | Custom validation function |
|
||||
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA |
|
||||
| `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. |
|
||||
| `name` | `string` | - | The name of the input element, used when submitting an HTML form |
|
||||
| `value` | `string` | - | The value of the input element, used when submitting an HTML form |
|
||||
| `onChange` | `(isSelected: boolean) => void` | - | Handler called when the checkbox value changes |
|
||||
| `children` | `React.ReactNode \| (values: CheckboxRenderProps) => React.ReactNode` | - | Checkbox content or render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, CheckboxRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
| `children` | `React.ReactNode \| (values: CheckboxFieldRenderProps) => React.ReactNode` | - | Checkbox content or field render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, CheckboxFieldRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
|
||||
### CheckboxRenderProps
|
||||
### Checkbox.Content Props
|
||||
|
||||
When using the render prop pattern, these values are provided:
|
||||
The clickable `<label>` that wraps the control and label text. Put `Checkbox.Control` and the `Label` inside it; keep `Description`/`FieldError` as siblings of `Checkbox.Content`. For a checkbox with no label, omit the `Label` and pass an `aria-label` on `Checkbox`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode \| (values: CheckboxButtonRenderProps) => React.ReactNode` | - | Button content (control + label), or a button render prop |
|
||||
| `className` | `string \| (values: CheckboxButtonRenderProps) => string` | - | Classes applied to the clickable label |
|
||||
|
||||
### CheckboxFieldRenderProps
|
||||
|
||||
When using a render prop on the root `Checkbox`, these field-level values are provided:
|
||||
|
||||
| Prop | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `isSelected` | `boolean` | Whether the checkbox is currently checked |
|
||||
| `isIndeterminate` | `boolean` | Whether the checkbox is in an indeterminate state |
|
||||
| `isHovered` | `boolean` | Whether the checkbox is hovered |
|
||||
| `isPressed` | `boolean` | Whether the checkbox is currently pressed |
|
||||
| `isFocused` | `boolean` | Whether the checkbox is focused |
|
||||
| `isFocusVisible` | `boolean` | Whether the checkbox is keyboard focused |
|
||||
| `isDisabled` | `boolean` | Whether the checkbox is disabled |
|
||||
| `isReadOnly` | `boolean` | Whether the checkbox is read only |
|
||||
| `isInvalid` | `boolean` | Whether the checkbox is invalid |
|
||||
| `isRequired` | `boolean` | Whether the checkbox is required |
|
||||
|
||||
### CheckboxButtonRenderProps
|
||||
|
||||
`Checkbox.Control` and `Checkbox.Indicator` use button-level render props (`isHovered`, `isPressed`, `isFocusVisible`, etc.). Pass a function as `Checkbox.Control` children or to `Checkbox.Indicator` to access them.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
title: RadioGroup
|
||||
description: Radio group for selecting a single option from a list
|
||||
icon: updated
|
||||
links:
|
||||
rac: RadioGroup
|
||||
rac: RadioField
|
||||
source: radio-group/radio-group.tsx
|
||||
styles: radio-group.css
|
||||
storybook: Components/Forms/RadioGroup
|
||||
@@ -20,7 +21,6 @@ import { RadioGroup, Radio } from '@heroui/react';
|
||||
name="radio-group-basic"
|
||||
/>
|
||||
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import the RadioGroup component and access all parts using dot notation.
|
||||
@@ -33,17 +33,18 @@ export default () => (
|
||||
<Label />
|
||||
<Description />
|
||||
<Radio value="option1">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
<span>✓</span> {/* Custom indicator (optional) */}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label />
|
||||
<Description />
|
||||
<Radio.Content> {/* The clickable area: control + label */}
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
<span>✓</span> {/* Custom indicator (optional) */}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
Label {/* plain text — the clickable label */}
|
||||
</Radio.Content>
|
||||
<Description /> {/* Sibling — stays outside the button (announced via aria-describedby) */}
|
||||
<FieldError /> {/* Optional — per-radio validation message */}
|
||||
</Radio>
|
||||
<FieldError />
|
||||
<FieldError /> {/* Optional — group-level validation */}
|
||||
</RadioGroup>
|
||||
)
|
||||
```
|
||||
@@ -111,7 +112,6 @@ When used inside a [Surface](/docs/components/surface) component, use `variant="
|
||||
name="radio-group-delivery-and-payment"
|
||||
/>
|
||||
|
||||
|
||||
<RelatedShowcases component="RadioGroup" />
|
||||
|
||||
<RelatedComponents component="radiogroup" />
|
||||
@@ -194,6 +194,7 @@ The RadioGroup component uses these CSS classes ([View source styles](https://gi
|
||||
#### Base Classes
|
||||
- `.radio-group` - Base radio group container
|
||||
- `.radio` - Individual radio item
|
||||
- `.radio__content` - Radio button (RAC label wrapper for control + label text)
|
||||
- `.radio__control` - Radio control (circular button)
|
||||
- `.radio__indicator` - Radio indicator (inner dot)
|
||||
- `.radio__content` - Radio content wrapper
|
||||
@@ -238,8 +239,8 @@ The radio supports both CSS pseudo-classes and data attributes for flexibility:
|
||||
| `value` | `string` | - | The value of the radio button |
|
||||
| `isDisabled` | `boolean` | `false` | Whether the radio button is disabled |
|
||||
| `name` | `string` | - | The name of the radio button, used when submitting an HTML form |
|
||||
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | Radio content or render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
| `children` | `React.ReactNode \| (values: RadioFieldRenderProps) => React.ReactNode` | - | Radio content or field render prop |
|
||||
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioFieldRenderProps>` | - | Overrides the default DOM element with a custom render function.|
|
||||
|
||||
### Radio.Control Props
|
||||
|
||||
@@ -255,27 +256,28 @@ Extends `React.HTMLAttributes<HTMLSpanElement>`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode \| (values: RadioRenderProps) => React.ReactNode` | - | Optional content or render prop that receives the current radio state. |
|
||||
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | Optional content or render prop that receives the current radio button state. |
|
||||
|
||||
### Radio.Content Props
|
||||
|
||||
Extends `React.HTMLAttributes<HTMLDivElement>`.
|
||||
The clickable area of the radio (the `<label>` wrapping the hidden input). Place `Radio.Control` and the `Label` inside it. `className` accepts a render function that receives `RadioButtonRenderProps`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode` | - | The content to render inside the content wrapper (typically Label and Description) |
|
||||
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | The clickable content (typically Radio.Control and Label) |
|
||||
|
||||
### RadioRenderProps
|
||||
### RadioFieldRenderProps
|
||||
|
||||
When using the render prop pattern, these values are provided:
|
||||
When using a render prop on the root `Radio`, these field-level values are provided:
|
||||
|
||||
| Prop | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `isSelected` | `boolean` | Whether the radio is currently selected |
|
||||
| `isHovered` | `boolean` | Whether the radio is hovered |
|
||||
| `isPressed` | `boolean` | Whether the radio is currently pressed |
|
||||
| `isFocused` | `boolean` | Whether the radio is focused |
|
||||
| `isFocusVisible` | `boolean` | Whether the radio is keyboard focused |
|
||||
| `isDisabled` | `boolean` | Whether the radio is disabled |
|
||||
| `isReadOnly` | `boolean` | Whether the radio is read only |
|
||||
| `isInvalid` | `boolean` | Whether the radio is in an invalid state |
|
||||
| `isRequired` | `boolean` | Whether the radio is required |
|
||||
|
||||
### RadioButtonRenderProps
|
||||
|
||||
`Radio.Control` and `Radio.Indicator` use button-level render props (`isHovered`, `isPressed`, `isFocusVisible`, etc.). Pass a function as `Radio.Control` children or to `Radio.Indicator` to access them.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: TextField
|
||||
description: Composition-friendly text fields with labels, descriptions, and inline validation
|
||||
icon: updated
|
||||
links:
|
||||
rac: TextField
|
||||
source: textfield/textfield.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Autocomplete
|
||||
description: An autocomplete combines a select with filtering, allowing users to search and select from a list of options
|
||||
icon: updated
|
||||
links:
|
||||
rac: Select
|
||||
source: autocomplete/autocomplete.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Typography
|
||||
description: A semantic typography primitive for headings, body copy, and inline code built on React Aria Components Text.
|
||||
icon: new
|
||||
links:
|
||||
source: typography/typography.tsx
|
||||
styles: typography.css
|
||||
|
||||
@@ -35,27 +35,27 @@ export default function App() {
|
||||
<CheckboxGroup name="interests">
|
||||
<Label>Select interests</Label>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Coding</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Coding
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Design</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Design
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Writing</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Writing
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -78,7 +78,7 @@ export default function App() {
|
||||
### 3. Checkbox Structure
|
||||
|
||||
**v2:** Simple Checkbox components with children as labels
|
||||
**v3:** Compound Checkbox components with `Checkbox.Control`, `Checkbox.Indicator`, and `Checkbox.Content`
|
||||
**v3:** Compound Checkbox components with `Checkbox.Content`, `Checkbox.Control`, and `Checkbox.Indicator`
|
||||
|
||||
### 4. Event Handler
|
||||
|
||||
@@ -126,27 +126,27 @@ export default function App() {
|
||||
>
|
||||
<Label>Select interests</Label>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Coding</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Coding
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Design</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Design
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Writing</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Writing
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -157,7 +157,7 @@ export default function App() {
|
||||
## Summary
|
||||
|
||||
- Keep using `CheckboxGroup`; replace `label` prop with `Label` component as a child
|
||||
- Update Checkbox children to use compound component structure (`Checkbox.Control`, `Checkbox.Indicator`, `Checkbox.Content`)
|
||||
- Update Checkbox children to use compound component structure (`Checkbox.Content`, `Checkbox.Control`, `Checkbox.Indicator`)
|
||||
- Change `onValueChange` to `onChange`
|
||||
- Add `name` prop for form integration
|
||||
- Built on React Aria Components for accessibility
|
||||
|
||||
@@ -27,11 +27,11 @@ import { Checkbox, Label } from "@heroui/react";
|
||||
export default function App() {
|
||||
return (
|
||||
<Checkbox defaultSelected id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
@@ -43,12 +43,12 @@ export default function App() {
|
||||
### 1. Component Structure
|
||||
|
||||
**v2:** Simple component with children as label
|
||||
**v3:** Compound components: `Checkbox.Control`, `Checkbox.Indicator`, `Checkbox.Content`
|
||||
**v3:** Compound components: `Checkbox.Content`, `Checkbox.Control`, `Checkbox.Indicator`
|
||||
|
||||
### 2. Label Handling
|
||||
|
||||
**v2:** Label passed as children directly to `Checkbox`
|
||||
**v3:** Label must be wrapped in `Checkbox.Content` using the `Label` component
|
||||
**v3:** Label goes inside `Checkbox.Content` (the clickable label); `Description`/`FieldError` are siblings of `Checkbox.Content`
|
||||
|
||||
### 3. Prop Changes
|
||||
|
||||
@@ -95,11 +95,11 @@ For migrating checkbox groups, see the [CheckboxGroup migration guide](/docs/rea
|
||||
const [isSelected, setIsSelected] = useState(false);
|
||||
|
||||
<Checkbox id="subscribe" isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="subscribe">Subscribe</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Subscribe
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -123,13 +123,13 @@ For migrating checkbox groups, see the [CheckboxGroup migration guide](/docs/rea
|
||||
import { Checkbox, Label, Description } from "@heroui/react";
|
||||
|
||||
<Checkbox id="option" defaultSelected>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Description>Description text</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
<Description>Description text</Description>
|
||||
</Checkbox>
|
||||
```
|
||||
</Tab>
|
||||
@@ -157,27 +157,27 @@ For migrating checkbox groups, see the [CheckboxGroup migration guide](/docs/rea
|
||||
<Label>Select cities</Label>
|
||||
<Description>Choose all that apply</Description>
|
||||
<Checkbox value="buenos-aires">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Buenos Aires</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Buenos Aires
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="sydney">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Sydney</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Sydney
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="san-francisco">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>San Francisco</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
San Francisco
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
@@ -201,21 +201,21 @@ For migrating checkbox groups, see the [CheckboxGroup migration guide](/docs/rea
|
||||
```tsx
|
||||
{/* Colors - use Tailwind classes */}
|
||||
<Checkbox defaultSelected id="primary">
|
||||
<Checkbox.Control className="data-[selected=true]:bg-primary data-[selected=true]:border-primary">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="primary">Primary</Label>
|
||||
<Checkbox.Control className="data-[selected=true]:bg-primary data-[selected=true]:border-primary">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Primary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
{/* Sizes - use Tailwind classes */}
|
||||
<Checkbox defaultSelected id="medium">
|
||||
<Checkbox.Control className="size-5">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="medium">Medium</Label>
|
||||
<Checkbox.Control className="size-5">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Medium
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -235,13 +235,13 @@ For migrating checkbox groups, see the [CheckboxGroup migration guide](/docs/rea
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Checkbox defaultSelected id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) => isSelected ? <HeartIcon /> : null}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) => isSelected ? <HeartIcon /> : null}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -255,21 +255,21 @@ v3 introduces a `variant` prop with `"primary"` (default) and `"secondary"` opti
|
||||
```tsx
|
||||
{/* Primary variant (default) */}
|
||||
<Checkbox variant="primary" id="primary-option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="primary-option">Primary</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Primary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
{/* Secondary variant - lower emphasis, suitable for Surface components */}
|
||||
<Checkbox variant="secondary" id="secondary-option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="secondary-option">Secondary</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Secondary
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -285,11 +285,11 @@ v3 introduces a `variant` prop with `"primary"` (default) and `"secondary"` opti
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Checkbox isIndeterminate id="option">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="option">Option</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Option
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -304,13 +304,13 @@ v3 Checkbox supports a render prop pattern that provides state information:
|
||||
<Checkbox id="terms">
|
||||
{({isSelected, isIndeterminate, isHovered, isPressed, isFocused, isDisabled}) => (
|
||||
<>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="terms">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
|
||||
{isSelected ? "Terms accepted" : "Accept terms"}
|
||||
</Label>
|
||||
|
||||
</Checkbox.Content>
|
||||
</>
|
||||
)}
|
||||
@@ -321,15 +321,15 @@ v3 Checkbox supports a render prop pattern that provides state information:
|
||||
|
||||
```tsx
|
||||
<Checkbox id="custom">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected, isIndeterminate}) =>
|
||||
isIndeterminate ? <MinusIcon /> : isSelected ? <CheckIcon /> : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="custom">Custom indicator</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected, isIndeterminate}) =>
|
||||
isIndeterminate ? <MinusIcon /> : isSelected ? <CheckIcon /> : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
Custom indicator
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -363,13 +363,13 @@ Available render props:
|
||||
|
||||
```tsx
|
||||
<Checkbox className="custom-base" id="option">
|
||||
<Checkbox.Control className="custom-control">
|
||||
<Checkbox.Indicator className="custom-indicator" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content className="custom-content">
|
||||
<Label htmlFor="option" className="custom-label">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control className="custom-control">
|
||||
<Checkbox.Indicator className="custom-indicator" />
|
||||
</Checkbox.Control>
|
||||
|
||||
Option
|
||||
</Label>
|
||||
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
```
|
||||
@@ -380,17 +380,18 @@ The v3 Checkbox follows this structure:
|
||||
|
||||
```
|
||||
Checkbox (Root)
|
||||
├── Checkbox.Control
|
||||
│ └── Checkbox.Indicator
|
||||
└── Checkbox.Content (optional)
|
||||
├── Label (required if using Content)
|
||||
└── Description (optional)
|
||||
├── Checkbox.Content (the clickable label)
|
||||
│ ├── Checkbox.Control
|
||||
│ │ └── Checkbox.Indicator
|
||||
│ └── Label
|
||||
├── Description (optional, sibling)
|
||||
└── FieldError (optional, sibling)
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
1. **Component Structure**: Must use compound components (`Control`, `Indicator`, `Content`)
|
||||
2. **Label Handling**: Labels must use `Label` component inside `Checkbox.Content`
|
||||
1. **Component Structure**: Must use compound components (`Button`, `Control`, `Indicator`)
|
||||
2. **Label Handling**: Labels go inside `Checkbox.Content`
|
||||
3. **onValueChange → onChange**: Event handler prop renamed
|
||||
4. **Color Removed**: Use Tailwind CSS classes on `Checkbox.Control`
|
||||
5. **Size Removed**: Use Tailwind CSS classes on `Checkbox.Control`
|
||||
|
||||
@@ -35,28 +35,28 @@ export default function App() {
|
||||
<RadioGroup name="city">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Description>Capital of Japan</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
<Description>Capital of Japan</Description>
|
||||
</Radio>
|
||||
<Radio value="paris">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Paris</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Paris
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -74,12 +74,12 @@ export default function App() {
|
||||
### 2. Radio Structure
|
||||
|
||||
**v2:** Simple Radio components with children as labels
|
||||
**v3:** Compound Radio components with `Radio.Control`, `Radio.Indicator`, and `Radio.Content`
|
||||
**v3:** Compound Radio components with `Radio.Content`, `Radio.Control`, and `Radio.Indicator`
|
||||
|
||||
### 3. Description Handling
|
||||
|
||||
**v2:** Used `description` prop on individual `Radio` components
|
||||
**v3:** Use `Description` component inside `Radio.Content`
|
||||
**v3:** Use `Description` component as a sibling of `Radio.Content`
|
||||
|
||||
### 4. Event Handler
|
||||
|
||||
@@ -118,22 +118,22 @@ export default function App() {
|
||||
<RadioGroup name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Description>Basic features</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
<Description>Basic features</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Pro</Label>
|
||||
<Description>All features</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Pro
|
||||
</Radio.Content>
|
||||
<Description>All features</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
```
|
||||
@@ -160,11 +160,11 @@ export default function App() {
|
||||
<RadioGroup variant="primary" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -173,11 +173,11 @@ export default function App() {
|
||||
<RadioGroup variant="secondary" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -194,19 +194,19 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
<RadioGroup isReadOnly defaultValue="basic" name="plan">
|
||||
<Label>Select plan</Label>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Basic</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Basic
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Pro</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Pro
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -238,19 +238,19 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
<RadioGroup name="city" value={value} onChange={setValue}>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -262,7 +262,7 @@ import { RadioGroup, Radio, Label } from "@heroui/react";
|
||||
|
||||
- Replace `label` prop with `Label` component as child
|
||||
- Update Radio children to use compound component structure
|
||||
- Replace `description` prop on Radio with `Description` component inside `Radio.Content`
|
||||
- Replace `description` prop on Radio with `Description` component as a sibling of `Radio.Content`
|
||||
- Change `onValueChange` to `onChange`
|
||||
- Add `name` prop for form integration
|
||||
- New `variant` prop: `"primary"` (default) or `"secondary"` for lower emphasis styling
|
||||
|
||||
@@ -34,21 +34,21 @@ export default function App() {
|
||||
<RadioGroup>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Description>Capital of Japan</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
<Description>Capital of Japan</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
@@ -60,7 +60,7 @@ export default function App() {
|
||||
### 1. Component Structure
|
||||
|
||||
**v2:** Simple Radio with children as label
|
||||
**v3:** Compound components: `Radio.Control`, `Radio.Indicator`, `Radio.Content`
|
||||
**v3:** Compound components: `Radio.Content`, `Radio.Control`, `Radio.Indicator`
|
||||
|
||||
### 2. Prop Changes
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function App() {
|
||||
|---------|-------------|-------|
|
||||
| `onValueChange` | `onChange` | Renamed event handler |
|
||||
| `label` (on RadioGroup) | — | Use `Label` component |
|
||||
| `description` (on Radio) | — | Use `Description` component inside `Radio.Content` |
|
||||
| `description` (on Radio) | — | Use `Description` component as a sibling of `Radio.Content` |
|
||||
| `size` | — | Removed (use Tailwind CSS) |
|
||||
| `color` | — | Removed (use Tailwind CSS) |
|
||||
| `classNames` | — | Use `className` props on individual components |
|
||||
@@ -108,13 +108,13 @@ export default function App() {
|
||||
<RadioGroup>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Description>Capital of England</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
<Description>Capital of England</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
@@ -122,11 +122,11 @@ export default function App() {
|
||||
<RadioGroup isInvalid>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<FieldError>Please select an option</FieldError>
|
||||
@@ -162,19 +162,19 @@ export default function App() {
|
||||
<RadioGroup value={selected} onChange={setSelected}>
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -198,19 +198,19 @@ export default function App() {
|
||||
<RadioGroup orientation="horizontal">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -227,11 +227,11 @@ v3 introduces a `variant` prop on `RadioGroup` with `"primary"` (default) and `"
|
||||
<RadioGroup variant="primary">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -240,11 +240,11 @@ v3 introduces a `variant` prop on `RadioGroup` with `"primary"` (default) and `"
|
||||
<RadioGroup variant="secondary">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -258,19 +258,19 @@ v3 supports `isReadOnly` on `RadioGroup`, which prevents value changes while kee
|
||||
<RadioGroup isReadOnly defaultValue="london">
|
||||
<Label>Select city</Label>
|
||||
<Radio value="london">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>London</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
London
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="tokyo">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Tokyo</Label>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Tokyo
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
@@ -284,19 +284,19 @@ The v3 Radio follows this structure:
|
||||
RadioGroup (Root)
|
||||
├── Label (optional)
|
||||
├── Radio
|
||||
│ ├── Radio.Control
|
||||
│ │ └── Radio.Indicator
|
||||
│ └── Radio.Content
|
||||
│ ├── Label
|
||||
│ └── Description (optional)
|
||||
│ ├── Radio.Content (the clickable label)
|
||||
│ │ ├── Radio.Control
|
||||
│ │ │ └── Radio.Indicator
|
||||
│ │ └── Label
|
||||
│ └── Description (optional, sibling)
|
||||
└── FieldError (optional)
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
1. **Component Structure**: Must use compound components (`Radio.Control`, `Radio.Indicator`, `Radio.Content`)
|
||||
1. **Component Structure**: Must use compound components (`Radio.Content`, `Radio.Control`, `Radio.Indicator`)
|
||||
2. **Label Handling**: `label` prop removed - use `Label` component
|
||||
3. **Description Handling**: `description` prop removed - use `Description` component inside `Radio.Content`
|
||||
3. **Description Handling**: `description` prop removed - use `Description` component as a sibling of `Radio.Content`
|
||||
4. **Event Handler**: `onValueChange` → `onChange`
|
||||
5. **Styling Props Removed**: `size`, `color` - use Tailwind CSS
|
||||
6. **ClassNames Removed**: Use `className` props on individual components
|
||||
|
||||
@@ -27,11 +27,11 @@ import { Switch, Label } from "@heroui/react";
|
||||
export default function App() {
|
||||
return (
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
);
|
||||
@@ -43,7 +43,7 @@ export default function App() {
|
||||
### 1. Component Structure
|
||||
|
||||
**v2:** Simple Switch with children as label
|
||||
**v3:** Compound components (`Switch.Control`, `Switch.Thumb`, `Switch.Content`) with `Label` component
|
||||
**v3:** Compound components (`Switch.Content`, `Switch.Control`, `Switch.Thumb`) with `Label` component
|
||||
|
||||
### 2. Prop Changes
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function App() {
|
||||
### 3. New Components
|
||||
|
||||
- `SwitchGroup` - For grouping multiple switches
|
||||
- `Switch.Content` - Container for label and description
|
||||
- `Switch.Content` - The clickable label wrapping the control and `Label`
|
||||
- `Switch.Icon` - For icons inside the thumb
|
||||
|
||||
## Migration Examples
|
||||
@@ -88,11 +88,11 @@ export default function App() {
|
||||
const [isSelected, setIsSelected] = useState(true);
|
||||
|
||||
<Switch isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Airplane mode</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Airplane mode
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -110,9 +110,11 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch defaultSelected aria-label="Automatic updates">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
</Tab>
|
||||
@@ -129,15 +131,15 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon>
|
||||
<CheckIcon />
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon>
|
||||
<CheckIcon />
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -160,13 +162,13 @@ export default function App() {
|
||||
<Tab value="v3">
|
||||
```tsx
|
||||
<Switch>
|
||||
<Switch.Control className="flex items-center gap-2">
|
||||
<SunIcon />
|
||||
<Switch.Thumb />
|
||||
<MoonIcon />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Dark mode</Label>
|
||||
<Switch.Control className="flex items-center gap-2">
|
||||
<SunIcon />
|
||||
<Switch.Thumb />
|
||||
<MoonIcon />
|
||||
</Switch.Control>
|
||||
Dark mode
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -188,13 +190,13 @@ export default function App() {
|
||||
import { Switch, Label, Description } from "@heroui/react";
|
||||
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
<Description>You will receive notifications for all activity</Description>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
<Description>You will receive notifications for all activity</Description>
|
||||
</Switch>
|
||||
```
|
||||
</Tab>
|
||||
@@ -223,54 +225,54 @@ export default function App() {
|
||||
{/* Sizes */}
|
||||
<div className="flex gap-4">
|
||||
<Switch size="sm">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Small</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Small
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch size="md">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Medium</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Medium
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch size="lg">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Large</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Large
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
{/* Colors - Use Tailwind CSS classes */}
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-accent">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Primary</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-accent">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Primary
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-success">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Success</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-success">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Success
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch>
|
||||
<Switch.Control className="data-[selected=true]:bg-danger">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Danger</Label>
|
||||
<Switch.Control className="data-[selected=true]:bg-danger">
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Danger
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
@@ -295,19 +297,19 @@ export default function App() {
|
||||
|
||||
<SwitchGroup>
|
||||
<Switch name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Allow Notifications</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Allow Notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Marketing emails</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Marketing emails
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</SwitchGroup>
|
||||
@@ -321,12 +323,13 @@ The v3 Switch follows this structure:
|
||||
|
||||
```
|
||||
Switch (Root)
|
||||
├── Switch.Control
|
||||
│ └── Switch.Thumb
|
||||
│ └── Switch.Icon (optional)
|
||||
└── Switch.Content (optional)
|
||||
├── Label (optional)
|
||||
└── Description (optional)
|
||||
├── Switch.Content (the clickable label)
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ │ └── Switch.Icon (optional)
|
||||
│ └── Label
|
||||
├── Description (optional, sibling)
|
||||
└── FieldError (optional, sibling)
|
||||
```
|
||||
|
||||
For groups:
|
||||
@@ -334,17 +337,17 @@ For groups:
|
||||
```
|
||||
SwitchGroup
|
||||
├── Switch
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ └── Switch.Content
|
||||
│ ├── Label
|
||||
│ └── Description (optional)
|
||||
│ ├── Switch.Content
|
||||
│ │ ├── Switch.Control
|
||||
│ │ │ └── Switch.Thumb
|
||||
│ │ └── Label
|
||||
│ └── Description (optional)
|
||||
└── Switch
|
||||
├── Switch.Control
|
||||
│ └── Switch.Thumb
|
||||
└── Switch.Content
|
||||
├── Label
|
||||
└── Description (optional)
|
||||
├── Switch.Content
|
||||
│ ├── Switch.Control
|
||||
│ │ └── Switch.Thumb
|
||||
│ └── Label
|
||||
└── Description (optional)
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
@@ -357,7 +360,7 @@ SwitchGroup
|
||||
### Label Handling
|
||||
|
||||
- **v2:** Children were used as label
|
||||
- **v3:** Use `Label` component inside `Switch.Content`; optionally add `Description` alongside it
|
||||
- **v3:** Label goes inside `Switch.Content` (the clickable label); `Description`/`FieldError` are siblings of `Switch.Content`
|
||||
|
||||
### Icons
|
||||
|
||||
@@ -366,11 +369,11 @@ SwitchGroup
|
||||
|
||||
## Summary
|
||||
|
||||
1. **Component Structure**: Must use compound components (`Switch.Control`, `Switch.Thumb`, `Switch.Content`)
|
||||
2. **Content Container**: Use `Switch.Content` to wrap `Label` and `Description` for proper layout
|
||||
1. **Component Structure**: Must use compound components (`Switch.Content`, `Switch.Control`, `Switch.Thumb`)
|
||||
2. **Clickable Label**: Use `Switch.Content` to wrap `Switch.Control` and `Label`; place `Description`/`FieldError` as siblings of `Switch.Content`
|
||||
3. **Label Handling**: Children no longer used as label - use `Label` component inside `Switch.Content`
|
||||
4. **Event Handler**: `onValueChange` → `onChange`
|
||||
5. **Styling Props Removed**: `color` - use Tailwind CSS
|
||||
6. **Icon Props Removed**: `thumbIcon`, `startContent`, `endContent` - use components or customize directly
|
||||
7. **ClassNames Removed**: Use `className` props on individual components
|
||||
8. **New Components**: `SwitchGroup` for grouping switches, `Switch.Content` for label/description container
|
||||
8. **New Components**: `SwitchGroup` for grouping switches, `Switch.Content` as the clickable label wrapping the control and `Label`
|
||||
|
||||
@@ -9,6 +9,16 @@ description: All updates and changes to HeroUI v3, including new features, fixes
|
||||
|
||||
## Latest Release
|
||||
|
||||
### v3.2.0
|
||||
|
||||
**June 6, 2026**
|
||||
|
||||
Calendar week and day views, a reworked year picker, and range demos on React Aria 1.18, plus tooltip delay theme variables and the patch fixes shipped with it. Breaking: `Radio`, `Checkbox`, and `Switch` move to an explicit `*.Content` composition (control nests inside `*.Content`; the label is plain text, no nested `<Label>`; help text becomes a sibling).
|
||||
|
||||
[Read full release notes →](/docs/react/releases/v3-2-0)
|
||||
|
||||
---
|
||||
|
||||
### v3.1.0
|
||||
|
||||
**May 25, 2026**
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"---Overview---",
|
||||
"index",
|
||||
"---Releases---",
|
||||
"v3-2-0",
|
||||
"v3-1-0",
|
||||
"v3-0-5",
|
||||
"v3-0-4",
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: v3.2.0
|
||||
description: Calendar week/day views and year picker on React Aria 1.18, plus breaking Radio, Checkbox, and Switch composition changes.
|
||||
github:
|
||||
pull: 6616
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-muted">June 6, 2026</span>
|
||||
</div>
|
||||
|
||||
Calendar gains week and day views, a reworked year picker, and range demos built on React Aria 1.18. [Tooltip](/docs/components/tooltip) adds theme variables for global show and hide delays. The toggles (`Radio`, `Checkbox`, `Switch`) move to React Aria's `*Field` + `*Button` composition. This release also rolls in the patch fixes shipped alongside React Aria 1.18 (`Table.SortableColumnHeader`, toast and fieldset fixes, scroll and RTL style fixes).
|
||||
|
||||
⚠️ **Breaking changes**: `Radio`, `Checkbox`, and `Switch` move to an explicit `*.Content` composition — `*.Control` nests inside `*.Content`, the label is plain text inside `*.Content` (no nested `<Label>`), and `Description`/`FieldError` become siblings of `*.Content`. See [Breaking Changes](#-breaking-changes).
|
||||
|
||||
## Installation
|
||||
|
||||
Update to the latest version:
|
||||
|
||||
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
|
||||
<Tab value="npm">
|
||||
```bash
|
||||
npm i @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="pnpm">
|
||||
```bash
|
||||
pnpm add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="yarn">
|
||||
```bash
|
||||
yarn add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="bun">
|
||||
```bash
|
||||
bun add @heroui/styles@latest @heroui/react@latest
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Callout type="info">
|
||||
**Using AI assistants?** Prompt "Hey Cursor, update HeroUI to the latest version" and your AI assistant will compare versions and apply the necessary changes. Learn more about the [HeroUI MCP Server](/docs/ui-for-agents/mcp-server).
|
||||
</Callout>
|
||||
|
||||
## What's New
|
||||
|
||||
### Calendar
|
||||
|
||||
`Calendar` and `RangeCalendar` gain week and day views, plus new React Aria 1.18 calendar props.
|
||||
|
||||
- **Week / day views**: `visibleDuration` renders multi-week or single-day layouts
|
||||
- **Multiple selection**: select several dates in a single `Calendar`
|
||||
- **React Aria 1.18 props**: `weeksInMonth` and `isDateUnavailable(date, anchorDate)` for ranges
|
||||
- **Internals**: month labels use React Aria's `CalendarHeading`, and the year picker is rebuilt on React Aria calendar hooks
|
||||
|
||||
**Week view:**
|
||||
|
||||
<ComponentPreview name="calendar-week-view" />
|
||||
|
||||
**Day view:**
|
||||
|
||||
<ComponentPreview name="calendar-day-view" />
|
||||
|
||||
**Multiple selection:**
|
||||
|
||||
<ComponentPreview name="calendar-multiple-selection" />
|
||||
|
||||
**Multiple selection:**
|
||||
|
||||
<ComponentPreview name="calendar-multiple-selection" />
|
||||
|
||||
### Table.SortableColumnHeader
|
||||
|
||||
`Table.SortableColumnHeader` renders a sortable column label with an optional ascending/descending indicator. Use it inside a `Table.Column` render prop and forward `sortDirection` ([#6588](https://github.com/heroui-inc/heroui/pull/6588)).
|
||||
|
||||
```tsx
|
||||
<Table.Column allowsSorting>
|
||||
{({sortDirection}) => (
|
||||
<Table.SortableColumnHeader sortDirection={sortDirection}>
|
||||
Name
|
||||
</Table.SortableColumnHeader>
|
||||
)}
|
||||
</Table.Column>
|
||||
```
|
||||
|
||||
- **Default indicator**: Chevron appears when a sort direction exists
|
||||
- **Custom indicator**: Pass `indicator`, or hide it with `showIndicator={false}`
|
||||
- **Style slots**: `.table__sortable-column-header` + `.table__sortable-column-indicator`
|
||||
|
||||
<ComponentPreview name="table-sorting" />
|
||||
|
||||
### Tooltip delay theme variables
|
||||
|
||||
[Tooltip](/docs/components/tooltip) reads default show and hide delays from theme CSS variables ([#6617](https://github.com/heroui-inc/heroui/pull/6617)):
|
||||
|
||||
- `--tooltip-delay` — delay before showing a tooltip (default: `1500ms`)
|
||||
- `--tooltip-close-delay` — delay before hiding a tooltip (default: `500ms`)
|
||||
|
||||
Override them globally:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--tooltip-delay: 700ms;
|
||||
--tooltip-close-delay: 0ms;
|
||||
}
|
||||
```
|
||||
|
||||
Individual `delay` and `closeDelay` props still override these values on specific tooltips.
|
||||
|
||||
<Callout type="warning">
|
||||
**Behavior change:** With the default HeroUI theme, tooltip delays now default to `1500ms` / `500ms` instead of the previous React Aria defaults of `700ms` / `0ms`. Set the CSS variables or props explicitly to preserve the old timing.
|
||||
</Callout>
|
||||
|
||||
## Component Fixes
|
||||
|
||||
- **Toast**: ViewTransition updates are serialized in the toast queue, preventing skipped transitions and AbortError rejections when `toast.promise()` swaps the loading toast for success/error feedback ([#6511](https://github.com/heroui-inc/heroui/pull/6511)).
|
||||
- **Fieldset**: `disabled` propagates through React Aria Button, CheckboxGroup, Link, RadioGroup, Slider, ToggleButton, and ToggleButtonGroup contexts ([#6596](https://github.com/heroui-inc/heroui/pull/6596)).
|
||||
|
||||
## Style Fixes
|
||||
|
||||
- **Modal / AlertDialog**: `scroll-inside` dialogs cap height with `max-h-full min-h-0` so the body scrolls instead of overflowing ([#6597](https://github.com/heroui-inc/heroui/pull/6597)).
|
||||
- **ScrollShadow**: Fade masks reserve space for visible native scrollbars via `--scroll-shadow-scrollbar-size` ([#6598](https://github.com/heroui-inc/heroui/pull/6598)).
|
||||
- **Table RTL**: Column separators and resize handles use logical `end-0` positioning in RTL ([#6606](https://github.com/heroui-inc/heroui/pull/6606)).
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **React Aria Components**: `1.17.0` → `1.18.0` ([#6586](https://github.com/heroui-inc/heroui/pull/6586)). 1.18 adds the `*Field` + `*Button` composition adopted by the toggles, `CalendarHeading`, and `isDateUnavailable(date, anchorDate)`.
|
||||
- **@internationalized/date**: `3.12.1` → `3.12.2`
|
||||
- **React Aria / Stately helpers**: `@react-aria/*`, `@react-stately/*`, and `@react-types/shared` patch updates
|
||||
|
||||
## ⚠️ Breaking Changes
|
||||
|
||||
### Radio, Checkbox & Switch: explicit `*.Content` composition
|
||||
|
||||
These toggles now use React Aria's `*Field` + `*Button` composition under the hood. `X.Content` is now the **clickable label** (React Aria's `*Button`). Three things change:
|
||||
|
||||
- **`X.Control` moves inside `X.Content`** — they used to be siblings.
|
||||
- **The label is plain text inside `X.Content`** — `X.Content` renders the `<label>` element, so don't nest a `<Label>` component (nested `<label>` elements are invalid HTML). For a standalone `Label`, place it **outside** and link it with `htmlFor` + the toggle `id`.
|
||||
- **`Description`/`FieldError` move out** as siblings of `X.Content`, so they're exposed via `aria-describedby` instead of being folded into the accessible name.
|
||||
|
||||
**Checkbox**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Checkbox>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>Accept terms</Label>
|
||||
<Description>You agree to our terms</Description>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
// v3.2
|
||||
<Checkbox>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
Accept terms
|
||||
</Checkbox.Content>
|
||||
<Description>You agree to our terms</Description>
|
||||
</Checkbox>
|
||||
```
|
||||
|
||||
**Radio**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Radio value="a">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>Option A</Label>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
|
||||
// v3.2
|
||||
<Radio value="a">
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
Option A
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
```
|
||||
|
||||
**Switch**
|
||||
|
||||
```tsx
|
||||
// v3.1
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Label>Enable notifications</Label>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
|
||||
// v3.2
|
||||
<Switch>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
Enable notifications
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
```
|
||||
|
||||
**Migration summary**
|
||||
|
||||
| v3.1 | v3.2 |
|
||||
|------|------|
|
||||
| `X.Control` and `X.Content` are siblings | `X.Control` nests inside `X.Content` |
|
||||
| `X.Content` is a layout `<div>` wrapping `Label` + help text | `X.Content` is the clickable `<label>` wrapping `X.Control` + label text |
|
||||
| Label provided via `<Label>` inside `X.Content` | Label is **plain text** inside `X.Content` (no nested `<Label>`) |
|
||||
| `Description` / `FieldError` inside `X.Content` | `Description` / `FieldError` as siblings of `X.Content` |
|
||||
|
||||
**External label** — to use a standalone `Label`, place it outside the toggle and link it with `htmlFor` + the toggle `id`:
|
||||
|
||||
```tsx
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="terms">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label htmlFor="terms">Accept terms</Label>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Control-only checkboxes and switches** (no label, e.g. table row selection or icon switches) still need `X.Content` as the clickable wrapper. Wrap `Checkbox.Control` / `Switch.Control` in `X.Content`, omit the label, and pass an `aria-label` on the root.
|
||||
|
||||
Full per-component guides: [Checkbox](/docs/react/migration/checkbox), [Checkbox Group](/docs/react/migration/checkbox-group), [Radio](/docs/react/migration/radio), [Radio Group](/docs/react/migration/radio-group), and [Switch](/docs/react/migration/switch).
|
||||
|
||||
## Links
|
||||
|
||||
- [Calendar Docs](/docs/react/components/calendar)
|
||||
- [Tooltip Docs](/docs/react/components/tooltip)
|
||||
- [Checkbox Docs](/docs/react/components/checkbox)
|
||||
- [Radio Group Docs](/docs/react/components/radio-group)
|
||||
- [Switch Docs](/docs/react/components/switch)
|
||||
- [Component Docs](/docs/react/components)
|
||||
- [GitHub Repository](https://github.com/heroui-inc/heroui)
|
||||
- [GitHub PR #6616](https://github.com/heroui-inc/heroui/pull/6616)
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks to everyone who contributed to this release!
|
||||
|
||||
<PRContributors />
|
||||
@@ -0,0 +1,106 @@
|
||||
"use client";
|
||||
|
||||
import {Rocket} from "@gravity-ui/icons";
|
||||
import LinkRoot from "fumadocs-core/link";
|
||||
import {AnimatePresence, animate, motion, useMotionValue, useReducedMotion} from "motion/react";
|
||||
import {useEffect, useState} from "react";
|
||||
|
||||
interface ReleaseBadge {
|
||||
label: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
interface ReleaseBadgesProps {
|
||||
badges: ReleaseBadge[];
|
||||
/** Autoplay interval in milliseconds. */
|
||||
intervalMs?: number;
|
||||
}
|
||||
|
||||
// Soft, fluid settle for the badge slide (Apple-style spring, minimal bounce).
|
||||
const slideSpring = {bounce: 0.18, type: "spring", visualDuration: 0.4} as const;
|
||||
// Quick ease-out fade so opacity never lingers behind the movement.
|
||||
const fadeOut = {duration: 0.22, ease: [0.215, 0.61, 0.355, 1]} as const;
|
||||
|
||||
function BadgePill({badge}: {badge: ReleaseBadge}) {
|
||||
return (
|
||||
<LinkRoot
|
||||
className="flex items-center gap-1 rounded-full bg-accent-soft px-2 py-1 text-xs text-accent-soft-foreground transition-colors hover:bg-accent-soft-hover"
|
||||
href={badge.href}
|
||||
>
|
||||
<Rocket className="size-3 shrink-0 text-accent-soft-foreground" />
|
||||
<span className="max-w-60 truncate sm:max-w-full">{badge.label}</span>
|
||||
</LinkRoot>
|
||||
);
|
||||
}
|
||||
|
||||
export function ReleaseBadges({badges, intervalMs = 5000}: ReleaseBadgesProps) {
|
||||
const reduceMotion = useReducedMotion() ?? false;
|
||||
const [index, setIndex] = useState(0);
|
||||
const [paused, setPaused] = useState(false);
|
||||
const progress = useMotionValue(0);
|
||||
const count = badges.length;
|
||||
|
||||
// Autoplay: drive a single progress value (transform-only fill) and advance
|
||||
// on completion. Stopping retains the value, so hover/focus pause + resume
|
||||
// and manual jumps stay in sync and interruptible.
|
||||
useEffect(() => {
|
||||
if (count <= 1 || paused) return;
|
||||
|
||||
if (reduceMotion) {
|
||||
const id = setInterval(() => setIndex((i) => (i + 1) % count), intervalMs);
|
||||
|
||||
return () => clearInterval(id);
|
||||
}
|
||||
|
||||
const remaining = (1 - progress.get()) * intervalMs;
|
||||
const controls = animate(progress, 1, {
|
||||
duration: remaining / 1000,
|
||||
ease: "linear",
|
||||
onComplete: () => {
|
||||
progress.set(0);
|
||||
setIndex((i) => (i + 1) % count);
|
||||
},
|
||||
});
|
||||
|
||||
return () => controls.stop();
|
||||
}, [index, paused, reduceMotion, count, intervalMs, progress]);
|
||||
|
||||
if (count === 0) return null;
|
||||
|
||||
// Single highlight: render the plain badge (no carousel chrome).
|
||||
if (count === 1) {
|
||||
const [only] = badges;
|
||||
|
||||
return only ? <BadgePill badge={only} /> : null;
|
||||
}
|
||||
|
||||
const activeIndex = index % count;
|
||||
const active = badges[activeIndex];
|
||||
|
||||
if (!active) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex h-6 items-center justify-center"
|
||||
onBlurCapture={() => setPaused(false)}
|
||||
onFocusCapture={() => setPaused(true)}
|
||||
onMouseEnter={() => setPaused(true)}
|
||||
onMouseLeave={() => setPaused(false)}
|
||||
>
|
||||
<AnimatePresence initial={false} mode="popLayout">
|
||||
<motion.div
|
||||
key={activeIndex}
|
||||
animate={{opacity: 1, y: 0}}
|
||||
exit={reduceMotion ? {opacity: 0} : {opacity: 0, y: -10}}
|
||||
initial={reduceMotion ? {opacity: 0} : {opacity: 0, y: 10}}
|
||||
style={{willChange: "transform, opacity"}}
|
||||
transition={
|
||||
reduceMotion ? {duration: 0} : {default: slideSpring, opacity: fadeOut, y: slideSpring}
|
||||
}
|
||||
>
|
||||
<BadgePill badge={active} />
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import {Rocket} from "@gravity-ui/icons";
|
||||
import {buttonVariants} from "@heroui/react";
|
||||
import LinkRoot from "fumadocs-core/link";
|
||||
import {notFound} from "next/navigation";
|
||||
@@ -11,6 +10,7 @@ import {i18n} from "@/lib/i18n";
|
||||
|
||||
import {DemoShowcase} from "./components/demo-showcase";
|
||||
import {ProBanner} from "./components/pro-banner";
|
||||
import {ReleaseBadges} from "./components/release-badges";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
export const revalidate = false;
|
||||
@@ -31,13 +31,7 @@ export default async function HomePage({params}: {params: Promise<{lang: string}
|
||||
<main className="flex min-h-[calc(100vh-4rem)] flex-col">
|
||||
<section className="z-10 flex min-h-0 flex-1 flex-col items-center px-4 pt-12 text-center">
|
||||
<div className="mx-auto flex max-w-2xl flex-col items-center justify-center">
|
||||
<LinkRoot
|
||||
className="flex items-center gap-1 rounded-full bg-accent-soft px-2 py-1 text-xs text-accent-soft-foreground transition-colors hover:bg-accent-soft-hover"
|
||||
href="/docs/native/releases/create-heroui-native-app"
|
||||
>
|
||||
<Rocket className="size-3 text-accent-soft-foreground" />
|
||||
<span className="max-w-60 truncate sm:max-w-full">{home.releaseBadge}</span>
|
||||
</LinkRoot>
|
||||
<ReleaseBadges badges={home.releaseBadges} />
|
||||
<h1 className="mt-2 text-3xl font-bold tracking-tight text-foreground sm:text-4xl lg:mt-4 lg:text-5xl">
|
||||
{home.titleMain} <div className="text-muted/70">{home.titleMuted}</div>
|
||||
</h1>
|
||||
|
||||
@@ -122,9 +122,11 @@ export function ShuffleButton({enableKeyboardShortcut = true}: ShuffleButtonProp
|
||||
variant="secondary"
|
||||
onChange={setIsDontShowAgainChecked}
|
||||
>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label htmlFor="dont-show-again">{dict.dontShowAgain}</Label>
|
||||
</div>
|
||||
|
||||
@@ -12,16 +12,20 @@ export function UIComponentsDemo() {
|
||||
<div className="flex w-full items-center justify-center gap-8">
|
||||
{/* Checkbox - Selected State */}
|
||||
<Checkbox defaultSelected aria-label={t.checkboxAriaLabel}>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
|
||||
{/* Switch - On State */}
|
||||
<Switch defaultSelected aria-label={t.switchAriaLabel}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
|
||||
{/* Radio Buttons - Unselected and Selected */}
|
||||
@@ -33,14 +37,18 @@ export function UIComponentsDemo() {
|
||||
orientation="horizontal"
|
||||
>
|
||||
<Radio value="option1">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="option2">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
|
||||
@@ -230,9 +230,11 @@ export function DesignThemeSelector({
|
||||
</Description>
|
||||
</div>
|
||||
<Switch isSelected={vibrant} onChange={handleVibrantToggle}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,31 +6,31 @@ export function Basic() {
|
||||
<Label>选择你的兴趣</Label>
|
||||
<Description>可多选</Description>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>编程</Label>
|
||||
<Description>热爱构建软件</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
编程
|
||||
</Checkbox.Content>
|
||||
<Description>热爱构建软件</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>设计</Label>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
设计
|
||||
</Checkbox.Content>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>写作</Label>
|
||||
<Description>热衷于内容创作</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
写作
|
||||
</Checkbox.Content>
|
||||
<Description>热衷于内容创作</Description>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
);
|
||||
|
||||
@@ -10,27 +10,27 @@ export function Controlled() {
|
||||
<CheckboxGroup className="min-w-[320px]" name="skills" value={selected} onChange={setSelected}>
|
||||
<Label>你的技能</Label>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>编程</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
编程
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>设计</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
设计
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>写作</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
写作
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label className="my-4 text-sm text-muted">已选:{selected.join(", ") || "无"}</Label>
|
||||
|
||||
@@ -8,31 +8,31 @@ export function CustomRenderFunction() {
|
||||
<Label>选择你的兴趣</Label>
|
||||
<Description>可多选</Description>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>编程</Label>
|
||||
<Description>热爱构建软件</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
编程
|
||||
</Checkbox.Content>
|
||||
<Description>热爱构建软件</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>设计</Label>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
设计
|
||||
</Checkbox.Content>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>写作</Label>
|
||||
<Description>热衷于内容创作</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
写作
|
||||
</Checkbox.Content>
|
||||
<Description>热衷于内容创作</Description>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
);
|
||||
|
||||
@@ -6,22 +6,22 @@ export function Disabled() {
|
||||
<Label>功能</Label>
|
||||
<Description>功能选择暂时不可用</Description>
|
||||
<Checkbox value="feature1">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>功能一</Label>
|
||||
<Description>该功能即将推出</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
功能一
|
||||
</Checkbox.Content>
|
||||
<Description>该功能即将推出</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="feature2">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>功能二</Label>
|
||||
<Description>该功能即将推出</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
功能二
|
||||
</Checkbox.Content>
|
||||
<Description>该功能即将推出</Description>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
);
|
||||
|
||||
@@ -32,22 +32,19 @@ export function FeaturesAndAddOns() {
|
||||
<Description>选择接收更新的方式</Description>
|
||||
<div className="flex flex-col gap-2">
|
||||
{addOns.map((addon) => (
|
||||
<Checkbox
|
||||
key={addon.value}
|
||||
value={addon.value}
|
||||
variant="secondary"
|
||||
className={clsx(
|
||||
"group relative flex-col gap-4 rounded-3xl bg-surface px-5 py-4 transition-all",
|
||||
"data-[selected=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Checkbox.Control className="absolute top-3 right-4 size-5 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content className="flex flex-row items-start justify-start gap-4">
|
||||
<addon.icon className="size-5 text-accent" />
|
||||
<Checkbox key={addon.value} value={addon.value} variant="secondary">
|
||||
<Checkbox.Content
|
||||
className={clsx(
|
||||
"group relative flex w-full flex-row items-start justify-start gap-4 rounded-3xl bg-surface px-5 py-4 transition-all",
|
||||
"data-[selected=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Checkbox.Control className="absolute top-3 right-4 size-5 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<addon.icon className="size-5 text-accent-soft-foreground" />
|
||||
<div className="flex flex-col gap-1">
|
||||
<Label>{addon.title}</Label>
|
||||
<span>{addon.title}</span>
|
||||
<Description>{addon.description}</Description>
|
||||
</div>
|
||||
</Checkbox.Content>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Checkbox, CheckboxGroup, Label} from "@heroui/react";
|
||||
import {Checkbox, CheckboxGroup} from "@heroui/react";
|
||||
import {useState} from "react";
|
||||
|
||||
export function Indeterminate() {
|
||||
@@ -17,37 +17,37 @@ export function Indeterminate() {
|
||||
setSelected(isSelected ? allOptions : []);
|
||||
}}
|
||||
>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>全选</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
全选
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<div className="ml-6 flex flex-col gap-2">
|
||||
<CheckboxGroup value={selected} onChange={setSelected}>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>编程</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
编程
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>设计</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
设计
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>写作</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
写作
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
|
||||
@@ -7,31 +7,31 @@ export function OnSurface() {
|
||||
<Label>选择你的兴趣</Label>
|
||||
<Description>可多选</Description>
|
||||
<Checkbox value="coding">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>编程</Label>
|
||||
<Description>热爱构建软件</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
编程
|
||||
</Checkbox.Content>
|
||||
<Description>热爱构建软件</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="design">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>设计</Label>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
设计
|
||||
</Checkbox.Content>
|
||||
<Description>喜欢打造精美界面</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="writing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>写作</Label>
|
||||
<Description>热衷于内容创作</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
写作
|
||||
</Checkbox.Content>
|
||||
<Description>热衷于内容创作</Description>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
</Surface>
|
||||
|
||||
@@ -18,27 +18,27 @@ export function Validation() {
|
||||
<CheckboxGroup isRequired name="preferences">
|
||||
<Label>偏好设置</Label>
|
||||
<Checkbox value="email">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>邮件通知</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
邮件通知
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="sms">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>短信通知</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
短信通知
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox value="push">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>推送通知</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
推送通知
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<FieldError>请至少选择一种通知方式。</FieldError>
|
||||
|
||||
@@ -8,52 +8,52 @@ export function WithCustomIndicator() {
|
||||
<Label>功能</Label>
|
||||
<Description>选择你需要的功能</Description>
|
||||
<Checkbox value="notifications">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>邮件通知</Label>
|
||||
<Description>通过邮件接收更新</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
邮件通知
|
||||
</Checkbox.Content>
|
||||
<Description>通过邮件接收更新</Description>
|
||||
</Checkbox>
|
||||
<Checkbox value="newsletter">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>邮件通讯</Label>
|
||||
<Description>每周接收邮件简报</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
邮件通讯
|
||||
</Checkbox.Content>
|
||||
<Description>每周接收邮件简报</Description>
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
import {Checkbox} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<Checkbox id="basic-terms">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox name="basic-terms">
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="basic-terms">接受条款与条件</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
接受条款与条件
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
import {Checkbox} from "@heroui/react";
|
||||
import {useState} from "react";
|
||||
|
||||
export function Controlled() {
|
||||
@@ -8,16 +8,14 @@ export function Controlled() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="email-notifications" isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Checkbox id="email-notifications" isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="email-notifications">邮件通知</Label>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
邮件通知
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<p className="text-sm text-muted">
|
||||
状态:<span className="font-medium">{isSelected ? "已勾选" : "未勾选"}</span>
|
||||
</p>
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
import {Checkbox} from "@heroui/react";
|
||||
|
||||
export function CustomIndicator() {
|
||||
return (
|
||||
<div className="flex gap-4">
|
||||
<Checkbox defaultSelected name="heart">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12.62 20.81c-.34.12-.9.12-1.24 0C8.48 19.82 2 15.69 2 8.69 2 5.6 4.49 3.1 7.56 3.1c1.82 0 3.43.88 4.44 2.24a5.53 5.53 0 0 1 4.44-2.24C19.51 3.1 22 5.6 22 8.69c0 7-6.48 11.13-9.38 12.12Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>心形</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12.62 20.81c-.34.12-.9.12-1.24 0C8.48 19.82 2 15.69 2 8.69 2 5.6 4.49 3.1 7.56 3.1c1.82 0 3.43.88 4.44 2.24a5.53 5.53 0 0 1 4.44-2.24C19.51 3.1 22 5.6 22 8.69c0 7-6.48 11.13-9.38 12.12Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
心形
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox defaultSelected name="plus">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg fill="none" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M6 12H18"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
<path
|
||||
d="M12 18V6"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>加号</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? (
|
||||
<svg fill="none" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M6 12H18"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
<path
|
||||
d="M12 18V6"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
加号
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Checkbox isIndeterminate name="indeterminate">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isIndeterminate}) =>
|
||||
isIndeterminate ? (
|
||||
<svg stroke="currentColor" strokeWidth={3} viewBox="0 0 24 24">
|
||||
<line x1="21" x2="3" y1="12" y2="12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>部分选中</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator>
|
||||
{({isIndeterminate}) =>
|
||||
isIndeterminate ? (
|
||||
<svg stroke="currentColor" strokeWidth={3} viewBox="0 0 24 24">
|
||||
<line x1="21" x2="3" y1="12" y2="12" />
|
||||
</svg>
|
||||
) : null
|
||||
}
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Control>
|
||||
部分选中
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,12 @@ import {Checkbox, Label} from "@heroui/react";
|
||||
export function CustomRenderFunction() {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="basic-terms" render={(props) => <label {...props} data-custom="bar" />}>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox id="basic-terms" render={(props) => <div {...props} data-custom="bar" />}>
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label htmlFor="basic-terms">接受条款与条件</Label>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
import {Checkbox} from "@heroui/react";
|
||||
|
||||
export function CustomStyles() {
|
||||
return (
|
||||
<Checkbox id="custom">
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="custom">自定义样式复选框</Label>
|
||||
<Checkbox.Control className="border-2 border-purple-500 data-[selected=true]:border-purple-500 data-[selected=true]:bg-purple-500">
|
||||
<Checkbox.Indicator className="text-white" />
|
||||
</Checkbox.Control>
|
||||
自定义样式复选框
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
import {Checkbox} from "@heroui/react";
|
||||
|
||||
export function DefaultSelected() {
|
||||
return (
|
||||
<Checkbox defaultSelected id="default-notifications">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="default-notifications">启用邮件通知</Label>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
启用邮件通知
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, Description} from "@heroui/react";
|
||||
|
||||
export function Disabled() {
|
||||
return (
|
||||
<Checkbox isDisabled id="feature">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="feature">高级功能</Label>
|
||||
<Description>该功能即将推出</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
高级功能
|
||||
</Checkbox.Content>
|
||||
<Description>该功能即将推出</Description>
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
|
||||
export function ExternalLabel() {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="label-marketing">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
<Label htmlFor="label-marketing">给我发送营销邮件</Label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Button, Checkbox, Label} from "@heroui/react";
|
||||
import {Button, Checkbox} from "@heroui/react";
|
||||
import React from "react";
|
||||
|
||||
export function Form() {
|
||||
@@ -9,7 +9,7 @@ export function Form() {
|
||||
const formData = new FormData(e.target as HTMLFormElement);
|
||||
|
||||
alert(
|
||||
`表单已提交,内容如下:\n${Array.from(formData.entries())
|
||||
`表单提交数据:\n${Array.from(formData.entries())
|
||||
.map(([key, value]) => `${key}: ${value}`)
|
||||
.join("\n")}`,
|
||||
);
|
||||
@@ -18,36 +18,30 @@ export function Form() {
|
||||
return (
|
||||
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="form-notifications" name="notifications" value="on">
|
||||
<Checkbox name="notifications" value="on">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="form-notifications">启用通知</Label>
|
||||
启用通知
|
||||
</Checkbox.Content>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox defaultSelected id="form-newsletter" name="newsletter" value="on">
|
||||
</Checkbox>
|
||||
<Checkbox defaultSelected name="newsletter" value="on">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="form-newsletter">订阅邮件通讯</Label>
|
||||
订阅新闻通讯
|
||||
</Checkbox.Content>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox id="form-marketing" name="marketing" value="on">
|
||||
</Checkbox>
|
||||
<Checkbox name="marketing" value="on">
|
||||
<Checkbox.Content>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
</Checkbox>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="form-marketing">接收营销资讯</Label>
|
||||
接收营销更新
|
||||
</Checkbox.Content>
|
||||
</div>
|
||||
</Checkbox>
|
||||
</div>
|
||||
<Button className="mt-4" size="sm" type="submit" variant="primary">
|
||||
提交
|
||||
|
||||
@@ -9,31 +9,31 @@ export function FullRounded() {
|
||||
className="[&_[data-slot='checkbox-default-indicator--checkmark']]:size-2"
|
||||
name="small-rounded"
|
||||
>
|
||||
<Checkbox.Control className="size-3 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>小尺寸</Label>
|
||||
<Checkbox.Control className="size-3 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
小尺寸
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<Checkbox name="default-rounded">
|
||||
<Checkbox.Control className="size-4 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>默认尺寸</Label>
|
||||
<Checkbox.Control className="size-4 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
默认尺寸
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<Checkbox name="large-rounded">
|
||||
<Checkbox.Control className="size-5 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>大尺寸</Label>
|
||||
<Checkbox.Control className="size-5 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
大尺寸
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
@@ -42,11 +42,11 @@ export function FullRounded() {
|
||||
className="[&_[data-slot='checkbox-default-indicator--checkmark']]:size-4"
|
||||
name="xl-rounded"
|
||||
>
|
||||
<Checkbox.Control className="size-6 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label>特大尺寸</Label>
|
||||
<Checkbox.Control className="size-6 rounded-full before:rounded-full">
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
特大尺寸
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, Description} from "@heroui/react";
|
||||
import {useState} from "react";
|
||||
|
||||
export function Indeterminate() {
|
||||
@@ -17,13 +17,13 @@ export function Indeterminate() {
|
||||
setIsIndeterminate(false);
|
||||
}}
|
||||
>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="select-all">全选</Label>
|
||||
<Description>展示部分选中状态(短横线图标)</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
全选
|
||||
</Checkbox.Content>
|
||||
<Description>展示部分选中状态(短横线图标)</Description>
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ export {Invalid} from "./invalid";
|
||||
export {RenderProps} from "./render-props";
|
||||
export {Variants} from "./variants";
|
||||
export {WithDescription} from "./with-description";
|
||||
export {WithLabel} from "./with-label";
|
||||
export {ExternalLabel} from "./external-label";
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, FieldError} from "@heroui/react";
|
||||
|
||||
export function Invalid() {
|
||||
return (
|
||||
<Checkbox isInvalid id="agreement" name="agreement">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox isInvalid isRequired name="agreement">
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="agreement">我同意条款</Label>
|
||||
<Description>请勾选同意条款后继续</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
我同意条款
|
||||
</Checkbox.Content>
|
||||
<FieldError>您必须接受条款才能继续</FieldError>
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, Description} from "@heroui/react";
|
||||
|
||||
export function RenderProps() {
|
||||
return (
|
||||
<Checkbox id="render-props-terms">
|
||||
{({isSelected}) => (
|
||||
<>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="render-props-terms">{isSelected ? "已同意条款" : "接受条款"}</Label>
|
||||
<Description>{isSelected ? "感谢您的确认" : "请先阅读并接受条款"}</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
{isSelected ? "已同意条款" : "接受条款"}
|
||||
</Checkbox.Content>
|
||||
<Description>{isSelected ? "感谢您的确认" : "请先阅读并接受条款"}</Description>
|
||||
</>
|
||||
)}
|
||||
</Checkbox>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, Description} from "@heroui/react";
|
||||
|
||||
export function Variants() {
|
||||
return (
|
||||
@@ -6,25 +6,25 @@ export function Variants() {
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-sm font-medium text-muted">主要变体</p>
|
||||
<Checkbox id="primary" name="primary" variant="primary">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="primary">主要复选框</Label>
|
||||
<Description>默认背景的标准样式</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
主要复选框
|
||||
</Checkbox.Content>
|
||||
<Description>默认背景的标准样式</Description>
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-sm font-medium text-muted">次要变体</p>
|
||||
<Checkbox id="secondary" name="secondary" variant="secondary">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="secondary">次要复选框</Label>
|
||||
<Description>用于表面容器的低强调样式</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
次要复选框
|
||||
</Checkbox.Content>
|
||||
<Description>用于表面容器的低强调样式</Description>
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {Checkbox, Description, Label} from "@heroui/react";
|
||||
import {Checkbox, Description} from "@heroui/react";
|
||||
|
||||
export function WithDescription() {
|
||||
return (
|
||||
<Checkbox id="description-notifications">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox name="description-notifications">
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="description-notifications">邮件通知</Label>
|
||||
<Description>当有人在评论中@你时收到通知</Description>
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
邮件通知
|
||||
</Checkbox.Content>
|
||||
<Description>当有人在评论中提及您时收到通知</Description>
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import {Checkbox, Label} from "@heroui/react";
|
||||
|
||||
export function WithLabel() {
|
||||
return (
|
||||
<Checkbox id="label-marketing">
|
||||
<Checkbox.Control>
|
||||
<Checkbox.Indicator />
|
||||
</Checkbox.Control>
|
||||
<Checkbox.Content>
|
||||
<Label htmlFor="label-marketing">接收营销邮件</Label>
|
||||
</Checkbox.Content>
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import {Calendar, DateField, DatePicker, Label} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<DatePicker className="w-64" name="date">
|
||||
<DatePicker className="w-72" name="date">
|
||||
<Label>日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
<DateField.Input>{(segment) => <DateField.Segment segment={segment} />}</DateField.Input>
|
||||
|
||||
@@ -10,7 +10,7 @@ export function Controlled() {
|
||||
const [value, setValue] = useState<DateValue | null>(today(getLocalTimeZone()));
|
||||
|
||||
return (
|
||||
<div className="flex w-64 flex-col gap-4">
|
||||
<div className="flex w-72 flex-col gap-4">
|
||||
<DatePicker name="date" value={value} onChange={setValue}>
|
||||
<Label>日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Calendar, DateField, DatePicker, Label} from "@heroui/react";
|
||||
export function CustomRenderFunction() {
|
||||
return (
|
||||
<DatePicker
|
||||
className="w-64"
|
||||
className="w-72"
|
||||
name="date"
|
||||
render={(props) => <div {...props} data-custom="date-picker" />}
|
||||
>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {getLocalTimeZone, today} from "@internationalized/date";
|
||||
|
||||
export function Disabled() {
|
||||
return (
|
||||
<DatePicker isDisabled className="w-64" name="date" value={today(getLocalTimeZone())}>
|
||||
<DatePicker isDisabled className="w-72" name="date" value={today(getLocalTimeZone())}>
|
||||
<Label>日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
<DateField.Input>{(segment) => <DateField.Segment segment={segment} />}</DateField.Input>
|
||||
|
||||
@@ -37,7 +37,7 @@ export function FormExample() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form className="flex w-64 flex-col gap-3" onSubmit={handleSubmit}>
|
||||
<Form className="flex w-72 flex-col gap-3" onSubmit={handleSubmit}>
|
||||
<DatePicker
|
||||
isRequired
|
||||
isInvalid={isInvalid}
|
||||
|
||||
@@ -50,7 +50,7 @@ export function FormatOptions() {
|
||||
<div className="flex flex-col gap-4">
|
||||
<DatePicker
|
||||
key={granularity}
|
||||
className="w-fit min-w-64"
|
||||
className="w-fit min-w-72"
|
||||
defaultValue={defaultValue}
|
||||
granularity={granularity}
|
||||
hideTimeZone={hideTimeZone}
|
||||
@@ -173,16 +173,20 @@ export function FormatOptions() {
|
||||
|
||||
<div className="flex min-w-80 flex-col gap-2">
|
||||
<Switch isSelected={hideTimeZone} onChange={setHideTimeZone}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">隐藏时区</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
隐藏时区
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch isSelected={shouldForceLeadingZeros} onChange={setShouldForceLeadingZeros}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">强制前导零</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
强制前导零
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export function InternationalCalendar() {
|
||||
return (
|
||||
<I18nProvider locale="hi-IN-u-ca-indian">
|
||||
<DatePicker
|
||||
className="w-64"
|
||||
className="w-72"
|
||||
defaultValue={today(getLocalTimeZone())}
|
||||
name="international-date"
|
||||
>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Icon} from "@iconify/react";
|
||||
|
||||
export function WithCustomIndicator() {
|
||||
return (
|
||||
<DatePicker className="w-64" name="date">
|
||||
<DatePicker className="w-72" name="date">
|
||||
<Label>日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
<DateField.Input>{(segment) => <DateField.Segment segment={segment} />}</DateField.Input>
|
||||
|
||||
@@ -14,7 +14,7 @@ export function WithValidation() {
|
||||
return (
|
||||
<DatePicker
|
||||
isRequired
|
||||
className="w-64"
|
||||
className="w-72"
|
||||
isInvalid={isInvalid}
|
||||
minValue={currentDate}
|
||||
name="date"
|
||||
|
||||
@@ -4,7 +4,7 @@ import {DateField, DateRangePicker, Label, RangeCalendar} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<DateRangePicker className="w-72" endName="endDate" startName="startDate">
|
||||
<DateRangePicker className="w-80" endName="endDate" startName="startDate">
|
||||
<Label>出行日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
<DateField.Input slot="start">
|
||||
|
||||
@@ -16,7 +16,7 @@ export function Controlled() {
|
||||
const [value, setValue] = useState<DateRange | null>({end: start.add({days: 4}), start});
|
||||
|
||||
return (
|
||||
<div className="flex w-72 flex-col gap-4">
|
||||
<div className="flex w-80 flex-col gap-4">
|
||||
<DateRangePicker endName="endDate" startName="startDate" value={value} onChange={setValue}>
|
||||
<Label>出行日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {DateField, DateRangePicker, Label, RangeCalendar} from "@heroui/react";
|
||||
export function CustomRenderFunction() {
|
||||
return (
|
||||
<DateRangePicker
|
||||
className="w-72"
|
||||
className="w-80"
|
||||
endName="endDate"
|
||||
render={(props) => <div data-custom="foo" {...props} />}
|
||||
startName="startDate"
|
||||
|
||||
@@ -9,7 +9,7 @@ export function Disabled() {
|
||||
return (
|
||||
<DateRangePicker
|
||||
isDisabled
|
||||
className="w-72"
|
||||
className="w-80"
|
||||
endName="endDate"
|
||||
startName="startDate"
|
||||
value={{end: start.add({days: 4}), start}}
|
||||
|
||||
@@ -41,7 +41,7 @@ export function FormExample() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form className="flex w-72 flex-col gap-3" onSubmit={handleSubmit}>
|
||||
<Form className="flex w-80 flex-col gap-3" onSubmit={handleSubmit}>
|
||||
<DateRangePicker
|
||||
isRequired
|
||||
endName="tripEndDate"
|
||||
|
||||
@@ -85,7 +85,7 @@ export function FormatOptions() {
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<DateRangePicker
|
||||
key={granularity}
|
||||
className="w-max min-w-72"
|
||||
className="w-max min-w-80"
|
||||
defaultValue={defaultValue}
|
||||
endName="endDate"
|
||||
granularity={granularity}
|
||||
@@ -259,16 +259,20 @@ export function FormatOptions() {
|
||||
|
||||
<div className="flex min-w-[529px] flex-col gap-2">
|
||||
<Switch isSelected={hideTimeZone} onChange={setHideTimeZone}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">隐藏时区</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
隐藏时区
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
<Switch isSelected={shouldForceLeadingZeros} onChange={setShouldForceLeadingZeros}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">强制前导零</Label>
|
||||
<Switch.Content>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
强制前导零
|
||||
</Switch.Content>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@ export function InputContainer() {
|
||||
return (
|
||||
<DateRangePicker
|
||||
shouldForceLeadingZeros
|
||||
className="w-full max-w-2xs min-w-72"
|
||||
className="w-full max-w-2xs min-w-80"
|
||||
defaultValue={defaultValue}
|
||||
granularity="second"
|
||||
hourCycle={12}
|
||||
|
||||
@@ -10,7 +10,7 @@ export function InternationalCalendar() {
|
||||
return (
|
||||
<I18nProvider locale="hi-IN-u-ca-indian">
|
||||
<DateRangePicker
|
||||
className="w-72"
|
||||
className="w-80"
|
||||
defaultValue={{end: start.add({days: 7}), start}}
|
||||
endName="endDate"
|
||||
startName="startDate"
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Icon} from "@iconify/react";
|
||||
|
||||
export function WithCustomIndicator() {
|
||||
return (
|
||||
<DateRangePicker className="w-72" endName="endDate" startName="startDate">
|
||||
<DateRangePicker className="w-80" endName="endDate" startName="startDate">
|
||||
<Label>出行日期</Label>
|
||||
<DateField.Group fullWidth>
|
||||
<DateField.Input slot="start">
|
||||
|
||||
@@ -20,7 +20,7 @@ export function WithValidation() {
|
||||
return (
|
||||
<DateRangePicker
|
||||
isRequired
|
||||
className="w-72"
|
||||
className="w-80"
|
||||
endName="endDate"
|
||||
isInvalid={isInvalid}
|
||||
minValue={currentDate}
|
||||
|
||||
@@ -560,9 +560,9 @@ export const demos: Record<string, DemoItem> = {
|
||||
component: CheckboxDemos.Indeterminate,
|
||||
file: "cn/checkbox/indeterminate.tsx",
|
||||
},
|
||||
"checkbox-with-label": {
|
||||
component: CheckboxDemos.WithLabel,
|
||||
file: "cn/checkbox/with-label.tsx",
|
||||
"checkbox-external-label": {
|
||||
component: CheckboxDemos.ExternalLabel,
|
||||
file: "cn/checkbox/external-label.tsx",
|
||||
},
|
||||
"checkbox-with-description": {
|
||||
component: CheckboxDemos.WithDescription,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Button, Label, Modal, Radio, RadioGroup} from "@heroui/react";
|
||||
import {Button, Modal, Radio, RadioGroup} from "@heroui/react";
|
||||
import {useState} from "react";
|
||||
|
||||
export function ScrollComparison() {
|
||||
@@ -14,16 +14,20 @@ export function ScrollComparison() {
|
||||
onChange={(value) => setScroll(value as "inside" | "outside")}
|
||||
>
|
||||
<Radio value="inside">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Label>内部</Label>
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
内部
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="outside">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Label>外部</Label>
|
||||
<Radio.Content>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
外部
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
|
||||
@@ -6,31 +6,31 @@ export function Basic() {
|
||||
<Label>选择套餐</Label>
|
||||
<Description>选择最适合你的套餐</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>基础版</Label>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
基础版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>高级版</Label>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
高级版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>商业版</Label>
|
||||
<Description>无限消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
商业版
|
||||
</Radio.Content>
|
||||
<Description>无限消息</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
@@ -11,31 +11,31 @@ export function Controlled() {
|
||||
<RadioGroup name="plan-controlled" value={value} onChange={setValue}>
|
||||
<Label>订阅套餐</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>入门版</Label>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
入门版
|
||||
</Radio.Content>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>专业版</Label>
|
||||
<Description>高级报表与分析</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
专业版
|
||||
</Radio.Content>
|
||||
<Description>高级报表与分析</Description>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>团队版</Label>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
团队版
|
||||
</Radio.Content>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<p className="text-sm text-muted">
|
||||
|
||||
@@ -8,43 +8,43 @@ export function CustomIndicator() {
|
||||
<Label>选择套餐</Label>
|
||||
<Description>选择最适合你的套餐</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>基础版</Label>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
基础版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>高级版</Label>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
高级版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>商业版</Label>
|
||||
<Description>无限消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
isSelected ? <span className="text-xs leading-none text-background">✓</span> : null
|
||||
}
|
||||
</Radio.Indicator>
|
||||
</Radio.Control>
|
||||
商业版
|
||||
</Radio.Content>
|
||||
<Description>无限消息</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
@@ -6,37 +6,37 @@ export function CustomRenderFunction() {
|
||||
return (
|
||||
<RadioGroup
|
||||
defaultValue="premium"
|
||||
name="plan"
|
||||
name="plan-custom-render"
|
||||
render={(props) => <div {...props} data-custom="foo" />}
|
||||
>
|
||||
<Label>选择套餐</Label>
|
||||
<Description>选择最适合你的套餐</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>基础版</Label>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
基础版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>高级版</Label>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
高级版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>商业版</Label>
|
||||
<Description>无限消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
商业版
|
||||
</Radio.Content>
|
||||
<Description>无限消息</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
@@ -63,20 +63,18 @@ export function DeliveryAndPayment() {
|
||||
<Label>配送方式</Label>
|
||||
<div className="grid gap-x-4 md:grid-cols-3">
|
||||
{deliveryOptions.map((option) => (
|
||||
<Radio
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={clsx(
|
||||
"group relative flex-col gap-4 rounded-xl border border-transparent bg-surface px-5 py-4 transition-all data-[selected=true]:border-accent data-[selected=true]:bg-accent/10",
|
||||
"data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Radio.Control className="absolute top-3 right-4 size-5">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content className="flex flex-col gap-6">
|
||||
<Radio key={option.value} value={option.value}>
|
||||
<Radio.Content
|
||||
className={clsx(
|
||||
"group relative flex w-full flex-col gap-6 rounded-xl border border-transparent bg-surface px-5 py-4 transition-all data-[selected=true]:border-accent data-[selected=true]:bg-accent/10",
|
||||
"data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Radio.Control className="absolute top-3 right-4 size-5">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Label>{option.title}</Label>
|
||||
<span>{option.title}</span>
|
||||
<Description>{option.description}</Description>
|
||||
</div>
|
||||
<span className="text-sm font-semibold">{option.price}</span>
|
||||
@@ -93,21 +91,19 @@ export function DeliveryAndPayment() {
|
||||
</div>
|
||||
<div className="grid gap-x-4 md:grid-cols-2">
|
||||
{paymentOptions.map((option) => (
|
||||
<Radio
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={clsx(
|
||||
"group relative flex-col gap-4 rounded-xl border border-transparent bg-surface px-5 py-4 transition-all",
|
||||
"data-[selected=true]:border-accent data-[selected=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Radio.Control className="absolute top-3 right-4 size-5">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content className="flex flex-row items-start justify-start gap-4">
|
||||
<Radio key={option.value} value={option.value}>
|
||||
<Radio.Content
|
||||
className={clsx(
|
||||
"group relative flex w-full flex-row items-start justify-start gap-4 rounded-xl border border-transparent bg-surface px-5 py-4 transition-all",
|
||||
"data-[selected=true]:border-accent data-[selected=true]:bg-accent/10",
|
||||
)}
|
||||
>
|
||||
<Radio.Control className="absolute top-3 right-4 size-5">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Icon className="size-6" icon={option.icon} />
|
||||
<div className="flex flex-col gap-1">
|
||||
<Label>{option.title}</Label>
|
||||
<span>{option.title}</span>
|
||||
<Description>{option.description}</Description>
|
||||
</div>
|
||||
</Radio.Content>
|
||||
|
||||
@@ -6,31 +6,31 @@ export function Disabled() {
|
||||
<Label>订阅套餐</Label>
|
||||
<Description>我们正在发布更新,暂时无法更改套餐。</Description>
|
||||
<Radio value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>入门版</Label>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
入门版
|
||||
</Radio.Content>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>专业版</Label>
|
||||
<Description>高级报表与分析</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
专业版
|
||||
</Radio.Content>
|
||||
<Description>高级报表与分析</Description>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>团队版</Label>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
团队版
|
||||
</Radio.Content>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
@@ -6,31 +6,31 @@ export function Horizontal() {
|
||||
<Label>订阅套餐</Label>
|
||||
<RadioGroup defaultValue="pro" name="plan-orientation" orientation="horizontal">
|
||||
<Radio value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>入门版</Label>
|
||||
<Description>适合副项目</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
入门版
|
||||
</Radio.Content>
|
||||
<Description>适合副项目</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>专业版</Label>
|
||||
<Description>高级报表</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
专业版
|
||||
</Radio.Content>
|
||||
<Description>高级报表</Description>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>团队版</Label>
|
||||
<Description>最多 10 名队友</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
团队版
|
||||
</Radio.Content>
|
||||
<Description>最多 10 名队友</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
@@ -3,35 +3,35 @@ import {Description, Label, Radio, RadioGroup, Surface} from "@heroui/react";
|
||||
export function OnSurface() {
|
||||
return (
|
||||
<Surface className="w-full rounded-3xl p-6">
|
||||
<RadioGroup defaultValue="premium" name="plan" variant="secondary">
|
||||
<RadioGroup defaultValue="premium" name="plan-on-surface" variant="secondary">
|
||||
<Label>选择套餐</Label>
|
||||
<Description>选择最适合你的套餐</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>基础版</Label>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
基础版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 100 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>高级版</Label>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
高级版
|
||||
</Radio.Content>
|
||||
<Description>每月包含 200 条消息</Description>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>商业版</Label>
|
||||
<Description>无限消息</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
商业版
|
||||
</Radio.Content>
|
||||
<Description>无限消息</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</Surface>
|
||||
|
||||
@@ -15,31 +15,31 @@ export function Uncontrolled() {
|
||||
>
|
||||
<Label>订阅套餐</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>入门版</Label>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
入门版
|
||||
</Radio.Content>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>专业版</Label>
|
||||
<Description>高级报表与分析</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
专业版
|
||||
</Radio.Content>
|
||||
<Description>高级报表与分析</Description>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>团队版</Label>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
团队版
|
||||
</Radio.Content>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<p className="text-sm text-muted">
|
||||
|
||||
@@ -21,31 +21,31 @@ export function Validation() {
|
||||
<RadioGroup isRequired name="plan-validation">
|
||||
<Label>订阅套餐</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>入门版</Label>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
入门版
|
||||
</Radio.Content>
|
||||
<Description>适合副项目和小型团队</Description>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>专业版</Label>
|
||||
<Description>高级报表与分析</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
专业版
|
||||
</Radio.Content>
|
||||
<Description>高级报表与分析</Description>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label>团队版</Label>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
团队版
|
||||
</Radio.Content>
|
||||
<Description>最多可与 10 名队友共享访问权限</Description>
|
||||
</Radio>
|
||||
<FieldError>请先选择订阅套餐再继续。</FieldError>
|
||||
</RadioGroup>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user