跳到主要内容

Input 输入框

单行输入。44px 高(control.lg),8px 圆角(radius.md),灰底无边框,focus 时显橙色描边。

多行内容请用 <Textarea />。Input 不接受 multiline / numberOfLines

实时预览

下方渲染的就是 src/components/ui/Input/Input.tsx 本体,通过 react-native-web 翻译成浏览器节点。

idle / filled / error / focus
请输入 11 位手机号

状态

来源:src/components/ui/TextField/styles.ts(值取自 src/theme/colors.ts)。状态优先级 error > focus > filled > idle

状态背景边框
idlec.surfaceContainerHigh(亮色 #F0F0F0透明
focusc.surface#FFFFFF1px c.primary#EB6E00
filledc.surface#FFFFFF1px c.outline#EDEDED
errorc.surface#FFFFFF1px c.error#F4511E

视觉规范

来源:src/components/ui/TextField/styles.ts

元素规则
高度44px(control.lg,可用 height prop 覆盖)
圆角8px(radius.md
内边距paddingHorizontal: space[5](12)
字号t.body(15),色 c.foreground#333333
占位文字c.foregroundSubtle#999999
错误文字下方独立 <Text>t.micro(11)/ c.error
leading / trailing任意 ReactNode(自填 <Icon> 等);间距 gap: space[3](8)
disabled容器 opacity: 0.5 + editable=false

用法

import { Input, Icon } from '@unif/react-native-design';
import { useColors } from '@unif/react-native-design';

<Input value={text} onChangeText={setText} placeholder="搜索…" />

{/* 密码:直接透传 RN TextInput 的 secureTextEntry */}
<Input
value={pwd}
onChangeText={setPwd}
secureTextEntry
placeholder="密码"
/>

{/* 多行:用 Textarea,不要再用 Input multiline */}
<Textarea
value={text}
onChangeText={setText}
minHeight={88}
placeholder="详细说明…"
/>

{/* 错误态 */}
<Input
value={text}
onChangeText={setText}
error="格式不正确"
/>

{/* 自定义前后插槽 —— 颜色走 hook */}
function MyForm() {
const c = useColors();
return (
<Input
value={text}
onChangeText={setText}
leading={<Icon name="search" size={18} color={c.foregroundSubtle} />}
trailing={text ? <Icon name="close" size={14} color={c.foregroundSubtle} /> : null}
/>
);
}

API

InputProps = Omit<TextInputProps, 'style' | 'multiline' | 'numberOfLines'> + 这 6 个扩展。所有 RN TextInput propsvalue / onChangeText / placeholder / secureTextEntry / keyboardType / returnKeyType / autoCapitalize 等)都直接可用。

PropType说明
leadingReactNode?前置插槽(图标、label 等)
trailingReactNode?后置插槽(清除按钮、显示密码切换等)
errorstring?错误文字 —— 容器进入 error 态(红描边)并在下方显示
heightnumber?覆盖容器高度,默认 dim.controlLg(44)
disabledboolean?整体禁用 + 视觉变灰,优先级高于 editable
containerStyleStyleProp<ViewStyle>?容器外层样式(不是 TextInput 的 style)

testID 来自透传的 TextInputProps:设在外层容器,内层 <TextInput> 自动派生 ${testID}-inputstyle / multiline / numberOfLinesOmit 掉——容器样式走 containerStyle,多行请用 <Textarea />

没有内置的 clearable / leadingIcon —— 自己组合 <Icon>leading/trailing 即可。Search 组件就是基于这种组合的预设。多行文本请用 <Textarea />

无障碍(a11y)

来源:src/components/ui/Input/Input.tsxTextField/TextFieldBase.tsxtypes.ts

输入框的核心 a11y 来自 RN 内置的 TextInput(Input 是 TextFieldBase 的薄 wrap,最终渲染原生 <TextInput>)。

  • 默认 accessibilityRole:不显式设置 —— 继承底层 <TextInput>(RN/平台自带文本框语义,无需我们硬编码 role)。
  • a11y props:InputProps = Omit<TextInputProps, 'style' | 'multiline' | 'numberOfLines'> + 6 个扩展,所以 RN TextInput 的全部 a11y / 行为 props(accessibilityLabelplaceholderkeyboardTypesecureTextEntry 等)都直接透传到 <TextInput>。朗读文案优先来自 accessibilityLabel,缺省时由 placeholder / value 提供。
  • 包裹层唯一额外设置的 a11y 是:disabled 时对内层 <TextInput>accessibilityState={{ disabled: true }}(同时 editable=falsedisabled 优先级高于 editable);非 disabled 时不附加该状态。
  • error 文字渲染为下方独立 <Text>与输入框做程序化关联(无 accessibilityLabelledBy / describedBy),SR 会作为相邻文本读到。
// placeholder 无法完全替代 label;无可见 label 时显式传 accessibilityLabel
<Input value={phone} onChangeText={setPhone} placeholder="11 位手机号" accessibilityLabel="手机号" keyboardType="phone-pad" />