# 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 `` 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 `` 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: ```js { "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 | ### 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 │ └── 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