Add the Extrudex Design System v3 bundle
Tokens (light + dark, neumorphism, 54/54 WCAG AA contrast pairs), the self-hosted JetBrains Mono fonts, and interactive mockups of every screen across three iterations. Iteration 3 is final: phone, tablet and desktop tiers, device preview, and "empty spool weight" terminology. The build scripts regenerate the screens byte-identically from source. Implementation is tracked in Maestro feature UI Refresh - V3.0 (224b72a1-8d84-4970-97ea-5dafa4d8ea3b). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9ba0d409c8
commit
d9ed1898b9
@@ -0,0 +1,10 @@
|
||||
def lum(h):
|
||||
h=h.lstrip('#'); r,g,b=[int(h[i:i+2],16)/255 for i in (0,2,4)]
|
||||
f=lambda c: c/12.92 if c<=0.03928 else ((c+0.055)/1.055)**2.4
|
||||
return 0.2126*f(r)+0.7152*f(g)+0.0722*f(b)
|
||||
def cr(a,b):
|
||||
la,lb=sorted([lum(a),lum(b)],reverse=True); return (la+0.05)/(lb+0.05)
|
||||
import sys
|
||||
pairs=[l.split() for l in sys.stdin if l.strip()]
|
||||
for p in pairs:
|
||||
print(f"{p[0]:>9} on {p[1]:>9} {cr(p[0],p[1]):5.2f} {' '.join(p[2:])}")
|
||||
@@ -0,0 +1,22 @@
|
||||
import pathlib; exec(open(pathlib.Path(__file__).with_name('contrast.py')).read().split('import sys')[0])
|
||||
def blend(fg,bg,a):
|
||||
f=[int(fg[i:i+2],16) for i in (1,3,5)]; b=[int(bg[i:i+2],16) for i in (1,3,5)]
|
||||
return '#'+''.join(f'{round(x*a+y*(1-a)):02x}' for x,y in zip(f,b))
|
||||
D=dict(page='#2c2c30',inset='#232327',high='#36363a',text='#f4f4f6',muted='#b2b2ba',acc='#a99af0',accbg='#a99af0',onacc='#2a2431',ctl='#85858f',ok='#a9d88b',err='#f08b93',warn='#e8c170',info='#8fc3f0')
|
||||
L=dict(page='#e4e2ea',inset='#d9d6e1',high='#f1f0f5',text='#2a2431',muted='#55505f',acc='#5b43b8',accbg='#5b43b8',onacc='#ffffff',ctl='#736e86',ok='#2c6619',err='#a8202f',warn='#7c5100',info='#1d5e94')
|
||||
rows=[]
|
||||
for name,T in (('Dark',D),('Light',L)):
|
||||
chk=[('Body text','text','page',4.5),('Body text on inset (inputs)','text','inset',4.5),('Body text on high surface (dialog)','text','high',4.5),
|
||||
('Secondary text','muted','page',4.5),('Secondary text on inset','muted','inset',4.5),('Secondary text on high','muted','high',4.5),
|
||||
('Accent text / links','acc','page',4.5),('Accent text on high','acc','high',4.5),('Text on primary button','onacc','accbg',4.5),
|
||||
('Success text','ok','page',4.5),('Error text','err','page',4.5),('Error text on high','err','high',4.5),('Warning text','warn','page',4.5),('Info text','info','page',4.5),
|
||||
('Control border vs page (1.4.11)','ctl','page',3),('Control border vs inset','ctl','inset',3),('Control border vs high','ctl','high',3),('Focus ring vs page','acc','page',3),('Focus ring vs high','acc','high',3),
|
||||
('Primary button fill vs page','accbg','page',3),('Error border vs inset','err','inset',3),('Warning border vs page','warn','page',3)]
|
||||
for label,a,b,need in chk:
|
||||
r=cr(T[a],T[b]); rows.append((name,label,T[a],T[b],r,need))
|
||||
# tinted chips: 10% wash of status over page
|
||||
for s in ('ok','err','warn','info','acc'):
|
||||
bg=blend(T[s],T['page'],0.10); r=cr(T[s],bg); rows.append((name,f'{s} chip text on 10% wash',T[s],bg,r,4.5))
|
||||
print('| Theme | Pair | Foreground | Background | Ratio | Needs | Result |\n|---|---|---|---|---|---|---|')
|
||||
for n,l,a,b,r,need in rows:
|
||||
print(f"| {n} | {l} | `{a}` | `{b}` | {r:.2f}:1 | {need}:1 | {'Pass' if r>=need else '**FAIL**'} |")
|
||||
Reference in New Issue
Block a user