mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
feat(web): 2026 font (#25174)
* feat(web): 2026 font * chore: docs font * spacing tweak * tweak minimum font weight and update ui lib * small tweaks * docs: small tweaks * more tweaks
This commit is contained in:
parent
39212a049c
commit
edc513a3df
38 changed files with 104 additions and 87 deletions
|
|
@ -8,19 +8,19 @@
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Overpass';
|
font-family: 'GoogleSans';
|
||||||
src: url('/fonts/overpass/Overpass.ttf') format('truetype-variations');
|
src: url('/fonts/GoogleSans/GoogleSans.ttf') format('truetype-variations');
|
||||||
font-weight: 1 999;
|
font-weight: 410 900;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
ascent-override: 106.25%;
|
ascent-override: 106.25%;
|
||||||
size-adjust: 106.25%;
|
size-adjust: 106.25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Overpass Mono';
|
font-family: 'GoogleSansCode';
|
||||||
src: url('/fonts/overpass/OverpassMono.ttf') format('truetype-variations');
|
src: url('/fonts/GoogleSansCode/GoogleSansCode.ttf') format('truetype-variations');
|
||||||
font-weight: 1 999;
|
font-weight: 1 900;
|
||||||
font-style: normal;
|
font-style: monospace;
|
||||||
ascent-override: 106.25%;
|
ascent-override: 106.25%;
|
||||||
size-adjust: 106.25%;
|
size-adjust: 106.25%;
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,8 @@ img {
|
||||||
|
|
||||||
/* You can override the default Infima variables here. */
|
/* You can override the default Infima variables here. */
|
||||||
:root {
|
:root {
|
||||||
font-family: 'Overpass', sans-serif;
|
font-family: 'GoogleSans', sans-serif;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
--ifm-color-primary: #4250af;
|
--ifm-color-primary: #4250af;
|
||||||
--ifm-color-primary-dark: #4250af;
|
--ifm-color-primary-dark: #4250af;
|
||||||
--ifm-color-primary-darker: #4250af;
|
--ifm-color-primary-darker: #4250af;
|
||||||
|
|
@ -48,6 +49,16 @@ img {
|
||||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-family: 'GoogleSans', sans-serif;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
}
|
||||||
|
|
||||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
--ifm-color-primary: #adcbfa;
|
--ifm-color-primary: #adcbfa;
|
||||||
|
|
@ -71,15 +82,22 @@ div[class^='announcementBar_'] {
|
||||||
padding: 10px 10px 10px 16px;
|
padding: 10px 10px 10px 16px;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__list-item-collapsible {
|
.menu__list-item-collapsible {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__link--active {
|
.menu__link--active {
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents__link {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 450;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* workaround for version switcher PR 15894 */
|
/* workaround for version switcher PR 15894 */
|
||||||
|
|
@ -88,13 +106,14 @@ div[class*='navbar__items'] > li:has(a[class*='version-switcher-34ab39']) {
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
|
font-family: 'GoogleSansCode';
|
||||||
}
|
}
|
||||||
|
|
||||||
.buy-button {
|
.buy-button {
|
||||||
padding: 8px 14px;
|
padding: 8px 14px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
font-family: 'Overpass', sans-serif;
|
font-family: 'GoogleSans', sans-serif;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0 0 5px 2px rgba(181, 206, 254, 0.4);
|
box-shadow: 0 0 5px 2px rgba(181, 206, 254, 0.4);
|
||||||
|
|
|
||||||
BIN
docs/static/fonts/GoogleSans/GoogleSans.ttf
vendored
Normal file
BIN
docs/static/fonts/GoogleSans/GoogleSans.ttf
vendored
Normal file
Binary file not shown.
BIN
docs/static/fonts/GoogleSansCode/GoogleSansCode.ttf
vendored
Normal file
BIN
docs/static/fonts/GoogleSansCode/GoogleSansCode.ttf
vendored
Normal file
Binary file not shown.
BIN
docs/static/fonts/overpass/Overpass-Italic.ttf
vendored
BIN
docs/static/fonts/overpass/Overpass-Italic.ttf
vendored
Binary file not shown.
BIN
docs/static/fonts/overpass/Overpass.ttf
vendored
BIN
docs/static/fonts/overpass/Overpass.ttf
vendored
Binary file not shown.
BIN
docs/static/fonts/overpass/OverpassMono.ttf
vendored
BIN
docs/static/fonts/overpass/OverpassMono.ttf
vendored
Binary file not shown.
|
|
@ -738,8 +738,8 @@ importers:
|
||||||
specifier: file:../open-api/typescript-sdk
|
specifier: file:../open-api/typescript-sdk
|
||||||
version: link:../open-api/typescript-sdk
|
version: link:../open-api/typescript-sdk
|
||||||
'@immich/ui':
|
'@immich/ui':
|
||||||
specifier: ^0.56.1
|
specifier: ^0.57.3
|
||||||
version: 0.56.1(@sveltejs/kit@2.49.3(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.3(svelte@5.46.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)
|
version: 0.57.3(@sveltejs/kit@2.49.3(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.3(svelte@5.46.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)
|
||||||
'@mapbox/mapbox-gl-rtl-text':
|
'@mapbox/mapbox-gl-rtl-text':
|
||||||
specifier: 0.2.3
|
specifier: 0.2.3
|
||||||
version: 0.2.3(mapbox-gl@1.13.3)
|
version: 0.2.3(mapbox-gl@1.13.3)
|
||||||
|
|
@ -3087,8 +3087,8 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
svelte: ^5.0.0
|
svelte: ^5.0.0
|
||||||
|
|
||||||
'@immich/ui@0.56.1':
|
'@immich/ui@0.57.3':
|
||||||
resolution: {integrity: sha512-W4uEQn9pxVKRvIV7sl9p6dU2r7xlVsMFxBeClxtXzSsiJEoE10uZwBIm0L9q17c4TQ/+lk9e/w1e4jNSvFqFwQ==}
|
resolution: {integrity: sha512-5Y0KmyHRojem1gvX4hbr01GZ35oq22AkYE3CImvg3+jmZQhP0newTiqyVYJsfnEupLZKu5bFIlWykIe8uwMqDQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
svelte: ^5.0.0
|
svelte: ^5.0.0
|
||||||
|
|
||||||
|
|
@ -15144,7 +15144,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
svelte: 5.46.1
|
svelte: 5.46.1
|
||||||
|
|
||||||
'@immich/ui@0.56.1(@sveltejs/kit@2.49.3(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.3(svelte@5.46.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)':
|
'@immich/ui@0.57.3(@sveltejs/kit@2.49.3(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.3(svelte@5.46.1)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.46.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.46.1)
|
'@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.46.1)
|
||||||
'@internationalized/date': 3.10.0
|
'@internationalized/date': 3.10.0
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
"@formatjs/icu-messageformat-parser": "^3.0.0",
|
"@formatjs/icu-messageformat-parser": "^3.0.0",
|
||||||
"@immich/justified-layout-wasm": "^0.4.3",
|
"@immich/justified-layout-wasm": "^0.4.3",
|
||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@immich/ui": "^0.56.1",
|
"@immich/ui": "^0.57.3",
|
||||||
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
|
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
|
||||||
"@mdi/js": "^7.4.47",
|
"@mdi/js": "^7.4.47",
|
||||||
"@photo-sphere-viewer/core": "^5.14.0",
|
"@photo-sphere-viewer/core": "^5.14.0",
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-immich-mono: Overpass Mono, monospace;
|
--font-immich-mono: GoogleSansCode, monospace;
|
||||||
|
|
||||||
--spacing-18: 4.5rem;
|
--spacing-18: 4.5rem;
|
||||||
|
|
||||||
|
|
@ -84,25 +84,25 @@
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Overpass';
|
font-family: 'GoogleSans';
|
||||||
src: url('$lib/assets/fonts/overpass/Overpass.ttf') format('truetype-variations');
|
src: url('$lib/assets/fonts/GoogleSans/GoogleSans.ttf') format('truetype-variations');
|
||||||
font-weight: 1 999;
|
font-weight: 410 900;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
ascent-override: 106.25%;
|
ascent-override: 106.25%;
|
||||||
size-adjust: 106.25%;
|
size-adjust: 106.25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Overpass Mono';
|
font-family: 'GoogleSansCode';
|
||||||
src: url('$lib/assets/fonts/overpass/OverpassMono.ttf') format('truetype-variations');
|
src: url('$lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf') format('truetype-variations');
|
||||||
font-weight: 1 999;
|
font-weight: 1 900;
|
||||||
font-style: monospace;
|
font-style: monospace;
|
||||||
ascent-override: 106.25%;
|
|
||||||
size-adjust: 106.25%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
: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 */
|
/* Used by layouts to ensure proper spacing between navbar and content */
|
||||||
--navbar-height: calc(4.5rem + 4px);
|
--navbar-height: calc(4.5rem + 4px);
|
||||||
--navbar-height-md: calc(4.5rem + 4px - 14px);
|
--navbar-height-md: calc(4.5rem + 4px - 14px);
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import overpass from '$lib/assets/fonts/overpass/Overpass.ttf?url';
|
import GoogleSans from '$lib/assets/fonts/GoogleSans/GoogleSans.ttf?url';
|
||||||
import overpassMono from '$lib/assets/fonts/overpass/OverpassMono.ttf?url';
|
import GoogleSansCode from '$lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf?url';
|
||||||
import type { Handle } from '@sveltejs/kit';
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
|
||||||
// only used during the build to replace the variables from app.html
|
// only used during the build to replace the variables from app.html
|
||||||
export const handle = (async ({ event, resolve }) => {
|
export const handle = (async ({ event, resolve }) => {
|
||||||
return resolve(event, {
|
return resolve(event, {
|
||||||
transformPageChunk: ({ html }) => {
|
transformPageChunk: ({ html }) => {
|
||||||
return html.replace('%app.font%', overpass).replace('%app.monofont%', overpassMono);
|
return html.replace('%app.font%', GoogleSans).replace('%app.monofont%', GoogleSansCode);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}) satisfies Handle;
|
}) satisfies Handle;
|
||||||
|
|
|
||||||
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -31,7 +31,7 @@
|
||||||
{#if isOwned}
|
{#if isOwned}
|
||||||
<Textarea
|
<Textarea
|
||||||
bind:value={description}
|
bind:value={description}
|
||||||
class="outline-none border-b border-gray-500 bg-transparent ring-0 focus:ring-0 resize-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary dark:bg-transparent"
|
class="outline-none border-b max-h-32 border-transparent pl-0 bg-transparent ring-0 focus:ring-0 resize-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary dark:bg-transparent"
|
||||||
rows={1}
|
rows={1}
|
||||||
grow
|
grow
|
||||||
shape="rectangle"
|
shape="rectangle"
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
{:else if description}
|
{:else if description}
|
||||||
<p class="break-words whitespace-pre-line w-full text-black dark:text-white text-base">
|
<p class="wrap-break-words whitespace-pre-line w-full text-black dark:text-white text-base">
|
||||||
{description}
|
{description}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -566,7 +566,7 @@
|
||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="detail-panel"
|
id="detail-panel"
|
||||||
class="row-start-1 row-span-4 w-[360px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray bg-light"
|
class="row-start-1 row-span-4 w-90 overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray bg-light"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<DetailPanel {asset} currentAlbum={album} albums={appearsInAlbums} />
|
<DetailPanel {asset} currentAlbum={album} albums={appearsInAlbums} />
|
||||||
|
|
@ -577,7 +577,7 @@
|
||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="editor-panel"
|
id="editor-panel"
|
||||||
class="row-start-1 row-span-4 w-[400px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
class="row-start-1 row-span-4 w-100 overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<EditorPanel {asset} onClose={closeEditor} />
|
<EditorPanel {asset} onClose={closeEditor} />
|
||||||
|
|
@ -624,7 +624,7 @@
|
||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="activity-panel"
|
id="activity-panel"
|
||||||
class="row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
class="row-start-1 row-span-5 w-90 md:w-115 overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<ActivityViewer
|
<ActivityViewer
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<section class="px-4 mt-10">
|
<section class="px-4 mt-10">
|
||||||
<Textarea
|
<Textarea
|
||||||
bind:value={description}
|
bind:value={description}
|
||||||
class="max-h-40 outline-none border-b border-gray-500 bg-transparent ring-0 focus:ring-0 resize-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary dark:bg-transparent"
|
class="max-h-40 pl-0 outline-none border-b border-gray-500 bg-transparent ring-0 focus:ring-0 resize-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary dark:bg-transparent"
|
||||||
rows={1}
|
rows={1}
|
||||||
grow
|
grow
|
||||||
shape="rectangle"
|
shape="rectangle"
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
<div class="absolute flex h-16 w-full place-items-center justify-between border-b p-2 text-dark">
|
<div class="absolute flex h-16 w-full place-items-center justify-between border-b p-2 text-dark">
|
||||||
<div class="flex gap-2 items-center">
|
<div class="flex gap-2 items-center">
|
||||||
{#if title}
|
{#if title}
|
||||||
<div class="font-medium outline-none pe-8" tabindex="-1" id={headerId}>{title}</div>
|
<div class="outline-none pe-8" tabindex="-1" id={headerId}>{title}</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if description}
|
{#if description}
|
||||||
<p class="text-sm text-gray-400 dark:text-gray-600">{description}</p>
|
<p class="text-sm text-gray-400 dark:text-gray-600">{description}</p>
|
||||||
|
|
|
||||||
|
|
@ -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 h-35 w-full flex-col justify-between rounded-3xl bg-subtle text-primary p-5">
|
||||||
<div class="flex place-items-center gap-4">
|
<div class="flex place-items-center gap-4">
|
||||||
<Icon {icon} size="40" />
|
<Icon {icon} size="40" />
|
||||||
<Text size="large" fontWeight="bold" class="uppercase">{title}</Text>
|
<Text size="giant" class="font-medium">{title}</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative mx-auto font-mono text-2xl font-semibold">
|
<div class="relative mx-auto font-immich-mono text-2xl font-medium">
|
||||||
<span class="text-gray-400 dark:text-gray-600">{zeros()}</span><span>{value}</span>
|
<span class="text-gray-300 dark:text-gray-600">{zeros()}</span><span>{value}</span>
|
||||||
{#if unit}
|
{#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}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import { locale } from '$lib/stores/preferences.store';
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import { getByteUnitString, getBytesWithUnit } from '$lib/utils/byte-units';
|
import { getByteUnitString, getBytesWithUnit } from '$lib/utils/byte-units';
|
||||||
import type { ServerStatsResponseDto } from '@immich/sdk';
|
import type { ServerStatsResponseDto } from '@immich/sdk';
|
||||||
import { Code, Heading, Icon, Text } from '@immich/ui';
|
import { Code, Icon, Text } from '@immich/ui';
|
||||||
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
|
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
|
|
@ -13,8 +13,7 @@
|
||||||
|
|
||||||
const { stats }: Props = $props();
|
const { stats }: Props = $props();
|
||||||
|
|
||||||
const zeros = (value: number) => {
|
const zeros = (value: number, maxLength = 13) => {
|
||||||
const maxLength = 13;
|
|
||||||
const valueLength = value.toString().length;
|
const valueLength = value.toString().length;
|
||||||
const zeroLength = maxLength - valueLength;
|
const zeroLength = maxLength - valueLength;
|
||||||
|
|
||||||
|
|
@ -27,7 +26,7 @@
|
||||||
|
|
||||||
<div class="flex flex-col gap-5 my-4">
|
<div class="flex flex-col gap-5 my-4">
|
||||||
<div>
|
<div>
|
||||||
<Heading size="tiny" class="mb-2">{$t('total_usage')}</Heading>
|
<Text class="mb-2 font-medium">{$t('total_usage')}</Text>
|
||||||
|
|
||||||
<div class="hidden justify-between lg:flex gap-4">
|
<div class="hidden justify-between lg:flex gap-4">
|
||||||
<StatsCard icon={mdiCameraIris} title={$t('photos')} value={stats.photos} />
|
<StatsCard icon={mdiCameraIris} title={$t('photos')} value={stats.photos} />
|
||||||
|
|
@ -40,38 +39,35 @@
|
||||||
<div class="flex flex-wrap gap-x-12">
|
<div class="flex flex-wrap gap-x-12">
|
||||||
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
||||||
<Icon icon={mdiCameraIris} size="25" />
|
<Icon icon={mdiCameraIris} size="25" />
|
||||||
<Text fontWeight="bold" class="uppercase">{$t('photos')}</Text>
|
<Text class="font-medium" size="medium">{$t('photos')}</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
<div class="relative text-center font-immich-mono text-2xl font-medium">
|
||||||
<span class="text-gray-400 dark:text-gray-600">{zeros(stats.photos)}</span><span class="text-primary"
|
<span class="text-light-300">{zeros(stats.photos)}</span><span class="text-primary">{stats.photos}</span>
|
||||||
>{stats.photos}</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-x-12">
|
<div class="flex flex-wrap gap-x-12">
|
||||||
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
<div class="flex flex-1 place-items-center gap-4 text-primary">
|
||||||
<Icon icon={mdiPlayCircle} size="25" />
|
<Icon icon={mdiPlayCircle} size="25" />
|
||||||
<Text fontWeight="bold" class="uppercase">{$t('videos')}</Text>
|
<Text class="font-medium" size="medium">{$t('videos')}</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative text-center font-mono text-2xl font-semibold">
|
<div class="relative text-center font-immich-mono text-2xl font-medium">
|
||||||
<span class="text-gray-400 dark:text-gray-600">{zeros(stats.videos)}</span><span class="text-primary"
|
<span class="text-light-300">{zeros(stats.videos)}</span><span class="text-primary">{stats.videos}</span>
|
||||||
>{stats.videos}</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-x-5">
|
<div class="flex flex-wrap gap-x-5">
|
||||||
<div class="flex flex-1 flex-nowrap place-items-center gap-4 text-primary">
|
<div class="flex flex-1 flex-nowrap place-items-center gap-4 text-primary">
|
||||||
<Icon icon={mdiChartPie} size="25" />
|
<Icon icon={mdiChartPie} size="25" />
|
||||||
<Text fontWeight="bold" class="uppercase">{$t('storage')}</Text>
|
<Text class="font-medium" size="medium">{$t('storage')}</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative flex text-center font-mono text-2xl font-semibold">
|
<div class="relative flex text-center font-immich-mono text-2xl font-medium">
|
||||||
<span class="text-gray-400 dark:text-gray-600">{zeros(statsUsage)}</span><span class="text-primary"
|
<span class="text-light-300">{zeros(statsUsage)}</span><span class="text-primary">{statsUsage}</span>
|
||||||
>{statsUsage}</span
|
|
||||||
>
|
<div class="absolute -right-1.5 -bottom-4">
|
||||||
<Code color="muted" class="font-light">{statsUsageUnit}</Code>
|
<Code color="muted" class="text-xs font-light font-immich-mono">{statsUsageUnit}</Code>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -79,7 +75,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Heading size="tiny" class="mb-2">{$t('user_usage_detail')}</Heading>
|
<Text class="mt-6 mb-2 font-medium">{$t('user_usage_detail')}</Text>
|
||||||
<table class="mt-5 w-full text-start">
|
<table class="mt-5 w-full text-start">
|
||||||
<thead
|
<thead
|
||||||
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray"
|
||||||
|
|
|
||||||
|
|
@ -467,7 +467,7 @@
|
||||||
/>
|
/>
|
||||||
{#if showAssetName && !isTimelineAsset(asset)}
|
{#if showAssetName && !isTimelineAsset(asset)}
|
||||||
<div
|
<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}
|
{asset.originalFileName}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@
|
||||||
>
|
>
|
||||||
{#snippet children({ feature })}
|
{#snippet children({ feature })}
|
||||||
<div
|
<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()}
|
{feature.properties?.point_count?.toLocaleString()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="border-2 rounded-2xl border-primary/20 my-4 px-6 py-4 transition-all {isOpen
|
class="border-2 rounded-2xl border-primary/20 mt-4 px-6 py-4 transition-all {isOpen
|
||||||
? 'border-primary/60 shadow-md'
|
? 'border-primary/60 shadow-md'
|
||||||
: ''}"
|
: ''}"
|
||||||
bind:this={accordionElement}
|
bind:this={accordionElement}
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@
|
||||||
let closestLanguage = $derived(getClosestAvailableLocale([$lang], langCodes));
|
let closestLanguage = $derived(getClosestAvailableLocale([$lang], langCodes));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="max-w-[300px]">
|
<div class="max-w-75">
|
||||||
{#if showSettingDescription}
|
{#if showSettingDescription}
|
||||||
<div>
|
<div>
|
||||||
<div class="flex h-6.5 place-items-center gap-1">
|
<div class="flex h-6.5 place-items-center gap-1">
|
||||||
<Label>{$t('language')}</Label>
|
<Label size="small">{$t('language')}</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Text size="small" color="muted">{$t('language_setting_description')}</Text>
|
<Text size="small" color="muted">{$t('language_setting_description')}</Text>
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,12 @@
|
||||||
>
|
>
|
||||||
{#if $connected}
|
{#if $connected}
|
||||||
<div class="flex gap-2 place-items-center place-content-center">
|
<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>
|
<p class="dark:text-immich-gray">{$t('server_online')}</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex gap-2 place-items-center place-content-center">
|
<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>
|
<p class="text-red-500">{$t('server_offline')}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="mt-4 h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
<div class="mt-4 h-1.75 w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||||
<div class="h-[7px] rounded-full {usageClasses}" style="width: {usedPercentage}%"></div>
|
<div class="h-1.75 rounded-full {usageClasses}" style="width: {usedPercentage}%"></div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
{#each parents as parent (parent)}
|
{#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 />
|
<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)}>
|
<a class="underline hover:font-semibold whitespace-pre-wrap" href={getLink(parent.path)}>
|
||||||
{parent.value}
|
{parent.value}
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/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 />
|
<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>
|
<p class="cursor-default whitespace-pre-wrap">{node.value}</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,9 @@
|
||||||
size="20"
|
size="20"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</a>
|
||||||
|
|
||||||
{#if isOpen}
|
{#if isOpen}
|
||||||
|
|
|
||||||
|
|
@ -543,7 +543,7 @@
|
||||||
in:fade={{ duration: 200 }}
|
in:fade={{ duration: 200 }}
|
||||||
out: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" />
|
<Icon icon={mdiPlay} size="20" class="rotate-90 relative top-px -end-0.5" />
|
||||||
{#if (timelineManager.scrolling && scrollHoverLabel) || isHover || isDragging}
|
{#if (timelineManager.scrolling && scrollHoverLabel) || isHover || isDragging}
|
||||||
<p
|
<p
|
||||||
|
|
@ -588,7 +588,7 @@
|
||||||
>
|
>
|
||||||
{#if !usingMobileDevice}
|
{#if !usingMobileDevice}
|
||||||
{#if segment.hasLabel}
|
{#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}
|
{segment.year}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
maxlength="1"
|
maxlength="1"
|
||||||
bind:this={pinCodeInputElements[index]}
|
bind:this={pinCodeInputElements[index]}
|
||||||
id="pin-code-{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]}
|
bind:value={pinValues[index]}
|
||||||
onkeydown={handleKeydown}
|
onkeydown={handleKeydown}
|
||||||
oninput={(event) => handleInput(event, index)}
|
oninput={(event) => handleInput(event, index)}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<div class="ms-8 mt-4 flex flex-col gap-4">
|
<div class="ms-8 mt-4 flex flex-col gap-6">
|
||||||
<Field label={$t('theme_selection')} description={$t('theme_selection_description')}>
|
<Field label={$t('theme_selection')} description={$t('theme_selection_description')}>
|
||||||
<Switch checked={themeManager.theme.system} onCheckedChange={(checked) => themeManager.setSystem(checked)} />
|
<Switch checked={themeManager.theme.system} onCheckedChange={(checked) => themeManager.setSystem(checked)} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
|
|
||||||
<Field label={$t('default_locale')} description={$t('default_locale_description')}>
|
<Field label={$t('default_locale')} description={$t('default_locale_description')}>
|
||||||
<Switch checked={$locale == 'default'} onCheckedChange={handleToggleLocaleBrowser} />
|
<Switch checked={$locale == 'default'} onCheckedChange={handleToggleLocaleBrowser} />
|
||||||
<Text size="small" class="mt-2">{selectedDate}</Text>
|
<Text size="small" class="mt-2 font-immich-mono text-sm">{selectedDate}</Text>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
{#if $locale !== 'default'}
|
{#if $locale !== 'default'}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<section class="my-4">
|
<section class="my-4">
|
||||||
<div in:fade={{ duration: 500 }}>
|
<div in:fade={{ duration: 500 }}>
|
||||||
<form autocomplete="off" {onsubmit}>
|
<form autocomplete="off" {onsubmit}>
|
||||||
<div class="ms-4 mt-4 flex flex-col gap-4">
|
<div class="ms-4 mt-4 flex flex-col gap-6">
|
||||||
<Field label={$t('enable')} description={$t('notification_toggle_setting_description')}>
|
<Field label={$t('enable')} description={$t('notification_toggle_setting_description')}>
|
||||||
<Switch bind:checked={emailNotificationsEnabled} />
|
<Switch bind:checked={emailNotificationsEnabled} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
checked={selectAllSubItems}
|
checked={selectAllSubItems}
|
||||||
onCheckedChange={handleSelectAllSubItems}
|
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>
|
||||||
<div class="mx-6 mt-3 grid grid-cols-3 gap-2">
|
<div class="mx-6 mt-3 grid grid-cols-3 gap-2">
|
||||||
{#each subItems as item (item)}
|
{#each subItems as item (item)}
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
checked={selectedItems.includes(item)}
|
checked={selectedItems.includes(item)}
|
||||||
onCheckedChange={() => handleToggleItem(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>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</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-sm overflow-hidden">{key.name}</td>
|
||||||
<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
|
title={JSON.stringify(key.permissions, undefined, 2)}>{key.permissions}</td
|
||||||
>
|
>
|
||||||
<td class="w-1/4 text-ellipsis px-4 text-sm overflow-hidden"
|
<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">
|
<Modal title={$t('api_key')} icon={mdiKeyVariant} {onClose} size="small">
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Text size="small" class="mb-4">{$t('api_key_description')}</Text>
|
<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>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
|
|
||||||
|
|
@ -141,12 +141,12 @@
|
||||||
<div class="flex gap-2 justify-end place-items-center">
|
<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>
|
<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">
|
<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')}
|
{$t('selected_gps_coordinates')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
title="latitude, longitude"
|
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'
|
? 'bg-primary/90 text-light font-semibold scale-105'
|
||||||
: ''}">{location.latitude.toFixed(3)}, {location.longitude.toFixed(3)}</Text
|
: ''}">{location.latitude.toFixed(3)}, {location.longitude.toFixed(3)}</Text
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@
|
||||||
|
|
||||||
{#snippet cardOrder(index: number)}
|
{#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">
|
<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}
|
{index + 1}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue