ObsiViewer/docs/ui-theming.md

96 lines
3.5 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.

# UI Theming and CM6 Highlight
## Theme Variables
- **Global tokens** (in `src/styles.css`):
- `--color-accent` main accent color (per-theme override via `[data-theme]`).
- `--cm-hl-bg` computed background for inline highlights (theme dependent).
- `--cm-hl-br` border radius for highlights (default 3px).
- **Button tokens**:
- `--btn-radius`, `--btn-padding-y`, `--btn-padding-x`, `--btn-font`, `--btn-shadow`, `--btn-ring`, `--btn-speed`.
- `--btn-bg`, `--btn-fg`, `--btn-bg-hover`, `--btn-bg-active`, `--btn-outline`.
### Defaults
```css
:root {
--color-accent: #3b82f6;
--cm-hl-bg: color-mix(in srgb, var(--color-accent) 28%, transparent);
--cm-hl-br: 3px;
}
[data-theme="dark"], .dark {
--cm-hl-bg: color-mix(in srgb, var(--color-accent) 22%, transparent);
}
[data-theme="nimbus"] { --color-accent: #7c3aed; }
[data-theme="emerald"] { --color-accent: #10b981; }
```
## CodeMirror 6 Highlight Extensions
Files in `src/app/shared/editor/extensions/`:
- `highlight-occurrences.extension.ts` inline dynamic occurrences via regex.
- `ranged-highlights.extension.ts` ranged highlights via `StateEffect`/`StateField`.
- `markdown-theme-highlight.extension.ts` composes ranged + Markdown `HighlightStyle` and facet-driven CSS variable.
### CSS class
- `.cm-md-highlight { background: var(--cm-hl-bg); border-radius: var(--cm-hl-br, 3px); transition: background var(--btn-speed) ease; }`
## Angular Integration
Service: `EditorHighlightService` (`src/app/shared/editor/editor-highlight.service.ts`)
- `extensions: Extension[]` base markdown theme highlight extensions to add at editor creation.
- `occurrencesExtension(pattern)` build occurrences extension.
- `applyOccurrences(view, compartment, pattern)` reconfigure a `Compartment` with occurrences.
- `setRanges(view, ranges)` / `clearRanges(view)` ranged highlights via effects.
- `facet()` access the facet to optionally override `--cm-hl-bg` per-view.
Example inside editor component:
```ts
// compartments
occurrencesCompartment = new Compartment();
highlightFacetCompartment = new Compartment();
// in EditorState.create extensions
...highlightService.extensions,
occurrencesCompartment.of([]),
highlightFacetCompartment.of([]),
// API usage
highlightOccurrences("TODO");
setHighlights([{ from: 10, to: 24 }]);
clearHighlights();
// optional color override
view.dispatch({ effects: highlightFacetCompartment.reconfigure([ highlightService.facet().of('color-mix(in srgb, var(--color-accent) 40%, transparent)') ])});
```
Live theme changes are applied by reconfiguring the theme compartment and calling `EditorView.requestMeasure(...)` to refresh decorations that rely on CSS variables.
## Button Utilities
Classes in `src/styles.css`:
- Base: `btn`
- Variants: `btn-solid`, `btn-outline`, `btn-ghost`
- Sizes: `btn-sm`, `btn-md`, `btn-lg`
Example:
```html
<button class="btn btn-solid btn-sm">Save</button>
<button class="btn btn-outline btn-sm">Cancel</button>
<button class="btn btn-ghost btn-sm" aria-label="Close"></button>
```
## Accessibility
- Buttons use focus ring via `--btn-outline`.
- Ensure icon-only buttons have `aria-label`.
## Performance Notes
- Occurrence highlights compute decorations only over visible ranges; cost is O(visibleText) per viewport update.
- Ranged highlights use a `StateField` and `tr.changes.mapPos` to keep ranges aligned after edits; updates are incremental.
- For large docs (≥5k lines), prefer ranged highlights for bulk operations; occurrences are fine for quick regex patterns like `TODO`.