跳转到正文
OrbZ入门原生 Web 组件

原生 Web 组件

原生 <orb-z> 元素是 Orbz 的基础。无论应用使用纯 JavaScript 还是框架,只要支持自定义元素就能使用。

自动注册

在应用代码中导入一次浏览器入口:

main.ts
import "@neongate-ai/orbz/browser";

模块会调用 defineOrbz()。注册带有保护:在服务器上不执行操作;若页面其他部分已注册 orb-z,则返回已有构造函数。

标签可在模块加载前后渲染。自定义元素定义完成后,浏览器会升级已有标签。

<orb-z state="idle" size="18rem"></orb-z>

连接或升级元素绝不会启动语音。宿主必须显式配置语音引擎,并在访客主动启用时调用 startTalking()。

显式注册

要精确控制注册时机,请使用根入口:

import { defineOrbz } from "@neongate-ai/orbz"; const OrbzElementClass = defineOrbz();

defineOrbz() 在浏览器中返回元素构造函数;当 customElements 或 HTMLElement 不可用时返回 undefined。可安全重复调用。

通过 HTML 属性控制

<orb-z state="thinking" size="320px" speed="1.15" preset="periwinkle" reduced-motion="system" elevated ></orb-z>

元素监听属性变化,因此更新属性会立即同步外观:

const orb = document.querySelector("orb-z"); orb?.setAttribute("state", "speaking"); orb?.setAttribute("speed", "1.25"); orb?.toggleAttribute("elevated", true);

通过 JavaScript 属性控制

在 JavaScript 中更改状态时,使用属性通常更清晰:

import type { OrbzElement } from "@neongate-ai/orbz"; const orb = document.querySelector<OrbzElement>("orb-z"); if (orb) { orb.state = "listening"; orb.size = 300; // normalized to "300px" orb.speed = 1.2; orb.reducedMotion = "system"; orb.elevated = true; }

每个公开 JavaScript 属性都会反映到对应的 HTML 属性。size 可接受转换为像素的数字,或 "20rem" 等 CSS 长度字符串。

语音引擎和对话流程仅通过 JavaScript 属性设置。先准备流程并插入元素,只有用户明确操作后才配置引擎并启动语音:

import "@neongate-ai/orbz/browser"; import { WebSpeechAdapter, type OrbzElement, type OrbzTalkStep } from "@neongate-ai/orbz"; const flow = [ { id: "welcome", kind: "say", needsAuth: false, text: "Hello." }, { id: "name", kind: "ask", needsAuth: false, text: "What is your name?", capture: "fullName" }, { id: "help", kind: "say", needsAuth: false, text: "How can I help, {{fullName}}?" }, { id: "answer", kind: "respond", needsAuth: false, strategy: "openai", fallback: "I cannot answer that right now." } ] as const satisfies readonly OrbzTalkStep[]; const orb = document.createElement("orb-z") as OrbzElement; orb.talkFlow = flow; orb.voiceEngine = new WebSpeechAdapter({ language: "en-US" }); document.body.append(orb); const startVoiceButton = document.querySelector<HTMLButtonElement>("[data-start-voice]"); startVoiceButton?.addEventListener("click", async () => { await orb.startTalking(); });

布尔属性

paused 和 elevated 遵循原生 HTML 布尔属性语义:只要属性存在就为真,与所赋字符串无关。

<!-- Elevated --> <orb-z elevated></orb-z> <!-- Also elevated: "false" is still a present attribute --> <orb-z elevated="false"></orb-z>

移除属性,或将 JavaScript 属性设为 false:

orb?.removeAttribute("elevated"); if (orb) { orb.paused = false; orb.elevated = false; }

内置预设或自定义配色

使用 preset 属性选择内置配色:

<orb-z preset="magenta"></orb-z>

默认外观是 Neongate;省略 preset 即可跨版本选择默认外观。其他预设为 periwinkle、magenta、peach、mocha 和 ivory。参见预设名称和版本兼容性。

使用自定义配色时,省略 preset 并设置五个颜色属性中的任意属性:

<orb-z color-primary="#7C3AED" color-secondary="#22D3EE" color-accent="#F472B6" color-highlight="#FDE68A" color-background="#09090B" ></orb-z>

未设置的颜色回退为 Neongate 默认值。不要同时使用显式 preset 和 color-*。若两种模式同时存在,预设优先,Orbz 会在控制台报告冲突。

由应用状态机驱动

让应用保持唯一事实来源,并使 Orbz 映射该状态:

import type { OrbzElement, OrbzState } from "@neongate-ai/orbz"; const orb = document.querySelector<OrbzElement>("orb-z"); function presentAssistantState(state: OrbzState, message: string) { if (orb) orb.state = state; const status = document.querySelector<HTMLElement>("[data-assistant-status]"); if (status) status.textContent = message; } presentAssistantState("thinking", "Assistant is preparing a response");

支持五个状态:idle、listening、thinking、speaking 和 asleep。未知值归一化为 idle。

播放方法

原生元素提供三个专用动画方法:

orb?.pause(); // freeze the current animation orb?.play(); // resume it orb?.restart(); // rebuild the current state's animation

paused 属性仍是声明式方案。在命令式浏览器集成更方便时可使用方法。

动效偏好

reduced-motion="system" 遵循用户的 prefers-reduced-motion 并响应变化。always 强制使用减少动态效果的呈现,never 强制使用完整动效。

<div role="status" aria-live="polite"> <orb-z state="thinking" reduced-motion="system"></orb-z> <span data-assistant-status>Assistant is thinking</span> </div>

在球体外提供有意义的文字。组件是视觉信号,不应成为用户了解助手状态的唯一途径。

框架模板

导入一次 /browser 后,Vue、Svelte 和 Angular 可将响应式值直接绑定到原生标签。应用与 Orbz 之间没有框架适配器或共享运行时。

完整应用见沙盒工作区 。

最近更新于