refactor(features, widgets): update ThemeManager, FontSampler, FontSearch, and SampleList

This commit is contained in:
Ilia Mashkov
2026-03-02 22:20:48 +03:00
parent 0fa3437661
commit 55e2efc222
14 changed files with 1512 additions and 115 deletions
@@ -14,7 +14,74 @@ const { Story } = defineMeta({
},
story: { inline: false },
},
layout: 'centered',
viewport: {
viewports: {
mobile1: {
name: 'iPhone 5/SE',
styles: {
width: '320px',
height: '568px',
},
},
mobile2: {
name: 'iPhone 14 Pro Max',
styles: {
width: '414px',
height: '896px',
},
},
tablet: {
name: 'iPad (Portrait)',
styles: {
width: '834px',
height: '1112px',
},
},
desktop: {
name: 'Desktop (Small)',
styles: {
width: '1024px',
height: '1280px',
},
},
widgetMedium: {
name: 'Widget Medium',
styles: {
width: '768px',
height: '800px',
},
},
widgetWide: {
name: 'Widget Wide',
styles: {
width: '1024px',
height: '800px',
},
},
widgetExtraWide: {
name: 'Widget Extra Wide',
styles: {
width: '1280px',
height: '800px',
},
},
fullWidth: {
name: 'Full Width',
styles: {
width: '100%',
height: '800px',
},
},
fullScreen: {
name: 'Full Screen',
styles: {
width: '100%',
height: '100%',
},
},
},
},
layout: 'padded',
},
argTypes: {
showFilters: {
@@ -31,14 +98,14 @@ let showFiltersClosed = $state(false);
let showFiltersOpen = $state(true);
</script>
<Story name="Default">
<div class="w-full max-w-2xl">
<Story name="Default" parameters={{ globals: { viewport: 'widgetWide' } }}>
<div class="w-full max-w-3xl">
<FontSearch bind:showFilters={showFiltersDefault} />
</div>
</Story>
<Story name="Filters Open">
<div class="w-full max-w-2xl">
<Story name="Filters Open" parameters={{ globals: { viewport: 'widgetWide' } }}>
<div class="w-full max-w-3xl">
<FontSearch bind:showFilters={showFiltersOpen} />
<div class="mt-8 text-center">
<p class="text-text-muted text-sm">Filters panel is open and visible</p>
@@ -46,8 +113,8 @@ let showFiltersOpen = $state(true);
</div>
</Story>
<Story name="Filters Closed">
<div class="w-full max-w-2xl">
<Story name="Filters Closed" parameters={{ globals: { viewport: 'widgetWide' } }}>
<div class="w-full max-w-3xl">
<FontSearch bind:showFilters={showFiltersClosed} />
<div class="mt-8 text-center">
<p class="text-text-muted text-sm">Filters panel is closed - click the slider icon to open</p>
@@ -55,13 +122,13 @@ let showFiltersOpen = $state(true);
</div>
</Story>
<Story name="Full Width">
<Story name="Full Width" parameters={{ globals: { viewport: 'fullWidth' } }}>
<div class="w-full px-8">
<FontSearch />
</div>
</Story>
<Story name="In Context" tags={['!autodocs']}>
<Story name="In Context" tags={['!autodocs']} parameters={{ globals: { viewport: 'widgetWide' } }}>
<div class="w-full max-w-3xl p-8 space-y-6">
<div class="text-center mb-8">
<h1 class="text-4xl font-bold mb-2">Font Browser</h1>
@@ -78,8 +145,8 @@ let showFiltersOpen = $state(true);
</div>
</Story>
<Story name="With Filters Demo">
<div class="w-full max-w-2xl">
<Story name="With Filters Demo" parameters={{ globals: { viewport: 'widgetWide' } }}>
<div class="w-full max-w-3xl">
<div class="mb-4 p-4 bg-background-40 rounded-lg">
<p class="text-sm text-text-muted">
<strong class="text-foreground">Demo Note:</strong> Click the slider icon to toggle filters. Use the
@@ -90,7 +157,7 @@ let showFiltersOpen = $state(true);
</div>
</Story>
<Story name="Responsive Behavior">
<Story name="Responsive Behavior" parameters={{ globals: { viewport: 'fullWidth' } }}>
<div class="w-full">
<div class="mb-4 text-center">
<p class="text-text-muted text-sm">Resize browser to see responsive layout</p>
@@ -11,15 +11,12 @@ import {
mapManagerToParams,
} from '$features/GetFonts';
import { springySlideFade } from '$shared/lib';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import {
Button,
Footnote,
IconButton,
SearchBar,
} from '$shared/ui';
import SlidersHorizontalIcon from '@lucide/svelte/icons/sliders-horizontal';
import { onMount } from 'svelte';
import { untrack } from 'svelte';
import { cubicOut } from 'svelte/easing';
import {
Tween,
@@ -29,22 +26,17 @@ import { type SlideParams } from 'svelte/transition';
interface Props {
/**
* Controllable flag to show/hide filters (bindable)
* Show filters flag
* @default true
*/
showFilters?: boolean;
}
let { showFilters = $bindable(true) }: Props = $props();
onMount(() => {
/**
* The Pairing:
* We "plug" this manager into the global store.
* addBinding returns a function that removes this binding when the component unmounts.
*/
const unbind = unifiedFontStore.addBinding(() => mapManagerToParams(filterManager));
return unbind;
$effect(() => {
const params = mapManagerToParams(filterManager);
untrack(() => unifiedFontStore.setParams(params));
});
const transform = new Tween(
@@ -67,8 +59,8 @@ function toggleFilters() {
}
</script>
<div class="flex flex-col gap-3 border-b border-t border-[#1a1a1a]/5 dark:border-white/10">
<div class="relative w-full flex border-b border-[#1a1a1a]/5 dark:border-white/10 py-4 md:py-6">
<div class="flex flex-col gap-3 border-b border-t border-swiss-black/5 dark:border-white/10">
<div class="relative w-full flex flex-col md:flex-row gap-y-4 border-b border-swiss-black/5 dark:border-white/10 py-4 md:py-6">
<SearchBar
id="font-search"
class="w-full"
@@ -3,29 +3,45 @@
Wraps FontSearch with a Section component
-->
<script lang="ts">
import { handleTitleStatusChanged } from '$entities/Breadcrumb';
import { NavigationWrapper } from '$entities/Breadcrumb';
import type { ResponsiveManager } from '$shared/lib';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { Section } from '$shared/ui';
import { getContext } from 'svelte';
import {
getContext,
untrack,
} from 'svelte';
import FontSearch from '../FontSearch/FontSearch.svelte';
let isExpanded = $state(true);
const responsive = getContext<ResponsiveManager>('responsive');
const isMobileOrTabletPortrait = $derived(responsive.isMobile || responsive.isTabletPortrait);
let isExpanded = $state(!isMobileOrTabletPortrait);
$effect(() => {
if (isMobileOrTabletPortrait) {
untrack(() => {
isExpanded = false;
});
}
});
</script>
<Section
class="py-4 sm:py-10 md:py-12 gap-6 sm:gap-x-12 sm:gap-y-8"
index={2}
id="query_module"
onTitleStatusChange={handleTitleStatusChanged}
title="Query Module"
headerTitle="query_matrix"
headerSubtitle="active_nodes:"
>
{#snippet content({ className })}
<div class={cn(className, !responsive.isDesktopLarge && 'col-start-0 col-span-2')}>
<FontSearch bind:showFilters={isExpanded} />
</div>
<NavigationWrapper index={1} title="Query">
{#snippet content(registerAction)}
<Section
class="pt-16 md:pt-24 gap-6 sm:gap-x-12 sm:gap-y-8"
index={0}
id="query_module"
title="Query Module"
headerTitle="query_matrix"
headerSubtitle="active_nodes:"
headerAction={registerAction}
>
{#snippet content({ className })}
<div class={cn(className, !responsive.isDesktopLarge && 'col-start-0 col-span-2')}>
<FontSearch bind:showFilters={isExpanded} />
</div>
{/snippet}
</Section>
{/snippet}
</Section>
</NavigationWrapper>