Files
workspace/code/fms/.codebuddy/plans/button-enhance_280ee511.md
T
2026-08-16 22:01:32 +08:00

6.0 KiB
Raw Blame History

name, overview, todos
name overview todos
button-enhance 为 Button 组件补齐行为层能力:nativeType、disabled、loading、size、block 五个 prop,配套样式与 token,并更新 App.vue 展示页示例。
id content status
add-size-tokens 在 tokens.css 新增 sm/lg 尺寸、内边距与字号 token completed
id content status dependencies
button-props 改造 button.vue:新增 nativeType、disabled、loading、size、block 五个 prop 与 spinner 模板 completed
add-size-tokens
id content status dependencies
button-styles 扩展 index.scss:实现 size、block、disabled、loading 与 spinner 动画样式 completed
add-size-tokens
id content status dependencies
app-demo 更新 App.vue 展示页补充禁用、加载、尺寸、通栏示例 completed
button-props
button-styles

产品概述

为现有 Button 组件补齐行为层能力,使其从"纯视觉变体"升级为可直接用于表单和异步场景的交互组件,同时保持当前克制、token 驱动的设计语言。

核心功能

  • 原生 type 控制:新增 nativeType prop,默认 button,避免放入表单时误触发表单提交
  • 禁用态:新增 disabled prop,禁用点击、hover/active 效果,光标提示 not-allowed
  • 加载态:新增 loading prop,显示内联 SVG spinner,标记 aria-busy,加载期间禁止交互且布局宽度不跳动
  • 尺寸三档:新增 size prop(small / default / large),通过 token 驱动高度、内边距与字号
  • 通栏模式:新增 block prop,按钮占满整行宽度,适配表单底部操作区

技术栈

  • Vue 3 <script setup> 组合式 API
  • Sass/SCSS(项目已装 sass ^1.102.0,沿用 <style scoped lang="scss"> + @use './index.scss' 模式)
  • 设计 token 驱动(CSS 变量,命名沿用 --fms- 前缀)

实现方案

总体策略

不改动现有 6 种视觉变体(default/secondary/outline/ghost/danger/link)和基础交互,只在组件上追加行为层 prop 与对应 class,向后完全兼容。尺寸三档、禁用态、加载态全部通过 token 与 scoped 样式实现,单一来源,符合项目既有模式。

关键决策

  • nativeType 默认 button:HTML 原生 <button> 默认 type="submit",显式设默认值消除表单误提交隐患,同时保留透传覆盖能力。
  • loading 复用 disabled 语义:loading 时计算属性 isDisabled = disabled || loading,统一走原生 :disabled 路径,避免重复点击;同时挂 aria-busy 供屏幕阅读器识别。
  • spinner 用内联 SVG:项目无图标库,参考 ThemeToggle.vue/ColorThemePicker.vue 的内联 <svg> 写法,不引入新依赖;spinner 前置、文字保留占位,避免加载时按钮宽度跳变。
  • 尺寸走 token 而非写死数值:新增 --fms-control-height-sm/lg、--fms-control-padding-x-sm/lg、--fms-font-size-sm/lg 三组 token,与现有 --fms-control-height(default)形成三档体系,延续「font-size 已 token 化」的既有约定。
  • disabled 态覆盖 hover/active::disabled 下取消 transform: scale(0.97) 与背景/文字颜色变化,保证「看起来不能点」;spinner 旋转动画纳入 prefers-reduced-motion: reduce 降级,与现有动效处理一致。

实现要点

button.vue 改造

  • 新增 props:nativeType(String,默认 'button')、disabled(Boolean,默认 false)、loading(Boolean,默认 false)、size(String,默认 'default',可选 'small' | 'large')、block(Boolean,默认 false)。
  • classes 计算属性在原有 button、button-${type} 基础上追加:size !== 'default' 时加 button-${size},block 加 button-block,loading 加 button-loading。
  • 模板绑定 :type="nativeType"、:disabled="isDisabled"、:aria-busy="loading || undefined",loading 时在 <slot> 前渲染 spinner SVG。
  • 沿用 <style scoped lang="scss">@use './index.scss';</style> 不改变隔离方式。

index.scss 扩展

  • 新增 .button-small / .button-large:分别引用 sm/lg 的 height、padding-x、font-size token。
  • 新增 .button-block:display: flex; width: 100%。
  • 新增 .button:disabled:cursor: not-allowed、opacity 降低、取消 hover/active 的颜色与缩放效果(需覆盖各 type 的 hover 规则)。
  • 新增 .button-spinner:固定尺寸(约 14px)、animation: spin 旋转,@media (prefers-reduced-motion: reduce) 下 animation: none。

tokens.css 扩展

  • 在「控件」分组补充:--fms-control-height-sm: 24px、--fms-control-height-lg: 40px、--fms-control-padding-x-sm: 8px、--fms-control-padding-x-lg: 14px。
  • 在「字体」分组补充:--fms-font-size-sm: 12px、--fms-font-size-lg: 16px。
  • 深色模式 .dark 下尺寸 token 与浅色一致,无需重复覆盖。

App.vue 展示页更新

  • 在现有 6 种 type 行下方补充示例分组:禁用态(disabled)、加载态(loading)、三种尺寸(small/default/large)、通栏(block)。
  • 保持现有 .button-row 布局与卡片容器风格一致。

目录结构

fms-vue/src/
├── theme/
│   └── tokens.css                        # [MODIFY] 新增 sm/lg 尺寸与字号 token
├── components/ui/button/
│   ├── button.vue                        # [MODIFY] 新增 5 个 prop、spinner 模板、aria/disabled 绑定
│   └── index.scss                        # [MODIFY] 新增 size/block/disabled/loading/spinner 样式
└── App.vue                               # [MODIFY] 补充禁用、加载、尺寸、通栏示例

验证方式

  • pnpm dev 启动后检查:disabled 按钮不可点击且光标为 not-allowed;loading 按钮显示 spinner 且重复点击无效、宽度不跳动;三种尺寸视觉正确;block 按钮占满容器宽度。
  • 表单场景验证:<Button nativeType="submit"> 可正常提交,默认按钮不触发提交。