[FEATURE] artifact-design: add a searchable glossary sidebar

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 28, 2026

Preflight checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request

Problem statement

The artifact-design skill does not explain how to handle pages with a lot of domain jargon, such as protocol comparisons, architecture decision records, security write-ups, and RFC summaries.

The usual approaches both get in the reader's way:

  1. Define every term inline. This bloats the prose and forces readers who know the vocabulary to skip repeated explanations.
  2. Put a glossary at the bottom. Readers lose their place whenever they look up a term.

For a page with dozens of terms, the glossary should remain visible beside the content and let readers search or filter the terms. This needs explicit implementation guidance because a layout where only the main column scrolls is easy to get wrong with CSS Grid.

Proposed solution

Add a glossary sidebar pattern to artifact-design. Recommend it for reference and explainer pages with roughly 15 or more unfamiliar terms. Shorter pages should keep definitions inline.

Keep the glossary visible on desktop

At widths above roughly 1040px, only the main column should scroll. The glossary should remain visible. Below that breakpoint, it should become a normal section after the content, never an overlay.

@media (min-width: 1040px) {
  body { overflow: hidden; }

  /* Use 100vh so the host wrapper does not need explicit heights. */
  .plate {
    height: 100vh;
    padding-top: 0;
    padding-bottom: 0;
  }

  .layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--aside-w, 22rem);
    grid-template-rows: minmax(0, 1fr);
    height: 100%;
  }

  .col-main {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
Let readers collapse it

The sidebar should collapse to a rail about 3rem wide so wide diagrams and tables can use the extra space. Store the choice in localStorage and keep the default usable when storage is unavailable.

.layout[data-aside="closed"] { --aside-w: 3rem; }
.layout[data-aside="closed"] .aside-inner { display: none; }
.layout[data-aside="open"] .rail { display: none; }
function setAside(state, moveFocus) {
  layout.dataset.aside = state;
  const open = state === "open";
  railOpen.setAttribute("aria-expanded", String(open));
  glossCollapse.setAttribute("aria-expanded", String(open));

  try {
    localStorage.setItem("glossary-aside", state);
  } catch {
    /* The default works if storage is unavailable. */
  }

  if (moveFocus) {
    const target = open ? glossCollapse : railOpen;
    // Both controls are hidden below the breakpoint.
    if (target.offsetParent !== null) target.focus();
  }
}
Add search and category filters

Terms should live in data rather than repeated markup. One render function can apply a text query, a category filter, and an N of M count.

const TERMS = [
  ["code_verifier", "pkce", "A high-entropy random string the client keeps to itself..."],
  ["device_code", "device", "The client's opaque polling handle..."],
  ["Refresh token", "both", "A longer-lived credential exchanged for new access tokens..."],
];

function renderGlossary() {
  const q = glossSearch.value.trim().toLowerCase();
  const shown = TERMS.filter(([term, tag, def]) => {
    if (glossTag !== "all" && tag !== glossTag) return false;
    if (!q) return true;
    return (term + " " + def).toLowerCase().includes(q);
  });

  // Render shown, then update the count.
  glossCount.textContent = `${shown.length} of ${TERMS.length}`;
}

In a comparison document, categories such as pkce, device, and both tell readers which flow each term belongs to. The chip colors can match the corresponding diagrams in the main column.

Alternative solutions

  • <abbr title> and hover tooltips do not work well on touch screens. They are also hidden until interaction and cannot be searched.
  • Inline <details> elements interrupt the prose and repeat definitions at every occurrence.
  • A glossary at the bottom with anchor links moves the reader away from the sentence they were reading and makes them navigate back.
  • Without a documented pattern, generated artifacts often miss one of the CSS sizing rules and scroll the whole page instead of the main column.

Priority

Medium

Feature category

Skills / Artifacts

Use case example

Consider an OAuth device-code versus PKCE security write-up with 31 terms in three categories: PKCE, Device, and Both. A reader may need definitions for code_verifier, code_challenge, S256, device_code, user_code, authorization_pending, and slow_down while following a sequence diagram.

With the sidebar open, the diagram and glossary remain visible at the same time. Searching for refresh can narrow 31 terms to 3, and selecting Device shows only terms for that grant. The same pattern would work for incident reports, migration guides, protocol summaries, and onboarding documents.

Additional context

The fixed scroll layout depends on these CSS rules:

  1. grid-template-rows: minmax(0, 1fr) constrains the grid row. Without it, content sets the row height and the main column has no bounded area to scroll within.
  2. min-height: 0 lets the scrolling grid child shrink below its content height.
  3. height: 100vh on the outer wrapper avoids relying on an explicit html and body height from the artifact host.
  4. overscroll-behavior: contain stops scroll chaining when the main column reaches either end.

The pattern should also document these accessibility details:

  • Set aria-expanded and aria-controls on both sidebar controls.
  • Move focus to the control that becomes visible after collapsing or opening the sidebar.
  • Check offsetParent before moving focus because both controls are hidden below the breakpoint.
  • Set aria-pressed on category filters.
  • Render terms with <dl>, <dt>, and <dd>.
  • Use <input type="search"> with an aria-label.

Category colors should be defined on bare :root, then redefined under both @media (prefers-color-scheme: dark) and :root[data-theme="dark"], as required by the skill's three-state theme rule.

I have a working reference implementation that could be added to the skill examples.

View original on GitHub ↗