mcpField
F
fluid-functionalism

fluid-functionalism

github.com/mickadesign设计与 UI1.1k641 次安装1 天前更新
代码仓库

关于 fluid-functionalism

Fluid Functionalism 是一个 shadcn/ui 组件注册表及配套技能,为 React 界面提供强调状态变化可见性的动效组件,并支持 Radix 与 Base UI 两种风味。它还指导组件安装、组合、界面审查及安全更新。

主要功能

  1. 01提供 Radix 与 Base UI 组件
  2. 02弹性动效与流畅悬停状态
  3. 03组件文档含交互演示和提示词
  4. 04读取项目技术栈并审查界面
  5. 05检查更新并保留本地修改

适用场景

  1. 01在 shadcn/ui 项目中安装组件
  2. 02按统一动效系统组合界面
  3. 03审查常用页面的交互体验
  4. 04升级组件并处理本地改动

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mickadesign/fluid-functionalism --skill fluid-functionalism

安装后在 Claude Code 中输入/fluid-functionalism确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
components.md
craft.md
custom-motion.md
stack-audit.md
scripts/
audit.mjs
package.json
stack.mjs
upgrade.mjs

详细介绍

流畅功能主义

一个 shadcn/ui 组件注册表,让每次状态变化都清晰可见:用弹簧动画而非固定时长;每个列表只有一个悬停高亮,它会滑向离光标最近的项目;标签加粗时不会推动相邻元素。触及基础组件的组件提供两种风格——Radix 和 Base UI——且 API 相同。

文档和实时演示:https://www.fluidfunctionalism.com — 每个组件页面都有一个 Playground 和 Copy prompt 按钮,按钮文本是一份独立完整的说明(安装命令、用法代码片段、属性、文档 URL)。

此技能涵盖四项工作:

  1. 了解项目 — 每次运行开始时读取技术栈(见下一节)。读取快速且准确,因此无需缓存,也不会过时。
  2. 安装并组合组件 — 选择合适的注册表条目和风格,将其接入,并围绕已有内容进行组合。组件目录见 references/components.md;每个文档页面和顶层区块的设计细节——其中内置的具体行为、取值和设计原因——见 references/craft.md。目录会将可单独安装的部分映射到管理它们的父级区块。组合前先阅读该区块,才能真正用好此库,而不只是安装它。
  3. 编写适合与这些组件并用的自定义 UI — 如果要构建库中未提供的内容,请遵循动效系统,让它的动态效果与应用其他部分一致。手动编写任何动画、悬停或状态变化样式前,请阅读 references/custom-motion.md。
  4. 保持更新 — 在不丢失本地工作的前提下,将已安装的条目更新到最新版本:收到更新请求时。

每次运行:读取技术栈

安装、组合或提供建议之前,请针对应用目录运行技术栈脚本,也就是包含其 package.json 和 components.json 的目录。在大多数项目中,这就是当前目录;在 monorepo 中,请将其作为参数传入:

node <skill>/scripts/stack.mjs [apps/web]

它只需要 Node,运行不到一秒,也不会写入任何内容。它会读取 FF 所需的依赖项(React 19、Tailwind v4、motion、shadcn 接线配置),确定风格,并检查两个不易察觉的质量隐患(应用周围的 MotionConfig reducedMotion="user",以及缺少 opsz 轴的 Inter),还会列出已安装的 FF 部件,以及同名文件中哪些是原始文件或本地文件。每行都会注明来源 file:line。如果没有 Node,请手动读取相同的文件: 检查项。

事实要读取,绝不凭记忆。 每项技术栈事实都能再次读取,而且比验证缓存副本更快;一旦缓存结论与代码不符,就会误导之后的每个会话。无需记录,风格结论也会保持稳定,因为每次都会以相同方式得出:先检查已安装的 FF 组件,再检查 package.json。因此,不要将审计结果写入项目;将它们写在回复中。

决定是例外。 代码无法显示用户做出的决定:不采用流畅悬停效果、特意保留静止效果,或使用非令牌时长。脚本的 DECISIONS 行会指出此前决定所在的位置,搜索范围从应用目录一直到仓库根目录。请阅读并遵循这些决定,不要再次提出已经定下的事项。是否记录新决定由你选择,记录位置应与项目现有的意图记录方式一致;参见 决定。如果脚本报告了此技能早期版本遗留的审计文件,请遵循其中的决定并忽略其中的事实 (早期审计文件)。

每次安装前,请核实目标当前文件,并比较任何同名文件的差异;只有检查确认目标仍是原始文件时,才传入 --overwrite。

当用户要求审核或提供建议时

按照 references/stack-audit.md 执行完整审核: 在阅读技术栈的基础上,挑出最有帮助的 2–5 项 UI 升级。先检查系统(动效标记、流畅悬停、表面、尺寸),再检查组件;每项按影响 / 工作量评分,并按影响与工作量之比排序。只检查 UI 和设计系统;基础设施方面的发现只陈述事实,绝不作为建议提出。以下三条规则决定这些发现如何呈现,也是建议与 lint 报告的区别:

  • 每项建议都从界面出发,而不是从导致问题的代码出发: 说明产品使用者当前看到什么、在哪个表面、他们多常看到它,以及它能改善哪方面的体验。文件和修复规模只能放在次要位置,不能作为重点。
  • 应用从未有过的行为,应该作为问题提出,而不是作为发现。 修复产品已有但表现不佳的功能,是可以给出的建议;引入新的标志性动效,尤其是流畅悬停,会改变整个产品的感受,因此应先询问用户,再决定是否将其列入建议。保持静止往往是刻意为之。
  • 安装受阻绝不能成为成果的门槛。 旧版 Tailwind 或 React 会阻止 CLI 运行,但不会阻止产品得到改进;每项改进都可以手动完成。绝不要优先提出用户未要求的迁移。

先测量,再给建议。 当应用在运行时,在提出任何建议前,先用 scripts/audit.mjs 检查使用频率最高的路由:它会移动真实指针,并报告各列表项的悬停效果是流畅滑入,还是在行间闪退;选择选项卡时是否会挤动相邻项;实际发布的过渡时长和控件高度;以及已加载的字体能否呈现字重变化。之后,每项建议和入围项都必须通过证据门槛:引用测量结果或 file:line、指出人们实际使用的表面、提出且仅提出一项 FF 修正,并经过证伪检查,删除所有无法成立的内容。“无需建议变更”是有效结果;总能发现问题的审核只会让人学会忽视它。

在回复中列出入围项。由于每项都附有证据,下次审核会根据届时的代码重新生成列表:已修复的项目会自动消失,只有被拒绝的项目才需要做出决定,以保持其处理状态。

当被要求更新时

当用户要求更新或升级 Fluid Functionalism,或询问自安装以来有哪些变化时:

  1. 读取技术栈(见上文)。更新不会将文件切换到另一种风格:每个文件都保留其导入所表明的基础库。

  2. 检查有哪些更新:

    node <skill>/scripts/upgrade.mjs [apps/web]
    

    它会将每个已安装的 FF 文件与注册表当前提供的条目进行比较,并采用文件自身导入所表明的风格,同时忽略安装时会改写的内容(导入别名、换行符、"use client" 行)。CURRENT 文件无需处理。DIFFERS 会列出其余文件及其行数;--diff <name>(或路径)会输出其中一个文件的差异,本地文件在 - 一侧,注册表版本在 + 一侧。REWRITES 行表示 CLI 还会改写其他内容(JavaScript 输出、Tailwind 前缀):请手动比较这些内容。它不会写入任何文件,并且需要访问网络以连接 fluidfunctionalism.com。

  3. 阅读变更日志: https://www.fluidfunctionalism.com/changelog.md,按月份从新到旧排列。每条记录都注明安装 URL;每条 Breaking 记录都附有迁移步骤和变更前后的差异。

  4. 对每项差异分类。 变更日志中有说明的变更,表示注册表已更新:使用报告中对应的行重新安装该条目。未说明的变更属于本地编辑:展示变更内容,并在覆盖前征求确认。同一个文件中两种变更都有:先重新安装,再重新应用本地编辑;更好的做法是将编辑移到包装组件中,这样下次更新时就能保留(见「注意事项」)。--overwrite 还会重写该条目依赖的项,报告行中会注明这些依赖:运行前请检查其中是否有本地编辑。

  5. 迁移调用位置,处理每条涉及项目所用条目的 Breaking 记录:在整个应用中查找差异中的 - 行,并将其改写为对应的 + 行。重命名会导致类型检查失败,因此让类型检查器找出它们。

  6. **验证:**运行类型检查器和构建,再次运行 upgrade.mjs(每个文件都显示为 CURRENT,或是用户选择保留的本地编辑),并逐项报告变更内容以及保留未动的内容。

切勿盲目地通过重新安装所有内容来更新:--overwrite 会抹掉本地工作,而某个版本更新可能会破坏安装过程不会触及的调用位置。

一次性项目设置

读取技术栈时会告知你以下哪些设置已完成。跳过已完成的项。

  1. 添加注册表(或按 URL 安装,见下一节):

    npx shadcn@latest registry add @fluid
    
  2. **为每个项目选定一种风格。**不带前缀的名称会安装 Radix 风格;添加 base/ 前缀则使用 Base UI。技术栈脚本会根据项目现有用法确定选择:优先检查已安装的 FF 组件,其次检查 package.json 中的 @base-ui/react → 所有位置都使用 base/ 名称;若有 @radix-ui/react-*(或尚未使用任何组件)→ 使用不带前缀的名称。input-group、color-picker 和 ask-user-questions 在两种风格下都会导入 Base UI,因此不能作为判断依据。一个项目中切勿混用两种风格——依赖项会随所选风格而变化,因此 Base UI 对话框会引入 Base UI 按钮。

  3. **在根部启用减少动态效果设置。**在应用布局中添加一行,类似 ThemeProvider:

    import { MotionConfig } from "motion/react";
    
    <MotionConfig reducedMotion="user">{/* providers + app */}</MotionConfig>
    

    这样,每个 Motion 组件都会遵循操作系统的 prefers-reduced-motion 设置:移除变换和布局动画,保留不透明度和颜色渐变(有助于理解内容)。

  4. **如果项目使用 Inter,并希望字重动画保持宽度,请加载其光学尺寸轴。**使用 next/font/google 时:Inter({ subsets: ["latin"], axes: ["opsz"] })。自行托管时:使用 font-weight: 100 900 的 @font-face,并指向 InterVariable.ttf。不使用 opsz 轴也能正常运行——只是标签在字重变粗时会稍微变宽。

安装组件

npx shadcn@latest add @fluid/button            # Radix flavor
npx shadcn@latest add @fluid/base/button       # Base UI flavor
# URL form (no registry entry needed) - the flavor lives in the path, so a
# base project needs the /base/ segment here too:
npx shadcn@latest add https://www.fluidfunctionalism.com/r/button.json       # Radix
npx shadcn@latest add https://www.fluidfunctionalism.com/r/base/button.json  # Base UI

依赖项、共享库(springs、font-weight、上下文)和钩子会自动解析——只需安装你需要的组件,无需操心其依赖。

当项目的 shadcn 文件为原始版本时,传入 --overwrite:此库安装的文件使用相同名称(button.tsx、dialog.tsx,等等),如果不加该标记,CLI 会逐个询问是否覆盖文件——非交互式 shell(你)会在第一个问题处退出。但如果这些文件包含本地自定义内容,或同目录存放了故事文件/测试(逐个比对目标文件即可确认),--overwrite 会破坏这些内容——请先检查或比对,而不要盲目传入该标记。

npx shadcn@latest add @fluid/dialog --overwrite

如果有符合需求的模块,优先选择它——sidebar-app(完整应用外壳)、dialog-sidebar(设置对话框)、queued-stack(排队的撰写器消息)都可作为单个条目安装,并包含其使用的所有组件,且已完成组合。

完整目录列出了每个组件、系统和模块,以及注册表名称、变体和功能,详见 references/components.md。选择要安装的内容时请先阅读;猜测名称会浪费一次安装往返。

预设: Sidebar、Card、InputMessage、AskUserQuestions、Dropdown、Combobox 和 CommandMenu 的 Playground 会将配置编码为一段短代码。如果用户提供了预设代码,或带有 ?preset= 的文档 URL,请直接将其作为组合模块安装: npx shadcn@latest add https://www.fluidfunctionalism.com/r/preset/<code>.json。

使用系统进行组合

已安装的组件已遵循所有规则。只有在围绕它们编写 UI 时,这些规则才会派上用场——例如自定义列表、定制卡片网格或自己制作的动画图标。配方和代码片段位于 references/custom-motion.md;系统的构成如下:

  • 三种弹簧速度,均使用令牌。 从 @/lib/springs 导入 spring.fast(0.08s)/ spring.moderate (0.16s)/ spring.slow(0.24s)。移动的对象越大,弹簧速度越慢。绝不手动编写 duration——导入 令牌,并在关闭时使用配套的 .exit 缓动,让退出动画干脆利落,而不是反向重播进入动画。
  • 页面显示只需 1 个类。 安装 @fluid/reveal,然后在页面容器上添加 1 个类:对于只读一次的页面使用 reveal-landing,对于应用使用 reveal-product,更轻微的效果使用 -subtle。应用中的数据加载较慢时, 用 reveal-swap 包裹 shadcn 的 Skeleton,使其淡入淡出并替换为真实内容块;在两者上都添加 reveal-items,即可让行逐个显示。不要在每个元素上手动实现 whileInView 淡入效果,并让主视觉图片和 标题不参与任何显示动画。规则和配方: references/custom-motion.md。
  • 每个列表只使用一个悬停高亮。 任何带悬停效果的自定义列表、菜单、条带或网格,都使用 useFluidHover + <FluidHoverHighlight />(安装 @fluid/use-fluid-hover)——不要在高亮会滑动的组件旁边, 为每一行单独设置 :hover 背景。
  • 调整字重,不触发布局重排。 状态变化时(已选中/激活/打开)需要加粗的文本,使用 ghost-span 模式和 fontWeights 令牌,确保布局不会偏移。
  • 文本采用六种角色。 使用 @/lib/size-context 中的 typeClass(role, variant) 或 useSize().type.<role> 设置文本大小(display、title、subtitle、body、caption、micro;每种角色都包含字号和行高); 服务端组件从 @/lib/type-scale 导入 typeClass。文本使用 3 种字重:正文使用 fontWeights.normal, 标题和已选项目使用 fontWeights.semibold,只有 display 样式使用 fontWeights.bold;绝不使用 Tailwind font-*。文本颜色只有 2 种:foreground 和 muted;不要通过调整不透明度来改变它们;不要使用 全大写、字母间距或眉题。绝不使用原始的 text-[13px],也不要在 cn() 中单独使用 text-caption:标准的 tailwind-merge 会将它识别为颜色并移除。文本字段使用 useSize().field,它会在触屏 屏幕上添加 16px,避免 iOS Safari 在聚焦时将页面缩放到该字段。渲染后的 markdown 放入 .typeset(安装 @fluid/typography),不要手动为元素设置样式。
  • 图标切换在同一单元格中交叉淡入淡出。 两个图形放在同一个网格单元格中,并通过淡入淡出、轻微模糊和 缩放完成切换——槽位尺寸始终不变。
  • 嵌套圆角保持同心。 一个圆角表面紧贴另一个表面时,按以下公式计算: inner radius = max(0, outer radius - inset - border);inset 是内部间距,通常为父级内边距;border 是父级 边框宽度。项目提供的形状组合(container 12/24px → bg 8/20px)适用于固定的 4px 总内缩量。 对于其他内缩量,使用 @/lib/shape-context 中的 nestedRadius(),不要重复使用该组合。超过 24px、 间隙不对称,或内层表面未延伸到圆角处时,应将各层独立处理并凭视觉调整。
  • 使用 transform/opacity 移动,绝不使用 top/left/width/height——这样动画就会由合成器处理, MotionConfig 也能免费减少动画效果。
  • 主题使用标准 shadcn 配置。 项目已有的主题令牌(颜色、圆角、字体)可直接应用;不要另行创建一套令牌。 图标默认使用 Lucide;如需在整个应用中切换图标库,应通过 @/lib/icon-context 中的 IconProvider 完成, 不要编辑已安装的组件。

最后 1%:精湛之处所在

这里的参考资料用于指导系统;每个组件的细节—— 其精确的运作方式、边缘情况的行为以及背后的原因——也都 有文档记录。按影响范围排序:

  • references/craft.md — 每个有文档记录的 系统和组件,以及每个顶层区块的精湛之处:内置行为、 精确取值和背后的原因。目录会将可单独安装的部分映射到 所属的父级章节。在组合、封装、扩展或模仿组件之前,先阅读 对应章节——这样可以避免组合后的代码与自己尚不了解的行为 相冲突(按钮已处理自身的按压几何效果;选择控件已在选中后显示 300ms 的确认反馈;面板已会在子元素收起时自动贴合)。
  • 已安装的源代码才是最终依据。 这些组件在代码注释中附有设计 理由。修改组件前,请先阅读其已安装文件(components/ui/*、 hooks/*、lib/*)——不要凭对 stock shadcn 版本行为的记忆来 更改样式或调整时序。
  • 精湛之处都记录在 references/craft.md 中。 复制提示词文档仅包含安装、用法和属性。组合组件前,请阅读其对应的 精湛之处章节,并将其中的要点视为约束,而非建议。

注意事项

  • 不要通过修改已安装的组件来改变时序或悬停行为——请改用封装或 组合。下次使用 --overwrite 安装时,修改会丢失,也会让应用偏离系统。
  • 基于带风格变体的组件构建的组件(AskUserQuestions、ColorPicker、 CommandMenu、InputCopy、InputMessage 和各个区块)也使用 base/ 前缀。单一来源的条目(badge、card、table、input-group、 chat-message、thinking-indicator、各个库和钩子)在两类项目中 使用相同名称。
  • 注册表要求使用 Tailwind CSS v4、React 19 和 motion(以 motion/react 导入)。如果技术栈较旧,请在安装一半组件之前向用户 指出不兼容之处。
  • 如果按名称安装失败,请查阅 references/components.md 中的目录——注册表 名称不一定与组件的显示名称相同(例如 TabsSubtle → tabs-subtle、 Fluid Hover → use-fluid-hover、Motion → springs)。
  • base 风格位于 base/<name> 路径下——@fluid/base/select, URL 为 /r/base/select.json。<name>-base 之类的名称是内部构建 名称;/r/<name>-base.json 按设计会返回 404(构建过程会将这些 文件移入 base/)。该处返回 404 并不意味着注册表缺少 base 风格—— 下结论前,请先尝试文档记录的 base/<name> 形式;切勿根据猜测的 URL 记录“注册表仅支持 Radix”。

评论

支持 Markdown