Files
noise/signal-emacs-ui.html

209 lines
13 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>signal.el — UI screens</title>
<style>
:root{
--page:#15171c;
--bg:#282c34;
--bg-dim:#21252b;
--fg:#bbc2cf;
--fg-dim:#5b6268;
--fg-faint:#3f4450;
--modeline-bg:#1c1f24;
--modeline-fg:#9da5b4;
--modeline-inactive:#5b6268;
--hl-line:#2c323c;
--blue:#3a76f0; /* Signal blue: prompt, matches, selection */
--blue-soft:#6f9bf5;
--green:#98be65; /* delivered, e2e */
--yellow:#ecbe7b; /* unread */
--red:#ff6c6b;
--mono:"Iosevka","JetBrains Mono","Fira Code",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
body{
background:var(--page);
color:var(--fg);
font-family:var(--mono);
font-size:14px;
line-height:1.5;
padding:56px 20px 96px;
}
.wrap{max-width:900px;margin:0 auto}
header.page{margin-bottom:56px}
header.page h1{
font-size:15px;font-weight:600;letter-spacing:.04em;color:var(--fg);
}
header.page h1 .ext{color:var(--blue-soft)}
header.page p{
margin-top:6px;color:var(--fg-dim);font-size:13px;max-width:62ch;
}
kbd{
color:var(--blue-soft);
font-family:inherit;font-size:inherit;
}
section.screen{margin-bottom:72px}
.caption{
display:flex;align-items:baseline;gap:14px;margin-bottom:12px;
}
.caption h2{
font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
color:var(--modeline-fg);
}
.caption span{font-size:12px;color:var(--fg-dim)}
/* ——— the Emacs frame ——— */
.frame{
background:var(--bg);
border:1px solid #0c0d10;
border-radius:6px;
overflow:hidden;
box-shadow:0 14px 40px rgba(0,0,0,.45);
}
.buffer{
padding:10px 0 14px;
min-height:330px;
white-space:pre;
overflow-x:auto;
tab-size:4;
}
.ln{padding:0 16px 0 22px;position:relative}
.fringe{position:absolute;left:8px;color:var(--yellow)}
.hl{background:var(--hl-line)}
.header-line{
background:var(--bg-dim);
color:var(--fg-dim);
padding:2px 16px 2px 22px;
border-bottom:1px solid #1a1d22;
white-space:pre;overflow-x:auto;
}
.dim{color:var(--fg-dim)}
.faint{color:var(--fg-faint)}
.name{color:var(--fg);font-weight:600}
.unread{color:var(--yellow);font-weight:600}
.blue{color:var(--blue-soft)}
.green{color:var(--green)}
.me{color:var(--blue-soft);font-weight:600}
.sep{color:var(--fg-faint)}
.modeline{
background:var(--modeline-bg);
color:var(--modeline-fg);
padding:2px 16px;
white-space:pre;overflow-x:auto;
border-top:1px solid #14161a;
}
.modeline .mode{color:var(--blue-soft)}
.modeline .e2e{color:var(--green)}
.echo{
background:var(--bg);
color:var(--fg-dim);
padding:3px 16px 5px;
white-space:pre;overflow-x:auto;
}
.echo kbd{color:var(--blue-soft)}
.cursor{
display:inline-block;width:.62em;height:1.25em;
background:var(--fg);vertical-align:text-bottom;
animation:blink 1.1s steps(1) infinite;
}
@media (prefers-reduced-motion:reduce){.cursor{animation:none}}
@keyframes blink{50%{opacity:0}}
/* minibuffer completion (vertico-style) */
.dimmed{opacity:.38}
.mini{
background:var(--bg);
border-top:1px solid #14161a;
padding:4px 0 6px;
white-space:pre;overflow-x:auto;
}
.cand{padding:0 16px 0 22px}
.cand.sel{background:var(--hl-line)}
.cand .m{color:var(--blue-soft);font-weight:700}
.cand .ann{color:var(--fg-faint)}
.prompt{padding:2px 16px 0 22px}
.prompt .p{color:var(--blue-soft);font-weight:600}
.prompt .count{color:var(--fg-dim)}
/* which-key panel */
.whichkey{
background:var(--bg-dim);
border-top:1px solid #14161a;
padding:8px 0 10px;
white-space:pre;overflow-x:auto;
}
.wk{padding:0 16px 0 22px}
.wk kbd{color:var(--blue-soft);font-weight:600}
.wk .arr{color:var(--fg-faint)}
@media (max-width:560px){
body{font-size:12px;padding:32px 8px 64px}
.buffer{min-height:240px}
}
</style>
</head>
<body>
<div class="wrap">
<header class="page">
<h1>signal<span class="ext">.el</span> — screens</h1>
<p>Four frames. No mouse targets, no chrome. Every action is a binding; conversation switching is a minibuffer completion, never a sidebar.</p>
</header>
<!-- ============ SCREEN 1: chat list ============ -->
<section class="screen">
<div class="caption"><h2>Chat list</h2><span>*signal* — ibuffer-style root buffer, <kbd>n</kbd>/<kbd>p</kbd> to move, <kbd>RET</kbd> to open</span></div>
<div class="frame">
<div class="header-line"> U Name Last message When</div>
<div class="buffer"><div class="ln"><span class="fringe"></span><span class="unread"> 3</span> <span class="name">Family</span> <span class="dim">Dad: see you sunday then</span> <span class="faint">09:41</span></div><div class="ln hl"><span class="fringe"></span><span class="unread"> 1</span> <span class="name">Sarah</span> <span class="dim">photo: IMG_2041.jpg</span> <span class="faint">09:12</span></div><div class="ln"> <span class="name">Mark Okafor</span> <span class="dim">me: merged, cutting the release now</span> <span class="faint">08:55</span></div><div class="ln"> <span class="name">cycling crew</span> <span class="dim">Priya: saturday 7am, usual spot?</span> <span class="faint">Mon</span></div><div class="ln"> <span class="name">Hawat alerts</span> <span class="dim">backup completed: zendo (4.2 GiB)</span> <span class="faint">Mon</span></div><div class="ln"> <span class="name">Elena V.</span> <span class="dim">thanks! that fixed it</span> <span class="faint">Sun</span></div><div class="ln"> <span class="name">school parents</span> <span class="dim">Reminder: early pickup friday</span> <span class="faint">Sun</span></div><div class="ln"> <span class="name">Tom</span> <span class="dim">me: voice message (0:42)</span> <span class="faint">Jun 5</span></div><div class="ln"> <span class="name">Note to Self</span> <span class="dim">uv pip compile --universal</span> <span class="faint">Jun 4</span></div></div>
<div class="modeline"> <span class="e2e"></span> <b>*signal*</b> 9 chats · 4 unread <span class="mode">(Signal Chats)</span> ─ U:%%- ─ Top ────────────</div>
<div class="echo"><kbd>C-x b</kbd> switch chat <kbd>RET</kbd> open <kbd>m</kbd> mark read <kbd>g</kbd> refresh <kbd>/</kbd> filter</div>
</div>
</section>
<!-- ============ SCREEN 2: conversation buffer ============ -->
<section class="screen">
<div class="caption"><h2>Conversation</h2><span>*signal:Sarah* — compose inline at the prompt, <kbd>RET</kbd> sends, <kbd>M-RET</kbd> newline</span></div>
<div class="frame">
<div class="buffer"><div class="ln"><span class="sep">───────────────────────────── Tue, Jun 9 ─────────────────────────────</span></div>
<div class="ln"><span class="faint">[08:58]</span> <span class="name">Sarah</span><span class="dim">&gt;</span> are you taking the girls to the pool after school?</div><div class="ln"><span class="faint">[09:02]</span> <span class="me">me</span><span class="dim">&gt;</span> yeah, leaving around 4. want me to grab dinner on the way back? <span class="green">✓✓</span></div><div class="ln"><span class="faint">[09:03]</span> <span class="name">Sarah</span><span class="dim">&gt;</span> yes please. thai?</div><div class="ln"><span class="faint">[09:10]</span> <span class="me">me</span><span class="dim">&gt;</span> done. ordering the usual <span class="green">✓✓</span></div><div class="ln"><span class="faint">[09:12]</span> <span class="name">Sarah</span><span class="dim">&gt;</span> <span class="blue">[photo: IMG_2041.jpg — RET to view]</span></div><div class="ln"> </div><div class="ln"><span class="sep">───────────────────────────────────────────────────────────────────────</span></div><div class="ln"><span class="blue">&gt;</span> looks great. see you toni<span class="cursor"></span></div></div>
<div class="modeline"> <span class="e2e">⌁ E2E</span> <b>*signal:Sarah*</b> Sarah is typing… <span class="mode">(Signal Chat Fill)</span> ─ U:%%- ─ Bot ───</div>
<div class="echo"><kbd>RET</kbd> send <kbd>C-c C-a</kbd> attach <kbd>C-c C-r</kbd> reply-to <kbd>C-c C-e</kbd> emoji react <kbd>M-p</kbd> edit last</div>
</div>
</section>
<!-- ============ SCREEN 3: minibuffer switcher ============ -->
<section class="screen">
<div class="caption"><h2>Minibuffer switcher</h2><span>the core interaction — <kbd>C-x b</kbd> from anywhere, fuzzy narrowing, <kbd>C-n</kbd>/<kbd>C-p</kbd>, <kbd>RET</kbd></span></div>
<div class="frame">
<div class="dimmed">
<div class="buffer" style="min-height:200px"><div class="ln"><span class="faint">[09:10]</span> <span class="me">me</span><span class="dim">&gt;</span> done. ordering the usual <span class="green">✓✓</span></div><div class="ln"><span class="faint">[09:12]</span> <span class="name">Sarah</span><span class="dim">&gt;</span> <span class="blue">[photo: IMG_2041.jpg — RET to view]</span></div><div class="ln"> </div><div class="ln"><span class="sep">───────────────────────────────────────────────────────────────────────</span></div><div class="ln"><span class="blue">&gt;</span> </div></div>
<div class="modeline"> <span class="e2e">⌁ E2E</span> <b>*signal:Sarah*</b> <span class="mode">(Signal Chat Fill)</span> ─ U:%%- ─ Bot ───</div>
</div>
<div class="mini"><div class="cand sel"><span class="name"><span class="m">s</span><span class="m">a</span><span class="m">r</span>ah</span> <span class="ann">direct · 1 unread · 09:12</span></div><div class="cand">school parent<span class="m">s</span> <span class="m">a</span>nd ca<span class="m">r</span>pool <span class="ann">group · Sun</span></div><div class="cand"><span class="m">S</span>amir D<span class="m">a</span><span class="m">r</span>wish <span class="ann">direct · May 30</span></div><div class="prompt"><span class="p">Switch to chat</span> <span class="count">(3/47)</span><span class="p">:</span> sar<span class="cursor"></span></div></div>
</div>
</section>
<!-- ============ SCREEN 4: which-key ============ -->
<section class="screen">
<div class="caption"><h2>Discoverability</h2><span>which-key panel after <kbd>C-c s</kbd> — the keymap is the menu</span></div>
<div class="frame">
<div class="dimmed">
<div class="buffer" style="min-height:170px"><div class="ln"><span class="faint">[09:03]</span> <span class="name">Sarah</span><span class="dim">&gt;</span> yes please. thai?</div><div class="ln"><span class="faint">[09:10]</span> <span class="me">me</span><span class="dim">&gt;</span> done. ordering the usual <span class="green">✓✓</span></div><div class="ln"> </div><div class="ln"><span class="sep">───────────────────────────────────────────────────────────────────────</span></div><div class="ln"><span class="blue">&gt;</span> </div></div>
<div class="modeline"> <span class="e2e">⌁ E2E</span> <b>*signal:Sarah*</b> <span class="mode">(Signal Chat Fill)</span> ─ U:%%- ─ Bot ───</div>
</div>
<div class="whichkey"><div class="wk"><kbd>C-c s</kbd></div><div class="wk"> </div><div class="wk"><kbd>a</kbd> <span class="arr"></span> attach file <kbd>m</kbd> <span class="arr"></span> mute chat <kbd>v</kbd> <span class="arr"></span> verify safety number</div><div class="wk"><kbd>d</kbd> <span class="arr"></span> disappearing msgs <kbd>n</kbd> <span class="arr"></span> new chat <kbd>x</kbd> <span class="arr"></span> delete message</div><div class="wk"><kbd>g</kbd> <span class="arr"></span> new group <kbd>p</kbd> <span class="arr"></span> pin chat <kbd>/</kbd> <span class="arr"></span> search in chat</div><div class="wk"><kbd>i</kbd> <span class="arr"></span> chat info <kbd>r</kbd> <span class="arr"></span> mark all read <kbd>?</kbd> <span class="arr"></span> describe bindings</div></div>
</div>
</section>
</div>
</body>
</html>