[FEATURE] artifact-design: add a searchable glossary sidebar
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:
- Define every term inline. This bloats the prose and forces readers who know the vocabulary to skip repeated explanations.
- 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:
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.min-height: 0lets the scrolling grid child shrink below its content height.height: 100vhon the outer wrapper avoids relying on an explicithtmlandbodyheight from the artifact host.overscroll-behavior: containstops scroll chaining when the main column reaches either end.
The pattern should also document these accessibility details:
- Set
aria-expandedandaria-controlson both sidebar controls. - Move focus to the control that becomes visible after collapsing or opening the sidebar.
- Check
offsetParentbefore moving focus because both controls are hidden below the breakpoint. - Set
aria-pressedon category filters. - Render terms with
<dl>,<dt>, and<dd>. - Use
<input type="search">with anaria-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.