mirror of
https://github.com/immich-app/immich.git
synced 2026-01-11 20:55:25 -08:00
feat(web): 2026 font
This commit is contained in:
@@ -49,7 +49,7 @@
|
||||
}
|
||||
|
||||
@theme {
|
||||
--font-immich-mono: Overpass Mono, monospace;
|
||||
--font-immich-mono: GoogleSansCode, monospace;
|
||||
|
||||
--spacing-18: 4.5rem;
|
||||
|
||||
@@ -84,25 +84,27 @@
|
||||
|
||||
@layer utilities {
|
||||
@font-face {
|
||||
font-family: 'Overpass';
|
||||
src: url('$lib/assets/fonts/overpass/Overpass.ttf') format('truetype-variations');
|
||||
font-weight: 1 999;
|
||||
font-family: 'GoogleSans';
|
||||
src: url('$lib/assets/fonts/GoogleSans/GoogleSans.ttf') format('truetype-variations');
|
||||
font-weight: 425 900;
|
||||
font-style: normal;
|
||||
ascent-override: 106.25%;
|
||||
size-adjust: 106.25%;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Overpass Mono';
|
||||
src: url('$lib/assets/fonts/overpass/OverpassMono.ttf') format('truetype-variations');
|
||||
font-weight: 1 999;
|
||||
font-family: 'GoogleSansCode';
|
||||
src: url('$lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf') format('truetype-variations');
|
||||
font-weight: 1 900;
|
||||
font-style: monospace;
|
||||
ascent-override: 106.25%;
|
||||
size-adjust: 106.25%;
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: 'Overpass', sans-serif;
|
||||
font-family: 'GoogleSans', sans-serif;
|
||||
letter-spacing: 0.1px;
|
||||
|
||||
/* Used by layouts to ensure proper spacing between navbar and content */
|
||||
--navbar-height: calc(4.5rem + 4px);
|
||||
--navbar-height-md: calc(4.5rem + 4px - 14px);
|
||||
|
||||
BIN
web/src/lib/assets/fonts/GoogleSans/GoogleSans.ttf
Normal file
BIN
web/src/lib/assets/fonts/GoogleSans/GoogleSans.ttf
Normal file
Binary file not shown.
BIN
web/src/lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf
Normal file
BIN
web/src/lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf
Normal file
Binary file not shown.
@@ -23,13 +23,13 @@
|
||||
<div class="flex h-35 w-full flex-col justify-between rounded-3xl bg-subtle text-primary p-5">
|
||||
<div class="flex place-items-center gap-4">
|
||||
<Icon {icon} size="40" />
|
||||
<Text size="large" fontWeight="bold" class="uppercase">{title}</Text>
|
||||
<Text size="large" fontWeight="semi-bold">{title}</Text>
|
||||
</div>
|
||||
|
||||
<div class="relative mx-auto font-mono text-2xl font-semibold">
|
||||
<div class="relative mx-auto font-immich-mono text-2xl font-semibold">
|
||||
<span class="text-gray-400 dark:text-gray-600">{zeros()}</span><span>{value}</span>
|
||||
{#if unit}
|
||||
<Code color="muted" class="absolute -top-5 end-1 font-light p-0">{unit}</Code>
|
||||
<Code color="muted" class="font-immich-mono absolute -top-5 end-1 font-light p-0">{unit}</Code>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
|
||||
const { stats }: Props = $props();
|
||||
|
||||
const zeros = (value: number) => {
|
||||
const maxLength = 13;
|
||||
const zeros = (value: number, maxLength = 13) => {
|
||||
const valueLength = value.toString().length;
|
||||
const zeroLength = maxLength - valueLength;
|
||||
|
||||
@@ -40,38 +39,35 @@
|
||||
<div class="flex flex-wrap gap-x-12">
|
||||
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
||||
<Icon icon={mdiCameraIris} size="25" />
|
||||
<Text fontWeight="bold" class="uppercase">{$t('photos')}</Text>
|
||||
<Text fontWeight="semi-bold">{$t('photos')}</Text>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-gray-400 dark:text-gray-600">{zeros(stats.photos)}</span><span class="text-primary"
|
||||
>{stats.photos}</span
|
||||
>
|
||||
<div class="relative text-center font-immich-mono text-2xl font-semibold">
|
||||
<span class="text-light-300">{zeros(stats.photos)}</span><span class="text-primary">{stats.photos}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-x-12">
|
||||
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
||||
<Icon icon={mdiPlayCircle} size="25" />
|
||||
<Text fontWeight="bold" class="uppercase">{$t('videos')}</Text>
|
||||
<Text fontWeight="semi-bold">{$t('videos')}</Text>
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-gray-400 dark:text-gray-600">{zeros(stats.videos)}</span><span class="text-primary"
|
||||
>{stats.videos}</span
|
||||
>
|
||||
<div class="relative text-center font-immich-mono text-2xl font-semibold">
|
||||
<span class="text-light-300">{zeros(stats.videos)}</span><span class="text-primary">{stats.videos}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-x-5">
|
||||
<div class="flex flex-1 flex-nowrap place-items-center gap-4 text-primary">
|
||||
<Icon icon={mdiChartPie} size="25" />
|
||||
<Text fontWeight="bold" class="uppercase">{$t('storage')}</Text>
|
||||
<Text fontWeight="semi-bold">{$t('storage')}</Text>
|
||||
</div>
|
||||
|
||||
<div class="relative flex text-center font-mono text-2xl font-semibold">
|
||||
<span class="text-gray-400 dark:text-gray-600">{zeros(statsUsage)}</span><span class="text-primary"
|
||||
>{statsUsage}</span
|
||||
>
|
||||
<Code color="muted" class="font-light">{statsUsageUnit}</Code>
|
||||
<div class="relative flex text-center font-immich-mono text-2xl font-semibold">
|
||||
<span class="text-light-300">{zeros(statsUsage)}</span><span class="text-primary">{statsUsage}</span>
|
||||
|
||||
<div class="absolute -right-1.5 -bottom-4">
|
||||
<Code color="muted" class="text-xs font-light font-immich-mono">{statsUsageUnit}</Code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -467,7 +467,7 @@
|
||||
/>
|
||||
{#if showAssetName && !isTimelineAsset(asset)}
|
||||
<div
|
||||
class="absolute text-center p-1 text-xs font-mono font-semibold w-full bottom-0 bg-linear-to-t bg-slate-50/75 dark:bg-slate-800/75 overflow-clip text-ellipsis whitespace-pre-wrap"
|
||||
class="absolute text-center p-1 text-xs font-immich-mono font-semibold w-full bottom-0 bg-linear-to-t bg-slate-50/75 dark:bg-slate-800/75 overflow-clip text-ellipsis whitespace-pre-wrap"
|
||||
>
|
||||
{asset.originalFileName}
|
||||
</div>
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
>
|
||||
{#snippet children({ feature })}
|
||||
<div
|
||||
class="rounded-full w-10 h-10 bg-immich-primary text-white flex justify-center items-center font-mono font-bold shadow-lg hover:bg-immich-dark-primary transition-all duration-200 hover:text-immich-dark-bg opacity-90"
|
||||
class="rounded-full w-10 h-10 bg-immich-primary text-white flex justify-center items-center font-immich-mono font-bold shadow-lg hover:bg-immich-dark-primary transition-all duration-200 hover:text-immich-dark-bg opacity-90"
|
||||
>
|
||||
{feature.properties?.point_count?.toLocaleString()}
|
||||
</div>
|
||||
|
||||
@@ -62,12 +62,12 @@
|
||||
>
|
||||
{#if $connected}
|
||||
<div class="flex gap-2 place-items-center place-content-center">
|
||||
<div class="w-[7px] h-[7px] bg-green-500 rounded-full"></div>
|
||||
<div class="w-1.75 h-1.75 bg-green-500 rounded-full"></div>
|
||||
<p class="dark:text-immich-gray">{$t('server_online')}</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex gap-2 place-items-center place-content-center">
|
||||
<div class="w-[7px] h-[7px] bg-red-500 rounded-full"></div>
|
||||
<div class="w-1.75 h-1.75 bg-red-500 rounded-full"></div>
|
||||
<p class="text-red-500">{$t('server_offline')}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
})}
|
||||
</p>
|
||||
|
||||
<div class="mt-4 h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||
<div class="h-[7px] rounded-full {usageClasses}" style="width: {usedPercentage}%"></div>
|
||||
<div class="mt-4 h-1.75 w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||
<div class="h-1.75 rounded-full {usageClasses}" style="width: {usedPercentage}%"></div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-2">
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
/>
|
||||
</li>
|
||||
{#each parents as parent (parent)}
|
||||
<li class="flex gap-2 items-center font-mono text-sm text-nowrap text-primary">
|
||||
<li class="flex gap-2 items-center font-immich-mono text-sm text-nowrap text-primary">
|
||||
<Icon icon={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size="16" aria-hidden />
|
||||
<a class="underline hover:font-semibold whitespace-pre-wrap" href={getLink(parent.path)}>
|
||||
{parent.value}
|
||||
@@ -59,7 +59,7 @@
|
||||
</li>
|
||||
{/each}
|
||||
|
||||
<li class="flex gap-2 items-center font-mono text-sm text-nowrap text-primary">
|
||||
<li class="flex gap-2 items-center font-immich-mono text-sm text-nowrap text-primary">
|
||||
<Icon icon={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size="16" aria-hidden />
|
||||
<p class="cursor-default whitespace-pre-wrap">{node.value}</p>
|
||||
</li>
|
||||
|
||||
@@ -42,7 +42,9 @@
|
||||
size="20"
|
||||
/>
|
||||
</div>
|
||||
<span class="text-nowrap overflow-hidden text-ellipsis font-mono ps-1 pt-1 whitespace-pre-wrap">{node.value}</span>
|
||||
<span class="text-nowrap overflow-hidden text-ellipsis font-immich-mono ps-1 pt-1 whitespace-pre-wrap"
|
||||
>{node.value}</span
|
||||
>
|
||||
</a>
|
||||
|
||||
{#if isOpen}
|
||||
|
||||
@@ -543,7 +543,7 @@
|
||||
in:fade={{ duration: 200 }}
|
||||
out:fade={{ duration: 200 }}
|
||||
>
|
||||
<Icon icon={mdiPlay} size="20" class="-rotate-90 relative top-[9px] -end-0.5" />
|
||||
<Icon icon={mdiPlay} size="20" class="-rotate-90 relative top-2.25 -end-0.5" />
|
||||
<Icon icon={mdiPlay} size="20" class="rotate-90 relative top-px -end-0.5" />
|
||||
{#if (timelineManager.scrolling && scrollHoverLabel) || isHover || isDragging}
|
||||
<p
|
||||
@@ -588,7 +588,7 @@
|
||||
>
|
||||
{#if !usingMobileDevice}
|
||||
{#if segment.hasLabel}
|
||||
<div class="absolute end-5 text-[12px] dark:text-immich-dark-fg font-immich-mono bottom-0">
|
||||
<div class="absolute end-5 text-[13px] dark:text-immich-dark-fg font-immich-mono bottom-0">
|
||||
{segment.year}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
maxlength="1"
|
||||
bind:this={pinCodeInputElements[index]}
|
||||
id="pin-code-{index}"
|
||||
class="h-12 w-10 rounded-xl border-2 border-suble dark:border-gray-700 text-center text-lg font-medium focus:border-immich-primary focus:ring-primary dark:focus:border-primary font-mono bg-white dark:bg-light"
|
||||
class="h-12 w-10 rounded-xl border-2 border-suble dark:border-gray-700 text-center text-lg font-medium focus:border-immich-primary focus:ring-primary dark:focus:border-primary font-immich-mono bg-white dark:bg-light"
|
||||
bind:value={pinValues[index]}
|
||||
onkeydown={handleKeydown}
|
||||
oninput={(event) => handleInput(event, index)}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
checked={$locale == 'default'}
|
||||
onToggle={handleToggleLocaleBrowser}
|
||||
>
|
||||
<p class="mt-2 dark:text-gray-400">{selectedDate}</p>
|
||||
<p class="mt-2 dark:text-gray-400 font-immich-mono text-sm">{selectedDate}</p>
|
||||
</SettingSwitch>
|
||||
</div>
|
||||
{#if $locale !== 'default'}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
checked={selectAllSubItems}
|
||||
onCheckedChange={handleSelectAllSubItems}
|
||||
/>
|
||||
<Label label={title} for="permission-{title}" class="font-mono text-primary text-lg" />
|
||||
<Label label={title} for="permission-{title}" class="font-immich-mono text-primary text-lg" />
|
||||
</div>
|
||||
<div class="mx-6 mt-3 grid grid-cols-3 gap-2">
|
||||
{#each subItems as item (item)}
|
||||
@@ -50,7 +50,7 @@
|
||||
checked={selectedItems.includes(item)}
|
||||
onCheckedChange={() => handleToggleItem(item)}
|
||||
/>
|
||||
<Label label={item} for="permission-{item}" class="text-sm font-mono" />
|
||||
<Label label={item} for="permission-{item}" class="text-sm font-immich-mono" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
>
|
||||
<td class="w-1/4 text-ellipsis px-4 text-sm overflow-hidden">{key.name}</td>
|
||||
<td
|
||||
class="w-1/4 text-ellipsis px-4 text-xs overflow-hidden line-clamp-3 break-all font-mono"
|
||||
class="w-1/4 text-ellipsis px-4 text-xs overflow-hidden line-clamp-3 break-all font-immich-mono"
|
||||
title={JSON.stringify(key.permissions, undefined, 2)}>{key.permissions}</td
|
||||
>
|
||||
<td class="w-1/4 text-ellipsis px-4 text-sm overflow-hidden"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<Modal title={$t('api_key')} icon={mdiKeyVariant} {onClose} size="small">
|
||||
<ModalBody>
|
||||
<Text size="small" class="mb-4">{$t('api_key_description')}</Text>
|
||||
<Textarea bind:value={secret} readonly class="font-mono" />
|
||||
<Textarea bind:value={secret} readonly class="font-immich-mono" />
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
|
||||
@@ -141,12 +141,12 @@
|
||||
<div class="flex gap-2 justify-end place-items-center">
|
||||
<Text class="hidden md:block text-xs mr-4 text-dark/50">{$t('geolocation_instruction_location')}</Text>
|
||||
<div class="border flex place-items-center place-content-center px-2 py-1 bg-primary/10 rounded-2xl">
|
||||
<Text class="hidden md:inline-block text-xs text-gray-500 font-mono mr-5 ml-2 uppercase">
|
||||
<Text class="hidden md:inline-block text-xs text-gray-500 font-immich-mono mr-5 ml-2 uppercase">
|
||||
{$t('selected_gps_coordinates')}
|
||||
</Text>
|
||||
<Text
|
||||
title="latitude, longitude"
|
||||
class="rounded-3xl font-mono text-sm text-primary px-2 py-1 transition-all duration-100 ease-in-out {locationUpdated
|
||||
class="rounded-3xl font-immich-mono text-sm text-primary px-2 py-1 transition-all duration-100 ease-in-out {locationUpdated
|
||||
? 'bg-primary/90 text-light font-semibold scale-105'
|
||||
: ''}">{location.latitude.toFixed(3)}, {location.longitude.toFixed(3)}</Text
|
||||
>
|
||||
|
||||
@@ -326,7 +326,7 @@
|
||||
|
||||
{#snippet cardOrder(index: number)}
|
||||
<div class="h-8 w-8 rounded-lg flex place-items-center place-content-center shrink-0 border bg-light-50">
|
||||
<Text size="small" class="font-mono font-bold">
|
||||
<Text size="small" class="font-immich-mono font-bold">
|
||||
{index + 1}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user