96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # 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`.
 |