feat(ComparisonSlider): rewrite slider labels to include selects for compared fonts

This commit is contained in:
Ilia Mashkov
2026-01-26 12:45:30 +03:00
parent 192ce2d34a
commit 67db6e22a7

View File

@@ -1,37 +1,110 @@
<script lang="ts"> <!--
import type { Snippet } from 'svelte'; Component: Labels
Displays labels for font selection in the comparison slider.
-->
<script lang="ts" generics="T extends { name: string; id: string }">
import {
FontVirtualList,
type UnifiedFont,
} from '$entities/Font';
import FontApplicator from '$entities/Font/ui/FontApplicator/FontApplicator.svelte';
import { displayedFontsStore } from '$features/DisplayFont';
import { buttonVariants } from '$shared/shadcn/ui/button';
import {
Content as SelectContent,
Item as SelectItem,
Root as SelectRoot,
Trigger as SelectTrigger,
} from '$shared/shadcn/ui/select';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
interface Props { interface Props<T> {
fontA: { name: string; id: string }; /**
fontB: { name: string; id: string }; * First font to compare
*/
fontA: T;
/**
* Second font to compare
*/
fontB: T;
/**
* Position of the slider
*/
sliderPos: number; sliderPos: number;
} }
let { fontA, fontB, sliderPos }: Props = $props(); let { fontA, fontB, sliderPos }: Props<T> = $props();
const fontList = $derived(
displayedFontsStore.fonts.filter(font => font.name !== fontA.name && font.name !== fontB.name),
);
function selectFontA(fontId: string) {
const newFontA = displayedFontsStore.getById(fontId);
if (!newFontA) return;
displayedFontsStore.fontA = newFontA;
}
function selectFontB(fontId: string) {
const newFontB = displayedFontsStore.getById(fontId);
if (!newFontB) return;
displayedFontsStore.fontB = newFontB;
}
</script> </script>
<!-- Bottom Labels --> {#snippet fontSelector(
<div class="absolute bottom-6 inset-x-8 sm:inset-x-12 flex justify-between items-center pointer-events-none z-20"> name: string,
<!-- Left Label (Font A) --> id: string,
fonts: UnifiedFont[],
handleChange: (value: string) => void,
)}
<div <div
class="flex flex-col gap-1 transition-opacity duration-300" class="z-50 pointer-events-auto **:bg-transparent"
style:opacity={sliderPos < 10 ? 0 : 1} onpointerdown={(e => e.stopPropagation())}
> >
<span class="text-[0.5rem] font-mono uppercase tracking-widest text-indigo-400" <SelectRoot type="single" onValueChange={handleChange}>
>Baseline</span> <SelectTrigger
<span class="text-xs sm:text-sm font-bold text-indigo-600"> class={cn(buttonVariants({ variant: 'ghost' }), 'border-none, hover:bg-indigo-100')}
{fontB.name} disabled={!fontList.length}
</span> >
<FontApplicator name={name} id={id}>
{name}
</FontApplicator>
</SelectTrigger>
<SelectContent
class="h-60 bg-transparent **:bg-transparent backdrop-blur-0 data-[state=open]:backdrop-blur-lg transition-[backdrop-filter] duration-200"
scrollYThreshold={100}
side="top"
>
<FontVirtualList items={fonts}>
{#snippet children({ item: font })}
<SelectItem value={font.id} class="data-[highlighted]:bg-indigo-100">
<FontApplicator name={font.name} id={font.id}>
{font.name}
</FontApplicator>
</SelectItem>
{/snippet}
</FontVirtualList>
</SelectContent>
</SelectRoot>
</div>
{/snippet}
<div class="absolute bottom-6 inset-x-6 sm:inset-x-6 flex justify-between items-end pointer-events-none z-20">
<div
class="flex flex-col gap-0.5 transition-opacity duration-300 items-start"
style:opacity={sliderPos < 15 ? 0 : 1}
>
<span class="text-[0.5rem] font-mono uppercase tracking-widest text-indigo-400">
Baseline</span>
{@render fontSelector(fontB.name, fontB.id, fontList, selectFontB)}
</div> </div>
<!-- Right Label (Font B) -->
<div <div
class="flex flex-col items-end text-right gap-1 transition-opacity duration-300" class="flex flex-col items-end text-right gap-1 transition-opacity duration-300"
style:opacity={sliderPos > 90 ? 0 : 1} style:opacity={sliderPos > 85 ? 0 : 1}
> >
<span class="text-[0.5rem] font-mono uppercase tracking-widest text-slate-400" <span class="text-[0.5rem] font-mono uppercase tracking-widest text-slate-400">
>Comparison</span> Comparison</span>
<span class="text-xs sm:text-sm font-bold text-slate-900"> {@render fontSelector(fontA.name, fontA.id, fontList, selectFontA)}
{fontA.name}
</span>
</div> </div>
</div> </div>