j3w1 / DiagnosticsVue · HTML · React · Astro

J3W1 / DESIGN SYSTEM

Diagnostics

Inline problem markers in code (underline patterns, an error line and an overview stripe) and the problems panel that lists them as a listbox, each severity carrying its glyph.

stable · LIGHT DOM · 1.1.0

Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.

Live variants

inline

✕ Language server stopped; markers may be stale.

import { readFile } from "node:fs/promises";
const title = document.title;
function render(frame) {
  const count = frame.children.length;
  escape(title);
  return frmae.title + count;
}
render(document.body) == null;

No problems in title.js

<j3w1-diagnostics id="example-diagnostics-inline"><div class="diagnostics diagnostics-inline">
  <p class="diagnostics-status" role="status">✕ Language server stopped; markers may be stale.</p>
  <div class="diagnostics-box" role="textbox" aria-multiline="true" aria-readonly="true" aria-label="title.js with 6 diagnostics, read-only" tabindex="0">
    <pre class="diagnostics-code"><span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">1</span><span class="diagnostics-text">import { <span class="diagnostics-unused" title="readFile is declared but never used">readFile</span> } from "node:fs/promises";</span><span class="diagnostics-mark diagnostics-mark-hint" aria-hidden="true">·</span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">2</span><span class="diagnostics-text">const title = document.title;</span><span class="diagnostics-mark" aria-hidden="true"></span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">3</span><span class="diagnostics-text">function <span class="diagnostics-hint" title="Hint: render could be an arrow function">render</span>(frame) {</span><span class="diagnostics-mark diagnostics-mark-hint" aria-hidden="true">·</span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">4</span><span class="diagnostics-text">  const count = <span class="diagnostics-info" title="Info: frame.children may be undefined; consider ?.">frame.children</span>.length;</span><span class="diagnostics-mark diagnostics-mark-info" aria-hidden="true">i</span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">5</span><span class="diagnostics-text">  <span class="diagnostics-deprecated" title="escape() is deprecated">escape</span>(title);</span><span class="diagnostics-mark diagnostics-mark-hint" aria-hidden="true">·</span></span>
<span class="diagnostics-line diagnostics-line-error"><span class="diagnostics-ln" aria-hidden="true">6</span><span class="diagnostics-text">  return <span class="diagnostics-error" title="Error: frmae is not defined">frmae</span>.title + count;</span><span class="diagnostics-mark diagnostics-mark-error" aria-hidden="true">✕</span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">7</span><span class="diagnostics-text">}</span><span class="diagnostics-mark" aria-hidden="true"></span></span>
<span class="diagnostics-line"><span class="diagnostics-ln" aria-hidden="true">8</span><span class="diagnostics-text">render(document.body) <span class="diagnostics-warning diagnostics-target" title="Warning: expected === and instead saw ==">==</span> null;</span><span class="diagnostics-mark diagnostics-mark-warning" aria-hidden="true">!</span></span></pre>
  </div>
  <p class="diagnostics-empty"><span class="diagnostics-glyph diagnostics-glyph-success" aria-hidden="true">✓</span> No problems in title.js</p>
</div></j3w1-diagnostics>

panel

Problems 1 error ! 1 warning i 1 info · 3 hints

✕ Language server stopped; the list may be stale.

  • Error: frmae is not defined title.js:6:10 no-undef
  • Warning: Expected === and instead saw == title.js:8:23 eqeqeq
  • Info: frame.children may be undefined; consider optional chaining title.js:4:17 ts-2532
  • Hint: readFile is declared but never used title.js:1:10 no-unused-vars
  • Hint: escape() is deprecated; use encodeURIComponent() title.js:5:3 deprecation

No problems

<j3w1-diagnostics id="example-diagnostics-panel"><div class="diagnostics diagnostics-panel">
  <div class="diagnostics-header">
    <span class="diagnostics-title" id="example-diagnostics-panel-dg-title">Problems</span>
    <span class="diagnostics-count"><span class="diagnostics-glyph diagnostics-glyph-error">✕</span> 1 <span class="sr-only">error</span></span>
    <span class="diagnostics-count"><span class="diagnostics-glyph diagnostics-glyph-warning">!</span> 1 <span class="sr-only">warning</span></span>
    <span class="diagnostics-count"><span class="diagnostics-glyph diagnostics-glyph-info">i</span> 1 <span class="sr-only">info</span></span>
    <span class="diagnostics-count"><span class="diagnostics-glyph diagnostics-glyph-hint">·</span> 3 <span class="sr-only">hints</span></span>
  </div>
  <p class="diagnostics-status" role="status">✕ Language server stopped; the list may be stale.</p>
  <ul class="diagnostics-list" role="listbox" aria-labelledby="example-diagnostics-panel-dg-title" aria-activedescendant="example-diagnostics-panel-dg-row-2" tabindex="0">
    <li class="diagnostics-row" role="option" id="example-diagnostics-panel-dg-row-1" aria-selected="false">
      <span class="diagnostics-glyph diagnostics-glyph-error" aria-hidden="true">✕</span>
      <span class="diagnostics-message"><span class="sr-only">Error: </span>frmae is not defined</span>
      <span class="diagnostics-loc">title.js:6:10</span>
      <span class="diagnostics-rule">no-undef</span>
    </li>
    <li class="diagnostics-row diagnostics-row-active" role="option" id="example-diagnostics-panel-dg-row-2" aria-selected="false">
      <span class="diagnostics-glyph diagnostics-glyph-warning" aria-hidden="true">!</span>
      <span class="diagnostics-message"><span class="sr-only">Warning: </span>Expected === and instead saw ==</span>
      <span class="diagnostics-loc">title.js:8:23</span>
      <span class="diagnostics-rule">eqeqeq</span>
    </li>
    <li class="diagnostics-row" role="option" id="example-diagnostics-panel-dg-row-3" aria-selected="false">
      <span class="diagnostics-glyph diagnostics-glyph-info" aria-hidden="true">i</span>
      <span class="diagnostics-message"><span class="sr-only">Info: </span>frame.children may be undefined; consider optional chaining</span>
      <span class="diagnostics-loc">title.js:4:17</span>
      <span class="diagnostics-rule">ts-2532</span>
    </li>
    <li class="diagnostics-row" role="option" id="example-diagnostics-panel-dg-row-4" aria-selected="false">
      <span class="diagnostics-glyph diagnostics-glyph-hint" aria-hidden="true">·</span>
      <span class="diagnostics-message"><span class="sr-only">Hint: </span>readFile is declared but never used</span>
      <span class="diagnostics-loc">title.js:1:10</span>
      <span class="diagnostics-rule">no-unused-vars</span>
    </li>
    <li class="diagnostics-row" role="option" id="example-diagnostics-panel-dg-row-5" aria-selected="false">
      <span class="diagnostics-glyph diagnostics-glyph-hint" aria-hidden="true">·</span>
      <span class="diagnostics-message"><span class="sr-only">Hint: </span>escape() is deprecated; use encodeURIComponent()</span>
      <span class="diagnostics-loc">title.js:5:3</span>
      <span class="diagnostics-rule">deprecation</span>
    </li>
  </ul>
  <p class="diagnostics-empty"><span class="diagnostics-glyph diagnostics-glyph-success" aria-hidden="true">✓</span> No problems</p>
</div></j3w1-diagnostics>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@1.1.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/diagnostics.css';
import '@j3w1/ui/register/diagnostics';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@1.1.0 j3w1-ui copy diagnostics --out ./vendor/j3w1/diagnostics

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
setText(text: string): voidReplace the bounded read-only text view; no code or shell execution occurs.

events

NameType / signatureMeaning
j3w1-actionCustomEventRequest a developer-view action; editing and execution belong to the host.

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Purpose

How problems appear on code and in the list that indexes them. Six kinds are distinguished by pattern and glyph as well as colour: error, warning, info, hint, unused and deprecated. The panel is the keyboard route to every marker.

Anatomy

Root .diagnostics with the variant class .diagnostics-inline or .diagnostics-panel. Inline parts: .diagnostics-code (the <pre>), -line, -ln, -text, -mark (the stripe cell), and the ranges .diagnostics-error, -warning, -info, -hint, -unused, -deprecated; .diagnostics-line-error marks the row filled color.diagnostic.error.bg; .diagnostics-target is the range that belongs to the selected row. Panel parts: -header, -title, -count, -status, -list, -row, -glyph (with -glyph-error and so on), -message, -loc, -rule, -empty. Patterns: error and warning wavy, info and hint dotted, unused dotted in color.diagnostic.unused.text, deprecated line-through in color.code.syntax.deprecated. Glyphs: error in color.diagnostic.error.text, ! warning in color.diagnostic.warning.text, i info in color.diagnostic.info.text, · hint in color.text.subtle. The stripe mark repeats the glyph in the stripe colour (color.diagnostic.error.stripe, color.diagnostic.warning.stripe).

States

StateVisualNon-colour channel
defaultranges decorated as above on color.code.bg; the error row filled color.diagnostic.error.bg; panel rows on color.surface.default with 1px color.border.divider between themunderline pattern; glyph
hoverpanel row background → color.interaction.hover.bg; inline ranges unchanged (the hover tooltip is a host surface)cursor: default on rows
focus-visiblethe active row: 1px dashed color.interaction.focus.ring at −2px; inline box: the container ring 2px color.interaction.focus.ring-container at −3pxthe ring
selectedrow filled color.interaction.selection.bg, text and glyph color.interaction.selection.text; the matching inline range filled color.code.selection-bg under its underlinearia-selected; the glyph stays; the fill spans the row
selected+focus-visiblethe selection fill and a 1px dashed ring in color.interaction.focus.ring-containerboth at once
errorthe provider failed: a role=status line with in color.status.danger.text above the stale rows; the inline stripe shows the same at its topglyph; live announcement
emptyno problems: rows and stripe marks hidden; ✓ No problems in color.text.muted with the glyph in color.status.success.text; inline decorations removedglyph; the absence of decoration

Precedence: selected > hover; focus-visible is drawn on top. A selected row recolours its glyph to the on-selection text so the shape, not the hue, carries the severity.

Keyboard

The panel follows the APG listbox pattern with aria-activedescendant: the list is one Tab stop, Up and Down move the active row, Home and End jump, type-ahead matches message text, Enter opens the location. Selection follows focus. Inline markers add no keys; next-problem and previous-problem navigation and the hover card are host bindings and host surfaces.

Accessibility

Never colour-only: every severity has its underline pattern in code and its glyph in the panel, and the glyph is part of the option’s accessible name (“Error: frmae is not defined, title.js line 6”). The error row background is an addition to the wavy underline, not a replacement. Contrast: color.diagnostic.error.text reaches 4.88:1 on the error row and 5.26:1 on the panel; every underline reaches 3:1 on its actual background including the selected range (the error underline measures 3.81:1 on the code selection fill); color.diagnostic.unused.text reaches 5.81:1 so unused code is still readable. aria-selected and aria-activedescendant carry the state; the status line is role=status, announced once. In forced-colours mode the underline patterns persist because they are text-decoration, not backgrounds.

Portability

Underline styles are native in Pango, Qt, JetBrains and most terminal emulators; where wavy is unavailable the port uses a plain underline plus the glyph and records the deviation. Hosts that draw their own overview ruler map the stripe colours; hosts without one omit the stripe and keep the glyphs. The listbox maps to any single-selection list widget.

Non-examples

Red-only errors without the glyph or the wavy pattern. A wavy underline for every severity, which leaves the pattern meaningless. Purple or cyan for info and hint. A hover on a panel row that changes only the text colour. A selected row whose glyph keeps its severity colour on the red fill (2.47:1). A panel row with a rounded highlight or a left accent bar instead of the fill. Removing the error line background to “calm” the editor.

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • DEMO Vue application demo
  • SPEC Complete UI theme specification