# 2.2 — Results Panel **Previous Step:** ← [Editor](../2.1-editor/2.1-editor.md) --- ## Page Metadata | Property | Value | |----------|-------| | **Scenario** | 02 — Calculation Experience | | **Page Number** | 2.2 | | **Platform** | Web (PWA), portable to macOS/Windows | | **Page Type** | Embedded Panel (within App Shell main area) | | **Viewport** | Desktop + tablet (side panel), mobile (bottom tray) | --- ## Overview **Page Purpose:** Display calculation results aligned line-by-line with the editor. Results are the reason the product exists — they must be clear, informative, and subtly styled so they complement the editor without competing for attention. **User Situation:** User is typing in the editor and their eyes flick right to see results. This happens dozens of times per session. The results must be instantly scannable — the eye should find the answer in milliseconds. **Success Criteria:** - Every result line aligns pixel-perfectly with its editor line - Results are readable but visually secondary to the editor - Different result types are distinguishable at a glance - Scroll synchronization is seamless **Entry Points:** - Always visible on desktop/tablet (side panel) - Toggle on mobile (bottom tray) --- ## Layout Structure ### Desktop/Tablet (side panel) ``` ┌──────────────────────────┐ │ │ │ ──── │ ← heading (no result) │ │ ← empty │ ──── │ ← comment (no result) │ 5,000 │ ← number │ 1,200 │ ← number │ 6,200 │ ← expression result │ │ ← empty │ ──── │ ← comment │ 1,500 │ ← number │ 400 │ ← number │ ⚠ error │ ← error (muted, not red) │ │ ← empty │ 1,900 │ ← aggregator result │ 4,300 │ ← expression result │ │ └──────────────────────────┘ Right-aligned, zebra striping matches editor ``` ### Mobile (bottom tray) ``` ┌─────────────────────────────┐ │ ═══ (drag handle) │ 48px collapsed │ Last result: 4,300 │ ├─────────────────────────────┤ │ Ln 5: salary = 5000 │ ← expanded: shows │ Ln 6: freelance = 1200 │ line + result pairs │ Ln 7: total_income = 6200 │ scrollable │ ... │ └─────────────────────────────┘ ``` --- ## Spacing | Property | Token | Pixels | |----------|-------|--------| | Content padding top/bottom | space-sm | 8px (matches editor) | | Result line padding horizontal | space-md | 12px (matches editor) | | Result line height | — | 24px (matches editor exactly) | | Mobile tray collapsed height | — | 48px | | Mobile tray expanded height | — | 40vh | | Mobile drag handle | — | 32px × 4px pill | --- ## Typography | Element | Size | Weight | Typeface | Color | |---------|------|--------|----------|-------| | Numeric result | text-md (15px) | 400 | system mono | var(--result-number) | | Unit value | text-md (15px) | 400 | system mono | var(--result-unit) | | Currency value | text-md (15px) | 400 | system mono | var(--result-currency) | | DateTime result | text-md (15px) | 400 | system mono | var(--result-datetime) | | Boolean result | text-md (15px) | 400 | system mono | var(--result-boolean) | | Error hint | text-xs (13px) | 400 | system sans | var(--text) at 30% opacity | | Non-result lines | — | — | — | Empty (no text rendered) | **Design change from current:** Weight reduced from 600 → 400. Color changed from var(--accent) to type-specific semantic colors. This makes results secondary to the editor content, matching macOS behavior. --- ## Result Type Colors New CSS custom properties per theme: | Token | Light | Dark | Matrix | Purpose | |-------|-------|------|--------|---------| | --result-number | #374151 (gray-700) | #d1d5db (gray-300) | #00ff41 | Plain numbers | | --result-unit | #0d9488 (teal-600) | #5eead4 (teal-300) | #00cc33 | Values with units (5 kg, 3.2 m) | | --result-currency | #d97706 (amber-600) | #fcd34d (amber-300) | #ffff00 | Currency values ($50, €42) | | --result-datetime | #7c3aed (violet-600) | #c4b5fd (violet-300) | #39ff14 | Dates and times | | --result-boolean | #6366f1 (indigo-500) | #818cf8 (indigo-400) | #00ff41 | true/false | | --result-error | var(--text) at 30% | var(--text) at 30% | rgba(#ff0000, 0.3) | Error hint text | **Why type-specific colors:** Users scanning results can instantly distinguish "that's a currency" from "that's a unit" from "that's a date" without reading the value. The colors are muted (not saturated) so they don't compete with the editor. --- ## Result Display Format | Result Type | Display Format | Example | |-------------|----------------|---------| | Number | Formatted with thousand separators | `6,200` | | Unit value | Value + unit abbreviation | `2.2 kg` · `156.2 mi` | | Currency | Symbol + value | `$4,300` · `€3,857.20` | | DateTime | Locale-formatted | `Mar 25, 2026` · `14:30` | | TimeDelta | Human-readable | `3 days, 4 hours` | | Boolean | Lowercase | `true` · `false` | | Comment | Empty line (dash marker) | `────` (subtle horizontal line) | | Heading | Empty line (dash marker) | `────` | | Empty | Empty line | (blank) | | Error | Muted hint | `· error` (tiny, de-emphasized) | | Variable assignment | Show assigned value | `5,000` | **Change from current:** Removed the `= ` prefix before results. Just show the value. Cleaner. ### Comment/Heading Marker | Property | Value | |----------|-------| | Content | `────` (4 em dashes, or CSS border-bottom) | | Color | var(--border) at 50% opacity | | Purpose | Visual separator showing this line has no numeric result | | Width | 60% of panel width, right-aligned | ### Error Hint | Property | Value | |----------|-------| | Content | `· error` or `· invalid` | | Color | var(--text) at 30% opacity | | Purpose | Subtle indicator that something went wrong — details are in the editor gutter | | Font | text-xs (13px), system sans | --- ## Zebra Striping | Property | Value | |----------|-------| | Pattern | Matches editor exactly (same even-line pattern) | | Colors | Same as editor per theme | | Sync | Uses line index, not DOM position, for consistency | --- ## Scroll Synchronization | Property | Value | |----------|-------| | Direction | Editor drives, results follows | | Method | `scrollTop` mirroring via passive scroll listener | | Latency | < 1 frame (requestAnimationFrame if needed) | | Results panel | `overflow-y: hidden` — no independent scrolling | | Edge case | If editor has heading margins (extra space), results panel inserts matching spacers | --- ## Result Hover Interaction **OBJECT ID:** `results-hover` | Property | Value | |----------|-------| | Trigger | Mouse hover over a result line | | Behavior | Show full precision + unit details in tooltip | | Tooltip content | Raw value (full precision), type label, conversion hint | | Example | Hover `$4,300` → "4300.00 USD (United States Dollar)" | | Example | Hover `2.2 kg` → "2.20462 kg (kilogram) · 4.85 lb" | | Style | Same as error tooltip (bg-secondary, border, 4px radius) | | Delay | 500ms hover delay (don't trigger on casual mouse movement) | --- ## Result Click Interaction **OBJECT ID:** `results-click` | Property | Value | |----------|-------| | Trigger | Single click on a result value | | Behavior | Copy raw value to clipboard | | Feedback | Brief flash (0.3s) — result text turns var(--success) then fades back | | Tooltip | "Copied!" appears for 1.5s | | Accessibility | aria-label="Copy result: {value}" | --- ## Mobile Bottom Tray **OBJECT ID:** `results-mobile-tray` ### Collapsed State (48px) | Property | Value | |----------|-------| | Content | Drag handle + last non-empty result value | | Drag handle | 32px × 4px pill, var(--border), centered | | Result text | "Last: {value}" or "No results" if empty | | Font | text-xs, var(--text) | | Background | var(--bg-secondary) | | Border | top 1px solid var(--border) | | Interaction | Tap or swipe up → expand | ### Expanded State (40vh) | Property | Value | |----------|-------| | Content | Scrollable list of all line results paired with their expressions | | Item format | `Ln {n}: {expression} → {result}` | | Item height | 36px (larger for touch) | | Active line | Highlighted with var(--accent-bg) | | Tap result | Copy to clipboard (same as desktop click) | | Interaction | Swipe down → collapse. Tap backdrop → collapse. | | Scroll | Independent scroll (not synced with editor in mobile) | ### Transitions | Property | Value | |----------|-------| | Expand/collapse | 200ms ease-out | | Spring | Optional subtle overshoot on expand | --- ## Page States | State | When | Results Display | |-------|------|-----------------| | **Normal** | Engine ready, results computed | Type-colored values per line | | **Engine loading** | WASM initializing | All result lines show `—` in var(--text) at 20% | | **Empty document** | No lines in editor | Panel is blank | | **All errors** | Every line has errors | All lines show muted `· error` hints | | **Stale results** | Document changed, eval pending | Previous results stay visible (no flash/flicker) | --- ## Accessibility | Feature | Implementation | |---------|---------------| | ARIA | `role="complementary"`, `aria-label="Calculation results"` | | Live updates | `aria-live="polite"` on result container — announces new results | | Screen reader | Each result: `aria-label="Line {n}: {expression} equals {result}"` | | Color-blind | Result types distinguishable by position + format, not just color | | Click feedback | `aria-label="Copied"` announced on clipboard copy | | Reduced motion | No flash animation; instant color change for copy feedback | --- ## Technical Notes - **Result alignment:** Line height must match editor exactly (24px). If editor adds heading margins, results panel must add matching spacer divs. - **Rendering:** ResultsPanel receives `EngineLineResult[]` from useEngine hook. Re-renders only changed lines (React key by line index). - **Copy to clipboard:** Use `navigator.clipboard.writeText()`. Fall back to textarea trick for older browsers. - **Hover tooltip positioning:** Position below the result line, right-aligned with panel. Flip above if near viewport bottom. - **Mobile tray:** Use CSS `transform: translateY()` for smooth expand/collapse. Touch events for swipe gesture. - **Cross-platform:** Side panel → native split view (macOS/Windows). Mobile tray → not applicable on desktop native. --- ## Open Questions | # | Question | Context | Status | |---|----------|---------|--------| | 1 | Should heading lines in results show `────` markers? | Helps visual alignment but adds visual noise | 🔴 Open | | 2 | Should copy-on-click copy formatted or raw value? | `$4,300` vs `4300` | 🟡 — Likely raw (more useful for pasting) | | 3 | Result hover tooltip — show conversion alternatives? | "2.2 kg · 4.85 lb" on hover | 🟢 Resolved: Yes, useful for unit/currency results | --- **Previous Step:** ← [Editor](../2.1-editor/2.1-editor.md) --- _Created using Whiteport Design Studio (WDS) methodology_