diff --git a/src/lib/components/Toolbar.svelte b/src/lib/components/Toolbar.svelte index cf856e8..310232b 100644 --- a/src/lib/components/Toolbar.svelte +++ b/src/lib/components/Toolbar.svelte @@ -502,8 +502,13 @@ /* Sits below the scrolling gallery (margins cancel the dropdown's padding) so it is reachable without scrolling to the last style. */ - .manage { + /* Qualified with .ol-option: that rule sits further down the sheet, so at equal + specificity its width/padding/hover would win over this one's. */ + .ol-option.manage { flex-shrink: 0; + /* auto, so the negative margins bleed the row to both panel edges instead of + pushing a 100%-wide box 4px past the right one. */ + width: auto; margin: 2px -2px -2px; padding: 0.45rem 0.6rem; gap: 0.45rem; @@ -520,7 +525,7 @@ flex-shrink: 0; } - .manage:hover { + .ol-option.manage:hover { background: color-mix(in srgb, var(--color-primary) 16%, var(--color-surface)); } diff --git a/src/lib/components/ToolbarExpanded.svelte b/src/lib/components/ToolbarExpanded.svelte index 107496d..f5d566e 100644 --- a/src/lib/components/ToolbarExpanded.svelte +++ b/src/lib/components/ToolbarExpanded.svelte @@ -9,8 +9,7 @@ import LinkDialog from './LinkDialog.svelte'; import { OPEN_LINK_DIALOG_EVENT } from '../editor/extensions/link'; import { - CANDIDATE_FONTS, - detectAvailableFonts, + detectInstalledFonts, queryLocalFontsIfAllowed, supportsLocalFontAccess, } from '../utils/fontDetect'; @@ -46,7 +45,6 @@ let recentFonts = $state([]); let detectedFonts = $state([]); let allInstalledFonts = $state(null); - let detectionRan = false; const localFontAccessSupported = typeof window !== 'undefined' && supportsLocalFontAccess(); @@ -64,19 +62,8 @@ try { localStorage.setItem(RECENT_FONTS_KEY, JSON.stringify(fonts)); } catch { /* quota or disabled */ } } - // The bundled metric-twin @font-faces (Calibri/Arial/Cambria/Courier New) only - // load on first use; force them so canvas measurement can see them as available. - const BUNDLED_TWINS = ['Calibri', 'Arial', 'Cambria', 'Courier New']; - async function ensureDetectionRan() { - if (detectionRan) return; - detectionRan = true; - if (typeof document !== 'undefined' && document.fonts) { - try { - await Promise.all(BUNDLED_TWINS.map((f) => document.fonts.load(`12px "${f}"`))); - } catch { /* detect with whatever loaded */ } - } - detectedFonts = detectAvailableFonts(CANDIDATE_FONTS); + detectedFonts = await detectInstalledFonts(); } onMount(() => { diff --git a/src/lib/utils/fontDetect.ts b/src/lib/utils/fontDetect.ts index d200e59..1708c4b 100644 --- a/src/lib/utils/fontDetect.ts +++ b/src/lib/utils/fontDetect.ts @@ -135,6 +135,23 @@ export async function unavailableFonts(families: Iterable): Promise | null = null; + +export function detectInstalledFonts(): Promise { + detection ??= (async () => { + if (typeof document !== 'undefined' && document.fonts) { + try { + await Promise.all(BUNDLED_FONTS.map((f) => document.fonts.load(`12px "${f}"`))); + } catch { /* detect with whatever loaded */ } + } + return detectAvailableFonts(CANDIDATE_FONTS); + })(); + return detection; +} + interface LocalFontData { family: string } interface QueryLocalFontsWindow { queryLocalFonts?: () => Promise;