Files
workspace/code/fms/.codebuddy/plans/input-component_ddf8a08f.md
2026-08-16 22:01:32 +08:00

8.6 KiB
Raw Permalink Blame History

name, overview, design, todos
name overview design todos
input-component 在 fms-vue 组件库中新建 Input(基础框)、InputPassword(密码框)、Textarea(多行)三个组件,沿用 button 的「纯 scoped scss + --fms-* tokens」风格,并在 App.vue 增加演示示例。参考 参考组件库/shadcn 与 antdv-next 的设计。
architecture styleKeywords fontSystem colorSystem
framework
vue
Minimalism
Neutral
Compact
Professional
fontFamily heading subheading body
PingFang SC
size weight
20px 600
size weight
14px 500
size weight
14px 400
primary background text functional
#0f172b
#ffffff
#f5f6f8
#1f2329
#86909c
#ef4444
#f59e0b
#e5e6eb
id content status
create-input 创建 input/input.vue 与 input/index.scss(基础框:v-model、size、status、prefix/suffix、allowClear、showCount) completed
id content status dependencies
create-password 创建 input-password/input-password.vue(复用 Input,Eye/EyeOff 切换) completed
create-input
id content status
create-textarea 创建 textarea/textarea.vue 与 textarea/index.scss(多行 + showCount) completed
id content status dependencies
app-demo 在 App.vue 增加 input/password/textarea 演示区块 completed
create-input
create-password
create-textarea
id content status dependencies
verify 运行 lint 校验并自查演示渲染与 dark 适配 completed
app-demo

用户需求

在 fms-vue 组件库中新增 Input 相关组件,设计参考本地 参考组件库/shadcn 与 参考组件库/antdv-next,样式采用纯 scoped scss + --fms-* CSS 变量(延续 button 做法,零运行时)。

产品概述

为轻量组件库补充文本输入能力,包含基础输入框、密码框、多行文本域三种独立组件,并在 App.vue 增加演示区块。

核心功能

  • Input 基础框:v-model 双向绑定、disabled 禁用、size(sm/default/lg)、status(error/warning)、prefix/suffix 插槽、allowClear 一键清除、showCount 字数统计(支持 maxlength)。
  • InputPassword 密码框:在 Input 基础上增加可见性切换(Eye/EyeOff 图标按钮),支持 disabled/size/status。
  • Textarea 多行文本域:多行输入,支持 disabled/size/status/showCount/maxlength 与自适应高度(可选)。
  • 演示示例:在 App.vue 新增 input 演示区块,覆盖上述主要用法。

技术栈

  • 框架:Vue 3(<script setup> + defineProps/computed),纯前端组件库
  • 样式:scoped SCSS + @use './index.scss',复用 src/theme/tokens.css 中的 --fms-* 变量
  • 图标:@lucide/vue(button 已引入),password 用 Eye/EyeOff,clear 用 X
  • 无第三方 input 库、无 CSS-in-JS,零运行时

实现方案

采用与现有 button/ 完全一致的组件范式:单 .vue 文件 + 同目录 index.scss,computed 拼 classes、<style scoped lang="scss"> @use './index.scss',图标统一 :deep(svg){width:1em;height:1em}。

  • Input.vue:用原生 <input> 承载,外层包裹 .input-wrapper(相对定位,承载 prefix/suffix/clear/count 绝对定位元素);v-model 通过 modelValue/update:modelValue + emit 实现;allowClear 仅在 hover 且有值时显示清除按钮;showCount 在右下角显示 len/maxlength。复用 shadcn 的 data-slot="input" 与 aria-invalid 语义,聚焦环用 outline + box-shadow ring(沿用 button 的 focus-visible 风格)。
  • size 映射:tokens 仅有默认高度 32px,组件内补全 sm=24px / lg=40px(scss 局部变量,不污染全局 token),字号 sm=12px / default=14px / lg=16px。
  • status 映射:error 用 --fms-danger 边框、warning 用 --fms-warning 边框,无现成 status 变量时用 color-mix(in srgb, var(--fms-danger) 50%, var(--fms-border)) 推导柔和边框,focus 时加深。
  • InputPassword.vue:基于 Input 组合(包裹 Input 并把 suffix 替换为可见切换按钮),内部 show = ref(false) 切换 type,切换按钮 type="button" 防提交。优先复用 Input 的 prefix/suffix/clear/status 能力,仅覆写 type。
  • Textarea.vue:原生 <textarea>,结构与 Input 平行(含 showCount、status、disabled、size),不做 prefix/suffix(多行场景通常不需要)。
  • 架构可扩展性:Input 的 wrapper/clear/count 逻辑封装为内部私有函数/片段,InputPassword 直接复用 Input 组件而非复制样式,降低后续维护成本。

实现注意事项

  • 复用 lucide/vue 与 button 相同的图标缩放规则,避免重复定义。
  • allowClear 清除后需 emit('update:modelValue','') 并触发 blur/focus 可见性关闭。
  • showCount 与 maxlength 联动:未设 maxlength 时仅显示当前长度。
  • 禁用态沿用 button 的 opacity:.5;pointer-events:none + disabled 属性。
  • 不改动 button/、button-group/、tokens.css 以外的现有文件;dark 适配靠 token 自动覆盖,组件只引用变量。
  • 性能:均为轻量受控组件,无虚拟列表/大量 DOM,聚焦与输入走原生事件,无需防抖(如需可后续加)。

架构设计

组件独立、互不影响,InputPassword 依赖 Input 复用其视觉与交互。演示区块为 App.vue 内的纯展示区域,不引入新路由。

目录结构

fms-vue/src/components/ui/
├── input/
│   ├── input.vue            # [NEW] Input 基础框。v-model、disabled、size、status、prefix/suffix 插槽、allowClear、showCount、maxlength。结构:.input-wrapper > (prefix)(input)(suffix/clear)(count)。
│   └── index.scss           # [NEW] Input 样式。定义 .input / .input-wrapper / 尺寸 sm/default/lg / 状态 error|warning / prefix|suffix|clear|count 定位,复用 --fms-* tokens。
├── input-password/
│   └── input-password.vue   # [NEW] 密码框。包裹 Input,suffix 提供 Eye/EyeOff 切换 type;透传 disabled/size/status/placeholder。
├── textarea/
│   ├── textarea.vue         # [NEW] 多行文本域。v-model、disabled、size、status、showCount、maxlength;结构:.textarea-wrapper > (textarea)(count)。
│   └── index.scss           # [NEW] Textarea 样式。复用 Input 的部分变量与状态色,定义多行高度与 padding。
fms-vue/src/App.vue           # [MODIFY] 新增 input 演示区块,演示上述三种组件的主要用法(含尺寸、状态、前后缀、清除、字数统计、密码切换)。

关键代码结构

// Input props(script setup defineProps 示意)
const props = defineProps({
  modelValue: { type: [String, Number], default: '' },
  type: { type: String, default: 'text' },
  disabled: { type: Boolean, default: false },
  size: { type: String, default: 'default' },       // 'sm' | 'default' | 'lg'
  status: { type: String, default: '' },            // '' | 'error' | 'warning'
  allowClear: { type: Boolean, default: false },
  showCount: { type: Boolean, default: false },
  maxlength: { type: [String, Number], default: undefined },
})
const emit = defineEmits(['update:modelValue', 'change', 'blur', 'focus'])

设计风格

沿用现有 fms-vue 组件库的克制中性风格(与 button 一致),采用浅色卡片背景 + 细边框 + 主色聚焦环。Input 视觉对齐 antdv-next 的紧凑专业感与 shadcn 的 minimal 边框,演示区块延续 App.vue 现有分区样式(标题 + 卡片容器 + 示例行)。

页面区块(App.vue 新增演示)

  1. 区块标题「Input 输入框」+ 说明。
  2. 基础用法行:默认 input、disabled、三种尺寸(sm/default/lg)。
  3. 前后缀与清除行:prefix 图标、suffix 文本、allowClear 演示。
  4. 状态行:error / warning 状态展示。
  5. 字数统计行:showCount + maxlength。
  6. 密码框行:InputPassword 可见切换。
  7. 多行文本行:Textarea + showCount。

Agent Extensions

Skill

  • antdv-next
  • Purpose: 查询 Input/Password/TextArea 的 props、slots、事件与尺寸/状态 token 定义,确保组件 API 与 antdv-next 设计对齐。
  • Expected outcome: 获取准确的属性命名(size/status/allowClear/showCount/prefix/suffix)与默认行为,用于指导 Input 系列组件实现。
  • ui-ux-pro-max
  • Purpose: 参考现代输入框交互与聚焦/禁用/错误态视觉规范,提升组件视觉一致性与可访问性。
  • Expected outcome: 输出聚焦环、错误态、前后缀间距等专业 UI 规范,落地到 index.scss。