Files
frontend-svelte/src/widgets/ComparisonView/ui/Character/Character.svelte

93 lines
2.4 KiB
Svelte

<!--
Component: Character
Renders a single character with morphing animation
-->
<script lang="ts">
import { typographySettingsStore } from '$features/SetupFont';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { comparisonStore } from '../../model';
interface Props {
/**
* Character
*/
char: string;
/**
* Proximity value
*/
proximity: number;
/**
* Past state
*/
isPast: boolean;
}
let { char, proximity, isPast }: Props = $props();
const fontA = $derived(comparisonStore.fontA);
const fontB = $derived(comparisonStore.fontB);
const typography = $derived(typographySettingsStore);
let slot = $state<0 | 1>(0);
let slotFonts = $state<[string, string]>(['', '']);
const displayChar = $derived(char === ' ' ? '\u00A0' : char);
const targetFont = $derived(isPast ? fontA?.name ?? '' : fontB?.name ?? '');
$effect(() => {
if (!targetFont || slotFonts[slot] === targetFont) return;
const next = slot === 0 ? 1 : 0;
slotFonts[next] = targetFont;
slot = next;
});
</script>
{#if fontA && fontB}
<span
class="char-wrap"
style:font-size="{typography.renderedSize}px"
style:will-change={proximity > 0 ? 'transform' : 'auto'}
>
{#each [0, 1] as s (s)}
<span
class={cn(
'char-inner',
'transition-colors duration-300',
isPast
? 'text-swiss-black/75 dark:text-brand/75'
: 'text-neutral-950 dark:text-white',
)}
style:font-family={slotFonts[s]}
style:font-weight={typography.weight}
style:opacity={slot === s ? '1' : '0'}
style:position={slot === s ? 'relative' : 'absolute'}
aria-hidden={slot !== s ? true : undefined}
>
{displayChar}
</span>
{/each}
</span>
{/if}
<style>
.char-wrap {
display: inline-block;
position: relative;
line-height: 1;
}
.char-inner {
top: 0;
left: 0;
backface-visibility: hidden;
-webkit-font-smoothing: antialiased;
font-synthesis: none;
text-rendering: geometricPrecision;
font-optical-sizing: auto;
transition:
opacity 0.1s ease-out,
color 0.2s ease-out,
transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
</style>