# ServiceNow Horizon 设计系统

## ServiceNow Horizon 设计系统界面预览

在不同记录间保留草稿，将请求标记为已审核，并在筛选或重新打开后恢复内容。

## ServiceNow Horizon 设计系统设计参考

已发布的 Horizon Workspace 间距、圆角和字体排版参考。官方参考表刻意不包含原应用配色。

### 已发布的 Workspace 间距

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| $now-global-space--xxs | 2px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--xs | 4px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--sm | 8px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--md | 12px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--lg | 16px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--xl | 24px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--xxl | 32px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
| $now-global-space--3xl | 40px | 已发布的 Sass 参考名称原样保留；这些并非虚构的 CSS 自定义属性。 |
### 已发布的圆角

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| now-global-border-radius--sm | 2px | 已发布的设计参考。小值适用于紧凑标签，中值适用于嵌套控件，大值适用于容器。 |
| now-global-border-radius--md | 6px | 已发布的设计参考。小值适用于紧凑标签，中值适用于嵌套控件，大值适用于容器。 |
| now-global-border-radius--lg | 8px | 已发布的设计参考。小值适用于紧凑标签，中值适用于嵌套控件，大值适用于容器。 |
### 已发布的字体排版角色

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| Heading family | Cabin | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| Body family | Lato | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| header-hero | 32px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| header-primary | 24px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| header-secondary | 20px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| header-tertiary | 16px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| title-primary | 20px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
| title-secondary | 16px | 文档记录的 Workspace 字体排版角色。此研究在本地加载公开的 Cabin 和 Lato 字体文件。 |
## ServiceNow Horizon 设计系统完整指南

实用指南，介绍如何为真实界面选择、应用和评审此系统。

完整指导、实现起点和源代码链接。

## ServiceNow Horizon 设计系统工作区与实施范围

### 从应用框架入手

> Horizon 涵盖多种 ServiceNow 应用框架。本页聚焦 Workspace：队列与选中记录同时显示，便于审核者在处理本地工作时保留上下文。本页不会将 Service Portal、Native Mobile 和 Core UI 描述成可以互换的外观主题。此交互式研究是一个原创的 HTML 应用，并非嵌入式 ServiceNow 实例。

### 区分已验证的基础内容与原创设计选择

参考资料给出了准确的已发布间距名称、圆角值和排版角色。本研究中的绿色操作色、中性色界面表面和焦点蓝是以 app 前缀声明的原创 OpenDesign 值，并未声称它们是官方 Horizon 令牌导出值。运行完整示例不需要安装虚构的 ServiceNow 软件包，也不需要平台 API。

## ServiceNow Horizon 设计系统工作区间距、圆角与字体

### 使用实际的间距序列

文档中列出的比例为 2、4、8、12、16、24、32 和 40px。本研究使用这些数值区分队列与记录之间的间距、记录内部的内边距，以及元数据之间更小的距离。即使重复使用同一级数值，它们也服务于不同的分组关系。如果整个屏幕采用统一内边距，层级就会变得模糊。

### 为标题和阅读文本设定不同角色

标题使用 Cabin，正文使用 Lato，与已发布的字体家族角色一致。宽屏上的页面标题为 32px，记录标题为 24px。圆角参考值为 2、6 和 8px，而不是想当然地套用通用的 4/8/12 序列。圆角状态标签不会仅凭形状或颜色传达状态，还会显示“开放”或“已审核”等文字。

## ServiceNow Horizon 设计系统队列、选中记录与筛选

### 始终保留一条选中记录

队列中的每个操作项都标明一项实践请求，并显示其负责人和状态。选中后，旁侧详情随之更新，新标题也会获得焦点。选中项带有 aria-current 属性和清晰可见的边框样式。这是原创的列表/详情模式，并非原生 Horizon 组件 API；示例提供了完整状态逻辑，供检查。

### 筛选移除选中项时妥善处理

状态筛选器会缩小队列的显示范围。如果选中的请求不再属于筛选结果，应用会自动选中第一个符合条件的请求。如果没有匹配项，则显示空状态消息和“显示所有请求”操作项。计数以包含三条记录的完整集合为分母。筛选不会删除记录，也不会悄然更改其状态。

- 确保选中记录仍属于当前筛选结果。

- 当筛选结果为空时，清晰显示空状态。

- 通过“显示所有请求”恢复列表，不删除数据。

## ServiceNow Horizon 设计系统草稿备注与审核验证

### 将草稿保留在对应记录中

审核者输入时，文本区域会更新对应记录的草稿。切换到其他请求后再返回，草稿仍会保留。备注为空或仅包含空白字符时，不能将请求标记为已审核：界面会显示内联错误、设置 aria-invalid，并将焦点移回文本区域。数据模型会明确区分已保存的备注和当前草稿。

### 让本地状态转换清晰可见

审核成功后，系统会保存去除首尾空白的备注，并将记录状态更改为“已审核”。队列会根据当前筛选条件重新计算，同时状态消息会指出受影响的记录。消息还会明确说明没有记录发送到 ServiceNow，以免视觉确认让人误以为示例执行了实际的平台操作。

## ServiceNow Horizon 设计系统重新打开与无障碍反馈

### 重新打开时保留有用内容

“重新打开请求”会将已审核记录恢复为“开放”状态，同时保留已保存的备注。在仅显示“已审核”记录的筛选条件下，列表可能因此变空；此时可通过恢复操作重新显示完整队列。这个组合能检验记录状态、筛选和选中详情之间的关系，比孤立地检查每个按钮更有参考价值。

### 结合文本、焦点和状态反馈

状态颜色始终配有文字标签。验证失败时，焦点会移至需要处理的字段；切换记录时，焦点会移至标题；本地更新则通过状态区域反馈。在正式的 Workspace 中，本研究不能取代使用辅助技术进行测试，但它提供了一套完整、可检查的本地流程，可作为测试的起点。

## ServiceNow Horizon 设计系统完整本地源代码与检查

### 安装公开的字体依赖项

提供的入口文件会导入公开的 Cabin 和 Lato 字体包，以及原创的组合样式表。其 HTML 外壳会提供根元素。本示例不包含 ServiceNow 运行时、凭据或端点。实际的平台集成应从 Horizon 的 Workspace 和开发者资源着手，而不应将本地记录数组视为 ServiceNow 的 API 契约。

1. 在原生应用中安装公开的字体依赖项。

2. 保存完整的入口文件、样式表和根 HTML 外壳。

3. 在保存审核前测试草稿保留情况。

4. 将状态筛选与重新打开及空状态恢复结合起来。

### 检查完整工作流

提交空备注，输入草稿，访问另一条请求后再返回，确认草稿仍然保留。将记录标记为已审核，筛选“已审核”并重新打开记录。检查空状态恢复和备注保留情况。在窄屏宽度下，队列会堆叠在详情上方，且不会遗漏任何操作。还要在这些状态变更过程中检查字体加载、JavaScript 错误和水平溢出。

## ServiceNow Horizon 设计系统组件示例

### main.js — 完整的队列和审核逻辑

所有记录、草稿、筛选、验证和恢复逻辑。

```
import '@fontsource/cabin/latin-600.css';
import '@fontsource/lato/latin-400.css';
import '@fontsource/lato/latin-700.css';
import './horizon.css';
const records=[{id:'REQ-104',title:'Review the workshop outline',owner:'Design team',priority:'Normal',detail:'Compare the proposed agenda with the decision the team needs to make. Capture one question that should be resolved before the workshop.'},{id:'REQ-105',title:'Check the shared resource list',owner:'Content team',priority:'High',detail:'Review the resource titles for clear action language and confirm that each summary explains when the resource is useful.'},{id:'REQ-106',title:'Prepare the research readout',owner:'Research team',priority:'Normal',detail:'Group the observations by theme. Keep direct observations separate from the team’s interpretation and include the questions still open.'}].map(x=>({...x,status:'Open',note:''}));let selected=records[0].id;
document.querySelector('#root').innerHTML=`<main><header><p class="eyebrow">OpenDesign · Workflow study</p><h1>Team review workspace</h1><p>Review three original practice requests. Update a local record while keeping the queue and details in context.</p></header><div class="toolbar"><label>Status <select id="filter"><option>All</option><option>Open</option><option>Reviewed</option></select></label><p id="queue-count" role="status"></p></div><div class="workspace"><nav aria-label="Practice request queue"><div id="queue"></div><p id="empty" hidden>No requests match this status.</p><button id="clear" hidden>Show all requests</button></nav><section id="detail" aria-labelledby="record-title"></section></div><p id="feedback" role="status"></p><footer><strong>Original application, documented foundations.</strong> Cabin headings, Lato body text, the published 2–40px spacing scale and 2/6/8px radius references inform this study. The colors and application behavior are original OpenDesign choices. This is not the ServiceNow platform or a connected Workspace.</footer></main>`;
function renderQueue(){let filter=document.querySelector('#filter').value,visible=records.filter(x=>filter==='All'||x.status===filter);if(!visible.some(x=>x.id===selected))selected=visible[0]?.id;const queue=document.querySelector('#queue');queue.replaceChildren(...visible.map(r=>{let b=document.createElement('button');b.className='queue-item';b.dataset.id=r.id;b.setAttribute('aria-current',String(r.id===selected));b.innerHTML=`<span class="record-id">${r.id}</span><strong>${r.title}</strong><span>${r.owner}</span><span class="status ${r.status.toLowerCase()}">${r.status}</span>`;b.onclick=()=>{selected=r.id;renderQueue();renderDetail();document.querySelector('#record-title')?.focus()};return b}));document.querySelector('#queue-count').textContent=`${visible.length} of ${records.length} requests`;document.querySelector('#empty').hidden=visible.length>0;document.querySelector('#clear').hidden=visible.length>0;}
function renderDetail(){const r=records.find(x=>x.id===selected),panel=document.querySelector('#detail');if(!r){panel.innerHTML='<h2 id="record-title">Choose another status</h2><p>All local requests are still available through the status filter.</p>';return}panel.innerHTML=`<p class="eyebrow">${r.id} · ${r.owner}</p><h2 id="record-title" tabindex="-1">${r.title}</h2><p>${r.detail}</p><dl><div><dt>Priority</dt><dd>${r.priority}</dd></div><div><dt>Status</dt><dd>${r.status}</dd></div></dl><form id="review"><label for="note">Review note</label><p class="hint" id="hint">Write one useful observation. This note remains in the page.</p><textarea id="note" rows="4" aria-describedby="hint error"></textarea><p id="error" class="error" hidden>Enter a review note before marking this request reviewed.</p><div class="actions"><button type="submit" class="primary">${r.status==='Open'?'Mark reviewed':'Update review'}</button><button type="button" id="reopen" ${r.status==='Open'?'hidden':''}>Reopen request</button></div></form>`;const note=panel.querySelector('#note');note.value=r.draft??r.note;note.oninput=()=>{r.draft=note.value;document.querySelector('#error').hidden=true;note.removeAttribute('aria-invalid');document.querySelector('#feedback').textContent=''};panel.querySelector('#review').onsubmit=e=>{e.preventDefault();if(!note.value.trim()){document.querySelector('#error').hidden=false;note.setAttribute('aria-invalid','true');note.focus();return}r.note=note.value.trim();r.draft=r.note;r.status='Reviewed';renderQueue();renderDetail();document.querySelector('#feedback').textContent=r.id+' reviewed locally. No record was sent to ServiceNow.';document.querySelector('#record-title')?.focus();};panel.querySelector('#reopen').onclick=()=>{r.status='Open';renderQueue();renderDetail();document.querySelector('#feedback').textContent=r.id+' reopened. The saved review note is retained.';document.querySelector('#record-title')?.focus();};}
document.querySelector('#filter').onchange=()=>{renderQueue();renderDetail();document.querySelector('#feedback').textContent=''};document.querySelector('#clear').onclick=()=>{document.querySelector('#filter').value='All';renderQueue();renderDetail();document.querySelector('#filter').focus()};renderQueue();renderDetail();
```

代码参考

- 所有交互行为均为原创应用代码，并非官方 Workspace 组件 API。

### horizon.css — 原创界面构成

采用有文档记录的字体、间距和圆角参考值，并使用带应用前缀的原创颜色。

```
:root{--app-ink:#21342c;--app-action:#285c47;--app-surface:#f2f5f3;--app-border:#c9d3cd;--app-error:#a32424;--app-radius-small:2px;--app-radius-medium:6px;--app-radius-large:8px}*{box-sizing:border-box}body{margin:0;font:16px/1.5 Lato,Arial,sans-serif;color:var(--app-ink);background:var(--app-surface)}main{max-width:1160px;margin:auto;padding:32px}h1,h2,h3{font-family:Cabin,Arial,sans-serif;font-weight:600;line-height:1.25}h1{font-size:32px;margin:8px 0 16px}h2{font-size:24px;margin:8px 0 24px}.eyebrow{font-size:12px;letter-spacing:.08em;font-weight:700}header>p:last-child{max-width:68ch}.toolbar{display:flex;justify-content:space-between;align-items:center;gap:16px;margin:24px 0}.toolbar label{display:flex;gap:12px;align-items:center}select,textarea,button{font:inherit}select{padding:8px;border:1px solid var(--app-border);border-radius:6px;background:white;color:var(--app-ink)}.workspace{display:grid;grid-template-columns:minmax(200px,1fr) minmax(0,2fr);gap:24px}nav{align-self:start}.queue-item{display:grid;gap:8px;width:100%;text-align:left;margin-bottom:12px;background:white;border:1px solid var(--app-border);border-radius:8px;padding:16px;color:var(--app-ink);cursor:pointer}.queue-item[aria-current=true]{border:2px solid var(--app-action);padding:15px;background:#e8f0ea}.queue-item strong{font-size:16px}.record-id,.queue-item>span{font-size:14px}.status{justify-self:start;border-radius:2px;padding:2px 8px;background:#e8eeeb}.status.reviewed{background:#d0ead9}.workspace section{background:white;padding:24px;border:1px solid var(--app-border);border-radius:8px;min-width:0}dl{display:flex;gap:40px;margin:24px 0}dt{font-size:14px;color:#58685f}dd{margin:4px 0;font-weight:700}form>label{font-weight:700}.hint{font-size:14px;margin:8px 0}textarea{width:100%;padding:12px;border:1px solid #6b7f72;border-radius:6px;resize:vertical;color:var(--app-ink)}button{border:1px solid #6b7f72;border-radius:6px;background:white;padding:8px 16px;color:var(--app-ink);cursor:pointer}.primary{background:var(--app-action);color:white;border-color:var(--app-action)}.actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:16px}.error{color:var(--app-error);font-weight:700}.hint,.error{max-width:60ch}#feedback:empty{display:none}#feedback{background:#d0ead9;padding:16px;border-radius:6px}footer{font-size:14px;margin-top:32px;padding-top:24px;border-top:1px solid var(--app-border)}:focus-visible{outline:3px solid #477fd0;outline-offset:3px}[hidden]{display:none!important}@media(max-width:760px){main{padding:20px}.workspace{grid-template-columns:1fr}.toolbar{flex-wrap:wrap}.workspace section{padding:16px}h1{font-size:24px}.eyebrow{overflow-wrap:anywhere}}
```

代码参考

- 不得将原创颜色值描述为官方 Horizon 设计令牌。

### index.html — 根目录外壳

独立应用的完整入口文件。

```
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Team review study</title></head><body><div id="root"></div><script type="module" src="/src/main.js"></script></body></html>
```

代码参考

- 用此文件替换根目录中的 Vite index.html。

## ServiceNow Horizon 设计系统 Agent 设置

### 实现起点

此设置仅运行原创研究项目。原生 ServiceNow 实现需要适当的平台开发环境。

```
npm create vite@latest horizon-study -- --template vanilla
cd horizon-study
npm install
npm install @fontsource/cabin@5.3.0 @fontsource/lato@5.3.0
# Save index.html at root; main.js and horizon.css in src.
npm run dev
```

### 适用于你项目的提示词

```
基于已验证的 Horizon Workspace 字体、间距和圆角参考值，构建完整的原创请求审核研究项目。原创颜色使用应用前缀。保留每条记录的草稿，在审核前进行验证，在状态变更后重新计算筛选结果中的选中项，重新打开时保留备注，并提供空状态恢复功能。不得声称与 ServiceNow 实时连接。
```

## ServiceNow Horizon 设计系统来源与范围

一项原创的 OpenDesign HTML/CSS 研究项目，参考了 Horizon Workspace 基础规范。项目采用有文档记录的 Cabin/Lato 字体及间距、圆角数值，并使用原创颜色和工作流逻辑。这不是 ServiceNow 实例，也不是原生 Workspace 运行环境。

- Workspace 概览 框架背景与相关资源。

- 间距 精确的模块化比例及 Sass 参考名称。

- 圆角 已发布的 2/6/8px 数值。

- 排版 Cabin/Lato 字体及字号角色。

- 颜色指南 用途说明和非颜色状态提示。

## ServiceNow Horizon 设计系统相关资源

### ServiceTitan Anvil

通过三级令牌模型、经过验证的明暗主题角色值，以及完整的服务分配交互，让 Anvil2 更具体：技师、时间和审核状态保持同步。

### Siemens iX

使用明确的严重程度词汇、适配主题的颜色角色和 iX Event List API 检查工业事件。本指南将构建本地设备记录簿，并清楚区分已审核记录与已解决的机器警报。

### Sprout Social Seeds

通过完整的编辑审核队列，检查 Seeds 实际公开的颜色、间距、产品字体排印和边框令牌；队列支持混合选择、筛选后的空状态和撤销操作。


- [实现参考](https://horizon.servicenow.com/workspace/overview)
- [来源](https://horizon.servicenow.com/workspace/foundations/spacing/spacing-overview)
- [来源](https://horizon.servicenow.com/workspace/foundations/corner-radius)
- [来源](https://horizon.servicenow.com/workspace/foundations/typography/typography-overview)
- [代码参考](https://horizon.servicenow.com/workspace/overview)
- [Workspace 概览 框架背景与相关资源。](https://horizon.servicenow.com/workspace/overview)
- [间距 精确的模块化比例及 Sass 参考名称。](https://horizon.servicenow.com/workspace/foundations/spacing/spacing-overview)
- [圆角 已发布的 2/6/8px 数值。](https://horizon.servicenow.com/workspace/foundations/corner-radius)
- [排版 Cabin/Lato 字体及字号角色。](https://horizon.servicenow.com/workspace/foundations/typography/typography-overview)
- [颜色指南 用途说明和非颜色状态提示。](https://horizon.servicenow.com/workspace/foundations/color/color-overview)
