#Input 输入框
用于输入单行文本,如姓名、邮箱或搜索关键词。
#基础输入
可以使用 Lucide 图标作为前缀,或通过原生 type 指定邮箱、密码等输入方式。
交互预览基础输入
basic.tsx
import { Input } from '@sudden3/leaf-ui';
import { Mail, Search } from 'lucide-react';
export function InputBasic() {
return (
<div className="leaf-demo-stack">
<Input aria-label="项目名称" placeholder="为你的项目起个名字" />
<Input aria-label="搜索项目" prefix={<Search />} placeholder="搜索项目" />
<Input aria-label="邮箱" type="email" prefix={<Mail />} placeholder="hello@leaf.design" />
<Input aria-label="只读项目名称" defaultValue="Leaf Garden" readOnly />
</div>
);
}
#密码输入
设置 type="password" 可输入密码并切换可见状态。可自定义切换图标,也可以隐藏切换按钮。
交互预览密码输入
password.tsx
import { Input } from '@sudden3/leaf-ui';
import { Eye, EyeOff, LockKeyhole } from 'lucide-react';
import { useState } from 'react';
export function InputPassword() {
const [visible, setVisible] = useState(false);
return (
<div className="leaf-demo-stack">
<Input
type="password"
aria-label="密码"
placeholder="请输入密码"
autoComplete="new-password"
prefix={<LockKeyhole />}
/>
<Input
type="password"
aria-label="受控密码"
defaultValue="leaf-garden"
visible={visible}
onVisibleChange={setVisible}
visibilityIcon={(shown) => (shown ? <EyeOff size={16} /> : <Eye size={16} />)}
/>
<Input type="password" aria-label="禁用密码" defaultValue="leaf-garden" disabled />
<Input
type="password"
aria-label="无切换按钮"
placeholder="不展示切换按钮"
visibilityToggle={false}
/>
</div>
);
}
#校验与禁用
通过 status 表达校验结果,并用 aria-describedby 关联说明。只读内容使用 readOnly。
交互预览校验与禁用
项目名称不能为空。
states.tsx
import { Input } from '@sudden3/leaf-ui';
export function InputStates() {
return (
<div className="leaf-demo-stack">
<Input aria-label="禁用输入" disabled placeholder="暂时不可编辑" />
<Input
aria-label="项目名称错误"
status="error"
placeholder="请输入项目名称"
aria-describedby="project-error"
/>
<span id="project-error" className="leaf-demo-error">
项目名称不能为空。
</span>
<Input aria-label="名称警告" status="warning" defaultValue="已经存在相似名称" />
</div>
);
}
#受控输入与回车
onPressEnter 在按下 Enter 时触发;输入法正在组合文字或事件已被阻止时不会触发。
交互预览受控输入与回车
已提交:等待输入
controlled.tsx
import { Input } from '@sudden3/leaf-ui';
import { useState } from 'react';
export function InputControlled() {
const [value, setValue] = useState('');
const [submitted, setSubmitted] = useState('');
return (
<div className="leaf-demo-stack">
<Input
aria-label="输入并回车"
value={value}
placeholder="输入后按 Enter"
onChange={(event) => setValue(event.target.value)}
onPressEnter={() => setSubmitted(value)}
/>
<span className="leaf-demo-note" aria-live="polite">
已提交:{submitted || '等待输入'}
</span>
</div>
);
}
#尺寸对齐
按钮、输入框和选择器提供一致的小、中、大三种尺寸,方便在同一行中排列。
交互预览尺寸对齐
sm
md
lg
control-sizes.tsx
import { Button, type ControlSize, Input, Select } from '@sudden3/leaf-ui';
export function ControlSizes() {
return (
<div className="leaf-demo-stack leaf-demo-stack--wide">
{(['sm', 'md', 'lg'] as const).map((size: ControlSize) => (
<div key={size} className="leaf-demo-control-row">
<span className="leaf-demo-size">{size}</span>
<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>
</div>
))}
</div>
);
}
#清除与字数统计
交互预览清除与字数统计
11 / 30
4 字
当前内容:Leaf Garden
clear.tsx
import { Input } from '@sudden3/leaf-ui';
import { useState } from 'react';
export function InputClear() {
const [value, setValue] = useState('Leaf Garden');
return (
<div className="leaf-demo-stack">
<Input
aria-label="项目名称"
value={value}
onChange={(event) => setValue(event.target.value)}
allowClear
showCount
maxLength={30}
/>
<Input
aria-label="关键词"
defaultValue="Leaf"
allowClear
showCount={(text) => `${text.length} 字`}
/>
<p className="leaf-demo-note">当前内容:{value || '未填写'}</p>
</div>
);
}
#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 '@sudden3/leaf-ui';#无障碍
通过 label + htmlFor/id 或 aria-label 提供名称。placeholder 用于提示输入格式;它不能替代标签。prefix / suffix 按装饰性内容处理,请将可交互操作放在输入框外。