Remove design screenshots from annotation PR
No files matched your search
@@ -1,461 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>PAP-9432 — Document Annotations UX</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf8;
|
||||
--panel: #ffffff;
|
||||
--ink: #111111;
|
||||
--muted: #666666;
|
||||
--line: #e5e5e0;
|
||||
--accent: #d33;
|
||||
--maxw: 1200px;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
font: 15px/1.55 -apple-system, system-ui, "Segoe UI", sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--ink);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
a { color: inherit; }
|
||||
|
||||
.shell { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }
|
||||
|
||||
.toc {
|
||||
position: sticky; top: 0; align-self: start;
|
||||
height: 100vh; overflow: auto;
|
||||
padding: 24px 16px 24px 24px;
|
||||
border-right: 1px solid var(--line);
|
||||
background: var(--panel);
|
||||
font-size: 13px;
|
||||
z-index: 20;
|
||||
}
|
||||
.toc h1 { font-size: 14px; margin: 0 0 4px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
|
||||
.toc h2 { font-size: 12px; margin: 24px 0 6px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
|
||||
.toc a { display: block; text-decoration: none; padding: 6px 8px; margin-left: -8px; border-radius: 4px; color: var(--ink); }
|
||||
.toc a:hover { background: var(--bg); }
|
||||
.toc .num { display: inline-block; width: 22px; color: var(--muted); }
|
||||
.toc .toc-summary { display: none; }
|
||||
.toc .toc-body { display: block; }
|
||||
|
||||
main { padding: 48px 56px 96px; max-width: 1300px; min-width: 0; }
|
||||
|
||||
header.hero { max-width: var(--maxw); margin-bottom: 64px; }
|
||||
header.hero .crumb { color: var(--muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; }
|
||||
header.hero h1 { font-size: 36px; line-height: 1.15; margin: 8px 0 16px; }
|
||||
header.hero p { color: var(--muted); max-width: 720px; font-size: 16px; }
|
||||
header.hero .pills { margin-top: 20px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
header.hero .pill { font-size: 12px; padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); color: var(--muted); }
|
||||
|
||||
section { scroll-margin-top: 24px; max-width: var(--maxw); margin-bottom: 96px; }
|
||||
section .lede { color: var(--muted); margin: 0 0 12px; font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; font-weight: 700; }
|
||||
section h2 { font-size: 28px; line-height: 1.2; margin: 0 0 8px; }
|
||||
section h2 .step-num { display: inline-block; width: 40px; color: var(--muted); }
|
||||
section h3 { font-size: 16px; margin: 24px 0 8px; }
|
||||
section .desc { color: var(--muted); margin: 0 0 24px; max-width: 760px; }
|
||||
|
||||
.grid {
|
||||
display: grid; gap: 24px;
|
||||
grid-template-columns: minmax(0, 1.4fr) 220px minmax(0, 0.9fr);
|
||||
align-items: start;
|
||||
}
|
||||
@media (max-width: 1180px) {
|
||||
.grid { grid-template-columns: minmax(0, 1fr) 200px; }
|
||||
.grid > .notes-col { grid-column: 1 / -1; }
|
||||
}
|
||||
@media (max-width: 980px) { .grid { grid-template-columns: 1fr; } .grid > .mobile-col { max-width: 280px; } }
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.shell { grid-template-columns: 1fr; }
|
||||
.toc {
|
||||
position: sticky; top: 0;
|
||||
height: auto; max-height: 60vh;
|
||||
padding: 12px 16px;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.toc .toc-summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.toc .toc-summary::-webkit-details-marker { display: none; }
|
||||
.toc .toc-summary .title { font-size: 13px; font-weight: 600; }
|
||||
.toc .toc-summary .crumb { font-size: 11px; color: var(--muted); letter-spacing: 0.04em; text-transform: uppercase; }
|
||||
.toc .toc-summary .chevron {
|
||||
width: 10px; height: 10px;
|
||||
border-right: 1.5px solid var(--ink);
|
||||
border-bottom: 1.5px solid var(--ink);
|
||||
transform: rotate(45deg);
|
||||
transition: transform 120ms ease;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.toc[open] .toc-summary .chevron { transform: rotate(225deg) translate(-2px, -2px); }
|
||||
.toc .toc-body { display: none; padding-top: 8px; border-top: 1px solid var(--line); margin-top: 8px; }
|
||||
.toc[open] .toc-body { display: block; }
|
||||
main { padding: 24px 20px 64px; }
|
||||
header.hero { margin-bottom: 40px; }
|
||||
header.hero h1 { font-size: 28px; }
|
||||
header.hero p { font-size: 15px; }
|
||||
section { margin-bottom: 64px; scroll-margin-top: 80px; }
|
||||
section h2 { font-size: 24px; }
|
||||
section h2 .step-num { width: 32px; }
|
||||
.flow-section { padding: 20px; margin-bottom: 40px; scroll-margin-top: 80px; }
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
main { padding: 16px 14px 56px; }
|
||||
header.hero { margin-bottom: 32px; }
|
||||
header.hero h1 { font-size: 24px; line-height: 1.2; }
|
||||
header.hero p { font-size: 14px; }
|
||||
section { margin-bottom: 48px; }
|
||||
section h2 { font-size: 20px; line-height: 1.25; }
|
||||
section h2 .step-num { width: 28px; }
|
||||
section h3 { font-size: 15px; margin: 20px 0 6px; }
|
||||
section .desc { font-size: 14px; }
|
||||
.grid { gap: 16px; }
|
||||
.flow-section { padding: 16px; border-radius: 8px; }
|
||||
.wire .label { padding: 8px 10px; font-size: 11px; gap: 8px; }
|
||||
body { font-size: 14px; }
|
||||
}
|
||||
|
||||
.wire {
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: zoom-in;
|
||||
transition: transform 80ms ease, box-shadow 80ms ease;
|
||||
}
|
||||
.wire:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||
.wire .label {
|
||||
padding: 10px 14px;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
border-bottom: 1px solid var(--line);
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
}
|
||||
.wire img { display: block; width: 100%; height: auto; background: #fff; }
|
||||
.wire.mobile-wire img { max-width: 220px; margin: 0 auto; }
|
||||
|
||||
.notes ul { padding-left: 20px; margin: 8px 0; }
|
||||
.notes li { margin-bottom: 6px; }
|
||||
.notes .why {
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--line);
|
||||
border-left: 3px solid var(--ink);
|
||||
padding: 14px 18px;
|
||||
border-radius: 4px;
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.flow-section { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 32px; margin-bottom: 64px; max-width: var(--maxw); }
|
||||
.flow-section h2 { margin-top: 0; }
|
||||
.flow-section .wire { margin-top: 16px; }
|
||||
|
||||
.lightbox {
|
||||
position: fixed; inset: 0;
|
||||
background: rgba(0,0,0,0.86);
|
||||
display: none;
|
||||
align-items: center; justify-content: center;
|
||||
z-index: 100;
|
||||
cursor: zoom-out;
|
||||
padding: 32px;
|
||||
}
|
||||
.lightbox.open { display: flex; }
|
||||
.lightbox img { max-width: 100%; max-height: 100%; background: #fff; box-shadow: 0 30px 80px rgba(0,0,0,0.4); border-radius: 4px; }
|
||||
.lightbox .close { position: absolute; top: 16px; right: 24px; font-size: 28px; color: #fff; cursor: pointer; }
|
||||
.lightbox .caption { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); color: #fff; font-size: 13px; opacity: 0.9; }
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.lightbox { padding: 12px; overflow: auto; touch-action: pinch-zoom; }
|
||||
.lightbox.open { display: block; }
|
||||
.lightbox img { display: block; width: 100%; max-width: none; max-height: none; height: auto; margin: 40px auto 56px; box-shadow: none; }
|
||||
.lightbox .close { position: fixed; top: 8px; right: 12px; font-size: 32px; }
|
||||
.lightbox .caption { position: fixed; left: 50%; transform: translateX(-50%); font-size: 12px; bottom: 12px; text-align: center; background: rgba(0,0,0,0.7); border-radius: 4px; padding: 6px 12px; }
|
||||
}
|
||||
|
||||
.footer { color: var(--muted); font-size: 12px; max-width: var(--maxw); border-top: 1px solid var(--line); padding-top: 24px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="shell">
|
||||
<details class="toc">
|
||||
<summary class="toc-summary">
|
||||
<span>
|
||||
<span class="crumb">PAP-9432 · Doc Annotations</span><br>
|
||||
<span class="title">Jump to a screen</span>
|
||||
</span>
|
||||
<span class="chevron" aria-hidden="true"></span>
|
||||
</summary>
|
||||
<nav class="toc-body" aria-label="Section navigation">
|
||||
<h1>PAP-9432</h1>
|
||||
<div style="font-size: 13px; color: var(--muted); margin-bottom: 16px;">Phase 1 UX spec</div>
|
||||
|
||||
<h2>Flow</h2>
|
||||
<a href="#flow"><span class="num">⤳</span>Annotation lifecycle</a>
|
||||
|
||||
<h2>Screens</h2>
|
||||
<a href="#s1"><span class="num">1</span>Rendered mode — selection</a>
|
||||
<a href="#s2"><span class="num">2</span>Side panel / bottom sheet</a>
|
||||
<a href="#s3"><span class="num">3</span>Edit mode</a>
|
||||
<a href="#s4"><span class="num">4</span>State matrix</a>
|
||||
<a href="#s5"><span class="num">5</span>Deep link</a>
|
||||
|
||||
<h2>Notes</h2>
|
||||
<a href="#a11y"><span class="num">a</span>Accessibility</a>
|
||||
<a href="#open"><span class="num">?</span>Open questions</a>
|
||||
</nav>
|
||||
</details>
|
||||
|
||||
<main>
|
||||
<header class="hero">
|
||||
<div class="crumb">PAP-9432 · Phase 1 UX spec</div>
|
||||
<h1>Document annotations — UX spec</h1>
|
||||
<p>Document-native highlights and comment threads on Paperclip issue documents (primary target: the <code>plan</code> document). Paired desktop/mobile wireframes for rendered mode, edit mode, side panel, state matrix, and deep-link behaviour. Pair this with the <code>spec</code> document on PAP-9432.</p>
|
||||
<div class="pills">
|
||||
<span class="pill">6 screens</span>
|
||||
<span class="pill">Desktop + mobile</span>
|
||||
<span class="pill">Lo-fi · monochrome</span>
|
||||
<span class="pill">Click any wireframe to zoom</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section id="flow" class="flow-section">
|
||||
<div class="lede">Flow</div>
|
||||
<h2>Annotation lifecycle across revisions</h2>
|
||||
<p class="desc">Single thread followed through select → compose → resolve → revision → re-anchor outcomes. Dashed arrows are side effects (e.g. assignee wake).</p>
|
||||
<div class="wire" data-zoom data-caption="Annotation lifecycle">
|
||||
<div class="label"><span>flow.svg</span><span>1280×720</span></div>
|
||||
<img src="wireframes/flow.svg" alt="Annotation lifecycle flow" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="s1">
|
||||
<div class="lede">Step 1 · Capture</div>
|
||||
<h2><span class="step-num">1.</span>Rendered mode — selection</h2>
|
||||
<p class="desc">User selects body text; floating toolbar offers Comment + Copy link. <code>⌘⇧M</code> is the keyboard equivalent.</p>
|
||||
<div class="grid">
|
||||
<div class="wire" data-zoom data-caption="Rendered selection (desktop)">
|
||||
<div class="label"><span>rendered-selection.svg</span><span>1280×800 · desktop</span></div>
|
||||
<img src="wireframes/rendered-selection.svg" alt="Rendered-mode selection — desktop" />
|
||||
</div>
|
||||
<div class="wire mobile-wire mobile-col" data-zoom data-caption="Rendered selection (mobile)">
|
||||
<div class="label"><span>mobile</span><span>375×812</span></div>
|
||||
<img src="wireframes/rendered-selection-mobile.svg" alt="Rendered-mode selection — mobile" />
|
||||
</div>
|
||||
<div class="notes-col">
|
||||
<div class="notes">
|
||||
<h3>Annotations</h3>
|
||||
<ul>
|
||||
<li><b>1</b> — floating selection toolbar anchored above the range (flips below if <48px from card top).</li>
|
||||
<li><b>2</b> — active highlight: solid mid-grey underline.</li>
|
||||
<li><b>3</b> — resolved highlight: dashed underline, only visible when "Show resolved" is on.</li>
|
||||
<li><b>4</b> — unresolved-count chip lives between rev menu and right-actions.</li>
|
||||
<li><b>5</b> — <code>⌘⇧M</code> opens the comment composer for the current selection.</li>
|
||||
<li><i>Mobile</i> — selection sheet → <code>+ Comment</code> opens the bottom sheet directly; native platform sheet is preferred when extensible.</li>
|
||||
</ul>
|
||||
<div class="why"><b>Why this changes:</b> document-native capture matches Google Docs / Notion mental models; agents and reviewers already think in "select text → comment" rather than "open a chat".</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="s2">
|
||||
<div class="lede">Step 2 · Read & reply</div>
|
||||
<h2><span class="step-num">2.</span>Side panel · bottom sheet</h2>
|
||||
<p class="desc">Annotation panel is bound to one document. Desktop = right slide-in (380px), mobile = bottom sheet with peek/half/full snap points.</p>
|
||||
<div class="grid">
|
||||
<div class="wire" data-zoom data-caption="Side panel (desktop)">
|
||||
<div class="label"><span>side-panel.svg</span><span>1280×800 · desktop</span></div>
|
||||
<img src="wireframes/side-panel.svg" alt="Side panel — desktop" />
|
||||
</div>
|
||||
<div class="wire mobile-wire mobile-col" data-zoom data-caption="Bottom sheet (mobile)">
|
||||
<div class="label"><span>mobile</span><span>375×812</span></div>
|
||||
<img src="wireframes/side-panel-mobile.svg" alt="Bottom sheet — mobile" />
|
||||
</div>
|
||||
<div class="notes-col">
|
||||
<div class="notes">
|
||||
<h3>Annotations</h3>
|
||||
<ul>
|
||||
<li><b>1</b> — filter chips (Open / Resolved / Stale / Orphan); active chip is filled.</li>
|
||||
<li><b>2</b> — focused thread auto-expands with composer; others collapse to 2-line summary.</li>
|
||||
<li><b>3</b> — focused anchor in body gets a 2px border + soft fill; bi-directional click linkage.</li>
|
||||
<li><i>Mobile</i> — single thread at a time; prev/next steps through current filter. Composer collapses to a pill at rest.</li>
|
||||
</ul>
|
||||
<div class="why"><b>Why this changes:</b> right-rail Properties is rarely read while reviewing comments — collapsing it for the panel buys 380px without a new layout. On mobile, single-thread focus + prev/next avoids horizontal cramming that kills usability in narrow viewports.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="s3">
|
||||
<div class="lede">Step 3 · Edit mode</div>
|
||||
<h2><span class="step-num">3.</span>Edit-mode capture + dirty-draft guardrails</h2>
|
||||
<p class="desc">MDXEditor/Lexical hosts selection capture via a plugin; existing thread anchors render as read-only decorations. Dirty/conflicted drafts disable new-anchor creation with explicit reason text.</p>
|
||||
<div class="grid">
|
||||
<div class="wire" data-zoom data-caption="Edit mode (desktop)">
|
||||
<div class="label"><span>edit-mode.svg</span><span>1280×800 · desktop</span></div>
|
||||
<img src="wireframes/edit-mode.svg" alt="Edit mode — desktop" />
|
||||
</div>
|
||||
<div class="wire mobile-wire mobile-col" data-zoom data-caption="Edit mode (mobile)">
|
||||
<div class="label"><span>mobile</span><span>375×812</span></div>
|
||||
<img src="wireframes/edit-mode-mobile.svg" alt="Edit mode — mobile" />
|
||||
</div>
|
||||
<div class="notes-col">
|
||||
<div class="notes">
|
||||
<h3>Annotations</h3>
|
||||
<ul>
|
||||
<li><b>1</b> — toolbar primary action uses current Lexical <code>RangeSelection</code>; same <code>⌘⇧M</code> shortcut.</li>
|
||||
<li><b>2</b> — dirty-draft banner names the reason; resolves the second autosave commits.</li>
|
||||
<li><b>3</b> — side-panel footer CTA mirrors the disabled state; existing threads remain readable.</li>
|
||||
<li><i>Mobile</i> — keyboard accessory bar shows the disabled state inline so it isn't a surprise.</li>
|
||||
</ul>
|
||||
<div class="why"><b>Why this changes:</b> anchors are tied to a saved revision baseline. Allowing creation against a dirty draft either fabricates revisions or risks anchors into never-saved text. The explicit disabled-with-reason pattern is preferable to silent allow-then-fail.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="s4">
|
||||
<div class="lede">Step 4 · State matrix</div>
|
||||
<h2><span class="step-num">4.</span>Open · Resolved · Stale · Orphaned</h2>
|
||||
<p class="desc">Identical data layout, distinct chrome. Resolved hidden by default; stale highlights remain but flagged; orphaned have no in-body anchor.</p>
|
||||
<div class="grid">
|
||||
<div class="wire" data-zoom data-caption="State matrix (desktop)">
|
||||
<div class="label"><span>states.svg</span><span>1280×800 · desktop</span></div>
|
||||
<img src="wireframes/states.svg" alt="Annotation states — desktop" />
|
||||
</div>
|
||||
<div class="wire mobile-wire mobile-col" data-zoom data-caption="State matrix (mobile)">
|
||||
<div class="label"><span>mobile</span><span>375×812</span></div>
|
||||
<img src="wireframes/states-mobile.svg" alt="Annotation states — mobile" />
|
||||
</div>
|
||||
<div class="notes-col">
|
||||
<div class="notes">
|
||||
<h3>Annotations</h3>
|
||||
<ul>
|
||||
<li><b>Open</b> — solid grey underline, primary "Open" pill, Reply / Resolve / Copy link.</li>
|
||||
<li><b>Resolved</b> — dashed outline + dimmed card, hidden by default; Reopen + Copy link.</li>
|
||||
<li><b>Stale</b> — dashed outline + <code>⚠</code>; Re-anchor (inline re-select), Show diff, Resolve.</li>
|
||||
<li><b>Orphaned</b> — no in-body anchor; panel-only with "View rev N" link to the last valid revision.</li>
|
||||
</ul>
|
||||
<div class="why"><b>Why this changes:</b> distinguishing fuzzy vs. lost anchors avoids the binary "vanished" failure mode. Reviewers keep their thoughts even when prose changes, and stale state surfaces a path back to a clean anchor.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="s5">
|
||||
<div class="lede">Step 5 · Deep linking</div>
|
||||
<h2><span class="step-num">5.</span>Folded → unfolded with focused thread + comment</h2>
|
||||
<p class="desc">URL adds <code>&thread=…&comment=…</code> to the existing <code>#document-<i>key</i></code> anchor. Resolving forces unfold, scroll, pulse, panel auto-open, thread expand, comment focus.</p>
|
||||
<div class="grid">
|
||||
<div class="wire" data-zoom data-caption="Deep link (desktop)">
|
||||
<div class="label"><span>deep-link.svg</span><span>1280×800 · desktop</span></div>
|
||||
<img src="wireframes/deep-link.svg" alt="Deep link — desktop" />
|
||||
</div>
|
||||
<div class="wire mobile-wire mobile-col" data-zoom data-caption="Deep link (mobile)">
|
||||
<div class="label"><span>mobile</span><span>375×812</span></div>
|
||||
<img src="wireframes/deep-link-mobile.svg" alt="Deep link — mobile" />
|
||||
</div>
|
||||
<div class="notes-col">
|
||||
<div class="notes">
|
||||
<h3>Annotations</h3>
|
||||
<ul>
|
||||
<li><b>1</b> — folded card auto-unfolds; count chip remains the only chrome on the folded header.</li>
|
||||
<li><b>2</b> — URL grammar — three precision levels, each optional.</li>
|
||||
<li><b>3</b> — body pulse ring (1.4s) on anchor; then steady focused border.</li>
|
||||
<li><b>4</b> — panel auto-opens, expands target thread, comment-level focus ring.</li>
|
||||
</ul>
|
||||
<div class="why"><b>Why this changes:</b> agents quote-link inside comments today; without unambiguous deep-link resolution, a clicked link drops the reader into a generic doc view and forces them to scroll-hunt. Three precision levels (doc / thread / comment) means we don't have to invent a new scheme for each entry point.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="a11y">
|
||||
<div class="lede">Accessibility</div>
|
||||
<h2>Keyboard, focus, motion, ARIA</h2>
|
||||
<div class="notes">
|
||||
<ul>
|
||||
<li><b>Shortcut</b> — <code>⌘⇧M</code> / <code>Ctrl⇧M</code> opens Comment for the current selection in both rendered and edit modes.</li>
|
||||
<li><b>Tab order</b> — header filters → thread cards (<code>tabindex=0</code>) → expanded thread composer.</li>
|
||||
<li><b>Focus on open</b> — composer textarea (compose) or first comment row (deep link).</li>
|
||||
<li><b>Focus on close</b> — returns to the originating highlight or the count chip.</li>
|
||||
<li><b>Escape semantics</b> — composer dirty → confirm-discard; otherwise collapse thread → close panel. Bottom sheet snaps down one step per <code>Esc</code> / scrim tap.</li>
|
||||
<li><b>Visible focus</b> — <code>focus-visible:ring-2 ring-ring ring-offset-2</code>; 2px outline on highlight runs (never colour alone).</li>
|
||||
<li><b>ARIA</b> — panel <code>role="complementary"</code>, thread <code>role="article"</code> + <code>aria-labelledby</code> on quote, hidden state text on highlights and thread headers.</li>
|
||||
<li><b>Reduced motion</b> — pulse, slide, snap fall back to instant under <code>prefers-reduced-motion: reduce</code>; focus rings stay.</li>
|
||||
<li><b>Contrast</b> — quote chip <code>bg-muted/40</code> on <code>bg-card</code> passes AA; <code>Stale</code> never relies on the <code>⚠</code> glyph alone.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="open">
|
||||
<div class="lede">For reviewer</div>
|
||||
<h2>Open questions</h2>
|
||||
<div class="notes">
|
||||
<ul>
|
||||
<li><b>Q1</b> — Selection on touch: inject into native selection sheet where supported (iOS Safari, Chrome Android), fall back to floating FAB anchored to selection rect. <i>Recommend platform-sheet-first with FAB fallback.</i></li>
|
||||
<li><b>Q2</b> — Resolved visibility default: hidden with toggle (recommended) or visible with softer chrome. <i>Hidden by default — matches Google Docs and keeps long plan docs readable.</i></li>
|
||||
<li><b>Q3</b> — Stale Re-anchor: inline re-select (recommended) vs. modal with two body previews. <i>Inline; "Show diff" covers the modal-style comparison need.</i></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="footer">
|
||||
Wireframes follow the in-tree <code>wireframe</code> skill house style — black on white, 1.5pt strokes, 8px grid, type sizes 12/14/20/28. Red dashed annotations are the call-out layer only and not part of the proposed UI.
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div class="lightbox" id="lb" aria-hidden="true">
|
||||
<span class="close" id="lbClose">×</span>
|
||||
<img id="lbImg" alt="" />
|
||||
<div class="caption" id="lbCap"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const lb = document.getElementById('lb');
|
||||
const lbImg = document.getElementById('lbImg');
|
||||
const lbCap = document.getElementById('lbCap');
|
||||
const lbClose = document.getElementById('lbClose');
|
||||
|
||||
document.querySelectorAll('[data-zoom]').forEach((el) => {
|
||||
el.addEventListener('click', () => {
|
||||
const target = el.tagName === 'IMG' ? el : el.querySelector('img');
|
||||
if (!target) return;
|
||||
lbImg.src = target.src;
|
||||
lbImg.alt = target.alt;
|
||||
lbCap.textContent = el.dataset.caption || target.alt || '';
|
||||
lb.classList.add('open');
|
||||
});
|
||||
});
|
||||
|
||||
function close() { lb.classList.remove('open'); }
|
||||
lb.addEventListener('click', close);
|
||||
lbClose.addEventListener('click', close);
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') close(); });
|
||||
|
||||
const toc = document.querySelector('details.toc');
|
||||
if (toc) {
|
||||
const mq = window.matchMedia('(max-width: 900px)');
|
||||
const apply = () => { toc.open = !mq.matches; };
|
||||
apply();
|
||||
mq.addEventListener('change', apply);
|
||||
toc.querySelectorAll('.toc-body a').forEach((a) => {
|
||||
a.addEventListener('click', () => { if (mq.matches) toc.open = false; });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,81 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="812" viewBox="0 0 375 812"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="375" height="812" />
|
||||
|
||||
<line x1="0" y1="44" x2="375" y2="44" />
|
||||
<line x1="0" y1="778" x2="375" y2="778" />
|
||||
|
||||
<!-- top bar -->
|
||||
<g transform="translate(0,44)">
|
||||
<rect x="0" y="0" width="375" height="48" />
|
||||
<text x="16" y="30" font-size="14" stroke="none" fill="#000">← Issue</text>
|
||||
<text x="187" y="30" text-anchor="middle" font-size="14" font-weight="600" stroke="none" fill="#000">PLAN — rev 4</text>
|
||||
<text x="359" y="30" text-anchor="end" font-size="14" stroke="none" fill="#000">⋯</text>
|
||||
</g>
|
||||
|
||||
<!-- URL hint -->
|
||||
<g transform="translate(16,108)">
|
||||
<rect x="0" y="0" width="343" height="24" rx="12" fill="#fafafa" />
|
||||
<text x="12" y="16" font-size="12" stroke="none" fill="#666">…#document-plan&thread=docann_xyz</text>
|
||||
</g>
|
||||
|
||||
<!-- document body, scrolled to anchor -->
|
||||
<g transform="translate(16,148)">
|
||||
<rect x="0" y="0" width="343" height="320" rx="8" />
|
||||
<g transform="translate(12,12)">
|
||||
<rect x="0" y="0" width="200" height="14" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="28" width="319" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- focused anchor pulse -->
|
||||
<rect x="-4" y="56" width="319" height="36" stroke="#000" stroke-width="2" fill="#fafafa" />
|
||||
<rect x="0" y="64" width="304" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="80" width="240" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="120" width="319" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="136" width="296" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- bottom sheet auto-open with targeted thread -->
|
||||
<g transform="translate(0,488)">
|
||||
<rect x="0" y="0" width="375" height="290" rx="16" />
|
||||
<rect x="163" y="8" width="48" height="4" rx="2" fill="#ccc" stroke="none" />
|
||||
<g transform="translate(16,24)">
|
||||
<text x="0" y="16" font-size="14" font-weight="600" stroke="none" fill="#000">Thread</text>
|
||||
<text x="343" y="16" text-anchor="end" font-size="14" stroke="none" fill="#000">×</text>
|
||||
</g>
|
||||
<g transform="translate(16,52)">
|
||||
<rect x="0" y="0" width="343" height="216" rx="6" stroke="#000" stroke-width="2" />
|
||||
<rect x="12" y="12" width="319" height="24" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="28" font-size="12" stroke="none" fill="#666">“quote …”</text>
|
||||
<g transform="translate(12,48)">
|
||||
<text x="0" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">Dotta · 2m ago</text>
|
||||
<rect x="0" y="20" width="280" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<!-- targeted comment ring -->
|
||||
<g transform="translate(12,96)">
|
||||
<rect x="-4" y="-4" width="327" height="64" stroke="#000" stroke-width="2" fill="#fafafa" />
|
||||
<text x="0" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">UXDesigner · just now</text>
|
||||
<text x="0" y="28" font-size="12" stroke="none" fill="#666">[comment=c_42]</text>
|
||||
<rect x="0" y="36" width="240" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<g transform="translate(12,180)">
|
||||
<rect x="0" y="0" width="32" height="24" rx="4" />
|
||||
<text x="16" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">‹</text>
|
||||
<text x="48" y="16" font-size="12" stroke="none" fill="#666">1 of 2 open</text>
|
||||
<rect x="124" y="0" width="32" height="24" rx="4" />
|
||||
<text x="140" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">›</text>
|
||||
<rect x="251" y="0" width="76" height="24" rx="4" />
|
||||
<text x="289" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="8" y="140" width="359" height="200" />
|
||||
<rect x="0" y="482" width="375" height="296" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="8" y="134">1 deep link unfolds doc, scrolls anchor into upper half of viewport above the sheet</text>
|
||||
<text x="0" y="476">2 bottom sheet opens automatically; comment-id focus ring on target comment</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.3 KiB |
@@ -1,102 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800" viewBox="0 0 1280 800"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="800" />
|
||||
|
||||
<g transform="translate(0,0)"><rect x="0" y="0" width="1280" height="56" /></g>
|
||||
|
||||
<!-- URL bar mockup -->
|
||||
<g transform="translate(48,16)">
|
||||
<rect x="0" y="0" width="864" height="24" rx="12" fill="#fafafa" />
|
||||
<text x="12" y="16" font-size="12" stroke="none" fill="#666">/PAP/issues/PAP-9436#document-plan&thread=docann_xyz&comment=c_42</text>
|
||||
</g>
|
||||
|
||||
<!-- before: folded document card -->
|
||||
<g transform="translate(48,80)">
|
||||
<text x="0" y="14" font-size="12" font-weight="600" stroke="none" fill="#000">Before deep link</text>
|
||||
<g transform="translate(0,24)">
|
||||
<rect x="0" y="0" width="568" height="56" rx="8" />
|
||||
<text x="16" y="36" font-size="12" stroke="none" fill="#666">▸ PLAN rev 4 updated 12m ago 3 comments</text>
|
||||
<text x="552" y="36" text-anchor="end" font-size="12" stroke="none" fill="#666">⋯</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- after: auto-opened, scrolled, focused -->
|
||||
<g transform="translate(48,180)" data-region="after">
|
||||
<text x="0" y="14" font-size="12" font-weight="600" stroke="none" fill="#000">After deep link — folded card auto-opens, scrolls to anchor, opens panel to thread</text>
|
||||
<g transform="translate(0,24)">
|
||||
<rect x="0" y="0" width="744" height="540" rx="8" stroke="#000" stroke-width="2" />
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="14" font-size="12" stroke="none" fill="#666">▾</text>
|
||||
<rect x="16" y="0" width="48" height="20" rx="10" />
|
||||
<text x="40" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">PLAN</text>
|
||||
<text x="76" y="14" font-size="12" stroke="none" fill="#666">rev 4 ▾</text>
|
||||
<rect x="200" y="0" width="96" height="20" rx="10" fill="#e6e6e6" />
|
||||
<circle cx="214" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="224" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
</g>
|
||||
|
||||
<g transform="translate(24,64)">
|
||||
<rect x="0" y="0" width="280" height="20" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="40" width="680" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="56" width="640" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- focused anchor — pulse ring -->
|
||||
<rect x="-8" y="92" width="700" height="40" stroke="#000" stroke-width="2" fill="#fafafa" />
|
||||
<rect x="0" y="104" width="660" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="120" width="380" height="10" fill="#000" stroke="none" />
|
||||
<!-- following body -->
|
||||
<rect x="0" y="160" width="660" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="176" width="620" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="208" width="540" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- side panel, scrolled to targeted comment -->
|
||||
<g transform="translate(760,24)">
|
||||
<rect x="0" y="0" width="424" height="540" rx="8" />
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="16" font-size="14" font-weight="600" stroke="none" fill="#000">Comments</text>
|
||||
<text x="0" y="36" font-size="12" stroke="none" fill="#666">PLAN · rev 4</text>
|
||||
</g>
|
||||
<line x1="0" y1="56" x2="424" y2="56" />
|
||||
<g transform="translate(16,72)">
|
||||
<rect x="0" y="0" width="392" height="232" rx="6" stroke="#000" stroke-width="2" />
|
||||
<rect x="12" y="12" width="368" height="28" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“selected quote …”</text>
|
||||
<g transform="translate(12,52)">
|
||||
<circle cx="12" cy="12" r="10" fill="#e6e6e6" stroke="none" />
|
||||
<text x="32" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">Dotta · 2m ago</text>
|
||||
<rect x="32" y="32" width="320" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<!-- targeted comment ring -->
|
||||
<g transform="translate(12,124)">
|
||||
<rect x="-4" y="-4" width="376" height="84" stroke="#000" stroke-width="2" fill="#fafafa" />
|
||||
<circle cx="12" cy="12" r="10" fill="#e6e6e6" stroke="none" />
|
||||
<text x="32" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">UXDesigner · just now</text>
|
||||
<text x="32" y="28" font-size="12" stroke="none" fill="#666">[comment=c_42]</text>
|
||||
<rect x="32" y="40" width="280" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="32" y="56" width="220" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(16,316)">
|
||||
<rect x="0" y="0" width="392" height="48" rx="6" />
|
||||
<text x="12" y="20" font-size="12" stroke="none" fill="#666">Reply…</text>
|
||||
<rect x="320" y="12" width="56" height="24" rx="4" fill="#000" />
|
||||
<text x="348" y="28" text-anchor="middle" font-size="12" stroke="none" fill="#fff">Reply</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="40" y="76" width="592" height="80" />
|
||||
<rect x="40" y="170" width="744" height="40" />
|
||||
<rect x="40" y="312" width="744" height="48" />
|
||||
<rect x="752" y="304" width="440" height="68" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="40" y="72">1 folded state — fold curtain still hides body. Deep link forces unfold + scroll + focus.</text>
|
||||
<text x="40" y="164">2 URL grammar — `#document-{key}&thread={id}&comment={id}`; key alone scrolls to doc only</text>
|
||||
<text x="40" y="308">3 body pulse — 1.4s ring on anchor, then steady focused border</text>
|
||||
<text x="752" y="300">4 panel auto-opens on the right, expands target thread, scrolls to target comment, focus ring on comment</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1,73 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="812" viewBox="0 0 375 812"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="375" height="812" />
|
||||
|
||||
<line x1="0" y1="44" x2="375" y2="44" />
|
||||
<line x1="0" y1="778" x2="375" y2="778" />
|
||||
|
||||
<!-- top bar (edit context) -->
|
||||
<g transform="translate(0,44)">
|
||||
<rect x="0" y="0" width="375" height="48" />
|
||||
<text x="16" y="30" font-size="14" stroke="none" fill="#000">← Cancel</text>
|
||||
<text x="187" y="30" text-anchor="middle" font-size="14" font-weight="600" stroke="none" fill="#000">Edit plan</text>
|
||||
<text x="359" y="30" text-anchor="end" font-size="14" stroke="none" fill="#000">Done</text>
|
||||
</g>
|
||||
|
||||
<!-- saving banner -->
|
||||
<g transform="translate(0,92)">
|
||||
<rect x="0" y="0" width="375" height="32" fill="#fafafa" />
|
||||
<text x="16" y="20" font-size="12" stroke="none" fill="#666">⟳ Saving draft… new comments disabled until saved</text>
|
||||
</g>
|
||||
|
||||
<!-- editor toolbar (sticky) -->
|
||||
<g transform="translate(0,124)" data-region="toolbar">
|
||||
<rect x="0" y="0" width="375" height="48" />
|
||||
<g font-size="14" stroke="none" fill="#000">
|
||||
<text x="16" y="30">B</text>
|
||||
<text x="40" y="30" font-style="italic">I</text>
|
||||
<text x="72" y="30">H</text>
|
||||
<text x="104" y="30">•</text>
|
||||
<text x="136" y="30">⌧</text>
|
||||
<line x1="168" y1="12" x2="168" y2="36" stroke="#ccc" />
|
||||
<rect x="184" y="10" width="176" height="28" rx="14" fill="#fafafa" stroke="#ccc" />
|
||||
<text x="272" y="28" text-anchor="middle" font-size="12" fill="#999">+ Comment (save first)</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- editor body -->
|
||||
<g transform="translate(16,196)" data-region="editor-body">
|
||||
<rect x="0" y="0" width="200" height="16" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="32" width="312" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="48" width="288" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- selection -->
|
||||
<rect x="-2" y="76" width="312" height="14" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="80" width="308" height="10" fill="#000" stroke="none" />
|
||||
<rect x="-2" y="92" width="200" height="14" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="96" width="196" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="128" width="288" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- existing thread underline (read-only) -->
|
||||
<rect x="0" y="160" width="240" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<line x1="0" y1="174" x2="240" y2="174" stroke-dasharray="3 3" />
|
||||
<rect x="0" y="192" width="248" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
|
||||
<!-- in-keyboard accessory bar (showing comment shortcut grayed) -->
|
||||
<g transform="translate(0,640)">
|
||||
<line x1="0" y1="0" x2="375" y2="0" />
|
||||
<rect x="0" y="0" width="375" height="48" fill="#fafafa" />
|
||||
<text x="16" y="30" font-size="12" stroke="none" fill="#666">Comment disabled — autosave in progress</text>
|
||||
<text x="359" y="30" text-anchor="end" font-size="12" stroke="none" fill="#666">Hide</text>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="0" y="88" width="375" height="40" />
|
||||
<rect x="176" y="128" width="192" height="40" />
|
||||
<rect x="0" y="632" width="375" height="56" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="0" y="82">1 dirty-state ribbon — explains why new anchors are disabled</text>
|
||||
<text x="176" y="124">2 toolbar action disabled with reason hover (sheet on tap)</text>
|
||||
<text x="0" y="626">3 keyboard accessory mirrors the disabled state</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,125 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800" viewBox="0 0 1280 800"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="800" />
|
||||
|
||||
<g transform="translate(0,0)"><rect x="0" y="0" width="1280" height="56" /></g>
|
||||
|
||||
<!-- 1: edit-mode document card -->
|
||||
<g transform="translate(48,80)" data-region="edit-card">
|
||||
<rect x="0" y="0" width="744" height="664" rx="8" stroke="#000" stroke-width="2" />
|
||||
<!-- chrome -->
|
||||
<g transform="translate(16,16)">
|
||||
<rect x="0" y="0" width="56" height="20" rx="10" fill="#e6e6e6" />
|
||||
<text x="28" y="14" text-anchor="middle" font-size="12" stroke="none" fill="#000">EDIT</text>
|
||||
<rect x="64" y="0" width="48" height="20" rx="10" />
|
||||
<text x="88" y="14" text-anchor="middle" font-size="12" stroke="none" fill="#000">PLAN</text>
|
||||
<text x="120" y="14" font-size="12" stroke="none" fill="#666">rev 4 ← editing</text>
|
||||
<!-- save state -->
|
||||
<text x="248" y="14" font-size="12" stroke="none" fill="#666">⟳ Saving…</text>
|
||||
<!-- count chip remains visible -->
|
||||
<rect x="376" y="0" width="96" height="20" rx="10" />
|
||||
<circle cx="390" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="400" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
<!-- right actions -->
|
||||
<rect x="608" y="0" width="56" height="20" rx="4" />
|
||||
<text x="636" y="14" text-anchor="middle" font-size="12" stroke="none" fill="#000">Cancel</text>
|
||||
<rect x="672" y="0" width="40" height="20" rx="4" fill="#000" />
|
||||
<text x="692" y="14" text-anchor="middle" font-size="12" stroke="none" fill="#fff">Done</text>
|
||||
</g>
|
||||
|
||||
<!-- 2: MDXEditor toolbar -->
|
||||
<g transform="translate(16,52)" data-region="editor-toolbar">
|
||||
<rect x="0" y="0" width="712" height="40" rx="4" fill="#fafafa" />
|
||||
<g font-size="14" stroke="none" fill="#000">
|
||||
<text x="16" y="26">B</text>
|
||||
<text x="40" y="26" font-style="italic">I</text>
|
||||
<text x="64" y="26" text-decoration="line-through">S</text>
|
||||
<line x1="88" y1="10" x2="88" y2="30" stroke="#ccc" />
|
||||
<text x="104" y="26">H1</text>
|
||||
<text x="136" y="26">H2</text>
|
||||
<text x="168" y="26">•</text>
|
||||
<text x="192" y="26">1.</text>
|
||||
<line x1="220" y1="10" x2="220" y2="30" stroke="#ccc" />
|
||||
<text x="236" y="26">⌧ Link</text>
|
||||
<text x="292" y="26">⌗ Code</text>
|
||||
<text x="352" y="26">⌹ Table</text>
|
||||
<line x1="432" y1="10" x2="432" y2="30" stroke="#ccc" />
|
||||
<!-- Annotation capture button -->
|
||||
<rect x="448" y="6" width="184" height="28" rx="14" fill="#fff" stroke="#000" />
|
||||
<text x="540" y="24" text-anchor="middle" font-size="12" fill="#000">+ Comment on selection</text>
|
||||
<text x="648" y="24" font-size="12" fill="#666">⌘⇧M</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 3: editor body with selection -->
|
||||
<g transform="translate(24,108)" data-region="editor-body">
|
||||
<rect x="0" y="0" width="280" height="20" fill="#e6e6e6" stroke="none" />
|
||||
<!-- live caret/cursor indicator -->
|
||||
<line x1="284" y1="0" x2="284" y2="20" stroke="#000" stroke-width="2" />
|
||||
<rect x="0" y="40" width="680" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="56" width="640" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- selected range (lexical selection halo) -->
|
||||
<rect x="-2" y="84" width="680" height="14" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="88" width="676" height="10" fill="#000" stroke="none" />
|
||||
<rect x="-2" y="100" width="480" height="14" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="104" width="476" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="136" width="660" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="152" width="600" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- existing thread anchor decoration in edit mode (renders as a soft underline) -->
|
||||
<rect x="0" y="184" width="280" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<line x1="0" y1="198" x2="280" y2="198" stroke-dasharray="3 3" />
|
||||
<rect x="0" y="216" width="540" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- floating selection action -->
|
||||
<g transform="translate(48,68)">
|
||||
<rect x="0" y="0" width="216" height="32" rx="16" fill="#fff" />
|
||||
<text x="14" y="20" font-size="12" stroke="none" fill="#000">+ Comment</text>
|
||||
<line x1="100" y1="6" x2="100" y2="26" stroke="#ccc" />
|
||||
<text x="116" y="20" font-size="12" stroke="none" fill="#666">⌘⇧M</text>
|
||||
<path d="M 24 32 L 32 40 L 40 32 Z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 4: dirty/conflict banner (alternative state shown small) -->
|
||||
<g transform="translate(16,556)" data-region="dirty-banner">
|
||||
<rect x="0" y="0" width="712" height="48" rx="4" fill="#fafafa" />
|
||||
<text x="16" y="20" font-size="12" font-weight="600" stroke="none" fill="#000">Save draft to anchor new comments</text>
|
||||
<text x="16" y="36" font-size="12" stroke="none" fill="#666">Existing threads remain readable. New anchors are disabled while the draft is unsaved.</text>
|
||||
<rect x="600" y="12" width="96" height="24" rx="4" />
|
||||
<text x="648" y="28" text-anchor="middle" font-size="12" stroke="none" fill="#000">Save now</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- side panel (shrunk, read-only in dirty case) -->
|
||||
<g transform="translate(808,80)" data-region="panel">
|
||||
<rect x="0" y="0" width="424" height="664" rx="8" />
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="16" font-size="14" font-weight="600" stroke="none" fill="#000">Comments</text>
|
||||
<text x="0" y="36" font-size="12" stroke="none" fill="#666">PLAN · rev 4 · read-only while draft is dirty</text>
|
||||
</g>
|
||||
<line x1="0" y1="56" x2="424" y2="56" />
|
||||
<g transform="translate(16,72)">
|
||||
<rect x="0" y="0" width="392" height="88" rx="6" fill="#fafafa" />
|
||||
<rect x="12" y="12" width="368" height="20" fill="#fff" stroke="#e6e6e6" />
|
||||
<text x="20" y="26" font-size="12" stroke="none" fill="#666">“existing quote …”</text>
|
||||
<text x="20" y="56" font-size="12" stroke="none" fill="#000">Dotta · 1h ago</text>
|
||||
<text x="20" y="72" font-size="12" stroke="none" fill="#666">2 replies</text>
|
||||
</g>
|
||||
<!-- disabled new-thread button -->
|
||||
<g transform="translate(16,604)">
|
||||
<rect x="0" y="0" width="392" height="40" rx="20" fill="#fafafa" stroke="#ccc" />
|
||||
<text x="196" y="24" text-anchor="middle" font-size="12" stroke="none" fill="#999">New comment disabled — save draft first</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="488" y="120" width="208" height="40" />
|
||||
<rect x="48" y="548" width="744" height="64" />
|
||||
<rect x="808" y="596" width="424" height="56" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="488" y="114">1 toolbar primary action — uses current Lexical selection; same shortcut ⌘⇧M</text>
|
||||
<text x="48" y="544">2 dirty-draft banner — explains why new anchors are disabled until save lands</text>
|
||||
<text x="808" y="592">3 disabled "new comment" CTA mirrors banner reason</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.1 KiB |
@@ -1,141 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="720" />
|
||||
|
||||
<text x="48" y="48" font-size="20" font-weight="600" stroke="none" fill="#000">Annotation lifecycle — single thread across revisions</text>
|
||||
<text x="48" y="72" font-size="12" stroke="none" fill="#666">Each card is one state in the lifecycle of a single thread. Arrows show user/system events that drive transitions.</text>
|
||||
|
||||
<!-- Step thumbnails -->
|
||||
<g font-size="12" stroke="none" fill="#000">
|
||||
<!-- 1. Select -->
|
||||
<g transform="translate(48,120)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">1. Select text</text>
|
||||
<rect x="16" y="48" width="168" height="8" fill="#000" stroke="none" />
|
||||
<rect x="16" y="64" width="120" height="8" fill="#000" stroke="none" />
|
||||
<rect x="32" y="96" width="136" height="28" rx="14" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="114" text-anchor="middle">+ Comment</text>
|
||||
<text x="100" y="148" text-anchor="middle" fill="#666">selection toolbar</text>
|
||||
</g>
|
||||
<!-- 2. Compose -->
|
||||
<g transform="translate(296,120)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">2. Compose</text>
|
||||
<rect x="16" y="40" width="168" height="20" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="24" y="54" font-size="11" fill="#666">“quote…”</text>
|
||||
<rect x="16" y="68" width="168" height="48" stroke="#000" />
|
||||
<text x="24" y="86" font-size="11" fill="#666">type comment…</text>
|
||||
<rect x="120" y="124" width="64" height="22" rx="4" fill="#000" />
|
||||
<text x="152" y="138" text-anchor="middle" fill="#fff">Send</text>
|
||||
</g>
|
||||
<!-- 3. Open thread -->
|
||||
<g transform="translate(544,120)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">3. Open thread</text>
|
||||
<rect x="16" y="40" width="168" height="20" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<rect x="16" y="68" width="168" height="14" fill="#bbb" stroke="none" />
|
||||
<text x="100" y="106" text-anchor="middle">anchor + 2 replies</text>
|
||||
<text x="100" y="132" text-anchor="middle" fill="#666">wakes agent on issue</text>
|
||||
</g>
|
||||
<!-- 4. Resolve -->
|
||||
<g transform="translate(792,120)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">4. Resolve</text>
|
||||
<rect x="16" y="48" width="168" height="14" stroke="#000" stroke-dasharray="2 3" fill="#fff" />
|
||||
<rect x="64" y="80" width="72" height="20" rx="10" stroke="#000" />
|
||||
<text x="100" y="94" text-anchor="middle">Resolved</text>
|
||||
<text x="100" y="124" text-anchor="middle" fill="#666">hidden by default;</text>
|
||||
<text x="100" y="138" text-anchor="middle" fill="#666">"Show resolved" reveals</text>
|
||||
</g>
|
||||
|
||||
<!-- 5. Revision -->
|
||||
<g transform="translate(48,360)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">5. Doc revised</text>
|
||||
<text x="100" y="48" text-anchor="middle" fill="#666">rev 4 → rev 5</text>
|
||||
<rect x="16" y="64" width="168" height="8" fill="#000" stroke="none" />
|
||||
<rect x="16" y="80" width="168" height="8" fill="#000" stroke="none" />
|
||||
<text x="100" y="116" text-anchor="middle">server remaps anchor</text>
|
||||
</g>
|
||||
<!-- 6. Exact remap -->
|
||||
<g transform="translate(296,360)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">6a. Exact remap</text>
|
||||
<rect x="16" y="48" width="168" height="14" fill="#bbb" stroke="none" />
|
||||
<text x="100" y="92" text-anchor="middle" fill="#666">quote+prefix+suffix match</text>
|
||||
<text x="100" y="116" text-anchor="middle" fill="#666">thread stays Open</text>
|
||||
</g>
|
||||
<!-- 7. Stale -->
|
||||
<g transform="translate(544,360)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">6b. Stale</text>
|
||||
<rect x="16" y="48" width="168" height="14" stroke="#000" stroke-dasharray="2 3" fill="#fafafa" />
|
||||
<text x="100" y="92" text-anchor="middle" fill="#666">fuzzy match only</text>
|
||||
<text x="100" y="116" text-anchor="middle" fill="#666">⚠ flag + Re-anchor action</text>
|
||||
</g>
|
||||
<!-- 8. Orphaned -->
|
||||
<g transform="translate(792,360)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">6c. Orphaned</text>
|
||||
<rect x="16" y="48" width="168" height="14" stroke="#000" stroke-dasharray="2 3" fill="#e6e6e6" />
|
||||
<text x="100" y="92" text-anchor="middle" fill="#666">no match in body</text>
|
||||
<text x="100" y="116" text-anchor="middle" fill="#666">view rev 3 to see original</text>
|
||||
</g>
|
||||
|
||||
<!-- 9. Reopen -->
|
||||
<g transform="translate(1040,120)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">4'. Reopen</text>
|
||||
<rect x="16" y="48" width="168" height="14" fill="#bbb" stroke="none" />
|
||||
<text x="100" y="92" text-anchor="middle" fill="#666">resolved → open</text>
|
||||
<text x="100" y="116" text-anchor="middle" fill="#666">re-wakes assignee</text>
|
||||
</g>
|
||||
|
||||
<!-- 10. Edit mode draft -->
|
||||
<g transform="translate(1040,360)">
|
||||
<rect width="200" height="160" rx="8" stroke="#000" fill="#fff" />
|
||||
<text x="100" y="24" text-anchor="middle" font-weight="600">Edit-mode draft</text>
|
||||
<text x="100" y="48" text-anchor="middle" fill="#666">dirty / conflicted</text>
|
||||
<rect x="16" y="64" width="168" height="40" fill="#fafafa" />
|
||||
<text x="100" y="86" text-anchor="middle" fill="#666">read-only panel</text>
|
||||
<text x="100" y="100" text-anchor="middle" fill="#666">no new anchors</text>
|
||||
<text x="100" y="132" text-anchor="middle" fill="#666">save → unlocks</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Arrows -->
|
||||
<g stroke="#000" fill="none">
|
||||
<!-- 1 → 2 -->
|
||||
<path d="M 248 200 H 296" marker-end="url(#arrow)" />
|
||||
<!-- 2 → 3 -->
|
||||
<path d="M 496 200 H 544" marker-end="url(#arrow)" />
|
||||
<!-- 3 → 4 -->
|
||||
<path d="M 744 200 H 792" marker-end="url(#arrow)" />
|
||||
<!-- 4 → 9 -->
|
||||
<path d="M 992 200 H 1040" marker-end="url(#arrow)" />
|
||||
<!-- 3 → 5 (revision happens) -->
|
||||
<path d="M 644 280 V 320 H 148 V 360" marker-end="url(#arrow)" />
|
||||
<!-- 5 → 6a/6b/6c -->
|
||||
<path d="M 248 440 H 296" marker-end="url(#arrow)" />
|
||||
<path d="M 248 440 H 280 V 480 H 644" marker-end="url(#arrow)" />
|
||||
<path d="M 248 440 H 280 V 520 H 892" marker-end="url(#arrow)" />
|
||||
<!-- edit-mode side connector -->
|
||||
<path d="M 992 440 H 1040" stroke-dasharray="3 3" marker-end="url(#arrow)" />
|
||||
</g>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#000" stroke="none" />
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- legend -->
|
||||
<g transform="translate(48,584)" font-size="12" stroke="none" fill="#000">
|
||||
<text x="0" y="0" font-weight="600">Legend</text>
|
||||
<line x1="0" y1="20" x2="48" y2="20" stroke="#000" />
|
||||
<text x="56" y="24" fill="#666">user/system event</text>
|
||||
<line x1="240" y1="20" x2="288" y2="20" stroke="#000" stroke-dasharray="3 3" />
|
||||
<text x="296" y="24" fill="#666">side-effect (e.g. wake)</text>
|
||||
<rect x="480" y="12" width="14" height="14" stroke="#000" stroke-dasharray="2 3" fill="#fafafa" />
|
||||
<text x="500" y="24" fill="#666">resolved / stale chrome</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.8 KiB |
@@ -1,80 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="812" viewBox="0 0 375 812"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="375" height="812" />
|
||||
|
||||
<!-- safe area rails -->
|
||||
<line x1="0" y1="44" x2="375" y2="44" />
|
||||
<line x1="0" y1="778" x2="375" y2="778" />
|
||||
|
||||
<!-- 1: top bar -->
|
||||
<g transform="translate(0,44)">
|
||||
<rect x="0" y="0" width="375" height="48" />
|
||||
<text x="16" y="30" font-size="14" stroke="none" fill="#000">← Issue</text>
|
||||
<text x="359" y="30" font-size="14" text-anchor="end" stroke="none" fill="#000">⋯</text>
|
||||
</g>
|
||||
|
||||
<!-- 2: issue title -->
|
||||
<g transform="translate(16,100)">
|
||||
<text x="0" y="20" font-size="14" stroke="none" fill="#666">PAP-9436</text>
|
||||
<text x="0" y="48" font-size="20" font-weight="600" stroke="none" fill="#000">Phase 4: Document</text>
|
||||
<text x="0" y="72" font-size="20" font-weight="600" stroke="none" fill="#000">annotation UI</text>
|
||||
</g>
|
||||
|
||||
<!-- 3: document card -->
|
||||
<g transform="translate(16,200)" data-region="document-card">
|
||||
<rect x="0" y="0" width="343" height="500" rx="8" />
|
||||
<!-- chrome -->
|
||||
<g transform="translate(12,12)">
|
||||
<text x="0" y="14" font-size="12" stroke="none" fill="#666">▾</text>
|
||||
<rect x="16" y="0" width="40" height="20" rx="10" />
|
||||
<text x="36" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">PLAN</text>
|
||||
<text x="64" y="14" font-size="12" stroke="none" fill="#666">rev 4 ▾</text>
|
||||
<!-- counter chip -->
|
||||
<rect x="216" y="0" width="88" height="20" rx="10" />
|
||||
<circle cx="230" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="240" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
</g>
|
||||
|
||||
<!-- body -->
|
||||
<g transform="translate(16,52)">
|
||||
<rect x="0" y="0" width="180" height="16" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="32" width="304" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="48" width="288" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- selected text -->
|
||||
<rect x="0" y="80" width="304" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="96" width="224" height="10" fill="#000" stroke="none" />
|
||||
<!-- next -->
|
||||
<rect x="0" y="128" width="296" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="144" width="312" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- active highlight -->
|
||||
<rect x="0" y="176" width="220" height="10" fill="#bbb" stroke="none" />
|
||||
<!-- resolved highlight -->
|
||||
<rect x="0" y="208" width="160" height="10" fill="#f2f2f2" stroke="#000" stroke-dasharray="2 3" />
|
||||
</g>
|
||||
|
||||
<!-- selection action sheet over selection -->
|
||||
<g transform="translate(40,308)" data-region="selection-action">
|
||||
<rect x="0" y="0" width="264" height="44" rx="22" />
|
||||
<text x="20" y="28" font-size="14" stroke="none" fill="#000">+ Comment</text>
|
||||
<line x1="124" y1="10" x2="124" y2="34" />
|
||||
<text x="140" y="28" font-size="14" stroke="none" fill="#000">⎘ Copy link</text>
|
||||
<path d="M 32 44 L 40 52 L 48 44 Z" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 4: ambient hint at bottom -->
|
||||
<g transform="translate(0,720)">
|
||||
<line x1="0" y1="0" x2="375" y2="0" />
|
||||
<text x="16" y="22" font-size="12" stroke="none" fill="#666">Long-press text to select • Selection menu appears above</text>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="28" y="304" width="288" height="56" />
|
||||
<rect x="20" y="200" width="120" height="20" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="28" y="296">1 native selection sheet → tap "Comment" opens compose drawer (full bottom sheet)</text>
|
||||
<text x="20" y="194">2 unresolved count chip</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
@@ -1,121 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800" viewBox="0 0 1280 800"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="800" />
|
||||
|
||||
<!-- 1: app top bar -->
|
||||
<g transform="translate(0,0)" data-region="topbar">
|
||||
<rect x="0" y="0" width="1280" height="56" fill="#fff" />
|
||||
<rect x="24" y="20" width="120" height="16" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="1080" y="16" width="80" height="24" rx="4" />
|
||||
<rect x="1176" y="16" width="80" height="24" rx="4" />
|
||||
<text x="1216" y="32" font-size="12" text-anchor="middle" stroke="none" fill="#000">Share</text>
|
||||
<text x="1120" y="32" font-size="12" text-anchor="middle" stroke="none" fill="#000">⋯ More</text>
|
||||
</g>
|
||||
|
||||
<!-- 2: issue header -->
|
||||
<g transform="translate(48,72)" data-region="issue-header">
|
||||
<text x="0" y="20" font-size="12" stroke="none" fill="#666">PAP / Issue</text>
|
||||
<text x="0" y="56" font-size="28" font-weight="600" stroke="none" fill="#000">Phase 4: Document annotation UI</text>
|
||||
<rect x="0" y="80" width="72" height="20" rx="10" />
|
||||
<text x="36" y="94" font-size="12" text-anchor="middle" stroke="none" fill="#000">in progress</text>
|
||||
<rect x="80" y="80" width="64" height="20" rx="10" />
|
||||
<text x="112" y="94" font-size="12" text-anchor="middle" stroke="none" fill="#000">medium</text>
|
||||
</g>
|
||||
|
||||
<!-- 3: document card -->
|
||||
<g transform="translate(48,200)" data-region="document-card">
|
||||
<rect x="0" y="0" width="800" height="544" rx="8" />
|
||||
<!-- document chrome -->
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="14" font-size="12" stroke="none" fill="#666">▾</text>
|
||||
<rect x="16" y="0" width="48" height="20" rx="10" />
|
||||
<text x="40" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">PLAN</text>
|
||||
<text x="76" y="14" font-size="12" stroke="none" fill="#666">rev 4 ▾</text>
|
||||
<text x="128" y="14" font-size="12" stroke="none" fill="#666">updated 12m ago</text>
|
||||
<!-- NEW: unresolved count chip -->
|
||||
<rect x="248" y="0" width="96" height="20" rx="10" />
|
||||
<circle cx="262" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="272" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
<!-- right actions -->
|
||||
<rect x="640" y="0" width="24" height="20" rx="4" />
|
||||
<text x="652" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">⧉</text>
|
||||
<rect x="672" y="0" width="24" height="20" rx="4" />
|
||||
<text x="684" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">⋯</text>
|
||||
<rect x="704" y="0" width="64" height="20" rx="10" />
|
||||
<text x="736" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">Comments</text>
|
||||
</g>
|
||||
|
||||
<!-- 4: rendered markdown body with selection -->
|
||||
<g transform="translate(24,64)" data-region="markdown-body">
|
||||
<!-- heading -->
|
||||
<rect x="0" y="0" width="280" height="20" fill="#e6e6e6" stroke="none" />
|
||||
<!-- paragraph 1 -->
|
||||
<rect x="0" y="40" width="740" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="56" width="700" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="72" width="560" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- selected text run (annotated) -->
|
||||
<rect x="0" y="104" width="740" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="120" width="540" height="10" fill="#000" stroke="none" />
|
||||
<!-- next paragraph -->
|
||||
<rect x="0" y="152" width="720" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="168" width="680" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="184" width="520" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- existing highlighted run (open thread) -->
|
||||
<rect x="0" y="216" width="320" height="10" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="232" width="180" height="10" fill="#bbb" stroke="none" />
|
||||
<!-- more body -->
|
||||
<rect x="0" y="264" width="720" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="280" width="640" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- existing resolved highlight (lighter dashed underline) -->
|
||||
<rect x="0" y="312" width="240" height="10" fill="#f2f2f2" stroke="#000" stroke-dasharray="2 3" />
|
||||
<rect x="0" y="328" width="420" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- fold curtain hint -->
|
||||
<line x1="0" y1="412" x2="740" y2="412" stroke-dasharray="4 4" />
|
||||
<text x="370" y="436" font-size="12" text-anchor="middle" stroke="none" fill="#666">show more ▾</text>
|
||||
</g>
|
||||
|
||||
<!-- 5: floating selection toolbar above selected range -->
|
||||
<g transform="translate(96,232)" data-region="selection-toolbar">
|
||||
<rect x="0" y="0" width="232" height="36" rx="18" fill="#fff" />
|
||||
<text x="14" y="22" font-size="14" stroke="none" fill="#000">+ Comment</text>
|
||||
<line x1="112" y1="8" x2="112" y2="28" />
|
||||
<text x="124" y="22" font-size="14" stroke="none" fill="#000">⎘ Copy link</text>
|
||||
<text x="206" y="22" font-size="14" stroke="none" fill="#666">⌘⇧M</text>
|
||||
<!-- pointer caret toward selection -->
|
||||
<path d="M 24 36 L 32 44 L 40 36 Z" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 6: right rail issue properties (collapses when panel opens) -->
|
||||
<g transform="translate(880,200)" data-region="right-rail">
|
||||
<rect x="0" y="0" width="352" height="544" rx="8" />
|
||||
<text x="16" y="32" font-size="14" stroke="none" fill="#000">Properties</text>
|
||||
<line x1="16" y1="48" x2="336" y2="48" />
|
||||
<text x="16" y="80" font-size="12" stroke="none" fill="#666">Assignee</text>
|
||||
<circle cx="312" cy="76" r="10" fill="#e6e6e6" stroke="none" />
|
||||
<text x="16" y="120" font-size="12" stroke="none" fill="#666">Status</text>
|
||||
<text x="328" y="120" font-size="12" text-anchor="end" stroke="none" fill="#000">in progress</text>
|
||||
<text x="16" y="160" font-size="12" stroke="none" fill="#666">Priority</text>
|
||||
<text x="328" y="160" font-size="12" text-anchor="end" stroke="none" fill="#000">medium</text>
|
||||
<text x="16" y="200" font-size="12" stroke="none" fill="#666">Project</text>
|
||||
<text x="328" y="200" font-size="12" text-anchor="end" stroke="none" fill="#000">Paperclip App</text>
|
||||
<text x="16" y="240" font-size="12" stroke="none" fill="#666">Blockers</text>
|
||||
<text x="328" y="240" font-size="12" text-anchor="end" stroke="none" fill="#000">0</text>
|
||||
</g>
|
||||
|
||||
<!-- annotation callouts (red dashed) -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="60" y="208" width="784" height="40" />
|
||||
<rect x="60" y="298" width="408" height="30" />
|
||||
<rect x="60" y="368" width="408" height="30" />
|
||||
<rect x="312" y="208" width="100" height="22" />
|
||||
<rect x="136" y="424" width="248" height="44" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="60" y="200">1 selected range — floating toolbar anchors above selection (or below on near-top)</text>
|
||||
<text x="60" y="294">2 active thread highlight — solid underline, hover/focus elevates</text>
|
||||
<text x="60" y="364">3 resolved thread highlight — dashed underline, dimmed</text>
|
||||
<text x="312" y="204">4 unresolved count chip in document chrome</text>
|
||||
<text x="136" y="420">5 floating toolbar — "Comment" + "Copy link"; ⌘⇧M keyboard shortcut</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.2 KiB |
@@ -1,90 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="812" viewBox="0 0 375 812"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="375" height="812" />
|
||||
|
||||
<!-- safe area lines -->
|
||||
<line x1="0" y1="44" x2="375" y2="44" />
|
||||
<line x1="0" y1="778" x2="375" y2="778" />
|
||||
|
||||
<!-- 1: scrim over document -->
|
||||
<g transform="translate(0,44)">
|
||||
<rect x="0" y="0" width="375" height="380" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<!-- dim representation of document underneath -->
|
||||
<g transform="translate(16,24)" stroke="#ccc" fill="none">
|
||||
<rect x="0" y="0" width="343" height="16" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="32" width="320" height="8" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="48" width="296" height="8" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="80" width="200" height="8" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="112" width="296" height="8" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="128" width="248" height="8" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<text x="187" y="364" text-anchor="middle" font-size="12" stroke="none" fill="#666">Tap scrim to dismiss</text>
|
||||
</g>
|
||||
|
||||
<!-- 2: bottom sheet -->
|
||||
<g transform="translate(0,400)" data-region="bottom-sheet">
|
||||
<rect x="0" y="0" width="375" height="378" rx="16" />
|
||||
<!-- grab handle -->
|
||||
<rect x="163" y="8" width="48" height="4" rx="2" fill="#ccc" stroke="none" />
|
||||
<!-- header -->
|
||||
<g transform="translate(16,24)">
|
||||
<text x="0" y="16" font-size="14" font-weight="600" stroke="none" fill="#000">Comments</text>
|
||||
<text x="0" y="36" font-size="12" stroke="none" fill="#666">PLAN · rev 4</text>
|
||||
<text x="343" y="16" text-anchor="end" font-size="14" stroke="none" fill="#000">×</text>
|
||||
</g>
|
||||
|
||||
<!-- filter chips -->
|
||||
<g transform="translate(16,76)">
|
||||
<rect x="0" y="0" width="72" height="28" rx="14" fill="#e6e6e6" />
|
||||
<text x="36" y="18" font-size="12" text-anchor="middle" stroke="none" fill="#000">Open 2</text>
|
||||
<rect x="80" y="0" width="96" height="28" rx="14" />
|
||||
<text x="128" y="18" font-size="12" text-anchor="middle" stroke="none" fill="#666">Resolved 1</text>
|
||||
<rect x="184" y="0" width="80" height="28" rx="14" />
|
||||
<text x="224" y="18" font-size="12" text-anchor="middle" stroke="none" fill="#666">Stale 0</text>
|
||||
</g>
|
||||
|
||||
<!-- thread (focused) -->
|
||||
<g transform="translate(16,116)">
|
||||
<rect x="0" y="0" width="343" height="180" rx="6" stroke="#000" stroke-width="2" />
|
||||
<rect x="12" y="12" width="319" height="28" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“selected quote …”</text>
|
||||
<g transform="translate(12,52)">
|
||||
<circle cx="12" cy="12" r="10" fill="#e6e6e6" stroke="none" />
|
||||
<text x="32" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">Dotta · board</text>
|
||||
<text x="32" y="28" font-size="12" stroke="none" fill="#666">2m ago</text>
|
||||
<rect x="32" y="40" width="280" height="8" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="32" y="56" width="240" height="8" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<!-- thread nav (prev/next) -->
|
||||
<g transform="translate(12,144)">
|
||||
<rect x="0" y="0" width="32" height="24" rx="4" />
|
||||
<text x="16" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">‹</text>
|
||||
<text x="48" y="16" font-size="12" stroke="none" fill="#666">1 of 2 open</text>
|
||||
<rect x="124" y="0" width="32" height="24" rx="4" />
|
||||
<text x="140" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">›</text>
|
||||
<rect x="251" y="0" width="76" height="24" rx="4" />
|
||||
<text x="289" y="16" text-anchor="middle" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- composer (collapsed) -->
|
||||
<g transform="translate(16,308)" data-region="composer">
|
||||
<rect x="0" y="0" width="343" height="48" rx="24" />
|
||||
<text x="16" y="30" font-size="14" stroke="none" fill="#666">Reply…</text>
|
||||
<rect x="287" y="8" width="48" height="32" rx="16" fill="#000" />
|
||||
<text x="311" y="28" font-size="12" text-anchor="middle" stroke="none" fill="#fff">Send</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="8" y="404" width="359" height="40" />
|
||||
<rect x="8" y="552" width="359" height="60" />
|
||||
<rect x="8" y="716" width="359" height="56" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="8" y="400">1 grab handle — swipe up to expand to full height, swipe down to dismiss</text>
|
||||
<text x="8" y="548">2 single thread focus — prev/next steps through "Open" filter; tapping body scrolls to anchor</text>
|
||||
<text x="8" y="710">3 composer collapses; tapping expands to multiline + mention chip</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,152 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800" viewBox="0 0 1280 800"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="800" />
|
||||
|
||||
<!-- top bar -->
|
||||
<g transform="translate(0,0)">
|
||||
<rect x="0" y="0" width="1280" height="56" />
|
||||
<rect x="24" y="20" width="120" height="16" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
|
||||
<!-- 1: document card (narrowed to make room for side panel) -->
|
||||
<g transform="translate(48,80)" data-region="document-card">
|
||||
<rect x="0" y="0" width="744" height="664" rx="8" />
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="14" font-size="12" stroke="none" fill="#666">▾</text>
|
||||
<rect x="16" y="0" width="48" height="20" rx="10" />
|
||||
<text x="40" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">PLAN</text>
|
||||
<text x="76" y="14" font-size="12" stroke="none" fill="#666">rev 4 ▾</text>
|
||||
<!-- count chip pressed/active -->
|
||||
<rect x="200" y="0" width="96" height="20" rx="10" fill="#e6e6e6" />
|
||||
<circle cx="214" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="224" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
<!-- right actions -->
|
||||
<rect x="592" y="0" width="24" height="20" rx="4" />
|
||||
<text x="604" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">⧉</text>
|
||||
<rect x="624" y="0" width="24" height="20" rx="4" />
|
||||
<text x="636" y="14" font-size="12" text-anchor="middle" stroke="none" fill="#000">⋯</text>
|
||||
</g>
|
||||
|
||||
<!-- body, with the active thread anchor visibly focused -->
|
||||
<g transform="translate(24,64)">
|
||||
<rect x="0" y="0" width="280" height="20" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="40" width="680" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="56" width="640" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="72" width="540" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- focused thread (active selection echo) -->
|
||||
<rect x="-4" y="100" width="668" height="34" fill="#fafafa" stroke="#000" />
|
||||
<rect x="0" y="108" width="660" height="10" fill="#000" stroke="none" />
|
||||
<rect x="0" y="124" width="500" height="10" fill="#000" stroke="none" />
|
||||
<!-- following body -->
|
||||
<rect x="0" y="160" width="660" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="176" width="620" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- second thread (open) -->
|
||||
<rect x="0" y="216" width="300" height="10" fill="#bbb" stroke="none" />
|
||||
<rect x="0" y="248" width="640" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<!-- resolved thread highlight -->
|
||||
<rect x="0" y="288" width="220" height="10" fill="#f2f2f2" stroke="#000" stroke-dasharray="2 3" />
|
||||
<rect x="0" y="320" width="600" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="0" y="336" width="540" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 2: side annotation panel -->
|
||||
<g transform="translate(808,80)" data-region="annotation-panel">
|
||||
<rect x="0" y="0" width="424" height="664" rx="8" />
|
||||
<!-- header -->
|
||||
<g transform="translate(16,16)">
|
||||
<text x="0" y="16" font-size="14" font-weight="600" stroke="none" fill="#000">Comments</text>
|
||||
<text x="0" y="36" font-size="12" stroke="none" fill="#666">PLAN · rev 4</text>
|
||||
<!-- filters -->
|
||||
<g transform="translate(208,0)">
|
||||
<rect x="0" y="0" width="72" height="24" rx="12" fill="#e6e6e6" />
|
||||
<text x="36" y="16" font-size="12" text-anchor="middle" stroke="none" fill="#000">Open 2</text>
|
||||
<rect x="80" y="0" width="88" height="24" rx="12" />
|
||||
<text x="124" y="16" font-size="12" text-anchor="middle" stroke="none" fill="#666">Resolved 1</text>
|
||||
<rect x="176" y="0" width="32" height="24" rx="12" />
|
||||
<text x="192" y="16" font-size="12" text-anchor="middle" stroke="none" fill="#000">×</text>
|
||||
</g>
|
||||
</g>
|
||||
<line x1="0" y1="56" x2="424" y2="56" />
|
||||
|
||||
<!-- thread 1 (focused) -->
|
||||
<g transform="translate(16,72)" data-region="thread-focused">
|
||||
<rect x="0" y="0" width="392" height="208" rx="6" stroke="#000" stroke-width="2" />
|
||||
<rect x="12" y="12" width="368" height="32" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="32" font-size="12" stroke="none" fill="#666">“selected quote from the document …”</text>
|
||||
<!-- comment 1 -->
|
||||
<g transform="translate(12,56)">
|
||||
<circle cx="12" cy="12" r="10" fill="#e6e6e6" stroke="none" />
|
||||
<text x="32" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">Dotta · board</text>
|
||||
<text x="32" y="28" font-size="12" stroke="none" fill="#666">2m ago</text>
|
||||
<rect x="32" y="40" width="320" height="10" fill="#e6e6e6" stroke="none" />
|
||||
<rect x="32" y="56" width="280" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
<!-- comment 2 (agent reply) -->
|
||||
<g transform="translate(12,136)">
|
||||
<rect x="0" y="0" width="20" height="20" fill="#e6e6e6" stroke="none" />
|
||||
<text x="32" y="12" font-size="12" font-weight="600" stroke="none" fill="#000">UXDesigner · agent</text>
|
||||
<text x="32" y="28" font-size="12" stroke="none" fill="#666">just now</text>
|
||||
<rect x="32" y="40" width="296" height="10" fill="#e6e6e6" stroke="none" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- reply composer -->
|
||||
<g transform="translate(16,288)" data-region="reply-composer">
|
||||
<rect x="0" y="0" width="392" height="80" rx="6" />
|
||||
<text x="12" y="24" font-size="12" stroke="none" fill="#666">Reply…</text>
|
||||
<line x1="0" y1="48" x2="392" y2="48" />
|
||||
<text x="12" y="68" font-size="12" stroke="none" fill="#666">@ mention</text>
|
||||
<rect x="248" y="52" width="64" height="24" rx="4" />
|
||||
<text x="280" y="68" font-size="12" text-anchor="middle" stroke="none" fill="#000">Resolve</text>
|
||||
<rect x="320" y="52" width="56" height="24" rx="4" fill="#000" />
|
||||
<text x="348" y="68" font-size="12" text-anchor="middle" stroke="none" fill="#fff">Reply</text>
|
||||
</g>
|
||||
|
||||
<!-- thread 2 (collapsed open) -->
|
||||
<g transform="translate(16,384)" data-region="thread-2">
|
||||
<rect x="0" y="0" width="392" height="88" rx="6" />
|
||||
<rect x="12" y="12" width="368" height="20" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="26" font-size="12" stroke="none" fill="#666">“another anchored quote…”</text>
|
||||
<g transform="translate(12,44)">
|
||||
<circle cx="10" cy="10" r="8" fill="#e6e6e6" stroke="none" />
|
||||
<text x="28" y="10" font-size="12" font-weight="600" stroke="none" fill="#000">Senior PE</text>
|
||||
<text x="28" y="26" font-size="12" stroke="none" fill="#666">1d ago · 2 replies</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- thread 3 (resolved, dimmed) -->
|
||||
<g transform="translate(16,488)" data-region="thread-3">
|
||||
<rect x="0" y="0" width="392" height="80" rx="6" fill="#fafafa" />
|
||||
<rect x="12" y="12" width="368" height="20" fill="#fff" stroke="#e6e6e6" stroke-dasharray="2 3" />
|
||||
<text x="20" y="26" font-size="12" stroke="none" fill="#666">“resolved quote…”</text>
|
||||
<g transform="translate(12,44)">
|
||||
<circle cx="10" cy="10" r="8" fill="#e6e6e6" stroke="none" />
|
||||
<text x="28" y="10" font-size="12" font-weight="600" stroke="none" fill="#666">CodexCoder</text>
|
||||
<text x="28" y="26" font-size="12" stroke="none" fill="#666">Resolved · 3h ago</text>
|
||||
<rect x="312" y="-6" width="68" height="20" rx="10" />
|
||||
<text x="346" y="8" font-size="12" text-anchor="middle" stroke="none" fill="#000">Reopen</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- footer / new thread CTA -->
|
||||
<line x1="0" y1="604" x2="424" y2="604" />
|
||||
<g transform="translate(16,612)">
|
||||
<rect x="0" y="0" width="392" height="40" rx="20" />
|
||||
<text x="16" y="24" font-size="12" stroke="none" fill="#000">+ New comment on selection</text>
|
||||
<text x="376" y="24" font-size="12" text-anchor="end" stroke="none" fill="#666">⌘⇧M</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="800" y="72" width="440" height="64" />
|
||||
<rect x="800" y="280" width="440" height="80" />
|
||||
<rect x="48" y="180" width="744" height="32" />
|
||||
</g>
|
||||
<g stroke="none" fill="#d33" font-size="12">
|
||||
<text x="800" y="64">1 panel header — filter chips (Open / Resolved) + clear-focus ×</text>
|
||||
<text x="800" y="272">2 expanded thread — quote chip, replies, mention picker, Resolve + Reply</text>
|
||||
<text x="48" y="174">3 focused anchor — soft inset background, links pane ↔ body</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.5 KiB |
@@ -1,91 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="812" viewBox="0 0 375 812"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="375" height="812" />
|
||||
|
||||
<line x1="0" y1="44" x2="375" y2="44" />
|
||||
<line x1="0" y1="778" x2="375" y2="778" />
|
||||
|
||||
<!-- header -->
|
||||
<g transform="translate(0,44)">
|
||||
<rect x="0" y="0" width="375" height="48" />
|
||||
<text x="16" y="30" font-size="14" stroke="none" fill="#000">← PLAN</text>
|
||||
<text x="187" y="30" text-anchor="middle" font-size="14" font-weight="600" stroke="none" fill="#000">Comments</text>
|
||||
<text x="359" y="30" text-anchor="end" font-size="14" stroke="none" fill="#000">⋯</text>
|
||||
</g>
|
||||
|
||||
<!-- filter chips -->
|
||||
<g transform="translate(16,108)">
|
||||
<rect x="0" y="0" width="72" height="28" rx="14" />
|
||||
<text x="36" y="18" text-anchor="middle" font-size="12" stroke="none" fill="#666">Open 1</text>
|
||||
<rect x="80" y="0" width="96" height="28" rx="14" fill="#e6e6e6" />
|
||||
<text x="128" y="18" text-anchor="middle" font-size="12" stroke="none" fill="#000">Resolved 1</text>
|
||||
<rect x="184" y="0" width="80" height="28" rx="14" />
|
||||
<text x="224" y="18" text-anchor="middle" font-size="12" stroke="none" fill="#666">Stale 1</text>
|
||||
<rect x="272" y="0" width="80" height="28" rx="14" />
|
||||
<text x="312" y="18" text-anchor="middle" font-size="12" stroke="none" fill="#666">Orphan 1</text>
|
||||
</g>
|
||||
|
||||
<!-- stacked state cards -->
|
||||
<g transform="translate(16,156)">
|
||||
<!-- open -->
|
||||
<rect x="0" y="0" width="343" height="120" rx="6" />
|
||||
<rect x="12" y="12" width="319" height="24" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="28" font-size="12" stroke="none" fill="#666">“quote …”</text>
|
||||
<rect x="12" y="48" width="56" height="20" rx="10" fill="#000" />
|
||||
<text x="40" y="62" text-anchor="middle" font-size="12" stroke="none" fill="#fff">Open</text>
|
||||
<text x="80" y="62" font-size="12" stroke="none" fill="#666">rev 4 · 2 replies</text>
|
||||
<line x1="12" y1="80" x2="331" y2="80" stroke="#ccc" />
|
||||
<text x="12" y="100" font-size="12" stroke="none" fill="#000">Reply</text>
|
||||
<text x="120" y="100" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
<text x="244" y="100" font-size="12" stroke="none" fill="#000">Copy link</text>
|
||||
</g>
|
||||
|
||||
<g transform="translate(16,292)">
|
||||
<rect x="0" y="0" width="343" height="120" rx="6" fill="#fafafa" />
|
||||
<rect x="12" y="12" width="319" height="24" fill="#fff" stroke="#e6e6e6" stroke-dasharray="2 3" />
|
||||
<text x="20" y="28" font-size="12" stroke="none" fill="#666">“quote …”</text>
|
||||
<rect x="12" y="48" width="72" height="20" rx="10" />
|
||||
<text x="48" y="62" text-anchor="middle" font-size="12" stroke="none" fill="#666">Resolved</text>
|
||||
<text x="92" y="62" font-size="12" stroke="none" fill="#666">rev 3 → 4</text>
|
||||
<line x1="12" y1="80" x2="331" y2="80" stroke="#ccc" />
|
||||
<text x="12" y="100" font-size="12" stroke="none" fill="#000">Reopen</text>
|
||||
<text x="244" y="100" font-size="12" stroke="none" fill="#000">Copy link</text>
|
||||
</g>
|
||||
|
||||
<g transform="translate(16,428)">
|
||||
<rect x="0" y="0" width="343" height="120" rx="6" />
|
||||
<rect x="12" y="12" width="319" height="24" fill="#fafafa" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="20" y="28" font-size="12" stroke="none" fill="#666">“fuzzy quote …”</text>
|
||||
<rect x="12" y="48" width="56" height="20" rx="10" />
|
||||
<text x="40" y="62" text-anchor="middle" font-size="12" stroke="none" fill="#000">Stale</text>
|
||||
<text x="80" y="62" font-size="12" stroke="none" fill="#000">⚠ matched fuzzy</text>
|
||||
<line x1="12" y1="80" x2="331" y2="80" stroke="#ccc" />
|
||||
<text x="12" y="100" font-size="12" stroke="none" fill="#000">Re-anchor</text>
|
||||
<text x="120" y="100" font-size="12" stroke="none" fill="#000">Show diff</text>
|
||||
<text x="244" y="100" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
</g>
|
||||
|
||||
<g transform="translate(16,564)">
|
||||
<rect x="0" y="0" width="343" height="120" rx="6" />
|
||||
<rect x="12" y="12" width="319" height="24" fill="#e6e6e6" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="20" y="28" font-size="12" stroke="none" fill="#666">“original quote …”</text>
|
||||
<rect x="12" y="48" width="80" height="20" rx="10" fill="#e6e6e6" />
|
||||
<text x="52" y="62" text-anchor="middle" font-size="12" stroke="none" fill="#000">Orphaned</text>
|
||||
<text x="104" y="62" font-size="12" stroke="none" fill="#666">last seen rev 3</text>
|
||||
<line x1="12" y1="80" x2="331" y2="80" stroke="#ccc" />
|
||||
<text x="12" y="100" font-size="12" stroke="none" fill="#000">View rev 3</text>
|
||||
<text x="120" y="100" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
<text x="244" y="100" font-size="12" stroke="none" fill="#000">Copy link</text>
|
||||
</g>
|
||||
|
||||
<!-- footer -->
|
||||
<g transform="translate(0,716)">
|
||||
<line x1="0" y1="0" x2="375" y2="0" />
|
||||
<text x="16" y="22" font-size="12" stroke="none" fill="#666">Filter chips wrap to a second row at 320px. "Show resolved/orphaned" toggles persist per-document.</text>
|
||||
</g>
|
||||
|
||||
<!-- callouts -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="8" y="148" width="359" height="544" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.1 KiB |
@@ -1,118 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800" viewBox="0 0 1280 800"
|
||||
font-family="-apple-system, system-ui, sans-serif" fill="#fff" stroke="#000" stroke-width="1.5">
|
||||
<rect x="0" y="0" width="1280" height="800" />
|
||||
|
||||
<!-- title -->
|
||||
<g transform="translate(48,48)">
|
||||
<text x="0" y="24" font-size="20" font-weight="600" stroke="none" fill="#000">Thread state matrix — visible chrome per state</text>
|
||||
<text x="0" y="48" font-size="12" stroke="none" fill="#666">Same anchor data, different presentation. Card states on the left, in-body highlight states on the right.</text>
|
||||
</g>
|
||||
|
||||
<!-- LEFT: panel state cards -->
|
||||
<g transform="translate(48,112)" data-region="state-cards">
|
||||
<!-- Open / active -->
|
||||
<g transform="translate(0,0)">
|
||||
<rect x="0" y="0" width="416" height="160" rx="6" />
|
||||
<rect x="12" y="12" width="392" height="28" fill="#fafafa" stroke="#e6e6e6" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“selected quote …”</text>
|
||||
<text x="12" y="60" font-size="12" font-weight="600" stroke="none" fill="#000">Open · active anchor</text>
|
||||
<text x="12" y="80" font-size="12" stroke="none" fill="#666">Dotta · 2m ago · 2 replies</text>
|
||||
<rect x="12" y="96" width="60" height="20" rx="10" fill="#000" stroke="#000" />
|
||||
<text x="42" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#fff">Open</text>
|
||||
<text x="84" y="110" font-size="12" stroke="none" fill="#666">rev 4 (current)</text>
|
||||
<line x1="12" y1="128" x2="404" y2="128" stroke="#ccc" />
|
||||
<text x="12" y="146" font-size="12" stroke="none" fill="#666">Reply • Resolve • Copy link</text>
|
||||
</g>
|
||||
|
||||
<!-- Resolved -->
|
||||
<g transform="translate(0,176)">
|
||||
<rect x="0" y="0" width="416" height="160" rx="6" fill="#fafafa" />
|
||||
<rect x="12" y="12" width="392" height="28" fill="#fff" stroke="#e6e6e6" stroke-dasharray="2 3" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“resolved quote …”</text>
|
||||
<text x="12" y="60" font-size="12" font-weight="600" stroke="none" fill="#666">Resolved</text>
|
||||
<text x="12" y="80" font-size="12" stroke="none" fill="#666">CodexCoder · 3h ago · 1 reply</text>
|
||||
<rect x="12" y="96" width="78" height="20" rx="10" />
|
||||
<text x="51" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#666">Resolved</text>
|
||||
<text x="102" y="110" font-size="12" stroke="none" fill="#666">rev 3 → 4</text>
|
||||
<line x1="12" y1="128" x2="404" y2="128" stroke="#ccc" />
|
||||
<text x="12" y="146" font-size="12" stroke="none" fill="#666">Reopen • Copy link</text>
|
||||
</g>
|
||||
|
||||
<!-- Stale -->
|
||||
<g transform="translate(440,0)">
|
||||
<rect x="0" y="0" width="416" height="160" rx="6" />
|
||||
<rect x="12" y="12" width="392" height="28" fill="#fafafa" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“fuzzy-matched quote …”</text>
|
||||
<text x="12" y="60" font-size="12" font-weight="600" stroke="none" fill="#000">Stale · fuzzy anchor</text>
|
||||
<text x="12" y="80" font-size="12" stroke="none" fill="#666">Senior PE · resolved match at rev 4</text>
|
||||
<rect x="12" y="96" width="56" height="20" rx="10" />
|
||||
<text x="40" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">Stale</text>
|
||||
<rect x="76" y="96" width="76" height="20" rx="10" />
|
||||
<text x="114" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">Re-anchor</text>
|
||||
<rect x="160" y="96" width="80" height="20" rx="10" />
|
||||
<text x="200" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">Show diff</text>
|
||||
<line x1="12" y1="128" x2="404" y2="128" stroke="#ccc" />
|
||||
<text x="12" y="146" font-size="12" stroke="none" fill="#666">Click "Show diff" to compare rev 3 anchor vs rev 4 text</text>
|
||||
</g>
|
||||
|
||||
<!-- Orphaned -->
|
||||
<g transform="translate(440,176)">
|
||||
<rect x="0" y="0" width="416" height="160" rx="6" />
|
||||
<rect x="12" y="12" width="392" height="28" fill="#e6e6e6" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="20" y="30" font-size="12" stroke="none" fill="#666">“original quote no longer in body”</text>
|
||||
<text x="12" y="60" font-size="12" font-weight="600" stroke="none" fill="#000">Orphaned · no match</text>
|
||||
<text x="12" y="80" font-size="12" stroke="none" fill="#666">QA · last seen rev 3 · 4 replies</text>
|
||||
<rect x="12" y="96" width="80" height="20" rx="10" fill="#e6e6e6" />
|
||||
<text x="52" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">Orphaned</text>
|
||||
<rect x="100" y="96" width="92" height="20" rx="10" />
|
||||
<text x="146" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">View rev 3</text>
|
||||
<rect x="200" y="96" width="64" height="20" rx="10" />
|
||||
<text x="232" y="110" text-anchor="middle" font-size="12" stroke="none" fill="#000">Resolve</text>
|
||||
<line x1="12" y1="128" x2="404" y2="128" stroke="#ccc" />
|
||||
<text x="12" y="146" font-size="12" stroke="none" fill="#666">No in-body anchor → no scroll-to action; quote stays canonical</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- RIGHT: in-body highlight legend -->
|
||||
<g transform="translate(880,112)" data-region="legend">
|
||||
<rect x="0" y="0" width="352" height="496" rx="8" />
|
||||
<text x="16" y="32" font-size="14" font-weight="600" stroke="none" fill="#000">In-body highlight legend</text>
|
||||
<line x1="16" y1="48" x2="336" y2="48" />
|
||||
|
||||
<!-- legend rows -->
|
||||
<g transform="translate(16,72)">
|
||||
<rect x="0" y="0" width="240" height="10" fill="#000" stroke="none" />
|
||||
<text x="0" y="32" font-size="12" stroke="none" fill="#000">Active selection (composing)</text>
|
||||
|
||||
<rect x="0" y="56" width="240" height="10" fill="#bbb" stroke="none" />
|
||||
<text x="0" y="88" font-size="12" stroke="none" fill="#000">Open thread — solid mid-grey underline</text>
|
||||
|
||||
<rect x="0" y="112" width="240" height="10" fill="#fafafa" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="0" y="144" font-size="12" stroke="none" fill="#000">Resolved thread — dashed outline, dim fill</text>
|
||||
|
||||
<rect x="0" y="168" width="240" height="10" fill="#fafafa" stroke="#000" stroke-dasharray="2 3" />
|
||||
<text x="0" y="200" font-size="12" stroke="none" fill="#000">Stale (fuzzy match) — dashed outline, ⚠ flag</text>
|
||||
<text x="244" y="178" font-size="12" stroke="none" fill="#000">⚠</text>
|
||||
|
||||
<line x1="0" y1="232" x2="240" y2="232" stroke="#ccc" stroke-dasharray="3 3" />
|
||||
<text x="0" y="264" font-size="12" stroke="none" fill="#000">Orphaned — no in-body underline; panel-only</text>
|
||||
|
||||
<rect x="0" y="296" width="240" height="14" fill="#fff" stroke="#000" stroke-width="2" />
|
||||
<text x="0" y="332" font-size="12" stroke="none" fill="#000">Focused thread — heavy 2px border across anchor</text>
|
||||
</g>
|
||||
|
||||
<!-- count chip semantics -->
|
||||
<g transform="translate(16,440)">
|
||||
<rect x="0" y="0" width="96" height="20" rx="10" />
|
||||
<circle cx="14" cy="10" r="3" fill="#000" stroke="none" />
|
||||
<text x="24" y="14" font-size="12" stroke="none" fill="#000">3 comments</text>
|
||||
<text x="112" y="14" font-size="12" stroke="none" fill="#666">unresolved count only — resolved/stale/orphaned hidden until filter toggled</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- footer callout -->
|
||||
<g stroke="#d33" stroke-dasharray="4 4" fill="none">
|
||||
<rect x="40" y="104" width="824" height="416" />
|
||||
</g>
|
||||
<text x="40" y="540" stroke="none" fill="#d33" font-size="12">All four states show identical author/quote/reply metadata. Only the chrome (border, fill, badge, actions) differs — never the data layout.</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 169 KiB |
|
Before Width: | Height: | Size: 285 KiB |
|
Before Width: | Height: | Size: 294 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 281 KiB |
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 217 KiB |
@@ -1,104 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
// Capture screenshots of the Document Annotation storybook stories.
|
||||
// Usage: node scripts/screenshot-doc-annotations.mjs <storybook-static-dir> <output-dir>
|
||||
|
||||
import http from "node:http";
|
||||
import path from "node:path";
|
||||
import fs from "node:fs/promises";
|
||||
import { chromium } from "@playwright/test";
|
||||
|
||||
async function main() {
|
||||
const [, , staticDir, outDir] = process.argv;
|
||||
if (!staticDir || !outDir) {
|
||||
console.error("usage: node scripts/screenshot-doc-annotations.mjs <storybook-static-dir> <output-dir>");
|
||||
process.exit(1);
|
||||
}
|
||||
await fs.mkdir(outDir, { recursive: true });
|
||||
const absStaticDir = path.resolve(staticDir);
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
try {
|
||||
let urlPath = decodeURIComponent((req.url || "/").split("?")[0]);
|
||||
if (urlPath.endsWith("/")) urlPath += "iframe.html";
|
||||
const filePath = path.resolve(absStaticDir, `.${urlPath}`);
|
||||
if (!filePath.startsWith(absStaticDir + path.sep) && filePath !== absStaticDir) {
|
||||
res.writeHead(403);
|
||||
res.end("Forbidden");
|
||||
return;
|
||||
}
|
||||
const buf = await fs.readFile(filePath);
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const mime = {
|
||||
".html": "text/html; charset=utf-8",
|
||||
".js": "application/javascript",
|
||||
".css": "text/css",
|
||||
".json": "application/json",
|
||||
".svg": "image/svg+xml",
|
||||
".png": "image/png",
|
||||
".woff": "font/woff",
|
||||
".woff2": "font/woff2",
|
||||
".map": "application/json",
|
||||
}[ext] || "application/octet-stream";
|
||||
res.writeHead(200, { "content-type": mime });
|
||||
res.end(buf);
|
||||
} catch (err) {
|
||||
res.writeHead(404);
|
||||
res.end(String(err));
|
||||
}
|
||||
});
|
||||
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const port = server.address().port;
|
||||
const baseUrl = `http://127.0.0.1:${port}/iframe.html`;
|
||||
|
||||
const browser = await chromium.launch();
|
||||
try {
|
||||
const stories = [
|
||||
// INTEGRATED — these are the captures the UX gate requires. They render
|
||||
// IssueDocumentsSection chrome (count chip in header row, body + side panel
|
||||
// wired together, edit mode wrapping the layer, real shadcn Sheet on mobile).
|
||||
{ id: "product-documents-annotations--integrated-desktop-open", file: "01-integrated-desktop-open.png", width: 1440, height: 900 },
|
||||
{ id: "product-documents-annotations--integrated-desktop-zero-comments", file: "02-integrated-desktop-zero-count.png", width: 1440, height: 900 },
|
||||
{ id: "product-documents-annotations--integrated-desktop-edit-mode", file: "03-integrated-desktop-edit-mode.png", width: 1440, height: 900 },
|
||||
{ id: "product-documents-annotations--integrated-desktop-dirty-draft", file: "04-integrated-desktop-dirty-draft.png", width: 1440, height: 900 },
|
||||
{ id: "product-documents-annotations--integrated-mobile-bottom-sheet", file: "05-integrated-mobile-sheet.png", width: 390, height: 844 },
|
||||
// ISOLATED — kept around for visual debugging of state pieces.
|
||||
{ id: "product-documents-annotations--desktop-open-focused", file: "10-states-open-focused.png", width: 1280, height: 900 },
|
||||
{ id: "product-documents-annotations--desktop-resolved-focused", file: "11-states-resolved-focused.png", width: 1280, height: 900 },
|
||||
{ id: "product-documents-annotations--desktop-stale-focused", file: "12-states-stale-focused.png", width: 1280, height: 900 },
|
||||
{ id: "product-documents-annotations--desktop-orphaned-focused", file: "13-states-orphaned-focused.png", width: 1280, height: 900 },
|
||||
];
|
||||
|
||||
const themeArg = (process.env.SCREENSHOT_THEME || "dark").toLowerCase();
|
||||
const theme = themeArg === "light" ? "light" : "dark";
|
||||
|
||||
for (const story of stories) {
|
||||
const ctx = await browser.newContext({
|
||||
viewport: { width: story.width, height: story.height },
|
||||
deviceScaleFactor: 2,
|
||||
colorScheme: theme,
|
||||
});
|
||||
const page = await ctx.newPage();
|
||||
const url = `${baseUrl}?id=${story.id}&viewMode=story&globals=theme:${theme}`;
|
||||
await page.goto(url, { waitUntil: "networkidle" });
|
||||
await page.evaluate((appliedTheme) => {
|
||||
document.documentElement.classList.toggle("dark", appliedTheme === "dark");
|
||||
document.documentElement.style.colorScheme = appliedTheme;
|
||||
}, theme);
|
||||
// Allow async query prefill + the layer's interval-driven layout pass to settle.
|
||||
await page.waitForTimeout(900);
|
||||
const out = path.join(outDir, story.file);
|
||||
await page.screenshot({ path: out, fullPage: false });
|
||||
console.log("wrote", out);
|
||||
await ctx.close();
|
||||
}
|
||||
} finally {
|
||||
await browser.close();
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||