mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
chore: tailwindcss v4 and z-war clean up (#18358)
* chore: styling tweak * replace full-screen-modal, update docs * scrubber * fix: control app bar in memory viewer * face lift * pr feedback * clean up
This commit is contained in:
parent
2431e04a09
commit
c8641d24f6
42 changed files with 871 additions and 928 deletions
|
|
@ -1,9 +1,8 @@
|
|||
<script lang="ts">
|
||||
import AlbumCover from '$lib/components/album-page/album-cover.svelte';
|
||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAlbumInfo, type AlbumResponseDto } from '@immich/sdk';
|
||||
import { Button } from '@immich/ui';
|
||||
import { Button, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiRenameOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
|
|
@ -47,29 +46,33 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal icon={mdiRenameOutline} title={$t('edit_album')} width="wide" {onClose}>
|
||||
<form {onsubmit} autocomplete="off" id="edit-album-form">
|
||||
<div class="flex items-center">
|
||||
<div class="hidden sm:flex">
|
||||
<AlbumCover {album} class="h-[200px] w-[200px] m-4 shadow-lg" />
|
||||
</div>
|
||||
|
||||
<div class="grow">
|
||||
<div class="m-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="name">{$t('name')}</label>
|
||||
<input class="immich-form-input" id="name" type="text" bind:value={albumName} />
|
||||
<Modal icon={mdiRenameOutline} title={$t('edit_album')} size="medium" {onClose}>
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="edit-album-form">
|
||||
<div class="flex items-center">
|
||||
<div class="hidden sm:flex">
|
||||
<AlbumCover {album} class="h-[200px] w-[200px] m-4 shadow-lg" />
|
||||
</div>
|
||||
|
||||
<div class="m-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="description">{$t('description')}</label>
|
||||
<textarea class="immich-form-input" id="description" bind:value={description}></textarea>
|
||||
<div class="grow">
|
||||
<div class="m-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="name">{$t('name')}</label>
|
||||
<input class="immich-form-input" id="name" type="text" bind:value={albumName} />
|
||||
</div>
|
||||
|
||||
<div class="m-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="description">{$t('description')}</label>
|
||||
<textarea class="immich-form-input" id="description" bind:value={description}></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<div class="flex gap-2 w-full">
|
||||
<Button shape="round" color="secondary" fullWidth onclick={() => onCancel?.()}>{$t('cancel')}</Button>
|
||||
<Button shape="round" type="submit" fullWidth disabled={isSubmitting} form="edit-album-form">{$t('save')}</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<Button shape="round" color="secondary" fullWidth onclick={() => onCancel?.()}>{$t('cancel')}</Button>
|
||||
<Button shape="round" type="submit" fullWidth disabled={isSubmitting} form="edit-album-form">{$t('save')}</Button>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { Button } from '@immich/ui';
|
||||
import { Button, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiFolderRemove } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||
|
||||
interface Props {
|
||||
exclusionPattern: string;
|
||||
|
|
@ -42,37 +41,40 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal title={$t('add_exclusion_pattern')} icon={mdiFolderRemove} onClose={onCancel}>
|
||||
<form {onsubmit} autocomplete="off" id="add-exclusion-pattern-form">
|
||||
<p class="py-5 text-sm">
|
||||
{$t('admin.exclusion_pattern_description')}
|
||||
<br /><br />
|
||||
{$t('admin.add_exclusion_pattern_description')}
|
||||
</p>
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="exclusionPattern">{$t('pattern')}</label>
|
||||
<input
|
||||
class="immich-form-input"
|
||||
id="exclusionPattern"
|
||||
name="exclusionPattern"
|
||||
type="text"
|
||||
bind:value={exclusionPattern}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-8 flex w-full gap-4">
|
||||
{#if isDuplicate}
|
||||
<p class="text-red-500 text-sm">{$t('errors.exclusion_pattern_already_exists')}</p>
|
||||
<Modal size="small" title={$t('add_exclusion_pattern')} icon={mdiFolderRemove} onClose={onCancel}>
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="add-exclusion-pattern-form">
|
||||
<p class="py-5 text-sm">
|
||||
{$t('admin.exclusion_pattern_description')}
|
||||
<br /><br />
|
||||
{$t('admin.add_exclusion_pattern_description')}
|
||||
</p>
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="exclusionPattern">{$t('pattern')}</label>
|
||||
<input
|
||||
class="immich-form-input"
|
||||
id="exclusionPattern"
|
||||
name="exclusionPattern"
|
||||
type="text"
|
||||
bind:value={exclusionPattern}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-8 flex w-full gap-4">
|
||||
{#if isDuplicate}
|
||||
<p class="text-red-500 text-sm">{$t('errors.exclusion_pattern_already_exists')}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<div class="flex gap-2 w-full">
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{$t('cancel')}</Button>
|
||||
{#if isEditing}
|
||||
<Button shape="round" color="danger" fullWidth onclick={onDelete}>{$t('delete')}</Button>
|
||||
{/if}
|
||||
<Button shape="round" type="submit" disabled={!canSubmit} fullWidth form="add-exclusion-pattern-form"
|
||||
>{submitText}</Button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{$t('cancel')}</Button>
|
||||
{#if isEditing}
|
||||
<Button shape="round" color="danger" fullWidth onclick={onDelete}>{$t('delete')}</Button>
|
||||
{/if}
|
||||
<Button shape="round" type="submit" disabled={!canSubmit} fullWidth form="add-exclusion-pattern-form"
|
||||
>{submitText}</Button
|
||||
>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Button } from '@immich/ui';
|
||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||
import { Button, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiFolderSync } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
|
@ -46,29 +45,33 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal {title} icon={mdiFolderSync} onClose={onCancel}>
|
||||
<form {onsubmit} autocomplete="off" id="library-import-path-form">
|
||||
<p class="py-5 text-sm">{$t('admin.library_import_path_description')}</p>
|
||||
<Modal {title} icon={mdiFolderSync} onClose={onCancel} size="small">
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="library-import-path-form">
|
||||
<p class="py-5 text-sm">{$t('admin.library_import_path_description')}</p>
|
||||
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="path">{$t('path')}</label>
|
||||
<input class="immich-form-input" id="path" name="path" type="text" bind:value={importPath} />
|
||||
</div>
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="path">{$t('path')}</label>
|
||||
<input class="immich-form-input" id="path" name="path" type="text" bind:value={importPath} />
|
||||
</div>
|
||||
|
||||
<div class="mt-8 flex w-full gap-4">
|
||||
{#if isDuplicate}
|
||||
<p class="text-red-500 text-sm">{$t('errors.import_path_already_exists')}</p>
|
||||
<div class="mt-8 flex w-full gap-4">
|
||||
{#if isDuplicate}
|
||||
<p class="text-red-500 text-sm">{$t('errors.import_path_already_exists')}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<div class="flex gap-2 w-full">
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{cancelText}</Button>
|
||||
{#if isEditing}
|
||||
<Button shape="round" color="danger" fullWidth onclick={onDelete}>{$t('delete')}</Button>
|
||||
{/if}
|
||||
<Button shape="round" type="submit" disabled={!canSubmit} fullWidth form="library-import-path-form"
|
||||
>{submitText}</Button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{cancelText}</Button>
|
||||
{#if isEditing}
|
||||
<Button shape="round" color="danger" fullWidth onclick={onDelete}>{$t('delete')}</Button>
|
||||
{/if}
|
||||
<Button shape="round" type="submit" disabled={!canSubmit} fullWidth form="library-import-path-form"
|
||||
>{submitText}</Button
|
||||
>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script lang="ts">
|
||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||
import type { LibraryResponseDto } from '@immich/sdk';
|
||||
import { Button, Field, Input } from '@immich/ui';
|
||||
import { Button, Field, Input, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiRenameOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
|
|
@ -21,15 +20,19 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<form {onsubmit} autocomplete="off">
|
||||
<FullScreenModal icon={mdiRenameOutline} title={$t('rename')} onClose={onCancel}>
|
||||
<Field label={$t('name')}>
|
||||
<Input bind:value={newName} />
|
||||
</Field>
|
||||
<Modal icon={mdiRenameOutline} title={$t('rename')} onClose={onCancel} size="small">
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="rename-library-form">
|
||||
<Field label={$t('name')}>
|
||||
<Input bind:value={newName} />
|
||||
</Field>
|
||||
</form>
|
||||
</ModalBody>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<ModalFooter>
|
||||
<div class="flex gap-2 w-full">
|
||||
<Button shape="round" fullWidth color="secondary" onclick={onCancel}>{$t('cancel')}</Button>
|
||||
<Button shape="round" fullWidth type="submit">{$t('save')}</Button>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</form>
|
||||
<Button shape="round" fullWidth type="submit" form="rename-library-form">{$t('save')}</Button>
|
||||
</div>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { searchUsersAdmin } from '@immich/sdk';
|
||||
import { Button } from '@immich/ui';
|
||||
import { Button, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiFolderSync } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||
|
||||
interface Props {
|
||||
onCancel: () => void;
|
||||
|
|
@ -30,15 +29,19 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal title={$t('select_library_owner')} icon={mdiFolderSync} onClose={onCancel}>
|
||||
<form {onsubmit} autocomplete="off" id="select-library-owner-form">
|
||||
<p class="p-5 text-sm">{$t('admin.note_cannot_be_changed_later')}</p>
|
||||
<Modal title={$t('select_library_owner')} icon={mdiFolderSync} onClose={onCancel} size="small">
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="select-library-owner-form">
|
||||
<p class="p-5 text-sm">{$t('admin.note_cannot_be_changed_later')}</p>
|
||||
|
||||
<SettingSelect bind:value={ownerId} options={userOptions} name="user" />
|
||||
</form>
|
||||
<SettingSelect bind:value={ownerId} options={userOptions} name="user" />
|
||||
</form>
|
||||
</ModalBody>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{$t('cancel')}</Button>
|
||||
<Button shape="round" type="submit" fullWidth form="select-library-owner-form">{$t('create')}</Button>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
<ModalFooter>
|
||||
<div class="flex gap-2 w-full">
|
||||
<Button shape="round" color="secondary" fullWidth onclick={onCancel}>{$t('cancel')}</Button>
|
||||
<Button shape="round" type="submit" fullWidth form="select-library-owner-form">{$t('create')}</Button>
|
||||
</div>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { getAllTags, upsertTags, type TagResponseDto } from '@immich/sdk';
|
||||
import { Button } from '@immich/ui';
|
||||
import { Button, Modal, ModalBody, ModalFooter } from '@immich/ui';
|
||||
import { mdiClose, mdiTag } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { SvelteSet } from 'svelte/reactivity';
|
||||
import Combobox, { type ComboBoxOption } from '../shared-components/combobox.svelte';
|
||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||
|
||||
interface Props {
|
||||
onTag: (tagIds: string[]) => void;
|
||||
|
|
@ -52,48 +51,52 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal title={$t('tag_assets')} icon={mdiTag} onClose={onCancel}>
|
||||
<form {onsubmit} autocomplete="off" id="create-tag-form">
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<Combobox
|
||||
onSelect={handleSelect}
|
||||
label={$t('tag')}
|
||||
{allowCreate}
|
||||
defaultFirstOption
|
||||
options={allTags.map((tag) => ({ id: tag.id, label: tag.value, value: tag.id }))}
|
||||
placeholder={$t('search_tags')}
|
||||
/>
|
||||
<Modal size="small" title={$t('tag_assets')} icon={mdiTag} onClose={onCancel}>
|
||||
<ModalBody>
|
||||
<form {onsubmit} autocomplete="off" id="create-tag-form">
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<Combobox
|
||||
onSelect={handleSelect}
|
||||
label={$t('tag')}
|
||||
{allowCreate}
|
||||
defaultFirstOption
|
||||
options={allTags.map((tag) => ({ id: tag.id, label: tag.value, value: tag.id }))}
|
||||
placeholder={$t('search_tags')}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<section class="flex flex-wrap pt-2 gap-1">
|
||||
{#each selectedIds as tagId (tagId)}
|
||||
{@const tag = tagMap[tagId]}
|
||||
{#if tag}
|
||||
<div class="flex group transition-all">
|
||||
<span
|
||||
class="inline-block h-min whitespace-nowrap ps-3 pe-1 group-hover:ps-3 py-1 text-center align-baseline leading-none text-gray-100 dark:text-immich-dark-gray bg-immich-primary dark:bg-immich-dark-primary roudned-s-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
|
||||
>
|
||||
<p class="text-sm">
|
||||
{tag.value}
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-e-full place-items-center place-content-center pe-2 ps-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
|
||||
title="Remove tag"
|
||||
onclick={() => handleRemove(tagId)}
|
||||
>
|
||||
<Icon path={mdiClose} />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</section>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<div class="flex w-full gap-2">
|
||||
<Button shape="round" fullWidth color="secondary" onclick={onCancel}>{$t('cancel')}</Button>
|
||||
<Button type="submit" shape="round" fullWidth form="create-tag-form" {disabled}>{$t('tag_assets')}</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<section class="flex flex-wrap pt-2 gap-1">
|
||||
{#each selectedIds as tagId (tagId)}
|
||||
{@const tag = tagMap[tagId]}
|
||||
{#if tag}
|
||||
<div class="flex group transition-all">
|
||||
<span
|
||||
class="inline-block h-min whitespace-nowrap ps-3 pe-1 group-hover:ps-3 py-1 text-center align-baseline leading-none text-gray-100 dark:text-immich-dark-gray bg-immich-primary dark:bg-immich-dark-primary roudned-s-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
|
||||
>
|
||||
<p class="text-sm">
|
||||
{tag.value}
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-e-full place-items-center place-content-center pe-2 ps-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
|
||||
title="Remove tag"
|
||||
onclick={() => handleRemove(tagId)}
|
||||
>
|
||||
<Icon path={mdiClose} />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</section>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
<Button shape="round" fullWidth color="secondary" onclick={onCancel}>{$t('cancel')}</Button>
|
||||
<Button type="submit" shape="round" fullWidth form="create-tag-form" {disabled}>{$t('tag_assets')}</Button>
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue