Files
Outcut/docs/superpowers/specs/2026-04-23-outlook-relook-design.md
Joel Brock 984bfd6cb9 feat: add Gmail-style keyboard navigation to spec and plan
Task 14: keyboard.js with focus cursor, multi-select, and action
keys (j/k navigate, x/Space select, # delete, e archive, Shift+i/u
read/unread, v move). New keyboardMultiSelect setting and CSS.
2026-04-23 08:46:24 -07:00

12 KiB

Outlook Relook — Design Spec

Chrome extension that reskins Outlook Web App (outlook.office.com) with a minimalist, clutter-free aesthetic and granular user control over every visual and behavioral tweak.

Target

  • Primary: outlook.office.com (Microsoft 365)
  • Also affects the Outlook PWA (same web app, same DOM)

Architecture

Manifest V3 Chrome extension with four layers:

  1. Theme CSS — swappable stylesheets that override OWA's visual identity
  2. MutationObserver — watches OWA's DOM and suppresses unwanted elements as they appear
  3. Behavior JS — lightweight patches for UX annoyances (auto-advance, hover suppression, etc.)
  4. Settings popup — granular toggle panel, persists to chrome.storage.sync

Data Flow

popup.js  --chrome.storage.sync-->  content.js  --injects-->  OWA DOM
                                        |
                                  observer.js  --watches-->  OWA DOM mutations
                                        |
                                  behavior.js  --patches-->  OWA event handlers

Communication

  • chrome.storage.sync for persisting all user preferences (syncs across devices)
  • chrome.runtime.onMessage / chrome.tabs.sendMessage for real-time popup-to-content-script communication (theme switches, toggle changes apply immediately without page reload)

Theme System

Base Layer (base.css)

Applied regardless of active theme. Handles universal spacing and density overrides:

  • Collapse vertical chrome: reduce top bar height, command bar padding, folder headers
  • Tighten message list row height and padding
  • Tighten reading pane header and action bar
  • Remove decorative spacing between sections
  • Narrow date column in message list
  • Cap reading pane line length with max-width on email body container

Swiss Theme (swiss.css)

  • Monochrome palette: pure white background, black text, one configurable accent color
  • Helvetica Neue / Arial font stack
  • No shadows, no rounded corners, no gradients
  • Tight grid spacing, high content density
  • Thin 1px borders only where needed for structure
  • Folder pane: minimal, no icons, text-only with indent hierarchy
  • Single-line-per-message option for maximum density

Material Theme (material.css)

  • Light gray surface hierarchy (white > #f5f5f5 > #eeeeee)
  • Roboto / system font stack
  • Subtle elevation: 1-2px shadows on cards/panels only
  • Rounded corners (4px) on interactive elements
  • Material-style accent color (default: blue 500, configurable)
  • Comfortable density: more breathing room than Swiss, still tighter than stock OWA

Color Scheme

Each theme has light and dark variants defined via CSS custom properties at :root. A data-outlook-relook-scheme="light|dark" attribute on <html> controls the active variant. Three modes in settings: Light, Dark, System (follows OS preference via prefers-color-scheme media query).

Theme Switching

Changing the theme in the popup swaps the injected <link> stylesheet immediately (no page reload). base.css always stays loaded. Each theme file is self-contained with no cross-theme dependencies, making it easy to add Brutalist, Modern SaaS, or other themes later.

Selector Strategy

OWA uses obfuscated/generated class names that change with every deployment. The extension uses a resilience-ordered selector approach.

Priority Order (most to least stable)

  1. aria-label and role attributes
  2. data-* attributes (Microsoft's internal attributes)
  3. Structural selectors (positional relationships, nesting depth)
  4. Text content matching (JS-based, find elements by inner text)
  5. Class name patterns (last resort)

Selector Registry (selectors.js)

Central map of logical element names to selector strategies:

{
  "copilot-button": {
    primary: '[aria-label*="Copilot"]',
    fallbacks: ['[data-app-id*="copilot"]']
  },
  "suggested-replies": {
    primary: '[role="group"][aria-label*="Suggested"]',
    fallbacks: ['...structural selector...']
  }
}

Each entry has a primary selector and ordered fallbacks. The observer tries them in sequence.

Self-Healing

When a primary selector stops matching after an OWA update, the extension logs a console warning and tries fallbacks. Future iteration could surface "X toggle may be broken" in the popup.

Settings Panel

The popup UI is organized into 6 categories. All settings persist via chrome.storage.sync.

Theme & Appearance

Toggle Type Default
Theme Dropdown: Swiss / Material Swiss
Color scheme Radio: Light / Dark / System System
Accent color Color picker Theme default

Density & Spacing

Toggle Type Default
Density preset Dropdown: Comfortable / Compact / Ultra-compact Compact
Compact top bar Boolean On
Compact command bar / ribbon Boolean On
Compact message list rows Boolean On
Compact reading pane header Boolean On
Compact folder pane Boolean On
Narrow date column Boolean On
Compress compose toolbar Boolean On
Reading pane max-width Boolean On

Changing the density preset sets all individual density toggles to the preset's values. The user can then individually override any of them afterward. Subsequent preset changes reset all individual toggles again.

Hide Elements

Toggle Type Default
Copilot button, pane, and inline compose suggestions Boolean On
Suggested replies Boolean On
Promotional banners (Try new Outlook, Upgrade, Get the app) Boolean On
Focused / Other inbox tabs Boolean On
Left sidebar app icons (Calendar, People, To Do) Boolean Off
Groups section in folder pane Boolean Off
My Day / right-side panel toggle buttons Boolean On
Sender avatars in message list Boolean Off
Feature discovery tooltips / "what's new" callouts Boolean On
Viva Insights / Daily Briefing cards Boolean On
"Unread in Other" Focused Inbox banner Boolean On
Activity feed / "Someone mentioned you" banners Boolean On

Readability

Toggle Type Default
Unread message distinction (bold + left border) Boolean On
Preview text on its own line Boolean Off
Normalize font weight across density modes Boolean On
Dark mode email body fix Boolean On
Message list font size Dropdown: Small / Medium / Large Medium

Behavior

Toggle Type Default
Auto-collapse ribbon on page load Boolean On
Remember sidebar collapsed/expanded state Boolean On
Suppress contact card hover popups Boolean On
Auto-advance to next email after delete Boolean On
Auto-dismiss notification toasts Dropdown: Off / 3s / 5s / 10s 5s
Reposition toast notifications Dropdown: Bottom-left / Top-right Top-right
Sticky Reply/Forward bar on scroll Boolean On
Auto-resize compose window Boolean On
Throttle desktop notifications Boolean Off

Keyboard Navigation

Gmail-style keyboard navigation and multi-select for the message list. OWA lacks the ability to select multiple messages and act on them purely from the keyboard — this is the single biggest functionality gap vs Gmail.

Toggle Type Default
Keyboard multi-select mode Boolean On

Key bindings (active when message list is focused, not during compose):

Key Action
j / Down Arrow Move focus to next message
k / Up Arrow Move focus to previous message
x or Space Toggle select on focused message (multi-select)
Shift+j / Shift+Down Select and move to next (extend selection)
Shift+k / Shift+Up Select and move to previous (extend selection)
# Delete selected message(s)
e Archive selected message(s)
Shift+i Mark selected as read
Shift+u Mark selected as unread
v Move selected (open OWA's move-to-folder dialog)
Escape Deselect all
Enter / o Open focused message in reading pane

Implementation approach:

  • The extension manages its own "focus cursor" on the message list, visually distinguished from OWA's native selection (e.g., a left-border highlight or subtle background tint)
  • A Set tracks "checked" (multi-selected) message elements, visually marked with a checkbox indicator or distinct background
  • Action keys (#, e, Shift+i, etc.) iterate over checked messages and dispatch OWA's native actions for each (via toolbar button clicks, context menu triggers, or keyboard shortcut forwarding)
  • If no messages are checked, actions apply to the currently focused message (single-select behavior, matching Gmail)
  • All keyboard handling is suppressed when a compose window, search bar, or dialog has focus — detected via activeElement checks
  • A new file content/keyboard.js encapsulates all keyboard navigation logic, separate from behavior.js

Quick Actions (injected UI)

Toggle Type Default
"Mark all as read" button on folder headers Boolean On
Quick folder jump (keyboard shortcut) Boolean On

Info

  • Extension version display
  • Reset to defaults button
  • Export / Import settings (JSON)

File Structure

outlook-relook/
├── manifest.json
├── popup/
│   ├── popup.html
│   ├── popup.js
│   └── popup.css
├── content/
│   ├── content.js             # Entry: injects CSS, starts observer, listens for messages
│   ├── observer.js            # MutationObserver logic, element suppression
│   ├── selectors.js           # Selector registry (logical name -> strategies)
│   ├── behavior.js            # JS behavior tweaks
│   ├── keyboard.js            # Gmail-style keyboard navigation & multi-select
│   └── injector.js            # DOM injection (mark-all-read, folder jump)
├── themes/
│   ├── base.css               # Shared density/spacing/hiding overrides
│   ├── swiss.css              # Swiss theme (light + dark variants)
│   └── material.css           # Material theme (light + dark variants)
├── icons/
│   ├── icon-16.png
│   ├── icon-48.png
│   └── icon-128.png
├── selectors-test.html        # Snapshot DOM fragments for selector testing
└── README.md

Tech Stack

  • Vanilla JS — no framework, no build step
  • CSS custom properties for theming
  • chrome.storage.sync for settings persistence
  • chrome.runtime.onMessage for popup-content script communication
  • ES modules via Manifest V3 content script support (if needed later)

No node_modules, no transpilation, no bundler. Edit-reload-refresh dev loop.

Development & Testing

Local Development

  1. chrome://extensions -> Developer Mode -> Load unpacked -> point to project root
  2. Edit files -> click Reload on extension card
  3. Refresh OWA tab to see changes
  4. Popup changes visible immediately by closing/reopening

Testing

  • Manual testing against live OWA — primary method
  • selectors-test.html — static HTML with OWA DOM snapshots for offline selector verification
  • Console logging — observer and selector engine log warnings on selector failures

No automated test suite. For a personal extension targeting third-party DOM, automated tests would be brittle and low-value.

Versioning

  • Semantic versioning in manifest.json
  • Git tags for releases if/when publishing to Chrome Web Store

Future Expansion

The architecture supports straightforward additions:

  • New themes: add a CSS file to themes/, add an option to the theme dropdown
  • New toggles: add an entry to the settings config, add a CSS rule or observer selector
  • New behavior patches: add a function to behavior.js gated by a setting
  • Brutalist theme: monospace, high contrast, maximum density
  • Modern SaaS theme: Linear/Superhuman-inspired, subtle animations
  • Chrome Web Store publishing: add screenshots, store description, privacy policy