mcpField
T
thinking-orbs

thinking-orbs

github.com/boraoztunc设计与 UI43497 次安装11 周前更新
代码仓库

关于 thinking-orbs

面向 React 18+ 界面的状态反馈组件技能,用单色 Canvas 圆点动画表示 AI 活动阶段。它提供六种语义状态、两种固定尺寸,并内置主题、可访问性和减少动态效果处理。

主要功能

  1. 01六种活动状态
  2. 0220 和 64 像素预设
  3. 03自动浅色与深色主题
  4. 04离屏及标签隐藏时暂停
  5. 05减少动态效果与无障碍支持

适用场景

  1. 01显示搜索或分析状态
  2. 02在文本生成期间展示活动反馈
  3. 03为语音输入界面指示聆听状态
  4. 04在结果生成或结构化输出时显示状态

安装

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

$npx skills add https://github.com/boraoztunc/skills --skill thinking-orbs

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

附带文件REFERENCES.md

详细介绍

思考光球

核心约定

  1. 在需要提供不确定性 AI 活动反馈的 React 18+ 界面中使用 thinking-orbs。
  2. 将产品的实际生命周期映射到已提供的六种状态之一。
  3. 仅使用经过调校的 20 或 64 像素尺寸。不要将一个预设拉伸成另一个尺寸。
  4. 除非周围界面的主题固定,否则保持 theme="auto"。
  5. 如果活动对用户很重要,请将光球与简洁、可见的状态文本搭配使用。
  6. 将 aria-label 覆盖为针对具体任务的标签;如果相邻的实时文本已播报相同状态,也可以让辅助技术忽略光球。
  7. 使用 paused 冻结当前帧。不要用 speed={0} 模拟暂停。
  8. 将光球视为不确定性反馈,绝不能将其用作进度百分比或完成信号。

此包会在透明的 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 → orbits
  • searching → globe
  • solving → rubik
  • listening → wave
  • composing → ribbon
  • shaping → morph

仅当其他渲染器负责管理画布生命周期时,才使用原始 API。它提供的是帧绘制器,而非组件行为。绕过 <ThinkingOrb> 时,请自行实现 DPR 尺寸调整、清除画布、动画调度、暂停、主题解析、减少动态效果、可见性处理、清理和无障碍支持。

验证

运行项目的类型检查、测试、生产构建和 git diff --check。然后在真实浏览器中验证:

  1. 触发每个产品阶段,确认映射后的光球状态准确。
  2. 确认 20 和 64 像素的实例无需 CSS 缩放也清晰锐利。
  3. 测试深色、浅色主题以及实时主题切换。
  4. 测试减少动态效果模式,确认光球变为具有代表性的静态帧。
  5. 将光球滚动到视口外再返回;确认它恢复运行且没有明显异常。
  6. 隐藏并恢复标签页;确认动画恢复运行。
  7. 检查无障碍支持:状态只播报一次,并使用针对具体任务的标签。
  8. 确认光球在成功、错误、取消和空闲状态下都会消失。
  9. 确认没有控制台错误、水合警告或布局偏移。

常见问题

  • 尺寸类型错误: 尺寸只能使用 20 或 64;不要传入任意尺寸。
  • 对比度不正确: 请记住,dark 针对深色背景,因此绘制的是浅色图案。
  • 屏幕阅读器重复播报: 如果相邻的 role="status" 文本已播报任务状态,请隐藏画布。
  • 状态具有误导性: 生成期间不要显示 searching,麦克风采集期间不要显示 composing。
  • 加载 UI 一直存在: 工作结束后移除光球,并渲染实际的终态。
  • 水合或服务端组件错误: 将导入移入客户端组件。
  • 需要品牌色: 公共 API 为单色;请改用其他加载指示器,或有意创建库的分支,而不要依赖不受支持的样式。

交接

报告映射后的产品阶段、选定的尺寸、主题模式、无障碍标签策略、减少动态效果行为,以及构建和浏览器验证情况。区分本地实现与已部署版本。

评论

支持 Markdown