Shade Library Developer Reference
A source-level map of library/shades/index.html and
library/shades/shade-library.js: data contracts, state, rendering, exports, sharing,
saved items, UI chrome and validation.
Overview
A source-level map of library/shades/index.html and library/shades/shade-library.js : data contracts, state, rendering, exports, sharing, saved items, UI chrome and validation.
1. Runtime overview
+Shade Library is a static page plus an ESM browser runtime. The page shell declares SEO, structured data, application containers, filters, tabs and shared Auric Artisan UI chrome. The runtime fetches generated Shade Gen data, normalizes compact records, computes color metrics, renders a virtual (windowed) card grid and powers the Inspect, Harmony, Accessibility, Stats, Export and Saved workflows.
- Page shell:
library/shades/index.html. - Runtime:
library/shades/shade-library.js. - Data URL:
/data/shade-gen/shades.json. - Saved key:
aa.shades.saved. - Guide key:
aa.shades.guide.dismissed. - Share type:
shade. - Workspace domain:
shades.
2. File and dependency map
+| File | Role |
|---|---|
library/shades/index.html |
HTML route, SEO, JSON-LD, application containers, tabs, filters and includes. |
library/shades/shade-library.js |
ESM runtime for fetch, normalize, filter, render, inspect, export, save and share. |
data/shade-gen/shades.json |
8,192 generated shade records in compact JSON shape. |
data/shade-gen/index.json |
Manifest with count, seed, methods, step presets and generated file names. |
js/library/page-mirror.js |
Mirrors saved shades into the Library workspace. |
js/library/share/dialog.js |
Opens the share dialog for shade payloads. |
js/library/share/router.js |
Registers the shade share handler and hydrates shared shade ids. |
js/library/tokens/dialog.js |
Opens the design-token export dialog. |
/js/unified.js |
Shared site behavior for includes, legal sections, cursor, loader and page chrome. |
3. Page shell, SEO and UI Chrome
+The page shell is a complete indexable route, not just a JavaScript mount point. It declares canonical, Open Graph, Twitter Card and JSON-LD metadata for the public shade dataset.
- Canonical:
https://auricartisan.com/library/shades/. - Preload:
/data/shade-gen/shades.json. - Structured data:
Datasetfor the 8,192-entry shade library andBreadcrumbListfor Home -> Shade Library. - Shared styles: main, unified and dark-mode CSS, plus the page stylesheet
/css/shade-library.css. - Chrome: header, time, announcement, custom cursor, scroll rail, loader, footer, idle layer and generated inline scripts.
- CVD filter defs: deuteranopia, protanopia, tritanopia, achromatopsia and low-vision SVG filters are present for compatibility with visual color tools.
Keep the cursor, scroll, loader, footer and idle canvas in sync with other documentation and library routes so the page feels native to Auric Artisan.
4. DOM contract
+
shade-library.js reads fixed ids at startup. Rename these only with a matching
runtime update.
| Group | Important IDs |
|---|---|
| Counts and badges | slib-hero-count, slib-tab-library-badge,
slib-tab-saved-badge |
| Search | slib-search, slib-result-search,
slib-result-clear, slib-shuffle,
slib-random |
| Tabs and panels | .anz-tab-btn, .anz-panel, p-library,
p-inspect, p-harmony, p-accessibility,
p-stats, p-export, p-saved |
| Filters | slib-filter-hue, slib-filter-chroma,
slib-filter-light, slib-filter-method,
slib-sort, slib-reset, slib-export-visible |
| Library grid | slib-loading, slib-grid,
slib-page-info, slib-scroll-top |
| Advanced content | slib-inspect-empty, slib-inspect,
slib-harmony, slib-accessibility,
slib-stats, slib-export, slib-saved,
slib-toast |
5. Dataset contract
+
loadData() fetches DATA_URL with cache: "force-cache".
It accepts a raw array, { shades: [...] } or { samples: [...] }. Every
item passes through normalizeShade(raw, index).
{
"id": "shade_000000",
"n": "Material Like #FF724C #00001",
"b": "#ff724c",
"m": "material-like",
"t": ["50", "100", "300", "500", "700", "900", "950"],
"c": ["#fff0ec", "#ffdfd7", "#ff886b", "#ff724c", "#cd5531", "#4b1200", "#1e0400"],
"s": 0.5833
}
Compact fields map to expanded fields as follows:
id->shade_id.n->name.b->base.m->method.t->tokens.c-> source colors.s-> score fallback whenmeta.scoreis absent.
Normalized colors contain token, HEX, RGB, Lab, OKLCH and contrast values. Normalized shade
objects also carry derived private fields such as _avgL, _avgC,
_hue, _spread, _tokenCount,
_minAdjacent, _autoAA, _whiteAA,
_blackAA and _search.
6. State and load sequence
+
The runtime uses a single module-local state object. It tracks raw normalized data,
active filters, the filtered set (visibleShades), selected shade, panel render status and workflow progress.
{
all: [],
filtered: [],
visibleShades: [],
page: 0,
activeShade: null,
panelsRendered: {
harmony: false,
accessibility: false,
stats: false,
export: false,
saved: false
},
progress: {
browse: false,
inspect: false,
harmony: false,
accessibility: false,
export: false
}
}
Startup sequence:
- Resolve DOM ids into
els. - Attach event listeners for search, filters, tabs, cards and exports.
- Call
loadData(). - Fetch and normalize dataset records.
- Populate method filter options from the data.
- Apply filters and hand the result to the virtual grid.
- Render saved panel state and register the
shadeshare handler.
7. Color science helpers
+Shade Library keeps enough color math in the browser to make compact dataset records useful without shipping full per-token metrics.
parseHex()andrgbToHex()parse and serialize HEX and RGB.rgbToLab()computes CIE Lab values for inspection.rgbToOklab()andrgbToOklch()compute perceptual values for lightness, chroma and hue filters.contrastRatio()computes WCAG-style contrast ratios against white, black and adjacent colors.textOn()chooses white or black readable text for swatches.shadeToneLabel()categorizes systems as Neutral, Hue Shift, Light, Deep or Balanced.colorName()builds generated tone, chroma and hue labels for token cards.
The computed OKLCH data is used for filters, stats, hue buckets, tone labels and generated names. Keep conversion changes synchronized with user-facing docs and regression tests because they alter filtering behavior.
8. Filtering, sorting and pagination
+
applyFilters() combines the top search field, result search field, select filters
and sort mode into state.filtered. renderPage() copies that list into
state.visibleShades and hands it to the virtual grid from
createVirtualGrid() in js/library/virtual-grid.js.
| Mode | Runtime Rule |
|---|---|
| Text | Every search term must appear in the shade's normalized _search text.
|
| Hue | Dominant hue is bucketed into red, orange, yellow, green, cyan, blue, purple or pink. |
| Chroma | Muted below 0.07 average chroma, vivid above 0.15, balanced between them. |
| Lightness | Dark below 0.40 average OKLCH lightness, light above 0.70, mid between them. |
| Method | Exact match against the normalized generator method. |
| Sort | Original id, lightness asc/desc, chroma asc/desc, hue, score desc, tokens desc or random. |
Search input is debounced at 120 ms. There is no page-size control: the grid scrolls through
the whole filtered list, and Back to top calls vgrid.scrollToTop().
9. Rendering and interaction model
+Cards and panels are rendered as HTML strings after escaping user-facing values. The library is static-data driven, and the virtual grid keeps only about one screenful of cards in the DOM rather than the whole dataset.
shadeCard()builds grid cards with swatches, metadata, Inspect, Copy and Save controls.- Clicking a swatch copies that swatch HEX.
- Clicking Inspect or the card body calls
openInspect(shade). - Clicking Copy copies all shade HEX values.
- Clicking Save toggles local saved state and workspace mirroring.
- Keyboard Enter or Space on a focused card opens Inspect.
- Pressing / focuses search unless an input or textarea is already active.
selectTab() toggles tab ARIA state and lazy-renders expensive panels the first
time they are opened. Export and Saved panels render on each open because their content depends
on current selection and saved ids.
10. Panel responsibilities
+| Panel | Function |
|---|---|
Inspect |
Renders token strip, summary metrics, per-color RGB, Lab, OKLCH, contrast, quick copy pills and selected-shade export actions. |
Harmony |
Summarizes visible shade systems by method, hue bucket, shade profile and token count. |
Accessibility |
Computes auto-AA coverage, white and black text coverage, selected-shade checks and all-token candidate cards. |
Stats |
Builds histograms for average lightness, average chroma, hue spread, token count and score. |
Export |
Shows selected-shade export buttons and bulk export buttons for the filtered results. |
Saved |
Reads local saved ids, renders shade cards and links users to the Library workspace. |
Progress state is no longer shown. markFlowStep() is kept as a no-op because the
flow strip it advanced was removed.
11. Export system
+
Export helpers produce plain text, JSON blobs, SVG strings and canvas-generated PNG downloads.
Clipboard writes fall back to a temporary textarea if navigator.clipboard is not
available.
stripShade()returns the portable selected-shade JSON object.cssVars()writes a.aa-shade-{prefix}CSS custom property block.scssVars()writes one SCSS variable per token.tailwindToken()writes a Tailwind color fragment keyed by slugged shade name.shadeSvg()writes a standalone SVG strip with token titles.exportShadePng()renders the active shade strip to a 1600 x 420 canvas.exportBulk()writes the filtered results as JSON, compact JSON, CSV, CSS, SCSS, Tailwind or HEX-list files.
{
"id": "shade_000000",
"name": "Material Like #FF724C #00001",
"base": "#ff724c",
"method": "material-like",
"tokens": ["50", "100", "300", "500", "700", "900", "950"],
"colors": [
{ "token": "50", "hex": "#fff0ec", "contrast": { "white": 1.11, "black": 18.93 } }
],
"meta": {
"score": 0.5833,
"avg_lightness": 0.628,
"avg_chroma": 0.098,
"auto_aa_tokens": 4
}
}
Bulk CSV uses these columns: id, name, base,
method, tokens, score,
avg_lightness, avg_chroma, auto_aa and
colors.
13. Accessibility and UX rules
+- The app container uses
role="application". - Tabs use
role="tablist",role="tab",aria-selectedandaria-controls. - Panels use
role="tabpanel"with matching labels. - The grid uses
aria-live="polite"so result changes can be announced. - The toast uses
role="status"andaria-live="polite". - Cards support keyboard activation with Enter and Space.
- There is no simple/advanced mode switch: all seven tabs are always available.
- The guide was removed;
aa.shades.guide.dismissedis still declared but no longer read or written.
Keep text labels visible for important actions. Tooltip metadata helps expert users, but the controls should still make sense without hover.
14. Performance, validation and maintenance
+The current data count is small enough for client-side filtering, but the code is still shaped to avoid rendering all 8,192 cards at once. Keep expensive work tied to normalized data, debounced search, windowed rendering and lazy panel creation.
- Regenerate
data/shade-genwhen generator methods, compact record shape, seed or public count changes. - Keep
data/shade-gen/index.json, page hero count, JSON-LD Dataset count and docs aligned. - Update
normalizeShade()before changing compact field names. - Update filter docs when hue buckets, chroma thresholds, lightness thresholds or sort modes change.
- Validate clipboard, canvas download and URL object cleanup when changing export behavior.
- Check localStorage migrations before changing
SAVED_KEYor saved id format. - After documentation changes, regenerate documentation discovery, feeds, sitemaps, PWA cache and search index.
node scripts/generate-discovery.mjs
node scripts/generate-pwa-cache-manifest.mjs
node search/client/build-index.js
For user-facing workflow details, see the Shade Library User Guide. For generator internals, see the Shade Gen Developer Reference.