Skip to main content

按钮与表单

Summary

按钮与表单组件统一操作反馈、输入外观和焦点样式。Button 提供四种外观与三种尺寸,IconButton 必须提供可访问名称;Segmented、Slider 和 Switch 由应用保存状态。DropdownSelect 提供统一主题的下拉菜单,以字符串回调更新选择;原生 Select 保留浏览器事件接口。字段组件把标签、说明和错误关联到控件,表单校验与提交由应用负责。

参考资料​

效果展示​

进度
提醒已关闭

示例状态保存在当前组件中,刷新页面后恢复初始值。

按钮​

属性类型与默认值用途
variantprimary、secondary、ghost、danger;默认 secondary操作层级
sizesm、md、lg;默认 md控件尺寸
leftIconReactNode文字前的图标
fullWidthboolean填满可用宽度
roundedboolean胶囊形圆角
activeboolean按钮选中态,同时设置 aria-pressed

Button 支持原生按钮属性和 ref,默认 type="button"。表单提交应显式设置 type="submit"。

267 Btsx
import { Button, IconButton } from '@lailai0916/ui';

export function Actions() {
return (
<>
<Button variant="primary" type="submit">
保存
</Button>
<IconButton label="关闭" size="sm">
×
</IconButton>
</>
);
}

IconButton 的 label 必填。默认 variant="ghost",尺寸为 sm 或 md;顶部栏的搜索、导航等图标操作使用 variant="header",与语言和主题按钮共享圆角、悬停边框、按压、焦点与图标描边。顶部样式在桌面为 32 像素,在宽度不超过 980 像素或粗指针设备上为 44 像素,尺寸由该样式统一管理;图标推荐使用 17 像素。

209 Btsx
import { Icon, IconButton } from '@lailai0916/ui';

<IconButton variant="header" label="搜索" title="搜索(⌘K / Ctrl+K)" onClick={openSearch}>
<Icon icon="lucide:search" width={17} />
</IconButton>;

两种外观均保留原生按钮属性、ref 与操作提示。示例中的搜索状态和 openSearch 由应用提供。

语言按钮​

LanguageButton 接受 locale="en" | "zh-Hans" 和 onLocaleChange。按钮显示当前的“EN”或“中”,点击请求切换到另一种语言;翻译、保存偏好和路由由宿主管理。

默认提示与可访问名称说明当前语言及切换目标,也可通过 label 覆盖。悬停或键盘聚焦显示提示,Escape 关闭;桌面为 32 px,小于等于 980 px 或触摸设备增至 44 px。支持原生按钮属性与 ref,默认 type="button"。

示例只切换按钮状态。实际应用应把回调连接到自己的语言管理器。

选择与调整​

组件必要属性可选属性与行为
Segmentedvalue、items;按钮模式提供 onChange默认纵向;orientation="horizontal" 横向;size="sm" 紧凑;ariaLabel 命名选择组
Slidervalue、min、max、onChangestep、label、valueLabel、onCommit、aria-label
Switchchecked、onChange用 aria-label 提供开关用途

Segmented.items 中每项包含 value 和 label,可附 icon。按钮模式采用单选组语义,通过方向键移动和选择。横向排列在 480 px 以下堆叠,也可指定 stackAt={360},或用 stackAt={0} 始终保持横向。

size 默认为 md。size="sm" 使用紧凑文字和 32 px 高的选项,在小屏或触摸设备上增至 44 px;选中块、圆角和焦点样式与默认尺寸一致。

导航模式给每一项设置 href,选中值由当前路由决定,此时不会调用 onChange。同一组不要混用按钮与链接。

440 Btsx
import { useState } from 'react';
import { Segmented } from '@lailai0916/ui';

export function DensityControl() {
const [density, setDensity] = useState('compact');
return (
<Segmented
ariaLabel="显示密度"
orientation="horizontal"
value={density}
onChange={setDensity}
items={[
{ value: 'compact', label: '紧凑' },
{ value: 'comfortable', label: '宽松' },
]}
/>
);
}

Slider.onChange 接收数值,Switch.onChange 接收布尔值;它们与原生输入框的事件参数不同。

下拉选择​

DropdownSelect 和 DropdownSelectField 从 0.3.5 起提供统一外观的单选菜单。触发按钮和展开列表均使用组件库样式,随宿主的浅色与深色主题切换。

选择导出文件的格式。

属性类型与行为
options必填;每项包含字符串 value、字符串 label,可设 disabled;value 应唯一
value、onValueChange受控值与更新回调;回调接收新的字符串值
defaultValue非受控模式的初始值,与 value 二选一
placeholder尚未选择时显示的文字,不能代替标签
id、name控件 ID 与表单字段名;提供 name 后选中值可由 FormData 读取
disabled、required、invalid整个控件禁用、必填语义与错误状态
ref指向触发按钮,类型为 HTMLButtonElement
557 Btsx
import { useState } from 'react';
import { DropdownSelectField } from '@lailai0916/ui';

export function ExportFormatField() {
const [format, setFormat] = useState('json');
return (
<DropdownSelectField
label="导出格式"
name="format"
required
value={format}
onValueChange={setFormat}
description="选择导出文件的格式。"
options={[
{ value: 'json', label: 'JSON' },
{ value: 'csv', label: 'CSV' },
{ value: 'xlsx', label: 'Excel', disabled: true },
]}
/>
);
}

非受控模式使用 defaultValue;无初始选择时可设置 placeholder。基础组件应通过关联标签、aria-label 或 aria-labelledby 提供可访问名称。

243 Btsx
import { DropdownSelect } from '@lailai0916/ui';

<DropdownSelect
aria-label="排列顺序"
name="sort"
defaultValue="updated"
options={[
{ value: 'updated', label: '最近更新' },
{ value: 'name', label: '名称' },
]}
/>;

DropdownSelectField 要求可见 label,支持 description、error 和 wrapperClassName。它自动生成 ID、关联说明和错误;传入 error 同时设置 aria-invalid。wrapperClassName 用于外层布局,className 用于触发按钮。颜色、圆角和阴影通过公开的 --lk-* 主题变量定制。

方向键移动选项,Enter 或空格确认,Home 和 End 跳至首尾,输入文字可定位选项,Escape 关闭菜单。禁用项不可选;长列表可滚动,弹层会根据可用空间调整位置。在 Dialog 内使用时,菜单保持在对话框内交互,不需要额外挂载主题 Provider。

Select 和 SelectField 仍使用原生 <select>,保留浏览器与系统的展开菜单。它们接受 <option> 子元素、原生 onChange 事件和 HTMLSelectElement ref;新下拉组件接受 options 数组、onValueChange(string) 和按钮 ref,不支持原生 multiple、size 或 <optgroup> 接口。替换时应同步调整属性与事件处理。

表单字段​

TextField、TextAreaField 和 SelectField 分别接受原生 input、textarea、select 属性。三者均要求 label,支持 description、error,并自动生成字段 ID、连接说明与错误消息。

727 Btsx
import { useState } from 'react';
import { SelectField, Stack, TextAreaField, TextField } from '@lailai0916/ui';

export function ProfileFields() {
const [email, setEmail] = useState('');
return (
<Stack>
<TextField
label="电子邮箱"
type="email"
autoComplete="email"
required
value={email}
onChange={(event) => setEmail(event.currentTarget.value)}
description="用于接收通知。"
/>
<TextAreaField label="备注" rows={3} defaultValue="" />
<SelectField label="语言" defaultValue="zh-Hans">
<option value="zh-Hans">简体中文</option>
<option value="en">English</option>
</SelectField>
</Stack>
);
}

校验失败时传入具体的 error 文案,组件会设置 aria-invalid 并关联错误消息。业务校验、请求状态与提交处理由宿主负责;不要把占位文字作为唯一标签。

原生控件与应用操作​

Input、TextArea 和 Select 提供不带标签框架的基础控件,保留原生属性、事件与 ref。应用提供关联标签;通常优先使用 TextField、TextAreaField、SelectField。字段的 wrapperClassName 只安排外层布局,代码内容可使用 monospace。

PasswordInput 与 PasswordField 提供密码显隐,默认操作名称跟随 Provider 语言,也可设置 showLabel、hideLabel。显隐按钮不会提交表单,autoComplete 由应用选择。

Checkbox、Radio 必须提供可见 label,可附加 description;受控选中状态、name、value、disabled 与事件采用原生输入接口。

ButtonLink 接受 to 或 href,使用 Button 同款 variant、size、rounded、fullWidth 与 leftIcon,通过 Provider 接入路由。CopyButton 接受待复制的 value,默认反馈跟随语言,复制失败时明确提示;onCopied 与 onError 可接入应用处理。