160 lines
8.9 KiB
Markdown
160 lines
8.9 KiB
Markdown
# 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]
|
||
```
|