# Badge Polish: Gear Animation + Custom Color Picker — Design Spec
**Date:** 2026-08-26
**Status:** Draft
**Parent spec:** `2026-08-26-inline-color-popover-design.md`
## Overview
Two improvements to the inline color popover and badge system:
1. **Gear icon animation** — remove the permanent padding gap on subreddit badges. The badge grows on hover to reveal the gear, then shrinks back.
2. **Custom color picker** — replace all native `` elements (which delegate to the macOS system picker) with an inline SV+Hue picker widget built in vanilla JS/canvas.
## Improvement 1: Gear Icon Animation
### Current Behavior
`.rt-badge--subreddit` has `padding-right: 18px` at all times, reserving space for the gear icon even when it's hidden. This wastes ~12px on every subreddit badge.
### New Behavior
The subreddit badge uses `padding-right: 6px` at rest (matching the left padding). On hover, `padding-right` transitions to `18px` over 150ms, smoothly expanding the badge to reveal the gear icon. The gear's opacity transition (0 → 0.6, 150ms) runs in parallel. When the mouse leaves, both transitions reverse — the gear fades out and the badge shrinks.
The adjacent comments badge shifts right during the expansion. This is natural inline-block flow and at 150ms feels intentional rather than jittery.
### CSS Changes
```css
.rt-badge--subreddit {
position: relative;
padding-right: 6px;
transition: padding-right 0.15s;
/* background, border-color, color unchanged */
}
.rt-badge--subreddit:hover {
padding-right: 18px;
}
```
The gear icon CSS (`.rt-badge-gear`) is unchanged — it remains `position: absolute; right: 3px` and animates opacity on parent hover.
### File Changes
| File | Change |
|---|---|
| `content/styles/badges.css` | Change `.rt-badge--subreddit` `padding-right` from `18px` to `6px`, add `transition: padding-right 0.15s`, add `.rt-badge--subreddit:hover { padding-right: 18px }`. |
No JS changes required.
---
## Improvement 2: Custom Color Picker Widget
### Problem
The native `` delegates to the OS-level color picker. On macOS, this opens a separate floating panel that is detached from the popover context, has limited precision, and feels foreign to the extension's UI.
### Solution
Replace all `` elements — in both the inline popover and the extension popup — with a custom color picker widget. The picker renders inline within the containing UI (popover or popup), provides full color control, and stays visually consistent with the extension's design.
### Picker Structure — Tabbed Interface
The picker uses three tabs, providing different ways to choose a color:
```
┌──────────────────────────────┐
│ [Palette] [Named] [Custom] │ ← tab bar
├──────────────────────────────┤
│ │
│ (active tab content) │
│ │
├──────────────────────────────┤
│ [■ swatch] #c84a20 │ ← current color + hex input (always visible)
└──────────────────────────────┘
```
The hex text input and a small swatch preview of the current color are always visible below the tab content, regardless of which tab is active. This lets the user see and edit the exact value at all times.
**Tab persistence:** The picker remembers which tab was last used and reopens to that tab. The initial default (before any tab has been selected) is the Palette tab.
### Tab 1: Palette (Tailwind/shadcn Colors)
A grid of color swatches from the Tailwind CSS / shadcn color palette. The palette is organized by hue family (rows) with shades as columns.
**Hue families (rows):** red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose. Gray-scale families (slate, gray, zinc, neutral, stone) are grouped in a separate section at the top or bottom.
**Shades (columns):** 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 (11 per row).
**Layout:** Each swatch is a small square (~16×16px). The grid is scrollable vertically within a fixed-height container (~180px) to avoid the picker growing too tall. Hue family labels appear as small text on the left of each row, or omitted if space is tight (the colors are self-explanatory when grouped).
**Interaction:** Clicking a swatch immediately selects that color — updates the hex input, the swatch preview, and calls `onChange`. The selected swatch gets a subtle highlight border.
### Tab 2: Named Colors (HTML/CSS Named Colors)
All 148 CSS named colors displayed as labeled swatches in a scrollable grid.
**Layout:** Swatches are ~24×18px with the color name displayed below or beside each swatch in small text (~9px). The grid is sorted alphabetically by default. The container is scrollable within the same fixed height (~180px).
**Interaction:** Same as the palette tab — clicking selects the color immediately.
### Tab 3: Custom (SV+Hue Picker)
The freeform picker for precise color selection.
#### Picker Anatomy
```
┌──────────────────────────────┐
│ ┌──────────────────────┐ │
│ │ │ │ ← SV square (saturation-value)
│ │ [cursor ●] │ │ Click/drag to pick S + V
│ │ │ │ Canvas-rendered for current hue
│ └──────────────────────┘ │
│ ┌──────────────────────────┐ │
│ │ ← hue slider → │ │ ← Hue bar (horizontal rainbow)
│ └──────────────────────────┘ │ Click/drag to change hue
└──────────────────────────────┘
```
#### Color Model
The picker uses HSV internally (hue, saturation, value). HSV maps naturally to the SV square (X = saturation, Y = value) and hue bar (X = hue). Colors are converted to/from hex (`#rrggbb`) for storage, display, and sync with the hex text input.
#### SV Square
A `