Compare commits
5 Commits
dde187e0b2
...
816d4b89ce
| Author | SHA1 | Date | |
|---|---|---|---|
| 816d4b89ce | |||
| aa1379c15b | |||
| 33e589f041 | |||
| b12dc6257d | |||
| 35e0f06a77 |
@@ -265,6 +265,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
/* 21× border-black/5 dark:border-white/10 → single token */
|
||||||
|
.border-subtle {
|
||||||
|
@apply border-black/5 dark:border-white/10;
|
||||||
|
}
|
||||||
|
/* Secondary text pair */
|
||||||
|
.text-secondary {
|
||||||
|
@apply text-neutral-500 dark:text-neutral-400;
|
||||||
|
}
|
||||||
|
/* Standard focus ring */
|
||||||
|
.focus-ring {
|
||||||
|
@apply focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Global utility - useful across your app */
|
/* Global utility - useful across your app */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
* {
|
* {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function createButtonText(item: BreadcrumbItem) {
|
|||||||
flex items-center justify-between
|
flex items-center justify-between
|
||||||
z-40
|
z-40
|
||||||
bg-surface/90 dark:bg-dark-bg/90 backdrop-blur-md
|
bg-surface/90 dark:bg-dark-bg/90 backdrop-blur-md
|
||||||
border-b border-black/5 dark:border-white/10
|
border-b border-subtle
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="max-w-8xl px-4 sm:px-6 h-full w-full flex items-center justify-between gap-2 sm:gap-4">
|
<div class="max-w-8xl px-4 sm:px-6 h-full w-full flex items-center justify-between gap-2 sm:gap-4">
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const stats = $derived([
|
|||||||
group relative
|
group relative
|
||||||
w-full h-full
|
w-full h-full
|
||||||
bg-paper dark:bg-dark-card
|
bg-paper dark:bg-dark-card
|
||||||
border border-black/5 dark:border-white/10
|
border border-subtle
|
||||||
hover:border-brand dark:hover:border-brand
|
hover:border-brand dark:hover:border-brand
|
||||||
hover:shadow-brand/10
|
hover:shadow-brand/10
|
||||||
hover:shadow-[5px_5px_0px_0px]
|
hover:shadow-[5px_5px_0px_0px]
|
||||||
@@ -76,7 +76,7 @@ const stats = $derived([
|
|||||||
class="
|
class="
|
||||||
flex items-center justify-between
|
flex items-center justify-between
|
||||||
px-4 sm:px-5 md:px-6 py-3 sm:py-4
|
px-4 sm:px-5 md:px-6 py-3 sm:py-4
|
||||||
border-b border-black/5 dark:border-white/10
|
border-b border-subtle
|
||||||
bg-paper dark:bg-dark-card
|
bg-paper dark:bg-dark-card
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -145,7 +145,7 @@ const stats = $derived([
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Mobile stats footer (md:hidden — header stats take over above) -->
|
<!-- ── Mobile stats footer (md:hidden — header stats take over above) -->
|
||||||
<div class="md:hidden px-4 sm:px-5 py-1.5 sm:py-2 border-t border-black/5 dark:border-white/10 flex gap-2 sm:gap-4 bg-paper dark:bg-dark-card mt-auto">
|
<div class="md:hidden px-4 sm:px-5 py-1.5 sm:py-2 border-t border-subtle flex gap-2 sm:gap-4 bg-paper dark:bg-dark-card mt-auto">
|
||||||
{#each stats as stat, i}
|
{#each stats as stat, i}
|
||||||
<Footnote class="text-[0.4375rem] sm:text-[0.5rem] tracking-wider {i === 0 ? 'ml-auto' : ''}">
|
<Footnote class="text-[0.4375rem] sm:text-[0.5rem] tracking-wider {i === 0 ? 'ml-auto' : ''}">
|
||||||
{stat.label}:{stat.value}
|
{stat.label}:{stat.value}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
DEFAULT_TYPOGRAPHY_CONTROLS_DATA,
|
DEFAULT_TYPOGRAPHY_CONTROLS_DATA,
|
||||||
} from '$entities/Font';
|
} from '$entities/Font';
|
||||||
import {
|
import {
|
||||||
afterEach,
|
|
||||||
beforeEach,
|
beforeEach,
|
||||||
describe,
|
describe,
|
||||||
expect,
|
expect,
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ $effect(() => {
|
|||||||
'transition-colors duration-150',
|
'transition-colors duration-150',
|
||||||
'hover:bg-white/50 dark:hover:bg-white/5',
|
'hover:bg-white/50 dark:hover:bg-white/5',
|
||||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30',
|
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30',
|
||||||
isOpen && 'bg-paper dark:bg-dark-card border-black/5 dark:border-white/10 shadow-sm',
|
isOpen && 'bg-paper dark:bg-dark-card border-subtle shadow-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -96,7 +96,7 @@ $effect(() => {
|
|||||||
class={cn(
|
class={cn(
|
||||||
'z-50 w-72',
|
'z-50 w-72',
|
||||||
'bg-surface dark:bg-dark-card',
|
'bg-surface dark:bg-dark-card',
|
||||||
'border border-black/5 dark:border-white/10',
|
'border border-subtle',
|
||||||
'shadow-[0_20px_40px_-10px_rgba(0,0,0,0.15)]',
|
'shadow-[0_20px_40px_-10px_rgba(0,0,0,0.15)]',
|
||||||
'rounded-none p-4',
|
'rounded-none p-4',
|
||||||
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
||||||
@@ -109,7 +109,7 @@ $effect(() => {
|
|||||||
escapeKeydownBehavior="close"
|
escapeKeydownBehavior="close"
|
||||||
>
|
>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center justify-between mb-3 pb-3 border-b border-black/5 dark:border-white/10">
|
<div class="flex items-center justify-between mb-3 pb-3 border-b border-subtle">
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<Settings2Icon size={12} class="text-swiss-red" />
|
<Settings2Icon size={12} class="text-swiss-red" />
|
||||||
<span
|
<span
|
||||||
@@ -154,13 +154,13 @@ $effect(() => {
|
|||||||
class={cn(
|
class={cn(
|
||||||
'flex items-center gap-1 md:gap-2 p-1.5 md:p-2',
|
'flex items-center gap-1 md:gap-2 p-1.5 md:p-2',
|
||||||
'bg-surface/95 dark:bg-dark-bg/95 backdrop-blur-xl',
|
'bg-surface/95 dark:bg-dark-bg/95 backdrop-blur-xl',
|
||||||
'border border-black/5 dark:border-white/10',
|
'border border-subtle',
|
||||||
'shadow-[0_20px_40px_-10px_rgba(0,0,0,0.1)]',
|
'shadow-[0_20px_40px_-10px_rgba(0,0,0,0.1)]',
|
||||||
'rounded-none ring-1 ring-black/5 dark:ring-white/5',
|
'rounded-none ring-1 ring-black/5 dark:ring-white/5',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<!-- Header: icon + label -->
|
<!-- Header: icon + label -->
|
||||||
<div class="px-2 md:px-3 flex items-center gap-1.5 md:gap-2 border-r border-black/5 dark:border-white/10 mr-1 text-swiss-black dark:text-neutral-200 shrink-0">
|
<div class="px-2 md:px-3 flex items-center gap-1.5 md:gap-2 border-r border-subtle mr-1 text-swiss-black dark:text-neutral-200 shrink-0">
|
||||||
<Settings2Icon
|
<Settings2Icon
|
||||||
size={14}
|
size={14}
|
||||||
class="text-swiss-red"
|
class="text-swiss-red"
|
||||||
|
|||||||
@@ -3,10 +3,7 @@
|
|||||||
Description: The main page component of the application.
|
Description: The main page component of the application.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { scrollBreadcrumbsStore } from '$entities/Breadcrumb';
|
|
||||||
import { ComparisonView } from '$widgets/ComparisonView';
|
import { ComparisonView } from '$widgets/ComparisonView';
|
||||||
import { FontSearchSection } from '$widgets/FontSearch';
|
|
||||||
import { SampleListSection } from '$widgets/SampleList';
|
|
||||||
import { cubicIn } from 'svelte/easing';
|
import { cubicIn } from 'svelte/easing';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
</script>
|
</script>
|
||||||
@@ -18,8 +15,4 @@ import { fade } from 'svelte/transition';
|
|||||||
<section class="w-auto">
|
<section class="w-auto">
|
||||||
<ComparisonView />
|
<ComparisonView />
|
||||||
</section>
|
</section>
|
||||||
<main class="w-full pt-0 pb-10 sm:px-6 sm:pt-16 sm:pb-12 md:px-8 md:pt-32 md:pb-16 lg:px-10 lg:pt-48 lg:pb-20 xl:px-16">
|
|
||||||
<FontSearchSection />
|
|
||||||
<SampleListSection index={1} />
|
|
||||||
</main>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const variantStyles: Record<ButtonVariant, string> = {
|
|||||||
),
|
),
|
||||||
ghost: cn(
|
ghost: cn(
|
||||||
'bg-transparent',
|
'bg-transparent',
|
||||||
'text-neutral-500 dark:text-neutral-400',
|
'text-secondary',
|
||||||
'border border-transparent',
|
'border border-transparent',
|
||||||
'hover:bg-transparent dark:hover:bg-transparent',
|
'hover:bg-transparent dark:hover:bg-transparent',
|
||||||
'hover:text-brand dark:hover:text-brand',
|
'hover:text-brand dark:hover:text-brand',
|
||||||
@@ -121,7 +121,7 @@ const variantStyles: Record<ButtonVariant, string> = {
|
|||||||
),
|
),
|
||||||
icon: cn(
|
icon: cn(
|
||||||
'bg-surface dark:bg-dark-bg',
|
'bg-surface dark:bg-dark-bg',
|
||||||
'text-neutral-500 dark:text-neutral-400',
|
'text-secondary',
|
||||||
'border border-transparent',
|
'border border-transparent',
|
||||||
'hover:bg-paper dark:hover:bg-paper',
|
'hover:bg-paper dark:hover:bg-paper',
|
||||||
'hover:text-brand',
|
'hover:text-brand',
|
||||||
@@ -172,7 +172,7 @@ const activeStyles: Partial<Record<ButtonVariant, string>> = {
|
|||||||
'bg-paper dark:bg-dark-card border-black/10 dark:border-white/10 shadow-sm text-neutral-900 dark:text-neutral-100',
|
'bg-paper dark:bg-dark-card border-black/10 dark:border-white/10 shadow-sm text-neutral-900 dark:text-neutral-100',
|
||||||
ghost: 'bg-transparent dark:bg-transparent text-brand dark:text-brand',
|
ghost: 'bg-transparent dark:bg-transparent text-brand dark:text-brand',
|
||||||
outline: 'bg-surface dark:bg-paper border-brand',
|
outline: 'bg-surface dark:bg-paper border-brand',
|
||||||
icon: 'bg-paper dark:bg-paper text-brand border-black/5 dark:border-white/10',
|
icon: 'bg-paper dark:bg-paper text-brand border-subtle',
|
||||||
};
|
};
|
||||||
|
|
||||||
const classes = $derived(cn(
|
const classes = $derived(cn(
|
||||||
@@ -184,7 +184,7 @@ const classes = $derived(cn(
|
|||||||
'select-none',
|
'select-none',
|
||||||
'outline-none',
|
'outline-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2',
|
'focus-ring',
|
||||||
'focus-visible:ring-offset-surface dark:focus-visible:ring-offset-dark-bg',
|
'focus-visible:ring-offset-surface dark:focus-visible:ring-offset-dark-bg',
|
||||||
'disabled:cursor-not-allowed disabled:pointer-events-none',
|
'disabled:cursor-not-allowed disabled:pointer-events-none',
|
||||||
// Variant
|
// Variant
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ let { children, class: className, ...rest }: Props = $props();
|
|||||||
class={cn(
|
class={cn(
|
||||||
'flex items-center gap-1 p-1',
|
'flex items-center gap-1 p-1',
|
||||||
'bg-surface dark:bg-dark-bg',
|
'bg-surface dark:bg-dark-bg',
|
||||||
'border border-black/5 dark:border-white/10',
|
'border border-subtle',
|
||||||
'rounded-none',
|
'rounded-none',
|
||||||
'transition-colors duration-500',
|
'transition-colors duration-500',
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -93,9 +93,7 @@ const displayLabel = $derived(label ?? controlLabel ?? '');
|
|||||||
step={control.step}
|
step={control.step}
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
/>
|
/>
|
||||||
<span
|
<span class="font-mono text-[0.6875rem] text-secondary tabular-nums w-10 text-right shrink-0">
|
||||||
class="font-mono text-[0.6875rem] text-neutral-500 dark:text-neutral-400 tabular-nums w-10 text-right shrink-0"
|
|
||||||
>
|
|
||||||
{formattedValue()}
|
{formattedValue()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,7 +127,7 @@ const displayLabel = $derived(label ?? controlLabel ?? '');
|
|||||||
'border border-transparent',
|
'border border-transparent',
|
||||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30',
|
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30',
|
||||||
open
|
open
|
||||||
? 'bg-paper dark:bg-dark-card shadow-sm border-black/5 dark:border-white/10'
|
? 'bg-paper dark:bg-dark-card shadow-sm border-subtle'
|
||||||
: 'hover:bg-paper/50 dark:hover:bg-dark-card/50',
|
: 'hover:bg-paper/50 dark:hover:bg-dark-card/50',
|
||||||
)}
|
)}
|
||||||
aria-label={controlLabel}
|
aria-label={controlLabel}
|
||||||
@@ -157,7 +155,7 @@ const displayLabel = $derived(label ?? controlLabel ?? '');
|
|||||||
|
|
||||||
<!-- Vertical slider popover -->
|
<!-- Vertical slider popover -->
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
class="w-auto py-4 px-3 h-64 flex items-center justify-center rounded-none border border-black/5 dark:border-white/10 shadow-sm bg-paper dark:bg-dark-card"
|
class="w-auto py-4 px-3 h-64 flex items-center justify-center rounded-none border border-subtle shadow-sm bg-paper dark:bg-dark-card"
|
||||||
align="center"
|
align="center"
|
||||||
side="top"
|
side="top"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ interface Props {
|
|||||||
const { label, children, class: className }: Props = $props();
|
const { label, children, class: className }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={cn('flex flex-col gap-3 py-6 border-b border-black/5 dark:border-white/10 last:border-0', className)}>
|
<div class={cn('flex flex-col gap-3 py-6 border-b border-subtle last:border-0', className)}>
|
||||||
<div class="flex justify-between items-center text-[0.6875rem] font-primary font-bold tracking-tight text-neutral-900 dark:text-neutral-100 uppercase leading-none">
|
<div class="flex justify-between items-center text-[0.6875rem] font-primary font-bold tracking-tight text-neutral-900 dark:text-neutral-100 uppercase leading-none">
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ import type { Snippet } from 'svelte';
|
|||||||
import { cubicOut } from 'svelte/easing';
|
import { cubicOut } from 'svelte/easing';
|
||||||
import type { HTMLInputAttributes } from 'svelte/elements';
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
||||||
import { scale } from 'svelte/transition';
|
import { scale } from 'svelte/transition';
|
||||||
|
import {
|
||||||
|
inputSizeConfig,
|
||||||
|
inputVariantConfig,
|
||||||
|
} from './config';
|
||||||
import type {
|
import type {
|
||||||
InputSize,
|
InputSize,
|
||||||
InputVariant,
|
InputVariant,
|
||||||
@@ -80,36 +84,11 @@ let {
|
|||||||
...rest
|
...rest
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
const sizeConfig: Record<InputSize, { input: string; text: string; height: string; clearIcon: number }> = {
|
|
||||||
sm: { input: 'px-3 py-1.5', text: 'text-sm', height: 'h-8', clearIcon: 12 },
|
|
||||||
md: { input: 'px-4 py-2', text: 'text-base', height: 'h-10', clearIcon: 14 },
|
|
||||||
lg: { input: 'px-4 py-3', text: 'text-lg md:text-xl', height: 'h-12', clearIcon: 16 },
|
|
||||||
xl: { input: 'px-4 py-3', text: 'text-xl md:text-2xl', height: 'h-14', clearIcon: 18 },
|
|
||||||
};
|
|
||||||
|
|
||||||
const variantConfig: Record<InputVariant, { base: string; focus: string; error: string }> = {
|
|
||||||
default: {
|
|
||||||
base: 'bg-paper dark:bg-paper border border-black/5 dark:border-white/10',
|
|
||||||
focus: 'focus:border-brand focus:ring-1 focus:ring-brand/20',
|
|
||||||
error: 'border-brand ring-1 ring-brand/20',
|
|
||||||
},
|
|
||||||
underline: {
|
|
||||||
base: 'bg-transparent border-0 border-b border-neutral-300 dark:border-neutral-700',
|
|
||||||
focus: 'focus:border-brand',
|
|
||||||
error: 'border-brand',
|
|
||||||
},
|
|
||||||
filled: {
|
|
||||||
base: 'bg-surface dark:bg-paper border border-transparent',
|
|
||||||
focus: 'focus:border-brand focus:ring-1 focus:ring-brand/20',
|
|
||||||
error: 'border-brand ring-1 ring-brand/20',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const hasValue = $derived(value !== undefined && value !== '');
|
const hasValue = $derived(value !== undefined && value !== '');
|
||||||
const showClear = $derived(showClearButton && hasValue && !!onclear);
|
const showClear = $derived(showClearButton && hasValue && !!onclear);
|
||||||
const hasRightSlot = $derived(!!rightIcon || showClearButton);
|
const hasRightSlot = $derived(!!rightIcon || showClearButton);
|
||||||
const cfg = $derived(sizeConfig[size]);
|
const cfg = $derived(inputSizeConfig[size]);
|
||||||
const styles = $derived(variantConfig[variant]);
|
const styles = $derived(inputVariantConfig[variant]);
|
||||||
|
|
||||||
const inputClasses = $derived(cn(
|
const inputClasses = $derived(cn(
|
||||||
'font-primary rounded-none outline-none transition-all duration-200',
|
'font-primary rounded-none outline-none transition-all duration-200',
|
||||||
@@ -170,7 +149,7 @@ const inputClasses = $derived(cn(
|
|||||||
<span
|
<span
|
||||||
class={cn(
|
class={cn(
|
||||||
'text-[0.625rem] font-mono tracking-wide px-1',
|
'text-[0.625rem] font-mono tracking-wide px-1',
|
||||||
error ? 'text-brand ' : 'text-neutral-500 dark:text-neutral-400',
|
error ? 'text-brand ' : 'text-secondary',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{helperText}
|
{helperText}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import type {
|
||||||
|
InputSize,
|
||||||
|
InputVariant,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
|
/** Size-specific layout classes: padding, text size, height, and clear-icon pixel size. */
|
||||||
|
export const inputSizeConfig: Record<InputSize, { input: string; text: string; height: string; clearIcon: number }> = {
|
||||||
|
sm: { input: 'px-3 py-1.5', text: 'text-sm', height: 'h-8', clearIcon: 12 },
|
||||||
|
md: { input: 'px-4 py-2', text: 'text-base', height: 'h-10', clearIcon: 14 },
|
||||||
|
lg: { input: 'px-4 py-3', text: 'text-lg md:text-xl', height: 'h-12', clearIcon: 16 },
|
||||||
|
xl: { input: 'px-4 py-3', text: 'text-xl md:text-2xl', height: 'h-14', clearIcon: 18 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Variant-specific classes: base background/border, focus ring, and error state. */
|
||||||
|
export const inputVariantConfig: Record<InputVariant, { base: string; focus: string; error: string }> = {
|
||||||
|
default: {
|
||||||
|
base: 'bg-paper dark:bg-paper border border-subtle',
|
||||||
|
focus: 'focus:border-brand focus:ring-1 focus:ring-brand/20',
|
||||||
|
error: 'border-brand ring-1 ring-brand/20',
|
||||||
|
},
|
||||||
|
underline: {
|
||||||
|
base: 'bg-transparent border-0 border-b border-neutral-300 dark:border-neutral-700',
|
||||||
|
focus: 'focus:border-brand',
|
||||||
|
error: 'border-brand',
|
||||||
|
},
|
||||||
|
filled: {
|
||||||
|
base: 'bg-surface dark:bg-paper border border-transparent',
|
||||||
|
focus: 'focus:border-brand focus:ring-1 focus:ring-brand/20',
|
||||||
|
error: 'border-brand ring-1 ring-brand/20',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -20,7 +20,7 @@ let {
|
|||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Input bind:value variant="underline" {...rest}>
|
<Input bind:value variant="default" {...rest}>
|
||||||
{#snippet rightIcon(size)}
|
{#snippet rightIcon(size)}
|
||||||
<SearchIcon size={inputIconSize[size]} />
|
<SearchIcon size={inputIconSize[size]} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function close() {
|
|||||||
'overflow-hidden',
|
'overflow-hidden',
|
||||||
'will-change-[width]',
|
'will-change-[width]',
|
||||||
'transition-[width] duration-300 ease-out',
|
'transition-[width] duration-300 ease-out',
|
||||||
'border-r border-black/5 dark:border-white/10',
|
'border-r border-subtle',
|
||||||
'bg-surface dark:bg-dark-bg',
|
'bg-surface dark:bg-dark-bg',
|
||||||
isOpen ? 'w-80 opacity-100' : 'w-0 opacity-0',
|
isOpen ? 'w-80 opacity-100' : 'w-0 opacity-0',
|
||||||
'transition-[width,opacity] duration-300 ease-out',
|
'transition-[width,opacity] duration-300 ease-out',
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ let {
|
|||||||
const isVertical = $derived(orientation === 'vertical');
|
const isVertical = $derived(orientation === 'vertical');
|
||||||
|
|
||||||
const labelClasses = `font-mono text-[0.625rem] tabular-nums shrink-0
|
const labelClasses = `font-mono text-[0.625rem] tabular-nums shrink-0
|
||||||
text-neutral-500 dark:text-neutral-400
|
text-secondary
|
||||||
group-hover:text-neutral-700 dark:group-hover:text-neutral-300
|
group-hover:text-neutral-700 dark:group-hover:text-neutral-300
|
||||||
transition-colors`;
|
transition-colors`;
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ $effect(() => {
|
|||||||
<span
|
<span
|
||||||
class={cn(
|
class={cn(
|
||||||
'char-inner',
|
'char-inner',
|
||||||
|
'transition-colors duration-300',
|
||||||
isPast
|
isPast
|
||||||
? 'text-swiss-black/75 dark:text-brand/75'
|
? 'text-swiss-black/75 dark:text-brand/75'
|
||||||
: 'text-neutral-950 dark:text-white',
|
: 'text-neutral-950 dark:text-white',
|
||||||
|
|||||||
@@ -6,22 +6,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { NavigationWrapper } from '$entities/Breadcrumb';
|
import { NavigationWrapper } from '$entities/Breadcrumb';
|
||||||
import type { ResponsiveManager } from '$shared/lib';
|
import type { ResponsiveManager } from '$shared/lib';
|
||||||
import {
|
import { SidebarContainer } from '$shared/ui';
|
||||||
ControlGroup,
|
|
||||||
SidebarContainer,
|
|
||||||
Slider,
|
|
||||||
} from '$shared/ui';
|
|
||||||
import {
|
import {
|
||||||
getContext,
|
getContext,
|
||||||
untrack,
|
untrack,
|
||||||
} from 'svelte';
|
} from 'svelte';
|
||||||
import FontList from '../FontList/FontList.svelte';
|
import FontList from '../FontList/FontList.svelte';
|
||||||
import Header from '../Header/Header.svelte';
|
import Header from '../Header/Header.svelte';
|
||||||
|
import Search from '../Search/Search.svelte';
|
||||||
import Sidebar from '../Sidebar/Sidebar.svelte';
|
import Sidebar from '../Sidebar/Sidebar.svelte';
|
||||||
import SliderArea from '../SliderArea/SliderArea.svelte';
|
import SliderArea from '../SliderArea/SliderArea.svelte';
|
||||||
|
|
||||||
const responsive = getContext<ResponsiveManager>('responsive');
|
const responsive = getContext<ResponsiveManager>('responsive');
|
||||||
// const typography = $derived(comparisonStore.typography);
|
|
||||||
const isMobileOrTabletPortrait = $derived(responsive.isMobile || responsive.isTabletPortrait);
|
const isMobileOrTabletPortrait = $derived(responsive.isMobile || responsive.isTabletPortrait);
|
||||||
let isSidebarOpen = $state(!isMobileOrTabletPortrait);
|
let isSidebarOpen = $state(!isMobileOrTabletPortrait);
|
||||||
|
|
||||||
@@ -42,53 +38,9 @@ $effect(() => {
|
|||||||
{#snippet sidebar()}
|
{#snippet sidebar()}
|
||||||
<Sidebar class="w-full h-full border-none">
|
<Sidebar class="w-full h-full border-none">
|
||||||
{#snippet main()}
|
{#snippet main()}
|
||||||
|
<Search />
|
||||||
<FontList />
|
<FontList />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
<!--
|
|
||||||
{#snippet controls()}
|
|
||||||
{#if typography.sizeControl && typography.weightControl && typography.heightControl && typography.spacingControl}
|
|
||||||
<ControlGroup label="Size">
|
|
||||||
<Slider
|
|
||||||
bind:value={typography.sizeControl.value}
|
|
||||||
min={typography.sizeControl.min}
|
|
||||||
max={typography.sizeControl.max}
|
|
||||||
step={typography.sizeControl.step}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
|
|
||||||
<ControlGroup label="Weight">
|
|
||||||
<Slider
|
|
||||||
bind:value={typography.weightControl.value}
|
|
||||||
min={typography.weightControl.min}
|
|
||||||
max={typography.weightControl.max}
|
|
||||||
step={typography.weightControl.step}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-6 mt-4">
|
|
||||||
<ControlGroup label="Leading" class="border-0 py-0">
|
|
||||||
<Slider
|
|
||||||
bind:value={typography.heightControl.value}
|
|
||||||
min={typography.heightControl.min}
|
|
||||||
max={typography.heightControl.max}
|
|
||||||
step={typography.heightControl.step}
|
|
||||||
format={(v => v.toFixed(1))}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
|
|
||||||
<ControlGroup label="Tracking" class="border-0 py-0">
|
|
||||||
<Slider
|
|
||||||
bind:value={typography.spacingControl.value}
|
|
||||||
min={typography.spacingControl.min}
|
|
||||||
max={typography.spacingControl.max}
|
|
||||||
step={typography.spacingControl.step}
|
|
||||||
format={(v => v.toFixed(2))}
|
|
||||||
/>
|
|
||||||
</ControlGroup>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/snippet}
|
|
||||||
-->
|
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</SidebarContainer>
|
</SidebarContainer>
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ $effect(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-1 min-h-0 h-full">
|
<div class="flex-1 min-h-0 h-full">
|
||||||
<div class="py-2 pl-4 relative flex flex-col min-h-0 h-full">
|
<div class="py-2 relative flex flex-col min-h-0 h-full">
|
||||||
<div class="px-2 py-4 mr-4 sticky border-b border-black/5 dark:border-white/10 mb-2">
|
<div class="py-2 mx-6 sticky border-b border-subtle">
|
||||||
<Label class="font-primary text-neutral-400" bold variant="default" size="sm" uppercase>
|
<Label class="font-primary text-neutral-400" bold variant="default" size="sm" uppercase>
|
||||||
Typeface Selection
|
Typeface Selection
|
||||||
</Label>
|
</Label>
|
||||||
@@ -80,7 +80,7 @@ $effect(() => {
|
|||||||
data-font-list
|
data-font-list
|
||||||
weight={DEFAULT_FONT_WEIGHT}
|
weight={DEFAULT_FONT_WEIGHT}
|
||||||
itemHeight={45}
|
itemHeight={45}
|
||||||
class="bg-transparent min-h-0 h-full scroll-stable pr-4"
|
class="bg-transparent min-h-0 h-full scroll-stable py-2 pl-6 pr-4"
|
||||||
>
|
>
|
||||||
{#snippet children({ item: font, index })}
|
{#snippet children({ item: font, index })}
|
||||||
{@const isSelectedA = font.id === comparisonStore.fontA?.id}
|
{@const isSelectedA = font.id === comparisonStore.fontA?.id}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const fontBName = $derived(comparisonStore.fontB?.name ?? '');
|
|||||||
'flex items-center justify-between',
|
'flex items-center justify-between',
|
||||||
'px-4 md:px-8 py-4 md:py-6',
|
'px-4 md:px-8 py-4 md:py-6',
|
||||||
'h-16 md:h-20 z-20',
|
'h-16 md:h-20 z-20',
|
||||||
'border-b border-black/5 dark:border-white/10',
|
'border-b border-subtle',
|
||||||
'bg-surface dark:bg-dark-bg',
|
'bg-surface dark:bg-dark-bg',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { filterManager } from '$features/GetFonts';
|
||||||
|
import { SearchBar } from '$shared/ui';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="p-6 border-b border-black/5">
|
||||||
|
<SearchBar
|
||||||
|
id="font-search"
|
||||||
|
class="w-full"
|
||||||
|
placeholder="Typeface Search"
|
||||||
|
bind:value={filterManager.queryValue}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
@@ -44,7 +44,7 @@ let {
|
|||||||
'flex flex-col h-full',
|
'flex flex-col h-full',
|
||||||
'w-80',
|
'w-80',
|
||||||
'bg-surface dark:bg-dark-bg',
|
'bg-surface dark:bg-dark-bg',
|
||||||
'border-r border-black/5 dark:border-white/10',
|
'border-r border-subtle',
|
||||||
'transition-colors duration-500',
|
'transition-colors duration-500',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
@@ -53,7 +53,7 @@ let {
|
|||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
p-6 shrink-0
|
p-6 shrink-0
|
||||||
border-b border-black/5 dark:border-white/10
|
border-b border-subtle
|
||||||
bg-surface dark:bg-dark-bg
|
bg-surface dark:bg-dark-bg
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -100,7 +100,7 @@ let {
|
|||||||
class="
|
class="
|
||||||
shrink-0 p-6
|
shrink-0 p-6
|
||||||
bg-surface dark:bg-dark-bg
|
bg-surface dark:bg-dark-bg
|
||||||
border-t border-black/5 dark:border-white/10
|
border-t border-subtle
|
||||||
z-10
|
z-10
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user