NS Design System
v3.0.0 · 257 tokens

143Syntax highlighter

The system's code surface — a title bar with the file name, copy / ask-AI / share / wrap actions, line numbers, diff-marked lines, and a footer whose one job is Run. Three chromes (block, mac, vscode) differ ONLY in the bar: the body, the palette, the footer and every interaction are identical, because a code block whose copy button moves depending on its skin is two components pretending to be one. Highlighting happens at build time via components/core/highlight.js, which maps any grammar onto seven roles — adding a language means adding a keyword list, never a colour.

Use it for

  • Lesson and docs code samples — anything longer than a term
  • A multi-file sample, as vscode tabs
  • Showing a change: added, removed and called-out lines
  • A runnable snippet, where the product supplies the runner

Not for

  • A single term inside a sentence — that is .ns-code-inline
  • An editor. This renders code; it does not edit it
  • Highlighting on the client — the markup arrives tokenised, so readers do not download a grammar to re-derive what the build already knew

Anatomy

Bar, body, and the four chrome actions. The file name is always mono and always present — a code block without a name is a code block you cannot refer to. Live: copy, wrap, and both menus work on this page.

CaseRouter.cls apex

Ask about this code

Ask Claude

The code and its language go to the assistant you pick. Nothing leaves the page until you choose one.

Share

public with sharing class CaseRouter {  // Route new cases to the right queue.  public static void route(List<Case> cases) {    for (Case c : cases) c.OwnerId = queueFor(c.Origin);  }}
markup
<figure class="ns-code" data-lang="apex">
  <figcaption class="ns-code__bar">
    <span class="ns-code__file"><i class="ph ph-code" aria-hidden="true"></i><span>CaseRouter.cls</span></span>
    <span class="ns-code__actions">
      <span class="ns-code__lang">apex</span>
      <button type="button" class="ns-code__btn ns-code__btn--icon" data-code="wrap" aria-pressed="false" aria-label="Wrap long lines"><i class="ph ph-text-align-justify" aria-hidden="true"></i></button>
      <button type="button" class="ns-code__btn" popovertarget="ai-anatomy"><i class="ph ph-sparkle" aria-hidden="true"></i><span class="ns-code__btn-label">Ask AI</span></button>
      <div id="ai-anatomy" popover="auto" class="ns-popover ns-menu ns-code__menu">
        <p class="ns-menu__label">Ask about this code</p>
        <a class="ns-menu__item" href="https://claude.ai/new" target="_blank" rel="noopener"><i class="ph ph-sparkle" aria-hidden="true"></i>Ask Claude</a>
        <button type="button" class="ns-menu__item" data-code="ask" data-provider="explain"><i class="ph ph-lightbulb" aria-hidden="true"></i>Explain this code</button>
        <button type="button" class="ns-menu__item" data-code="ask" data-provider="tests"><i class="ph ph-list-checks" aria-hidden="true"></i>Write tests for it</button>
        <button type="button" class="ns-menu__item" data-code="ask" data-provider="review"><i class="ph ph-magnifying-glass" aria-hidden="true"></i>Review for bugs</button>
        <p class="ns-code__menu-note">The code and its language go to the assistant you pick. Nothing leaves the page until you choose one.</p>
      </div>
      <button type="button" class="ns-code__btn ns-code__btn--icon" popovertarget="share-anatomy" aria-label="Share this snippet"><i class="ph ph-share-network" aria-hidden="true"></i></button>
      <div id="share-anatomy" popover="auto" class="ns-popover ns-menu ns-code__menu">
        <p class="ns-menu__label">Share</p>
        <button type="button" class="ns-menu__item" data-code="share"><i class="ph ph-link-simple" aria-hidden="true"></i>Copy link</button>
        <button type="button" class="ns-menu__item" data-code="share" data-share="native"><i class="ph ph-arrow-up-right" aria-hidden="true"></i>Share via&hellip;</button>
      </div>
      <button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button>
    </span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4
5
6</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">public</span> <span class="ns-tok-kw">with</span> <span class="ns-tok-kw">sharing</span> <span class="ns-tok-kw">class</span> <span class="ns-tok-type">CaseRouter</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">  <span class="ns-tok-com">// Route new cases to the right queue.</span></span><span class="ns-code__line">  <span class="ns-tok-kw">public</span> <span class="ns-tok-kw">static</span> <span class="ns-tok-kw">void</span> <span class="ns-tok-fn">route</span><span class="ns-tok-punct">(</span><span class="ns-tok-type">List</span><span class="ns-tok-punct">&lt;</span><span class="ns-tok-type">Case</span><span class="ns-tok-punct">&gt;</span> cases<span class="ns-tok-punct">)</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">    <span class="ns-tok-kw">for</span> <span class="ns-tok-punct">(</span><span class="ns-tok-type">Case</span> c <span class="ns-tok-punct">:</span> cases<span class="ns-tok-punct">)</span> c<span class="ns-tok-punct">.</span><span class="ns-tok-type">OwnerId</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-fn">queueFor</span><span class="ns-tok-punct">(</span>c<span class="ns-tok-punct">.</span><span class="ns-tok-type">Origin</span><span class="ns-tok-punct">);</span></span><span class="ns-code__line">  <span class="ns-tok-punct">}</span></span><span class="ns-code__line"><span class="ns-tok-punct">}</span></span></code></pre>
  </div>
</figure>

mac window

Traffic lights and a centred title. The dots are drawn from the STATUS tokens, not from literal red/amber/green — the shape quotes macOS, the palette stays this system's. They carry no behaviour and are aria-hidden: a window control that does not control a window must not be a button.

useCourseProgress.js
export function useCourseProgress(id) {  const [done, setDone] = useState(0);  useEffect(() => { fetchProgress(id).then(setDone); }, [id]);  return done;}
markup
<figure class="ns-code ns-code--mac" data-lang="javascript">
  <figcaption class="ns-code__bar">
    <span class="ns-code__dots" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="ns-code__file"><span>useCourseProgress.js</span></span>
    <span class="ns-code__actions">
      <button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button>
    </span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4
5</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">export</span> <span class="ns-tok-kw">function</span> <span class="ns-tok-fn">useCourseProgress</span><span class="ns-tok-punct">(</span>id<span class="ns-tok-punct">)</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">  <span class="ns-tok-kw">const</span> <span class="ns-tok-punct">[</span>done<span class="ns-tok-punct">,</span> setDone<span class="ns-tok-punct">]</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-fn">useState</span><span class="ns-tok-punct">(</span><span class="ns-tok-num">0</span><span class="ns-tok-punct">);</span></span><span class="ns-code__line">  <span class="ns-tok-fn">useEffect</span><span class="ns-tok-punct">(()</span> <span class="ns-tok-punct">=&gt;</span> <span class="ns-tok-punct">{</span> <span class="ns-tok-fn">fetchProgress</span><span class="ns-tok-punct">(</span>id<span class="ns-tok-punct">).</span><span class="ns-tok-fn">then</span><span class="ns-tok-punct">(</span>setDone<span class="ns-tok-punct">);</span> <span class="ns-tok-punct">},</span> <span class="ns-tok-punct">[</span>id<span class="ns-tok-punct">]);</span></span><span class="ns-code__line">  <span class="ns-tok-kw">return</span> done<span class="ns-tok-punct">;</span></span><span class="ns-code__line"><span class="ns-tok-punct">}</span></span></code></pre>
  </div>
</figure>

vscode window

A tab strip above and a brand status bar below. The active tab is the one whose background matches the code underneath it — a tab is a piece cut out of the editor surface, which is the whole visual idea. The 2px top accent is the same current-item device the navbar uses. Live: click the tabs, or use arrow keys.

public with sharing class CaseRouter {  public static void route(List<Case> cases) {    for (Case c : cases) c.OwnerId = queueFor(c.Origin);  }}
Saved apex · UTF-8 · LF
markup
<figure class="ns-code ns-code--vscode" data-lang="apex">
  <div class="ns-code__tabs" role="tablist" aria-label="Sample files">
    <button type="button" role="tab" class="ns-code__tab" aria-selected="true" tabindex="0" aria-controls="vs-p1" id="vs-t1"><i class="ph ph-code" aria-hidden="true"></i>CaseRouter.cls</button>
    <button type="button" role="tab" class="ns-code__tab" aria-selected="false" tabindex="-1" aria-controls="vs-p2" id="vs-t2"><i class="ph ph-code" aria-hidden="true"></i>CaseRouterTest.cls</button>
    <button type="button" role="tab" class="ns-code__tab" aria-selected="false" tabindex="-1" aria-controls="vs-p3" id="vs-t3"><i class="ph ph-code" aria-hidden="true"></i>queues.soql</button>
  </div>
  <div role="tabpanel" id="vs-p1" aria-labelledby="vs-t1">
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4
5</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">public</span> <span class="ns-tok-kw">with</span> <span class="ns-tok-kw">sharing</span> <span class="ns-tok-kw">class</span> <span class="ns-tok-type">CaseRouter</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">  <span class="ns-tok-kw">public</span> <span class="ns-tok-kw">static</span> <span class="ns-tok-kw">void</span> <span class="ns-tok-fn">route</span><span class="ns-tok-punct">(</span><span class="ns-tok-type">List</span><span class="ns-tok-punct">&lt;</span><span class="ns-tok-type">Case</span><span class="ns-tok-punct">&gt;</span> cases<span class="ns-tok-punct">)</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">    <span class="ns-tok-kw">for</span> <span class="ns-tok-punct">(</span><span class="ns-tok-type">Case</span> c <span class="ns-tok-punct">:</span> cases<span class="ns-tok-punct">)</span> c<span class="ns-tok-punct">.</span><span class="ns-tok-type">OwnerId</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-fn">queueFor</span><span class="ns-tok-punct">(</span>c<span class="ns-tok-punct">.</span><span class="ns-tok-type">Origin</span><span class="ns-tok-punct">);</span></span><span class="ns-code__line">  <span class="ns-tok-punct">}</span></span><span class="ns-code__line"><span class="ns-tok-punct">}</span></span></code></pre>
  </div>
  </div>
  <div role="tabpanel" id="vs-p2" aria-labelledby="vs-t2" hidden>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4
5
6</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line">@isTest</span><span class="ns-code__line"><span class="ns-tok-kw">private</span> <span class="ns-tok-kw">class</span> <span class="ns-tok-type">CaseRouterTest</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">  @isTest <span class="ns-tok-kw">static</span> <span class="ns-tok-kw">void</span> <span class="ns-tok-fn">routesWebCases</span><span class="ns-tok-punct">()</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line">    <span class="ns-tok-type">System</span><span class="ns-tok-punct">.</span><span class="ns-tok-fn">assertEquals</span><span class="ns-tok-punct">(</span><span class="ns-tok-num">1</span><span class="ns-tok-punct">,</span> <span class="ns-tok-num">1</span><span class="ns-tok-punct">,</span> <span class="ns-tok-str">'placeholder'</span><span class="ns-tok-punct">);</span></span><span class="ns-code__line">  <span class="ns-tok-punct">}</span></span><span class="ns-code__line"><span class="ns-tok-punct">}</span></span></code></pre>
  </div>
  </div>
  <div role="tabpanel" id="vs-p3" aria-labelledby="vs-t3" hidden>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">SELECT</span> <span class="ns-tok-type">Id</span><span class="ns-tok-punct">,</span> <span class="ns-tok-type">Name</span> <span class="ns-tok-kw">FROM</span> <span class="ns-tok-type">Group</span></span><span class="ns-code__line"><span class="ns-tok-kw">WHERE</span> <span class="ns-tok-type">Type</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-str">'Queue'</span></span><span class="ns-code__line"><span class="ns-tok-kw">ORDER</span> <span class="ns-tok-kw">BY</span> <span class="ns-tok-type">Name</span> <span class="ns-tok-kw">ASC</span></span></code></pre>
  </div>
  </div>
  <div class="ns-code__foot">
    <span class="ns-code__status"><i class="ph ph-check-circle" aria-hidden="true"></i>Saved</span>
    <span class="ns-code__meta">apex &middot; UTF-8 &middot; LF</span>
  </div>
</figure>

Run

Run lives in the footer and nowhere else — it is the one action here that changes something, and putting it beside Copy would set a state-changing button one pixel from a harmless one. It does NOT execute anything: it raises ns:code-run and waits for the host to call done(). A design system that evaluated the code in its own docs would be a security hole with a play button on it. This demo carries data-output, which is the documented stand-in.

queues.soql soql
SELECT Id, Name, DeveloperNameFROM GroupWHERE Type = 'Queue'ORDER BY Name ASC LIMIT 200
4 lines · 118 B
markup
<figure class="ns-code" data-lang="soql" data-output="Rows: 3
Support Queue        &middot; 00G5g000004bYtR
Escalations Queue    &middot; 00G5g000004bYtS
Partner Queue        &middot; 00G5g000004bYtT

Completed in 0.42s">
  <figcaption class="ns-code__bar">
    <span class="ns-code__file"><i class="ph ph-database" aria-hidden="true"></i><span>queues.soql</span></span>
    <span class="ns-code__actions">
      <span class="ns-code__lang">soql</span>
      <button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button>
    </span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">SELECT</span> <span class="ns-tok-type">Id</span><span class="ns-tok-punct">,</span> <span class="ns-tok-type">Name</span><span class="ns-tok-punct">,</span> <span class="ns-tok-type">DeveloperName</span></span><span class="ns-code__line"><span class="ns-tok-kw">FROM</span> <span class="ns-tok-type">Group</span></span><span class="ns-code__line"><span class="ns-tok-kw">WHERE</span> <span class="ns-tok-type">Type</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-str">'Queue'</span></span><span class="ns-code__line"><span class="ns-tok-kw">ORDER</span> <span class="ns-tok-kw">BY</span> <span class="ns-tok-type">Name</span> <span class="ns-tok-kw">ASC</span> <span class="ns-tok-kw">LIMIT</span> <span class="ns-tok-num">200</span></span></code></pre>
  </div>
  <div class="ns-code__foot">
    <button type="button" class="ns-code__run" data-code="run"><i class="ph ph-play" aria-hidden="true"></i>Run</button>
    <span class="ns-code__status" data-code-status></span>
    <span class="ns-code__meta">4 lines &middot; 118 B</span>
  </div>
  <output class="ns-code__out" aria-live="polite" hidden></output>
</figure>

Marked lines

Added, removed and called-out lines — a 2px leading edge plus a wash, the same accent-line device the rest of the system uses. Diff colour is never the only signal: the sample is introduced in prose, because a red line and a green line are one colour to a monochromat.

CaseRouter.cls — the bulkification fix
public static void route(List<Case> cases) {  Map<String, Id> queues = queueMap();  for (Case c : cases) {    c.OwnerId = [SELECT Id FROM Group WHERE DeveloperName = :c.Origin].Id;    c.OwnerId = queues.get(c.Origin);  }}
markup
<figure class="ns-code" data-lang="apex">
  <figcaption class="ns-code__bar">
    <span class="ns-code__file"><i class="ph ph-git-branch" aria-hidden="true"></i><span>CaseRouter.cls &mdash; the bulkification fix</span></span>
    <span class="ns-code__actions"><button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button></span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2
3
4
5
6
7</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">public</span> <span class="ns-tok-kw">static</span> <span class="ns-tok-kw">void</span> <span class="ns-tok-fn">route</span><span class="ns-tok-punct">(</span><span class="ns-tok-type">List</span><span class="ns-tok-punct">&lt;</span><span class="ns-tok-type">Case</span><span class="ns-tok-punct">&gt;</span> cases<span class="ns-tok-punct">)</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line ns-code__line--mark">  <span class="ns-tok-type">Map</span><span class="ns-tok-punct">&lt;</span><span class="ns-tok-type">String</span><span class="ns-tok-punct">,</span> <span class="ns-tok-type">Id</span><span class="ns-tok-punct">&gt;</span> queues <span class="ns-tok-punct">=</span> <span class="ns-tok-fn">queueMap</span><span class="ns-tok-punct">();</span></span><span class="ns-code__line">  <span class="ns-tok-kw">for</span> <span class="ns-tok-punct">(</span><span class="ns-tok-type">Case</span> c <span class="ns-tok-punct">:</span> cases<span class="ns-tok-punct">)</span> <span class="ns-tok-punct">{</span></span><span class="ns-code__line ns-code__line--del">    c<span class="ns-tok-punct">.</span><span class="ns-tok-type">OwnerId</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-punct">[</span><span class="ns-tok-kw">SELECT</span> <span class="ns-tok-type">Id</span> <span class="ns-tok-kw">FROM</span> <span class="ns-tok-type">Group</span> <span class="ns-tok-kw">WHERE</span> <span class="ns-tok-type">DeveloperName</span> <span class="ns-tok-punct">=</span> <span class="ns-tok-punct">:</span>c<span class="ns-tok-punct">.</span><span class="ns-tok-type">Origin</span><span class="ns-tok-punct">].</span><span class="ns-tok-type">Id</span><span class="ns-tok-punct">;</span></span><span class="ns-code__line ns-code__line--add">    c<span class="ns-tok-punct">.</span><span class="ns-tok-type">OwnerId</span> <span class="ns-tok-punct">=</span> queues<span class="ns-tok-punct">.</span><span class="ns-tok-kw">get</span><span class="ns-tok-punct">(</span>c<span class="ns-tok-punct">.</span><span class="ns-tok-type">Origin</span><span class="ns-tok-punct">);</span></span><span class="ns-code__line">  <span class="ns-tok-punct">}</span></span><span class="ns-code__line"><span class="ns-tok-punct">}</span></span></code></pre>
  </div>
</figure>

On the console surface

--dark forces the navy console on a light page, which is what a docs body wants: code should look like code, not like an indented paragraph. Under [data-theme="dark"] every block goes here automatically, so this modifier is only for the light-page case.

deploy.sh
# Deploy the metadata, then run the local tests only.sf project deploy start --source-dir force-app --test-level RunLocalTests --wait 30
markup
<figure class="ns-code ns-code--dark" data-lang="bash">
  <figcaption class="ns-code__bar">
    <span class="ns-code__file"><i class="ph ph-terminal-window" aria-hidden="true"></i><span>deploy.sh</span></span>
    <span class="ns-code__actions"><button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button></span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__gutter" aria-hidden="true">1
2</pre>
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-com"># Deploy the metadata, then run the local tests only.</span></span><span class="ns-code__line">sf project deploy start <span class="ns-tok-punct">--</span><span class="ns-tok-kw">source</span><span class="ns-tok-punct">-</span>dir force<span class="ns-tok-punct">-</span>app <span class="ns-tok-punct">--</span>test<span class="ns-tok-punct">-</span>level <span class="ns-tok-type">RunLocalTests</span> <span class="ns-tok-punct">--</span>wait <span class="ns-tok-num">30</span></span></code></pre>
  </div>
</figure>

Compact, no gutter, inline

--compact tightens leading and drops a size, for a sample set beside prose rather than under a heading. Dropping the gutter is right whenever the lines are not going to be referred to by number. The inline chip is the one-liner sibling: same mono, same sunken chip, no chrome.

tokens.js
import { tokens } from "@namaste-salesforce/design-system";

Set the reading weight with --weight-body, never with font-weight: 400.

markup
<figure class="ns-code ns-code--compact" data-lang="javascript">
  <figcaption class="ns-code__bar">
    <span class="ns-code__file"><span>tokens.js</span></span>
    <span class="ns-code__actions"><button type="button" class="ns-code__btn" data-code="copy"><i class="ph ph-file-text" aria-hidden="true"></i><span class="ns-code__btn-label"><span>Copy</span></span></button></span>
  </figcaption>
  <div class="ns-code__body">
    <pre class="ns-code__pre"><code><span class="ns-code__line"><span class="ns-tok-kw">import</span> <span class="ns-tok-punct">{</span> tokens <span class="ns-tok-punct">}</span> <span class="ns-tok-kw">from</span> <span class="ns-tok-str">"@namaste-salesforce/design-system"</span><span class="ns-tok-punct">;</span></span></code></pre>
  </div>
</figure>
<p>Set the reading weight with <code class="ns-code-inline">--weight-body</code>, never with <code class="ns-code-inline">font-weight: 400</code>.</p>

Accessibility contract

  • Line numbers live in a separate aria-hidden gutter, so they are never announced and never land in the clipboard
  • The Ask-AI and Share menus are native popovers: light-dismiss, Esc and focus return come from the platform, not from a re-implementation
  • The tab strip is a real tablist — arrow keys, Home/End, and one tab stop for the whole strip
  • Run's result renders into an aria-live="polite" output, so the outcome of the button you pressed is announced
  • Every icon-only control (wrap, share) carries an aria-label; the copy confirmation is a text change, not a colour change
  • The seven syntax roles all clear 4.5:1 on their own surface in both themes — syntax colour is decoration on top of code that reads without it