1
0
mirror of https://github.com/immich-app/immich.git synced 2024-11-28 09:33:27 +02:00

feat(web) dark mode (#867)

This commit is contained in:
Alex 2022-10-26 11:10:48 -05:00 committed by GitHub
parent ae96508e15
commit f94176a910
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 362 additions and 186 deletions

View File

@ -59,15 +59,15 @@ input:focus-visible {
@layer utilities { @layer utilities {
.immich-form-input { .immich-form-input {
@apply bg-slate-100 p-2 rounded-md focus:border-immich-primary text-sm; @apply bg-slate-100 p-2 rounded-md dark:text-immich-dark-bg focus:border-immich-primary text-sm;
} }
.immich-form-label { .immich-form-label {
@apply font-medium text-sm text-gray-500; @apply font-medium text-sm text-gray-500 dark:text-gray-300;
} }
.immich-btn-primary { .immich-btn-primary {
@apply bg-immich-primary text-gray-100 border rounded-xl py-2 px-4 transition-all duration-150 hover:bg-immich-primary hover:shadow-lg text-sm font-medium; @apply bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray text-gray-100 border dark:border-immich-dark-gray rounded-xl py-2 px-4 transition-all duration-150 hover:bg-immich-primary dark:hover:bg-immich-dark-primary/90 hover:shadow-lg text-sm font-medium;
} }
.immich-text-button { .immich-text-button {

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" class="dark">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
@ -7,7 +7,7 @@
%sveltekit.head% %sveltekit.head%
</head> </head>
<body> <body class="bg-immich-bg dark:bg-immich-dark-bg">
<div>%sveltekit.body%</div> <div>%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -11,17 +11,17 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
</script> </script>
<div class="flex border-b pb-5"> <div class="flex border-b pb-5 dark:border-b-immich-dark-gray">
<div class="w-[70%]"> <div class="w-[70%]">
<h1 class="text-immich-primary text-sm">{title.toUpperCase()}</h1> <h1 class="text-immich-primary dark:text-immich-dark-primary text-sm">{title.toUpperCase()}</h1>
<p class="text-sm mt-1">{subtitle}</p> <p class="text-sm mt-1 dark:text-immich-dark-fg">{subtitle}</p>
<p class="text-sm"> <p class="text-sm dark:text-immich-dark-fg">
<slot /> <slot />
</p> </p>
<table class="text-left w-full mt-5"> <table class="text-left w-full mt-5">
<!-- table header --> <!-- table header -->
<thead <thead
class="border rounded-md mb-2 bg-immich-primary/10 flex text-immich-primary w-full h-12" class="border rounded-md mb-2 dark:bg-immich-dark-gray dark:border-immich-dark-gray bg-immich-primary/10 flex text-immich-primary dark:text-immich-dark-primary w-full h-12"
> >
<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">Status</th> <th class="text-center w-1/3 font-medium text-sm">Status</th>
@ -29,8 +29,10 @@
<th class="text-center w-1/3 font-medium text-sm">Waiting</th> <th class="text-center w-1/3 font-medium text-sm">Waiting</th>
</tr> </tr>
</thead> </thead>
<tbody class="overflow-y-auto rounded-md w-full max-h-[320px] block border bg-white"> <tbody
<tr class="text-center flex place-items-center w-full h-[40px]"> class="overflow-y-auto rounded-md w-full max-h-[320px] block border bg-white dark:border-immich-dark-gray dark:bg-[#e5e5e5] dark:text-immich-dark-bg"
>
<tr class="text-center flex place-items-center w-full h-[60px]">
<td class="text-sm px-2 w-1/3 text-ellipsis">{jobStatus ? 'Active' : 'Idle'}</td> <td class="text-sm px-2 w-1/3 text-ellipsis">{jobStatus ? 'Active' : 'Idle'}</td>
<td class="text-sm px-2 w-1/3 text-ellipsis">{activeJobCount}</td> <td class="text-sm px-2 w-1/3 text-ellipsis">{activeJobCount}</td>
<td class="text-sm px-2 w-1/3 text-ellipsis">{waitingJobCount}</td> <td class="text-sm px-2 w-1/3 text-ellipsis">{waitingJobCount}</td>
@ -41,7 +43,7 @@
<div class="w-[30%] flex place-items-center place-content-end"> <div class="w-[30%] flex place-items-center place-content-end">
<button <button
on:click={() => dispatch('click')} on:click={() => dispatch('click')}
class="px-6 py-3 text-sm bg-immich-primary font-medium rounded-2xl hover:bg-immich-primary/50 transition-all hover:cursor-pointer disabled:cursor-not-allowed shadow-sm text-immich-bg" class="px-6 py-3 text-sm bg-immich-primary dark:bg-immich-dark-primary font-medium rounded-2xl hover:bg-immich-primary/50 transition-all hover:cursor-pointer disabled:cursor-not-allowed shadow-sm text-immich-bg dark:text-immich-dark-gray"
disabled={jobStatus} disabled={jobStatus}
> >
{#if jobStatus} {#if jobStatus}

View File

@ -22,7 +22,7 @@
<div class="flex flex-col gap-5"> <div class="flex flex-col gap-5">
<div> <div>
<p class="text-sm">TOTAL USAGE</p> <p class="text-sm dark:text-immich-dark-fg">TOTAL USAGE</p>
<div class="flex mt-5 justify-between"> <div class="flex mt-5 justify-between">
<StatsCard logo={CameraIris} title={'PHOTOS'} value={stats.photos.toString()} /> <StatsCard logo={CameraIris} title={'PHOTOS'} value={stats.photos.toString()} />
@ -33,9 +33,11 @@
</div> </div>
<div> <div>
<p class="text-sm">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="text-left w-full mt-5">
<thead class="border rounded-md mb-4 bg-gray-50 flex text-immich-primary w-full h-12"> <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"
>
<tr class="flex w-full place-items-center"> <tr class="flex w-full place-items-center">
<th class="text-center w-1/5 font-medium text-sm">User</th> <th class="text-center w-1/5 font-medium text-sm">User</th>
<th class="text-center w-1/5 font-medium text-sm">Photos</th> <th class="text-center w-1/5 font-medium text-sm">Photos</th>
@ -44,11 +46,13 @@
<th class="text-center w-1/5 font-medium text-sm">Size</th> <th class="text-center w-1/5 font-medium text-sm">Size</th>
</tr> </tr>
</thead> </thead>
<tbody class="overflow-y-auto rounded-md w-full max-h-[320px] block border"> <tbody
class="overflow-y-auto rounded-md w-full max-h-[320px] block border dark:border-immich-dark-gray dark:text-immich-dark-bg"
>
{#each stats.usageByUser as user, i} {#each stats.usageByUser as user, i}
<tr <tr
class={`text-center flex place-items-center w-full h-[50px] ${ class={`text-center flex place-items-center w-full h-[50px] ${
i % 2 == 0 ? 'bg-immich-gray' : 'bg-immich-bg' i % 2 == 0 ? 'bg-immich-gray dark:bg-[#e5e5e5]' : 'bg-immich-bg dark:bg-[#eeeeee]'
}`} }`}
> >
<td class="text-sm px-2 w-1/5 text-ellipsis">{getFullName(user.userId)}</td> <td class="text-sm px-2 w-1/5 text-ellipsis">{getFullName(user.userId)}</td>

View File

@ -17,15 +17,17 @@
}; };
</script> </script>
<div class="w-[180px] h-[140px] bg-immich-gray rounded-3xl p-5 flex flex-col justify-between"> <div
<div class="flex place-items-center gap-4"> class="w-[180px] h-[140px] bg-immich-gray dark:bg-immich-dark-gray rounded-3xl p-5 flex flex-col justify-between"
<svelte:component this={logo} size="40" color={'#4250af'} /> >
<p class="text-immich-primary">{title}</p> <div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<svelte:component this={logo} size="40" />
<p>{title}</p>
</div> </div>
<div class="relative text-center font-mono font-semibold text-2xl"> <div class="relative text-center font-mono font-semibold text-2xl">
<span class="text-[#DCDADA]">{zeros()}</span><span class="text-immich-primary" <span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span
>{parseInt(value)}</span class="text-immich-primary dark:text-immich-dark-primary">{parseInt(value)}</span
> >
{#if unit} {#if unit}
<span class="absolute -top-5 right-2 text-base font-light text-gray-400">{unit}</span> <span class="absolute -top-5 right-2 text-base font-light text-gray-400">{unit}</span>

View File

@ -9,7 +9,9 @@
</script> </script>
<table class="text-left w-full my-5"> <table class="text-left w-full my-5">
<thead class="border rounded-md mb-4 bg-gray-50 flex text-immich-primary w-full h-12 "> <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"
>
<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">Email</th> <th class="text-center w-1/4 font-medium text-sm">Email</th>
<th class="text-center w-1/4 font-medium text-sm">First name</th> <th class="text-center w-1/4 font-medium text-sm">First name</th>
@ -17,11 +19,13 @@
<th class="text-center w-1/4 font-medium text-sm">Edit</th> <th class="text-center w-1/4 font-medium text-sm">Edit</th>
</tr> </tr>
</thead> </thead>
<tbody class="overflow-y-auto rounded-md w-full max-h-[320px] block border"> <tbody
class="overflow-y-auto rounded-md w-full max-h-[320px] block border dark:border-immich-dark-gray"
>
{#each allUsers as user, i} {#each allUsers as user, i}
<tr <tr
class={`text-center flex place-items-center w-full h-[80px] ${ class={`text-center flex place-items-center w-full h-[80px] dark:text-immich-dark-bg ${
i % 2 == 0 ? 'bg-gray-100' : 'bg-immich-bg' i % 2 == 0 ? 'bg-immich-gray dark:bg-[#e5e5e5]' : 'bg-immich-bg dark:bg-[#eeeeee]'
}`} }`}
> >
<td class="text-sm px-4 w-1/4 text-ellipsis">{user.email}</td> <td class="text-sm px-4 w-1/4 text-ellipsis">{user.email}</td>
@ -32,7 +36,7 @@
on:click={() => { on:click={() => {
dispatch('edit-user', { user }); dispatch('edit-user', { user });
}} }}
class="bg-immich-primary text-gray-100 rounded-full p-3 transition-all duration-150 hover:bg-immich-primary/75" 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"
><PencilOutline size="20" /></button ><PencilOutline size="20" /></button
></td ></td
> >

View File

@ -60,12 +60,7 @@
on:click|stopPropagation|preventDefault={showAlbumContextMenu} on:click|stopPropagation|preventDefault={showAlbumContextMenu}
data-testid="context-button-parent" data-testid="context-button-parent"
> >
<CircleIconButton <CircleIconButton logo={DotsVertical} size={'20'} hoverColor={'rgba(95,99,104, 0.5)'} />
logo={DotsVertical}
size={'20'}
hoverColor={'rgba(95,99,104, 0.5)'}
logoColor={'#fdf8ec'}
/>
</div> </div>
<div class={`h-[275px] w-[275px] z-[-1]`}> <div class={`h-[275px] w-[275px] z-[-1]`}>
@ -78,11 +73,14 @@
</div> </div>
<div class="mt-4"> <div class="mt-4">
<p class="text-sm font-medium text-gray-800" data-testid="album-name"> <p
class="text-sm font-medium text-gray-800 dark:text-immich-dark-primary"
data-testid="album-name"
>
{album.albumName} {album.albumName}
</p> </p>
<span class="text-xs flex gap-2" data-testid="album-details"> <span class="text-xs flex gap-2 dark:text-immich-dark-fg" data-testid="album-details">
<p>{album.assetCount} items</p> <p>{album.assetCount} items</p>
{#if album.shared} {#if album.shared}

View File

@ -331,7 +331,7 @@
}; };
</script> </script>
<section class="bg-immich-bg"> <section class="bg-immich-bg dark:bg-immich-dark-bg">
<!-- Multiselection mode app bar --> <!-- Multiselection mode app bar -->
{#if isMultiSelectionMode} {#if isMultiSelectionMode}
<ControlAppBar <ControlAppBar
@ -340,7 +340,9 @@
tailwindClasses={'bg-white shadow-md'} tailwindClasses={'bg-white shadow-md'}
> >
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
<p class="font-medium text-immich-primary">Selected {multiSelectAsset.size}</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">
Selected {multiSelectAsset.size}
</p>
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="trailing"> <svelte:fragment slot="trailing">
{#if isOwned} {#if isOwned}
@ -386,7 +388,7 @@
<button <button
disabled={album.assetCount == 0} disabled={album.assetCount == 0}
on:click={() => (isShowShareUserSelection = true)} on:click={() => (isShowShareUserSelection = true)}
class="immich-text-button border bg-immich-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed" class="immich-text-button border bg-immich-primary dark:bg-immich-dark-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed dark:text-immich-dark-bg dark:border-immich-dark-gray"
><span class="px-2">Share</span></button ><span class="px-2">Share</span></button
> >
{/if} {/if}
@ -404,9 +406,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 w-[99%] border-b-2 border-transparent outline-none ${ class={`transition-all text-6xl text-immich-primary dark:text-immich-dark-primary w-[99%] border-b-2 border-transparent outline-none ${
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 bg-immich-bg`} } 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`}
type="text" type="text"
bind:value={album.albumName} bind:value={album.albumName}
disabled={!isOwned} disabled={!isOwned}
@ -468,13 +470,15 @@
<!-- Album is empty - Show asset selectection buttons --> <!-- Album is empty - Show asset selectection buttons -->
<section id="empty-album" class=" mt-[200px] flex place-content-center place-items-center"> <section id="empty-album" class=" mt-[200px] flex place-content-center place-items-center">
<div class="w-[300px]"> <div class="w-[300px]">
<p class="text-xs">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-white rounded-md mt-5 flex place-items-center gap-6 px-8 transition-all hover:bg-gray-100 hover:text-immich-primary" 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"
> >
<span><Plus color="#4250af" size="24" /> </span> <span class="text-text-immich-primary dark:text-immich-dark-primary"
<span class="text-lg text-immich-fg">Select photos</span> ><Plus size="24" />
</span>
<span class="text-lg">Select photos</span>
</button> </button>
</div> </div>
</section> </section>

View File

@ -70,7 +70,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 z-[9999]" class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
> >
<ControlAppBar <ControlAppBar
on:close-button-click={() => { on:close-button-click={() => {
@ -80,28 +80,28 @@
> >
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
{#if $selectedAssets.size == 0} {#if $selectedAssets.size == 0}
<p class="text-lg">Add to album</p> <p class="text-lg dark:text-immich-dark-fg">Add to album</p>
{:else} {:else}
<p class="text-lg">{$selectedAssets.size} selected</p> <p class="text-lg dark:text-immich-dark-fg">{$selectedAssets.size} selected</p>
{/if} {/if}
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="trailing"> <svelte:fragment slot="trailing">
<button <button
on:click={() => openFileUploadDialog(UploadType.ALBUM)} on:click={() => openFileUploadDialog(UploadType.ALBUM)}
class="text-immich-primary text-sm hover:bg-immich-primary/10 transition-all px-6 py-2 rounded-lg font-medium" 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"
> >
Select from computer Select from computer
</button> </button>
<button <button
disabled={$selectedAssets.size === 0} disabled={$selectedAssets.size === 0}
on:click={addSelectedAssets} on:click={addSelectedAssets}
class="immich-text-button border bg-immich-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed" class="immich-text-button border bg-immich-primary dark:bg-immich-dark-primary text-gray-50 hover:bg-immich-primary/75 px-6 text-sm disabled:opacity-25 disabled:bg-gray-500 disabled:cursor-not-allowed dark:text-immich-dark-bg dark:border-immich-dark-gray"
><span class="px-2">Done</span></button ><span class="px-2">Done</span></button
> >
</svelte:fragment> </svelte:fragment>
</ControlAppBar> </ControlAppBar>
<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg"> <section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg">
<AssetGrid isAlbumSelectionMode={true} /> <AssetGrid isAlbumSelectionMode={true} />
</section> </section>
</section> </section>

View File

@ -68,14 +68,14 @@
<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 gap-2 place-items-center">
<p class="font-medium text-immich-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="max-h-[400px] overflow-y-auto immich-scrollbar 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" class="flex gap-4 p-5 place-items-center justify-between w-full transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
> >
<div class="flex gap-4 place-items-center"> <div class="flex gap-4 place-items-center">
<CircleAvatar {user} /> <CircleAvatar {user} />
@ -88,14 +88,13 @@
on:click={() => showContextMenu(user.id)} on:click={() => showContextMenu(user.id)}
logo={DotsVertical} logo={DotsVertical}
backgroundColor={'transparent'} backgroundColor={'transparent'}
logoColor={'#5f6368'}
hoverColor={'#e2e7e9'} hoverColor={'#e2e7e9'}
size={'20'} size={'20'}
/> />
{:else if user.id == currentUser?.id} {:else if user.id == currentUser?.id}
<button <button
on:click={() => removeUser('me')} on:click={() => removeUser('me')}
class="text-sm text-immich-primary font-medium transition-colors hover:text-immich-primary/75" class="text-sm text-immich-primary dark:text-immich-dark-primary font-medium transition-colors hover:text-immich-primary/75"
>Leave</button >Leave</button
> >
{/if} {/if}

View File

@ -38,7 +38,7 @@
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<span class="flex gap-2 place-items-center"> <span class="flex gap-2 place-items-center">
<img src="/immich-logo.svg" width="24" alt="Immich" /> <img src="/immich-logo.svg" width="24" alt="Immich" />
<p class="font-medium text-immich-fg">Invite to album</p> <p class="font-medium">Invite to album</p>
</span> </span>
</svelte:fragment> </svelte:fragment>
@ -51,7 +51,7 @@
{#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 transition-colors" 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"
> >
<CircleAvatar size={28} {user} /> <CircleAvatar size={28} {user} />
<p class="text-xs font-medium">{user.firstName} {user.lastName}</p> <p class="text-xs font-medium">{user.firstName} {user.lastName}</p>
@ -68,11 +68,11 @@
{#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 transition-all" class="w-full flex place-items-center gap-4 py-4 px-5 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all"
> >
{#if selectedUsers.includes(user)} {#if selectedUsers.includes(user)}
<span <span
class="bg-immich-primary text-white rounded-full w-12 h-12 border flex place-items-center place-content-center text-3xl" 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"
>✓</span >✓</span
> >
{:else} {:else}
@ -80,7 +80,7 @@
{/if} {/if}
<div class="text-left"> <div class="text-left">
<p class="text-immich-fg"> <p class="text-immich-fg dark:text-immich-dark-fg">
{user.firstName} {user.firstName}
{user.lastName} {user.lastName}
</p> </p>

View File

@ -207,7 +207,7 @@
<div <div
transition:fly={{ duration: 150 }} transition:fly={{ duration: 150 }}
id="detail-panel" id="detail-panel"
class="bg-immich-bg w-[360px] row-span-full transition-all overflow-y-auto" class="bg-immich-bg w-[360px] row-span-full transition-all overflow-y-auto dark:bg-immich-dark-bg dark:border-l dark:border-l-immich-dark-gray"
translate="yes" translate="yes"
> >
<DetailPanel {asset} albums={appearsInAlbums} on:close={() => (isShowDetail = false)} /> <DetailPanel {asset} albums={appearsInAlbums} on:close={() => (isShowDetail = false)} />

View File

@ -97,16 +97,16 @@
}; };
</script> </script>
<section class="p-2"> <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" 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"
on:click={() => dispatch('close')} on:click={() => dispatch('close')}
> >
<Close size="24" color="#232323" /> <Close size="24" />
</button> </button>
<p class="text-immich-fg text-lg">Info</p> <p class="text-immich-fg dark:text-immich-dark-fg text-lg">Info</p>
</div> </div>
<div class="px-4 py-4"> <div class="px-4 py-4">
@ -202,10 +202,10 @@
<div class="h-[360px] w-full" id="map" /> <div class="h-[360px] w-full" id="map" />
</div> </div>
<section class="p-2"> <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="text-sm pb-4 ">APPEARS IN</p>
{/if} {/if}
{#each albums as album} {#each albums as album}
<a data-sveltekit-prefetch href={`/albums/${album.id}`}> <a data-sveltekit-prefetch href={`/albums/${album.id}`}>
@ -219,7 +219,7 @@
</div> </div>
<div class="mt-auto mb-auto"> <div class="mt-auto mb-auto">
<p>{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>
{#if album.shared} {#if album.shared}

View File

@ -51,11 +51,17 @@
} }
</script> </script>
<div class="border bg-white p-4 shadow-sm w-[500px] rounded-md py-8"> <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] rounded-3xl py-8 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-items-center place-content-center gap-4 px-4">
<img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" /> <img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" />
<h1 class="text-2xl text-immich-primary font-medium">Admin Registration</h1> <h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
<p class="text-sm border rounded-md p-4 font-mono text-gray-600"> Admin Registration
</h1>
<p
class="text-sm border rounded-md p-4 font-mono text-gray-600 dark:border-immich-dark-bg dark:text-gray-300"
>
Since you are the first user on the system, you will be assigned as the Admin and are Since you are the first user on the system, you will be assigned as the Admin and are
responsible for administrative tasks, and additional users will be created by you. responsible for administrative tasks, and additional users will be created by you.
</p> </p>
@ -117,7 +123,7 @@
<div class="flex w-full"> <div class="flex w-full">
<button <button
type="submit" type="submit"
class="m-4 p-2 bg-immich-primary hover:bg-immich-primary/75 px-6 py-4 text-white rounded-md shadow-md w-full" class="m-4 p-2 bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-4 text-white rounded-md shadow-md w-full"
>Sign Up</button >Sign Up</button
> >
</div> </div>

View File

@ -43,12 +43,18 @@
} }
</script> </script>
<div class="border bg-white p-4 shadow-sm w-[500px] rounded-md py-8"> <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] rounded-3xl py-8 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-items-center place-content-center gap-4 px-4">
<img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" /> <img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" />
<h1 class="text-2xl text-immich-primary font-medium">Change Password</h1> <h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
Change Password
</h1>
<p class="text-sm border rounded-md p-4 font-mono text-gray-600"> <p
class="text-sm border rounded-md p-4 font-mono text-gray-600 dark:border-immich-dark-bg dark:text-gray-300"
>
Hi {user.firstName} Hi {user.firstName}
{user.lastName} ({user.email}), {user.lastName} ({user.email}),
<br /> <br />
@ -93,7 +99,7 @@
<div class="flex w-full"> <div class="flex w-full">
<button <button
type="submit" type="submit"
class="m-4 p-2 bg-immich-primary hover:bg-immich-primary/75 px-6 py-4 text-white rounded-md shadow-md w-full" class="m-4 p-2 bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-4 text-white rounded-md shadow-md w-full"
>Change Password</button >Change Password</button
> >
</div> </div>

View File

@ -53,11 +53,17 @@
} }
</script> </script>
<div class="border bg-white p-4 shadow-sm w-[500px] rounded-3xl py-8"> <div
class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] rounded-3xl py-8 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-items-center place-content-center gap-4 px-4">
<img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" /> <img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" />
<h1 class="text-2xl text-immich-primary font-medium">Create new user</h1> <h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
<p class="text-sm border rounded-md p-4 font-mono text-gray-600"> 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"
>
Please provide your user with the password, they will have to change it on their first sign Please provide your user with the password, they will have to change it on their first sign
in. in.
</p> </p>
@ -113,7 +119,7 @@
<div class="flex w-full"> <div class="flex w-full">
<button <button
type="submit" type="submit"
class="m-4 bg-immich-primary hover:bg-immich-primary/75 px-6 py-3 text-white rounded-full shadow-md w-full font-medium" class="m-4 bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-6 py-3 text-white dark:text-immich-dark-gray rounded-full shadow-md w-full font-medium"
>Create >Create
</button> </button>
</div> </div>

View File

@ -65,11 +65,16 @@
}; };
</script> </script>
<div class="border bg-white p-4 shadow-sm w-[500px] rounded-3xl py-8"> <div
<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] rounded-3xl py-8 dark:text-immich-dark-fg"
<!-- <img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo"/>--> >
<AccountEditOutline size="4em" color="#4250affe" /> <div
<h1 class="text-2xl text-immich-primary font-medium">Edit user</h1> class="flex flex-col place-items-center place-content-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
>
<AccountEditOutline size="4em" />
<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">
Edit user
</h1>
</div> </div>
<form on:submit|preventDefault={editUser} autocomplete="off"> <form on:submit|preventDefault={editUser} autocomplete="off">
@ -124,7 +129,7 @@
</button> </button>
<button <button
type="submit" type="submit"
class="flex-1 transition-colors bg-immich-primary hover:bg-immich-primary/75 px-6 py-3 text-white rounded-full shadow-md w-full font-medium" class="flex-1 transition-colors bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 dark:text-immich-dark-gray px-6 py-3 text-white rounded-full shadow-md w-full font-medium"
>Confirm >Confirm
</button> </button>
</div> </div>

View File

@ -32,15 +32,17 @@
}; };
</script> </script>
<div class="border bg-white p-4 shadow-sm w-[500px] rounded-md py-8"> <div
class="border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] rounded-md py-8"
>
<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> <div class="flex flex-col place-items-center place-content-center gap-4 px-4">
<img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" /> <img class="text-center" src="/immich-logo.svg" height="100" width="100" alt="immich-logo" />
<h1 class="text-2xl text-immich-primary font-medium">Login</h1> <h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Login</h1>
</div> </div>
{#if loginPageMessage} {#if loginPageMessage}
<p <p
class="text-sm border rounded-md m-4 p-4 text-immich-primary font-medium bg-immich-primary/5" class="text-sm border rounded-md m-4 p-4 text-immich-primary dark:text-immich-dark-primary font-medium bg-immich-primary/5 dark:border-immich-dark-bg"
> >
{@html loginPageMessage} {@html loginPageMessage}
</p> </p>
@ -78,7 +80,7 @@
<div class="flex w-full"> <div class="flex w-full">
<button <button
type="submit" type="submit"
class="m-4 p-2 bg-immich-primary hover:bg-immich-primary/75 px-6 py-4 text-white rounded-md shadow-md w-full font-semibold" class="m-4 p-2 bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray dark:hover:bg-immich-dark-primary/80 hover:bg-immich-primary/75 px-6 py-4 text-white rounded-md shadow-md w-full font-semibold"
>Login</button >Login</button
> >
</div> </div>

View File

@ -115,7 +115,9 @@
on:mouseleave={() => (isMouseOverGroup = false)} on:mouseleave={() => (isMouseOverGroup = false)}
> >
<!-- Date group title --> <!-- Date group title -->
<p class="font-medium text-sm text-immich-fg mb-2 flex place-items-center h-6"> <p
class="font-medium text-sm text-immich-fg dark:text-immich-dark-fg mb-2 flex place-items-center h-6"
>
{#if (hoveredDateGroup == dateGroupTitle && isMouseOverGroup) || $selectedGroup.has(dateGroupTitle)} {#if (hoveredDateGroup == dateGroupTitle && isMouseOverGroup) || $selectedGroup.has(dateGroupTitle)}
<div <div
transition:fly={{ x: -24, duration: 200, opacity: 0.5 }} transition:fly={{ x: -24, duration: 200, opacity: 0.5 }}

View File

@ -36,7 +36,7 @@
<div <div
use:clickOutside use:clickOutside
on:out-click={() => dispatch('close')} on:out-click={() => dispatch('close')}
class="bg-white w-[450px] min-h-[200px] max-h-[500px] rounded-lg shadow-md" class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg w-[450px] min-h-[200px] max-h-[500px] rounded-lg shadow-md"
> >
<div class="flex justify-between place-items-center p-5"> <div class="flex justify-between place-items-center p-5">
<div> <div>

View File

@ -9,7 +9,6 @@
export let logo: any; export let logo: any;
export let backgroundColor = 'transparent'; export let backgroundColor = 'transparent';
export let hoverColor = '#e2e7e9'; export let hoverColor = '#e2e7e9';
export let logoColor = '#5f6368';
export let size = '24'; export let size = '24';
export let title = ''; export let title = '';
let iconButton: HTMLButtonElement; let iconButton: HTMLButtonElement;
@ -26,10 +25,10 @@
<button <button
{title} {title}
bind:this={iconButton} bind:this={iconButton}
class={`immich-circle-icon-button rounded-full p-3 flex place-items-center place-content-center transition-all`} class={`immich-circle-icon-button dark:text-immich-dark-fg hover:dark:text-immich-dark-gray rounded-full p-3 flex place-items-center place-content-center transition-all`}
on:click={(mouseEvent) => dispatch('click', { mouseEvent })} on:click={(mouseEvent) => dispatch('click', { mouseEvent })}
> >
<svelte:component this={logo} {size} color={logoColor} /> <svelte:component this={logo} {size} />
</button> </button>
<style> <style>

View File

@ -32,7 +32,7 @@
<div <div
transition:slide={{ duration: 200, easing: quintOut }} transition:slide={{ duration: 200, easing: quintOut }}
bind:this={menuEl} bind:this={menuEl}
class="absolute bg-white w-[175px] z-[99999] rounded-lg shadow-md" class="absolute w-[175px] z-[99999] rounded-lg shadow-md"
style={`top: ${y}px; left: ${x}px;`} style={`top: ${y}px; left: ${x}px;`}
use:clickOutside use:clickOutside
on:out-click={() => dispatch('clickoutside')} on:out-click={() => dispatch('clickoutside')}

View File

@ -16,7 +16,7 @@
<button <button
class:disabled={isDisabled} class:disabled={isDisabled}
on:click={handleClick} on:click={handleClick}
class="bg-white hover:bg-immich-bg transition-all p-4 w-full text-left rounded-lg text-sm" class="bg-white hover:bg-gray-300 dark:text-immich-dark-bg transition-all p-4 w-full text-left rounded-lg text-sm"
> >
{#if text} {#if text}
{text} {text}

View File

@ -14,7 +14,7 @@
const onScroll = () => { const onScroll = () => {
if (window.pageYOffset > 80) { if (window.pageYOffset > 80) {
appBarBorder = 'border border-gray-200 bg-gray-50'; appBarBorder = 'border border-gray-200 bg-gray-50 dark:border-gray-600';
} else { } else {
appBarBorder = 'bg-immich-bg border border-transparent'; appBarBorder = 'bg-immich-bg border border-transparent';
} }
@ -39,14 +39,13 @@
> >
<div <div
id="asset-selection-app-bar" id="asset-selection-app-bar"
class={`flex justify-between ${appBarBorder} rounded-lg p-2 mx-2 mt-2 transition-all place-items-center ${tailwindClasses}`} class={`flex justify-between ${appBarBorder} rounded-lg p-2 mx-2 mt-2 transition-all place-items-center ${tailwindClasses} dark:bg-immich-dark-gray`}
> >
<div class="flex place-items-center gap-6"> <div class="flex place-items-center gap-6 dark:text-immich-dark-fg">
<CircleIconButton <CircleIconButton
on:click={() => dispatch('close-button-click')} on:click={() => dispatch('close-button-click')}
logo={backIcon} logo={backIcon}
backgroundColor={'transparent'} backgroundColor={'transparent'}
logoColor={'rgb(75 85 99)'}
hoverColor={'#e2e7e9'} hoverColor={'#e2e7e9'}
size={'24'} size={'24'}
/> />
@ -54,7 +53,7 @@
<slot name="leading" /> <slot name="leading" />
</div> </div>
<div class="flex place-items-center gap-1 mr-4"> <div class="flex place-items-center gap-1 mr-4 ">
<slot name="trailing" /> <slot name="trailing" />
</div> </div>
</div> </div>

View File

@ -136,7 +136,7 @@
<div <div
style:width={`${thumbnailSize}px`} style:width={`${thumbnailSize}px`}
style:height={`${thumbnailSize}px`} style:height={`${thumbnailSize}px`}
class={`bg-gray-100 relative select-none ${getSize()} ${ class={`bg-gray-100 dark:bg-immich-dark-gray relative select-none ${getSize()} ${
disabled ? 'cursor-not-allowed' : 'hover:cursor-pointer' disabled ? 'cursor-not-allowed' : 'hover:cursor-pointer'
}`} }`}
on:mouseenter={handleMouseOverThumbnail} on:mouseenter={handleMouseOverThumbnail}

View File

@ -6,6 +6,7 @@
import TrayArrowUp from 'svelte-material-icons/TrayArrowUp.svelte'; import TrayArrowUp from 'svelte-material-icons/TrayArrowUp.svelte';
import { clickOutside } from '../../utils/click-outside'; import { clickOutside } from '../../utils/click-outside';
import { api, UserResponseDto } from '@api'; import { api, UserResponseDto } from '@api';
import ThemeButton from './theme-button.svelte';
export let user: UserResponseDto; export let user: UserResponseDto;
export let shouldShowUploadButton = true; export let shouldShowUploadButton = true;
@ -42,28 +43,35 @@
}; };
</script> </script>
<section id="dashboard-navbar" class="fixed w-screen z-[100] bg-immich-bg text-sm"> <section
<div class="flex border-b place-items-center px-6 py-2 "> id="dashboard-navbar"
class="fixed w-screen z-[100] bg-immich-bg dark:bg-immich-dark-bg text-sm"
>
<div class="flex border-b dark:border-b-immich-dark-gray place-items-center px-6 py-2 ">
<a <a
data-sveltekit-prefetch data-sveltekit-prefetch
class="flex gap-2 place-items-center hover:cursor-pointer" class="flex gap-2 place-items-center hover:cursor-pointer"
href="/photos" href="/photos"
> >
<img src="/immich-logo.svg" alt="immich logo" height="35" width="35" /> <img src="/immich-logo.svg" alt="immich logo" height="35" width="35" />
<h1 class="font-immich-title text-2xl text-immich-primary">IMMICH</h1> <h1 class="font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary">
IMMICH
</h1>
</a> </a>
<div class="flex-1 ml-24"> <div class="flex-1 ml-24">
<input <input
class="w-[50%] border rounded-md bg-gray-200 px-8 py-4" class="w-[50%] rounded-md bg-gray-200 dark:bg-immich-dark-gray px-8 py-4"
placeholder="Search - Coming soon" placeholder="Search - Coming soon"
/> />
</div> </div>
<section class="flex gap-4 place-items-center"> <section class="flex gap-4 place-items-center">
<ThemeButton />
{#if $page.url.pathname !== '/admin' && shouldShowUploadButton} {#if $page.url.pathname !== '/admin' && shouldShowUploadButton}
<button <button
in:fly={{ x: 50, duration: 250 }} in:fly={{ x: 50, duration: 250 }}
on:click={() => dispatch('uploadClicked')} on:click={() => dispatch('uploadClicked')}
class="immich-text-button" class="immich-text-button dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
> >
<TrayArrowUp size="20" /> <TrayArrowUp size="20" />
<span> Upload </span> <span> Upload </span>
@ -73,8 +81,9 @@
{#if user.isAdmin} {#if user.isAdmin}
<a data-sveltekit-prefetch href={`admin`}> <a data-sveltekit-prefetch href={`admin`}>
<button <button
class={`flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 p-2 rounded-lg font-medium ${ class={`flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg p-2 rounded-lg font-medium ${
$page.url.pathname == '/admin' && 'text-immich-primary underline' $page.url.pathname == '/admin' &&
'text-immich-primary dark:immich-dark-primary underline'
}`}>Administration</button }`}>Administration</button
> >
</a> </a>
@ -87,7 +96,7 @@
on:click={showAccountInfoPanel} on:click={showAccountInfoPanel}
> >
<button <button
class="flex place-items-center place-content-center rounded-full bg-immich-primary/80 h-12 w-12 text-gray-100 hover:bg-immich-primary" class="flex place-items-center place-content-center rounded-full bg-immich-primary hover:bg-immich-primary/80 h-12 w-12 text-gray-100 dark:text-immich-dark-bg dark:bg-immich-dark-primary"
> >
{#if shouldShowProfileImage} {#if shouldShowProfileImage}
<img <img
@ -104,7 +113,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 text-[12px] text-gray-100 p-2 rounded-md shadow-md" 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"
> >
<p>{user.firstName} {user.lastName}</p> <p>{user.firstName} {user.lastName}</p>
<p>{user.email}</p> <p>{user.email}</p>
@ -119,13 +128,13 @@
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-white shadow-lg rounded-2xl w-[360px] text-center z-[100]" class="absolute right-[25px] top-[75px] bg-immich-bg dark:bg-immich-dark-gray dark:border dark:border-immich-dark-gray shadow-lg rounded-2xl w-[360px] text-center z-[100]"
use:clickOutside use:clickOutside
on:out-click={() => (shouldShowAccountInfoPanel = false)} on:out-click={() => (shouldShowAccountInfoPanel = false)}
> >
<div class="flex place-items-center place-content-center mt-6"> <div class="flex place-items-center place-content-center mt-6">
<button <button
class="flex place-items-center place-content-center rounded-full bg-immich-primary/80 h-20 w-20 text-gray-100 hover:bg-immich-primary" class="flex place-items-center place-content-center rounded-full bg-immich-primary dark:bg-immich-dark-primary dark:immich-dark-primary/80 h-20 w-20 text-gray-100 hover:bg-immich-primary dark:text-immich-dark-bg"
> >
{#if shouldShowProfileImage} {#if shouldShowProfileImage}
<img <img
@ -141,20 +150,21 @@
</button> </button>
</div> </div>
<p class="text-lg text-immich-primary font-medium mt-4"> <p class="text-lg text-immich-primary dark:text-immich-dark-primary font-medium mt-4">
{user.firstName} {user.firstName}
{user.lastName} {user.lastName}
</p> </p>
<p class="text-sm text-gray-500">{user.email}</p> <p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p>
<div class="my-4"> <div class="my-4">
<hr /> <hr class="dark:border-immich-dark-bg" />
</div> </div>
<div class="mb-6"> <div class="mb-6">
<button class="border rounded-3xl px-6 py-2 hover:bg-gray-50" on:click={logOut} <button
>Sign Out</button class="border rounded-3xl px-6 py-2 hover:bg-gray-50 dark:border-immich-dark-gray dark:bg-gray-300 dark:hover:bg-immich-dark-primary"
on:click={logOut}>Sign Out</button
> >
</div> </div>
</div> </div>

View File

@ -109,7 +109,7 @@
> >
{#if isHover} {#if isHover}
<div <div
class="border-b-2 border-immich-primary w-[100px] right-0 pr-6 py-1 text-sm pl-1 font-medium absolute bg-white z-50 pointer-events-none rounded-tl-md shadow-lg" 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-50 pointer-events-none rounded-tl-md shadow-lg 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" class="absolute right-0 w-10 h-[2px] 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" class="absolute right-0 pr-5 z-10 text-xs font-medium dark:text-immich-dark-fg"
> >
{groupDate.getFullYear()} {groupDate.getFullYear()}
</div> </div>

View File

@ -23,10 +23,13 @@
<div <div
on:click={onButtonClicked} on:click={onButtonClicked}
class={`flex gap-4 place-items-center pl-5 py-3 rounded-tr-full rounded-br-full hover:bg-gray-200 hover:text-immich-primary hover:cursor-pointer class={`flex gap-4 place-items-center pl-5 py-3 rounded-tr-full rounded-br-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
${isSelected && 'bg-immich-primary/10 text-immich-primary hover:bg-immich-primary/25'} ${
isSelected &&
'bg-immich-primary/10 dark:bg-immich-dark-primary/10 text-immich-primary dark:text-[#adcbfa] hover:bg-immich-primary/25'
}
`} `}
> >
<svelte:component this={logo} size="24" /> <svelte:component this={logo} size="24" />
<p class="font-medium text-sm">{title}</p> <p class="font-medium text-sm ">{title}</p>
</div> </div>

View File

@ -52,8 +52,7 @@
}; };
</script> </script>
<section id="sidebar" class="flex flex-col gap-1 pt-8 pr-6"> <section id="sidebar" class="flex flex-col gap-1 pt-8 pr-6 bg-immich-bg dark:bg-immich-dark-bg">
<!-- {domCount} -->
<a <a
data-sveltekit-prefetch data-sveltekit-prefetch
data-sveltekit-noscroll data-sveltekit-noscroll
@ -127,7 +126,7 @@
{/if} {/if}
</div> </div>
</a> </a>
<div class="text-xs ml-5 my-4"> <div class="text-xs ml-5 my-4 dark:text-immich-dark-fg">
<p>LIBRARY</p> <p>LIBRARY</p>
</div> </div>
<a data-sveltekit-prefetch href={$page.routeId !== 'albums' ? `/albums` : null} class="relative"> <a data-sveltekit-prefetch href={$page.routeId !== 'albums' ? `/albums` : null} class="relative">

View File

@ -46,18 +46,18 @@
}; };
</script> </script>
<div> <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"> <div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary">
<Cloud size={'24'} /> <Cloud size={'24'} />
</div> </div>
<div> <div>
<p class="text-sm font-medium text-immich-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="w-full bg-gray-200 rounded-full h-[7px] dark:bg-gray-700 my-2">
<!-- style={`width: ${$downloadAssets[fileName]}%`} --> <!-- style={`width: ${$downloadAssets[fileName]}%`} -->
<div <div
class="bg-immich-primary h-[7px] rounded-full" class="bg-immich-primary dark:bg-immich-dark-primary h-[7px] rounded-full"
style={`width: ${getStorageUsagePercentage()}%`} style={`width: ${getStorageUsagePercentage()}%`}
/> />
</div> </div>
@ -70,29 +70,29 @@
</div> </div>
</div> </div>
<div> <div>
<hr class="ml-5 my-4" /> <hr class="ml-5 my-4 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"> <div class="pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary">
<Dns size={'24'} /> <Dns size={'24'} />
</div> </div>
<div class="text-xs"> <div class="text-xs ">
<p class="text-sm font-medium text-immich-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="flex justify-items-center justify-between mt-2 ">
<p>Status</p> <p>Status</p>
{#if isServerOk} {#if isServerOk}
<p class="font-medium text-immich-primary">Online</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">Online</p>
{:else} {:else}
<p class="font-medium text-red-500">Offline</p> <p class="font-medium text-red-500">Offline</p>
{/if} {/if}
</div> </div>
<div class="flex justify-items-center justify-between mt-2"> <div class="flex justify-items-center justify-between mt-2 ">
<p>Version</p> <p>Version</p>
<p class="font-medium text-immich-primary">{serverVersion}</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">{serverVersion}</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,77 @@
<script lang="ts">
import { onMount } from 'svelte';
let toggleButton: HTMLElement;
onMount(() => {
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
// Change the icons inside the button based on previous settings
if (
localStorage.getItem('color-theme') === 'dark' ||
(!('color-theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
themeToggleLightIcon?.classList.remove('hidden');
} else {
themeToggleDarkIcon?.classList.remove('hidden');
}
});
const toggleTheme = () => {
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
// toggle icons inside button
themeToggleDarkIcon?.classList.toggle('hidden');
themeToggleLightIcon?.classList.toggle('hidden');
// if set via local storage previously
if (localStorage.getItem('color-theme')) {
if (localStorage.getItem('color-theme') === 'light') {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
}
} else {
if (document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
} else {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
}
}
};
</script>
<button
bind:this={toggleButton}
on:click={toggleTheme}
id="theme-toggle"
type="button"
class="text-gray-500 dark:text-immich-dark-primary hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none rounded-lg text-sm p-2.5"
>
<svg
id="theme-toggle-dark-icon"
class="hidden w-6 h-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
>
<svg
id="theme-toggle-light-icon"
class="hidden w-6 h-6"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
><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"
fill-rule="evenodd"
clip-rule="evenodd"
/></svg
>
</button>

View File

@ -26,7 +26,7 @@
</script> </script>
<div <div
class="flex min-w-[550px] border-b border-gray-300 place-items-center py-4 gap-6 transition-all hover:border-immich-primary" class="flex min-w-[550px] border-b border-gray-300 dark:border-immich-dark-gray place-items-center py-4 gap-6 transition-all hover:border-immich-primary dark:hover:border-immich-dark-primary"
> >
<div> <div>
{#await loadImageData(album.albumThumbnailAssetId)} {#await loadImageData(album.albumThumbnailAssetId)}
@ -46,13 +46,16 @@
</div> </div>
<div> <div>
<p class="font-medium text-gray-800">{album.albumName}</p> <p class="font-medium text-gray-800 dark:text-immich-dark-primary">{album.albumName}</p>
{#await getAlbumOwnerInfo() then albumOwner} {#await getAlbumOwnerInfo() then albumOwner}
{#if user.email == albumOwner.email} {#if user.email == albumOwner.email}
<p class="text-xs text-gray-600">Owned</p> <p class="text-xs text-gray-600 dark:text-immich-dark-fg">Owned</p>
{:else} {:else}
<p class="text-xs text-gray-600">Shared by {albumOwner.firstName} {albumOwner.lastName}</p> <p class="text-xs text-gray-600 dark:text-immich-dark-fg">
Shared by {albumOwner.firstName}
{albumOwner.lastName}
</p>
{/if} {/if}
{/await} {/await}
</div> </div>

View File

@ -15,8 +15,10 @@
let localVersion: string; let localVersion: string;
let remoteVersion: string; let remoteVersion: string;
let showNavigationLoadingBar = false; let showNavigationLoadingBar = false;
let canShow = false;
onMount(async () => { onMount(async () => {
checkUserTheme();
const res = await checkAppVersion(); const res = await checkAppVersion();
shouldShowAnnouncement = res.shouldShowAnnouncement; shouldShowAnnouncement = res.shouldShowAnnouncement;
@ -24,6 +26,21 @@
remoteVersion = res.remoteVersion ?? 'unknown'; remoteVersion = res.remoteVersion ?? 'unknown';
}); });
const checkUserTheme = () => {
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (
localStorage.getItem('color-theme') === 'dark' ||
(!('color-theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
canShow = true;
};
beforeNavigate(() => { beforeNavigate(() => {
showNavigationLoadingBar = true; showNavigationLoadingBar = true;
}); });
@ -34,24 +51,24 @@
</script> </script>
<main> <main>
<!-- {#key $page.url} --> {#if canShow}
<div in:fade={{ duration: 100 }}> <div in:fade={{ duration: 100 }}>
{#if showNavigationLoadingBar} {#if showNavigationLoadingBar}
<NavigationLoadingBar /> <NavigationLoadingBar />
{/if} {/if}
<slot /> <slot />
<DownloadPanel /> <DownloadPanel />
<UploadPanel /> <UploadPanel />
<NotificationList /> <NotificationList />
{#if shouldShowAnnouncement} {#if shouldShowAnnouncement}
<AnnouncementBox <AnnouncementBox
{localVersion} {localVersion}
{remoteVersion} {remoteVersion}
on:close={() => (shouldShowAnnouncement = false)} on:close={() => (shouldShowAnnouncement = false)}
/> />
{/if} {/if}
</div> </div>
<!-- {/key} --> {/if}
</main> </main>

View File

@ -19,9 +19,13 @@
<div class="flex place-items-center place-content-center "> <div class="flex place-items-center place-content-center ">
<img class="text-center" src="immich-logo.svg" height="200" width="200" alt="immich-logo" /> <img class="text-center" src="immich-logo.svg" height="200" width="200" alt="immich-logo" />
</div> </div>
<h1 class="text-4xl text-immich-primary font-bold font-immich-title">Welcome to IMMICH Web</h1> <h1
class="text-4xl text-immich-primary dark:text-immich-dark-primary font-bold font-immich-title"
>
Welcome to IMMICH Web
</h1>
<button <button
class="border px-4 py-2 rounded-md bg-immich-primary hover:bg-immich-primary/75 text-white font-bold w-[200px]" class="border px-4 py-4 rounded-md bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray dark:border-immich-dark-gray hover:bg-immich-primary/75 text-white font-bold w-[200px]"
on:click={onGettingStartedClicked} on:click={onGettingStartedClicked}
>Getting Started >Getting Started
</button> </button>

View File

@ -33,7 +33,7 @@
}; };
onMount(() => { onMount(() => {
selectedAction = AdminSideBarSelection.JOBS; selectedAction = AdminSideBarSelection.USER_MANAGEMENT;
getServerStats(); getServerStats();
}); });
@ -147,8 +147,10 @@
</section> </section>
<section class="overflow-y-auto relative"> <section class="overflow-y-auto relative">
<div id="setting-title" class="pt-10 fixed w-full z-50"> <div id="setting-title" class="pt-10 fixed w-full z-50">
<h1 class="text-lg ml-8 mb-4 text-immich-primary font-medium">{selectedAction}</h1> <h1 class="text-lg ml-8 mb-4 text-immich-primary dark:text-immich-dark-primary font-medium">
<hr /> {selectedAction}
</h1>
<hr class="dark:border-immich-dark-gray" />
</div> </div>
<section id="setting-content" class="relative pt-[85px] flex place-content-center"> <section id="setting-content" class="relative pt-[85px] flex place-content-center">

View File

@ -42,20 +42,28 @@
<NavigationBar user={data.user} shouldShowUploadButton={false} /> <NavigationBar user={data.user} shouldShowUploadButton={false} />
</section> </section>
<section class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg "> <section
class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg dark:bg-immich-dark-bg"
>
<SideBar /> <SideBar />
<!-- Main Section --> <!-- Main Section -->
<section class="overflow-y-auto relative immich-scrollbar"> <section class="overflow-y-auto relative immich-scrollbar">
<section id="album-content" class="relative pt-8 pl-4 mb-12 bg-immich-bg"> <section
<div class="px-4 flex justify-between place-items-center"> id="album-content"
class="relative pt-8 pl-4 mb-12 bg-immich-bg dark:bg-immich-dark-bg"
>
<div class="px-4 flex justify-between place-items-center dark:text-immich-dark-fg">
<div> <div>
<p class="font-medium">Albums</p> <p class="font-medium">Albums</p>
</div> </div>
<div> <div>
<button on:click={handleCreateAlbum} class="immich-text-button text-sm"> <button
on:click={handleCreateAlbum}
class="immich-text-button text-sm dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
>
<span> <span>
<PlusBoxOutline size="18" /> <PlusBoxOutline size="18" />
</span> </span>
@ -65,7 +73,7 @@
</div> </div>
<div class="my-4"> <div class="my-4">
<hr /> <hr class="dark:border-immich-dark-gray" />
</div> </div>
<!-- Album Card --> <!-- Album Card -->
@ -85,11 +93,11 @@
<!-- Empty Message --> <!-- Empty Message -->
{#if $albums.length === 0} {#if $albums.length === 0}
<div <div
class="border p-5 w-[50%] m-auto mt-10 bg-gray-50 rounded-3xl flex flex-col place-content-center place-items-center" 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"
> >
<img src="/empty-1.svg" alt="Empty shared album" width="500" /> <img src="/empty-1.svg" alt="Empty shared album" width="500" />
<p class="text-center text-immich-text-gray-500"> <p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg">
Create an album to organize your photos and videos Create an album to organize your photos and videos
</p> </p>
</div> </div>

View File

@ -65,7 +65,9 @@
tailwindClasses={'bg-white shadow-md'} tailwindClasses={'bg-white shadow-md'}
> >
<svelte:fragment slot="leading"> <svelte:fragment slot="leading">
<p class="font-medium text-immich-primary">Selected {$selectedAssets.size}</p> <p class="font-medium text-immich-primary dark:text-immich-dark-primary">
Selected {$selectedAssets.size}
</p>
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="trailing"> <svelte:fragment slot="trailing">
<CircleIconButton <CircleIconButton
@ -83,7 +85,9 @@
{/if} {/if}
</section> </section>
<section class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg"> <section
class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg dark:bg-immich-dark-bg"
>
<SideBar /> <SideBar />
<AssetGrid /> <AssetGrid />
</section> </section>

View File

@ -39,13 +39,18 @@
<NavigationBar user={data.user} shouldShowUploadButton={false} /> <NavigationBar user={data.user} shouldShowUploadButton={false} />
</section> </section>
<section class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg"> <section
class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg dark:bg-immich-dark-bg"
>
<SideBar /> <SideBar />
<section class="overflow-y-auto relative"> <section class="overflow-y-auto relative">
<section id="album-content" class="relative pt-8 pl-4 mb-12 bg-immich-bg"> <section
id="album-content"
class="relative pt-8 pl-4 mb-12 bg-immich-bg dark:bg-immich-dark-bg"
>
<!-- Main Section --> <!-- Main Section -->
<div class="px-4 flex justify-between place-items-center"> <div class="px-4 flex justify-between place-items-center dark:text-immich-dark-fg">
<div> <div>
<p class="font-medium">Sharing</p> <p class="font-medium">Sharing</p>
</div> </div>
@ -53,7 +58,7 @@
<div> <div>
<button <button
on:click={createSharedAlbum} on:click={createSharedAlbum}
class="flex place-items-center gap-1 text-sm hover:bg-immich-primary/5 p-2 rounded-lg font-medium hover:text-gray-700" class="flex place-items-center gap-1 text-sm hover:bg-immich-primary/5 p-2 rounded-lg font-medium hover:text-gray-700 dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg"
> >
<span> <span>
<PlusBoxOutline size="18" /> <PlusBoxOutline size="18" />
@ -64,7 +69,7 @@
</div> </div>
<div class="my-4"> <div class="my-4">
<hr /> <hr class="dark:border-immich-dark-gray" />
</div> </div>
<!-- Share Album List --> <!-- Share Album List -->
@ -79,7 +84,7 @@
<!-- Empty List --> <!-- Empty List -->
{#if data.sharedAlbums.length === 0} {#if data.sharedAlbums.length === 0}
<div <div
class="border p-5 w-[50%] m-auto mt-10 bg-gray-50 rounded-3xl flex flex-col place-content-center place-items-center" 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 dark:text-immich-dark-fg"
> >
<img src="/empty-2.svg" alt="Empty shared album" width="500" /> <img src="/empty-2.svg" alt="Empty shared album" width="500" />
<p class="text-center text-immich-text-gray-500"> <p class="text-center text-immich-text-gray-500">

View File

@ -1,14 +1,20 @@
module.exports = { module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'], content: ['./src/**/*.{html,js,svelte,ts}'],
darkMode: 'class',
theme: { theme: {
extend: { extend: {
colors: { colors: {
// Light Theme
'immich-primary': '#4250af', 'immich-primary': '#4250af',
'immich-bg': 'white', 'immich-bg': 'white',
'immich-fg': 'black', 'immich-fg': 'black',
'immich-gray': '#F6F6F4' 'immich-gray': '#F6F6F4',
// 'immich-bg': '#121212',
// 'immich-fg': '#D0D0D0', // Dark Theme
'immich-dark-primary': '#adcbfa',
'immich-dark-bg': 'black',
'immich-dark-fg': '#e5e7eb',
'immich-dark-gray': '#212121'
}, },
fontFamily: { fontFamily: {
'immich-title': ['Snowburst One', 'cursive'] 'immich-title': ['Snowburst One', 'cursive']