99 lines
3.1 KiB
Svelte
99 lines
3.1 KiB
Svelte
<script lang="ts">
|
|
import { slide } from "svelte/transition";
|
|
import { cubicOut } from "svelte/easing";
|
|
|
|
interface Props {
|
|
value: string;
|
|
onchange?: (font: string) => void;
|
|
}
|
|
|
|
let {
|
|
value = $bindable(),
|
|
onchange,
|
|
}: Props = $props();
|
|
|
|
const fonts = [
|
|
{ family: "", label: "System Default" },
|
|
{ family: "JetBrains Mono", label: "JetBrains Mono" },
|
|
{ family: "Space Mono", label: "Space Mono" },
|
|
{ family: "Roboto Mono", label: "Roboto Mono" },
|
|
{ family: "Fira Code", label: "Fira Code" },
|
|
{ family: "IBM Plex Mono", label: "IBM Plex Mono" },
|
|
{ family: "Source Code Pro", label: "Source Code Pro" },
|
|
{ family: "Share Tech Mono", label: "Share Tech Mono" },
|
|
{ family: "Major Mono Display", label: "Major Mono" },
|
|
{ family: "Azeret Mono", label: "Azeret Mono" },
|
|
{ family: "DM Mono", label: "DM Mono" },
|
|
{ family: "Inconsolata", label: "Inconsolata" },
|
|
{ family: "Ubuntu Mono", label: "Ubuntu Mono" },
|
|
{ family: "Overpass Mono", label: "Overpass Mono" },
|
|
{ family: "Red Hat Mono", label: "Red Hat Mono" },
|
|
{ family: "Martian Mono", label: "Martian Mono" },
|
|
{ family: "Noto Sans Mono", label: "Noto Sans Mono" },
|
|
{ family: "Oxygen Mono", label: "Oxygen Mono" },
|
|
{ family: "Anonymous Pro", label: "Anonymous Pro" },
|
|
{ family: "Courier Prime", label: "Courier Prime" },
|
|
];
|
|
|
|
function selectFont(family: string) {
|
|
value = family;
|
|
onchange?.(family);
|
|
}
|
|
|
|
function fontStyle(family: string): string {
|
|
return family ? `font-family: '${family}', monospace;` : "";
|
|
}
|
|
|
|
let expanded = $state(false);
|
|
</script>
|
|
|
|
<div class="flex flex-col gap-3">
|
|
<!-- Header row -->
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<div class="text-[13px] text-white">Countdown font</div>
|
|
<div class="text-[11px] text-[#555]">
|
|
{value || "System default"}
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
class="rounded-lg border border-[#1a1a1a] bg-black px-3 py-1.5 text-[12px] text-[#666]
|
|
transition-colors hover:border-[#333] hover:text-white"
|
|
onclick={() => { expanded = !expanded; }}
|
|
>
|
|
{expanded ? "Close" : "Browse"}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Font preview grid -->
|
|
{#if expanded}
|
|
<div
|
|
class="grid grid-cols-2 gap-2"
|
|
transition:slide={{ duration: 280, easing: cubicOut }}
|
|
>
|
|
{#each fonts as font}
|
|
<button
|
|
type="button"
|
|
class="flex flex-col items-center gap-1.5 rounded-xl border p-3
|
|
transition-all duration-150
|
|
{value === font.family
|
|
? 'border-white/30 bg-[#141414]'
|
|
: 'border-[#141414] bg-[#0a0a0a] hover:border-[#222] hover:bg-[#0f0f0f]'}"
|
|
onclick={() => selectFont(font.family)}
|
|
>
|
|
<span
|
|
class="text-[28px] leading-none tabular-nums text-white"
|
|
style={fontStyle(font.family)}
|
|
>
|
|
25:00
|
|
</span>
|
|
<span class="text-[9px] tracking-wider text-[#555] uppercase">
|
|
{font.label}
|
|
</span>
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|