feature/ux-improvements #26
@@ -1,44 +1,45 @@
|
|||||||
|
<!--
|
||||||
|
Component: Controls
|
||||||
|
Uses SidebarMenu to show ComparisonSlider's controls:
|
||||||
|
- List of fonts to pick
|
||||||
|
- Input to change text
|
||||||
|
- Sliders for font-weight, font-width, line-height
|
||||||
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { appliedFontsManager } from '$entities/Font';
|
import { appliedFontsManager } from '$entities/Font';
|
||||||
import { getFontUrl } from '$entities/Font/lib';
|
import { getFontUrl } from '$entities/Font/lib';
|
||||||
import type { ResponsiveManager } from '$shared/lib';
|
|
||||||
import { cn } from '$shared/shadcn/utils/shadcn-utils';
|
import { cn } from '$shared/shadcn/utils/shadcn-utils';
|
||||||
import {
|
import { SidebarMenu } from '$shared/ui';
|
||||||
Drawer,
|
import { comparisonStore } from '$widgets/ComparisonSlider/model';
|
||||||
IconButton,
|
import ComparisonList from './FontList.svelte';
|
||||||
} from '$shared/ui';
|
import ToggleMenuButton from './ToggleMenuButton.svelte';
|
||||||
import SlidersIcon from '@lucide/svelte/icons/sliders-vertical';
|
|
||||||
import { getContext } from 'svelte';
|
|
||||||
import { comparisonStore } from '../../../model';
|
|
||||||
import SelectComparedFonts from './SelectComparedFonts.svelte';
|
|
||||||
import TypographyControls from './TypographyControls.svelte';
|
import TypographyControls from './TypographyControls.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
sliderPos: number;
|
/**
|
||||||
isDragging: boolean;
|
* Additional class
|
||||||
typographyControls?: HTMLDivElement | null;
|
*/
|
||||||
container: HTMLElement;
|
class?: string;
|
||||||
|
/**
|
||||||
|
* Handler to trigger when menu opens/closes
|
||||||
|
*/
|
||||||
|
handleToggle?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let { class: className, handleToggle }: Props = $props();
|
||||||
sliderPos,
|
|
||||||
isDragging,
|
|
||||||
typographyControls = $bindable<HTMLDivElement | null>(null),
|
|
||||||
container,
|
|
||||||
}: Props = $props();
|
|
||||||
|
|
||||||
|
let visible = $state(false);
|
||||||
const fontA = $derived(comparisonStore.fontA);
|
const fontA = $derived(comparisonStore.fontA);
|
||||||
const fontB = $derived(comparisonStore.fontB);
|
const fontB = $derived(comparisonStore.fontB);
|
||||||
|
const typography = $derived(comparisonStore.typography);
|
||||||
const weight = $derived(comparisonStore.typography.weight);
|
let menuWrapper = $state<HTMLElement | null>(null);
|
||||||
|
|
||||||
const responsive = getContext<ResponsiveManager>('responsive');
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (!fontA || !fontB) {
|
if (!fontA || !fontB) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const weight = typography.weight;
|
||||||
const fontAUrl = getFontUrl(fontA, weight);
|
const fontAUrl = getFontUrl(fontA, weight);
|
||||||
const fontBUrl = getFontUrl(fontB, weight);
|
const fontBUrl = getFontUrl(fontB, weight);
|
||||||
|
|
||||||
@@ -63,41 +64,28 @@ $effect(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if responsive.isMobile}
|
<SidebarMenu
|
||||||
<Drawer>
|
class={cn(
|
||||||
{#snippet trigger({ isOpen, onClick })}
|
'w-96 flex flex-col h-full pl-4 lg:pl-6 py-4 sm:py-6 sm:pt-12 gap-4 sm:gap-6 pointer-events-auto overflow-hidden',
|
||||||
<IconButton class="absolute right-3 top-3" onclick={onClick}>
|
'relative h-full transition-all duration-700 ease-out',
|
||||||
{#snippet icon({ className })}
|
className,
|
||||||
<SlidersIcon class={className} />
|
)}
|
||||||
{/snippet}
|
bind:visible
|
||||||
</IconButton>
|
bind:wrapper={menuWrapper}
|
||||||
{/snippet}
|
onClickOutside={handleToggle}
|
||||||
|
>
|
||||||
{#snippet content({ isOpen, className })}
|
{#snippet action()}
|
||||||
<div class={cn(className, 'flex flex-col gap-6')}>
|
<!-- Always-visible mode switch -->
|
||||||
<SelectComparedFonts {sliderPos} />
|
<div class={cn('absolute top-4 left-0 z-50', visible && 'w-full')}>
|
||||||
<TypographyControls
|
<ToggleMenuButton bind:isActive={visible} onClick={handleToggle} />
|
||||||
{sliderPos}
|
</div>
|
||||||
{isDragging}
|
{/snippet}
|
||||||
isActive={isOpen}
|
<div class="h-2/3 overflow-hidden">
|
||||||
bind:wrapper={typographyControls}
|
<ComparisonList />
|
||||||
containerWidth={container?.clientWidth}
|
|
||||||
staticPosition
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/snippet}
|
|
||||||
</Drawer>
|
|
||||||
{:else}
|
|
||||||
<div class="absolute top-3 sm:top-6 left-3 sm:left-6 z-50">
|
|
||||||
<TypographyControls
|
|
||||||
{sliderPos}
|
|
||||||
{isDragging}
|
|
||||||
bind:wrapper={typographyControls}
|
|
||||||
containerWidth={container?.clientWidth}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="absolute bottom-3 sm:bottom-6 md:bottom-8 inset-x-3 sm:inset-x-6 md:inset-x-12">
|
<div class="relative flex w-auto border-b border-gray-400/50 px-2 ml-4 mr-8 lg:mr-10"></div>
|
||||||
<SelectComparedFonts {sliderPos} />
|
<div class="mr-4 sm:mr-6">
|
||||||
|
<TypographyControls />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</SidebarMenu>
|
||||||
|
|||||||
Reference in New Issue
Block a user