Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ebf75b24e | |||
| 7b46e06f8b | |||
| 0737db69a9 | |||
| 64b4a65e7b | |||
| 7f0d2b54e0 | |||
| 5b1a1d0b0a | |||
| 0562b94b03 | |||
| ef08512986 |
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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?.()}
|
||||
|
||||
@@ -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,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -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',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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> = {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user