InputGroup 输入框组
将相关输入控件与前后缀元素组合,以增强表单字段。
引入
import { InputGroup } from '@heroui/react';用法
"use client";
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
组件结构
import {InputGroup, TextField, Label} from '@heroui/react';
export default () => (
<TextField>
<Label />
<InputGroup>
<InputGroup.Prefix />
<InputGroup.Input /> {/* Or use InputGroup.TextArea for multiline input */}
<InputGroup.Suffix />
</InputGroup>
</TextField>
)InputGroup 使用可选的前缀与后缀包裹输入框,形成视觉上统一的组合。通常放在 TextField 内,用于在输入前后添加图标、文字、按钮等元素。单行输入请使用 InputGroup.Input,多行输入请使用 InputGroup.TextArea。
前缀图标
在输入框前添加图标。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
后缀图标
在输入框后添加图标。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
前缀与后缀
同时组合前缀与后缀。
"use client";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
export function WithPrefixAndSuffix() {文字前缀
使用文字作为前缀,例如货币符号或协议前缀。
"use client";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithTextPrefix() {文字后缀
使用文字作为后缀,例如域名后缀或单位。
"use client";
import {InputGroup, Label, TextField} from "@heroui/react";
export function WithTextSuffix() {图标前缀与文字后缀
组合图标前缀与文字后缀。
"use client";
import {Globe} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
复制按钮后缀
在后缀中加入交互按钮,例如复制按钮。
"use client";
import {Copy} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
图标前缀与复制按钮
组合图标前缀与交互式后缀按钮。
"use client";
import {Copy, Globe} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
密码显隐切换
在后缀中使用按钮切换密码可见性。
"use client";
import {Eye, EyeSlash} from "@gravity-ui/icons";
import {Button, InputGroup, Label, TextField} from "@heroui/react";
import {useState} from "react";加载状态
在后缀显示加载指示器,表示正在处理。
"use client";
import {InputGroup, Spinner, TextField} from "@heroui/react";
export function WithLoadingSuffix() {键盘快捷键
使用 Kbd 组件展示键盘快捷键。
"use client";
import {InputGroup, Kbd, TextField} from "@heroui/react";
export function WithKeyboardShortcut() {Badge 后缀
在后缀中加入徽章或 chip,用于展示状态或标签。
"use client";
import {Chip, InputGroup, TextField} from "@heroui/react";
export function WithBadgeSuffix() {必填字段
InputGroup 会遵循父级 TextField 的必填状态。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, TextField} from "@heroui/react";
校验
InputGroup 会自动反映父级 TextField 的无效状态。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {FieldError, InputGroup, Label, TextField} from "@heroui/react";
禁用状态
InputGroup 会遵循父级 TextField 的禁用状态。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
全宽
import {Envelope, Eye} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function FullWidth() {
return (变体
InputGroup 支持两种视觉变体:
primary(默认)— 带阴影的标准样式,适用于大多数场景secondary— 低强调、无阴影的变体,适合用在 Surface 组件内
import {Envelope} from "@gravity-ui/icons";
import {InputGroup, Label, TextField} from "@heroui/react";
export function Variants() {
return (在 Surface 内
在 Surface 内使用时,请使用 variant="secondary",以应用适合表面背景的低强调变体。
"use client";
import {Envelope} from "@gravity-ui/icons";
import {Description, InputGroup, Label, Surface, TextField} from "@heroui/react";
搭配 TextArea
多行输入请使用 InputGroup.TextArea,并搭配前缀与后缀。当存在 textarea 时,容器高度会自动适应内容,并将前缀/后缀与顶部对齐。
"use client";
import {ArrowUp, At, Microphone, PlugConnection, Plus} from "@gravity-ui/icons";
import {Button, InputGroup, Kbd, Spinner, TextField, Tooltip} from "@heroui/react";
import {useState} from "react";样式
传入 Tailwind CSS 类
import {InputGroup, TextField, Label} from '@heroui/react';
function CustomInputGroup() {
return (
<TextField>
<Label>Website</Label>
<InputGroup className="rounded-xl border-2 border-primary">
<InputGroup.Prefix className="bg-primary/10 text-primary">
https://
</InputGroup.Prefix>
<InputGroup.Input className="font-medium" />
<InputGroup.Suffix className="bg-primary/10 text-primary">
.com
</InputGroup.Suffix>
</InputGroup>
</TextField>
);
}自定义组件类
InputGroup 使用可自定义的 CSS 类。你可以覆盖这些类名以匹配自己的设计系统。
@layer components {
.input-group {
@apply bg-field text-field-foreground shadow-field rounded-field inline-flex min-h-9 items-center overflow-hidden border text-sm outline-none;
}
.input-group__input {
@apply flex-1 rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;
}
.input-group__prefix {
@apply text-field-placeholder rounded-l-field flex h-full items-center justify-center rounded-r-none bg-transparent px-3;
}
.input-group__suffix {
@apply text-field-placeholder rounded-r-field flex h-full items-center justify-center rounded-l-none bg-transparent px-3;
}
/* Secondary variant */
.input-group--secondary {
@apply shadow-none;
background-color: var(--color-default);
}
}CSS 类
.input-group– 根容器:带边框、背景与 flex 布局。默认使用min-h-9与items-center;当存在 textarea 时会切换为items-start。.input-group__input– 透明背景、无边框的输入元素。textarea 也使用该基础类。.input-group__prefix– 左侧圆角的前缀容器。与 textarea 搭配时与顶部对齐。.input-group__suffix– 右侧圆角的后缀容器。与 textarea 搭配时与顶部对齐。.input-group--primary– 带阴影的主变体(默认).input-group--secondary– 无阴影的次变体,适合用在 surface 上
说明: 使用 InputGroup.TextArea 时,容器会从 items-center 切换为 items-start,并使用 height: auto 替代固定高度。前缀与后缀与顶部对齐,并增加内边距以匹配 textarea 的垂直内边距。textarea 使用相同的 .input-group__input 基础类,并通过 [data-slot="input-group-textarea"] 选择器应用 textarea 专用样式(最小高度与纵向 resize)。
交互状态
InputGroup 会根据状态自动管理以下 data 属性:
- Hover:
[data-hovered]– 悬停在整个组合上时应用 - Focus Within:
[data-focus-within]– 输入框聚焦时应用 - Invalid:
[data-invalid]– 父级 TextField 为无效时应用 - Disabled:
[data-disabled]或[aria-disabled]– 父级 TextField 为禁用时应用
API 参考
InputGroup Props
InputGroup 继承 React Aria Group 组件的全部 props。
Base Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | (values: GroupRenderProps) => React.ReactNode | - | 子组件(Input、TextArea、Prefix、Suffix)或渲染函数。 |
className | string | (values: GroupRenderProps) => string | - | 用于样式的 CSS 类,支持渲染 prop。 |
style | React.CSSProperties | (values: GroupRenderProps) => React.CSSProperties | - | 行内样式,支持渲染 prop。 |
fullWidth | boolean | false | 输入组是否占满容器宽度 |
id | string | - | 元素的唯一标识符。 |
Variant Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
variant | "primary" | "secondary" | "primary" | 组件的视觉变体。primary 为默认带阴影样式。secondary 为低强调、无阴影变体,适合用在 surface 上。 |
Accessibility Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
aria-label | string | - | 没有可见标签时的无障碍标签。 |
aria-labelledby | string | - | 用于标注该组的元素 ID。 |
aria-describedby | string | - | 用于描述该组的元素 ID。 |
aria-details | string | - | 包含更多详情的元素 ID。 |
role | 'group' | 'region' | 'presentation' | 'group' | 分组的无障碍角色。重要内容可使用 region,纯视觉分组可使用 presentation。 |
Composition Components
InputGroup 与以下子组件配合使用:
- InputGroup.Root – 根容器(也可直接写作
InputGroup) - InputGroup.Input – 单行输入元素组件
- InputGroup.TextArea – 多行 textarea 元素组件
- InputGroup.Prefix – 前缀容器组件
- InputGroup.Suffix – 后缀容器组件
InputGroup.Input Props
InputGroup.Input 继承 React Aria Input 组件的全部 props。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 用于样式的 CSS 类。 |
variant | "primary" | "secondary" | "primary" | 输入的视觉变体。primary 为默认带阴影样式。secondary 为低强调、无阴影变体,适合用在 surface 上。 |
type | string | 'text' | 输入类型(text、password、email 等)。 |
value | string | - | 当前值(受控)。 |
defaultValue | string | - | 默认值(非受控)。 |
placeholder | string | - | 占位符文本。 |
disabled | boolean | - | 是否禁用输入。 |
readOnly | boolean | - | 是否只读。 |
InputGroup.TextArea Props
InputGroup.TextArea 继承 React Aria TextArea 组件的全部 props。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 用于样式的 CSS 类。 |
variant | "primary" | "secondary" | "primary" | textarea 的视觉变体。primary 为默认带阴影样式。secondary 为低强调、无阴影变体,适合用在 surface 上。 |
value | string | - | 当前值(受控)。 |
defaultValue | string | - | 默认值(非受控)。 |
placeholder | string | - | 占位符文本。 |
rows | number | - | 可见文本行数。 |
disabled | boolean | - | 是否禁用 textarea。 |
readOnly | boolean | - | 是否只读。 |
InputGroup.Prefix Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 前缀中要展示的内容(图标、文字等)。 |
className | string | - | 用于样式的 CSS 类。 |
InputGroup.Suffix Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 后缀中要展示的内容(图标、按钮、徽章等)。 |
className | string | - | 用于样式的 CSS 类。 |
Usage Example
import {InputGroup, TextField, Label, Button} from '@heroui/react';
import {Icon} from '@iconify/react';
function Example() {
return (
<TextField>
<Label>Email</Label>
<InputGroup>
<InputGroup.Prefix>
<Icon icon="gravity-ui:envelope" />
</InputGroup.Prefix>
<InputGroup.Input placeholder="name@email.com" />
<InputGroup.Suffix>
<Button isIconOnly size="sm" variant="ghost">
<Icon icon="gravity-ui:check" />
</Button>
</InputGroup.Suffix>
</InputGroup>
</TextField>
);
}TextArea Usage Example
import {Envelope} from "@gravity-ui/icons";
import {Description, FieldError, InputGroup, Label, TextField} from "@heroui/react";
import {useState} from "react";
function TextAreaExample() {
const [feedback, setFeedback] = useState("");
return (
<TextField fullWidth isInvalid={feedback.length > 500} name="feedback" onChange={setFeedback}>
<Label>Your Feedback</Label>
<InputGroup fullWidth>
<InputGroup.Prefix>
<Envelope className="size-4 text-muted" />
</InputGroup.Prefix>
<InputGroup.TextArea
className="resize-none"
placeholder="Share your thoughts, suggestions, or issues..."
rows={5}
value={feedback}
/>
</InputGroup>
<Description className="flex w-full items-center justify-between px-1">
<span>Maximum 500 characters.</span>
<span className="ml-auto">{feedback.length}/500</span>
</Description>
<FieldError>Feedback must be less than 500 characters</FieldError>
</TextField>
);
}




