🍕 feat(highlight): refined modes + single accent + selection labels#11
Merged
Conversation
Replaces the always-on, six-color, dashed-rainbow highlight pass with a
restrained four-mode model that defaults to "selection only" — closer to
Chrome DevTools' element inspector and a much friendlier baseline for
content-heavy editorial pages.
Why
---
On a typical New York Magazine page, the previous highlighter painted
every component all the time, in dashed pink/yellow/teal, with width
varying by sibling order. The result on a busy page was visually
overwhelming — three nested components share an edge and you get three
parallel dashes within 6px, with no encoding of *importance*. The
extension was strictly harder to read with than without.
Modes
-----
- off — no ambient outlines anywhere. Hover + selection still
render so click-to-inspect remains visible.
- selection — ambient off, only hovered/selected elements outlined.
NEW DEFAULT.
- editable — ambient outlines on [data-editable] only. Useful for
editorial / PM workflows.
- all — ambient outlines on every component. The "give me the
bird's-eye view" mode.
Visual language
---------------
- Single accent color (tailwind blue-600). State is encoded with width
+ opacity, not hue:
ambient → 1px @ 18% accent
hover → 2px @ 70% accent
selected → 2px @ 100% accent + top-left labelled badge
- Solid outlines (was: dashed/dotted/double). Reads as inspection,
not "draft/error".
- The selection badge is a small pill anchored above the selected box
rendering the component name from a new data-clay-slip-label attr.
- Find-on-page match outline kept as emerald green so it remains a
*different signal* from the regular accent.
How mode gating works
---------------------
The stylesheet keys ambient rules off `html[data-clay-slip-mode]`, so
switching modes is one attribute write — no per-element walking, no
restyle pass. `mode='off'` writes the attribute explicitly so we can
add `[mode="off"]` rules later (e.g. for diagnostics) without code
changes.
Wiring
------
- HighlightMode type added to UserPreferences (default 'selection').
loadPreferences() merges over DEFAULT_PREFERENCES so existing users
get the new default for free without a migration.
- Store gains setHighlightMode + cycleHighlightMode actions; both
persist to chrome.storage.sync. The boolean highlightEnabled state
+ toggleHighlights action are dropped — `mode === 'off'` covers it.
- Header eye button replaced with a HighlightModeMenu (native
<details> popover) showing the four modes + descriptions with
a click-outside-to-close handler for free.
- `h` keyboard shortcut now cycles modes.
- Options page gains a Highlight mode <select> above the existing
intensity slider. The slider's help text is rewritten to explain
the new "master multiplier" role.
Tests
-----
Adds tests/content/highlighter.test.ts (18 cases) covering:
- installHighlightStyles is idempotent and respects pre-set mode
- applyHighlights tags + labels in the right index, skips empty labels
- clearHighlights wipes every attribute we set, leaves data-editable
- setHighlightMode round-trips, falls back to 'selection' on garbage
- setHovered/setSelected toggle exactly one element at a time
- setHighlightOpacity clamps to [0, 1]
113 → 131 tests passing.
Version bump: 2.0.2 → 2.1.0 (UX-significant change, additive prefs).
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
On a typical content-heavy editorial page (e.g. nymag.com), the previous highlighter painted every component, all the time, in dashed pink/yellow/teal, with width varying by sibling order. Three nested components share an edge → three parallel dashes within ~6px. No encoding of importance. The extension was strictly harder to read with than without.
This PR replaces that with a four-mode model defaulting to selection only — closest to Chrome DevTools' element inspector — and a refined visual language built around a single accent color.
Modes
Switch modes:
Visual language
Single accent (tailwind blue-600). State is encoded with width + opacity, not hue. The selection badge is a small pill anchored above the selected box that renders the component's display name, sourced from a new `data-clay-slip-label` attribute via CSS `attr()`.
How mode gating works
The stylesheet keys ambient rules off `html[data-clay-slip-mode]`. Switching modes is one attribute write — no per-element walking, no restyle pass. The `'off'` mode explicitly writes the attribute so we can add `[mode="off"]` diagnostic rules later without code changes.
```css
html[data-clay-slip-mode="all"] [data-clay-slip-color],
html[data-clay-slip-mode="editable"] [data-clay-slip-color][data-editable] {
outline: 1px solid rgba(37, 99, 235, calc(0.18 * var(--clay-slip-outline-opacity))) !important;
outline-offset: -1px !important;
}
```
Wiring
Details
` for the popover (click-outside-to-close, keyboard activation, a11y for free).Tests
New file `tests/content/highlighter.test.ts` (18 cases) covering:
`113 → 131` tests passing.
Version
`2.0.2 → 2.1.0` (UX-significant change, additive preference).
Test plan
Screenshots
The before is in this thread (the multi-color dashed soup on nymag.com). The after will be added once the PR is reloaded locally.
Made with Cursor