aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/previews.js
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-24 14:44:28 -0400
committerCraig Jennings <c@cjennings.net>2026-06-24 16:15:24 -0400
commitfa5b28ea69f3bff0941f8a097a9746b7a67fa900 (patch)
tree71571b286b77b9168de3308f50877ad7f6fa4854 /scripts/theme-studio/previews.js
parentc11ad211f5d72b6ee2b48d80f25d16e3e85248eb (diff)
downloaddotemacs-fa5b28ea69f3bff0941f8a097a9746b7a67fa900.tar.gz
dotemacs-fa5b28ea69f3bff0941f8a097a9746b7a67fa900.zip
feat(theme-studio): nerd-icons gallery as a hue-ordered icon grid
The nerd-icons pane is now a grid: one row per color face, the rows ordered by hue so families cluster, distinct icons (deduped within a color) drawn in their color with the icon's nerd-font name beneath. A "preview:" dropdown above the grid picks the glyph size in points, with Left/Right arrows to step it. Single-pane apps show it disabled, naming the preview. This replaces the v1 legend in the pane, whose data is still captured for round-trip. build-nerd-icons-legend.el is now a library. A cj/nerd-icons-write-legend entry point requires nerd-icons only at write time, so the capture logic loads and unit-tests without it. It dedupes icons by name within a face, computes each face's native hue, and orders the groups by hue. Writing the test surfaced a latent bug: face-hsl used (cadr (assoc t spec)), which grabs the first keyword instead of the plist. It only worked because the real faces fall through to the face-foreground branch. I fixed it to a correct t-clause parse. Coverage: 7 ERT capture tests (dedupe, hue order, lightness tiebreak, name sort, skip rules), 4 Python validator edges, and browser gates for the grid and the size dropdown. Locate stays color-level: clicking a color flashes its icons, and clicking an icon flashes its color row. Icons aren't individually editable, so there's nothing per-icon to select.
Diffstat (limited to 'scripts/theme-studio/previews.js')
-rw-r--r--scripts/theme-studio/previews.js39
1 files changed, 28 insertions, 11 deletions
diff --git a/scripts/theme-studio/previews.js b/scripts/theme-studio/previews.js
index 592640cea..11ea13caa 100644
--- a/scripts/theme-studio/previews.js
+++ b/scripts/theme-studio/previews.js
@@ -498,14 +498,31 @@ function renderMarkdownPreview(){const a='markdown-mode',L=[];
L.push(os(a,'markdown-html-tag-delimiter-face','&lt;')+os(a,'markdown-html-tag-name-face','kbd')+os(a,'markdown-html-tag-delimiter-face','&gt;')+'Ctrl-C'+os(a,'markdown-html-tag-delimiter-face','&lt;/')+os(a,'markdown-html-tag-name-face','kbd')+os(a,'markdown-html-tag-delimiter-face','&gt;'));
L.push(os(a,'markdown-footnote-marker-face','[^1]:')+' '+os(a,'markdown-footnote-text-face','the footnote text.'));
return previewLines(L);}
-// nerd-icons legend preview: each curated filetype's real nerd-font glyph drawn
-// in its mapped color face, then the sample name. The legend rides
-// APPS['nerd-icons'].legend (captured by build-nerd-icons-legend.el); recoloring
-// a face repaints every row mapped to it because os() reads the live registry.
-// Falls back to the generic preview if the legend is missing (the bespoke app
-// only registers with a valid one, so that path is defensive).
-function renderNerdIconsPreview(){
- const a='nerd-icons',rows=(APPS[a]&&APPS[a].legend)||[],L=[];
- if(!rows.length)return genericPreview(a);
- for(const r of rows) L.push(os(a,r.face,r.glyph)+' '+r.label);
- return previewLines(L);}
+// nerd-icons gallery grid: the full colored catalog. Every distinct face-bearing
+// nerd-icons glyph (APPS['nerd-icons'].gallery, captured by build-nerd-icons-legend.el),
+// one row per color face, the rows ordered by hue so families cluster (blues
+// together, reds together). Each cell draws the glyph in its face color with the
+// icon's nerd-font name beneath. SIZEPT (points, default 14) sizes the glyphs so
+// the designer can view the grid at different buffer sizes via the preview-pane
+// dropdown; the cell width scales with it. Recoloring a face repaints its swatch
+// and every glyph in its row because os() reads the live registry. Falls back to
+// the generic preview if the gallery is missing (the bespoke app registers with a
+// valid legend, so that path is defensive).
+function renderNerdIconsPreview(sizePt){
+ const a='nerd-icons',groups=(APPS[a]&&APPS[a].gallery)||[];
+ if(!groups.length)return genericPreview(a);
+ const pt=sizePt||14,cellW=Math.round(pt*4.6+24);
+ let h=`<div class="ni-gallery" style="padding:10px 14px;font:10pt/1.4 ${PREVIEW_FONT}">`;
+ for(const g of groups){
+ h+='<div class="ni-row" style="margin:0 0 10px;border-top:1px solid #2a2a2a;padding-top:6px">'
+ +`<div class="ni-row-head" style="color:#8a8a8a;padding:0 0 5px">`
+ +os(a,g.face,'■')+' '+esc(g.face)+' ('+g.glyphs.length+')</div>'
+ +'<div class="ni-cells">';
+ for(const e of g.glyphs)
+ h+=`<span class="ni-cell" style="display:inline-block;width:${cellW}px;text-align:center;vertical-align:top;margin:3px 1px">`
+ +`<span style="font-size:${pt}pt;line-height:1.3">`+os(a,g.face,e.glyph)+'</span><br>'
+ +`<span style="font-size:7.5pt;color:#9a9a9a;word-break:break-all;line-height:1.2">`+esc(e.name)+'</span>'
+ +'</span>';
+ h+='</div></div>';
+ }
+ return h+'</div>';}