Skip to main content
Auric Artisan · Documentation

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.

Updated: May 26, 2026 Route: /library/shades/ Runtime: shade-library.js Author: Chirag Bansal
Back to Documentation Auric Artisan Home

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.

Table of contents

  1. 1. Runtime overview
  2. 2. File and dependency map
  3. 3. Page shell, SEO and UI Chrome
  4. 4. DOM contract
  5. 5. Dataset contract
  6. 6. State and load sequence
  7. 7. Color science helpers
  8. 8. Filtering, sorting and pagination
  9. 9. Rendering and interaction model
  10. 10. Panel responsibilities
  11. 11. Export system
  12. 12. Save, share and token dialog
  13. 13. Accessibility and UX rules
  14. 14. Performance, validation and maintenance

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: Dataset for the 8,192-entry shade library and BreadcrumbList for 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 when meta.score is 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:

  1. Resolve DOM ids into els.
  2. Attach event listeners for search, filters, tabs, cards and exports.
  3. Call loadData().
  4. Fetch and normalize dataset records.
  5. Populate method filter options from the data.
  6. Apply filters and hand the result to the virtual grid.
  7. Render saved panel state and register the shade share 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() and rgbToHex() parse and serialize HEX and RGB.
  • rgbToLab() computes CIE Lab values for inspection.
  • rgbToOklab() and rgbToOklch() 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.

12. Save, share and token dialog

+

Saved shades use localStorage for immediate tab state and mirrorSave() for workspace visibility.

  • toggleSaved(id) caps local saved ids at 500 entries.
  • mirrorSave() stores domain shades, asset type shade, tool id library-shades, description, colors and payload.
  • mirrorRemove() removes workspace mirror entries when a shade is unsaved.
  • shareShadeLink() calls shareViaDialog() with type shade.
  • registerShareHandler("shade", hydrateFromSharedShade) opens a matching shade from a shared payload.
  • openTokensDialog() builds tokens with default prefix color and base name shade-{id}.

The imported tokensFromSwatchList is not required by the current token export path; the runtime builds shade token objects directly so existing token names can be preserved.

13. Accessibility and UX rules

+
  • The app container uses role="application".
  • Tabs use role="tablist", role="tab", aria-selected and aria-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" and aria-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.dismissed is 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-gen when 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_KEY or 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.