1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-04 10:56:47 +01:00

chore(web): sort tailwindcss class automatically (#3330)

This commit is contained in:
Alex 2023-07-18 13:19:39 -05:00 committed by GitHub
parent f28fc8fa5c
commit 7316ad5a72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
117 changed files with 638 additions and 555 deletions

82
web/package-lock.json generated
View file

@ -53,6 +53,7 @@
"postcss": "^8.4.21", "postcss": "^8.4.21",
"prettier": "^2.8.4", "prettier": "^2.8.4",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",
"prettier-plugin-tailwindcss": "^0.4.1",
"svelte": "^4.0.5", "svelte": "^4.0.5",
"svelte-check": "^3.4.3", "svelte-check": "^3.4.3",
"svelte-jester": "^2.3.2", "svelte-jester": "^2.3.2",
@ -10146,6 +10147,80 @@
"svelte": "^3.2.0 || ^4.0.0-next.0" "svelte": "^3.2.0 || ^4.0.0-next.0"
} }
}, },
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz",
"integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==",
"dev": true,
"engines": {
"node": ">=12.17.0"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@shufo/prettier-plugin-blade": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"prettier": "^2.2 || ^3.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-marko": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*",
"prettier-plugin-twig-melody": "*"
},
"peerDependenciesMeta": {
"@ianvs/prettier-plugin-sort-imports": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@shufo/prettier-plugin-blade": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-marko": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"prettier-plugin-twig-melody": {
"optional": true
}
}
},
"node_modules/pretty-format": { "node_modules/pretty-format": {
"version": "27.5.1", "version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
@ -19248,6 +19323,13 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"prettier-plugin-tailwindcss": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.4.1.tgz",
"integrity": "sha512-hwn2EiJmv8M+AW4YDkbjJ6HlZCTzLyz1QlySn9sMuKV/Px0fjwldlB7tol8GzdgqtkdPtzT3iJ4UzdnYXP25Ag==",
"dev": true,
"requires": {}
},
"pretty-format": { "pretty-format": {
"version": "27.5.1", "version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",

View file

@ -48,6 +48,7 @@
"postcss": "^8.4.21", "postcss": "^8.4.21",
"prettier": "^2.8.4", "prettier": "^2.8.4",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",
"prettier-plugin-tailwindcss": "^0.4.1",
"svelte": "^4.0.5", "svelte": "^4.0.5",
"svelte-check": "^3.4.3", "svelte-check": "^3.4.3",
"svelte-jester": "^2.3.2", "svelte-jester": "^2.3.2",

View file

@ -56,7 +56,7 @@ input:focus-visible {
@layer utilities { @layer utilities {
.immich-form-input { .immich-form-input {
@apply bg-slate-200 p-4 rounded-xl focus:border-immich-primary text-sm dark:bg-gray-600 dark:text-immich-dark-fg disabled:bg-gray-400 dark:disabled:bg-gray-800 disabled:cursor-not-allowed disabled:text-gray-200; @apply rounded-xl bg-slate-200 p-4 text-sm focus:border-immich-primary disabled:cursor-not-allowed disabled:bg-gray-400 disabled:text-gray-200 dark:bg-gray-600 dark:text-immich-dark-fg dark:disabled:bg-gray-800;
} }
.immich-form-label { .immich-form-label {

View file

@ -12,7 +12,7 @@
</script> </script>
<button <button
class="h-full w-full py-2 flex gap-2 flex-col place-items-center place-content-center px-8 text-gray-600 transition-colors hover:bg-immich-primary hover:text-white dark:text-gray-200 dark:hover:bg-immich-dark-primary text-xs dark:hover:text-black {colorClasses[ class="flex h-full w-full flex-col place-content-center place-items-center gap-2 px-8 py-2 text-xs text-gray-600 transition-colors hover:bg-immich-primary hover:text-white dark:text-gray-200 dark:hover:bg-immich-dark-primary dark:hover:text-black {colorClasses[
color color
]}" ]}"
on:click on:click

View file

@ -11,6 +11,6 @@
}; };
</script> </script>
<div class="w-full text-center text-sm p-2 {colorClasses[color]}"> <div class="w-full p-2 text-center text-sm {colorClasses[color]}">
<slot /> <slot />
</div> </div>

View file

@ -34,9 +34,9 @@
</script> </script>
<div <div
class="flex sm:flex-row flex-col bg-gray-100 dark:bg-immich-dark-gray rounded-2xl sm:rounded-[35px] overflow-hidden" class="flex flex-col overflow-hidden rounded-2xl bg-gray-100 dark:bg-immich-dark-gray sm:flex-row sm:rounded-[35px]"
> >
<div class="flex flex-col w-full"> <div class="flex w-full flex-col">
{#if queueStatus.isPaused} {#if queueStatus.isPaused}
<JobTileStatus color="warning">Paused</JobTileStatus> <JobTileStatus color="warning">Paused</JobTileStatus>
{:else if queueStatus.isActive} {:else if queueStatus.isActive}
@ -44,8 +44,8 @@
{/if} {/if}
<div class="flex flex-col gap-2 p-5 sm:p-7 md:p-9"> <div class="flex flex-col gap-2 p-5 sm:p-7 md:p-9">
<div class="flex items-center gap-4 text-xl font-semibold text-immich-primary dark:text-immich-dark-primary"> <div class="flex items-center gap-4 text-xl font-semibold text-immich-primary dark:text-immich-dark-primary">
<span class="flex gap-2 items-center"> <span class="flex items-center gap-2">
<svelte:component this={icon} size="1.25em" class="shrink-0 hidden sm:block" /> <svelte:component this={icon} size="1.25em" class="hidden shrink-0 sm:block" />
{title.toUpperCase()} {title.toUpperCase()}
</span> </span>
<div class="flex gap-2"> <div class="flex gap-2">
@ -63,7 +63,7 @@
</div> </div>
{#if subtitle} {#if subtitle}
<div class="text-sm dark:text-white whitespace-pre-line">{subtitle}</div> <div class="whitespace-pre-line text-sm dark:text-white">{subtitle}</div>
{/if} {/if}
{#if slots?.description} {#if slots?.description}
@ -72,9 +72,9 @@
</div> </div>
{/if} {/if}
<div class="flex w-full max-w-md mt-2 flex-col sm:flex-row"> <div class="mt-2 flex w-full max-w-md flex-col sm:flex-row">
<div <div
class="{commonClasses} bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray rounded-t-lg sm:rounded-l-lg sm:rounded-r-none" class="{commonClasses} rounded-t-lg bg-immich-primary text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray sm:rounded-l-lg sm:rounded-r-none"
> >
<p>Active</p> <p>Active</p>
<p class="text-2xl"> <p class="text-2xl">
@ -83,7 +83,7 @@
</div> </div>
<div <div
class="{commonClasses} bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray rounded-b-lg sm:rounded-r-lg sm:rounded-l-none flex-row-reverse" class="{commonClasses} flex-row-reverse rounded-b-lg bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray sm:rounded-l-none sm:rounded-r-lg"
> >
<p class="text-2xl"> <p class="text-2xl">
{waitingCount.toLocaleString($locale)} {waitingCount.toLocaleString($locale)}
@ -93,7 +93,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="flex sm:flex-col flex-row sm:w-32 w-full overflow-hidden"> <div class="flex w-full flex-row overflow-hidden sm:w-32 sm:flex-col">
{#if !isIdle} {#if !isIdle}
{#if waitingCount > 0} {#if waitingCount > 0}
<JobTileButton color="gray" on:click={() => dispatch('command', { command: JobCommand.Empty, force: false })}> <JobTileButton color="gray" on:click={() => dispatch('command', { command: JobCommand.Empty, force: false })}>

View file

@ -29,20 +29,20 @@
<div> <div>
<p class="text-sm dark:text-immich-dark-fg">TOTAL USAGE</p> <p class="text-sm dark:text-immich-dark-fg">TOTAL USAGE</p>
<div class="mt-5 justify-between lg:flex hidden"> <div class="mt-5 hidden justify-between lg:flex">
<StatsCard logo={CameraIris} title="PHOTOS" value={stats.photos} /> <StatsCard logo={CameraIris} title="PHOTOS" value={stats.photos} />
<StatsCard logo={PlayCircle} title="VIDEOS" value={stats.videos} /> <StatsCard logo={PlayCircle} title="VIDEOS" value={stats.videos} />
<StatsCard logo={Memory} title="STORAGE" value={statsUsage} unit={statsUsageUnit} /> <StatsCard logo={Memory} title="STORAGE" value={statsUsage} unit={statsUsageUnit} />
</div> </div>
<div class="mt-5 lg:hidden flex"> <div class="mt-5 flex lg:hidden">
<div class="bg-immich-gray dark:bg-immich-dark-gray rounded-3xl p-5 flex flex-col justify-between"> <div class="flex flex-col justify-between rounded-3xl bg-immich-gray p-5 dark:bg-immich-dark-gray">
<div class="flex flex-wrap gap-x-12"> <div class="flex flex-wrap gap-x-12">
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary"> <div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<CameraIris size="25" /> <CameraIris size="25" />
<p>PHOTOS</p> <p>PHOTOS</p>
</div> </div>
<div class="relative text-center font-mono font-semibold text-2xl"> <div class="relative text-center font-mono text-2xl font-semibold">
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.photos)}</span><span <span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.photos)}</span><span
class="text-immich-primary dark:text-immich-dark-primary">{stats.photos}</span class="text-immich-primary dark:text-immich-dark-primary">{stats.photos}</span
> >
@ -54,7 +54,7 @@
<p>VIDEOS</p> <p>VIDEOS</p>
</div> </div>
<div class="relative text-center font-mono font-semibold text-2xl"> <div class="relative text-center font-mono text-2xl font-semibold">
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.videos)}</span><span <span class="text-[#DCDADA] dark:text-[#525252]">{zeros(stats.videos)}</span><span
class="text-immich-primary dark:text-immich-dark-primary">{stats.videos}</span class="text-immich-primary dark:text-immich-dark-primary">{stats.videos}</span
> >
@ -66,11 +66,11 @@
<p>STORAGE</p> <p>STORAGE</p>
</div> </div>
<div class="relative text-center font-mono font-semibold text-2xl flex"> <div class="relative flex text-center font-mono text-2xl font-semibold">
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros(statsUsage)}</span><span <span class="text-[#DCDADA] dark:text-[#525252]">{zeros(statsUsage)}</span><span
class="text-immich-primary dark:text-immich-dark-primary">{statsUsage}</span class="text-immich-primary dark:text-immich-dark-primary">{statsUsage}</span
> >
<span class="text-center my-auto ml-2 text-base font-light text-gray-400">{statsUsageUnit}</span> <span class="my-auto ml-2 text-center text-base font-light text-gray-400">{statsUsageUnit}</span>
</div> </div>
</div> </div>
</div> </div>
@ -79,28 +79,28 @@
<div> <div>
<p class="text-sm dark:text-immich-dark-fg">USER USAGE DETAIL</p> <p class="text-sm dark:text-immich-dark-fg">USER USAGE DETAIL</p>
<table class="text-left w-full mt-5"> <table class="mt-5 w-full text-left">
<thead <thead
class="border rounded-md mb-4 bg-gray-50 dark:bg-immich-dark-gray dark:border-immich-dark-gray flex text-immich-primary dark:text-immich-dark-primary w-full h-12" class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary"
> >
<tr class="flex w-full place-items-center"> <tr class="flex w-full place-items-center">
<th class="text-center w-1/4 font-medium text-sm">User</th> <th class="w-1/4 text-center text-sm font-medium">User</th>
<th class="text-center w-1/4 font-medium text-sm">Photos</th> <th class="w-1/4 text-center text-sm font-medium">Photos</th>
<th class="text-center w-1/4 font-medium text-sm">Videos</th> <th class="w-1/4 text-center text-sm font-medium">Videos</th>
<th class="text-center w-1/4 font-medium text-sm">Size</th> <th class="w-1/4 text-center text-sm font-medium">Size</th>
</tr> </tr>
</thead> </thead>
<tbody <tbody
class="overflow-y-auto rounded-md w-full max-h-[320px] block border dark:border-immich-dark-gray dark:text-immich-dark-fg" class="block max-h-[320px] w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg"
> >
{#each stats.usageByUser as user (user.userId)} {#each stats.usageByUser as user (user.userId)}
<tr <tr
class="text-center flex place-items-center w-full h-[50px] even:bg-immich-bg even:dark:bg-immich-dark-gray/50 odd:bg-immich-gray odd:dark:bg-immich-dark-gray/75" class="flex h-[50px] w-full place-items-center text-center odd:bg-immich-gray even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50"
> >
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.userFirstName} {user.userLastName}</td> <td class="w-1/4 text-ellipsis px-2 text-sm">{user.userFirstName} {user.userLastName}</td>
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.photos.toLocaleString($locale)}</td> <td class="w-1/4 text-ellipsis px-2 text-sm">{user.photos.toLocaleString($locale)}</td>
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.videos.toLocaleString($locale)}</td> <td class="w-1/4 text-ellipsis px-2 text-sm">{user.videos.toLocaleString($locale)}</td>
<td class="text-sm px-2 w-1/4 text-ellipsis">{asByteUnitString(user.usage, $locale)}</td> <td class="w-1/4 text-ellipsis px-2 text-sm">{asByteUnitString(user.usage, $locale)}</td>
</tr> </tr>
{/each} {/each}
</tbody> </tbody>

View file

@ -15,13 +15,13 @@
}; };
</script> </script>
<div class="w-[250px] h-[140px] bg-immich-gray dark:bg-immich-dark-gray rounded-3xl p-5 flex flex-col justify-between"> <div class="flex h-[140px] w-[250px] flex-col justify-between rounded-3xl bg-immich-gray p-5 dark:bg-immich-dark-gray">
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary"> <div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<svelte:component this={logo} size="40" /> <svelte:component this={logo} size="40" />
<p>{title}</p> <p>{title}</p>
</div> </div>
<div class="relative text-center font-mono font-semibold text-2xl"> <div class="relative text-center font-mono text-2xl font-semibold">
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span <span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span
class="text-immich-primary dark:text-immich-dark-primary">{value}</span class="text-immich-primary dark:text-immich-dark-primary">{value}</span
> >

View file

@ -79,7 +79,7 @@
{#await getConfigs() then} {#await getConfigs() then}
<div in:fade={{ duration: 500 }}> <div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault> <form autocomplete="off" on:submit|preventDefault>
<div class="flex flex-col gap-4 ml-4 mt-4"> <div class="ml-4 mt-4 flex flex-col gap-4">
<SettingInputField <SettingInputField
inputType={SettingInputFieldType.NUMBER} inputType={SettingInputFieldType.NUMBER}
label="CONSTANT RATE FACTOR (-crf)" label="CONSTANT RATE FACTOR (-crf)"

View file

@ -75,7 +75,7 @@
<div in:fade={{ duration: 500 }}> <div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault> <form autocomplete="off" on:submit|preventDefault>
{#each jobNames as jobName} {#each jobNames as jobName}
<div class="flex flex-col gap-4 ml-4 mt-4"> <div class="ml-4 mt-4 flex flex-col gap-4">
<SettingInputField <SettingInputField
inputType={SettingInputFieldType.NUMBER} inputType={SettingInputFieldType.NUMBER}
label="{api.getJobName(jobName)} Concurrency" label="{api.getJobName(jobName)} Concurrency"

View file

@ -107,7 +107,7 @@
<div class="mt-2"> <div class="mt-2">
{#await getConfigs() then} {#await getConfigs() then}
<div in:fade={{ duration: 500 }}> <div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault class="flex flex-col mx-4 gap-4 py-4"> <form autocomplete="off" on:submit|preventDefault class="mx-4 flex flex-col gap-4 py-4">
<p class="text-sm dark:text-immich-dark-fg"> <p class="text-sm dark:text-immich-dark-fg">
For more details about this feature, refer to the <a For more details about this feature, refer to the <a
href="http://immich.app/docs/administration/oauth#mobile-redirect-uri" href="http://immich.app/docs/administration/oauth#mobile-redirect-uri"

View file

@ -96,7 +96,7 @@
{#await getConfigs() then} {#await getConfigs() then}
<div in:fade={{ duration: 500 }}> <div in:fade={{ duration: 500 }}>
<form autocomplete="off" on:submit|preventDefault> <form autocomplete="off" on:submit|preventDefault>
<div class="flex flex-col gap-4 ml-4 mt-4"> <div class="ml-4 mt-4 flex flex-col gap-4">
<div class="ml-4"> <div class="ml-4">
<SettingSwitch <SettingSwitch
title="ENABLED" title="ENABLED"

View file

@ -7,8 +7,8 @@
const toggle = () => (isOpen = !isOpen); const toggle = () => (isOpen = !isOpen);
</script> </script>
<div class="border-b-[1px] border-gray-200 dark:border-gray-700 py-4"> <div class="border-b-[1px] border-gray-200 py-4 dark:border-gray-700">
<div class="flex justify-between place-items-center"> <div class="flex place-items-center justify-between">
<div> <div>
<h2 class="font-medium text-immich-primary dark:text-immich-dark-primary"> <h2 class="font-medium text-immich-primary dark:text-immich-dark-primary">
{title} {title}
@ -20,7 +20,7 @@
<button <button
on:click={toggle} on:click={toggle}
aria-expanded={isOpen} aria-expanded={isOpen}
class="immich-circle-icon-button hover:bg-immich-primary/10 dark:text-immich-dark-fg hover:dark:bg-immich-dark-primary/20 rounded-full p-3 flex place-items-center place-content-center transition-all" class="immich-circle-icon-button flex place-content-center place-items-center rounded-full p-3 transition-all hover:bg-immich-primary/10 dark:text-immich-dark-fg hover:dark:bg-immich-dark-primary/20"
> >
<svg <svg
style="tran" style="tran"

View file

@ -7,12 +7,12 @@
export let showResetToDefault = true; export let showResetToDefault = true;
</script> </script>
<div class="flex justify-between gap-2 mt-8"> <div class="mt-8 flex justify-between gap-2">
<div class="left"> <div class="left">
{#if showResetToDefault} {#if showResetToDefault}
<button <button
on:click={() => dispatch('reset-to-default')} on:click={() => dispatch('reset-to-default')}
class="text-sm dark:text-immich-dark-primary hover:dark:text-immich-dark-primary/75 text-immich-primary hover:text-immich-primary/75 font-medium bg-none" class="bg-none text-sm font-medium text-immich-primary hover:text-immich-primary/75 dark:text-immich-dark-primary hover:dark:text-immich-dark-primary/75"
> >
Reset to default Reset to default
</button> </button>

View file

@ -28,7 +28,7 @@
</script> </script>
<div class="w-full"> <div class="w-full">
<div class={`flex place-items-center gap-1 h-[26px]`}> <div class={`flex h-[26px] place-items-center gap-1`}>
<label class={`immich-form-label text-sm`} for={label}>{label}</label> <label class={`immich-form-label text-sm`} for={label}>{label}</label>
{#if required} {#if required}
<div class="text-red-400">*</div> <div class="text-red-400">*</div>
@ -37,7 +37,7 @@
{#if isEdited} {#if isEdited}
<div <div
transition:fly={{ x: 10, duration: 200, easing: quintOut }} transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]" class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
> >
Unsaved change Unsaved change
</div> </div>
@ -45,13 +45,13 @@
</div> </div>
{#if desc} {#if desc}
<p class="immich-form-label text-xs pb-2" id="{label}-desc"> <p class="immich-form-label pb-2 text-xs" id="{label}-desc">
{desc} {desc}
</p> </p>
{/if} {/if}
<input <input
class="immich-form-input pb-2 w-full" class="immich-form-input w-full pb-2"
aria-describedby={desc ? `${label}-desc` : undefined} aria-describedby={desc ? `${label}-desc` : undefined}
aria-labelledby="{label}-label" aria-labelledby="{label}-label"
id={label} id={label}

View file

@ -15,13 +15,13 @@
</script> </script>
<div class="w-full"> <div class="w-full">
<div class={`flex place-items-center gap-1 h-[26px]`}> <div class={`flex h-[26px] place-items-center gap-1`}>
<label class={`immich-form-label text-sm`} for="{name}-select">{label}</label> <label class={`immich-form-label text-sm`} for="{name}-select">{label}</label>
{#if isEdited} {#if isEdited}
<div <div
transition:fly={{ x: 10, duration: 200, easing: quintOut }} transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]" class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
> >
Unsaved change Unsaved change
</div> </div>
@ -29,13 +29,13 @@
</div> </div>
{#if desc} {#if desc}
<p class="immich-form-label text-xs pb-2" id="{name}-desc"> <p class="immich-form-label pb-2 text-xs" id="{name}-desc">
{desc} {desc}
</p> </p>
{/if} {/if}
<select <select
class="immich-form-input pb-2 w-full" class="immich-form-input w-full pb-2"
aria-describedby={desc ? `${name}-desc` : undefined} aria-describedby={desc ? `${name}-desc` : undefined}
{name} {name}
id="{name}-select" id="{name}-select"

View file

@ -9,16 +9,16 @@
export let isEdited = false; export let isEdited = false;
</script> </script>
<div class="flex justify-between place-items-center"> <div class="flex place-items-center justify-between">
<div> <div>
<div class="flex place-items-center gap-1 h-[26px]"> <div class="flex h-[26px] place-items-center gap-1">
<label class="immich-form-label text-sm" for={title}> <label class="immich-form-label text-sm" for={title}>
{title} {title}
</label> </label>
{#if isEdited} {#if isEdited}
<div <div
transition:fly={{ x: 10, duration: 200, easing: quintOut }} transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="bg-orange-100 px-2 rounded-full text-orange-900 text-[10px]" class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
> >
Unsaved change Unsaved change
</div> </div>
@ -28,8 +28,8 @@
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p> <p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
</div> </div>
<label class="relative inline-block flex-none w-[36px] h-[10px]"> <label class="relative inline-block h-[10px] w-[36px] flex-none">
<input class="opacity-0 w-0 h-0 disabled::cursor-not-allowed" type="checkbox" bind:checked on:click {disabled} /> <input class="disabled::cursor-not-allowed h-0 w-0 opacity-0" type="checkbox" bind:checked on:click {disabled} />
{#if disabled} {#if disabled}
<span class="slider-disable" /> <span class="slider-disable" />

View file

@ -133,7 +133,7 @@
<section class="dark:text-immich-dark-fg"> <section class="dark:text-immich-dark-fg">
{#await getConfigs() then} {#await getConfigs() then}
<div id="directory-path-builder" class="m-4"> <div id="directory-path-builder" class="m-4">
<h3 class="font-medium text-immich-primary dark:text-immich-dark-primary text-base">Variables</h3> <h3 class="text-base font-medium text-immich-primary dark:text-immich-dark-primary">Variables</h3>
<section class="support-date"> <section class="support-date">
{#await getSupportDateTimeFormat()} {#await getSupportDateTimeFormat()}
@ -150,9 +150,9 @@
</section> </section>
<div class="mt-4 flex flex-col"> <div class="mt-4 flex flex-col">
<h3 class="font-medium text-immich-primary dark:text-immich-dark-primary text-base">Template</h3> <h3 class="text-base font-medium text-immich-primary dark:text-immich-dark-primary">Template</h3>
<div class="text-xs my-2"> <div class="my-2 text-xs">
<h4>PREVIEW</h4> <h4>PREVIEW</h4>
</div> </div>
@ -167,17 +167,17 @@
<code>{user.storageLabel || user.id}</code> is the user's Storage Label <code>{user.storageLabel || user.id}</code> is the user's Storage Label
</p> </p>
<p class="text-xs p-4 bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg py-2 rounded-lg mt-2"> <p class="mt-2 rounded-lg bg-gray-200 p-4 py-2 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
<span class="text-immich-fg/25 dark:text-immich-dark-fg/50" <span class="text-immich-fg/25 dark:text-immich-dark-fg/50"
>UPLOAD_LOCATION/{user.storageLabel || user.id}</span >UPLOAD_LOCATION/{user.storageLabel || user.id}</span
>/{parsedTemplate()}.jpg >/{parsedTemplate()}.jpg
</p> </p>
<form autocomplete="off" class="flex flex-col" on:submit|preventDefault> <form autocomplete="off" class="flex flex-col" on:submit|preventDefault>
<div class="flex flex-col my-2"> <div class="my-2 flex flex-col">
<label class="text-xs" for="presets">PRESET</label> <label class="text-xs" for="presets">PRESET</label>
<select <select
class="text-sm bg-slate-200 p-2 rounded-lg mt-2 dark:bg-gray-600 hover:cursor-pointer" class="mt-2 rounded-lg bg-slate-200 p-2 text-sm hover:cursor-pointer dark:bg-gray-600"
name="presets" name="presets"
id="preset-select" id="preset-select"
bind:value={selectedPreset} bind:value={selectedPreset}
@ -202,7 +202,7 @@
</div> </div>
</div> </div>
<div id="migration-info" class="text-sm mt-4"> <div id="migration-info" class="mt-4 text-sm">
<p> <p>
Template changes will only apply to new assets. To retroactively apply the template to previously uploaded Template changes will only apply to new assets. To retroactively apply the template to previously uploaded
assets, run the <a href="/admin/jobs-status" class="text-immich-primary dark:text-immich-dark-primary" assets, run the <a href="/admin/jobs-status" class="text-immich-primary dark:text-immich-dark-primary"

View file

@ -9,18 +9,18 @@
}; };
</script> </script>
<div class="text-xs mt-2"> <div class="mt-2 text-xs">
<h4>DATE & TIME</h4> <h4>DATE & TIME</h4>
</div> </div>
<div class="text-xs bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg p-4 mt-2 rounded-lg"> <div class="mt-2 rounded-lg bg-gray-200 p-4 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
<div class="mb-2 text-gray-600 dark:text-immich-dark-fg"> <div class="mb-2 text-gray-600 dark:text-immich-dark-fg">
<p>Asset's creation timestamp is used for the datetime information</p> <p>Asset's creation timestamp is used for the datetime information</p>
<p>Sample time 2022-09-04T20:03:05.250</p> <p>Sample time 2022-09-04T20:03:05.250</p>
</div> </div>
<div class="flex gap-[50px]"> <div class="flex gap-[50px]">
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">YEAR</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">YEAR</p>
<ul> <ul>
{#each options.yearOptions as yearFormat} {#each options.yearOptions as yearFormat}
<li>{'{{'}{yearFormat}{'}}'} - {getLuxonExample(yearFormat)}</li> <li>{'{{'}{yearFormat}{'}}'} - {getLuxonExample(yearFormat)}</li>
@ -29,7 +29,7 @@
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">MONTH</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">MONTH</p>
<ul> <ul>
{#each options.monthOptions as monthFormat} {#each options.monthOptions as monthFormat}
<li>{'{{'}{monthFormat}{'}}'} - {getLuxonExample(monthFormat)}</li> <li>{'{{'}{monthFormat}{'}}'} - {getLuxonExample(monthFormat)}</li>
@ -38,7 +38,7 @@
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">DAY</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">DAY</p>
<ul> <ul>
{#each options.dayOptions as dayFormat} {#each options.dayOptions as dayFormat}
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li> <li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
@ -47,7 +47,7 @@
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">HOUR</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">HOUR</p>
<ul> <ul>
{#each options.hourOptions as dayFormat} {#each options.hourOptions as dayFormat}
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li> <li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
@ -56,7 +56,7 @@
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">MINUTE</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">MINUTE</p>
<ul> <ul>
{#each options.minuteOptions as dayFormat} {#each options.minuteOptions as dayFormat}
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li> <li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>
@ -65,7 +65,7 @@
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">SECOND</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">SECOND</p>
<ul> <ul>
{#each options.secondOptions as dayFormat} {#each options.secondOptions as dayFormat}
<li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li> <li>{'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}</li>

View file

@ -1,25 +1,25 @@
<div class="text-xs mt-4"> <div class="mt-4 text-xs">
<h4>OTHER VARIABLES</h4> <h4>OTHER VARIABLES</h4>
</div> </div>
<div class="text-xs bg-gray-200 dark:bg-gray-700 dark:text-immich-dark-fg p-4 mt-2 rounded-lg"> <div class="mt-2 rounded-lg bg-gray-200 p-4 text-xs dark:bg-gray-700 dark:text-immich-dark-fg">
<div class="flex gap-[50px]"> <div class="flex gap-[50px]">
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE NAME</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE NAME</p>
<ul> <ul>
<li>{`{{filename}}`}</li> <li>{`{{filename}}`}</li>
</ul> </ul>
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE EXTENSION</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE EXTENSION</p>
<ul> <ul>
<li>{`{{ext}}`}</li> <li>{`{{ext}}`}</li>
</ul> </ul>
</div> </div>
<div> <div>
<p class="text-immich-primary font-medium dark:text-immich-dark-primary">FILE TYPE</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">FILE TYPE</p>
<ul> <ul>
<li>{`{{filetype}}`} - VID or IMG</li> <li>{`{{filetype}}`} - VID or IMG</li>
<li>{`{{filetypefull}}`} - VIDEO or IMAGE</li> <li>{`{{filetypefull}}`} - VIDEO or IMAGE</li>

View file

@ -60,7 +60,7 @@
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div <div
class="group hover:cursor-pointer mt-4 border-[3px] border-transparent dark:hover:border-immich-dark-primary/75 hover:border-immich-primary/75 rounded-3xl p-5 relative" class="group relative mt-4 rounded-3xl border-[3px] border-transparent p-5 hover:cursor-pointer hover:border-immich-primary/75 dark:hover:border-immich-dark-primary/75"
on:click={() => dispatchClick('click', album)} on:click={() => dispatchClick('click', album)}
on:keydown={() => dispatchClick('click', album)} on:keydown={() => dispatchClick('click', album)}
data-testid="album-card" data-testid="album-card"
@ -69,7 +69,7 @@
{#if showContextMenu} {#if showContextMenu}
<div <div
id={`icon-${album.id}`} id={`icon-${album.id}`}
class="absolute top-6 right-6 z-10" class="absolute right-6 top-6 z-10"
on:click|stopPropagation|preventDefault={showAlbumContextMenu} on:click|stopPropagation|preventDefault={showAlbumContextMenu}
data-testid="context-button-parent" data-testid="context-button-parent"
> >
@ -79,16 +79,16 @@
</div> </div>
{/if} {/if}
<div class={`aspect-square relative`}> <div class={`relative aspect-square`}>
<img <img
src={imageData} src={imageData}
alt={album.id} alt={album.id}
class={`object-cover h-full w-full transition-all z-0 rounded-3xl duration-300 hover:shadow-lg`} class={`z-0 h-full w-full rounded-3xl object-cover transition-all duration-300 hover:shadow-lg`}
data-testid="album-image" data-testid="album-image"
draggable="false" draggable="false"
/> />
<div <div
class="w-full h-full absolute top-0 rounded-3xl {isSharingView class="absolute top-0 h-full w-full rounded-3xl {isSharingView
? 'group-hover:bg-yellow-800/25' ? 'group-hover:bg-yellow-800/25'
: 'group-hover:bg-indigo-800/25'} " : 'group-hover:bg-indigo-800/25'} "
/> />
@ -96,14 +96,14 @@
<div class="mt-4"> <div class="mt-4">
<p <p
class="text-xl font-semibold dark:text-immich-dark-primary text-immich-primary w-full truncate" class="w-full truncate text-xl font-semibold text-immich-primary dark:text-immich-dark-primary"
data-testid="album-name" data-testid="album-name"
title={album.albumName} title={album.albumName}
> >
{album.albumName} {album.albumName}
</p> </p>
<span class="text-sm flex gap-2 dark:text-immich-dark-fg" data-testid="album-details"> <span class="flex gap-2 text-sm dark:text-immich-dark-fg" data-testid="album-details">
{#if showItemCount} {#if showItemCount}
<p> <p>
{album.assetCount.toLocaleString($locale)} {album.assetCount.toLocaleString($locale)}

View file

@ -298,7 +298,7 @@
{#if isPublicShared && !isOwned} {#if isPublicShared && !isOwned}
<a <a
data-sveltekit-preload-data="hover" data-sveltekit-preload-data="hover"
class="flex gap-2 place-items-center hover:cursor-pointer ml-6" class="ml-6 flex place-items-center gap-2 hover:cursor-pointer"
href="https://immich.app" href="https://immich.app"
> >
<ImmichLogo height={30} width={30} /> <ImmichLogo height={30} width={30} />
@ -377,7 +377,7 @@
</ControlAppBar> </ControlAppBar>
{/if} {/if}
<section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40"> <section class="my-[160px] flex flex-col px-6 sm:px-12 md:px-24 lg:px-40">
<input <input
on:keydown={(e) => { on:keydown={(e) => {
if (e.key == 'Enter') { if (e.key == 'Enter') {
@ -387,9 +387,9 @@
}} }}
on:focus={() => (isEditingTitle = true)} on:focus={() => (isEditingTitle = true)}
on:blur={() => (isEditingTitle = false)} on:blur={() => (isEditingTitle = false)}
class={`transition-all text-6xl text-immich-primary dark:text-immich-dark-primary w-[99%] border-b-2 border-transparent outline-none ${ class={`w-[99%] border-b-2 border-transparent text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary ${
isOwned ? 'hover:border-gray-400' : 'hover:border-transparent' isOwned ? 'hover:border-gray-400' : 'hover:border-transparent'
} focus:outline-none focus:border-b-2 focus:border-immich-primary dark:focus:border-immich-dark-primary bg-immich-bg dark:bg-immich-dark-bg dark:focus:bg-immich-dark-gray`} } bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray`}
type="text" type="text"
bind:value={album.albumName} bind:value={album.albumName}
disabled={!isOwned} disabled={!isOwned}
@ -397,14 +397,14 @@
/> />
{#if album.assetCount > 0} {#if album.assetCount > 0}
<span class="flex gap-2 my-4 text-sm text-gray-500 font-medium" data-testid="album-details"> <span class="my-4 flex gap-2 text-sm font-medium text-gray-500" data-testid="album-details">
<p class="">{getDateRange()}</p> <p class="">{getDateRange()}</p>
<p>·</p> <p>·</p>
<p>{album.assetCount} items</p> <p>{album.assetCount} items</p>
</span> </span>
{/if} {/if}
{#if album.shared} {#if album.shared}
<div class="flex my-6 gap-x-1"> <div class="my-6 flex gap-x-1">
{#each album.sharedUsers as user (user.id)} {#each album.sharedUsers as user (user.id)}
<button on:click={() => (isShowShareInfoModal = true)}> <button on:click={() => (isShowShareInfoModal = true)}>
<UserAvatar {user} size="md" autoColor /> <UserAvatar {user} size="md" autoColor />
@ -415,7 +415,7 @@
style:display={isOwned ? 'block' : 'none'} style:display={isOwned ? 'block' : 'none'}
on:click={() => (isShowShareUserSelection = true)} on:click={() => (isShowShareUserSelection = true)}
title="Add more users" title="Add more users"
class="h-12 w-12 border bg-white transition-colors hover:bg-gray-300 text-3xl flex place-items-center place-content-center rounded-full" class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-white text-3xl transition-colors hover:bg-gray-300"
>+</button >+</button
> >
</div> </div>
@ -430,7 +430,7 @@
<p class="text-xs dark:text-immich-dark-fg">ADD PHOTOS</p> <p class="text-xs dark:text-immich-dark-fg">ADD PHOTOS</p>
<button <button
on:click={() => (isShowAssetSelection = true)} on:click={() => (isShowAssetSelection = true)}
class="w-full py-8 border bg-immich-bg dark:bg-immich-dark-gray text-immich-fg dark:text-immich-dark-fg dark:hover:text-immich-dark-primary rounded-md mt-5 flex place-items-center gap-6 px-8 transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none" class="mt-5 flex w-full place-items-center gap-6 rounded-md border bg-immich-bg px-8 py-8 text-immich-fg transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none dark:bg-immich-dark-gray dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
> >
<span class="text-text-immich-primary dark:text-immich-dark-primary"><Plus size="24" /> </span> <span class="text-text-immich-primary dark:text-immich-dark-primary"><Plus size="24" /> </span>
<span class="text-lg">Select photos</span> <span class="text-lg">Select photos</span>

View file

@ -35,7 +35,7 @@
<section <section
transition:fly={{ y: 500, duration: 100, easing: quintOut }} transition:fly={{ y: 500, duration: 100, easing: quintOut }}
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]" class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
> >
<ControlAppBar <ControlAppBar
on:close-button-click={() => { on:close-button-click={() => {
@ -56,14 +56,14 @@
<svelte:fragment slot="trailing"> <svelte:fragment slot="trailing">
<button <button
on:click={handleSelectFromComputerClicked} on:click={handleSelectFromComputerClicked}
class="text-immich-primary dark:text-immich-dark-primary text-sm hover:bg-immich-primary/10 dark:hover:bg-immich-dark-primary/25 transition-all px-6 py-2 rounded-lg font-medium" class="rounded-lg px-6 py-2 text-sm font-medium text-immich-primary transition-all hover:bg-immich-primary/10 dark:text-immich-dark-primary dark:hover:bg-immich-dark-primary/25"
> >
Select from computer Select from computer
</button> </button>
<Button size="sm" rounded="lg" disabled={$selectedAssets.size === 0} on:click={addSelectedAssets}>Done</Button> <Button size="sm" rounded="lg" disabled={$selectedAssets.size === 0} on:click={addSelectedAssets}>Done</Button>
</svelte:fragment> </svelte:fragment>
</ControlAppBar> </ControlAppBar>
<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg"> <section class="grid h-screen bg-immich-bg pl-[70px] pt-[100px] dark:bg-immich-dark-bg">
<AssetGrid isAlbumSelectionMode={true} /> <AssetGrid isAlbumSelectionMode={true} />
</section> </section>
</section> </section>

View file

@ -73,19 +73,19 @@
{#if !selectedRemoveUser} {#if !selectedRemoveUser}
<BaseModal on:close={() => dispatch('close')}> <BaseModal on:close={() => dispatch('close')}>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Options</p> <p class="font-medium text-immich-fg dark:text-immich-dark-fg">Options</p>
</span> </span>
</svelte:fragment> </svelte:fragment>
<section class="max-h-[400px] overflow-y-auto immich-scrollbar pb-4"> <section class="immich-scrollbar max-h-[400px] overflow-y-auto pb-4">
{#each album.sharedUsers as user} {#each album.sharedUsers as user}
<div <div
class="flex gap-4 p-5 place-items-center justify-between w-full transition-colors hover:bg-gray-50 dark:hover:bg-gray-700" class="flex w-full place-items-center justify-between gap-4 p-5 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
> >
<div class="flex gap-4 place-items-center"> <div class="flex place-items-center gap-4">
<UserAvatar {user} size="md" autoColor /> <UserAvatar {user} size="md" autoColor />
<p class="font-medium text-sm">{user.firstName} {user.lastName}</p> <p class="text-sm font-medium">{user.firstName} {user.lastName}</p>
</div> </div>
<div id={`icon-${user.id}`} class="flex place-items-center"> <div id={`icon-${user.id}`} class="flex place-items-center">
@ -108,7 +108,7 @@
{:else if user.id == currentUser?.id} {:else if user.id == currentUser?.id}
<button <button
on:click={() => (selectedRemoveUser = user)} on:click={() => (selectedRemoveUser = user)}
class="text-sm text-immich-primary dark:text-immich-dark-primary font-medium transition-colors hover:text-immich-primary/75" class="text-sm font-medium text-immich-primary transition-colors hover:text-immich-primary/75 dark:text-immich-dark-primary"
>Leave</button >Leave</button
> >
{/if} {/if}

View file

@ -23,7 +23,7 @@
<section <section
transition:fly={{ y: 500, duration: 100, easing: quintOut }} transition:fly={{ y: 500, duration: 100, easing: quintOut }}
class="absolute top-0 left-0 w-full h-full py-[160px] bg-immich-bg dark:bg-immich-dark-bg z-[9999]" class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg py-[160px] dark:bg-immich-dark-bg"
> >
<ControlAppBar on:close-button-click={() => dispatch('close')}> <ControlAppBar on:close-button-click={() => dispatch('close')}>
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
@ -42,7 +42,7 @@
</svelte:fragment> </svelte:fragment>
</ControlAppBar> </ControlAppBar>
<section class="flex flex-wrap gap-14 px-20 overflow-y-auto"> <section class="flex flex-wrap gap-14 overflow-y-auto px-20">
<!-- Image grid --> <!-- Image grid -->
<div class="flex flex-wrap gap-[2px]"> <div class="flex flex-wrap gap-[2px]">
{#each album.assets as asset} {#each album.assets as asset}

View file

@ -55,22 +55,22 @@
<BaseModal on:close={() => dispatch('close')}> <BaseModal on:close={() => dispatch('close')}>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<ImmichLogo width={24} /> <ImmichLogo width={24} />
<p class="font-medium">Invite to album</p> <p class="font-medium">Invite to album</p>
</span> </span>
</svelte:fragment> </svelte:fragment>
<div class="max-h-[300px] overflow-y-auto immich-scrollbar"> <div class="immich-scrollbar max-h-[300px] overflow-y-auto">
{#if selectedUsers.length > 0} {#if selectedUsers.length > 0}
<div class="flex gap-4 py-2 px-5 overflow-x-auto place-items-center mb-2"> <div class="mb-2 flex place-items-center gap-4 overflow-x-auto px-5 py-2">
<p class="font-medium">To</p> <p class="font-medium">To</p>
{#each selectedUsers as user} {#each selectedUsers as user}
{#key user.id} {#key user.id}
<button <button
on:click={() => deselectUser(user)} on:click={() => deselectUser(user)}
class="flex gap-1 place-items-center border border-gray-400 rounded-full p-1 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors" class="flex place-items-center gap-1 rounded-full border border-gray-400 p-1 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
> >
<UserAvatar {user} size="sm" autoColor /> <UserAvatar {user} size="sm" autoColor />
<p class="text-xs font-medium">{user.firstName} {user.lastName}</p> <p class="text-xs font-medium">{user.firstName} {user.lastName}</p>
@ -81,17 +81,17 @@
{/if} {/if}
{#if users.length > 0} {#if users.length > 0}
<p class="text-xs font-medium px-5">SUGGESTIONS</p> <p class="px-5 text-xs font-medium">SUGGESTIONS</p>
<div class="my-4"> <div class="my-4">
{#each users as user} {#each users as user}
<button <button
on:click={() => selectUser(user)} on:click={() => selectUser(user)}
class="w-full flex place-items-center gap-4 py-4 px-5 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all" class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700"
> >
{#if selectedUsers.includes(user)} {#if selectedUsers.includes(user)}
<span <span
class="bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-bg rounded-full w-12 h-12 border flex place-items-center place-content-center text-3xl dark:border-immich-dark-gray" class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg"
>✓</span >✓</span
> >
{:else} {:else}
@ -111,7 +111,7 @@
{/each} {/each}
</div> </div>
{:else} {:else}
<p class="text-sm p-5"> <p class="p-5 text-sm">
Looks like you have shared this album with all users or you don't have any user to share with. Looks like you have shared this album with all users or you don't have any user to share with.
</p> </p>
{/if} {/if}
@ -124,9 +124,9 @@
</div> </div>
<hr /> <hr />
<div id="shared-buttons" class="flex my-4 justify-around place-items-center place-content-center"> <div id="shared-buttons" class="my-4 flex place-content-center place-items-center justify-around">
<button <button
class="flex flex-col gap-2 place-items-center place-content-center hover:cursor-pointer" class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"
on:click={onSharedLinkClick} on:click={onSharedLinkClick}
> >
<Link size={24} /> <Link size={24} />
@ -135,7 +135,7 @@
{#if sharedLinks.length} {#if sharedLinks.length}
<button <button
class="flex flex-col gap-2 place-items-center place-content-center hover:cursor-pointer" class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"
on:click={() => goto(AppRoute.SHARED_LINKS)} on:click={() => goto(AppRoute.SHARED_LINKS)}
> >
<ShareCircle size={24} /> <ShareCircle size={24} />

View file

@ -25,20 +25,20 @@
<button <button
on:click={() => dispatcher('album')} on:click={() => dispatcher('album')}
class="w-full flex gap-4 px-6 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors" class="flex w-full gap-4 px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
> >
<div class="h-12 w-12 rounded-xl bg-slate-300"> <div class="h-12 w-12 rounded-xl bg-slate-300">
{#if album.albumThumbnailAssetId} {#if album.albumThumbnailAssetId}
<img <img
src={api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)} src={api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)}
alt={album.albumName} alt={album.albumName}
class={`object-cover h-full w-full transition-all z-0 rounded-xl duration-300 hover:shadow-lg`} class={`z-0 h-full w-full rounded-xl object-cover transition-all duration-300 hover:shadow-lg`}
data-testid="album-image" data-testid="album-image"
draggable="false" draggable="false"
/> />
{/if} {/if}
</div> </div>
<div class="h-12 flex flex-col items-start justify-center"> <div class="flex h-12 flex-col items-start justify-center">
<span>{albumNameArray[0]}<b>{albumNameArray[1]}</b>{albumNameArray[2]}</span> <span>{albumNameArray[0]}<b>{albumNameArray[1]}</b>{albumNameArray[2]}</span>
<span class="flex gap-1 text-sm"> <span class="flex gap-1 text-sm">
{#if variant === 'simple'} {#if variant === 'simple'}

View file

@ -46,12 +46,12 @@
</script> </script>
<div <div
class="h-16 flex justify-between place-items-center px-3 transition-transform duration-200 z-[1001] bg-gradient-to-b from-black/40" class="z-[1001] flex h-16 place-items-center justify-between bg-gradient-to-b from-black/40 px-3 transition-transform duration-200"
> >
<div class="text-white"> <div class="text-white">
<CircleIconButton isOpacity={true} logo={ArrowLeft} on:click={() => dispatch('goBack')} /> <CircleIconButton isOpacity={true} logo={ArrowLeft} on:click={() => dispatch('goBack')} />
</div> </div>
<div class="text-white flex gap-2 justify-end w-[calc(100%-3rem)] overflow-hidden"> <div class="flex w-[calc(100%-3rem)] justify-end gap-2 overflow-hidden text-white">
{#if showMotionPlayButton} {#if showMotionPlayButton}
{#if isMotionPhotoPlaying} {#if isMotionPhotoPlaying}
<CircleIconButton <CircleIconButton

View file

@ -245,9 +245,9 @@
<section <section
id="immich-asset-viewer" id="immich-asset-viewer"
class="fixed h-screen w-screen left-0 top-0 overflow-y-hidden bg-black z-[1001] grid grid-rows-[64px_1fr] grid-cols-4" class="fixed left-0 top-0 z-[1001] grid h-screen w-screen grid-cols-4 grid-rows-[64px_1fr] overflow-y-hidden bg-black"
> >
<div class="col-start-1 col-span-4 row-start-1 row-span-1 z-[1000] transition-transform"> <div class="z-[1000] col-span-4 col-start-1 row-span-1 row-start-1 transition-transform">
<AssetViewerNavBar <AssetViewerNavBar
{asset} {asset}
isMotionPhotoPlaying={shouldPlayMotionPhoto} isMotionPhotoPlaying={shouldPlayMotionPhoto}
@ -270,17 +270,17 @@
</div> </div>
{#if showNavigation} {#if showNavigation}
<div class="row-start-2 row-span-1 col-start-1 column-span-1 justify-self-start mb-[60px] z-[999]"> <div class="column-span-1 z-[999] col-start-1 row-span-1 row-start-2 mb-[60px] justify-self-start">
<NavigationArea on:click={navigateAssetBackward}><ChevronLeft size="36" /></NavigationArea> <NavigationArea on:click={navigateAssetBackward}><ChevronLeft size="36" /></NavigationArea>
</div> </div>
{/if} {/if}
<div class="row-start-1 row-span-full col-start-1 col-span-4"> <div class="col-span-4 col-start-1 row-span-full row-start-1">
{#key asset.id} {#key asset.id}
{#if !asset.resized} {#if !asset.resized}
<div class="h-full w-full flex justify-center"> <div class="flex h-full w-full justify-center">
<div <div
class="h-full bg-gray-100 dark:bg-immich-dark-gray flex items-center justify-center aspect-square px-auto" class="px-auto flex aspect-square h-full items-center justify-center bg-gray-100 dark:bg-immich-dark-gray"
> >
<ImageBrokenVariant size="25%" /> <ImageBrokenVariant size="25%" />
</div> </div>
@ -303,7 +303,7 @@
</div> </div>
{#if showNavigation} {#if showNavigation}
<div class="row-start-2 row-span-1 col-start-4 col-span-1 justify-self-end mb-[60px] z-[999]"> <div class="z-[999] col-span-1 col-start-4 row-span-1 row-start-2 mb-[60px] justify-self-end">
<NavigationArea on:click={navigateAssetForward}><ChevronRight size="36" /></NavigationArea> <NavigationArea on:click={navigateAssetForward}><ChevronRight size="36" /></NavigationArea>
</div> </div>
{/if} {/if}
@ -312,7 +312,7 @@
<div <div
transition:fly={{ duration: 150 }} transition:fly={{ duration: 150 }}
id="detail-panel" id="detail-panel"
class="bg-immich-bg w-[360px] z-[1002] row-span-full transition-all overflow-y-auto dark:bg-immich-dark-bg dark:border-l dark:border-l-immich-dark-gray" class="z-[1002] row-span-full w-[360px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg"
translate="yes" translate="yes"
> >
<DetailPanel <DetailPanel

View file

@ -80,20 +80,20 @@
<section class="p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg"> <section class="p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg">
<div class="flex place-items-center gap-2"> <div class="flex place-items-center gap-2">
<button <button
class="rounded-full p-3 flex place-items-center place-content-center hover:bg-gray-200 transition-colors dark:text-immich-dark-fg dark:hover:bg-gray-900" class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
on:click={() => dispatch('close')} on:click={() => dispatch('close')}
> >
<Close size="24" /> <Close size="24" />
</button> </button>
<p class="text-immich-fg dark:text-immich-dark-fg text-lg">Info</p> <p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
</div> </div>
<section class="mx-4 mt-10"> <section class="mx-4 mt-10">
<textarea <textarea
bind:this={textarea} bind:this={textarea}
class="max-h-[500px] class="max-h-[500px]
text-base text-black bg-transparent dark:text-white border-b focus:border-b-2 border-gray-500 w-full focus:border-immich-primary dark:focus:border-immich-dark-primary transition-all resize-none overflow-hidden outline-none disabled:border-none" w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
placeholder={$page?.data?.user?.id !== asset.ownerId ? '' : 'Add a description'} placeholder={$page?.data?.user?.id !== asset.ownerId ? '' : 'Add a description'}
style:display={$page?.data?.user?.id !== asset.ownerId && textarea?.value == '' ? 'none' : 'block'} style:display={$page?.data?.user?.id !== asset.ownerId && textarea?.value == '' ? 'none' : 'block'}
on:focusin={handleFocusIn} on:focusin={handleFocusIn}
@ -108,7 +108,7 @@
<section class="px-4 py-4 text-sm"> <section class="px-4 py-4 text-sm">
<h2>PEOPLE</h2> <h2>PEOPLE</h2>
<div class="flex flex-wrap gap-2 mt-4"> <div class="mt-4 flex flex-wrap gap-2">
{#each people as person (person.id)} {#each people as person (person.id)}
<a href="/people/{person.id}" class="w-[90px]" on:click={() => dispatch('close-viewer')}> <a href="/people/{person.id}" class="w-[90px]" on:click={() => dispatch('close-viewer')}>
<ImageThumbnail <ImageThumbnail
@ -120,7 +120,7 @@
heightStyle="90px" heightStyle="90px"
thumbhash={null} thumbhash={null}
/> />
<p class="font-medium mt-1 truncate">{person.name}</p> <p class="mt-1 truncate font-medium">{person.name}</p>
</a> </a>
{/each} {/each}
</div> </div>
@ -178,7 +178,7 @@
<p class="break-all"> <p class="break-all">
{getAssetFilename(asset)} {getAssetFilename(asset)}
</p> </p>
<div class="flex text-sm gap-2"> <div class="flex gap-2 text-sm">
{#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth} {#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth}
{#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)} {#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)}
<p> <p>
@ -200,7 +200,7 @@
<div> <div>
<p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p> <p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p>
<div class="flex text-sm gap-2"> <div class="flex gap-2 text-sm">
<p>{`ƒ/${asset.exifInfo.fNumber.toLocaleString($locale)}` || ''}</p> <p>{`ƒ/${asset.exifInfo.fNumber.toLocaleString($locale)}` || ''}</p>
{#if asset.exifInfo.exposureTime} {#if asset.exifInfo.exposureTime}
@ -227,10 +227,10 @@
<div> <div>
<p>{asset.exifInfo.city}</p> <p>{asset.exifInfo.city}</p>
<div class="flex text-sm gap-2"> <div class="flex gap-2 text-sm">
<p>{asset.exifInfo.state}</p> <p>{asset.exifInfo.state}</p>
</div> </div>
<div class="flex text-sm gap-2"> <div class="flex gap-2 text-sm">
<p>{asset.exifInfo.country}</p> <p>{asset.exifInfo.country}</p>
</div> </div>
</div> </div>
@ -258,7 +258,7 @@
<section class="p-2 dark:text-immich-dark-fg"> <section class="p-2 dark:text-immich-dark-fg">
<div class="px-4 py-4"> <div class="px-4 py-4">
{#if albums.length > 0} {#if albums.length > 0}
<p class="text-sm pb-4">APPEARS IN</p> <p class="pb-4 text-sm">APPEARS IN</p>
{/if} {/if}
{#each albums as album} {#each albums as album}
<a data-sveltekit-preload-data="hover" href={`/albums/${album.id}`}> <a data-sveltekit-preload-data="hover" href={`/albums/${album.id}`}>
@ -271,14 +271,14 @@
<div> <div>
<img <img
alt={album.albumName} alt={album.albumName}
class="w-[50px] h-[50px] object-cover rounded" class="h-[50px] w-[50px] rounded object-cover"
src={album.albumThumbnailAssetId && src={album.albumThumbnailAssetId &&
api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)} api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
draggable="false" draggable="false"
/> />
</div> </div>
<div class="mt-auto mb-auto"> <div class="mb-auto mt-auto">
<p class="dark:text-immich-dark-primary">{album.albumName}</p> <p class="dark:text-immich-dark-primary">{album.albumName}</p>
<div class="flex gap-2 text-sm"> <div class="flex gap-2 text-sm">
<p>{album.assetCount} items</p> <p>{album.assetCount} items</p>

View file

@ -15,25 +15,25 @@
{#if $isDownloading} {#if $isDownloading}
<div <div
transition:fly={{ x: -100, duration: 350 }} transition:fly={{ x: -100, duration: 350 }}
class="w-[315px] max-h-[270px] bg-immich-bg border rounded-2xl shadow-sm absolute bottom-10 left-2 p-4 z-[10000] text-sm" class="absolute bottom-10 left-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border bg-immich-bg p-4 text-sm shadow-sm"
> >
<p class="text-gray-500 text-xs mb-2">DOWNLOADING</p> <p class="mb-2 text-xs text-gray-500">DOWNLOADING</p>
<div class="max-h-[200px] my-2 overflow-y-auto mb-2 flex flex-col text-sm"> <div class="my-2 mb-2 flex max-h-[200px] flex-col overflow-y-auto text-sm">
{#each Object.keys($downloadAssets) as downloadKey (downloadKey)} {#each Object.keys($downloadAssets) as downloadKey (downloadKey)}
{@const download = $downloadAssets[downloadKey]} {@const download = $downloadAssets[downloadKey]}
<div class="mb-2 flex place-items-center" transition:slide> <div class="mb-2 flex place-items-center" transition:slide>
<div class="w-full pr-10"> <div class="w-full pr-10">
<div class="font-medium text-xs flex gap-2 place-items-center justify-between"> <div class="flex place-items-center justify-between gap-2 text-xs font-medium">
<p class="truncate">{downloadKey}</p> <p class="truncate">{downloadKey}</p>
{#if download.total} {#if download.total}
<p class="whitespace-nowrap">{asByteUnitString(download.total, $locale)}</p> <p class="whitespace-nowrap">{asByteUnitString(download.total, $locale)}</p>
{/if} {/if}
</div> </div>
<div class="flex place-items-center gap-2"> <div class="flex place-items-center gap-2">
<div class="w-full bg-gray-200 rounded-full h-[7px] dark:bg-gray-700"> <div class="h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
<div class="bg-immich-primary h-[7px] rounded-full" style={`width: ${download.percentage}%`} /> <div class="h-[7px] rounded-full bg-immich-primary" style={`width: ${download.percentage}%`} />
</div> </div>
<p class="whitespace-nowrap min-w-[4em] text-right"> <p class="min-w-[4em] whitespace-nowrap text-right">
<span class="text-immich-primary">{download.percentage}%</span> <span class="text-immich-primary">{download.percentage}%</span>
</p> </p>
</div> </div>

View file

@ -2,8 +2,8 @@
</script> </script>
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="group h-full flex place-items-center" on:click on:keydown> <div class="group flex h-full place-items-center" on:click on:keydown>
<button class="rounded-full p-3 transition text-gray-500 mx-4 group-hover:text-white group-hover:bg-gray-500"> <button class="mx-4 rounded-full p-3 text-gray-500 transition group-hover:bg-gray-500 group-hover:text-white">
<slot /> <slot />
</button> </button>
</div> </div>

View file

@ -103,7 +103,7 @@
<div <div
bind:this={element} bind:this={element}
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}
class="flex place-items-center place-content-center h-full select-none" class="flex h-full select-none place-content-center place-items-center"
> >
{#await loadAssetData()} {#await loadAssetData()}
<LoadingSpinner /> <LoadingSpinner />
@ -113,7 +113,7 @@
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}
src={assetData} src={assetData}
alt={asset.id} alt={asset.id}
class="object-contain h-full w-full" class="h-full w-full object-contain"
draggable="false" draggable="false"
/> />
</div> </div>

View file

@ -22,7 +22,7 @@
}; };
</script> </script>
<div transition:fade={{ duration: 150 }} class="flex place-items-center place-content-center h-full select-none"> <div transition:fade={{ duration: 150 }} class="flex h-full select-none place-content-center place-items-center">
<video <video
controls controls
class="h-full object-contain" class="h-full object-contain"
@ -35,7 +35,7 @@
</video> </video>
{#if isVideoLoading} {#if isVideoLoading}
<div class="absolute flex place-items-center place-content-center"> <div class="absolute flex place-content-center place-items-center">
<LoadingSpinner /> <LoadingSpinner />
</div> </div>
{/if} {/if}

View file

@ -33,7 +33,7 @@
on:image-load|once={() => (complete = true)} on:image-load|once={() => (complete = true)}
/> />
{#if hidden} {#if hidden}
<div class="absolute top-1/2 left-1/2 transform translate-x-[-50%] translate-y-[-50%]"> <div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
<EyeOffOutline size="2em" /> <EyeOffOutline size="2em" />
</div> </div>
{/if} {/if}
@ -44,7 +44,7 @@
style:height={heightStyle} style:height={heightStyle}
src={thumbHashToDataURL(Buffer.from(thumbhash, 'base64'))} src={thumbHashToDataURL(Buffer.from(thumbhash, 'base64'))}
alt={altText} alt={altText}
class="absolute object-cover top-0" class="absolute top-0 object-cover"
class:rounded-lg={curve} class:rounded-lg={curve}
class:shadow-lg={shadow} class:shadow-lg={shadow}
class:rounded-full={circle} class:rounded-full={circle}

View file

@ -69,7 +69,7 @@
<div <div
style:width="{width}px" style:width="{width}px"
style:height="{height}px" style:height="{height}px"
class="relative group overflow-hidden {disabled class="group relative overflow-hidden {disabled
? 'bg-gray-300' ? 'bg-gray-300'
: 'bg-immich-primary/20 dark:bg-immich-dark-primary/20'}" : 'bg-immich-primary/20 dark:bg-immich-dark-primary/20'}"
class:cursor-not-allowed={disabled} class:cursor-not-allowed={disabled}
@ -80,7 +80,7 @@
on:keydown={thumbnailKeyDownHandler} on:keydown={thumbnailKeyDownHandler}
> >
{#if intersecting} {#if intersecting}
<div class="absolute w-full h-full z-20"> <div class="absolute z-20 h-full w-full">
<!-- Select asset button --> <!-- Select asset button -->
{#if !readonly && (mouseOver || selected || selectionCandidate)} {#if !readonly && (mouseOver || selected || selectionCandidate)}
<button <button
@ -103,12 +103,12 @@
</div> </div>
<div <div
class="h-full w-full bg-gray-100 dark:bg-immich-dark-gray absolute select-none transition-transform" class="absolute h-full w-full select-none bg-gray-100 transition-transform dark:bg-immich-dark-gray"
class:scale-[0.85]={selected} class:scale-[0.85]={selected}
> >
<!-- Gradient overlay on hover --> <!-- Gradient overlay on hover -->
<div <div
class="absolute w-full h-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 group-hover:opacity-100 transition-opacity z-10" class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100"
/> />
<!-- Favorite asset star --> <!-- Favorite asset star -->
@ -133,13 +133,13 @@
thumbhash={asset.thumbhash} thumbhash={asset.thumbhash}
/> />
{:else} {:else}
<div class="w-full h-full p-4 flex items-center justify-center"> <div class="flex h-full w-full items-center justify-center p-4">
<ImageBrokenVariant size="48" /> <ImageBrokenVariant size="48" />
</div> </div>
{/if} {/if}
{#if asset.type === AssetTypeEnum.Video} {#if asset.type === AssetTypeEnum.Video}
<div class="absolute w-full h-full top-0"> <div class="absolute top-0 h-full w-full">
<VideoThumbnail <VideoThumbnail
url={api.getAssetFileUrl(asset.id, false, true, publicSharedKey)} url={api.getAssetFileUrl(asset.id, false, true, publicSharedKey)}
enablePlayback={mouseOver} enablePlayback={mouseOver}
@ -149,7 +149,7 @@
{/if} {/if}
{#if asset.type === AssetTypeEnum.Image && asset.livePhotoVideoId} {#if asset.type === AssetTypeEnum.Image && asset.livePhotoVideoId}
<div class="absolute w-full h-full top-0"> <div class="absolute top-0 h-full w-full">
<VideoThumbnail <VideoThumbnail
url={api.getAssetFileUrl(asset.livePhotoVideoId, false, true, publicSharedKey)} url={api.getAssetFileUrl(asset.livePhotoVideoId, false, true, publicSharedKey)}
pauseIcon={MotionPauseOutline} pauseIcon={MotionPauseOutline}
@ -162,7 +162,7 @@
</div> </div>
{#if selectionCandidate} {#if selectionCandidate}
<div <div
class="absolute w-full h-full top-0 bg-immich-primary opacity-40" class="absolute top-0 h-full w-full bg-immich-primary opacity-40"
in:fade={{ duration: 100 }} in:fade={{ duration: 100 }}
out:fade={{ duration: 100 }} out:fade={{ duration: 100 }}
/> />

View file

@ -29,7 +29,7 @@
} }
</script> </script>
<div class="absolute right-0 top-0 text-white text-xs font-medium flex gap-1 place-items-center z-20"> <div class="absolute right-0 top-0 z-20 flex place-items-center gap-1 text-xs font-medium text-white">
{#if showTime} {#if showTime}
<span class="pt-2"> <span class="pt-2">
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')} {Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')}
@ -38,7 +38,7 @@
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<span <span
class="pt-2 pr-2" class="pr-2 pt-2"
on:mouseenter={() => { on:mouseenter={() => {
if (playbackOnIconHover) { if (playbackOnIconHover) {
enablePlayback = true; enablePlayback = true;
@ -67,7 +67,7 @@
{#if enablePlayback} {#if enablePlayback}
<video <video
bind:this={player} bind:this={player}
class="w-full h-full object-cover" class="h-full w-full object-cover"
muted muted
autoplay autoplay
src={url} src={url}

View file

@ -14,7 +14,7 @@
</script> </script>
<span <span
class="inline-block h-min whitespace-nowrap px-4 pt-[0.55em] pb-[0.55em] text-center align-baseline text-xs leading-none {colorClasses[ class="inline-block h-min whitespace-nowrap px-4 pb-[0.55em] pt-[0.55em] text-center align-baseline text-xs leading-none {colorClasses[
color color
]}" ]}"
class:rounded-md={rounded === true} class:rounded-md={rounded === true}

View file

@ -59,7 +59,7 @@
{disabled} {disabled}
{title} {title}
on:click on:click
class="inline-flex justify-center items-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[ class="inline-flex items-center justify-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[
color color
]} {sizeClasses[size]}" ]} {sizeClasses[size]}"
class:rounded-lg={rounded === 'lg'} class:rounded-lg={rounded === 'lg'}

View file

@ -16,7 +16,7 @@
style:background-color={backgroundColor} style:background-color={backgroundColor}
style:--immich-icon-button-hover-color={hoverColor} style:--immich-icon-button-hover-color={hoverColor}
class:dark:text-immich-dark-fg={!forceDark} class:dark:text-immich-dark-fg={!forceDark}
class="rounded-full p-3 flex place-items-center place-content-center transition-all class="flex place-content-center place-items-center rounded-full p-3 transition-all
{isOpacity ? 'hover:bg-immich-bg/30' : 'immich-circle-icon-button hover:dark:text-immich-dark-gray'} {isOpacity ? 'hover:bg-immich-bg/30' : 'immich-circle-icon-button hover:dark:text-immich-dark-gray'}
{forceDark && 'hover:text-black'} {forceDark && 'hover:text-black'}
{hideMobile && 'hidden sm:flex'}" {hideMobile && 'hidden sm:flex'}"

View file

@ -33,18 +33,18 @@
{#if showMenu} {#if showMenu}
<div <div
transition:fly={{ y: -30, x: 30, duration: 200 }} transition:fly={{ y: -30, x: 30, duration: 200 }}
class="absolute top-5 right-0 min-w-[250px] bg-gray-100 dark:bg-gray-700 rounded-2xl py-4 shadow-lg dark:text-white text-black z-50 text-md flex flex-col" class="text-md absolute right-0 top-5 z-50 flex min-w-[250px] flex-col rounded-2xl bg-gray-100 py-4 text-black shadow-lg dark:bg-gray-700 dark:text-white"
> >
{#each options as option, index (option)} {#each options as option, index (option)}
<button <button
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-4 transition-all grid grid-cols-[20px,1fr] place-items-center gap-2" class="grid grid-cols-[20px,1fr] place-items-center gap-2 p-4 transition-all hover:bg-gray-300 dark:hover:bg-gray-800"
on:click={() => handleSelectOption(index)} on:click={() => handleSelectOption(index)}
> >
{#if value == option} {#if value == option}
<div class="text-immich-primary dark:text-immich-dark-primary font-medium"> <div class="font-medium text-immich-primary dark:text-immich-dark-primary">
<Check size="18" /> <Check size="18" />
</div> </div>
<p class="justify-self-start text-immich-primary dark:text-immich-dark-primary font-medium"> <p class="justify-self-start font-medium text-immich-primary dark:text-immich-dark-primary">
{option} {option}
</p> </p>
{:else} {:else}

View file

@ -15,7 +15,7 @@
</script> </script>
<div <div
class="flex place-items-center max-w-lg rounded-lg border dark:border-transparent p-2 bg-gray-100 dark:bg-gray-700" class="flex max-w-lg place-items-center rounded-lg border bg-gray-100 p-2 dark:border-transparent dark:bg-gray-700"
use:clickOutside use:clickOutside
on:outclick={() => dispatch('cancel')} on:outclick={() => dispatch('cancel')}
> >
@ -28,14 +28,14 @@
heightStyle="2rem" heightStyle="2rem"
/> />
<form <form
class="ml-4 flex justify-between w-full gap-16" class="ml-4 flex w-full justify-between gap-16"
autocomplete="off" autocomplete="off"
on:submit|preventDefault={() => dispatch('change', name)} on:submit|preventDefault={() => dispatch('change', name)}
> >
<!-- svelte-ignore a11y-autofocus --> <!-- svelte-ignore a11y-autofocus -->
<input <input
autofocus autofocus
class="gap-2 w-full bg-gray-100 dark:bg-gray-700 dark:text-white" class="w-full gap-2 bg-gray-100 dark:bg-gray-700 dark:text-white"
type="text" type="text"
placeholder="New name or nickname" placeholder="New name or nickname"
bind:value={name} bind:value={name}

View file

@ -25,12 +25,12 @@
<section <section
transition:fly={{ y: 500, duration: 100, easing: quintOut }} transition:fly={{ y: 500, duration: 100, easing: quintOut }}
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]" class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
> >
<ControlAppBar on:close-button-click={onClose}> <ControlAppBar on:close-button-click={onClose}>
<svelte:fragment slot="leading">Select feature photo</svelte:fragment> <svelte:fragment slot="leading">Select feature photo</svelte:fragment>
</ControlAppBar> </ControlAppBar>
<section class="pt-[100px] pl-[70px] bg-immich-bg dark:bg-immich-dark-bg"> <section class="bg-immich-bg pl-[70px] pt-[100px] dark:bg-immich-dark-bg">
<AssetSelectionViewer {assets} on:select={handleSelectedAsset} /> <AssetSelectionViewer {assets} on:select={handleSelectedAsset} />
</section> </section>
</section> </section>

View file

@ -18,14 +18,14 @@
</script> </script>
<button <button
class="relative transition-all rounded-lg" class="relative rounded-lg transition-all"
on:click={handleOnClicked} on:click={handleOnClicked}
disabled={!selectable} disabled={!selectable}
style:width={thumbnailSize ? thumbnailSize + 'px' : '100%'} style:width={thumbnailSize ? thumbnailSize + 'px' : '100%'}
style:height={thumbnailSize ? thumbnailSize + 'px' : '100%'} style:height={thumbnailSize ? thumbnailSize + 'px' : '100%'}
> >
<div <div
class="filter w-full h-full brightness-90 border-2" class="h-full w-full border-2 brightness-90 filter"
class:rounded-full={circle} class:rounded-full={circle}
class:rounded-lg={!circle} class:rounded-lg={!circle}
class:border-transparent={!border} class:border-transparent={!border}
@ -42,7 +42,7 @@
</div> </div>
<div <div
class="absolute top-0 left-0 w-full h-full bg-immich-primary/30 opacity-0" class="absolute left-0 top-0 h-full w-full bg-immich-primary/30 opacity-0"
class:hover:opacity-100={selectable} class:hover:opacity-100={selectable}
class:rounded-full={circle} class:rounded-full={circle}
class:rounded-lg={!circle} class:rounded-lg={!circle}
@ -50,7 +50,7 @@
{#if selected} {#if selected}
<div <div
class="absolute top-0 left-0 w-full h-full bg-blue-500/80" class="absolute left-0 top-0 h-full w-full bg-blue-500/80"
class:rounded-full={circle} class:rounded-full={circle}
class:rounded-lg={!circle} class:rounded-lg={!circle}
/> />
@ -58,7 +58,7 @@
{#if person.name} {#if person.name}
<span <span
class="absolute bottom-2 left-0 w-full text-center font-medium text-white text-ellipsis w-100 px-1 hover:cursor-pointer backdrop-blur-[1px]" class="w-100 absolute bottom-2 left-0 w-full text-ellipsis px-1 text-center font-medium text-white backdrop-blur-[1px] hover:cursor-pointer"
> >
{person.name} {person.name}
</span> </span>

View file

@ -75,7 +75,7 @@
<section <section
transition:fly={{ y: 500, duration: 100, easing: quintOut }} transition:fly={{ y: 500, duration: 100, easing: quintOut }}
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]" class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
> >
<ControlAppBar on:close-button-click={onClose}> <ControlAppBar on:close-button-click={onClose}>
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
@ -99,12 +99,12 @@
> >
</svelte:fragment> </svelte:fragment>
</ControlAppBar> </ControlAppBar>
<section class="pt-[100px] px-[70px] bg-immich-bg dark:bg-immich-dark-bg"> <section class="bg-immich-bg px-[70px] pt-[100px] dark:bg-immich-dark-bg">
<section id="merge-face-selector relative"> <section id="merge-face-selector relative">
<div class="place-items-center place-content-center mb-10 h-[200px]"> <div class="mb-10 h-[200px] place-content-center place-items-center">
<p class="uppercase mb-4 dark:text-white text-center">Choose matching faces to merge</p> <p class="mb-4 text-center uppercase dark:text-white">Choose matching faces to merge</p>
<div class="grid grid-flow-col-dense place-items-center place-content-center gap-4"> <div class="grid grid-flow-col-dense place-content-center place-items-center gap-4">
{#each selectedPeople as person (person.id)} {#each selectedPeople as person (person.id)}
<div animate:flip={{ duration: 250, easing: quintOut }}> <div animate:flip={{ duration: 250, easing: quintOut }}>
<FaceThumbnail border circle {person} selectable thumbnailSize={120} on:click={() => onSelect(person)} /> <FaceThumbnail border circle {person} selectable thumbnailSize={120} on:click={() => onSelect(person)} />
@ -118,10 +118,10 @@
</div> </div>
</div> </div>
<div <div
class="p-10 overflow-y-auto rounded-3xl bg-gray-200 dark:bg-immich-dark-gray" class="overflow-y-auto rounded-3xl bg-gray-200 p-10 dark:bg-immich-dark-gray"
style:max-height={screenHeight - 200 - 200 + 'px'} style:max-height={screenHeight - 200 - 200 + 'px'}
> >
<div class="grid grid-col-2 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10 gap-8"> <div class="grid-col-2 grid gap-8 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10">
{#each unselectedPeople as person (person.id)} {#each unselectedPeople as person (person.id)}
<FaceThumbnail {person} on:click={() => onSelect(person)} circle border selectable /> <FaceThumbnail {person} on:click={() => onSelect(person)} circle border selectable />
{/each} {/each}

View file

@ -11,19 +11,19 @@
<section <section
transition:fly={{ y: 500, duration: 100, easing: quintOut }} transition:fly={{ y: 500, duration: 100, easing: quintOut }}
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]" class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
> >
<div <div
class="absolute border-b dark:border-immich-dark-gray flex justify-between place-items-center dark:text-immich-dark-fg w-full h-16" class="absolute flex h-16 w-full place-items-center justify-between border-b dark:border-immich-dark-gray dark:text-immich-dark-fg"
> >
<div class="flex items-center justify-between p-8 w-full"> <div class="flex w-full items-center justify-between p-8">
<div class="flex items-center"> <div class="flex items-center">
<CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} /> <CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} />
<p class="ml-4">Show & hide faces</p> <p class="ml-4">Show & hide faces</p>
</div> </div>
<IconButton on:click={() => dispatch('doneClick')}>Done</IconButton> <IconButton on:click={() => dispatch('doneClick')}>Done</IconButton>
</div> </div>
<div class="absolute top-16 h-[calc(100%-theme(spacing.16))] w-full immich-scrollbar p-4 pb-8"> <div class="immich-scrollbar absolute top-16 h-[calc(100%-theme(spacing.16))] w-full p-4 pb-8">
<slot /> <slot />
</div> </div>
</div> </div>

View file

@ -50,7 +50,7 @@
} }
</script> </script>
<form on:submit|preventDefault={registerAdmin} method="post" class="flex flex-col gap-5 mt-5"> <form on:submit|preventDefault={registerAdmin} method="post" class="mt-5 flex flex-col gap-5">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<label class="immich-form-label" for="email">Admin Email</label> <label class="immich-form-label" for="email">Admin Email</label>
<input class="immich-form-input" id="email" name="email" type="email" autocomplete="email" required /> <input class="immich-form-input" id="email" name="email" type="email" autocomplete="email" required />

View file

@ -17,13 +17,13 @@
<FullScreenModal on:clickOutside={() => handleCancel()}> <FullScreenModal on:clickOutside={() => handleCancel()}>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div <div
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary" class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
> >
<KeyVariant size="4em" /> <KeyVariant size="4em" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium"> <h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
{title} {title}
</h1> </h1>
</div> </div>
@ -34,7 +34,7 @@
<input class="immich-form-input" id="name" name="name" type="text" bind:value={apiKey.name} /> <input class="immich-form-input" id="name" name="name" type="text" bind:value={apiKey.name} />
</div> </div>
<div class="flex w-full px-4 gap-4 mt-8"> <div class="mt-8 flex w-full gap-4 px-4">
<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button> <Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button>
<Button type="submit" fullwidth>{submitText}</Button> <Button type="submit" fullwidth>{submitText}</Button>
</div> </div>

View file

@ -31,13 +31,13 @@
<FullScreenModal> <FullScreenModal>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div <div
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary" class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
> >
<KeyVariant size="4em" /> <KeyVariant size="4em" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">API Key</h1> <h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">API Key</h1>
<p class="text-sm dark:text-immich-dark-fg"> <p class="text-sm dark:text-immich-dark-fg">
This value will only be shown once. Please be sure to copy it before closing the window. This value will only be shown once. Please be sure to copy it before closing the window.
@ -49,7 +49,7 @@
<textarea class="immich-form-input" id="secret" name="secret" readonly={true} value={secret} /> <textarea class="immich-form-input" id="secret" name="secret" readonly={true} value={secret} />
</div> </div>
<div class="flex w-full px-4 gap-4 mt-8"> <div class="mt-8 flex w-full gap-4 px-4">
{#if canCopyImagesToClipboard} {#if canCopyImagesToClipboard}
<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button> <Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button>
{/if} {/if}

View file

@ -46,7 +46,7 @@
} }
</script> </script>
<form on:submit|preventDefault={changePassword} method="post" class="flex flex-col gap-5 mt-5"> <form on:submit|preventDefault={changePassword} method="post" class="mt-5 flex flex-col gap-5">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<label class="immich-form-label" for="password">New Password</label> <label class="immich-form-label" for="password">New Password</label>
<input <input
@ -74,11 +74,11 @@
</div> </div>
{#if error} {#if error}
<p class="text-red-400 text-sm">{error}</p> <p class="text-sm text-red-400">{error}</p>
{/if} {/if}
{#if success} {#if success}
<p class="text-immich-primary text-sm">{success}</p> <p class="text-sm text-immich-primary">{success}</p>
{/if} {/if}
<div class="my-5 flex w-full"> <div class="my-5 flex w-full">
<Button type="submit" size="lg" fullwidth>Change password</Button> <Button type="submit" size="lg" fullwidth>Change password</Button>

View file

@ -78,12 +78,12 @@
</script> </script>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> <div class="flex flex-col place-content-center place-items-center gap-4 px-4">
<ImmichLogo class="text-center" height="100" width="100" /> <ImmichLogo class="text-center" height="100" width="100" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Create new user</h1> <h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Create new user</h1>
<p class="text-sm border rounded-md p-4 font-mono text-gray-600 dark:border-immich-dark-bg dark:text-gray-300"> <p class="rounded-md border p-4 font-mono text-sm text-gray-600 dark:border-immich-dark-bg dark:text-gray-300">
Please provide your user with the password, they will have to change it on their first sign in. Please provide your user with the password, they will have to change it on their first sign in.
</p> </p>
</div> </div>
@ -122,11 +122,11 @@
</div> </div>
{#if error} {#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p> <p class="ml-4 text-sm text-red-400">{error}</p>
{/if} {/if}
{#if success} {#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p> <p class="ml-4 text-sm text-immich-primary">{success}</p>
{/if} {/if}
<div class="flex w-full p-4"> <div class="flex w-full p-4">
<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button> <Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button>

View file

@ -67,13 +67,13 @@
</script> </script>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div <div
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary" class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
> >
<AccountEditOutline size="4em" /> <AccountEditOutline size="4em" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Edit user</h1> <h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Edit user</h1>
</div> </div>
<form on:submit|preventDefault={editUser} autocomplete="off"> <form on:submit|preventDefault={editUser} autocomplete="off">
@ -134,13 +134,13 @@
</div> </div>
{#if error} {#if error}
<p class="text-red-400 ml-4 text-sm">{error}</p> <p class="ml-4 text-sm text-red-400">{error}</p>
{/if} {/if}
{#if success} {#if success}
<p class="text-immich-primary ml-4 text-sm">{success}</p> <p class="ml-4 text-sm text-immich-primary">{success}</p>
{/if} {/if}
<div class="flex w-full px-4 gap-4 mt-8"> <div class="mt-8 flex w-full gap-4 px-4">
{#if canResetPassword} {#if canResetPassword}
<Button color="light-red" fullwidth on:click={() => (isShowResetPasswordConfirmation = true)} <Button color="light-red" fullwidth on:click={() => (isShowResetPasswordConfirmation = true)}
>Reset password</Button >Reset password</Button

View file

@ -79,7 +79,7 @@
</script> </script>
{#if authConfig.passwordLoginEnabled} {#if authConfig.passwordLoginEnabled}
<form on:submit|preventDefault={login} class="flex flex-col gap-5 mt-5"> <form on:submit|preventDefault={login} class="mt-5 flex flex-col gap-5">
{#if errorMessage} {#if errorMessage}
<p class="text-red-400" transition:fade> <p class="text-red-400" transition:fade>
{errorMessage} {errorMessage}
@ -128,10 +128,10 @@
{#if authConfig.enabled} {#if authConfig.enabled}
{#if authConfig.passwordLoginEnabled} {#if authConfig.passwordLoginEnabled}
<div class="inline-flex items-center justify-center w-full"> <div class="inline-flex w-full items-center justify-center">
<hr class="w-3/4 h-px my-4 bg-gray-200 border-0 dark:bg-gray-600" /> <hr class="my-4 h-px w-3/4 border-0 bg-gray-200 dark:bg-gray-600" />
<span <span
class="absolute px-3 font-medium text-gray-900 -translate-x-1/2 left-1/2 dark:text-white bg-white dark:bg-immich-dark-gray" class="absolute left-1/2 -translate-x-1/2 bg-white px-3 font-medium text-gray-900 dark:bg-immich-dark-gray dark:text-white"
> >
or or
</span> </span>
@ -162,5 +162,5 @@
{/if} {/if}
{#if !authConfig.enabled && !authConfig.passwordLoginEnabled} {#if !authConfig.enabled && !authConfig.passwordLoginEnabled}
<p class="text-center dark:text-immich-dark-fg p-4">Login has been disabled.</p> <p class="p-4 text-center dark:text-immich-dark-fg">Login has been disabled.</p>
{/if} {/if}

View file

@ -17,7 +17,7 @@
<slot name="header" /> <slot name="header" />
</header> </header>
<main <main
class="grid md:grid-cols-[theme(spacing.64)_auto] grid-cols-[theme(spacing.18)_auto] relative pt-[var(--navbar-height)] h-screen overflow-hidden bg-immich-bg dark:bg-immich-dark-bg" class="relative grid h-screen grid-cols-[theme(spacing.18)_auto] overflow-hidden bg-immich-bg pt-[var(--navbar-height)] dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
> >
<slot name="sidebar"> <slot name="sidebar">
<SideBar /> <SideBar />
@ -26,13 +26,13 @@
{#if title} {#if title}
<section class="relative"> <section class="relative">
<div <div
class="absolute border-b dark:border-immich-dark-gray flex justify-between place-items-center dark:text-immich-dark-fg w-full p-4 h-16" class="absolute flex h-16 w-full place-items-center justify-between border-b p-4 dark:border-immich-dark-gray dark:text-immich-dark-fg"
> >
<p class="font-medium">{title}</p> <p class="font-medium">{title}</p>
<slot name="buttons" /> <slot name="buttons" />
</div> </div>
<div class="absolute overflow-y-auto top-16 h-[calc(100%-theme(spacing.16))] w-full immich-scrollbar p-4 pb-8"> <div class="immich-scrollbar absolute top-16 h-[calc(100%-theme(spacing.16))] w-full overflow-y-auto p-4 pb-8">
<slot /> <slot />
</div> </div>
</section> </section>

View file

@ -20,9 +20,9 @@
<FullScreenModal on:clickOutside={() => dispatch('close')}> <FullScreenModal on:clickOutside={() => dispatch('close')}>
<div <div
class="flex flex-col gap-8 border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-8 shadow-sm w-96 max-w-lg rounded-3xl" class="flex w-96 max-w-lg flex-col gap-8 rounded-3xl border bg-white p-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray"
> >
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium self-center">Map Settings</h1> <h1 class="self-center text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">Map Settings</h1>
<form <form
on:submit|preventDefault={() => dispatch('save', settings)} on:submit|preventDefault={() => dispatch('save', settings)}
@ -32,8 +32,8 @@
<SettingSwitch title="Only favorites" bind:checked={settings.onlyFavorites} /> <SettingSwitch title="Only favorites" bind:checked={settings.onlyFavorites} />
{#if customDateRange} {#if customDateRange}
<div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4"> <div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4">
<div class="flex justify-between items-center gap-8"> <div class="flex items-center justify-between gap-8">
<label class="immich-form-label text-sm shrink-0" for="date-after">Date after</label> <label class="immich-form-label shrink-0 text-sm" for="date-after">Date after</label>
<input <input
class="immich-form-input w-40" class="immich-form-input w-40"
type="date" type="date"
@ -42,8 +42,8 @@
bind:value={settings.dateAfter} bind:value={settings.dateAfter}
/> />
</div> </div>
<div class="flex justify-between items-center gap-8"> <div class="flex items-center justify-between gap-8">
<label class="immich-form-label text-sm shrink-0" for="date-before">Date before</label> <label class="immich-form-label shrink-0 text-sm" for="date-before">Date before</label>
<input class="immich-form-input w-40" type="date" id="date-before" bind:value={settings.dateBefore} /> <input class="immich-form-input w-40" type="date" id="date-before" bind:value={settings.dateBefore} />
</div> </div>
<div class="flex justify-center text-xs"> <div class="flex justify-center text-xs">
@ -104,7 +104,7 @@
</div> </div>
{/if} {/if}
<div class="flex w-full gap-4 mt-4"> <div class="mt-4 flex w-full gap-4">
<Button color="gray" size="sm" fullwidth on:click={() => dispatch('close')}>Cancel</Button> <Button color="gray" size="sm" fullwidth on:click={() => dispatch('close')}>Cancel</Button>
<Button type="submit" size="sm" fullwidth>Save</Button> <Button type="submit" size="sm" fullwidth>Save</Button>
</div> </div>

View file

@ -111,12 +111,12 @@
</svelte:fragment> </svelte:fragment>
{#if !galleryInView} {#if !galleryInView}
<div class="flex place-items-center place-content-center overflow-hidden gap-2"> <div class="flex place-content-center place-items-center gap-2 overflow-hidden">
<CircleIconButton logo={paused ? Play : Pause} forceDark on:click={() => (paused = !paused)} /> <CircleIconButton logo={paused ? Play : Pause} forceDark on:click={() => (paused = !paused)} />
{#each currentMemory.assets as _, i} {#each currentMemory.assets as _, i}
<button class="relative w-full py-2" on:click={() => goto(`?memory=${memoryIndex}&asset=${i}`)}> <button class="relative w-full py-2" on:click={() => goto(`?memory=${memoryIndex}&asset=${i}`)}>
<span class="absolute left-0 w-full h-[2px] bg-gray-500" /> <span class="absolute left-0 h-[2px] w-full bg-gray-500" />
{#await resetPromise} {#await resetPromise}
<span class="absolute left-0 h-[2px] bg-white" style:width={`${i < assetIndex ? 100 : 0}%`} /> <span class="absolute left-0 h-[2px] bg-white" style:width={`${i < assetIndex ? 100 : 0}%`} />
{:then} {:then}
@ -139,7 +139,7 @@
{#if galleryInView} {#if galleryInView}
<div <div
class="sticky top-20 flex place-content-center place-items-center z-30 transition-opacity" class="sticky top-20 z-30 flex place-content-center place-items-center transition-opacity"
class:opacity-0={!galleryInView} class:opacity-0={!galleryInView}
class:opacity-100={galleryInView} class:opacity-100={galleryInView}
> >
@ -149,28 +149,28 @@
</div> </div>
{/if} {/if}
<!-- Viewer --> <!-- Viewer -->
<section class="pt-20 overflow-hidden"> <section class="overflow-hidden pt-20">
<div <div
class="flex w-[300%] h-[calc(100vh_-_180px)] items-center justify-center box-border ml-[-100%] gap-10 overflow-hidden" class="ml-[-100%] box-border flex h-[calc(100vh_-_180px)] w-[300%] items-center justify-center gap-10 overflow-hidden"
> >
<!-- PREVIOUS MEMORY --> <!-- PREVIOUS MEMORY -->
<div <div
class="rounded-2xl w-[20vw] h-1/2" class="h-1/2 w-[20vw] rounded-2xl"
class:opacity-25={previousMemory} class:opacity-25={previousMemory}
class:opacity-0={!previousMemory} class:opacity-0={!previousMemory}
class:hover:opacity-70={previousMemory} class:hover:opacity-70={previousMemory}
> >
<button class="rounded-2xl h-full w-full relative" disabled={!previousMemory} on:click={toPreviousMemory}> <button class="relative h-full w-full rounded-2xl" disabled={!previousMemory} on:click={toPreviousMemory}>
<img <img
class="rounded-2xl h-full w-full object-cover" class="h-full w-full rounded-2xl object-cover"
src={previousMemory ? api.getAssetThumbnailUrl(previousMemory.assets[0].id, 'JPEG') : noThumbnailUrl} src={previousMemory ? api.getAssetThumbnailUrl(previousMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
alt="" alt=""
draggable="false" draggable="false"
/> />
{#if previousMemory} {#if previousMemory}
<div class="absolute right-4 bottom-4 text-white text-left"> <div class="absolute bottom-4 right-4 text-left text-white">
<p class="font-semibold text-xs text-gray-200">PREVIOUS</p> <p class="text-xs font-semibold text-gray-200">PREVIOUS</p>
<p class="text-xl">{previousMemory.title}</p> <p class="text-xl">{previousMemory.title}</p>
</div> </div>
{/if} {/if}
@ -179,19 +179,19 @@
<!-- CURRENT MEMORY --> <!-- CURRENT MEMORY -->
<div <div
class="main-view rounded-2xl h-full relative w-[70vw] bg-black flex place-items-center place-content-center" class="main-view relative flex h-full w-[70vw] place-content-center place-items-center rounded-2xl bg-black"
> >
<div class="bg-black w-full h-full rounded-2xl"> <div class="h-full w-full rounded-2xl bg-black">
<!-- CONTROL BUTTONS --> <!-- CONTROL BUTTONS -->
<div class="absolute h-full flex justify-between w-full"> <div class="absolute flex h-full w-full justify-between">
<div class="flex h-full flex-col place-content-center place-items-center ml-4"> <div class="ml-4 flex h-full flex-col place-content-center place-items-center">
<div class="inline-block"> <div class="inline-block">
{#if canGoBack} {#if canGoBack}
<CircleIconButton logo={ChevronLeft} backgroundColor="#202123" on:click={toPrevious} /> <CircleIconButton logo={ChevronLeft} backgroundColor="#202123" on:click={toPrevious} />
{/if} {/if}
</div> </div>
</div> </div>
<div class="flex h-full flex-col place-content-center place-items-center mr-4"> <div class="mr-4 flex h-full flex-col place-content-center place-items-center">
<div class="inline-block"> <div class="inline-block">
{#if canGoForward} {#if canGoForward}
<CircleIconButton logo={ChevronRight} backgroundColor="#202123" on:click={toNext} /> <CircleIconButton logo={ChevronRight} backgroundColor="#202123" on:click={toNext} />
@ -203,14 +203,14 @@
{#key currentAsset.id} {#key currentAsset.id}
<img <img
transition:fade transition:fade
class="rounded-2xl w-full h-full object-contain transition-all" class="h-full w-full rounded-2xl object-contain transition-all"
src={api.getAssetThumbnailUrl(currentAsset.id, 'JPEG')} src={api.getAssetThumbnailUrl(currentAsset.id, 'JPEG')}
alt="" alt=""
draggable="false" draggable="false"
/> />
{/key} {/key}
<div class="absolute top-4 left-8 text-white text-sm font-medium"> <div class="absolute left-8 top-4 text-sm font-medium text-white">
<p> <p>
{DateTime.fromISO(currentMemory.assets[0].fileCreatedAt).toLocaleString(DateTime.DATE_FULL)} {DateTime.fromISO(currentMemory.assets[0].fileCreatedAt).toLocaleString(DateTime.DATE_FULL)}
</p> </p>
@ -224,22 +224,22 @@
<!-- NEXT MEMORY --> <!-- NEXT MEMORY -->
<div <div
class="rounded-xl w-[20vw] h-1/2" class="h-1/2 w-[20vw] rounded-xl"
class:opacity-25={nextMemory} class:opacity-25={nextMemory}
class:opacity-0={!nextMemory} class:opacity-0={!nextMemory}
class:hover:opacity-70={nextMemory} class:hover:opacity-70={nextMemory}
> >
<button class="rounded-2xl h-full w-full relative" on:click={toNextMemory} disabled={!nextMemory}> <button class="relative h-full w-full rounded-2xl" on:click={toNextMemory} disabled={!nextMemory}>
<img <img
class="rounded-2xl h-full w-full object-cover" class="h-full w-full rounded-2xl object-cover"
src={nextMemory ? api.getAssetThumbnailUrl(nextMemory.assets[0].id, 'JPEG') : noThumbnailUrl} src={nextMemory ? api.getAssetThumbnailUrl(nextMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
alt="" alt=""
draggable="false" draggable="false"
/> />
{#if nextMemory} {#if nextMemory}
<div class="absolute left-4 bottom-4 text-white text-left"> <div class="absolute bottom-4 left-4 text-left text-white">
<p class="font-semibold text-xs text-gray-200">UP NEXT</p> <p class="text-xs font-semibold text-gray-200">UP NEXT</p>
<p class="text-xl">{nextMemory.title}</p> <p class="text-xl">{nextMemory.title}</p>
</div> </div>
{/if} {/if}
@ -252,7 +252,7 @@
<section class="bg-immich-dark-gray pl-4"> <section class="bg-immich-dark-gray pl-4">
<div <div
class="sticky flex place-content-center place-items-center mb-10 mt-4 transition-all" class="sticky mb-10 mt-4 flex place-content-center place-items-center transition-all"
class:opacity-0={galleryInView} class:opacity-0={galleryInView}
class:opacity-100={!galleryInView} class:opacity-100={!galleryInView}
> >

View file

@ -155,7 +155,7 @@
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div <div
class="flex flex-col mt-5" class="mt-5 flex flex-col"
on:mouseenter={() => { on:mouseenter={() => {
isMouseOverGroup = true; isMouseOverGroup = true;
assetMouseEventHandler(dateGroupTitle, null); assetMouseEventHandler(dateGroupTitle, null);
@ -167,7 +167,7 @@
> >
<!-- Date group title --> <!-- Date group title -->
<p <p
class="font-medium text-xs md:text-sm text-immich-fg dark:text-immich-dark-fg mb-2 flex place-items-center h-6" class="mb-2 flex h-6 place-items-center text-xs font-medium text-immich-fg dark:text-immich-dark-fg md:text-sm"
style="width: {geometry[groupIndex].containerWidth}px" style="width: {geometry[groupIndex].containerWidth}px"
> >
{#if (hoveredDateGroup == dateGroupTitle && isMouseOverGroup) || $selectedGroup.has(dateGroupTitle)} {#if (hoveredDateGroup == dateGroupTitle && isMouseOverGroup) || $selectedGroup.has(dateGroupTitle)}
@ -185,7 +185,7 @@
</div> </div>
{/if} {/if}
<span class="first-letter:capitalize truncate" title={dateGroupTitle}> <span class="truncate first-letter:capitalize" title={dateGroupTitle}>
{dateGroupTitle} {dateGroupTitle}
</span> </span>
</p> </p>

View file

@ -283,7 +283,7 @@
<!-- Right margin MUST be equal to the width of immich-scrubbable-scrollbar --> <!-- Right margin MUST be equal to the width of immich-scrubbable-scrollbar -->
<section <section
id="asset-grid" id="asset-grid"
class="overflow-y-auto ml-4 mb-4 mr-[60px] scrollbar-hidden" class="scrollbar-hidden mb-4 ml-4 mr-[60px] overflow-y-auto"
bind:clientHeight={viewportHeight} bind:clientHeight={viewportHeight}
bind:clientWidth={viewportWidth} bind:clientWidth={viewportWidth}
bind:this={assetGridElement} bind:this={assetGridElement}

View file

@ -37,7 +37,7 @@
<section <section
id="memory-lane" id="memory-lane"
bind:this={memoryLaneElement} bind:this={memoryLaneElement}
class="relative overflow-x-hidden whitespace-nowrap mt-5 transition-all" class="relative mt-5 overflow-x-hidden whitespace-nowrap transition-all"
bind:offsetWidth bind:offsetWidth
on:scroll={onScroll} on:scroll={onScroll}
> >
@ -46,7 +46,7 @@
{#if canScrollLeft} {#if canScrollLeft}
<div class="absolute left-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> <div class="absolute left-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}>
<button <button
class="rounded-full opacity-50 hover:opacity-100 p-2 border border-gray-500 bg-gray-100 text-gray-500" class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
on:click={scrollLeft} on:click={scrollLeft}
> >
<ChevronLeft size="36" /></button <ChevronLeft size="36" /></button
@ -56,7 +56,7 @@
{#if canScrollRight} {#if canScrollRight}
<div class="absolute right-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> <div class="absolute right-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}>
<button <button
class="rounded-full opacity-50 hover:opacity-100 p-2 border border-gray-500 bg-gray-100 text-gray-500" class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
on:click={scrollRight} on:click={scrollRight}
> >
<ChevronRight size="36" /></button <ChevronRight size="36" /></button
@ -69,18 +69,18 @@
<div class="inline-block" bind:offsetWidth={innerWidth}> <div class="inline-block" bind:offsetWidth={innerWidth}>
{#each $memoryStore as memory, i (memory.title)} {#each $memoryStore as memory, i (memory.title)}
<button <button
class="memory-card relative inline-block mr-8 rounded-xl aspect-video h-[215px]" class="memory-card relative mr-8 inline-block aspect-video h-[215px] rounded-xl"
on:click={() => goto(`/memory?memory=${i}`)} on:click={() => goto(`/memory?memory=${i}`)}
> >
<img <img
class="rounded-xl h-full w-full object-cover" class="h-full w-full rounded-xl object-cover"
src={api.getAssetThumbnailUrl(memory.assets[0].id, 'JPEG')} src={api.getAssetThumbnailUrl(memory.assets[0].id, 'JPEG')}
alt={memory.title} alt={memory.title}
draggable="false" draggable="false"
/> />
<p class="absolute bottom-2 left-4 text-lg text-white z-10">{memory.title}</p> <p class="absolute bottom-2 left-4 z-10 text-lg text-white">{memory.title}</p>
<div <div
class="absolute top-0 left-0 w-full h-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent z-0 hover:bg-black/20 transition-all" class="absolute left-0 top-0 z-0 h-full w-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent transition-all hover:bg-black/20"
/> />
</button> </button>
{/each} {/each}

View file

@ -86,7 +86,7 @@
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
<a <a
data-sveltekit-preload-data="hover" data-sveltekit-preload-data="hover"
class="flex gap-2 place-items-center hover:cursor-pointer ml-6" class="ml-6 flex place-items-center gap-2 hover:cursor-pointer"
href="https://immich.app" href="https://immich.app"
> >
<ImmichLogo height="30" width="30" /> <ImmichLogo height="30" width="30" />
@ -105,7 +105,7 @@
</svelte:fragment> </svelte:fragment>
</ControlAppBar> </ControlAppBar>
{/if} {/if}
<section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40"> <section class="my-[160px] flex flex-col px-6 sm:px-12 md:px-24 lg:px-40">
<GalleryViewer {assets} {sharedLink} bind:selectedAssets viewFrom="shared-link-page" /> <GalleryViewer {assets} {sharedLink} bind:selectedAssets viewFrom="shared-link-page" />
</section> </section>
</section> </section>

View file

@ -49,23 +49,23 @@
<BaseModal on:close={() => dispatch('close')}> <BaseModal on:close={() => dispatch('close')}>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<p class="font-medium"> <p class="font-medium">
Add to {#if shared}Shared {/if} Album Add to {#if shared}Shared {/if} Album
</p> </p>
</span> </span>
</svelte:fragment> </svelte:fragment>
<div class="max-h-[400px] flex flex-col mb-2"> <div class="mb-2 flex max-h-[400px] flex-col">
{#if loading} {#if loading}
{#each { length: 3 } as _} {#each { length: 3 } as _}
<div class="animate-pulse flex gap-4 px-6 py-2"> <div class="flex animate-pulse gap-4 px-6 py-2">
<div class="h-12 w-12 bg-slate-200 rounded-xl" /> <div class="h-12 w-12 rounded-xl bg-slate-200" />
<div class="flex flex-col items-start justify-center gap-2"> <div class="flex flex-col items-start justify-center gap-2">
<span class="animate-pulse w-36 h-4 bg-slate-200" /> <span class="h-4 w-36 animate-pulse bg-slate-200" />
<div class="flex animate-pulse gap-1"> <div class="flex animate-pulse gap-1">
<span class="w-8 h-3 bg-slate-200" /> <span class="h-3 w-8 bg-slate-200" />
<span class="w-20 h-3 bg-slate-200" /> <span class="h-3 w-20 bg-slate-200" />
</div> </div>
</div> </div>
</div> </div>
@ -73,17 +73,17 @@
{:else} {:else}
<!-- svelte-ignore a11y-autofocus --> <!-- svelte-ignore a11y-autofocus -->
<input <input
class="px-6 py-2 text-2xl border-b-4 bg-immich-bg border-immich-bg focus:border-immich-primary dark:bg-immich-dark-gray dark:border-immich-dark-gray dark:focus:border-immich-dark-primary" class="border-b-4 border-immich-bg bg-immich-bg px-6 py-2 text-2xl focus:border-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:focus:border-immich-dark-primary"
placeholder="Search" placeholder="Search"
autofocus autofocus
bind:value={search} bind:value={search}
/> />
<div class="overflow-y-auto immich-scrollbar"> <div class="immich-scrollbar overflow-y-auto">
<button <button
on:click={handleNew} on:click={handleNew}
class="w-full flex gap-4 px-6 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors items-center" class="flex w-full items-center gap-4 px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
> >
<div class="h-12 w-12 flex justify-center items-center"> <div class="flex h-12 w-12 items-center justify-center">
<Plus size="30" /> <Plus size="30" />
</div> </div>
<p class=""> <p class="">
@ -92,14 +92,14 @@
</button> </button>
{#if filteredAlbums.length > 0} {#if filteredAlbums.length > 0}
{#if !shared && search.length === 0} {#if !shared && search.length === 0}
<p class="text-xs px-5 py-3">RECENT</p> <p class="px-5 py-3 text-xs">RECENT</p>
{#each recentAlbums as album (album.id)} {#each recentAlbums as album (album.id)}
<AlbumListItem variant="simple" {album} on:album={() => handleSelect(album)} /> <AlbumListItem variant="simple" {album} on:album={() => handleSelect(album)} />
{/each} {/each}
{/if} {/if}
{#if !shared} {#if !shared}
<p class="text-xs px-5 py-3"> <p class="px-5 py-3 text-xs">
{#if search.length === 0}ALL {/if}ALBUMS {#if search.length === 0}ALL {/if}ALBUMS
</p> </p>
{/if} {/if}
@ -107,9 +107,9 @@
<AlbumListItem {album} searchQuery={search} on:album={() => handleSelect(album)} /> <AlbumListItem {album} searchQuery={search} on:album={() => handleSelect(album)} />
{/each} {/each}
{:else if albums.length > 0} {:else if albums.length > 0}
<p class="text-sm px-5 py-1">It looks like you do not have any albums with this name yet.</p> <p class="px-5 py-1 text-sm">It looks like you do not have any albums with this name yet.</p>
{:else} {:else}
<p class="text-sm px-5 py-1">It looks like you do not have any albums yet.</p> <p class="px-5 py-1 text-sm">It looks like you do not have any albums yet.</p>
{/if} {/if}
</div> </div>
{/if} {/if}

View file

@ -31,14 +31,14 @@
id="immich-modal" id="immich-modal"
style:z-index={zIndex} style:z-index={zIndex}
transition:fade={{ duration: 100, easing: quintOut }} transition:fade={{ duration: 100, easing: quintOut }}
class="fixed top-0 left-0 w-full h-full bg-black/50 flex place-items-center place-content-center overflow-hidden" class="fixed left-0 top-0 flex h-full w-full place-content-center place-items-center overflow-hidden bg-black/50"
> >
<div <div
use:clickOutside use:clickOutside
on:outclick={() => dispatch('close')} on:outclick={() => dispatch('close')}
class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg w-[450px] min-h-[200px] max-h-[600px] rounded-lg shadow-md" class="max-h-[600px] min-h-[200px] w-[450px] rounded-lg bg-immich-bg shadow-md dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div class="flex justify-between place-items-center px-5 py-3"> <div class="flex place-items-center justify-between px-5 py-3">
<div> <div>
<slot name="title"> <slot name="title">
<p>Modal Title</p> <p>Modal Title</p>

View file

@ -26,23 +26,23 @@
<FullScreenModal on:clickOutside={handleCancel}> <FullScreenModal on:clickOutside={handleCancel}>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<div <div
class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary" class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
> >
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium pb-2"> <h1 class="pb-2 text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
{title} {title}
</h1> </h1>
</div> </div>
<div> <div>
<div class="px-4 py-5 text-md text-center"> <div class="text-md px-4 py-5 text-center">
<slot name="prompt"> <slot name="prompt">
<p>{prompt}</p> <p>{prompt}</p>
</slot> </slot>
</div> </div>
<div class="flex w-full px-4 gap-4 mt-4"> <div class="mt-4 flex w-full gap-4 px-4">
{#if !hideCancelButton} {#if !hideCancelButton}
<Button color={cancelColor} fullwidth on:click={handleCancel}> <Button color={cancelColor} fullwidth on:click={handleCancel}>
{cancelText} {cancelText}

View file

@ -23,7 +23,7 @@
<div <div
transition:slide={{ duration: 200, easing: quintOut }} transition:slide={{ duration: 200, easing: quintOut }}
bind:this={menuElement} bind:this={menuElement}
class="absolute w-[200px] z-[99999] rounded-lg overflow-hidden shadow-lg" class="absolute z-[99999] w-[200px] overflow-hidden rounded-lg shadow-lg"
style="left: {left}px; top: {top}px;" style="left: {left}px; top: {top}px;"
role="menu" role="menu"
use:clickOutside use:clickOutside

View file

@ -4,7 +4,7 @@
<button <button
on:click on:click
class="bg-slate-100 hover:bg-gray-200 text-immich-fg dark:text-immich-dark-bg p-4 w-full text-left text-sm font-medium focus:outline-none focus:ring-inset focus:ring-2" class="w-full bg-slate-100 p-4 text-left text-sm font-medium text-immich-fg hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-inset dark:text-immich-dark-bg"
role="menuitem" role="menuitem"
> >
{#if text} {#if text}

View file

@ -40,14 +40,14 @@
}); });
</script> </script>
<div in:fly={{ y: 10, duration: 200 }} class="fixed top-0 w-full bg-transparent z-[100]"> <div in:fly={{ y: 10, duration: 200 }} class="fixed top-0 z-[100] w-full bg-transparent">
<div <div
id="asset-selection-app-bar" id="asset-selection-app-bar"
class={`grid grid-cols-3 justify-between ${appBarBorder} rounded-lg p-2 mx-2 mt-2 transition-all place-items-center ${tailwindClasses} dark:bg-immich-dark-gray ${ class={`grid grid-cols-3 justify-between ${appBarBorder} mx-2 mt-2 place-items-center rounded-lg p-2 transition-all ${tailwindClasses} dark:bg-immich-dark-gray ${
forceDark && 'bg-immich-dark-gray text-white' forceDark && 'bg-immich-dark-gray text-white'
}`} }`}
> >
<div class="flex place-items-center gap-6 dark:text-immich-dark-fg justify-self-start"> <div class="flex place-items-center gap-6 justify-self-start dark:text-immich-dark-fg">
{#if showBackButton} {#if showBackButton}
<CircleIconButton <CircleIconButton
on:click={() => dispatch('close-button-click')} on:click={() => dispatch('close-button-click')}
@ -65,7 +65,7 @@
<slot /> <slot />
</div> </div>
<div class="flex place-items-center gap-1 mr-4 justify-self-end"> <div class="mr-4 flex place-items-center gap-1 justify-self-end">
<slot name="trailing" /> <slot name="trailing" />
</div> </div>
</div> </div>

View file

@ -140,7 +140,7 @@
<BaseModal on:close={() => dispatch('close')}> <BaseModal on:close={() => dispatch('close')}>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<Link size={24} /> <Link size={24} />
{#if editingLink} {#if editingLink}
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Edit link</p> <p class="font-medium text-immich-fg dark:text-immich-dark-fg">Edit link</p>
@ -175,10 +175,10 @@
{/if} {/if}
{/if} {/if}
<div class="mt-4 mb-2"> <div class="mb-2 mt-4">
<p class="text-xs">LINK OPTIONS</p> <p class="text-xs">LINK OPTIONS</p>
</div> </div>
<div class="p-4 bg-gray-100 dark:bg-black/40 rounded-lg"> <div class="rounded-lg bg-gray-100 p-4 dark:bg-black/40">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="mb-2"> <div class="mb-2">
<SettingInputField inputType={SettingInputFieldType.TEXT} label="Description" bind:value={description} /> <SettingInputField inputType={SettingInputFieldType.TEXT} label="Description" bind:value={description} />
@ -198,11 +198,11 @@
<div class="text-sm"> <div class="text-sm">
{#if editingLink} {#if editingLink}
<p class="my-2 immich-form-label"> <p class="immich-form-label my-2">
<SettingSwitch bind:checked={shouldChangeExpirationTime} title={'Change expiration time'} /> <SettingSwitch bind:checked={shouldChangeExpirationTime} title={'Change expiration time'} />
</p> </p>
{:else} {:else}
<p class="my-2 immich-form-label">Expire after</p> <p class="immich-form-label my-2">Expire after</p>
{/if} {/if}
<DropdownButton <DropdownButton

View file

@ -26,7 +26,7 @@
{#if dragStartTarget} {#if dragStartTarget}
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div <div
class="fixed inset-0 w-full h-full z-[1000] flex flex-col items-center justify-center bg-gray-100/90 dark:bg-immich-dark-bg/90 text-immich-dark-gray dark:text-immich-gray" class="fixed inset-0 z-[1000] flex h-full w-full flex-col items-center justify-center bg-gray-100/90 text-immich-dark-gray dark:bg-immich-dark-bg/90 dark:text-immich-gray"
transition:fade={{ duration: 250 }} transition:fade={{ duration: 250 }}
on:dragover={(e) => { on:dragover={(e) => {
// Prevent browser from opening the dropped file. // Prevent browser from opening the dropped file.
@ -34,7 +34,7 @@
e.preventDefault(); e.preventDefault();
}} }}
> >
<ImmichLogo class="animate-bounce w-48 m-16" /> <ImmichLogo class="m-16 w-48 animate-bounce" />
<div class="text-2xl">Drop files anywhere to upload</div> <div class="text-2xl">Drop files anywhere to upload</div>
</div> </div>
{/if} {/if}

View file

@ -25,7 +25,7 @@
{disabled} {disabled}
on:click={toggle} on:click={toggle}
aria-expanded={isOpen} aria-expanded={isOpen}
class="bg-gray-200 w-full flex p-2 rounded-lg dark:bg-gray-600 place-items-center justify-between disabled:cursor-not-allowed dark:disabled:bg-gray-300 disabled:bg-gray-600" class="flex w-full place-items-center justify-between rounded-lg bg-gray-200 p-2 disabled:cursor-not-allowed disabled:bg-gray-600 dark:bg-gray-600 dark:disabled:bg-gray-300"
> >
<div> <div>
{selected} {selected}
@ -49,14 +49,14 @@
</button> </button>
{#if isOpen} {#if isOpen}
<div class="flex flex-col mt-2 absolute w-full"> <div class="absolute mt-2 flex w-full flex-col">
{#each options.options as option} {#each options.options as option}
<button <button
on:click={() => { on:click={() => {
selected = option; selected = option;
isOpen = false; isOpen = false;
}} }}
class="bg-gray-200 dark:bg-gray-500 dark:hover:bg-gray-700 w-full flex p-2 hover:bg-gray-300 transition-all" class="flex w-full bg-gray-200 p-2 transition-all hover:bg-gray-300 dark:bg-gray-500 dark:hover:bg-gray-700"
> >
{option} {option}
</button> </button>

View file

@ -13,16 +13,16 @@
<div <div
on:click={actionHandler} on:click={actionHandler}
on:keydown={actionHandler} on:keydown={actionHandler}
class="border dark:border-immich-dark-gray {hoverClasses} p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center" class="border dark:border-immich-dark-gray {hoverClasses} m-auto mt-10 flex w-[50%] flex-col place-content-center place-items-center rounded-3xl bg-gray-50 p-5 dark:bg-immich-dark-gray"
> >
<img src={empty1Url} {alt} width="500" draggable="false" /> <img src={empty1Url} {alt} width="500" draggable="false" />
<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg">{text}</p> <p class="text-immich-text-gray-500 text-center dark:text-immich-dark-fg">{text}</p>
</div> </div>
{:else} {:else}
<div <div
class="border dark:border-immich-dark-gray p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center" class="m-auto mt-10 flex w-[50%] flex-col place-content-center place-items-center rounded-3xl border bg-gray-50 p-5 dark:border-immich-dark-gray dark:bg-immich-dark-gray"
> >
<img src={empty1Url} {alt} width="500" draggable="false" /> <img src={empty1Url} {alt} width="500" draggable="false" />
<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg">{text}</p> <p class="text-immich-text-gray-500 text-center dark:text-immich-dark-fg">{text}</p>
</div> </div>
{/if} {/if}

View file

@ -9,7 +9,7 @@
<section <section
in:fade={{ duration: 100 }} in:fade={{ duration: 100 }}
out:fade={{ duration: 100 }} out:fade={{ duration: 100 }}
class="fixed left-0 top-0 w-screen h-screen bg-black/40 z-[990] flex place-items-center place-content-center" class="fixed left-0 top-0 z-[990] flex h-screen w-screen place-content-center place-items-center bg-black/40"
> >
<div class="z-[9999]" use:clickOutside on:outclick={() => dispatch('clickOutside')}> <div class="z-[9999]" use:clickOutside on:outclick={() => dispatch('clickOutside')}>
<slot /> <slot />

View file

@ -5,20 +5,20 @@
export let showMessage = $$slots.message; export let showMessage = $$slots.message;
</script> </script>
<section class="min-h-screen w-screen flex place-items-center place-content-center p-4"> <section class="flex min-h-screen w-screen place-content-center place-items-center p-4">
<div <div
class="flex flex-col gap-4 border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-8 shadow-sm w-full max-w-lg rounded-3xl" class="flex w-full max-w-lg flex-col gap-4 rounded-3xl border bg-white p-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray"
> >
<div class="flex flex-col place-items-center place-content-center gap-4 py-4"> <div class="flex flex-col place-content-center place-items-center gap-4 py-4">
<ImmichLogo class="h-24 w-24" /> <ImmichLogo class="h-24 w-24" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium"> <h1 class="text-2xl font-medium text-immich-primary dark:text-immich-dark-primary">
{title} {title}
</h1> </h1>
</div> </div>
{#if showMessage} {#if showMessage}
<div <div
class="text-sm rounded-xl p-4 text-immich-primary dark:text-immich-dark-primary font-medium bg-immich-primary/5 dark:border-immich-dark-bg w-full border-immich-primary border-2" class="w-full rounded-xl border-2 border-immich-primary bg-immich-primary/5 p-4 text-sm font-medium text-immich-primary dark:border-immich-dark-bg dark:text-immich-dark-primary"
> >
<slot name="message" /> <slot name="message" />
</div> </div>

View file

@ -28,7 +28,7 @@
</script> </script>
{#if assets.length > 0} {#if assets.length > 0}
<div class="flex flex-wrap gap-1 w-full pb-20" bind:clientWidth={viewWidth}> <div class="flex w-full flex-wrap gap-1 pb-20" bind:clientWidth={viewWidth}>
{#each assets as asset (asset.id)} {#each assets as asset (asset.id)}
<div animate:flip={{ duration: 500 }}> <div animate:flip={{ duration: 500 }}>
<Thumbnail <Thumbnail

View file

@ -98,7 +98,7 @@
</script> </script>
{#if assets.length > 0} {#if assets.length > 0}
<div class="flex flex-wrap gap-1 w-full pb-20" bind:clientWidth={viewWidth}> <div class="flex w-full flex-wrap gap-1 pb-20" bind:clientWidth={viewWidth}>
{#each assets as asset (asset.id)} {#each assets as asset (asset.id)}
<div animate:flip={{ duration: 500 }}> <div animate:flip={{ duration: 500 }}>
<Thumbnail <Thumbnail

View file

@ -37,7 +37,7 @@
$: if (map) map.setView(center, zoom); $: if (map) map.setView(center, zoom);
</script> </script>
<div bind:this={container} class="w-full h-full" class:map-dark={allowDarkMode}> <div bind:this={container} class="h-full w-full" class:map-dark={allowDarkMode}>
{#if map} {#if map}
<slot /> <slot />
{/if} {/if}

View file

@ -1,7 +1,7 @@
<div> <div>
<svg <svg
role="status" role="status"
class={`w-[24px] h-[24px] text-gray-400 animate-spin dark:text-gray-600 fill-immich-primary`} class={`h-[24px] w-[24px] animate-spin fill-immich-primary text-gray-400 dark:text-gray-600`}
viewBox="0 0 100 101" viewBox="0 0 100 101"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

View file

@ -17,15 +17,15 @@
in:fade={{ duration: 100 }} in:fade={{ duration: 100 }}
out:fade={{ duration: 100 }} out:fade={{ duration: 100 }}
id="account-info-panel" id="account-info-panel"
class="absolute right-[25px] top-[75px] bg-gray-200 dark:bg-immich-dark-gray dark:border dark:border-immich-dark-gray shadow-lg rounded-3xl w-[360px] z-[100]" class="absolute right-[25px] top-[75px] z-[100] w-[360px] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray"
> >
<div <div
class="flex flex-col items-center justify-center gap-4 bg-white dark:bg-immich-dark-primary/10 rounded-3xl mx-4 mt-4 p-4" class="mx-4 mt-4 flex flex-col items-center justify-center gap-4 rounded-3xl bg-white p-4 dark:bg-immich-dark-primary/10"
> >
<UserAvatar size="lg" {user} /> <UserAvatar size="lg" {user} />
<div> <div>
<p class="text-lg text-immich-primary dark:text-immich-dark-primary font-medium text-center"> <p class="text-center text-lg font-medium text-immich-primary dark:text-immich-dark-primary">
{user.firstName} {user.firstName}
{user.lastName} {user.lastName}
</p> </p>
@ -34,7 +34,7 @@
<a href={AppRoute.USER_SETTINGS} on:click={() => dispatch('close')}> <a href={AppRoute.USER_SETTINGS} on:click={() => dispatch('close')}>
<Button color="dark-gray" size="sm" shadow={false} border> <Button color="dark-gray" size="sm" shadow={false} border>
<div class="flex gap-2 place-items-center place-content-center px-2"> <div class="flex place-content-center place-items-center gap-2 px-2">
<Cog size="18" /> <Cog size="18" />
Account Settings Account Settings
</div> </div>
@ -44,7 +44,7 @@
<div class="mb-4 flex flex-col"> <div class="mb-4 flex flex-col">
<button <button
class="py-3 w-full font-medium flex place-items-center gap-2 hover:bg-immich-primary/10 text-gray-500 dark:text-gray-300 place-content-center" class="flex w-full place-content-center place-items-center gap-2 py-3 font-medium text-gray-500 hover:bg-immich-primary/10 dark:text-gray-300"
on:click={() => dispatch('logout')} on:click={() => dispatch('logout')}
> >
<Logout size={24} /> <Logout size={24} />

View file

@ -33,23 +33,23 @@
}; };
</script> </script>
<section id="dashboard-navbar" class="fixed h-[var(--navbar-height)] w-screen z-[900] text-sm"> <section id="dashboard-navbar" class="fixed z-[900] h-[var(--navbar-height)] w-screen text-sm">
<div <div
class="grid h-full md:grid-cols-[theme(spacing.64)_auto] grid-cols-[theme(spacing.18)_auto] border-b dark:border-b-immich-dark-gray items-center py-2 bg-immich-bg dark:bg-immich-dark-bg" class="grid h-full grid-cols-[theme(spacing.18)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
> >
<a data-sveltekit-preload-data="hover" class="flex gap-2 md:mx-6 mx-4 place-items-center" href={AppRoute.PHOTOS}> <a data-sveltekit-preload-data="hover" class="mx-4 flex place-items-center gap-2 md:mx-6" href={AppRoute.PHOTOS}>
<ImmichLogo height="35" width="35" /> <ImmichLogo height="35" width="35" />
<h1 class="font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary md:block hidden"> <h1 class="hidden font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary md:block">
IMMICH IMMICH
</h1> </h1>
</a> </a>
<div class="flex justify-between gap-16 pr-6"> <div class="flex justify-between gap-16 pr-6">
<div class="w-full max-w-5xl flex-1 pl-4 sm:block hidden"> <div class="hidden w-full max-w-5xl flex-1 pl-4 sm:block">
<SearchBar grayTheme={true} /> <SearchBar grayTheme={true} />
</div> </div>
<section class="flex gap-4 place-items-center justify-end max-sm:w-full"> <section class="flex place-items-center justify-end gap-4 max-sm:w-full">
<a href={AppRoute.SEARCH} id="search-button" class="sm:hidden pl-4"> <a href={AppRoute.SEARCH} id="search-button" class="pl-4 sm:hidden">
<IconButton title="Search"> <IconButton title="Search">
<div class="flex gap-2"> <div class="flex gap-2">
<Magnify size="1.5em" /> <Magnify size="1.5em" />
@ -64,7 +64,7 @@
<LinkButton on:click={() => dispatch('uploadClicked')}> <LinkButton on:click={() => dispatch('uploadClicked')}>
<div class="flex gap-2"> <div class="flex gap-2">
<TrayArrowUp size="1.5em" /> <TrayArrowUp size="1.5em" />
<span class="md:block hidden">Upload</span> <span class="hidden md:block">Upload</span>
</div> </div>
</LinkButton> </LinkButton>
</div> </div>
@ -72,18 +72,18 @@
{#if user.isAdmin} {#if user.isAdmin}
<a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}> <a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}>
<div class="sm:block hidden"> <div class="hidden sm:block">
<LinkButton> <LinkButton>
<span <span
class={$page.url.pathname.includes('/admin') class={$page.url.pathname.includes('/admin')
? 'text-immich-primary dark:text-immich-dark-primary underline item' ? 'item text-immich-primary underline dark:text-immich-dark-primary'
: ''} : ''}
> >
Administration Administration
</span> </span>
</LinkButton> </LinkButton>
</div> </div>
<div class="sm:hidden block"> <div class="block sm:hidden">
<IconButton title="Administration"> <IconButton title="Administration">
<Cog <Cog
size="1.5em" size="1.5em"
@ -94,7 +94,7 @@
</IconButton> </IconButton>
<hr <hr
class={$page.url.pathname.includes('/admin') class={$page.url.pathname.includes('/admin')
? 'block border-1 w-2/3 mx-auto border-immich-primary dark:border-immich-dark-primary' ? 'border-1 mx-auto block w-2/3 border-immich-primary dark:border-immich-dark-primary'
: 'hidden'} : 'hidden'}
/> />
</div> </div>
@ -117,7 +117,7 @@
<div <div
in:fade={{ delay: 500, duration: 150 }} in:fade={{ delay: 500, duration: 150 }}
out:fade={{ delay: 200, duration: 150 }} out:fade={{ delay: 200, duration: 150 }}
class="absolute -bottom-12 right-5 border bg-gray-500 dark:bg-immich-dark-gray text-[12px] text-gray-100 p-2 rounded-md shadow-md dark:border-immich-dark-gray" class="absolute -bottom-12 right-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray"
> >
<p>{user.firstName} {user.lastName}</p> <p>{user.firstName} {user.lastName}</p>
<p>{user.email}</p> <p>{user.email}</p>

View file

@ -13,6 +13,6 @@
}); });
</script> </script>
<div class="absolute top-0 left-0 w-screen h-[3px] bg-white z-[999999999]"> <div class="absolute left-0 top-0 z-[999999999] h-[3px] w-screen bg-white">
<span class="absolute bg-immich-primary h-[3px]" style:width={`${$progress}%`} /> <span class="absolute h-[3px] bg-immich-primary" style:width={`${$progress}%`} />
</div> </div>

View file

@ -74,12 +74,12 @@
transition:fade={{ duration: 250 }} transition:fade={{ duration: 250 }}
style:background-color={backgroundColor()} style:background-color={backgroundColor()}
style:border={borderStyle()} style:border={borderStyle()}
class="min-h-[80px] w-[300px] rounded-2xl z-[999999] shadow-md p-4 mb-4 hover:cursor-pointer" class="z-[999999] mb-4 min-h-[80px] w-[300px] rounded-2xl p-4 shadow-md hover:cursor-pointer"
on:click={handleClick} on:click={handleClick}
on:keydown={handleClick} on:keydown={handleClick}
> >
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex gap-2 place-items-center"> <div class="flex place-items-center gap-2">
<svelte:component this={icon} color={primaryColor()} size="20" /> <svelte:component this={icon} color={primaryColor()} size="20" />
<h2 style:color={primaryColor()} class="font-medium" data-testid="title"> <h2 style:color={primaryColor()} class="font-medium" data-testid="title">
{notificationInfo.type.toString()} {notificationInfo.type.toString()}
@ -90,7 +90,7 @@
</button> </button>
</div> </div>
<p class="whitespace-pre-wrap text-sm pl-[28px] pr-[16px]" data-testid="message"> <p class="whitespace-pre-wrap pl-[28px] pr-[16px] text-sm" data-testid="message">
{notificationInfo.message} {notificationInfo.message}
</p> </p>
</div> </div>

View file

@ -65,21 +65,21 @@
<BaseModal on:close> <BaseModal on:close>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<p class="font-medium">Set profile picture</p> <p class="font-medium">Set profile picture</p>
</span> </span>
</svelte:fragment> </svelte:fragment>
<div class="flex justify-center place-items-center items-center"> <div class="flex place-items-center items-center justify-center">
<div <div
class="w-1/2 aspect-square rounded-full overflow-hidden relative flex border-immich-primary dark:border-immich-dark-primary border-4 bg-immich-dark-primary dark:bg-immich-primary" class="relative flex aspect-square w-1/2 overflow-hidden rounded-full border-4 border-immich-primary bg-immich-dark-primary dark:border-immich-dark-primary dark:bg-immich-primary"
> >
<PhotoViewer bind:element={imgElement} {asset} /> <PhotoViewer bind:element={imgElement} {asset} />
</div> </div>
</div> </div>
<span class="p-4 flex justify-end"> <span class="flex justify-end p-4">
<Button on:click={handleSetProfilePicture}> <Button on:click={handleSetProfilePicture}>
<p>Set as profile picture</p> <p>Set as profile picture</p>
</Button> </Button>
</span> </span>
<div class="max-h-[400px] flex flex-col mb-2" /> <div class="mb-2 flex max-h-[400px] flex-col" />
</BaseModal> </BaseModal>

View file

@ -94,7 +94,7 @@
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div <div
id="immich-scrubbable-scrollbar" id="immich-scrubbable-scrollbar"
class="fixed right-0 bg-immich-bg z-[100] hover:cursor-row-resize select-none" class="fixed right-0 z-[100] select-none bg-immich-bg hover:cursor-row-resize"
style:width={isDragging ? '100vw' : '60px'} style:width={isDragging ? '100vw' : '60px'}
style:background-color={isDragging ? 'transparent' : 'transparent'} style:background-color={isDragging ? 'transparent' : 'transparent'}
on:mouseenter={() => (isHover = true)} on:mouseenter={() => (isHover = true)}
@ -109,7 +109,7 @@
> >
{#if isHover} {#if isHover}
<div <div
class="border-b-2 border-immich-primary dark:border-immich-dark-primary w-[100px] right-0 pr-6 py-1 text-sm pl-1 font-medium absolute bg-immich-bg dark:bg-immich-dark-gray z-[100] pointer-events-none rounded-tl-md shadow-lg dark:text-immich-dark-fg" class="pointer-events-none absolute right-0 z-[100] w-[100px] rounded-tl-md border-b-2 border-immich-primary bg-immich-bg py-1 pl-1 pr-6 text-sm font-medium shadow-lg dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg"
style:top={currentMouseYLocation + 'px'} style:top={currentMouseYLocation + 'px'}
> >
{hoveredDate?.toLocaleString('default', { month: 'short' })} {hoveredDate?.toLocaleString('default', { month: 'short' })}
@ -120,7 +120,7 @@
<!-- Scroll Position Indicator Line --> <!-- Scroll Position Indicator Line -->
{#if !isDragging} {#if !isDragging}
<div <div
class="absolute right-0 w-10 h-[2px] bg-immich-primary dark:bg-immich-dark-primary" class="absolute right-0 h-[2px] w-10 bg-immich-primary dark:bg-immich-dark-primary"
style:top={scrollbarPosition + 'px'} style:top={scrollbarPosition + 'px'}
/> />
{/if} {/if}
@ -139,7 +139,7 @@
{#if segment.height > 8} {#if segment.height > 8}
<div <div
aria-label={segment.timeGroup + ' ' + segment.count} aria-label={segment.timeGroup + ' ' + segment.count}
class="absolute right-0 pr-5 z-10 text-xs font-medium dark:text-immich-dark-fg" class="absolute right-0 z-10 pr-5 text-xs font-medium dark:text-immich-dark-fg"
> >
{groupDate.getFullYear()} {groupDate.getFullYear()}
</div> </div>
@ -147,7 +147,7 @@
{:else if segment.height > 5} {:else if segment.height > 5}
<div <div
aria-label={segment.timeGroup + ' ' + segment.count} aria-label={segment.timeGroup + ' ' + segment.count}
class="absolute right-0 rounded-full h-[4px] w-[4px] mr-3 bg-gray-300 block" class="absolute right-0 mr-3 block h-[4px] w-[4px] rounded-full bg-gray-300"
/> />
{/if} {/if}
</div> </div>

View file

@ -66,9 +66,9 @@
name="q" name="q"
class="w-full transition-all {grayTheme class="w-full transition-all {grayTheme
? 'dark:bg-immich-dark-gray' ? 'dark:bg-immich-dark-gray'
: 'dark:bg-immich-dark-bg'} text-immich-fg/75 dark:text-immich-dark-fg px-14 py-4 {showBigSearchBar : 'dark:bg-immich-dark-bg'} px-14 py-4 text-immich-fg/75 dark:text-immich-dark-fg {showBigSearchBar
? 'rounded-t-3xl bg-white border border-gray-200 dark:border-gray-800' ? 'rounded-t-3xl border border-gray-200 bg-white dark:border-gray-800'
: 'rounded-3xl bg-gray-200 border border-transparent'}" : 'rounded-3xl border border-transparent bg-gray-200'}"
placeholder="Search your photos" placeholder="Search your photos"
required required
pattern="^(?!m:$).*$" pattern="^(?!m:$).*$"
@ -79,7 +79,7 @@
<div class="absolute inset-y-0 right-0 flex items-center pr-4"> <div class="absolute inset-y-0 right-0 flex items-center pr-4">
<button <button
type="reset" type="reset"
class="dark:text-immich-dark-fg/75 hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/25 rounded-full p-2 active:bg-immich-primary/10 dark:active:bg-immich-dark-primary/[.35]" class="rounded-full p-2 hover:bg-immich-primary/5 active:bg-immich-primary/10 dark:text-immich-dark-fg/75 dark:hover:bg-immich-dark-primary/25 dark:active:bg-immich-dark-primary/[.35]"
> >
<Close size="1.5em" /> <Close size="1.5em" />
</button> </button>
@ -89,23 +89,23 @@
{#if showBigSearchBar} {#if showBigSearchBar}
<div <div
transition:fly={{ y: 25, duration: 250 }} transition:fly={{ y: 25, duration: 250 }}
class="w-full pb-5 absolute bg-white transition-all rounded-b-3xl shadow-2xl border border-gray-200 dark:bg-immich-dark-gray dark:border-gray-800 dark:text-gray-300" class="absolute w-full rounded-b-3xl border border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-800 dark:bg-immich-dark-gray dark:text-gray-300"
> >
<div class="px-5 pt-5 text-xs"> <div class="px-5 pt-5 text-xs">
<p> <p>
Smart search is enabled by default, to search for metadata use the syntax <span Smart search is enabled by default, to search for metadata use the syntax <span
class="font-mono p-2 font-semibold text-immich-primary dark:text-immich-dark-primary bg-gray-100 rounded-lg dark:bg-gray-900 leading-7" class="rounded-lg bg-gray-100 p-2 font-mono font-semibold leading-7 text-immich-primary dark:bg-gray-900 dark:text-immich-dark-primary"
>m:your-search-term</span >m:your-search-term</span
> >
</p> </p>
</div> </div>
{#if $savedSearchTerms.length > 0} {#if $savedSearchTerms.length > 0}
<div class="px-5 pt-5 text-xs flex justify-between"> <div class="flex justify-between px-5 pt-5 text-xs">
<p>RECENT SEARCHES</p> <p>RECENT SEARCHES</p>
<button <button
type="button" type="button"
class="text-immich-primary dark:text-immich-dark-primary font-semibold p-2 hover:bg-immich-primary/25 rounded-lg" class="rounded-lg p-2 font-semibold text-immich-primary hover:bg-immich-primary/25 dark:text-immich-dark-primary"
on:click={clearSearchTerm}>Clear all</button on:click={clearSearchTerm}>Clear all</button
> >
</div> </div>
@ -114,7 +114,7 @@
{#each $savedSearchTerms as savedSearchTerm, i (i)} {#each $savedSearchTerms as savedSearchTerm, i (i)}
<button <button
type="button" type="button"
class="w-full hover:bg-gray-100 dark:hover:bg-gray-500/10 px-5 py-3 cursor-pointer flex gap-3 text-black dark:text-gray-300" class="flex w-full cursor-pointer gap-3 px-5 py-3 text-black hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-500/10"
on:click={() => { on:click={() => {
value = savedSearchTerm; value = savedSearchTerm;
onSearch(false); onSearch(false);

View file

@ -19,35 +19,35 @@
<div <div
on:click={onButtonClicked} on:click={onButtonClicked}
on:keydown={onButtonClicked} on:keydown={onButtonClicked}
class="flex gap-4 justify-between place-items-center w-full transition-[padding] delay-100 duration-100 py-3 rounded-r-full hover:bg-immich-gray dark:hover:bg-immich-dark-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary hover:cursor-pointer class="flex w-full place-items-center justify-between gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary
{isSelected {isSelected
? 'bg-immich-primary/10 dark:bg-immich-dark-primary/10 text-immich-primary dark:text-immich-dark-primary hover:bg-immich-primary/25' ? 'bg-immich-primary/10 text-immich-primary hover:bg-immich-primary/25 dark:bg-immich-dark-primary/10 dark:text-immich-dark-primary'
: ''} : ''}
pl-5 group-hover:sm:px-5 md:px-5 pl-5 group-hover:sm:px-5 md:px-5
" "
> >
<div class="flex gap-4 place-items-center w-full overflow-hidden truncate"> <div class="flex w-full place-items-center gap-4 overflow-hidden truncate">
<svelte:component this={logo} size="1.5em" class="shrink-0 {flippedLogo ? '-scale-x-100' : ''}" /> <svelte:component this={logo} size="1.5em" class="shrink-0 {flippedLogo ? '-scale-x-100' : ''}" />
<p class="font-medium text-sm">{title}</p> <p class="text-sm font-medium">{title}</p>
</div> </div>
<div <div
class="transition-[height] group-hover:sm:overflow-visible md:overflow-visible overflow-hidden duration-100 delay-1000 sm:group-hover:h-auto md:h-auto h-0" class="h-0 overflow-hidden transition-[height] delay-1000 duration-100 sm:group-hover:h-auto group-hover:sm:overflow-visible md:h-auto md:overflow-visible"
> >
{#if $$slots.moreInformation} {#if $$slots.moreInformation}
<div <div
class="relative flex justify-center select-none cursor-default" class="relative flex cursor-default select-none justify-center"
on:mouseenter={() => (showMoreInformation = true)} on:mouseenter={() => (showMoreInformation = true)}
on:mouseleave={() => (showMoreInformation = false)} on:mouseleave={() => (showMoreInformation = false)}
> >
<div class="hover:cursor-help p-1 text-gray-600 dark:text-gray-400"> <div class="p-1 text-gray-600 hover:cursor-help dark:text-gray-400">
<InformationOutline /> <InformationOutline />
</div> </div>
{#if showMoreInformation} {#if showMoreInformation}
<div class="absolute right-6 top-0"> <div class="absolute right-6 top-0">
<div <div
class="flex place-items-center place-content-center whitespace-nowrap rounded-3xl shadow-lg py-3 px-6 bg-immich-bg text-immich-fg dark:bg-gray-600 dark:text-immich-dark-fg text-xs border dark:border-immich-dark-gray" class="flex place-content-center place-items-center whitespace-nowrap rounded-3xl border bg-immich-bg px-6 py-3 text-xs text-immich-fg shadow-lg dark:border-immich-dark-gray dark:bg-gray-600 dark:text-immich-dark-fg"
class:hidden={!showMoreInformation} class:hidden={!showMoreInformation}
transition:fade={{ duration: 200 }} transition:fade={{ duration: 200 }}
> >

View file

@ -3,7 +3,7 @@
<section <section
id="sidebar" id="sidebar"
class="group flex flex-col gap-1 pt-8 bg-immich-bg dark:bg-immich-dark-bg transition-all duration-200 z-10 w-18 md:w-64 hover:sm:pr-6 md:pr-6 hover:sm:w-64 hover:sm:shadow-2xl hover:md:shadow-none hover:md:border-none hover:sm:border-r hover:sm:dark:border-r-immich-dark-gray relative overflow-y-auto immich-scrollbar" class="immich-scrollbar group relative z-10 flex w-18 flex-col gap-1 overflow-y-auto bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg hover:sm:w-64 hover:sm:border-r hover:sm:pr-6 hover:sm:shadow-2xl hover:sm:dark:border-r-immich-dark-gray md:w-64 md:pr-6 hover:md:border-none hover:md:shadow-none"
> >
<slot /> <slot />
</section> </section>

View file

@ -80,9 +80,9 @@
</SideBarButton> </SideBarButton>
</a> </a>
<div class="text-xs dark:text-immich-dark-fg transition-all duration-200"> <div class="text-xs transition-all duration-200 dark:text-immich-dark-fg">
<p class="p-6 hidden md:block group-hover:sm:block">LIBRARY</p> <p class="hidden p-6 group-hover:sm:block md:block">LIBRARY</p>
<hr class="mt-8 mb-[31px] mx-4 block md:hidden group-hover:sm:hidden" /> <hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
</div> </div>
<a data-sveltekit-preload-data="hover" href={AppRoute.FAVORITES} draggable="false"> <a data-sveltekit-preload-data="hover" href={AppRoute.FAVORITES} draggable="false">
<SideBarButton <SideBarButton

View file

@ -51,16 +51,16 @@
<div class="dark:text-immich-dark-fg"> <div class="dark:text-immich-dark-fg">
<div class="storage-status grid grid-cols-[64px_auto]"> <div class="storage-status grid grid-cols-[64px_auto]">
<div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary pb-[2.15rem] group-hover:sm:pb-0 md:pb-0"> <div class="pb-[2.15rem] pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
<Cloud size={'24'} /> <Cloud size={'24'} />
</div> </div>
<div class="hidden md:block group-hover:sm:block"> <div class="hidden group-hover:sm:block md:block">
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Storage</p> <p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Storage</p>
{#if serverInfo} {#if serverInfo}
<div class="w-full bg-gray-200 rounded-full h-[7px] dark:bg-gray-700 my-2"> <div class="my-2 h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
<!-- style={`width: ${$downloadAssets[fileName]}%`} --> <!-- style={`width: ${$downloadAssets[fileName]}%`} -->
<div <div
class="bg-immich-primary dark:bg-immich-dark-primary h-[7px] rounded-full" class="h-[7px] rounded-full bg-immich-primary dark:bg-immich-dark-primary"
style="width: {getStorageUsagePercentage()}%" style="width: {getStorageUsagePercentage()}%"
/> />
</div> </div>
@ -76,16 +76,16 @@
</div> </div>
</div> </div>
<div> <div>
<hr class="ml-5 my-4 dark:border-immich-dark-gray" /> <hr class="my-4 ml-5 dark:border-immich-dark-gray" />
</div> </div>
<div class="server-status grid grid-cols-[64px_auto]"> <div class="server-status grid grid-cols-[64px_auto]">
<div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary pb-11 md:pb-0 group-hover:sm:pb-0"> <div class="pb-11 pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
<Dns size={'24'} /> <Dns size={'24'} />
</div> </div>
<div class="text-xs hidden md:block group-hover:sm:block"> <div class="hidden text-xs group-hover:sm:block md:block">
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Server</p> <p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Server</p>
<div class="flex justify-items-center justify-between mt-2"> <div class="mt-2 flex justify-between justify-items-center">
<p>Status</p> <p>Status</p>
{#if isServerOk} {#if isServerOk}
@ -95,7 +95,7 @@
{/if} {/if}
</div> </div>
<div class="flex justify-items-center justify-between mt-2"> <div class="mt-2 flex justify-between justify-items-center">
<p>Version</p> <p>Version</p>
<p class="font-medium text-immich-primary dark:text-immich-dark-primary"> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">
{serverVersion} {serverVersion}

View file

@ -20,11 +20,11 @@
<IconButton on:click={toggleTheme} title="Toggle theme"> <IconButton on:click={toggleTheme} title="Toggle theme">
{#if $colorTheme === 'light'} {#if $colorTheme === 'light'}
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /></svg ><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /></svg
> >
{:else} {:else}
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
><path ><path
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
fill-rule="evenodd" fill-rule="evenodd"

View file

@ -15,12 +15,12 @@
<div <div
in:fade={{ duration: 250 }} in:fade={{ duration: 250 }}
out:fade={{ duration: 100 }} out:fade={{ duration: 100 }}
class="text-xs mt-3 rounded-lg bg-immich-bg grid grid-cols-[70px_auto] gap-2 h-[70px]" class="mt-3 grid h-[70px] grid-cols-[70px_auto] gap-2 rounded-lg bg-immich-bg text-xs"
> >
<div class="relative"> <div class="relative">
{#if showFallbackImage} {#if showFallbackImage}
<div in:fade={{ duration: 250 }}> <div in:fade={{ duration: 250 }}>
<ImmichLogo class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg" /> <ImmichLogo class="h-[70px] w-[70px] rounded-bl-lg rounded-tl-lg object-cover" />
</div> </div>
{:else} {:else}
<img <img
@ -34,30 +34,30 @@
}} }}
src={previewURL} src={previewURL}
alt="Preview of asset" alt="Preview of asset"
class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg" class="h-[70px] w-[70px] rounded-bl-lg rounded-tl-lg object-cover"
draggable="false" draggable="false"
/> />
{/if} {/if}
<div class="bottom-0 left-0 absolute w-full h-[25px] bg-immich-primary/30"> <div class="absolute bottom-0 left-0 h-[25px] w-full bg-immich-primary/30">
<p <p
class="absolute bottom-1 right-1 object-right-bottom text-gray-50/95 font-semibold stroke-immich-primary uppercase" class="absolute bottom-1 right-1 stroke-immich-primary object-right-bottom font-semibold uppercase text-gray-50/95"
> >
.{getFilenameExtension(uploadAsset.file.name)} .{getFilenameExtension(uploadAsset.file.name)}
</p> </p>
</div> </div>
</div> </div>
<div class="p-2 pr-4 flex flex-col justify-between"> <div class="flex flex-col justify-between p-2 pr-4">
<input <input
disabled disabled
class="bg-gray-100 border w-full p-1 rounded-md text-[10px] px-2" class="w-full rounded-md border bg-gray-100 p-1 px-2 text-[10px]"
value={`[${asByteUnitString(uploadAsset.file.size, $locale)}] ${uploadAsset.file.name}`} value={`[${asByteUnitString(uploadAsset.file.size, $locale)}] ${uploadAsset.file.name}`}
/> />
<div class="w-full bg-gray-300 h-[15px] rounded-md mt-[5px] text-white relative"> <div class="relative mt-[5px] h-[15px] w-full rounded-md bg-gray-300 text-white">
<div class="bg-immich-primary h-[15px] rounded-md transition-all" style={`width: ${uploadAsset.progress}%`} /> <div class="h-[15px] rounded-md bg-immich-primary transition-all" style={`width: ${uploadAsset.progress}%`} />
<p class="absolute h-full w-full text-center top-0 text-[10px]"> <p class="absolute top-0 h-full w-full text-center text-[10px]">
{uploadAsset.progress}/100 {uploadAsset.progress}/100
</p> </p>
</div> </div>

View file

@ -33,24 +33,24 @@
type: NotificationType.Info, type: NotificationType.Info,
}); });
}} }}
class="absolute right-6 bottom-6 z-[10000]" class="absolute bottom-6 right-6 z-[10000]"
> >
{#if showDetail} {#if showDetail}
<div <div
in:scale={{ duration: 250, easing: quartInOut }} in:scale={{ duration: 250, easing: quartInOut }}
class="bg-gray-200 p-4 text-sm w-[300px] rounded-lg shadow-sm border" class="w-[300px] rounded-lg border bg-gray-200 p-4 text-sm shadow-sm"
> >
<div class="flex justify-between place-item-center mb-4"> <div class="place-item-center mb-4 flex justify-between">
<p class="text-xs text-gray-500">UPLOADING {$uploadAssetsStore.length}</p> <p class="text-xs text-gray-500">UPLOADING {$uploadAssetsStore.length}</p>
<button <button
on:click={() => (showDetail = false)} on:click={() => (showDetail = false)}
class="w-[20px] h-[20px] bg-gray-50 rounded-full flex place-items-center place-content-center transition-colors hover:bg-gray-100" class="flex h-[20px] w-[20px] place-content-center place-items-center rounded-full bg-gray-50 transition-colors hover:bg-gray-100"
> >
<WindowMinimize /> <WindowMinimize />
</button> </button>
</div> </div>
<div class="max-h-[400px] overflow-y-auto pr-2 rounded-lg immich-scrollbar"> <div class="immich-scrollbar max-h-[400px] overflow-y-auto rounded-lg pr-2">
{#each $uploadAssetsStore as uploadAsset} {#each $uploadAssetsStore as uploadAsset}
{#key uploadAsset.id} {#key uploadAsset.id}
<UploadAssetPreview {uploadAsset} /> <UploadAssetPreview {uploadAsset} />
@ -63,14 +63,14 @@
<button <button
in:scale={{ duration: 250, easing: quartInOut }} in:scale={{ duration: 250, easing: quartInOut }}
on:click={() => (showDetail = true)} on:click={() => (showDetail = true)}
class="absolute -top-4 -left-4 text-xs rounded-full w-10 h-10 p-5 flex place-items-center place-content-center bg-immich-primary text-gray-200" class="absolute -left-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-primary p-5 text-xs text-gray-200"
> >
{$uploadAssetsStore.length} {$uploadAssetsStore.length}
</button> </button>
<button <button
in:scale={{ duration: 250, easing: quartInOut }} in:scale={{ duration: 250, easing: quartInOut }}
on:click={() => (showDetail = true)} on:click={() => (showDetail = true)}
class="bg-gray-300 p-5 rounded-full w-16 h-16 flex place-items-center place-content-center text-sm shadow-lg" class="flex h-16 w-16 place-content-center place-items-center rounded-full bg-gray-300 p-5 text-sm shadow-lg"
> >
<div class="animate-pulse"> <div class="animate-pulse">
<CloudUploadOutline size="30" color="#4250af" /> <CloudUploadOutline size="30" color="#4250af" />

View file

@ -49,7 +49,7 @@
</script> </script>
<figure <figure
class="{sizeClass} {colorClass} {interactiveClass} shadow-md overflow-hidden" class="{sizeClass} {colorClass} {interactiveClass} overflow-hidden shadow-md"
class:rounded-full={rounded} class:rounded-full={rounded}
title={showTitle ? title : undefined} title={showTitle ? title : undefined}
> >
@ -57,7 +57,7 @@
<img <img
src={api.getProfileImageUrl(user.id)} src={api.getProfileImageUrl(user.id)}
alt="Profile image of {title}" alt="Profile image of {title}"
class="object-cover w-full h-full" class="h-full w-full object-cover"
class:hidden={showFallback} class:hidden={showFallback}
draggable="false" draggable="false"
use:imageLoad use:imageLoad
@ -66,7 +66,7 @@
{/if} {/if}
{#if showFallback} {#if showFallback}
<span <span
class="flex justify-center items-center w-full h-full select-none" class="flex h-full w-full select-none items-center justify-center"
class:text-xs={size === 'sm'} class:text-xs={size === 'sm'}
class:text-lg={size === 'lg'} class:text-lg={size === 'lg'}
class:font-medium={!autoColor} class:font-medium={!autoColor}

View file

@ -43,15 +43,15 @@
{#if showModal} {#if showModal}
<FullScreenModal on:clickOutside={() => (showModal = false)}> <FullScreenModal on:clickOutside={() => (showModal = false)}>
<div <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray shadow-sm max-w-lg rounded-3xl py-10 px-8 dark:text-immich-dark-fg" class="max-w-lg rounded-3xl border bg-immich-bg px-8 py-10 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
> >
<p class="text-2xl mb-4">🎉 NEW VERSION AVAILABLE 🎉</p> <p class="mb-4 text-2xl">🎉 NEW VERSION AVAILABLE 🎉</p>
<div> <div>
Hi friend, there is a new release of Hi friend, there is a new release of
<span class="font-immich-title text-immich-primary dark:text-immich-dark-primary font-bold">IMMICH</span>, <span class="font-immich-title font-bold text-immich-primary dark:text-immich-dark-primary">IMMICH</span>,
please take your time to visit the please take your time to visit the
<span class="underline font-medium" <span class="font-medium underline"
><a href="https://github.com/immich-app/immich/releases/latest" target="_blank" rel="noopener noreferrer" ><a href="https://github.com/immich-app/immich/releases/latest" target="_blank" rel="noopener noreferrer"
>release notes</a >release notes</a
></span ></span
@ -60,7 +60,7 @@
especially if you use WatchTower or any mechanism that handles updating your application automatically. especially if you use WatchTower or any mechanism that handles updating your application automatically.
</div> </div>
<div class="font-medium mt-4">Your friend, Alex</div> <div class="mt-4 font-medium">Your friend, Alex</div>
<div class="font-sm mt-8"> <div class="font-sm mt-8">
<code>Server Version: {serverVersionName}</code> <code>Server Version: {serverVersionName}</code>
@ -68,7 +68,7 @@
<code>Latest Version: {githubVersion}</code> <code>Latest Version: {githubVersion}</code>
</div> </div>
<div class="text-right mt-8"> <div class="mt-8 text-right">
<Button fullwidth on:click={onAcknowledge}>Acknowledge</Button> <Button fullwidth on:click={onAcknowledge}>Acknowledge</Button>
</div> </div>
</div> </div>

View file

@ -59,7 +59,7 @@
</script> </script>
<div <div
class="w-full flex gap-4 dark:text-immich-gray transition-all border-b border-gray-200 dark:border-gray-600 hover:border-immich-primary dark:hover:border-immich-dark-primary py-4" class="flex w-full gap-4 border-b border-gray-200 py-4 transition-all hover:border-immich-primary dark:border-gray-600 dark:text-immich-gray dark:hover:border-immich-dark-primary"
> >
<div> <div>
{#await getAssetInfo()} {#await getAssetInfo()}
@ -69,7 +69,7 @@
id={asset.id} id={asset.id}
src={api.getAssetThumbnailUrl(asset.id, ThumbnailFormat.Webp)} src={api.getAssetThumbnailUrl(asset.id, ThumbnailFormat.Webp)}
alt={asset.id} alt={asset.id}
class="object-cover w-[100px] h-[100px] rounded-lg" class="h-[100px] w-[100px] rounded-lg object-cover"
loading="lazy" loading="lazy"
draggable="false" draggable="false"
/> />
@ -78,10 +78,10 @@
<div class="flex flex-col justify-between"> <div class="flex flex-col justify-between">
<div class="info-top"> <div class="info-top">
<div class="text-xs font-mono font-semibold text-gray-500 dark:text-gray-400"> <div class="font-mono text-xs font-semibold text-gray-500 dark:text-gray-400">
{#if link.expiresAt} {#if link.expiresAt}
{#if isExpired(link.expiresAt)} {#if isExpired(link.expiresAt)}
<p class="text-red-600 dark:text-red-400 font-bold">Expired</p> <p class="font-bold text-red-600 dark:text-red-400">Expired</p>
{:else} {:else}
<p> <p>
Expires {getCountDownExpirationDate()} Expires {getCountDownExpirationDate()}
@ -93,7 +93,7 @@
</div> </div>
<div class="text-sm"> <div class="text-sm">
<div class="flex gap-2 place-items-center text-immich-primary dark:text-immich-dark-primary"> <div class="flex place-items-center gap-2 text-immich-primary dark:text-immich-dark-primary">
{#if link.type === SharedLinkType.Album} {#if link.type === SharedLinkType.Album}
<p> <p>
{link.album?.albumName.toUpperCase()} {link.album?.albumName.toUpperCase()}
@ -122,7 +122,7 @@
<div class="info-bottom flex gap-4"> <div class="info-bottom flex gap-4">
{#if link.allowUpload} {#if link.allowUpload}
<div <div
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[80px]" class="flex w-[80px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
> >
Upload Upload
</div> </div>
@ -130,7 +130,7 @@
{#if link.allowDownload} {#if link.allowDownload}
<div <div
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[100px]" class="flex w-[100px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
> >
Download Download
</div> </div>
@ -138,7 +138,7 @@
{#if link.showExif} {#if link.showExif}
<div <div
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[60px]" class="flex w-[60px] place-content-center place-items-center rounded-full bg-immich-primary px-2 py-1 text-xs text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray"
> >
EXIF EXIF
</div> </div>
@ -146,7 +146,7 @@
</div> </div>
</div> </div>
<div class="flex-auto flex flex-col place-content-center place-items-end text-right"> <div class="flex flex-auto flex-col place-content-center place-items-end text-right">
<div class="flex"> <div class="flex">
<CircleIconButton logo={Delete} on:click={() => dispatch('delete')} /> <CircleIconButton logo={Delete} on:click={() => dispatch('delete')} />
<CircleIconButton logo={CircleEditOutline} on:click={() => dispatch('edit')} /> <CircleIconButton logo={CircleEditOutline} on:click={() => dispatch('edit')} />

View file

@ -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" on:submit|preventDefault> <form autocomplete="off" on:submit|preventDefault>
<div class="flex flex-col gap-4 ml-4 mt-4"> <div class="ml-4 mt-4 flex flex-col gap-4">
<SettingInputField <SettingInputField
inputType={SettingInputFieldType.PASSWORD} inputType={SettingInputFieldType.PASSWORD}
label="PASSWORD" label="PASSWORD"

View file

@ -22,9 +22,9 @@
}; };
</script> </script>
<div class="flex flex-row w-full"> <div class="flex w-full flex-row">
<!-- TODO: Device Image --> <!-- TODO: Device Image -->
<div class="hidden sm:flex pr-2 justify-center items-center text-immich-primary dark:text-immich-dark-primary"> <div class="hidden items-center justify-center pr-2 text-immich-primary dark:text-immich-dark-primary sm:flex">
{#if device.deviceOS === 'Android'} {#if device.deviceOS === 'Android'}
<Android size="40" /> <Android size="40" />
{:else if device.deviceOS === 'iOS' || device.deviceOS === 'Mac OS'} {:else if device.deviceOS === 'iOS' || device.deviceOS === 'Mac OS'}
@ -41,8 +41,8 @@
<Help size="40" /> <Help size="40" />
{/if} {/if}
</div> </div>
<div class="pl-4 sm:pl-0 flex flex-row grow justify-between gap-1"> <div class="flex grow flex-row justify-between gap-1 pl-4 sm:pl-0">
<div class="flex flex-col gap-1 justify-center dark:text-white"> <div class="flex flex-col justify-center gap-1 dark:text-white">
<span class="text-sm"> <span class="text-sm">
{#if device.deviceType || device.deviceOS} {#if device.deviceType || device.deviceOS}
<span>{device.deviceOS || 'Unknown'}{device.deviceType || 'Unknown'}</span> <span>{device.deviceOS || 'Unknown'}{device.deviceType || 'Unknown'}</span>
@ -56,10 +56,10 @@
</div> </div>
</div> </div>
{#if !device.current} {#if !device.current}
<div class="text-sm flex flex-col justify-center"> <div class="flex flex-col justify-center text-sm">
<button <button
on:click={() => dispatcher('delete')} on:click={() => dispatcher('delete')}
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75" class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
title="Log out" title="Log out"
> >
<TrashCanOutline size="16" /> <TrashCanOutline size="16" />

View file

@ -71,13 +71,13 @@
<section class="my-4"> <section class="my-4">
{#if currentDevice} {#if currentDevice}
<div class="mb-6"> <div class="mb-6">
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">CURRENT DEVICE</h3> <h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">CURRENT DEVICE</h3>
<DeviceCard device={currentDevice} /> <DeviceCard device={currentDevice} />
</div> </div>
{/if} {/if}
{#if otherDevices.length > 0} {#if otherDevices.length > 0}
<div class="mb-6"> <div class="mb-6">
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">OTHER DEVICES</h3> <h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">OTHER DEVICES</h3>
{#each otherDevices as device, i} {#each otherDevices as device, i}
<DeviceCard {device} on:delete={() => (deleteDevice = device)} /> <DeviceCard {device} on:delete={() => (deleteDevice = device)} />
{#if i !== otherDevices.length - 1} {#if i !== otherDevices.length - 1}
@ -85,7 +85,7 @@
{/if} {/if}
{/each} {/each}
</div> </div>
<h3 class="font-medium text-xs mb-2 text-immich-primary dark:text-immich-dark-primary">LOG OUT ALL DEVICES</h3> <h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">LOG OUT ALL DEVICES</h3>
<div class="flex justify-end"> <div class="flex justify-end">
<Button color="red" size="sm" on:click={() => (deleteAll = true)}>Log Out All Devices</Button> <Button color="red" size="sm" on:click={() => (deleteAll = true)}>Log Out All Devices</Button>
</div> </div>

View file

@ -60,7 +60,7 @@
<div in:fade={{ duration: 500 }}> <div in:fade={{ duration: 500 }}>
<div class="flex justify-end"> <div class="flex justify-end">
{#if loading} {#if loading}
<div class="flex place-items-center place-content-center"> <div class="flex place-content-center place-items-center">
<LoadingSpinner /> <LoadingSpinner />
</div> </div>
{:else if config.enabled} {:else if config.enabled}

View file

@ -37,22 +37,22 @@
<BaseModal on:close={() => dispatch('close')}> <BaseModal on:close={() => dispatch('close')}>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex place-items-center gap-2">
<ImmichLogo width={24} /> <ImmichLogo width={24} />
<p class="font-medium">Add partner</p> <p class="font-medium">Add partner</p>
</span> </span>
</svelte:fragment> </svelte:fragment>
<div class="max-h-[300px] overflow-y-auto immich-scrollbar"> <div class="immich-scrollbar max-h-[300px] overflow-y-auto">
{#if availableUsers.length > 0} {#if availableUsers.length > 0}
{#each availableUsers as user} {#each availableUsers as user}
<button <button
on:click={() => selectUser(user)} on:click={() => selectUser(user)}
class="w-full flex place-items-center gap-4 py-4 px-5 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all" class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700"
> >
{#if selectedUsers.includes(user)} {#if selectedUsers.includes(user)}
<span <span
class="bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-bg rounded-full w-12 h-12 border flex place-items-center place-content-center text-3xl dark:border-immich-dark-gray" class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg"
>✓</span >✓</span
> >
{:else} {:else}
@ -71,7 +71,7 @@
</button> </button>
{/each} {/each}
{:else} {:else}
<p class="text-sm p-5"> <p class="p-5 text-sm">
Looks like you shared your photos with all users or you don't have any user to share with. Looks like you shared your photos with all users or you don't have any user to share with.
</p> </p>
{/if} {/if}

View file

@ -56,7 +56,7 @@
{#if partners.length > 0} {#if partners.length > 0}
<div class="flex flex-row gap-4"> <div class="flex flex-row gap-4">
{#each partners as partner (partner.id)} {#each partners as partner (partner.id)}
<div class="flex rounded-lg gap-4 py-4 px-5 transition-all"> <div class="flex gap-4 rounded-lg px-5 py-4 transition-all">
<UserAvatar user={partner} size="md" autoColor /> <UserAvatar user={partner} size="md" autoColor />
<div class="text-left"> <div class="text-left">
<p class="text-immich-fg dark:text-immich-dark-fg"> <p class="text-immich-fg dark:text-immich-dark-fg">

View file

@ -116,43 +116,43 @@
<section class="my-4"> <section class="my-4">
<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}> <div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
<div class="flex justify-end mb-2"> <div class="mb-2 flex justify-end">
<Button size="sm" on:click={() => (newKey = { name: 'API Key' })}>New API Key</Button> <Button size="sm" on:click={() => (newKey = { name: 'API Key' })}>New API Key</Button>
</div> </div>
{#if keys.length > 0} {#if keys.length > 0}
<table class="text-left w-full"> <table class="w-full text-left">
<thead <thead
class="border rounded-md mb-4 bg-gray-50 flex text-immich-primary w-full h-12 dark:bg-immich-dark-gray dark:text-immich-dark-primary dark:border-immich-dark-gray" class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary"
> >
<tr class="flex w-full place-items-center"> <tr class="flex w-full place-items-center">
<th class="text-center w-1/3 font-medium text-sm">Name</th> <th class="w-1/3 text-center text-sm font-medium">Name</th>
<th class="text-center w-1/3 font-medium text-sm">Created</th> <th class="w-1/3 text-center text-sm font-medium">Created</th>
<th class="text-center w-1/3 font-medium text-sm">Action</th> <th class="w-1/3 text-center text-sm font-medium">Action</th>
</tr> </tr>
</thead> </thead>
<tbody class="overflow-y-auto rounded-md w-full block border dark:border-immich-dark-gray"> <tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
{#each keys as key, i} {#each keys as key, i}
{#key key.id} {#key key.id}
<tr <tr
class={`text-center flex place-items-center w-full h-[80px] dark:text-immich-dark-fg ${ class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
i % 2 == 0 ? 'bg-immich-gray dark:bg-immich-dark-gray/75' : 'bg-immich-bg dark:bg-immich-dark-gray/50' i % 2 == 0 ? 'bg-immich-gray dark:bg-immich-dark-gray/75' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
}`} }`}
> >
<td class="text-sm px-4 w-1/3 text-ellipsis">{key.name}</td> <td class="w-1/3 text-ellipsis px-4 text-sm">{key.name}</td>
<td class="text-sm px-4 w-1/3 text-ellipsis" <td class="w-1/3 text-ellipsis px-4 text-sm"
>{new Date(key.createdAt).toLocaleDateString($locale, format)} >{new Date(key.createdAt).toLocaleDateString($locale, format)}
</td> </td>
<td class="text-sm px-4 w-1/3 text-ellipsis"> <td class="w-1/3 text-ellipsis px-4 text-sm">
<button <button
on:click={() => (editKey = key)} on:click={() => (editKey = key)}
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75" class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
> >
<PencilOutline size="16" /> <PencilOutline size="16" />
</button> </button>
<button <button
on:click={() => (deleteKey = key)} on:click={() => (deleteKey = key)}
class="bg-immich-primary dark:bg-immich-dark-primary text-gray-100 dark:text-gray-700 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75" class="rounded-full bg-immich-primary p-3 text-gray-100 transition-all duration-150 hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:text-gray-700"
> >
<TrashCanOutline size="16" /> <TrashCanOutline size="16" />
</button> </button>

Some files were not shown because too many files have changed in this diff Show more