关于 thinking-orbs
thinking-orbs 是 React 组件包,用单色动态圆点呈现不确定的 AI 活动状态。它提供六种状态和两种固定尺寸,并内置主题、可见性及减少动态效果的处理。
主要功能
- 01六种常见 AI 任务状态
- 02两种固定画布尺寸
- 03自动处理主题和可见性
- 04减少动态效果时显示静态帧
- 05原始画布帧绘制 API
适用场景
- 01在 React 界面显示搜索或推理状态
- 02在 AI 生成回复旁展示状态
- 03提供适配减少动态效果设置的反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill thinking-orbs安装后在 Claude Code 中输入/thinking-orbs确认已加载。
附带文件agents/openai.yamlREFERENCES.md
详细介绍
思考光球
核心约定
- 在需要提供不确定性 AI 活动反馈的 React 18+ 界面中使用
thinking-orbs。 - 将产品的实际生命周期映射到已提供的六种状态之一。
- 仅使用经过调校的
20或64像素尺寸。不要将一个预设拉伸成另一个尺寸。 - 除非周围界面的主题固定,否则保持
theme="auto"。 - 如果活动对用户很重要,请将光球与简洁、可见的状态文本搭配使用。
- 将
aria-label覆盖为针对具体任务的标签;如果相邻的实时文本已播报相同状态,也可以让辅助技术忽略光球。 - 使用
paused冻结当前帧。不要用speed={0}模拟暂停。 - 将光球视为不确定性反馈,绝不能将其用作进度百分比或完成信号。
此包会在透明的 2D 画布上渲染单色圆点。不支持自定义颜色、任意尺寸或确定性进度。
安装
检查项目使用的包管理器,然后安装:
npm install thinking-orbs
此包将版本为 18 或更高版本的 react 和 react-dom 声明为对等依赖。从包根目录导入组件和导出的类型:
import {
ThinkingOrb,
type OrbSize,
type OrbState,
type OrbTheme,
type ThinkingOrbProps,
} from "thinking-orbs";
选择状态
working— 通用工具执行、多步骤工作,或没有更精确状态的活动。searching— 检索、网页搜索、文件搜索或知识查询。solving— 推理、分析、计算或规划。listening— 麦克风输入、语音采集,或等待用户以语音发言。composing— 撰写、总结、起草或生成文本回复。shaping— 创建或优化图像、布局、结构化内容或其他成型输出。
与其选择视觉效果醒目却不准确的状态,不如优先使用真实可信的通用 working 状态。仅当底层活动发生变化时才更改状态。
选择尺寸
- 在文本行内、按钮中或紧凑的状态行中使用
size={20}。 - 在聊天头像大小的场景、空状态中,或作为主要视觉状态时,使用
size={64}。
这些预设的圆点数量、圆点大小和速度调校各不相同。它们是独立设计,而非缩放比例。如果布局需要更多周围空间,请调整外层容器的大小,而不要对画布应用 CSS 变换。
基本用法
import { ThinkingOrb } from "thinking-orbs";
export function AgentStatus() {
return (
<ThinkingOrb
state="searching"
size={20}
theme="auto"
aria-label="Searching project files…"
/>
);
}
其他所有画布属性都会透传,包括 className、style、data-*、事件处理程序和 ARIA 属性。
对应产品生命周期
将产品阶段与视觉状态分开,以明确映射关系:
import { ThinkingOrb, type OrbState } from "thinking-orbs";
type AgentPhase =
| "idle"
| "retrieving"
| "reasoning"
| "writing"
| "creating"
| "done"
| "error";
const ORB_BY_PHASE: Partial<Record<AgentPhase, OrbState>> = {
retrieving: "searching",
reasoning: "solving",
writing: "composing",
creating: "shaping",
};
export function AgentActivity({ phase }: { phase: AgentPhase }) {
const state = ORB_BY_PHASE[phase];
if (!state) return null;
return <ThinkingOrb state={state} size={20} />;
}
在 done、error、取消或空闲时移除光球。应显示相应的结果、重试或错误界面,而不是让最后一个活动动画继续运行。
只播报一次状态
组件默认使用 role="img",并为每种状态提供相应标签,例如“正在搜索……”。当可见文本描述相同状态时,应让该文本成为唯一的播报来源:
export function LiveAgentStatus() {
return (
<div role="status" aria-live="polite" className="agent-status">
<ThinkingOrb state="solving" size={20} aria-hidden="true" />
<span>Reviewing the repository…</span>
</div>
);
}
普通阶段变化使用 aria-live="polite"。避免标签频繁变化。如果 role="status" 已负责播报,则不要再添加另一个隐藏的实时区域。
主题
使用以下选项之一:
<ThinkingOrb theme="auto" />
<ThinkingOrb theme="dark" />
<ThinkingOrb theme="light" />
auto首先检查祖先元素上的data-theme="dark|light"属性,或dark/light类。- 如果不存在祖先主题,
auto会遵循prefers-color-scheme。 - 主题变化会实时更新。
dark表示适用于深色背景的浅色圆点。light表示适用于浅色背景的深色圆点。
画布是透明的。请根据实际表面而非仅根据页面根元素检查对比度。
速度与暂停
<ThinkingOrb state="working" speed={0.85} />
<ThinkingOrb state="composing" paused={isWaitingForApproval} />
speed 会按比例调整所选状态和尺寸的预设速度。请从 1 开始;若需微调产品动画,建议使用约 0.75–1.25。极端值可能让精心调校的动画显得过于急促或停滞。
paused 会冻结当前帧,同时保留视觉状态。活动实际结束后,请移除组件。
Next.js 和客户端渲染
该组件使用 React effect、画布、requestAnimationFrame、媒体查询和观察器。在 Next.js App Router 中,请将包导入放在客户端边界之后:
"use client";
import { ThinkingOrb } from "thinking-orbs";
export function ThinkingStatus() {
return <ThinkingOrb state="working" size={20} />;
}
该库兼容 SSR,因为它只会在客户端解析主题后绘制。框架强制区分服务端组件和客户端组件时,仍然需要客户端边界。
内置运行时行为
- 使用纯 Canvas 2D 弧线绘制;不使用 WebGL 或 SVG 滤镜。
- 将设备像素比上限设为
2。 - 每个可见实例使用一个
requestAnimationFrame循环。 - 使用共享的
performance.now()时钟,让多个光球保持同步。 - 画布滚动到视口外时,通过
IntersectionObserver暂停。 - 浏览器标签页隐藏时暂停。
- 在
prefers-reduced-motion: reduce下渲染一个确定性的静态帧。 - 在减少动态效果模式下继续跟随实时主题变化。
不要在包装组件中重新实现这些行为。围绕该组件添加产品状态管理和布局,而不是再创建一个动画循环。
高级用户 Canvas API
产品 UI 优先使用 <ThinkingOrb>。该包还会导出解析后的预设和原始帧绘制器,供 React 之外的自定义画布使用:
import { MODE_DRAWS, resolvePreset } from "thinking-orbs";
const { mode, speed, opts } = resolvePreset("searching", 64);
const drawFrame = MODE_DRAWS[mode];
drawFrame(
context,
64,
(performance.now() / 1000) * speed,
true, // true draws light ink for a dark surface
opts,
);
STATE_TO_MODE 会公开内部映射:
working→orbitssearching→globesolving→rubiklistening→wavecomposing→ribbonshaping→morph
仅当其他渲染器负责管理画布生命周期时,才使用原始 API。它提供的是帧绘制器,而非组件行为。绕过 <ThinkingOrb> 时,请自行实现 DPR 尺寸调整、清除画布、动画调度、暂停、主题解析、减少动态效果、可见性处理、清理和无障碍支持。
验证
运行项目的类型检查、测试、生产构建和 git diff --check。然后在真实浏览器中验证:
- 触发每个产品阶段,确认映射后的光球状态准确。
- 确认
20和64像素的实例无需 CSS 缩放也清晰锐利。 - 测试深色、浅色主题以及实时主题切换。
- 测试减少动态效果模式,确认光球变为具有代表性的静态帧。
- 将光球滚动到视口外再返回;确认它恢复运行且没有明显异常。
- 隐藏并恢复标签页;确认动画恢复运行。
- 检查无障碍支持:状态只播报一次,并使用针对具体任务的标签。
- 确认光球在成功、错误、取消和空闲状态下都会消失。
- 确认没有控制台错误、水合警告或布局偏移。
常见问题
- 尺寸类型错误: 尺寸只能使用
20或64;不要传入任意尺寸。 - 对比度不正确: 请记住,
dark针对深色背景,因此绘制的是浅色图案。 - 屏幕阅读器重复播报: 如果相邻的
role="status"文本已播报任务状态,请隐藏画布。 - 状态具有误导性: 生成期间不要显示
searching,麦克风采集期间不要显示composing。 - 加载 UI 一直存在: 工作结束后移除光球,并渲染实际的终态。
- 水合或服务端组件错误: 将导入移入客户端组件。
- 需要品牌色: 公共 API 为单色;请改用其他加载指示器,或有意创建库的分支,而不要依赖不受支持的样式。
交接
报告映射后的产品阶段、选定的尺寸、主题模式、无障碍标签策略、减少动态效果行为,以及构建和浏览器验证情况。区分本地实现与已部署版本。