diff --git a/src/entities/Font/ui/FontApplicator/FontApplicator.svelte b/src/entities/Font/ui/FontApplicator/FontApplicator.svelte
index 15dd0d9..f724e94 100644
--- a/src/entities/Font/ui/FontApplicator/FontApplicator.svelte
+++ b/src/entities/Font/ui/FontApplicator/FontApplicator.svelte
@@ -20,6 +20,10 @@ interface Props {
* Font id to load
*/
id: string;
+ /**
+ * Font weight
+ */
+ weight?: number;
/**
* Additional classes
*/
@@ -30,7 +34,7 @@ interface Props {
children?: Snippet;
}
-let { name, id, className, children }: Props = $props();
+let { name, id, weight = 400, className, children }: Props = $props();
let element: Element;
// Track if the user has actually scrolled this into view
@@ -40,7 +44,7 @@ $effect(() => {
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
hasEnteredViewport = true;
- appliedFontsManager.touch([id]);
+ appliedFontsManager.touch([{ slug: id, weight }]);
// Once it has entered, we can stop observing to save CPU
observer.unobserve(element);
@@ -50,7 +54,7 @@ $effect(() => {
return () => observer.disconnect();
});
-const status = $derived(appliedFontsManager.getFontStatus(id));
+const status = $derived(appliedFontsManager.getFontStatus(id, weight, false));
// The "Show" condition: Element is in view AND (Font is ready OR it errored out)
const shouldReveal = $derived(hasEnteredViewport && (status === 'loaded' || status === 'error'));
diff --git a/src/features/DisplayFont/ui/FontComparer/FontComparer.svelte b/src/features/DisplayFont/ui/FontComparer/FontComparer.svelte
index 7a3238b..287f206 100644
--- a/src/features/DisplayFont/ui/FontComparer/FontComparer.svelte
+++ b/src/features/DisplayFont/ui/FontComparer/FontComparer.svelte
@@ -1,5 +1,6 @@
@@ -22,7 +23,13 @@ $effect(() => {
{#if fontA && fontB}
-
+
+
{/if}
{/if}
diff --git a/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte b/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte
index 872e11c..fa506f2 100644
--- a/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte
+++ b/src/features/DisplayFont/ui/FontSampler/FontSampler.svelte
@@ -7,6 +7,7 @@ import {
FontApplicator,
type UnifiedFont,
} from '$entities/Font';
+import { controlManager } from '$features/SetupFont';
import { ContentEditable } from '$shared/ui';
interface Props {
@@ -31,6 +32,8 @@ let {
text = $bindable(),
...restProps
}: Props = $props();
+
+const weight = $derived(controlManager.weight ?? 400);
diff --git a/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts b/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts
index 6c2f458..6eca284 100644
--- a/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts
+++ b/src/shared/lib/helpers/createCharacterComparison/createCharacterComparison.svelte.ts
@@ -19,6 +19,7 @@ export function createCharacterComparison(
text: () => string,
fontA: () => { name: string; id: string },
fontB: () => { name: string; id: string },
+ weight: () => number,
) {
let lines = $state([]);
let containerWidth = $state(0);
@@ -29,14 +30,16 @@ export function createCharacterComparison(
* @param text - Text string to measure
* @param fontFamily - Font family name
* @param fontSize - Font size in pixels
+ * @param fontWeight - Font weight
*/
function measureText(
ctx: CanvasRenderingContext2D,
text: string,
fontFamily: string,
fontSize: number,
+ fontWeight: number,
): number {
- ctx.font = `bold ${fontSize}px ${fontFamily}`;
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
return ctx.measureText(text).width;
}
@@ -62,6 +65,7 @@ export function createCharacterComparison(
* @param container - The container element to measure width from
* @param measureCanvas - The canvas element used for text measurement
*/
+
function breakIntoLines(
container: HTMLElement | undefined,
measureCanvas: HTMLCanvasElement | undefined,
@@ -70,15 +74,14 @@ export function createCharacterComparison(
const rect = container.getBoundingClientRect();
containerWidth = rect.width;
-
// Padding considerations - matches the container padding
const padding = window.innerWidth < 640 ? 48 : 96;
const availableWidth = rect.width - padding;
-
const ctx = measureCanvas.getContext('2d');
if (!ctx) return;
const fontSize = getFontSize();
+ const currentWeight = weight(); // Get current weight
const words = text().split(' ');
const newLines: LineData[] = [];
let currentLineWords: string[] = [];
@@ -86,9 +89,9 @@ export function createCharacterComparison(
function pushLine(words: string[]) {
if (words.length === 0) return;
const lineText = words.join(' ');
- // Measure width to ensure we know exactly how wide this line renders
- const widthA = measureText(ctx!, lineText, fontA().name, fontSize);
- const widthB = measureText(ctx!, lineText, fontB().name, fontSize);
+ // Measure both fonts at the CURRENT weight
+ const widthA = measureText(ctx!, lineText, fontA().name, fontSize, currentWeight);
+ const widthB = measureText(ctx!, lineText, fontB().name, fontSize, currentWeight);
const maxWidth = Math.max(widthA, widthB);
newLines.push({ text: lineText, width: maxWidth });
}
@@ -97,10 +100,9 @@ export function createCharacterComparison(
const testLine = currentLineWords.length > 0
? currentLineWords.join(' ') + ' ' + word
: word;
-
// Measure with both fonts and use the wider one to prevent layout shifts
- const widthA = measureText(ctx, testLine, fontA().name, fontSize);
- const widthB = measureText(ctx, testLine, fontB().name, fontSize);
+ const widthA = measureText(ctx, testLine, fontA().name, fontSize, currentWeight);
+ const widthB = measureText(ctx, testLine, fontB().name, fontSize, currentWeight);
const maxWidth = Math.max(widthA, widthB);
if (maxWidth > availableWidth && currentLineWords.length > 0) {
@@ -111,10 +113,7 @@ export function createCharacterComparison(
}
}
- if (currentLineWords.length > 0) {
- pushLine(currentLineWords);
- }
-
+ if (currentLineWords.length > 0) pushLine(currentLineWords);
lines = newLines;
}