DisplayFont was not a feature (FSD+ A-6): the whole slice was one presentational component that renders a Font styled by typography, with no model/domain/action. To get typography it reached sideways into a sibling feature (`$features/AdjustTypography/model`) — a feature->feature edge (C-1), the symptom of the mislayering, not the disease. Fix by inversion, mirroring the existing `status` prop pattern: - move FontSampler into entities/Font/ui (it now uses only entity siblings + $shared/ui) - it accepts a `typography` prop typed to a minimal contract defined in the component; the AdjustTypography store satisfies it structurally, so the entity has no dependency on the feature - SampleList (owns both) injects its typographySettingsStore as the prop - delete the DisplayFont slice; export FontSampler from the Font barrel; relocate the story (now passes a mock typography) Resolves A-6, A-7, and the FontSampler half of C-1. Verified: 0 type errors, 0 lint (boundary rule satisfied), 905 unit + 213 component tests, production build OK.
134 lines
3.5 KiB
Svelte
134 lines
3.5 KiB
Svelte
<script module>
|
|
import Providers from '$shared/lib/storybook/Providers.svelte';
|
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
import FontSampler from './FontSampler.svelte';
|
|
|
|
const { Story } = defineMeta({
|
|
title: 'Entities/Font/FontSampler',
|
|
component: FontSampler,
|
|
tags: ['autodocs'],
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
component:
|
|
'Displays a sample text with a given font in a contenteditable element. Visual design matches FontCard: sharp corners, brand hover accent, header stats showing font properties (size, weight, line height, letter spacing). Staggered entrance animation based on index.',
|
|
},
|
|
story: { inline: false },
|
|
},
|
|
},
|
|
argTypes: {
|
|
font: {
|
|
control: 'object',
|
|
description: 'Font information object',
|
|
},
|
|
status: {
|
|
control: 'select',
|
|
options: ['loading', 'loaded', 'error'],
|
|
description: 'Font-load status, supplied by the composing widget and forwarded to FontApplicator',
|
|
},
|
|
text: {
|
|
control: 'text',
|
|
description: 'Editable sample text (two-way bindable)',
|
|
},
|
|
index: {
|
|
control: { type: 'number', min: 0 },
|
|
description: 'Position index — drives the staggered entrance delay',
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import type { ComponentProps } from 'svelte';
|
|
import type { UnifiedFont } from '../../model/types';
|
|
|
|
// Mock fonts for testing
|
|
const mockArial: UnifiedFont = {
|
|
id: 'arial',
|
|
name: 'Arial',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin'],
|
|
variants: ['400', '700'],
|
|
styles: {
|
|
regular: '',
|
|
bold: '',
|
|
},
|
|
metadata: {
|
|
cachedAt: Date.now(),
|
|
version: '1.0',
|
|
popularity: 1,
|
|
},
|
|
features: {
|
|
isVariable: false,
|
|
},
|
|
};
|
|
|
|
const mockGeorgia: UnifiedFont = {
|
|
id: 'georgia',
|
|
name: 'Georgia',
|
|
provider: 'google',
|
|
category: 'serif',
|
|
subsets: ['latin'],
|
|
variants: ['400', '700'],
|
|
styles: {
|
|
regular: '',
|
|
bold: '',
|
|
},
|
|
metadata: {
|
|
cachedAt: Date.now(),
|
|
version: '1.0',
|
|
popularity: 2,
|
|
},
|
|
features: {
|
|
isVariable: false,
|
|
},
|
|
};
|
|
|
|
// Stand-in for the AdjustTypography store the composing widget injects.
|
|
const mockTypography = {
|
|
renderedSize: 48,
|
|
weight: 400,
|
|
height: 1.5,
|
|
spacing: 0,
|
|
};
|
|
</script>
|
|
|
|
<Story
|
|
name="Default"
|
|
args={{
|
|
font: mockArial,
|
|
status: 'loaded',
|
|
text: 'The quick brown fox jumps over the lazy dog',
|
|
index: 0,
|
|
typography: mockTypography,
|
|
}}
|
|
>
|
|
{#snippet template(args: ComponentProps<typeof FontSampler>)}
|
|
<Providers>
|
|
<div class="max-w-2xl mx-auto">
|
|
<FontSampler {...args} />
|
|
</div>
|
|
</Providers>
|
|
{/snippet}
|
|
</Story>
|
|
<Story
|
|
name="Long Text"
|
|
args={{
|
|
font: mockGeorgia,
|
|
status: 'loaded',
|
|
text:
|
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.',
|
|
index: 1,
|
|
typography: mockTypography,
|
|
}}
|
|
>
|
|
{#snippet template(args: ComponentProps<typeof FontSampler>)}
|
|
<Providers>
|
|
<div class="max-w-2xl mx-auto">
|
|
<FontSampler {...args} />
|
|
</div>
|
|
</Providers>
|
|
{/snippet}
|
|
</Story>
|