mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	refactor(web): centralize buttons (#2200)
This commit is contained in:
		| @@ -15,7 +15,6 @@ | ||||
|  | ||||
| :root { | ||||
| 	font-family: 'Work Sans', sans-serif; | ||||
| 	/* --immich-icon-button-hover-color: #d3d3d3; */ | ||||
| } | ||||
|  | ||||
| html { | ||||
| @@ -64,22 +63,6 @@ input:focus-visible { | ||||
| 		@apply font-medium text-gray-500 dark:text-gray-300; | ||||
| 	} | ||||
|  | ||||
| 	.immich-btn-primary { | ||||
| 		@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-btn-primary-big { | ||||
| 		@apply inline-flex justify-center items-center bg-immich-primary dark:bg-immich-dark-primary dark:text-immich-dark-gray text-white enabled:dark:hover:bg-immich-dark-primary/80 enabled:hover:bg-immich-primary/75 disabled:cursor-not-allowed px-6 py-4 rounded-3xl shadow-md w-full font-semibold; | ||||
| 	} | ||||
|  | ||||
| 	.immich-btn-secondary-big { | ||||
| 		@apply inline-flex justify-center items-center bg-gray-500 dark:bg-gray-200 text-white enabled:hover:bg-gray-500/75 enabled:dark:hover:bg-gray-200/80 dark:text-immich-dark-gray disabled:cursor-not-allowed px-6 py-4 rounded-3xl shadow-md w-full font-semibold; | ||||
| 	} | ||||
|  | ||||
| 	.immich-text-button { | ||||
| 		@apply flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 p-2 rounded-lg font-medium; | ||||
| 	} | ||||
|  | ||||
| 	/* width */ | ||||
| 	.immich-scrollbar::-webkit-scrollbar { | ||||
| 		width: 8px; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { api, UserResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -31,11 +32,7 @@ | ||||
| 		</p> | ||||
|  | ||||
| 		<div class="flex w-full px-4 gap-4 mt-8"> | ||||
| 			<button | ||||
| 				on:click={deleteUser} | ||||
| 				class="flex-1 transition-colors bg-red-500 hover:bg-red-400 px-6 py-3 text-white rounded-full w-full font-medium" | ||||
| 				>Confirm | ||||
| 			</button> | ||||
| 			<Button fullwidth color="red" on:click={deleteUser}>Confirm</Button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { api, UserResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -30,11 +31,7 @@ | ||||
| 		</p> | ||||
|  | ||||
| 		<div class="flex w-full px-4 gap-4 mt-8"> | ||||
| 			<button | ||||
| 				on:click={restoreUser} | ||||
| 				class="flex-1 transition-colors bg-lime-600 hover:bg-lime-500 px-6 py-3 text-white rounded-full w-full font-medium" | ||||
| 				>Confirm | ||||
| 			</button> | ||||
| 			<Button color="green" fullwidth on:click={restoreUser}>Confirm</Button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| <script lang="ts"> | ||||
| 	import Button from '$lib/components/elements/buttons/button.svelte'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
|  | ||||
| 	const dispatch = createEventDispatcher(); | ||||
| @@ -19,17 +20,7 @@ | ||||
| 	</div> | ||||
|  | ||||
| 	<div class="right"> | ||||
| 		<button | ||||
| 			on:click={() => dispatch('reset')} | ||||
| 			class="text-sm bg-gray-500 dark:bg-gray-200 hover:bg-gray-500/75 dark:hover:bg-gray-200/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 			>Reset | ||||
| 		</button> | ||||
|  | ||||
| 		<button | ||||
| 			type="submit" | ||||
| 			on:click={() => dispatch('save')} | ||||
| 			class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 			>Save | ||||
| 		</button> | ||||
| 		<Button size="sm" color="gray" on:click={() => dispatch('reset')}>Reset</Button> | ||||
| 		<Button size="sm" on:click={() => dispatch('save')}>Save</Button> | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
| 	import { AlbumResponseDto, api, ThumbnailFormat } from '@api'; | ||||
| 	import { createEventDispatcher, onMount } from 'svelte'; | ||||
| 	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import noThumbnailUrl from '$lib/assets/no-thumbnail.png'; | ||||
| 	import { locale } from '$lib/stores/preferences.store'; | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
| 	import AssetSelection from './asset-selection.svelte'; | ||||
| 	import UserSelectionModal from './user-selection-modal.svelte'; | ||||
| 	import ShareInfoModal from './share-info-modal.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import Close from 'svelte-material-icons/Close.svelte'; | ||||
| 	import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte'; | ||||
| 	import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte'; | ||||
| @@ -42,6 +42,7 @@ | ||||
| 	import { locale } from '$lib/stores/preferences.store'; | ||||
| 	import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
| 	export let sharedLink: SharedLinkResponseDto | undefined = undefined; | ||||
| @@ -469,12 +470,14 @@ | ||||
| 				{/if} | ||||
|  | ||||
| 				{#if isCreatingSharedAlbum && album.sharedUsers.length == 0} | ||||
| 					<button | ||||
| 					<Button | ||||
| 						size="sm" | ||||
| 						rounded="lg" | ||||
| 						disabled={album.assetCount == 0} | ||||
| 						on:click={() => (isShowShareUserSelection = true)} | ||||
| 						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 | ||||
| 					> | ||||
| 						Share | ||||
| 					</Button> | ||||
| 				{/if} | ||||
| 			</svelte:fragment> | ||||
| 		</ControlAppBar> | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| 		selectedAssets | ||||
| 	} from '$lib/stores/asset-interaction.store'; | ||||
| 	import { locale } from '$lib/stores/preferences.store'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	const dispatch = createEventDispatcher(); | ||||
|  | ||||
| @@ -63,12 +64,14 @@ | ||||
| 			> | ||||
| 				Select from computer | ||||
| 			</button> | ||||
| 			<button | ||||
| 			<Button | ||||
| 				size="sm" | ||||
| 				rounded="lg" | ||||
| 				disabled={$selectedAssets.size === 0} | ||||
| 				on:click={addSelectedAssets} | ||||
| 				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 | ||||
| 			> | ||||
| 				Done | ||||
| 			</Button> | ||||
| 		</svelte:fragment> | ||||
| 	</ControlAppBar> | ||||
| 	<section class="pt-[100px] pl-[70px] grid h-screen bg-immich-bg dark:bg-immich-dark-bg"> | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| 	import BaseModal from '../shared-components/base-modal.svelte'; | ||||
| 	import CircleAvatar from '../shared-components/circle-avatar.svelte'; | ||||
| 	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import ContextMenu from '../shared-components/context-menu/context-menu.svelte'; | ||||
| 	import MenuOption from '../shared-components/context-menu/menu-option.svelte'; | ||||
| 	import { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 	import { fly } from 'svelte/transition'; | ||||
| 	import Thumbnail from '../assets/thumbnail/thumbnail.svelte'; | ||||
| 	import ControlAppBar from '../shared-components/control-app-bar.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
|  | ||||
| @@ -30,12 +31,14 @@ | ||||
| 		</svelte:fragment> | ||||
|  | ||||
| 		<svelte:fragment slot="trailing"> | ||||
| 			<button | ||||
| 			<Button | ||||
| 				size="sm" | ||||
| 				rounded="lg" | ||||
| 				disabled={selectedThumbnail == undefined} | ||||
| 				on:click={() => dispatch('thumbnail-selected', { asset: selectedThumbnail })} | ||||
| 				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" | ||||
| 				><span class="px-2">Done</span></button | ||||
| 			> | ||||
| 				Done | ||||
| 			</Button> | ||||
| 		</svelte:fragment> | ||||
| 	</ControlAppBar> | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| 	import ShareCircle from 'svelte-material-icons/ShareCircle.svelte'; | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
| 	export let sharedUsersInAlbum: Set<UserResponseDto>; | ||||
| @@ -117,11 +118,9 @@ | ||||
|  | ||||
| 		{#if selectedUsers.length > 0} | ||||
| 			<div class="flex place-content-end p-5 "> | ||||
| 				<button | ||||
| 					on:click={() => dispatch('add-user', { selectedUsers })} | ||||
| 					class="text-white bg-immich-primary px-4 py-2 rounded-lg text-sm font-bold transition-colors hover:bg-immich-primary/75" | ||||
| 					>Add</button | ||||
| 				> | ||||
| 				<Button size="sm" rounded="lg" on:click={() => dispatch('add-user', { selectedUsers })}> | ||||
| 					Add | ||||
| 				</Button> | ||||
| 			</div> | ||||
| 		{/if} | ||||
| 	</div> | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| 	import InformationOutline from 'svelte-material-icons/InformationOutline.svelte'; | ||||
| 	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; | ||||
| 	import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import ContextMenu from '../shared-components/context-menu/context-menu.svelte'; | ||||
| 	import MenuOption from '../shared-components/context-menu/menu-option.svelte'; | ||||
| 	import Star from 'svelte-material-icons/Star.svelte'; | ||||
|   | ||||
							
								
								
									
										71
									
								
								web/src/lib/components/elements/buttons/button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								web/src/lib/components/elements/buttons/button.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| <script lang="ts" context="module"> | ||||
| 	export type Type = 'button' | 'submit' | 'reset'; | ||||
| 	export type Color = | ||||
| 		| 'primary' | ||||
| 		| 'secondary' | ||||
| 		| 'transparent-primary' | ||||
| 		| 'light-red' | ||||
| 		| 'red' | ||||
| 		| 'green' | ||||
| 		| 'gray' | ||||
| 		| 'transparent-gray' | ||||
| 		| 'dark-gray'; | ||||
| 	export type Size = 'icon' | 'link' | 'sm' | 'base' | 'lg'; | ||||
| 	export type Rounded = 'lg' | '3xl' | 'full' | false; | ||||
| 	export type Shadow = 'md' | false; | ||||
| </script> | ||||
|  | ||||
| <script lang="ts"> | ||||
| 	export let type: Type = 'button'; | ||||
| 	export let color: Color = 'primary'; | ||||
| 	export let size: Size = 'base'; | ||||
| 	export let rounded: Rounded = '3xl'; | ||||
| 	export let shadow: Shadow = 'md'; | ||||
| 	export let disabled = false; | ||||
| 	export let fullwidth = false; | ||||
| 	export let border = false; | ||||
| 	export let title: string | undefined = ''; | ||||
|  | ||||
| 	const colorClasses: Record<Color, string> = { | ||||
| 		primary: | ||||
| 			'bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray enabled:dark:hover:bg-immich-dark-primary/80 enabled:hover:bg-immich-primary/90', | ||||
| 		secondary: | ||||
| 			'bg-gray-500 dark:bg-gray-200 text-white dark:text-immich-dark-gray enabled:hover:bg-gray-500/90 enabled:dark:hover:bg-gray-200/90', | ||||
| 		'transparent-primary': | ||||
| 			'text-gray-500 dark:text-immich-dark-primary enabled:hover:bg-gray-100 enabled:dark:hover:bg-gray-700', | ||||
| 		'light-red': 'bg-[#F9DEDC] text-[#410E0B] enabled:hover:bg-red-50', | ||||
| 		red: 'bg-red-500 text-white enabled:hover:bg-red-400', | ||||
| 		green: 'bg-lime-600 text-white enabled:hover:bg-lime-500', | ||||
| 		gray: 'bg-gray-500 dark:bg-gray-200 enabled:hover:bg-gray-500/75 enabled:dark:hover:bg-gray-200/80 text-white dark:text-immich-dark-gray', | ||||
| 		'transparent-gray': | ||||
| 			'dark:text-immich-dark-fg enabled:hover:bg-immich-primary/5 enabled:hover:text-gray-700 enabled:hover:dark:text-immich-dark-fg enabled:dark:hover:bg-immich-dark-primary/25 ', | ||||
| 		'dark-gray': | ||||
| 			'dark:border-immich-dark-gray dark:bg-gray-500 enabled:dark:hover:bg-immich-dark-primary/50 enabled:hover:bg-immich-primary/10 dark:text-white' | ||||
| 	}; | ||||
|  | ||||
| 	const sizeClasses: Record<Size, string> = { | ||||
| 		icon: 'p-2.5', | ||||
| 		link: 'p-2 font-medium', | ||||
| 		sm: 'px-4 py-2 text-sm font-medium', | ||||
| 		base: 'px-6 py-3 font-medium', | ||||
| 		lg: 'px-6 py-4 font-semibold' | ||||
| 	}; | ||||
| </script> | ||||
|  | ||||
| <button | ||||
| 	{type} | ||||
| 	{disabled} | ||||
| 	{title} | ||||
| 	on:click | ||||
| 	class="inline-flex justify-center items-center transition-colors disabled:cursor-not-allowed disabled:opacity-60 {colorClasses[ | ||||
| 		color | ||||
| 	]} {sizeClasses[size]}" | ||||
| 	class:rounded-lg={rounded === 'lg'} | ||||
| 	class:rounded-3xl={rounded === '3xl'} | ||||
| 	class:rounded-full={rounded === 'full'} | ||||
| 	class:shadow-md={shadow === 'md'} | ||||
| 	class:w-full={fullwidth} | ||||
| 	class:border | ||||
| > | ||||
| 	<slot /> | ||||
| </button> | ||||
| @@ -1,7 +1,4 @@ | ||||
| <script lang="ts"> | ||||
| 	/** | ||||
| 	 * This is the circle icon component. | ||||
| 	 */ | ||||
| 	import type Icon from 'svelte-material-icons/AbTesting.svelte'; | ||||
| 
 | ||||
| 	export let logo: typeof Icon; | ||||
| @@ -15,7 +12,7 @@ | ||||
| 	{title} | ||||
| 	style:backgroundColor | ||||
| 	style:--immich-icon-button-hover-color={hoverColor} | ||||
| 	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`} | ||||
| 	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 | ||||
| > | ||||
| 	<svelte:component this={logo} {size} /> | ||||
							
								
								
									
										14
									
								
								web/src/lib/components/elements/buttons/icon-button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								web/src/lib/components/elements/buttons/icon-button.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <script lang="ts" context="module"> | ||||
| 	export type Color = 'transparent-primary' | 'transparent-gray'; | ||||
| </script> | ||||
|  | ||||
| <script lang="ts"> | ||||
| 	import Button from './button.svelte'; | ||||
|  | ||||
| 	export let color: Color = 'transparent-primary'; | ||||
| 	export let title: string | undefined = undefined; | ||||
| </script> | ||||
|  | ||||
| <Button size="icon" {color} {title} shadow={false} rounded="full" on:click> | ||||
| 	<slot /> | ||||
| </Button> | ||||
							
								
								
									
										13
									
								
								web/src/lib/components/elements/buttons/link-button.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/lib/components/elements/buttons/link-button.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <script lang="ts" context="module"> | ||||
| 	export type Color = 'transparent-primary' | 'transparent-gray'; | ||||
| </script> | ||||
|  | ||||
| <script lang="ts"> | ||||
| 	import Button from './button.svelte'; | ||||
|  | ||||
| 	export let color: Color = 'transparent-gray'; | ||||
| </script> | ||||
|  | ||||
| <Button size="link" {color} shadow={false} rounded="lg" on:click> | ||||
| 	<slot /> | ||||
| </Button> | ||||
| @@ -2,6 +2,7 @@ | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import { AppRoute } from '$lib/constants'; | ||||
| 	import { api } from '@api'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let error: string; | ||||
| 	let password = ''; | ||||
| @@ -115,6 +116,6 @@ | ||||
| 	{/if} | ||||
|  | ||||
| 	<div class="my-5 flex w-full"> | ||||
| 		<button type="submit" class="immich-btn-primary-big">Sign Up</button> | ||||
| 		<Button type="submit" size="lg" fullwidth>Sign up</Button> | ||||
| 	</div> | ||||
| </form> | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import KeyVariant from 'svelte-material-icons/KeyVariant.svelte'; | ||||
| 	import FullScreenModal from '../shared-components/full-screen-modal.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let apiKey: Partial<APIKeyResponseDto>; | ||||
| 	export let title = 'API Key'; | ||||
| @@ -40,17 +41,8 @@ | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="flex w-full px-4 gap-4 mt-8"> | ||||
| 				<button | ||||
| 					type="button" | ||||
| 					on:click={() => handleCancel()} | ||||
| 					class="flex-1 transition-colors bg-gray-500 dark:bg-gray-200 hover:bg-gray-500/75 dark:hover:bg-gray-200/80 px-6 py-3 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium" | ||||
| 					>{cancelText} | ||||
| 				</button> | ||||
| 				<button | ||||
| 					type="submit" | ||||
| 					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" | ||||
| 					>{submitText}</button | ||||
| 				> | ||||
| 				<Button color="gray" fullwidth on:click={() => handleCancel()}>{cancelText}</Button> | ||||
| 				<Button type="submit" fullwidth>{submitText}</Button> | ||||
| 			</div> | ||||
| 		</form> | ||||
| 	</div> | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let secret = ''; | ||||
|  | ||||
| @@ -54,16 +55,8 @@ | ||||
| 		</div> | ||||
|  | ||||
| 		<div class="flex w-full px-4 gap-4 mt-8"> | ||||
| 			<button | ||||
| 				on:click={() => handleCopy()} | ||||
| 				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" | ||||
| 				>Copy to Clipboard</button | ||||
| 			> | ||||
| 			<button | ||||
| 				on:click={() => handleDone()} | ||||
| 				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" | ||||
| 				>Done</button | ||||
| 			> | ||||
| 			<Button on:click={() => handleCopy()} fullwidth>Copy to Clipboard</Button> | ||||
| 			<Button on:click={() => handleDone()} fullwidth>Done</Button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </FullScreenModal> | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { api, UserResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
| 	let error: string; | ||||
| @@ -78,6 +79,6 @@ | ||||
| 		<p class="text-immich-primary text-sm">{success}</p> | ||||
| 	{/if} | ||||
| 	<div class="my-5 flex w-full"> | ||||
| 		<button type="submit" class="immich-btn-primary-big">Change Password</button> | ||||
| 		<Button type="submit" size="lg" fullwidth>Change password</Button> | ||||
| 	</div> | ||||
| </form> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let error: string; | ||||
| 	let success: string; | ||||
| @@ -140,13 +141,8 @@ | ||||
| 		{#if success} | ||||
| 			<p class="text-immich-primary ml-4 text-sm">{success}</p> | ||||
| 		{/if} | ||||
| 		<div class="flex w-full"> | ||||
| 			<button | ||||
| 				type="submit" | ||||
| 				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" | ||||
| 				disabled={isCreatingUser} | ||||
| 				>Create | ||||
| 			</button> | ||||
| 		<div class="flex w-full p-4"> | ||||
| 			<Button type="submit" disabled={isCreatingUser} fullwidth>Create</Button> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </div> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -112,16 +113,8 @@ | ||||
| 			<p class="text-immich-primary ml-4 text-sm">{success}</p> | ||||
| 		{/if} | ||||
| 		<div class="flex w-full px-4 gap-4 mt-8"> | ||||
| 			<button | ||||
| 				on:click={resetPassword} | ||||
| 				class="flex-1 transition-colors bg-[#F9DEDC] hover:bg-red-50 text-[#410E0B] px-6 py-3 rounded-full w-full font-medium" | ||||
| 				>Reset password | ||||
| 			</button> | ||||
| 			<button | ||||
| 				type="submit" | ||||
| 				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 | ||||
| 			</button> | ||||
| 			<Button color="light-red" fullwidth on:click={resetPassword}>Reset password</Button> | ||||
| 			<Button type="submit" fullwidth>Confirm</Button> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </div> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| 	import { api, oauth, OAuthConfigResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher, onMount } from 'svelte'; | ||||
| 	import { fade } from 'svelte/transition'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let error: string; | ||||
| 	let email = ''; | ||||
| @@ -110,22 +111,20 @@ | ||||
| 		</div> | ||||
|  | ||||
| 		<div class="my-5 flex w-full"> | ||||
| 			<button | ||||
| 				type="submit" | ||||
| 				class="immich-btn-primary-big inline-flex items-center h-14" | ||||
| 				disabled={loading || oauthLoading} | ||||
| 			> | ||||
| 			<Button type="submit" size="lg" fullwidth disabled={loading || oauthLoading}> | ||||
| 				{#if loading} | ||||
| 					<LoadingSpinner /> | ||||
| 					<span class="h-6"> | ||||
| 						<LoadingSpinner /> | ||||
| 					</span> | ||||
| 				{:else} | ||||
| 					Login | ||||
| 				{/if} | ||||
| 			</button> | ||||
| 			</Button> | ||||
| 		</div> | ||||
| 	</form> | ||||
| {/if} | ||||
|  | ||||
| {#if authConfig.enabled} | ||||
| {#if !authConfig.enabled} | ||||
| 	{#if authConfig.passwordLoginEnabled} | ||||
| 		<div class="inline-flex items-center justify-center w-full"> | ||||
| 			<hr class="w-3/4 h-px my-4 bg-gray-200 border-0 dark:bg-gray-600" /> | ||||
| @@ -141,19 +140,21 @@ | ||||
| 			<p class="text-red-400" transition:fade>{oauthError}</p> | ||||
| 		{/if} | ||||
| 		<a href={authConfig.url} class="flex w-full"> | ||||
| 			<button | ||||
| 			<Button | ||||
| 				type="button" | ||||
| 				disabled={loading || oauthLoading} | ||||
| 				class={'inline-flex items-center h-14 ' + authConfig.passwordLoginEnabled | ||||
| 					? 'immich-btn-secondary-big' | ||||
| 					: 'immich-btn-primary-big'} | ||||
| 				size="lg" | ||||
| 				fullwidth | ||||
| 				color={authConfig.passwordLoginEnabled ? 'secondary' : 'primary'} | ||||
| 			> | ||||
| 				{#if oauthLoading} | ||||
| 					<LoadingSpinner /> | ||||
| 					<span class="h-6"> | ||||
| 						<LoadingSpinner /> | ||||
| 					</span> | ||||
| 				{:else} | ||||
| 					{authConfig.buttonText || 'Login with OAuth'} | ||||
| 				{/if} | ||||
| 			</button> | ||||
| 			</Button> | ||||
| 		</a> | ||||
| 	</div> | ||||
| {/if} | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| 	import { api, AssetResponseDto, SharedLinkResponseDto } from '@api'; | ||||
| 	import ControlAppBar from '../shared-components/control-app-bar.svelte'; | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte'; | ||||
| 	import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte'; | ||||
| 	import { openFileUploadDialog } from '$lib/utils/file-uploader'; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| 	import Close from 'svelte-material-icons/Close.svelte'; | ||||
| 	import { createEventDispatcher, onMount, onDestroy } from 'svelte'; | ||||
| 	import { browser } from '$app/environment'; | ||||
| 	import CircleIconButton from './circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import { clickOutside } from '$lib/utils/click-outside'; | ||||
|  | ||||
| 	const dispatch = createEventDispatcher(); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import FullScreenModal from './full-screen-modal.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let title = 'Confirm'; | ||||
| 	export let prompt = 'Are you sure you want to do this?'; | ||||
| @@ -29,18 +30,8 @@ | ||||
| 			</slot> | ||||
|  | ||||
| 			<div class="flex w-full px-4 gap-4 mt-4"> | ||||
| 				<button | ||||
| 					on:click={() => handleCancel()} | ||||
| 					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" | ||||
| 				> | ||||
| 					{cancelText} | ||||
| 				</button> | ||||
| 				<button | ||||
| 					on:click={() => handleConfirm()} | ||||
| 					class="flex-1 transition-colors bg-red-500 hover:bg-red-400 px-6 py-3 text-white rounded-full w-full font-medium" | ||||
| 				> | ||||
| 					{confirmText} | ||||
| 				</button> | ||||
| 				<Button fullwidth on:click={() => handleCancel()}>{cancelText}</Button> | ||||
| 				<Button color="red" fullwidth on:click={() => handleConfirm()}>{confirmText}</Button> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|  | ||||
| 	import { createEventDispatcher, onDestroy, onMount } from 'svelte'; | ||||
| 	import Close from 'svelte-material-icons/Close.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import { fly } from 'svelte/transition'; | ||||
|  | ||||
| 	export let showBackButton = true; | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| 		SettingInputFieldType | ||||
| 	} from '$lib/components/admin-page/settings/setting-input-field.svelte'; | ||||
| 	import { handleError } from '$lib/utils/handle-error'; | ||||
| 	import Button from '$lib/components/elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let shareType: SharedLinkType; | ||||
| 	export let sharedAssets: AssetResponseDto[] = []; | ||||
| @@ -243,21 +244,11 @@ | ||||
| 		{#if !isShowSharedLink} | ||||
| 			{#if editingLink} | ||||
| 				<div class="flex justify-end"> | ||||
| 					<button | ||||
| 						on:click={handleEditLink} | ||||
| 						class="text-white dark:text-black bg-immich-primary px-4 py-2 rounded-lg text-sm transition-colors hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:hover:bg-immich-dark-primary/75" | ||||
| 					> | ||||
| 						Confirm | ||||
| 					</button> | ||||
| 					<Button size="sm" rounded="lg" on:click={handleEditLink}>Confirm</Button> | ||||
| 				</div> | ||||
| 			{:else} | ||||
| 				<div class="flex justify-end"> | ||||
| 					<button | ||||
| 						on:click={handleCreateSharedLink} | ||||
| 						class="text-white dark:text-black bg-immich-primary px-4 py-2 rounded-lg text-sm transition-colors hover:bg-immich-primary/75 dark:bg-immich-dark-primary dark:hover:bg-immich-dark-primary/75" | ||||
| 					> | ||||
| 						Create Link | ||||
| 					</button> | ||||
| 					<Button size="sm" rounded="lg" on:click={handleCreateSharedLink}>Create link</Button> | ||||
| 				</div> | ||||
| 			{/if} | ||||
| 		{/if} | ||||
| @@ -266,11 +257,7 @@ | ||||
| 			<div class="flex w-full gap-4"> | ||||
| 				<input class="immich-form-input w-full" bind:value={sharedLink} disabled /> | ||||
|  | ||||
| 				<button | ||||
| 					on:click={() => handleCopy()} | ||||
| 					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-2 text-white rounded-full shadow-md w-full font-medium" | ||||
| 					>Copy</button | ||||
| 				> | ||||
| 				<Button on:click={() => handleCopy()}>Copy</Button> | ||||
| 			</div> | ||||
| 		{/if} | ||||
| 	</section> | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| 	import Cog from 'svelte-material-icons/Cog.svelte'; | ||||
| 	import Logout from 'svelte-material-icons/Logout.svelte'; | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import Button from '$lib/components/elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -59,16 +60,22 @@ | ||||
|  | ||||
| 		<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{user.email}</p> | ||||
|  | ||||
| 		<div class=" mt-4 flex place-items-center place-content-center"> | ||||
| 			<button | ||||
| 				class="flex border rounded-3xl px-6 py-2 hover:bg-immich-primary/10 dark:border-immich-dark-gray dark:bg-gray-500 dark:hover:bg-immich-dark-primary/50 dark:text-white font-medium place-items-center place-content-center gap-2" | ||||
| 		<div class="mt-4"> | ||||
| 			<Button | ||||
| 				color="dark-gray" | ||||
| 				size="sm" | ||||
| 				shadow={false} | ||||
| 				border | ||||
| 				on:click={() => { | ||||
| 					goto('/user-settings'); | ||||
| 					dispatch('close'); | ||||
| 				}} | ||||
| 			> | ||||
| 				<span><Cog size="18" /></span>Account Settings</button | ||||
| 			> | ||||
| 				<div class="flex gap-2 place-items-center place-content-center px-2"> | ||||
| 					<Cog size="18" /> | ||||
| 					Account Settings | ||||
| 				</div> | ||||
| 			</Button> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| 	import AccountInfoPanel from './account-info-panel.svelte'; | ||||
| 	import ImmichLogo from '../immich-logo.svelte'; | ||||
| 	import SearchBar from '../search-bar/search-bar.svelte'; | ||||
| 	import LinkButton from '$lib/components/elements/buttons/link-button.svelte'; | ||||
| 	export let user: UserResponseDto; | ||||
| 	export let shouldShowUploadButton = true; | ||||
|  | ||||
| @@ -61,24 +62,27 @@ | ||||
| 				<ThemeButton /> | ||||
|  | ||||
| 				{#if !$page.url.pathname.includes('/admin') && shouldShowUploadButton} | ||||
| 					<button | ||||
| 						in:fly={{ x: 50, duration: 250 }} | ||||
| 						on:click={() => dispatch('uploadClicked')} | ||||
| 						class="immich-text-button dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg" | ||||
| 					> | ||||
| 						<TrayArrowUp size="20" /> | ||||
| 						<span> Upload </span> | ||||
| 					</button> | ||||
| 					<div in:fly={{ x: 50, duration: 250 }}> | ||||
| 						<LinkButton on:click={() => dispatch('uploadClicked')}> | ||||
| 							<div class="flex gap-2"> | ||||
| 								<TrayArrowUp size="20" /> | ||||
| 								<span>Upload</span> | ||||
| 							</div> | ||||
| 						</LinkButton> | ||||
| 					</div> | ||||
| 				{/if} | ||||
|  | ||||
| 				{#if user.isAdmin} | ||||
| 					<a data-sveltekit-preload-data="hover" href={AppRoute.ADMIN_USER_MANAGEMENT}> | ||||
| 						<button | ||||
| 							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.includes('/admin') && | ||||
| 								'text-immich-primary dark:immich-dark-primary underline' | ||||
| 							}`}>Administration</button | ||||
| 						> | ||||
| 						<LinkButton> | ||||
| 							<span | ||||
| 								class={$page.url.pathname.includes('/admin') | ||||
| 									? 'text-immich-primary dark:text-immich-dark-primary underline' | ||||
| 									: ''} | ||||
| 							> | ||||
| 								Administration | ||||
| 							</span> | ||||
| 						</LinkButton> | ||||
| 					</a> | ||||
| 				{/if} | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { browser } from '$app/environment'; | ||||
| 	import { colorTheme } from '$lib/stores/preferences.store'; | ||||
| 	import IconButton from '../elements/buttons/icon-button.svelte'; | ||||
|  | ||||
| 	const toggleTheme = () => { | ||||
| 		$colorTheme = $colorTheme === 'dark' ? 'light' : 'dark'; | ||||
| @@ -17,11 +18,7 @@ | ||||
| 	} | ||||
| </script> | ||||
|  | ||||
| <button | ||||
| 	on:click={toggleTheme} | ||||
| 	type="button" | ||||
| 	class="text-gray-500 dark:text-immich-dark-primary hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none rounded-full p-2.5" | ||||
| > | ||||
| <IconButton on:click={toggleTheme} title="Toggle theme"> | ||||
| 	{#if $colorTheme === 'light'} | ||||
| 		<svg class="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 | ||||
| @@ -35,4 +32,4 @@ | ||||
| 			/></svg | ||||
| 		> | ||||
| 	{/if} | ||||
| </button> | ||||
| </IconButton> | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import FullScreenModal from './full-screen-modal.svelte'; | ||||
| 	import type { ServerVersionReponseDto } from '@api'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let serverVersion: ServerVersionReponseDto; | ||||
|  | ||||
| @@ -72,10 +73,7 @@ | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="text-right mt-8"> | ||||
| 				<button | ||||
| 					class="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" | ||||
| 					on:click={onAcknowledge}>Acknowledge</button | ||||
| 				> | ||||
| 				<Button fullwidth on:click={onAcknowledge}>Acknowledge</Button> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</FullScreenModal> | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| 	import ContentCopy from 'svelte-material-icons/ContentCopy.svelte'; | ||||
| 	import CircleEditOutline from 'svelte-material-icons/CircleEditOutline.svelte'; | ||||
| 	import * as luxon from 'luxon'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import { goto } from '$app/navigation'; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| 	import SettingInputField, { | ||||
| 		SettingInputFieldType | ||||
| 	} from '../admin-page/settings/setting-input-field.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let password = ''; | ||||
| 	let newPassword = ''; | ||||
| @@ -64,13 +65,12 @@ | ||||
| 				/> | ||||
|  | ||||
| 				<div class="flex justify-end"> | ||||
| 					<button | ||||
| 					<Button | ||||
| 						type="submit" | ||||
| 						size="sm" | ||||
| 						disabled={!(password && newPassword && newPassword === confirmPassword)} | ||||
| 						on:click={() => handleChangePassword()} | ||||
| 						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 						>Save | ||||
| 					</button> | ||||
| 						on:click={() => handleChangePassword()}>Save</Button | ||||
| 					> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</form> | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -67,17 +68,10 @@ | ||||
| 				</div> | ||||
| 			{:else if config.enabled} | ||||
| 				{#if user.oauthId} | ||||
| 					<button | ||||
| 						on:click={() => handleUnlink()} | ||||
| 						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 						>Unlink OAuth | ||||
| 					</button> | ||||
| 					<Button size="sm" on:click={() => handleUnlink()}>Unlink Oauth</Button> | ||||
| 				{:else} | ||||
| 					<a href={config.url}> | ||||
| 						<button | ||||
| 							class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 							>Link to OAuth</button | ||||
| 						> | ||||
| 						<Button size="sm" on:click={() => handleUnlink()}>Link to OAuth</Button> | ||||
| 					</a> | ||||
| 				{/if} | ||||
| 			{/if} | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import { locale } from '$lib/stores/preferences.store'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let keys: APIKeyResponseDto[] = []; | ||||
|  | ||||
| @@ -124,11 +125,7 @@ | ||||
| <section class="my-4"> | ||||
| 	<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}> | ||||
| 		<div class="flex justify-end mb-2"> | ||||
| 			<button | ||||
| 				on:click={() => (newKey = { name: 'API Key' })} | ||||
| 				class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 				>New API Key | ||||
| 			</button> | ||||
| 			<Button size="sm" on:click={() => (newKey = { name: 'API Key' })}>New API Key</Button> | ||||
| 		</div> | ||||
|  | ||||
| 		{#if keys.length > 0} | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 	import SettingInputField, { | ||||
| 		SettingInputFieldType | ||||
| 	} from '../admin-page/settings/setting-input-field.svelte'; | ||||
| 	import Button from '../elements/buttons/button.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| @@ -65,12 +66,7 @@ | ||||
| 				/> | ||||
|  | ||||
| 				<div class="flex justify-end"> | ||||
| 					<button | ||||
| 						type="submit" | ||||
| 						on:click={() => handleSaveProfile()} | ||||
| 						class="text-sm bg-immich-primary dark:bg-immich-dark-primary hover:bg-immich-primary/75 dark:hover:bg-immich-dark-primary/80 px-4 py-2 text-white dark:text-immich-dark-gray rounded-full shadow-md font-medium disabled:opacity-50 disabled:cursor-not-allowed" | ||||
| 						>Save | ||||
| 					</button> | ||||
| 					<Button type="submit" size="sm" on:click={() => handleSaveProfile()}>Save</Button> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</form> | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 	import { useAlbums } from './albums.bloc'; | ||||
| 	import empty1Url from '$lib/assets/empty-1.svg'; | ||||
| 	import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; | ||||
| 	import LinkButton from '$lib/components/elements/buttons/link-button.svelte'; | ||||
|  | ||||
| 	export let data: PageData; | ||||
|  | ||||
| @@ -32,15 +33,12 @@ | ||||
|  | ||||
| <UserPageLayout user={data.user} title={data.meta.title}> | ||||
| 	<div slot="buttons"> | ||||
| 		<button | ||||
| 			on:click={handleCreateAlbum} | ||||
| 			class="immich-text-button text-sm dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg" | ||||
| 		> | ||||
| 			<span> | ||||
| 		<LinkButton on:click={handleCreateAlbum}> | ||||
| 			<div class="flex place-items-center gap-2 text-sm"> | ||||
| 				<PlusBoxOutline size="18" /> | ||||
| 			</span> | ||||
| 			<p>Create album</p> | ||||
| 		</button> | ||||
| 				Create album | ||||
| 			</div> | ||||
| 		</LinkButton> | ||||
| 	</div> | ||||
|  | ||||
| 	<!-- Album Card --> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <script lang="ts"> | ||||
| 	import CircleIconButton from '$lib/components/shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte'; | ||||
| 	import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; | ||||
| 	import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte'; | ||||
| 	import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte'; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import AssetGrid from '$lib/components/photos-page/asset-grid.svelte'; | ||||
| 	import AlbumSelectionModal from '$lib/components/shared-components/album-selection-modal.svelte'; | ||||
| 	import CircleIconButton from '$lib/components/shared-components/circle-icon-button.svelte'; | ||||
| 	import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte'; | ||||
| 	import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte'; | ||||
| 	import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; | ||||
| 	import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| 	} from '$lib/components/shared-components/notification/notification'; | ||||
| 	import empty2Url from '$lib/assets/empty-2.svg'; | ||||
| 	import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; | ||||
| 	import LinkButton from '$lib/components/elements/buttons/link-button.svelte'; | ||||
|  | ||||
| 	export let data: PageData; | ||||
|  | ||||
| @@ -34,25 +35,19 @@ | ||||
|  | ||||
| <UserPageLayout user={data.user} title={data.meta.title}> | ||||
| 	<div class="flex" slot="buttons"> | ||||
| 		<button | ||||
| 			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 dark:hover:bg-immich-dark-primary/25 dark:text-immich-dark-fg" | ||||
| 		> | ||||
| 			<span> | ||||
| 		<LinkButton on:click={createSharedAlbum}> | ||||
| 			<div class="flex place-items-center gap-1 text-sm"> | ||||
| 				<PlusBoxOutline size="18" /> | ||||
| 			</span> | ||||
| 			<p>Create shared album</p> | ||||
| 		</button> | ||||
| 				Create shared album | ||||
| 			</div> | ||||
| 		</LinkButton> | ||||
|  | ||||
| 		<button | ||||
| 			on:click={() => goto('/sharing/sharedlinks')} | ||||
| 			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> | ||||
| 		<LinkButton on:click={() => goto('/sharing/sharedlinks')}> | ||||
| 			<div class="flex place-items-center gap-1 text-sm"> | ||||
| 				<Link size="18" /> | ||||
| 			</span> | ||||
| 			<p>Shared links</p> | ||||
| 		</button> | ||||
| 				Shared links | ||||
| 			</div> | ||||
| 		</LinkButton> | ||||
| 	</div> | ||||
|  | ||||
| 	<section> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| <script lang="ts"> | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import Button from '$lib/components/elements/buttons/button.svelte'; | ||||
| 	import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte'; | ||||
| </script> | ||||
|  | ||||
| @@ -13,10 +14,8 @@ | ||||
| 		> | ||||
| 			Welcome to IMMICH Web | ||||
| 		</h1> | ||||
| 		<button | ||||
| 			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={() => goto('/auth/register')} | ||||
| 			>Getting Started | ||||
| 		</button> | ||||
| 		<Button size="lg" rounded="lg" on:click={() => goto('/auth/register')}> | ||||
| 			<span class="font-bold px-2">Getting Started</span> | ||||
| 		</Button> | ||||
| 	</div> | ||||
| </section> | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| 	import RestoreDialogue from '$lib/components/admin-page/restore-dialoge.svelte'; | ||||
| 	import { page } from '$app/stores'; | ||||
| 	import { locale } from '$lib/stores/preferences.store'; | ||||
| 	import Button from '$lib/components/elements/buttons/button.svelte'; | ||||
|  | ||||
| 	let allUsers: UserResponseDto[] = []; | ||||
| 	let shouldShowEditUserForm = false; | ||||
| @@ -151,12 +152,8 @@ | ||||
| 					Please inform the user, and they will need to change the password at the next log-on. | ||||
| 				</p> | ||||
|  | ||||
| 				<div class="flex w-full"> | ||||
| 					<button | ||||
| 						on:click={() => (shouldShowInfoPanel = false)} | ||||
| 						class="mt-6 bg-immich-primary hover:bg-immich-primary/75 px-6 py-3 text-white rounded-full shadow-md w-full font-medium" | ||||
| 						>Done | ||||
| 					</button> | ||||
| 				<div class="flex w-full mt-6"> | ||||
| 					<Button fullwidth on:click={() => (shouldShowInfoPanel = false)}>Done</Button> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</FullScreenModal> | ||||
| @@ -221,7 +218,5 @@ | ||||
| 		</tbody> | ||||
| 	</table> | ||||
|  | ||||
| 	<button on:click={() => (shouldShowCreateUserForm = true)} class="immich-btn-primary" | ||||
| 		>Create user</button | ||||
| 	> | ||||
| 	<Button size="sm" on:click={() => (shouldShowCreateUserForm = true)}>Create user</Button> | ||||
| </section> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user