Compare commits

..

8 Commits

18 changed files with 60 additions and 40 deletions
+8 -1
View File
@@ -91,7 +91,6 @@
--space-4xl: 4rem;
/* Typography Scale */
--text-2xs: 0.625rem;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
@@ -205,6 +204,14 @@
--font-mono: 'Space Mono', monospace;
--font-primary: 'Space Grotesk', system-ui, -apple-system, 'Segoe UI', Inter, Roboto, Arial, sans-serif;
--font-secondary: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
/* Micro typography scale — extends Tailwind's text-xs (0.75rem) downward */
--font-size-5xs: 0.4375rem;
--font-size-4xs: 0.5rem;
--font-size-3xs: 0.5625rem;
--font-size-2xs: 0.625rem;
/* Monospace label tracking — used in Loader and Footnote */
--tracking-wider-mono: 0.2em;
}
@layer base {
@@ -82,7 +82,7 @@ const stats = $derived([
>
<!-- Left: index · name · type badge · provider badge -->
<div class="flex items-center gap-2 sm:gap-4 min-w-0 shrink-0">
<span class="font-mono text-[0.625rem] tracking-widest text-neutral-400 uppercase leading-none shrink-0">
<span class="font-mono text-2xs tracking-widest text-neutral-400 uppercase leading-none shrink-0">
{String(index + 1).padStart(2, '0')}
</span>
<Divider orientation="vertical" class="h-3 shrink-0" />
@@ -94,14 +94,14 @@ const stats = $derived([
</span>
{#if fontType}
<Badge size="xs" variant="default" class="text-nowrap font-mono">
<Badge size="xs" variant="default" nowrap>
{fontType}
</Badge>
{/if}
<!-- Provider badge -->
{#if providerBadge}
<Badge size="xs" variant="default" class="text-nowrap font-mono" data-provider={font.provider}>
<Badge size="xs" variant="default" nowrap data-provider={font.provider}>
{providerBadge}
</Badge>
{/if}
@@ -147,7 +147,7 @@ const stats = $derived([
<!-- ── 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-subtle flex gap-2 sm:gap-4 bg-paper dark:bg-dark-card mt-auto">
{#each stats as stat, i}
<Footnote class="text-[0.4375rem] sm:text-[0.5rem] tracking-wider {i === 0 ? 'ml-auto' : ''}">
<Footnote class="text-5xs sm:text-4xs tracking-wider {i === 0 ? 'ml-auto' : ''}">
{stat.label}:{stat.value}
</Footnote>
{#if i < stats.length - 1}
@@ -61,13 +61,10 @@ function handleReset() {
{#each SORT_OPTIONS as option}
<Button
variant="ghost"
size={isMobileOrTabletPortrait ? 'sm' : 'md'}
size={isMobileOrTabletPortrait ? 'xs' : 'sm'}
active={sortStore.value === option}
onclick={() => sortStore.set(option)}
class={cn(
'font-bold uppercase tracking-wide font-primary, px-0',
isMobileOrTabletPortrait ? 'text-[0.5625rem]' : 'text-[0.625rem]',
)}
class="tracking-wide px-0"
>
{option}
</Button>
@@ -78,12 +75,9 @@ function handleReset() {
<!-- Reset_Filters -->
<Button
variant="ghost"
size={isMobileOrTabletPortrait ? 'sm' : 'md'}
size={isMobileOrTabletPortrait ? 'xs' : 'sm'}
onclick={handleReset}
class={cn(
'group text-[0.5625rem] md:text-[0.625rem] font-mono font-bold uppercase tracking-widest text-neutral-400',
isMobileOrTabletPortrait && 'px-0',
)}
class={cn('group font-mono tracking-widest text-neutral-400', isMobileOrTabletPortrait && 'px-0')}
iconPosition="left"
>
{#snippet icon()}
@@ -113,7 +113,7 @@ $effect(() => {
<div class="flex items-center gap-1.5">
<Settings2Icon size={12} class="text-swiss-red" />
<span
class="text-[0.5625rem] font-mono uppercase tracking-widest font-bold text-swiss-black dark:text-neutral-200"
class="text-3xs font-mono uppercase tracking-widest font-bold text-swiss-black dark:text-neutral-200"
>
CONTROLS
</span>
@@ -166,7 +166,7 @@ $effect(() => {
class="text-swiss-red"
/>
<span
class="text-[0.5625rem] md:text-[0.625rem] font-mono uppercase tracking-widest font-bold hidden sm:inline whitespace-nowrap"
class="text-3xs md:text-2xs font-mono uppercase tracking-widest font-bold hidden sm:inline whitespace-nowrap"
>
GLOBAL_CONTROLS
</span>
+7
View File
@@ -37,6 +37,11 @@ interface Props extends HTMLAttributes<HTMLSpanElement> {
* @default false
*/
dot?: boolean;
/**
* Prevent text wrapping
* @default false
*/
nowrap?: boolean;
/**
* Content snippet
*/
@@ -51,6 +56,7 @@ let {
variant = 'default',
size = 'xs',
dot = false,
nowrap = false,
children,
class: className,
...rest
@@ -63,6 +69,7 @@ let {
'font-mono uppercase tracking-wide',
labelSizeConfig[size],
badgeVariantConfig[variant],
nowrap && 'text-nowrap',
className,
)}
{...rest}
+5 -5
View File
@@ -150,11 +150,11 @@ const variantStyles: Record<ButtonVariant, string> = {
};
const sizeStyles: Record<ButtonSize, string> = {
xs: 'h-6 px-2 text-[9px] gap-1',
sm: 'h-8 px-3 text-[10px] gap-1.5',
md: 'h-10 px-4 text-[11px] gap-2',
lg: 'h-12 px-6 text-[12px] gap-2',
xl: 'h-14 px-8 text-[13px] gap-2.5',
xs: 'h-6 px-2 text-3xs gap-1',
sm: 'h-8 px-3 text-2xs gap-1.5',
md: 'h-10 px-4 text-xs gap-2',
lg: 'h-12 px-6 text-xs gap-2',
xl: 'h-14 px-8 text-sm gap-2.5',
};
// Square padding for icon-only mode
@@ -93,7 +93,7 @@ const displayLabel = $derived(label ?? controlLabel ?? '');
step={control.step}
orientation="horizontal"
/>
<span class="font-mono text-[0.6875rem] text-secondary tabular-nums w-10 text-right shrink-0">
<span class="font-mono text-xs text-secondary tabular-nums w-10 text-right shrink-0">
{formattedValue()}
</span>
</div>
@@ -136,7 +136,7 @@ const displayLabel = $derived(label ?? controlLabel ?? '');
{#if displayLabel}
<span
class="
text-[0.5625rem] font-primary font-bold tracking-tight uppercase
text-3xs font-primary font-bold tracking-tight uppercase
text-neutral-900 dark:text-neutral-100
mb-0.5 leading-none
"
@@ -25,7 +25,7 @@ const { label, children, class: className }: Props = $props();
</script>
<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-xs font-primary font-bold tracking-tight text-neutral-900 dark:text-neutral-100 uppercase leading-none">
{label}
</div>
{@render children?.()}
+2 -2
View File
@@ -27,14 +27,14 @@ const { children, class: className, render }: Props = $props();
{#if render}
{@render render({
class: cn(
'font-mono text-[0.5625rem] sm:text-[0.625rem] lowercase tracking-[0.2em] text-text-soft',
'font-mono text-3xs sm:text-2xs lowercase tracking-wider-mono text-text-soft',
className,
),
})}
{:else if children}
<span
class={cn(
'font-mono text-[0.5625rem] sm:text-[0.625rem] lowercase tracking-[0.2em] text-text-soft',
'font-mono text-3xs sm:text-2xs lowercase tracking-wider-mono text-text-soft',
className,
)}
>
+1 -1
View File
@@ -148,7 +148,7 @@ const inputClasses = $derived(cn(
{#if helperText}
<span
class={cn(
'text-[0.625rem] font-mono tracking-wide px-1',
'text-2xs font-mono tracking-wide px-1',
error ? 'text-brand ' : 'text-secondary',
)}
>
+8
View File
@@ -6,6 +6,7 @@
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import type { Snippet } from 'svelte';
import {
type LabelFont,
type LabelSize,
type LabelVariant,
labelSizeConfig,
@@ -28,6 +29,11 @@ interface Props {
* @default true
*/
uppercase?: boolean;
/**
* Font family
* @default 'mono'
*/
font?: LabelFont;
/**
* Bold text
* @default false
@@ -55,6 +61,7 @@ interface Props {
let {
variant = 'default',
size = 'sm',
font = 'mono',
uppercase = true,
bold = false,
icon,
@@ -68,6 +75,7 @@ let {
class={cn(
'font-mono tracking-widest leading-none',
'inline-flex items-center gap-1.5',
font === 'primary' && 'font-primary tracking-tight',
labelSizeConfig[size],
labelVariantConfig[variant],
uppercase && 'uppercase',
+6 -4
View File
@@ -3,6 +3,8 @@
* Import from here in each component to keep maps DRY.
*/
export type LabelFont = 'mono' | 'primary';
export type LabelVariant =
| 'default'
| 'accent'
@@ -14,10 +16,10 @@ export type LabelVariant =
export type LabelSize = 'xs' | 'sm' | 'md' | 'lg';
export const labelSizeConfig: Record<LabelSize, string> = {
xs: 'text-[0.5rem]',
sm: 'text-[0.5625rem] md:text-[0.625rem]',
md: 'text-[0.625rem] md:text-[0.6875rem]',
lg: 'text-[0.8rem] md:text-[0.875rem]',
xs: 'text-4xs',
sm: 'text-3xs md:text-2xs',
md: 'text-2xs md:text-xs',
lg: 'text-sm',
};
export const labelVariantConfig: Record<LabelVariant, string> = {
+1 -1
View File
@@ -71,7 +71,7 @@ let { size = 20, class: className = '', message = 'analyzing_data' }: Props = $p
<div class="w-px h-3 bg-text-muted/50"></div>
<!-- Message -->
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-text-subtle font-medium">
<span class="font-mono text-2xs uppercase tracking-wider-mono text-text-subtle font-medium">
{message}
</span>
</div>
@@ -53,7 +53,7 @@ const indexStr = $derived(String(index).padStart(2, '0'));
</div>
{#if subtitle}
<span class="text-neutral-300 dark:text-neutral-700 text-[0.625rem] hidden md:inline">/</span>
<span class="text-neutral-300 dark:text-neutral-700 text-2xs hidden md:inline">/</span>
<Label variant="muted" size="sm">{subtitle}</Label>
{/if}
</div>
@@ -13,7 +13,7 @@ interface Props {
const { text }: Props = $props();
</script>
{#if text}
<h2 class="text-3xl md:text-4xl lg:text-5xl font-['Space_Grotesk'] font-bold text-swiss-black dark:text-neutral-200 tracking-tight">
<h2 class="text-3xl md:text-4xl lg:text-5xl font-primary font-bold text-swiss-black dark:text-neutral-200 tracking-tight">
{text}
</h2>
{/if}
+1 -1
View File
@@ -69,7 +69,7 @@ let {
const isVertical = $derived(orientation === 'vertical');
const labelClasses = `font-mono text-[0.625rem] tabular-nums shrink-0
const labelClasses = `font-mono text-2xs tabular-nums shrink-0
text-secondary
group-hover:text-neutral-700 dark:group-hover:text-neutral-300
transition-colors`;
@@ -72,7 +72,7 @@ $effect(() => {
<div class="flex-1 min-h-0 h-full">
<div class="py-2 relative flex flex-col min-h-0 h-full">
<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 font="primary" variant="muted" bold size="sm" uppercase>
Typeface Selection
</Label>
</div>
@@ -70,19 +70,21 @@ let {
-->
<ButtonGroup>
<ToggleButton
size="sm"
active={comparisonStore.side === 'A'}
onclick={() => comparisonStore.side = 'A'}
class="flex-1 tracking-wide font-bold uppercase text-[0.625rem]"
class="flex-1 tracking-wide font-bold uppercase"
>
<span>Left Font</span>
</ToggleButton>
<ToggleButton
class="flex-1 tracking-wide font-bold uppercase text-[0.625rem]"
size="sm"
class="flex-1 tracking-wide font-bold uppercase"
active={comparisonStore.side === 'B'}
onclick={() => comparisonStore.side = 'B'}
>
<span class="uppercase">Right Font</span>
<span>Right Font</span>
</ToggleButton>
</ButtonGroup>
</div>