From c7518d6f297038fa9911f207d06834d4b0d24374 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Tue, 9 Jun 2026 04:43:43 -0500 Subject: feat(theme-studio): swatch dropdowns, lock toggles, palette seeding The design session added a batch of tool features. They landed together in the page generator, so this commits them as one. A custom swatch color dropdown replaces the native select in the syntax table, showing a color square, name, and hex per row, because native option backgrounds render unreliably on Linux Chrome. THEME_STUDIO_SEED= seeds the tool's starting palette, assignments, bold, italic, and UI from a theme.json at generate time, so opening the tool on a given palette is one regenerate with no import step. Lock toggles sit on all three tables. A closed lock marks a decided element/color pairing and disables that row's editing controls. Clear-unlocked resets the rest to default and leaves the locked rows alone. Locks persist in the saved theme, with keys namespaced (bare syntax, ui:, pkg:) so the tiers don't collide. The UI faces table gained a contrast column, and the three tables now share one column order: name, lock, color, style, contrast. The bg and fg rows are renamed to "bg (ground)" and "fg". --- scripts/theme-studio/generate.py | 158 +++++++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 31 deletions(-) (limited to 'scripts/theme-studio/generate.py') diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py index e6926e04..ee10e23f 100644 --- a/scripts/theme-studio/generate.py +++ b/scripts/theme-studio/generate.py @@ -24,7 +24,7 @@ MAP={k:v[0] for k,v in COLS.items()}; BOLD={k:v[1] for k,v in COLS.items()}; MAP PALETTE=[["#67809c","blue"],["#e8bd30","gold"],["#9b5fd0","regal"],["#2ba178","emerald"],["#5d9b86","sage"], ["#cb6b4d","terracotta"],["#be9e74","tan"],["#ffffff","white"],["#a9b2bb","silver"],["#838d97","steel"], ["#5e6770","pewter"],["#2f343a","gunmetal"],["#264364","navy"],["#000000","ground"],["#1a1714","bg-dim"]] -CATS=[["bg","background (ground)","Aa Bb 123"],["p","fg · default text","other / whitespace"],["kw","keyword","class def if return"],["bi","builtin","len echo printf"], +CATS=[["bg","bg (ground)","Aa Bb 123"],["p","fg","other / whitespace"],["kw","keyword","class def if return"],["bi","builtin","len echo printf"], ["pp","preprocessor","#include #define"],["fnd","function · def","resolve push"], ["fnc","function · call","printf rsync get"],["dec","decorator","@dataclass"], ["ty","type / class","int str Order Queue"],["prop","property / field","id name items"], @@ -53,6 +53,23 @@ UIMAP={"cursor":{"fg":None,"bg":"#a9b2bb"},"region":{"fg":None,"bg":"#264364"}, "show-paren-mismatch":{"fg":"#0d0b0a","bg":"#cb6b4d"},"link":{"fg":"#67809c","bg":None}, "error":{"fg":"#cb6b4d","bg":None},"warning":{"fg":"#e8bd30","bg":None}, "success":{"fg":"#5d9b86","bg":None},"vertical-border":{"fg":"#2f343a","bg":None}} + +# Optional palette seed: THEME_STUDIO_SEED= seeds the tool's starting +# palette / assignments / bold / italic / UI from a theme.json (path relative to +# this dir), instead of the hardcoded defaults above. Unset leaves them unchanged. +# Placed after every default it overrides (notably UIMAP) so the merge has targets. +# Mirrors what the in-page Import does, so reseed and import agree. +LOCKS=[]; ITALIC=[] +_seed=os.environ.get('THEME_STUDIO_SEED') +if _seed: + _d=json.load(open(os.path.join(HERE,_seed))) + if _d.get('palette'): PALETTE=_d['palette'] + if _d.get('assignments'): MAP.update(_d['assignments']) + if 'bold' in _d: BOLD={k:(k in _d['bold']) for k in BOLD} + if 'italic' in _d: ITALIC=_d['italic'] + if _d.get('ui'): + for _k,_v in _d['ui'].items(): UIMAP[_k]=_v + if 'locks' in _d: LOCKS=_d['locks'] # link is underlined by default (matches the built-in link face). UIMAP["link"]["underline"]=True # Tier-3 package faces (Phase 2): complete own-defface sets for org/magit/elfeed, @@ -396,6 +413,18 @@ HTML = """theme-studio table.leg th{cursor:pointer;color:#b4b1a2;text-align:left;padding:4px 12px;user-select:none;font-weight:normal} table.leg th:hover{color:#e8bd30} select.chip{appearance:none;border:1px solid #00000060;border-radius:5px;padding:5px 10px;font:bold 14px monospace;width:160px;cursor:pointer} + .cdd{display:inline-flex;align-items:center;gap:7px;border:1px solid #00000060;border-radius:5px;padding:5px 10px;font:bold 13px monospace;width:160px;cursor:pointer;box-sizing:border-box;overflow:hidden;white-space:nowrap} + .cddsw{display:inline-block;width:13px;height:13px;border-radius:3px;border:1px solid #0007;flex:none} + .cddpop{position:fixed;z-index:200;background:#161412;border:1px solid #3a3a3a;border-radius:6px;box-shadow:0 12px 34px #000c;max-height:60vh;overflow:auto;padding:4px} + .cddrow{display:flex;align-items:center;gap:9px;padding:4px 9px;cursor:pointer;color:#cdced1;font:12px monospace;border-radius:4px;white-space:nowrap} + .cddrow:hover{background:#252321} + .cddrow.sel{outline:1px solid #e8bd30;outline-offset:-1px} + .cddrow .cddnm{flex:1} + .cddrow .cddhx{opacity:.55;margin-left:10px} + .cdd.locked{cursor:default;opacity:.85;box-shadow:inset 0 0 0 2px #e8bd3088} + .lockbtn{background:none;border:none;cursor:pointer;font-size:15px;line-height:1;padding:2px 4px;opacity:.5;filter:grayscale(1)} + .lockbtn.on{opacity:1;filter:none} + .legctl{margin:0 0 8px;display:flex;gap:8px;align-items:center} .cat{color:#b4b1a2} .ex{font-size:17px} .sbtn{width:26px;height:24px;border:1px solid #3a3a3a;border-radius:3px;background:#eaeaea;color:#111;cursor:pointer;font-size:15px;margin-right:2px;padding:0} .sbtn.on{background:#0d0b0a;color:#cdced1;border-color:#8a9496} @@ -511,7 +540,8 @@ HTML = """theme-studio

code/color assignments

-
elements △color △styleexamplecontrast
+
+
elements △color △stylecontrastexample
@@ -521,7 +551,8 @@ HTML = """theme-studio

ui faces

-
face △foreground △background △stylepreview
+
+
face △foreground △background △stylecontrast △preview
@@ -533,10 +564,11 @@ HTML = """theme-studio +
-
face △fg △bg △styleinherit △size △contrast △
+
face △fg △bg △stylecontrast △inherit △size △
@@ -545,7 +577,8 @@ HTML = """theme-studio