#Input 输入框
用于输入单行文本,如姓名、邮箱或搜索关键词。
#基础输入
可以使用 Lucide 图标作为前缀,或通过原生 type 指定邮箱、密码等输入方式。
basic.tsx
import { Form, FormField, Input } from '@ifhover/leaf-ui';
import { Mail, Search } from 'lucide-react';
export function InputBasic() {
return (
<Form layout="vertical">
<FormField label="项目名称">
<Input aria-label="项目名称" placeholder="为你的项目起个名字" />
</FormField>
<FormField label="搜索项目">
<Input aria-label="搜索项目" prefix={<Search />} placeholder="搜索项目" />
</FormField>
<FormField label="邮箱">
<Input aria-label="邮箱" type="email" prefix={<Mail />} placeholder="hello@leaf.design" />
</FormField>
<FormField label="只读项目名称">
<Input aria-label="只读项目名称" defaultValue="Leaf Garden" readOnly />
</FormField>
</Form>
);
}
#密码输入
设置 type="password" 可输入密码并切换可见状态。可自定义切换图标,也可以隐藏切换按钮。
password.tsx
import { Form, FormField, Input } from '@ifhover/leaf-ui';
import { Eye, EyeOff, LockKeyhole } from 'lucide-react';
import { useState } from 'react';
export function InputPassword() {
const [visible, setVisible] = useState(false);
return (
<Form layout="vertical">
<FormField label="密码">
<Input
type="password"
aria-label="密码"
placeholder="请输入密码"
autoComplete="new-password"
prefix={<LockKeyhole />}
/>
</FormField>
<FormField label="受控密码">
<Input
type="password"
aria-label="受控密码"
defaultValue="leaf-garden"
visible={visible}
onVisibleChange={setVisible}
visibilityIcon={(shown) => (shown ? <EyeOff size={16} /> : <Eye size={16} />)}
/>
</FormField>
<FormField label="禁用密码">
<Input type="password" aria-label="禁用密码" defaultValue="leaf-garden" disabled />
</FormField>
<FormField label="无切换按钮">
<Input
type="password"
aria-label="无切换按钮"
placeholder="不展示切换按钮"
visibilityToggle={false}
/>
</FormField>
</Form>
);
}
#校验与禁用
通过 status 表达校验结果,并用 aria-describedby 关联说明。只读内容使用 readOnly。
states.tsx
import { Form, FormField, Input } from '@ifhover/leaf-ui';
export function InputStates() {
return (
<Form layout="vertical" onSubmit={(event) => event.preventDefault()}>
<FormField label="禁用输入">
<Input disabled placeholder="暂时不可编辑" />
</FormField>
<FormField label="项目名称错误" error="项目名称不能为空。">
<Input placeholder="请输入项目名称" />
</FormField>
<FormField label="名称警告">
<Input status="warning" defaultValue="已经存在相似名称" />
</FormField>
</Form>
);
}
#受控输入与回车
onPressEnter 在按下 Enter 时触发;输入法正在组合文字或事件已被阻止时不会触发。
controlled.tsx
import { Form, FormField, Input, Text } from '@ifhover/leaf-ui';
import { useState } from 'react';
export function InputControlled() {
const [value, setValue] = useState('');
const [submitted, setSubmitted] = useState('');
return (
<Form layout="vertical">
<FormField label="输入并回车">
<Input
aria-label="输入并回车"
value={value}
placeholder="输入后按 Enter"
onChange={(event) => setValue(event.target.value)}
onPressEnter={() => setSubmitted(value)}
/>
</FormField>
<Text tone="muted" aria-live="polite">
已提交:{submitted || '等待输入'}
</Text>
</Form>
);
}
#尺寸对齐
按钮、输入框和选择器提供一致的小、中、大三种尺寸,方便在同一行中排列。
sm
md
lg
control-sizes.tsx
import type { ControlSize } from '@ifhover/leaf-ui';
import { Button, Flex, Input, Select, Text } from '@ifhover/leaf-ui';
export function ControlSizes() {
return (
<Flex direction="column" gap="md">
{(['sm', 'md', 'lg'] as const).map((size: ControlSize) => (
<Flex key={size} align="center" gap="sm" wrap>
<Text tone="muted">{size}</Text>
<Input size={size} aria-label={`${size} 搜索`} placeholder="搜索项目" />
<Select
size={size}
aria-label={`${size} 状态`}
defaultValue="all"
options={[
{ label: '全部状态', value: 'all' },
{ label: '进行中', value: 'active' },
]}
/>
<Button size={size}>查询</Button>
</Flex>
))}
</Flex>
);
}
#清除与字数统计
clear.tsx
import { Form, FormField, Input, Text } from '@ifhover/leaf-ui';
import { useState } from 'react';
export function InputClear() {
const [value, setValue] = useState('Leaf Garden');
return (
<Form layout="vertical">
<FormField label="项目名称">
<Input
aria-label="项目名称"
value={value}
onChange={(event) => setValue(event.target.value)}
allowClear
showCount
maxLength={30}
/>
</FormField>
<FormField label="关键词">
<Input
aria-label="关键词"
defaultValue="Leaf"
allowClear
showCount={(text) => `${text.length} 字`}
/>
</FormField>
<Text tone="muted">当前内容:{value || '未填写'}</Text>
</Form>
);
}
#扩展用法
搜索内容:未搜索
输入组合
extensions.tsx
import { Flex, Input, InputGroup, InputSearch, Select, Space, Text } from '@ifhover/leaf-ui';
import { useState } from 'react';
export function ExtensionDemo() {
const [query, setQuery] = useState('');
return (
<Space direction="vertical" align="stretch">
<label htmlFor="input-extension-1">
搜索
<InputSearch
id="input-extension-1"
placeholder="搜索项目"
enterButton="搜索"
onSearch={setQuery}
/>
</label>
<p role="status">搜索内容:{query || '未搜索'}</p>
<Flex direction="column" gap="sm" align="center">
<Text>输入组合</Text>
<InputGroup aria-label="网址">
<Select
style={{ width: 110 }}
defaultValue="https"
options={[{ value: 'https', label: 'https://' }]}
/>
<Input aria-label="域名" placeholder="example.com" />
</InputGroup>
</Flex>
</Space>
);
}
#Input API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | 输入框尺寸 |
status | 'error' | 'warning' | — | 校验状态 |
prefix / suffix | ReactNode | — | 输入内容前后的装饰性内容 |
onPressEnter | KeyboardEventHandler<HTMLInputElement> | — | 按下回车时触发 |
type | HTMLInputTypeAttribute | 'text' | 输入方式,密码使用 'password' |
visibilityToggle | boolean | true | 密码输入框展示切换按钮 |
visible / defaultVisible | boolean | false | 受控密码可见状态 / 初始状态 |
onVisibleChange | (visible: boolean) => void | — | 密码可见状态变化 |
visibilityIcon | (visible: boolean) => ReactNode | — | 自定义密码切换图标 |
value / defaultValue | string | number | readonly string[] | — | 受控值 / 非受控初始值 |
onChange | ChangeEventHandler<HTMLInputElement> | — | 从 event.target.value 读取内容 |
disabled / readOnly | boolean | false | 禁用 / 只读 |
ref | Ref<HTMLInputElement> | — | 输入框引用 |
allowClear | boolean | false | 展示清除按钮 |
onClear | () => void | — | 清除后触发;onChange 同样触发 |
showCount | boolean | ((value: string, maxLength?: number) => ReactNode) | false | 展示或自定义字数统计 |
其余原生属性(name、required、maxLength、autoComplete 等)直接传给 input。className 与 style 作用于外层容器,可用于布局和宽度;区域主题通过 ConfigProvider 调整。
#类型
可导入 InputProps 定义组件属性,或单独使用尺寸、校验状态类型:
import type { InputProps, ControlSize, ControlStatus } from '@ifhover/leaf-ui';#无障碍
通过 label + htmlFor/id 或 aria-label 提供名称。placeholder 用于提示输入格式;它不能替代标签。prefix / suffix 按装饰性内容处理,请将可交互操作放在输入框外。
#扩展类型
import type { InputSearchProps, InputGroupProps } from '@ifhover/leaf-ui';#InputSearchProps API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸或间距预设 |
status | 'error' | 'warning' | — | 显示状态 |
prefix | ReactNode | — | 前置内容 |
suffix | ReactNode | — | 后置内容 |
allowClear | boolean | false | 显示清除按钮 |
onClear | () => void | — | 清除输入后触发 |
showCount | boolean | ((value: string, maxLength?: number) => ReactNode) | false | 显示字数,可自定义渲染 |
visibilityToggle | boolean | true | 显示密码切换按钮 |
visible | boolean | — | 受控的密码可见状态 |
defaultVisible | boolean | false | 初始密码可见状态 |
onVisibleChange | (visible: boolean) => void | — | 密码可见状态变化 |
visibilityIcon | (visible: boolean) => ReactNode | — | 自定义密码切换图标 |
onPressEnter | KeyboardEventHandler<HTMLInputElement> | — | 按下 Enter 时触发 |
onSearch | (value: string) => void | — | 搜索或按 Enter 时触发 |
loading | boolean | false | 加载状态 |
enterButton | ReactNode | — | 搜索按钮文字,省略时展示图标 |
#InputGroupProps API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
compact | boolean | — | 连接相邻控件 |