Files
codium_nostr_extension/plans/sidebar-aesthetics.md
T
2026-07-27 19:01:14 -04:00

160 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sidebar Aesthetics Plan
Apply the design rules from `~/lt/aesthetics/WEB.md` to the Nostr sidebar webview in [`src/ui/sidebar.ts`](../src/ui/sidebar.ts:1).
## Context
`WEB.md` defines a minimalist web aesthetic:
- **Monochrome first**: black, white, one red accent, plus one muted grey. No other hues.
- **Monospaced by default**: one fixed-width family for body, buttons, inputs, labels.
- **Minimal CSS surface**: few variables, few classes, reuse shell styles.
- **Readable over clever**: 1px borders, single radius token, no gradients/shadows as decoration.
- **Grayscale media**: images desaturated at rest, color returns on hover.
- **Dark mode = swapped variables**, not swapped styles.
- **Spacing ladder**: 5, 10, 15, 20, 40 px only.
- **Transitions**: 0.2s for interactive feedback; 0.5s max for slide-outs.
- **Accessibility**: tab-reachable, accent focus ring, alt text, reduced-motion respected.
The current sidebar is a VS Code webview that leans on `--vscode-*` theme variables with a generic VS Code look: mixed monospace/sans, blue-ish buttons, 2px radii, ad-hoc spacing (6px, 8px, 12px, 16px), no grayscale on avatars, no transitions.
## Reconciliation: WEB.md tokens vs VS Code theme
The sidebar lives inside VS Code, so it must respect the user's light/dark theme. We map the WEB.md four-token palette onto VS Code theme variables so the monochrome+accent system still tracks the active theme:
| WEB.md token | Sidebar value |
|---------------------|------------------------------------------------------------|
| `--primary-color` | `var(--vscode-foreground)` |
| `--secondary-color` | `var(--vscode-sideBar-background)` |
| `--accent-color` | `var(--vscode-statusBarItem-errorBackground, #ff0000)` — red, used only for hover/active/focus/destructive |
| `--muted-color` | `var(--vscode-descriptionForeground)` |
| `--border-color` | `var(--vscode-panel-border, var(--muted-color))` |
This keeps the "monochrome + one red scalpel" intent while remaining theme-aware. The accent resolves to red in most themes; where a theme overrides the error background we still get a single semantic accent.
## Changes
All changes are confined to the inline `<style>` and HTML structure inside [`NostrSidebarProvider.getHtml()`](../src/ui/sidebar.ts:196). No host-side TypeScript logic changes are required.
### 1. Variable block (`:root`)
Replace the current ad-hoc `:root` with the reconciled token set plus the WEB.md minimums:
- `--font-family: var(--vscode-editor-font-family), "Courier", monospace;` (monospace everywhere)
- `--primary-color`, `--secondary-color`, `--accent-color`, `--muted-color`, `--border-color` as in the table above.
- `--border-radius: 5px;` (single token, replaces the current 2px)
- `--border-width: 1px;` and `--border: var(--border-width) solid var(--border-color);`
- `--avatar-size-md: 32px;` (identity avatar)
- `--image-grayscale: 100%;` and `--image-grayscale-hover: 20%;`
- Spacing ladder documented as a comment: `5, 10, 15, 20, 40`.
### 2. Typography
- `* { font-family: var(--font-family); box-sizing: border-box; }`
- Body uses `var(--font-family)` and `var(--vscode-font-size)`.
- Section headings (`h2`) keep `11px`, `font-weight: 600`, uppercase, `letter-spacing: 0.5px`, color `var(--muted-color)` — already close to WEB.md's "UI chrome 14px / compact 12px" guidance; we keep 11px for the uppercase label style.
- Relay URLs and npub already use the editor font; ensure all inputs/buttons/selects also inherit `var(--font-family)`.
### 3. Buttons
Adopt the WEB.md `.btn` model adapted to the sidebar's full-width buttons:
- Default: `color: var(--primary-color); background: var(--secondary-color); border: 1px solid var(--primary-color); border-radius: var(--border-radius); padding: 8px 10px; font-weight: bold; cursor: pointer; transition: border-color 0.2s, background-color 0.2s, color 0.2s;`
- `:hover` → `border-color: var(--accent-color);` (never fill red on hover).
- `:active` → `background: var(--accent-color); color: var(--secondary-color); border-color: var(--accent-color);`
- `:disabled` → `opacity: 0.5; cursor: not-allowed;` (no recolor).
- `.secondary` → swap to muted border: `border-color: var(--muted-color); color: var(--muted-color);` hover still goes to accent border.
- Remove the old `--btn-bg`/`--btn2-bg` blue button styling.
### 4. Inputs / select
- Share border, radius, padding with buttons so they line up.
- `border: var(--border); border-radius: var(--border-radius); padding: 8px 10px; background: var(--vscode-inputBackground); color: var(--vscode-inputForeground);`
- `:focus` → `outline: none; border-color: var(--accent-color);` (accent focus ring, per WEB.md §7 and §14).
- Labels (`.field-label`) stay muted grey, above inputs, smaller than input text.
### 5. Avatar / images
- Global `img { filter: grayscale(var(--image-grayscale)); transition: filter 0.2s; }` and `img:hover { filter: grayscale(var(--image-grayscale-hover)); }`.
- `.avatar` and `.avatar-placeholder` use `--avatar-size-md: 32px`, `border-radius: var(--border-radius)` by default (square-with-radius per WEB.md §8; round variant only if we later opt in via `999px`).
- Avatar `alt` text set to the profile name or `"avatar"` (currently `alt="avatar"` — keep, but prefer name when available).
### 6. Spacing normalization
Migrate current values onto the ladder:
| Current | New |
|--------|-----|
| `margin-bottom: 16px` (section) | `20px` |
| `margin: 0 0 8px 0` (h2) | `0 0 10px 0` |
| `padding: 6px 10px` (button) | `8px 10px` |
| `margin-bottom: 6px` (button) | `10px` |
| `padding: 4px 6px` (input) | `8px 10px` |
| `margin: 4px 0 2px` (label) | `5px 0` |
| `padding: 12px` (body) | `10px` (or `15px`) |
| `gap: 6px` (relay row) | `10px` |
| `gap: 8px` (identity row) | `10px` |
### 7. Relay list and identity block
- Relay rows: keep flex row, `gap: 10px`, `padding: 5px 0`, monospace URL with `text-overflow: ellipsis; white-space: nowrap;` (already present).
- Identity block: treat as a single card — `border: var(--border); border-radius: var(--border-radius); padding: 10px; margin-bottom: 15px;` containing the avatar row, name, npub, backend label, and Sign Out button. This matches WEB.md §9 card conventions (1px border, 5–10px radius, 12px-ish padding, vertical flex).
- Empty-state text stays italic muted grey (WEB.md allows italic for empty-state).
### 8. Transitions and reduced motion
- Add `transition: border-color 0.2s, background-color 0.2s, color 0.2s, filter 0.2s;` to buttons, inputs, checkboxes, and images.
- Add `@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }`.
### 9. Accessibility pass
- Ensure every button/input/select has visible focus: accent border on inputs; for buttons add `:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 1px; }`.
- Relay checkboxes remain native (WEB.md §7: don't reinvent).
- Confirm tab order: Actions → Relays → Fetch button → Identity fields → Sign In/Out.
- Avatar `alt` text uses profile name when available, else `"avatar"`.
### 10. CSP
No CSP change needed. `style-src 'unsafe-inline'` already permits the inline styles; `img-src https: data:` already permits avatar loading. We are not adding any external resources.
## Out of scope
- No changes to host-side message handling, state shape, or commands.
- No new files; everything stays in [`sidebar.ts`](../src/ui/sidebar.ts:1).
- No layout shell refactor (the sidebar is a single pane, not the five-region web shell from WEB.md §4 — that section informs token choices, not structure).
- No dark-mode class toggle: VS Code drives light/dark via theme variables, which our token mapping already honors.
## Verification
1. Build the extension (`npm run build` via [`esbuild.mjs`](../esbuild.mjs:1)) and load it in VS Code.
2. Open the Nostr sidebar and confirm:
- All text is monospaced.
- Buttons are outlined monochrome; hover shows red border; click flashes red fill.
- Inputs show red border on focus.
- Avatar (when signed in with a profile picture) is grayscale until hover.
- Spacing feels even (no 6/8/12/16 oddities).
- Disabled buttons are dimmed, not recolored.
3. Toggle a light and a dark VS Code theme; confirm the palette tracks correctly and the accent stays red.
4. Tab through the sidebar; confirm visible focus rings and logical order.
5. Enable OS reduced-motion; confirm no transitions animate.
## Mermaid overview
```mermaid
flowchart LR
A[WEB.md rules] --> B[Token mapping]
B --> C[Typography: monospace]
B --> D[Buttons: outline + red hover/active]
B --> E[Inputs: accent focus]
B --> F[Avatar: grayscale + hover reveal]
B --> G[Spacing ladder 5/10/15/20/40]
B --> H[Transitions 0.2s + reduced-motion]
C --> I[sidebar.ts inline style + HTML]
D --> I
E --> I
F --> I
G --> I
H --> I
I --> J[Build + manual verify in VS Code]
```