组件/MotionButton 动效按钮

MotionButton 动效按钮

保留原生按钮和链接语义的 13 类交互与 35 个来源图标组合

自 0.6.3BETA

当前组件文档正在开发中

该页面正在持续迁移,示例与 API 可能会继续调整。

安装

import { TxMotionButton } from '@talex-touch/tuffex/motion-button'
import '@talex-touch/tuffex/base.css'
import '@talex-touch/tuffex/motion-button/style.css'

用法

全部交互与来源组合

演示可筛选 13 类交互,遍历 35 个图标组合,并切换网格、列表和图标矩阵。每项支持真实悬停、键盘聚焦、原生激活和装饰回放。选中状态与激活次数只保存在演示自己的本地状态里,复制项会真的写入剪贴板。

示例加载中...

调用方的操作与内容

sourceId 只选择视觉参数,不执行操作,也不提供默认文案。悬停可以显示勾选图标,但不宣称业务成功。只有调用方设置的 selected 才启用 activeLabel。

<script setup lang="ts">
import { ref } from 'vue'
import { TxMotionButton } from '@talex-touch/tuffex/motion-button'

const copied = ref(false)
const busy = ref(false)
const error = ref('')
const marked = ref(false)
async function copyHash() {
  busy.value = true
  error.value = ''
  try {
    await navigator.clipboard.writeText('43c29ce9cdd16459e3eab4992381b8d35b38776a')
    copied.value = true
  }
  catch {
    error.value = '无法访问剪贴板'
  }
  finally {
    busy.value = false
  }
}
</script>

<template>
  <TxMotionButton source-id="4" label="复制提交" active-label="已复制"
    :selected="copied" :disabled="busy" @click="copyHash" />
  <p role="status">{{ error }}</p>
  <TxMotionButton variant="sparkle" label="标记本地条目" :selected="marked" @click="marked = !marked">
    <template #icon><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M4 6h16M4 12h16M4 18h16" /></svg></template>
    <template #active-icon><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M20 6 9 17l-5-5" /></svg></template>
    <template #default="{ selected }">{{ selected ? '已标记本地条目' : '标记本地条目' }}</template>
  </TxMotionButton>
</template>

应用负责真实业务操作和图标内容。内容插槽用于标签和装饰,需要独立操作的控件应放在按钮外。

焦点模糊链接

来源 35 渲染真实链接或按钮的分组。组件不创建占位地址,也不把多个交互元素包在一个按钮里。

<script setup lang="ts">
import { ref } from 'vue'
import { TxMotionButton } from '@talex-touch/tuffex/motion-button'
const lastLabel = ref('')
</script>

<template>
  <TxMotionButton source-id="35" label="项目链接" :items="[
    { label: '仓库', href: 'https://github.com/TalexDreamSoul/talex-touch' },
    { label: '文档', href: '/docs' },
    { label: '本地操作' },
  ]" @select="item => lastLabel = item.label" />
  <output>{{ lastLabel }}</output>
</template>

最佳实践

  • 用 label、默认插槽或 ariaLabel 提供明确名称。图标矩阵中的控件也需要无障碍名称。
  • 在 @click 或 @select 中执行真实操作。根据调用方状态设置 selected 和 activeLabel。悬停与回放不报告成功,也不改写业务状态。
  • 导航用 href,表单提交用 type="submit"。按钮保留 Enter 和空格激活,链接保留 Enter 激活及组合键打开方式。
  • 操作不可执行时设置 disabled。禁用链接会移除地址和 Tab 停靠,不依靠装饰遮罩拦截事件。
  • 使用 sourceId 选择原始组合。内容不同时可以覆盖 variant、图标和颜色,也可以通过插槽提供自己的图标。
  • 焦点模糊的 #item 插槽只放非交互标签。外层原生链接或按钮已经负责聚焦和激活。
  • 设置 animated=false 保留内容和静态端点。减少动态效果、文档隐藏、控件离屏及 KeepAlive 失活都会暂停装饰动画。

API 参考

属性

属性类型默认值说明
sourceIdMotionButtonSourceId—原始字符串 ID "1"~"35",选择交互、图标对、活动颜色/填充和保留时间。不提供可见文案或业务操作。
variantMotionButtonVariant来源预设,否则 morph显式覆盖交互类型,下方列出全部 13 个值。
labelstring''调用方提供的可见标签。图标控件没有 ariaLabel 时也用它命名。
activeLabelstring—仅在 selected === true 时替换 label。
ariaLabelstring—覆盖无障碍名称。焦点模糊模式用于分组名称。
iconMorphIconSource来源预设首个图标,接受内置名称、SVG 路径 d、Lucide 风格 IconNode,以及 IconMorph 支持的 SVG 源码。
activeIconMorphIconSource来源预设,否则 icon图标对交互的目标图标。
iconColorstring来源预设,否则 currentColorpulse/shake 的首个图标活动颜色,也是目标颜色的回退值。静止图标继承控件文字颜色。
activeIconColorstring来源预设,否则 iconColor目标图标颜色,接受 CSS 颜色或 token,立即切换。
activeFillboolean来源预设,否则 false在 pulse/color-morph/morph 中填充活动图标。
size'xs' | 'sm' | 'md' | 'lg'md高度分别为 24/30/36/42 px,沿用 TuffEx 尺寸词汇。
disabledbooleanfalse原生按钮禁用,或移除链接地址和 Tab 停靠。焦点模糊模式会禁用所有条目。
animatedbooleantrue共享生命周期允许时启用装饰动画。
selectedboolean—调用方提供的目标图标状态,按钮同步 aria-pressed。不执行业务,也不确认成功。
hrefstring—渲染原生链接,代替按钮。
targetstring—原生链接目标窗口。
relstring_blank 时为 noopener noreferrer原生链接关系,显式值优先。
type'button' | 'submit' | 'reset'button原生按钮类型,不应用于链接。
iconOnlybooleanfalse只显示图标的方形控件,保留无障碍名称。
hoverBackgroundstringvar(--tx-fill-color)交互背景立即变化,不对悬停颜色补间。
holdDurationnumber来源预设,否则 0离开后保留装饰目标图标的毫秒数。4/21/22/24/25 默认保留 500 ms,不保留成功文案。
springTransition各元素的源参数显式覆盖几何弹簧。默认外层布局为 500/25,普通图标为 600/25,rotate/text-reveal 为 400/25,expand-ring 为 400/20,焦点轮廓为 350/20,通知点为 600/15。也接受 duration/ease;物理参数会传给 IconMorph。
magneticStrengthnumber0.35磁吸的指针偏移倍数。
magneticRangenumber—可选的作用距离,单位 px。未设置时保留目录样例在按钮内不限制距离的行为。
magneticSpringSpringConfig{ stiffness: 500, damping: 25 }磁吸位移与归零共用的逐帧弹簧。
itemsreadonly MotionButtonItem[][]焦点模糊的调用方条目。每项有 label,可选 href、target、rel 和 disabled。
blurAmountnumber4焦点模糊的其他条目模糊半径,单位 px。
opacityAmountnumber0.4其他条目的不透明度,限制在 0~1。
showBracketsbooleantrue显示活动条目的虚线轮廓。

id、name、value、form、download、aria-expanded 和 aria-controls 等原生属性透传到实际元素。焦点模糊模式的透传属性应用于分组。

事件

事件参数说明
clickMouseEvent普通按钮或链接的原生激活。禁用时不发出,不隐式更新状态,也不延迟业务操作。
select(item: MotionButtonItem, index: number, event: MouseEvent)启用的焦点模糊条目被原生激活。调用方未阻止默认事件时保留导航。

插槽

插槽参数说明
default{ active, selected, disabled }可见标签和内容,回退为经 TextMorph 渲染的 label。空焦点模糊分组也提供此回退。
icon{ active, selected }自定义首个图标。morph/color-morph 可用单个作用域图标插槽根据活动状态渲染。
active-icon{ active, selected }slide-arrow、sparkle、ring、morph 和 color-morph 的目标图标。成对插槽保留来源位移或缩放切换。
reveal{ active }text-reveal 的第二行揭示文字。它属于装饰,不重复进入无障碍名称,默认仍显示同一标签。
item{ item, index, active }焦点模糊的条目标签,不放嵌套交互控件。

暴露方法

方法签名说明
replay() => void回放视觉轨迹,不发出 click/select,不改写 selected。磁吸位移/归零和焦点模糊也可回放。失活或禁用时不启动工作。
focus() => void聚焦原生控件,或焦点模糊中首个启用的条目。

CSS 变量

变量默认值说明
--tx-motion-button-height24/30/36/42 px尺寸档位的控件高度。
--tx-motion-button-pad12/16/24/28 px尺寸档位的水平内边距。
--tx-motion-button-duration图标/轮廓弹簧解析结果图标和轮廓的几何过渡时长,失活时为零。
--tx-motion-button-ease图标/轮廓弹簧解析结果图标和轮廓的几何/透明度编译曲线。
--tx-motion-button-layout-duration500/25 弹簧解析结果外层内边距和缩放的过渡时长。
--tx-motion-button-layout-ease500/25 弹簧解析结果独立外层几何曲线。
--tx-motion-button-dot-duration600/15 弹簧解析结果ring 通知点过渡时长。
--tx-motion-button-dot-ease600/15 弹簧解析结果独立通知点曲线。
--tx-motion-button-hover-bghoverBackground立即切换的交互背景。
--tx-motion-button-icon-color解析后的目标颜色shake 的活动标签颜色,图标颜色和填充也立即变化。
--tx-motion-button-blurblurAmount焦点模糊的其他条目滤镜。
--tx-motion-button-dimopacityAmount焦点模糊的其他条目不透明度。

类型

导出 MotionButtonProps、MotionButtonEmits、MotionButtonInstance、MotionButtonItem、MotionButtonSize、MotionButtonVariant、MotionButtonSourceId、MotionButtonCatalogEntry 和 TxMotionButtonInstance。MotionButton 可安装,TxMotionButton 是 Vue 组件。MOTION_BUTTON_VARIANTS、MOTION_BUTTON_SOURCE_IDS、MOTION_BUTTON_CATALOG 和 MOTION_BUTTON_PRESETS 提供真实枚举与来源元数据。

交互独立轨迹
slide-arrow首个图标向左退出 10 px,标签保持连续,右侧图标从右侧 10 px 进入。宽度和间距沿 600/25 弹簧变化。
sparkle首个图标向上退出 15 px 并缩至 0.8,目标从下方进入。两个星粒分别从 −45°/+45° 回转,延迟 50/100 ms。
morph各来源线条图标对使用 IconMorph 的向量几何,0.5→1 的缩放和透明度入场保留来源切换节奏。
color-morphBookmark、ThumbsUp 和 Star 各保留自己的轮廓,立即切换颜色和填充,保留来源缩放/透明度节奏。
pulseHeart 在 400 ms 内按 1→1.25→1 脉冲缩放,活动填充和颜色立即变化。
rotateSettings 或 RefreshCw 图标沿 400/25 弹簧旋转 180°,离开时归零。
shakeTrash2 在 400 ms 内按 0/−2/0/−2/0 px 上下移动,同时按 0/−10°/10°/−10°/0° 摇动。
ringBell/BellRing 按 −15°/15° 和 0.8 倍缩放切换。独立的 6 px 通知点延迟 100 ms,沿自己的 600/15 弹簧弹出。
glare50 px、−20° 的光泽在 850 ms 内从 −150% 扫到 150%,间隔 1 s,仅交互时循环。
text-reveal箭头旋转 45°,两个 18 px 文本行沿 400/25 弹簧向上移动一行。
magnetic指针偏移乘以 strength 拉动控件,单一共享弹簧保留速度并回到同一原点。
expand-ring图标缩放至 1.1,独立轮廓在 600 ms 内从 1 扩散至 1.15,并淡出。
focus-blur其他真实链接/按钮模糊并降低透明度,活动条目的虚线轮廓沿 350/20 弹簧从 1.3 缩放至 1.1。

概述

  • 显式 variant、图标、颜色和 holdDuration 优先于 sourceId。来源标签只用于归属信息,不自动变成应用文案。
  • 悬停、聚焦、指针按下和回放驱动装饰。selected 保留目标图标并启用 activeLabel,始终由调用方提供。来源实现中仅凭悬停宣称“已复制”的行为不沿用。
  • 内容和装饰层不拦指针事件。普通控件使用原生按钮/链接,焦点模糊的各条目也保留原生语义和可见键盘轮廓。禁用链接没有 href、Tab 停靠或激活事件。
  • 原生表单提交/重置和链接导航不改成 JavaScript 键盘模拟。Enter/空格按下装饰遵循实际元素支持的按键。
  • 共享活动边界停止 CSS 循环、待执行回放帧、保留/回放定时器、磁吸 RAF 和图标/文字变形。SSR 不读取浏览器 API。减少动态效果时保留可读内容与静态端点。
  • 回放只处理视觉:先绘制静止姿态,再进入同一轨迹。磁吸回放只读一次控件尺寸,复用拉动和归零弹簧;焦点模糊回放强调首个启用条目。

技术实现

  • 上游:Amicro,MIT,Copyright (c) 2026 SYED SUBHAN UDDIN。
  • 行为来源:src/components/AnimatedButton.tsx:39~415、src/data/buttons.tsx:43~77 和 src/components/cards/FocusBlur.tsx:17~73。已阅读 registry 的 hover/magnetic-button.tsx 与 hover/glow-button.tsx,独立 registry 版本归入 Motion 交互组件族。
  • 原始图标来自上游锁文件固定的 lucide-react 0.546.0。全部 46 个 SVG 图标保留原始节点和几何属性,仅移除 React key。ISC 与 Feather 派生部分的 MIT 声明完整保存在 icons.ts 的 @license 头中。
  • TuffEx 落点:motion-button/src/TxMotionButton.vue、catalog.ts、icons.ts 和 MotionButtonGlyph.vue。图标变形复用 IconMorph,文字值变化复用 TextMorph,物理与生命周期复用已有共享弹簧和 useMotionActivity。活动边界变化时以实例 key 销毁旧变形控制器,不只改变减少动态效果标志。
  • 下表保留全部 35 个实际组合。ID 改变图标、轨迹参数、填充和保留时间,不只是更换标签。固定标签属于来源元数据,可见文案由调用方提供。
来源 ID来源组合交互图标来源
1Download for Macslide-arrowApple → ArrowRightbuttons.tsx:43
2Star on GitHubsparkleGitHub → Starbuttons.tsx:44
3Deploy AppmorphCloud → CloudUploadbuttons.tsx:45
4Copy HashmorphCopy → Check;保留图标 500 msbuttons.tsx:46
5SponsorpulseHeart;活动填充buttons.tsx:47
6SharemorphLink → Sendbuttons.tsx:48
7PreviewmorphPlay → Pausebuttons.tsx:49
8SettingsrotateSettingsbuttons.tsx:50
9DeleteshakeTrash2buttons.tsx:51
10SubscriberingBell → BellRingbuttons.tsx:52
11SearchmorphSearch → Xbuttons.tsx:53
12ThememorphMoon → Sunbuttons.tsx:54
13MicrophonemorphMic → MicOffbuttons.tsx:55
14CameramorphVideo → VideoOffbuttons.tsx:56
15VolumemorphVolume2 → VolumeXbuttons.tsx:57
16LockmorphLock → Unlockbuttons.tsx:58
17DirectorymorphFolder → FolderOpenbuttons.tsx:59
18VisibilitymorphEye → EyeOffbuttons.tsx:60
19Save Latercolor-morphBookmark 轮廓 → 填充buttons.tsx:61
20Likecolor-morphThumbsUp 轮廓 → 填充buttons.tsx:62
21DownloadmorphDownload → Check;保留图标 500 msbuttons.tsx:63
22UploadmorphUpload → Check;保留图标 500 msbuttons.tsx:64
23AccountmorphUser → UserCheckbuttons.tsx:65
24SubmitmorphSend → Check;保留图标 500 msbuttons.tsx:66
25EditmorphPen → Check;保留图标 500 msbuttons.tsx:67
26NetworkmorphWifi → WifiOffbuttons.tsx:68
27PowermorphBattery → BatteryChargingbuttons.tsx:69
28ExpandmorphMaximize → Minimizebuttons.tsx:70
29ReloadrotateRefreshCwbuttons.tsx:71
30Favoritecolor-morphStar 轮廓 → 填充buttons.tsx:72
31Glare ShineglareStar 与扫过的光泽buttons.tsx:73
32Text Revealtext-revealArrowRight 与两个文本行buttons.tsx:74
33Magnetic FieldmagneticGitHub 与真实指针拉动buttons.tsx:75
34Expand Ringexpand-ringLink 与独立扩散轮廓buttons.tsx:76
35Focus Blur Linksfocus-blur调用方提供的链接/按钮分组buttons.tsx:77
查看源码
packages/tuffex/packages/components/src/motion-button/index.ts