企業ソフトウェア · 新しいリソース

ServiceNow Horizonデザインシステム.

Horizon Workspace の正確な余白、角丸、タイポグラフィのリファレンスを、下書きの保持、入力検証、ステータスフィルター、復帰処理を備えた、ローカルで完結するリクエストの作成からレビューまでの一連の流れで確認できます。

OpenDesign ガイド6章参考項目19件オリジナルアプリケーションガイド
01

ServiceNow Horizonデザインシステムのインターフェースプレビュー

レコードを切り替えても下書きを保持し、リクエストをレビュー済みにして、フィルタリングや再オープン後も作業を続けられます。

少数のリクエストキューを確認する完全な例を開く
ローカルのCabinおよびLatoフォントを使用したオリジナルのHTML/CSS/JavaScript。ServiceNowプラットフォームとの接続はありません。· 実装リファレンス
02

ServiceNow Horizonデザインシステムのデザインリファレンス

公開されているHorizon Workspaceの間隔、角丸、タイポグラフィのリファレンス。オリジナルアプリの色は、この公式リファレンステーブルには意図的に含めていません。

公開されているWorkspaceの間隔

ソース
名前 / ルール値 / 設定用途
$now-global-space--xxs2px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--xs4px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--sm8px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--md12px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--lg16px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--xl24px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--xxl32px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。
$now-global-space--3xl40px公開済みの正確なSassリファレンス名です。CSSのカスタムプロパティを独自に作成したものではありません。

公開されている角丸

ソース
名前 / ルール値 / 設定用途
now-global-border-radius--sm2px公開デザインリファレンス。小さい値はコンパクトなラベル、中くらいの値はネストされたコントロール、大きい値はコンテナに適しています。
now-global-border-radius--md6px公開デザインリファレンス。小さい値はコンパクトなラベル、中くらいの値はネストされたコントロール、大きい値はコンテナに適しています。
now-global-border-radius--lg8px公開デザインリファレンス。小さい値はコンパクトなラベル、中くらいの値はネストされたコントロール、大きい値はコンテナに適しています。

公開されているタイポグラフィの役割

ソース
名前 / ルール値 / 設定用途
Heading familyCabinドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
Body familyLatoドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
header-hero32pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
header-primary24pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
header-secondary20pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
header-tertiary16pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
title-primary20pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
title-secondary16pxドキュメントに記載されたWorkspaceのタイポグラフィの役割。このスタディでは、公開されているCabinおよびLatoのフォントファイルをローカルで読み込みます。
03

ServiceNow Horizonデザインシステム完全ガイド

実際のインターフェースで、このデザインシステムを選び、適用し、レビューするための実践ガイドです。

DESIGN-servicenow-horizon.md

詳しいガイダンス、実装の出発点、ソースへのリンクをまとめています。

ガイドをダウンロード

ServiceNow Horizonデザインシステム:Workspaceと実装範囲

まずアプリのフレームワークから始める

Horizonは複数のServiceNowアプリフレームワークを対象としています。このページではWorkspaceに焦点を当てます。キューと選択中のレコードを並べて表示するため、レビュー担当者は文脈を失わずにローカルの作業を進められます。Service Portal、Native Mobile、Core UIを互いに置き換え可能なスキンとして扱うものではありません。ライブスタディはオリジナルのHTMLアプリであり、埋め込み型のServiceNowインスタンスではありません。

この OpenDesign ガイドから

検証済みの基盤と独自の選択を分ける

リファレンスには、公開済みの正確な間隔名、角丸値、タイポグラフィの役割を記載しています。スタディで使用する緑のアクションカラー、ニュートラルな背景、フォーカスブルーは、アプリ用の接頭辞を付けて宣言した独自のOpenDesign値です。公式のHorizonトークンを書き出したものとはしていません。完全なサンプルの実行に、独自に作成したServiceNowパッケージのインストールやプラットフォームAPIは必要ありません。

ServiceNow Horizonデザインシステム:Workspaceの間隔、角丸、文字スタイル

実際の間隔のスケールを使う

ドキュメントに記載されたスケールは2、4、8、12、16、24、32、40pxです。このスタディでは、キューとレコードの間隔、レコード内のパディング、メタデータ間のより小さな間隔を区別するために使っています。同じ値が繰り返されても、それぞれ異なるグループ関係を表します。画面全体を一律のパディングにすると、この階層が失われます。

見出しと本文には別々の役割を持たせる

公開されているファミリーの役割に合わせ、見出しにはCabin、本文にはLatoを使用しています。スタディでは、幅の広い画面のページ見出しを32px、レコード見出しを24pxにしています。角丸のリファレンスは2、6、8pxで、汎用的な4/8/12の並びを前提としていません。角丸のステータスラベルは、形や色だけでステータスを伝えるものではなく、「Open」または「Reviewed」のテキストも含みます。

ServiceNow Horizonデザインシステム:キュー、選択中のレコード、フィルタリング

選択中のレコードを1件に保つ

キュー内の各アクションには、練習用リクエストの名称、担当者、ステータスが表示されます。選択すると、隣の詳細欄が更新され、新しい見出しにフォーカスが移ります。選択中のアクションにはaria-currentと視認できる枠線スタイルが設定されます。これはネイティブのHorizonコンポーネントAPIではなく、独自のリスト/詳細パターンです。状態ロジックはすべて確認できるように提供しています。

フィルターで選択中の項目が除外された場合に復帰する

ステータスフィルターで、表示するキューを絞り込みます。選択中のリクエストが絞り込み結果に含まれなくなった場合は、該当する最初のリクエストが自動的に選択されます。該当するリクエストがない場合は、空の状態を示すメッセージと「すべてのリクエストを表示」アクションが表示されます。件数は3件すべてのレコードを分母として表示します。フィルタリングによってレコードが削除されたり、ステータスが通知なく変更されたりすることはありません。

  • 選択中のレコードを、現在のフィルター結果に含まれる状態に保ちます。
  • 該当するレコードがない場合は、わかりやすい空の状態を表示します。
  • データを削除せず、「すべてのリクエストを表示」から復帰できるようにします。

ServiceNow Horizonデザインシステム:下書きメモとレビューの検証

下書きを該当するレコードに保持する

レビュー担当者が入力すると、対応するレコードの下書きがテキストエリアで更新されます。別のリクエストに移動して戻っても、下書きは保持されます。空欄または空白文字だけのメモでは、リクエストをレビュー済みにできません。インラインエラーが表示され、aria-invalidが設定され、フォーカスがテキストエリアに戻ります。データモデルでは、保存済みメモと現在の下書きを明確に分けています。

ローカルの状態遷移を確認できるようにする

ServiceNow Horizonデザインシステム:再オープンとアクセシブルなフィードバック

再オープン時にも作業内容を保持する

「リクエストを再オープン」すると、保存済みメモを保持したまま、レビュー済みのレコードがOpenに戻ります。Reviewedのみのフィルターを適用している場合、リストが空になることがあります。その場合は復帰アクションでキュー全体を再表示できます。この組み合わせは、ボタンを個別に確認するだけではわかりにくい、レコードの状態、フィルタリング、選択中の詳細の関係を検証できます。

テキスト、フォーカス、ステータスを組み合わせる

ステータスの色にはテキストラベルを併用します。入力検証では修正が必要なフィールドにフォーカスし、レコード移動時には見出しにフォーカスします。ローカルでの更新はステータス領域で通知します。このスタディは、本番Workspaceで支援技術を使ったテストが不要になることを意味しません。テストを始めるための、完全で確認可能なローカルフローを提供します。

ServiceNow Horizon デザインシステムの完全なローカルソースと確認項目

公開フォントの依存関係をインストールする

提供されたエントリーでは、公開されている Cabin と Lato のフォントパッケージ、および元の構成用スタイルシートをインポートします。HTML シェルがルート要素を提供します。この例には ServiceNow のランタイム、認証情報、エンドポイントは含まれていません。実際のプラットフォーム連携は、ローカルのレコード配列を ServiceNow のAPI契約として扱うのではなく、Horizon の Workspace と開発者向けリソースから始めてください。

  1. 素のアプリに公開フォントの依存関係をインストールします。
  2. エントリー、スタイルシート、ルートHTMLシェルをすべて保存します。
  3. レビューを保存する前に、下書きが保持されることを確認します。
  4. ステータスによる絞り込みと、再オープンおよび空状態からの復帰を組み合わせます。

連携したワークフローを確認する

空のメモを送信し、下書きを入力したあと、別のリクエストに移動して戻り、内容が保持されていることを確認します。レコードをレビュー済みにし、「レビュー済み」で絞り込んでから再オープンします。空状態からの復帰とメモの保持も確認します。画面幅が狭い場合、キューの下に詳細が表示され、すべての操作が利用できます。これらの状態変化とあわせて、フォントの読み込み、JavaScriptのエラー、横方向のオーバーフローも確認します。

ServiceNow Horizon デザインシステムのコンポーネント例

main.js — キューとレビューの完全なロジック

すべてのレコード、下書き、フィルター、入力検証、復旧処理を含みます。

JavaScript
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 — 独自の構成

文書化されたタイポグラフィ、間隔、角丸の値を参照し、色にはアプリ固有の接頭辞を付けています。

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 — ルートシェル

スタンドアロンアプリのエントリーポイント全体です。

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 を置き換えます。
04

ServiceNow Horizon デザインシステムのエージェント設定

実装の出発点

ここでは独自の検証用サンプルのみを実行します。ServiceNow のネイティブ実装には、適切なプラットフォーム開発環境が必要です。

シェル
npm create vite@latest horizon-study -- --template vanilla
cd horizon-study
npm install
npm install @fontsource/[email protected] @fontsource/[email protected]
# Save index.html at root; main.js and horizon.css in src.
npm run dev

あなたのプロジェクト向けプロンプト

AI エージェント用プロンプト
検証済みの Horizon Workspace のタイポグラフィ、間隔、角丸の値を使って、独自のリクエストレビュー用サンプルを完成させてください。色にはアプリ固有の接頭辞を付けます。レコードごとの下書きを保持し、レビュー前に入力を検証し、ステータス変更後にフィルター適用後の選択状態を更新し、再オープン時もメモを保持して、空状態から復帰できるようにします。ServiceNow にライブ接続しているとは主張しないでください。
05

ServiceNow Horizon デザインシステムの情報源と適用範囲

Horizon Workspace の基盤を参考にした、独自のOpenDesign HTML/CSSサンプルです。文書化された Cabin/Lato のタイポグラフィと間隔・角丸の値を使い、色とワークフローのロジックは独自に設計しています。ServiceNow のインスタンスでも、ネイティブの Workspace ランタイムでもありません。