docs/design/v2: add 12-variant React design archive
Release / release (push) Successful in 3m19s

Stash the full claude.ai/design output (12 JSX variants — brutalist,
classic, cli, compact, fluent-live, glass, hero-live, minimal,
sketches, studio, wizard-live, workshop — plus shared hooks and a
standalone HTML preview) for reference when we get to the Wails
frontend in Phase 6/7.

Source archive: C:\Users\root\Downloads\app(1).zip (~1MB).

Not wired into any build target yet — current GUI is the temporary
MessageBox stub. Pulling these in is the goal of the Wails phase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 03:12:02 +03:00
parent 5da30ad058
commit 113616b039
20 changed files with 6566 additions and 0 deletions
+293
View File
@@ -0,0 +1,293 @@
// drover-v2.jsx — Round 2: four new dark-only variants.
// Reuses window.useDrover / StatusDot / icons / fmt helpers from drover-shared.jsx.
// =============================================================================
// V5 — COMPACT PRO. High-density, table-like. Wireshark/HTOP feel. Mono numbers.
// =============================================================================
const CPT = {
bg: '#101216', chrome: '#0a0c0f', panel: '#15181d', panel2: '#1a1d23',
border: '#262a31', borderSoft: '#1d2026',
text: '#e1e3e8', dim: '#838892', dimmer: '#535862',
accent: '#7aa9ff', danger: '#e5685a', warn: '#d6a64a', pass: '#5fc888', skip: '#6a6f78',
inputBg: '#0c0e12', primaryFg: '#0b1426',
};
function CompactWindow({ initial }) {
const t = CPT;
const D = window.useDrover(initial);
const palette = { pending: t.dimmer, running: t.accent, passed: t.pass, failed: t.danger, skipped: t.skip };
const fontMono = '"JetBrains Mono","SF Mono",ui-monospace,Consolas,monospace';
const fontUI = '"Inter","Segoe UI",system-ui,sans-serif';
const isActive = D.phase === 'active';
return (
<div style={{
width: 480, height: 640, background: t.bg, color: t.text, display:'flex', flexDirection:'column',
fontFamily: fontUI, fontSize: 12, overflow: 'hidden',
border: '1px solid #000',
}}>
{/* title bar */}
<div style={{
height: 28, background: t.chrome, borderBottom:`1px solid ${t.border}`,
display:'flex', alignItems:'center', userSelect:'none',
}}>
<div style={{ display:'flex', alignItems:'center', gap: 7, padding:'0 10px', flex:1 }}>
<window.BrandMark size={12} color={t.accent}/>
<span style={{ fontSize: 11.5, fontWeight: 600 }}>drover-go</span>
<span style={{ fontSize: 10, color: t.dimmer, fontFamily: fontMono }}>0.4.2</span>
<span style={{ fontSize: 10, color: t.dim, marginLeft: 8, fontFamily: fontMono }}>
· {D.form.host}:{D.form.port}{D.form.auth ? ' · auth' : ''}
</span>
</div>
<div style={{ display:'flex' }}>
<CompactCell t={t}><window.IconGear color={t.dim}/></CompactCell>
<CompactCell t={t}><window.IconMin color={t.dim}/></CompactCell>
<CompactCell t={t} hover="#c0463f"><window.IconClose color={t.dim}/></CompactCell>
</div>
</div>
<div style={{ flex: 1, overflow:'auto' }}>
{/* Row 1: form, single tight line */}
<div style={{ padding: '10px 12px', borderBottom:`1px solid ${t.borderSoft}` }}>
<div style={cptHead(t)}>SOCKS5</div>
<div style={{ display:'flex', gap: 6, alignItems:'center' }}>
<CptInput t={t} fontMono={fontMono} value={D.form.host}
onChange={v => D.update({ host: v })} placeholder="host" style={{ flex: 1 }}
onSubmit={D.runCheck}/>
<span style={{ color: t.dimmer, fontFamily: fontMono }}>:</span>
<CptInput t={t} fontMono={fontMono} value={D.form.port}
onChange={v => D.update({ port: v.replace(/\D/g,'') })}
placeholder="port" style={{ width: 64 }} onSubmit={D.runCheck}/>
<CptCheck t={t} checked={D.form.auth} onChange={(v) => {
D.update({ auth: v }); if (v) setTimeout(()=>document.getElementById('cpt-login')?.focus(),30);
}}>auth</CptCheck>
</div>
{D.form.auth && (
<div style={{ display:'flex', gap: 6, marginTop: 6 }}>
<CptInput id="cpt-login" t={t} fontMono={fontMono} value={D.form.login}
onChange={v => D.update({ login: v })} placeholder="login"
style={{ flex: 1 }} onSubmit={D.runCheck}/>
<CptInput t={t} fontMono={fontMono} value={D.form.password} type="password"
onChange={v => D.update({ password: v })} placeholder="password"
style={{ flex: 1 }} onSubmit={D.runCheck}/>
</div>
)}
<button onClick={D.runCheck} disabled={D.phase === 'checking' || isActive} style={{
marginTop: 8, width:'100%', padding:'6px 10px', borderRadius: 2, fontFamily: fontMono,
background: (D.phase==='checking'||isActive)?t.panel2:t.accent,
color: (D.phase==='checking'||isActive)?t.dimmer:t.primaryFg,
border:`1px solid ${t.border}`, fontWeight: 700, fontSize: 11.5, letterSpacing: 0.5,
cursor: D.phase==='checking'?'not-allowed':'pointer', textAlign: 'left',
}}>
{'>>'} {D.phase==='checking'?'CHECKING…':'check connection'}
</button>
</div>
{/* Row 2: status table, full width */}
<div style={{ padding: '8px 12px', borderBottom:`1px solid ${t.borderSoft}` }}>
<div style={cptHead(t)}>
<span>STATUS</span>
<span style={{ marginLeft:'auto', color: t.dim, fontFamily: fontMono }}>
{D.phase === 'idle' && 'idle'}
{D.phase === 'checking' && `${Object.keys(D.results).length}/${D.tests.length}`}
{(D.phase === 'checked' || D.phase === 'active') &&
(D.lastSummary?.failed === 0 ? 'all-pass' : `${D.lastSummary?.failed}/${D.tests.length} fail`)}
</span>
</div>
{D.phase === 'idle'
? <div style={{ color: t.dim, fontFamily: fontMono, fontSize: 11 }}>
<span style={{ color: t.dimmer }}></span> ready to check_
</div>
: <CompactStatusTable t={t} D={D} palette={palette} fontMono={fontMono}/>}
</div>
{/* Row 3: actions */}
<div style={{ padding: '8px 12px' }}>
<div style={{ display:'flex', gap: 6 }}>
<CompactStartBtn t={t} D={D} fontMono={fontMono}/>
<CompactStopBtn t={t} D={D} fontMono={fontMono}/>
</div>
{isActive && (
<div style={{
marginTop: 8, padding: '5px 8px', background: t.panel,
border:`1px solid ${t.borderSoft}`, borderRadius: 2,
fontFamily: fontMono, fontSize: 10.5, color: t.dim,
display:'flex', justifyContent:'space-between',
}}>
<span><window.IconArrowUp color={t.pass}/> {window.fmtBytes(D.stats.up)}</span>
<span><window.IconArrowDown color={t.accent}/> {window.fmtBytes(D.stats.down)}</span>
<span>tcp:{D.stats.tcp}</span>
<span>udp:{D.stats.udp}</span>
<span>up:{window.fmtUptime(D.stats.uptimeS)}</span>
</div>
)}
</div>
</div>
{/* Logs */}
<CompactLogs t={t} D={D} fontMono={fontMono}/>
</div>
);
}
function CompactCell({ children, t, hover }) {
const [h, setH] = React.useState(false);
return <div onMouseEnter={()=>setH(true)} onMouseLeave={()=>setH(false)} style={{
width: 32, height: 28, display:'flex', alignItems:'center', justifyContent:'center',
cursor:'pointer', background: h && hover ? hover : 'transparent', transition:'background .1s',
}}>{children}</div>;
}
function cptHead(t) {
return {
fontSize: 9.5, letterSpacing: 1.5, color: t.dim, fontWeight: 700,
marginBottom: 6, display:'flex', alignItems:'center',
};
}
function CptInput({ value, onChange, placeholder, type, style, onSubmit, t, fontMono, id }) {
return <input id={id} value={value} type={type||'text'}
onChange={e => onChange(e.target.value)} placeholder={placeholder}
onKeyDown={e => e.key === 'Enter' && onSubmit?.()}
style={{
background: t.inputBg, color: t.text, border:`1px solid ${t.border}`,
borderRadius: 2, padding:'5px 7px', fontFamily: fontMono, fontSize: 11.5,
outline:'none', boxSizing:'border-box', ...style,
}}/>;
}
function CptCheck({ checked, onChange, t, children }) {
return (
<label style={{
display:'inline-flex', alignItems:'center', gap: 5, cursor:'pointer', userSelect:'none',
padding:'4px 7px', border:`1px solid ${checked?t.accent:t.border}`, borderRadius: 2,
fontFamily: '"JetBrains Mono",monospace', fontSize: 11,
background: checked ? `${t.accent}22` : 'transparent', color: checked ? t.accent : t.dim,
}}>
<span>[{checked ? 'x' : ' '}]</span>
<input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)} style={{display:'none'}}/>
<span>{children}</span>
</label>
);
}
function CompactStatusTable({ t, D, palette, fontMono }) {
return (
<div style={{ fontFamily: fontMono, fontSize: 11 }}>
{D.tests.map((test) => {
const r = D.results[test.id];
const state = r?.result || (D.running === test.id ? 'running' : 'pending');
return (
<div key={test.id}>
<div style={{
display:'flex', alignItems:'center', gap: 7, padding:'2px 0', height: 20,
color: state === 'pending' ? t.dimmer : t.text,
}}>
<span style={{ width: 10, color: t.dimmer }}>{
state==='passed'?'✓':state==='failed'?'✗':state==='skipped'?'':state==='running'?'':'·'
}</span>
<window.StatusDot state={state} palette={palette} size={10}/>
<span title={test.desc}>{test.label}</span>
<span style={{
marginLeft:'auto',
color: state==='failed'?t.danger:state==='skipped'?t.skip:state==='passed'?t.pass:t.dim,
}}>{r?.metric || (state==='running'?'…':'')}</span>
{r?.result === 'failed' && (
<button onClick={() => D.toggleExpand(test.id)} style={{
background:'transparent', border:'none', cursor:'pointer', padding: 2, color: t.dim,
}}><window.IconChevron color={t.dim} dir={r.expanded?'up':'down'}/></button>
)}
</div>
{r?.result === 'failed' && r.expanded && (
<div className="drv-fadein" style={{
margin: '2px 0 6px 17px', padding:'5px 8px',
background: t.panel2, borderLeft:`2px solid ${t.danger}`,
fontSize: 10.5, color: t.dim,
}}>
<div style={{ color: t.danger, fontWeight: 600, marginBottom: 2 }}>{r.error}</div>
<div>{r.hint}</div>
</div>
)}
</div>
);
})}
</div>
);
}
function CompactStartBtn({ t, D, fontMono }) {
const allFailed = D.lastSummary && D.lastSummary.failed === D.tests.length;
const ok = D.phase === 'checked' && !allFailed;
const active = D.phase === 'active';
const warning = active && (D.lastSummary?.failed || 0) > 0;
if (active) {
const c = warning ? t.warn : t.pass;
return (
<div style={{
flex:1, padding:'6px 10px', border:`1px solid ${c}`, borderRadius: 2,
background: `${c}1a`, color: c, fontFamily: fontMono, fontWeight: 700, fontSize: 11.5,
display:'flex', alignItems:'center', gap: 6,
}}>
<span className="drv-pulsedot" style={{ width: 6, height: 6, borderRadius: 3, background: c }}/>
ACTIVE{warning ? ' · UDP-FALLBACK' : ''}
</div>
);
}
return (
<button onClick={D.startProxy} disabled={!ok} style={{
flex: 1, padding:'6px 10px', borderRadius: 2,
background: ok ? t.accent : t.panel, color: ok ? t.primaryFg : t.dimmer,
border:`1px solid ${ok ? t.accent : t.border}`, fontFamily: fontMono,
fontWeight: 700, fontSize: 11.5, letterSpacing: 0.5, textAlign:'left',
cursor: ok ? 'pointer' : 'not-allowed',
}}>{'>'} start proxying</button>
);
}
function CompactStopBtn({ t, D, fontMono }) {
const enabled = D.phase === 'active';
return (
<button onClick={D.stopProxy} disabled={!enabled} style={{
flex: 1, padding:'6px 10px', borderRadius: 2,
background: t.panel, color: enabled ? t.text : t.dimmer,
border:`1px solid ${t.border}`, fontFamily: fontMono,
fontWeight: 700, fontSize: 11.5, letterSpacing: 0.5, textAlign:'left',
cursor: enabled ? 'pointer' : 'not-allowed',
}}>{'■'} stop</button>
);
}
function CompactLogs({ t, D, fontMono }) {
return (
<div style={{ borderTop:`1px solid ${t.border}`, background: t.chrome, flexShrink: 0 }}>
<button onClick={() => D.setLogsOpen(!D.logsOpen)} style={{
width:'100%', padding:'6px 12px', display:'flex', alignItems:'center', gap: 7,
background:'transparent', border:'none', color: t.dim, cursor:'pointer',
fontFamily: fontMono, fontSize: 10.5, letterSpacing: 1,
}}>
<window.IconChevron color={t.dim} dir={D.logsOpen?'down':'right'}/>
<span style={{ fontWeight: 700 }}>LOGS</span>
<span style={{ marginLeft:'auto', color: t.dimmer }}>{D.logs.length} lines</span>
</button>
{D.logsOpen && (
<>
<div style={{ display:'flex', gap: 4, padding:'0 12px 6px' }}>
{[['copy', () => navigator.clipboard?.writeText(D.logs.map(x=>`[${x.level}] ${x.msg}`).join('\n'))],
['clear', D.clearLogs], ['file', null]].map(([l, fn]) => (
<button key={l} onClick={fn||undefined} style={{
background:'transparent', border:`1px solid ${t.border}`, color: t.dim,
padding:'2px 7px', fontSize: 10, fontFamily: fontMono, cursor:'pointer', borderRadius: 2,
}}>{l}</button>
))}
</div>
<div className="drv-log" ref={el => el && (el.scrollTop = el.scrollHeight)}
style={{ maxHeight: 110, overflowY:'auto', padding:'5px 12px',
fontFamily: fontMono, fontSize: 10, lineHeight: 1.55, color: t.dim, background: t.panel }}>
{D.logs.map((l,i) => (
<div key={i}>
<span style={{ color: t.dimmer }}>{window.fmtTime(l.t)}</span>{' '}
<span style={{ color: l.level==='ERROR'?t.danger:l.level==='WARN'?t.warn:t.pass, fontWeight: 700 }}>{l.level.padEnd(5)}</span>{' '}
{l.msg}
</div>
))}
</div>
</>
)}
</div>
);
}
window.CompactWindow = CompactWindow;