diff --git a/web/package-lock.json b/web/package-lock.json index 37f944d3bb..37f7faf711 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.17.3", + "@immich/ui": "^0.18.1", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -1320,9 +1320,9 @@ "link": true }, "node_modules/@immich/ui": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.17.4.tgz", - "integrity": "sha512-a6M7Fxno5fwY5A0kxdluS8r+A4L6xZhSTKMW8c8hoFhQHvbBTHAsGFKQF3GOEQLOlUuvsS2Lt7dMevBlAPgo/A==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.18.1.tgz", + "integrity": "sha512-XWWO6OTfH3MektyxCn0hWefZyOGyWwwx/2zHinuShpxTHSyfveJ4mOkFP8DkyMz0dnvJ1EfdkPBMkld3y5R/Hw==", "license": "GNU Affero General Public License version 3", "dependencies": { "@mdi/js": "^7.4.47", diff --git a/web/package.json b/web/package.json index c32e7b04a8..4102765f70 100644 --- a/web/package.json +++ b/web/package.json @@ -27,7 +27,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.17.3", + "@immich/ui": "^0.18.1", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", diff --git a/web/src/lib/components/admin-page/jobs/job-tile.svelte b/web/src/lib/components/admin-page/jobs/job-tile.svelte index 80dd29e0be..c77ff60f22 100644 --- a/web/src/lib/components/admin-page/jobs/job-tile.svelte +++ b/web/src/lib/components/admin-page/jobs/job-tile.svelte @@ -51,7 +51,7 @@ let isIdle = $derived(!queueStatus.isActive && !queueStatus.isPaused); let multipleButtons = $derived(allText || refreshText); - const commonClasses = 'flex place-items-center justify-between w-full py-2 sm:py-4 pr-4 pl-6'; + const commonClasses = 'flex place-items-center justify-between w-full py-2 sm:py-4 pe-4 ps-6'; </script> <div @@ -110,7 +110,7 @@ <div class="mt-2 flex w-full max-w-md flex-col sm:flex-row"> <div - class="{commonClasses} rounded-t-lg bg-immich-primary text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray sm:rounded-l-lg sm:rounded-r-none" + class="{commonClasses} rounded-t-lg bg-immich-primary text-white dark:bg-immich-dark-primary dark:text-immich-dark-gray sm:rounded-s-lg sm:rounded-e-none" > <p>{$t('active')}</p> <p class="text-2xl"> @@ -119,7 +119,7 @@ </div> <div - class="{commonClasses} flex-row-reverse rounded-b-lg bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray sm:rounded-l-none sm:rounded-r-lg" + class="{commonClasses} flex-row-reverse rounded-b-lg bg-gray-200 text-immich-dark-bg dark:bg-gray-700 dark:text-immich-gray sm:rounded-s-none sm:rounded-e-lg" > <p class="text-2xl"> {waitingCount.toLocaleString($locale)} diff --git a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte index bb288511ac..8bae8fee4b 100644 --- a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte +++ b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte @@ -79,7 +79,7 @@ <span class="text-[#DCDADA] dark:text-[#525252]">{zeros(statsUsage)}</span><span class="text-immich-primary dark:text-immich-dark-primary">{statsUsage}</span > - <span class="my-auto ml-2 text-center text-base font-light text-gray-400">{statsUsageUnit}</span> + <span class="my-auto ms-2 text-center text-base font-light text-gray-400">{statsUsageUnit}</span> </div> </div> </div> @@ -88,7 +88,7 @@ <div> <p class="text-sm dark:text-immich-dark-fg">{$t('user_usage_detail').toUpperCase()}</p> - <table class="mt-5 w-full text-left"> + <table class="mt-5 w-full text-start"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > diff --git a/web/src/lib/components/admin-page/server-stats/stats-card.svelte b/web/src/lib/components/admin-page/server-stats/stats-card.svelte index 14d32c055f..b1804427e9 100644 --- a/web/src/lib/components/admin-page/server-stats/stats-card.svelte +++ b/web/src/lib/components/admin-page/server-stats/stats-card.svelte @@ -31,7 +31,7 @@ class="text-immich-primary dark:text-immich-dark-primary">{value}</span > {#if unit} - <span class="absolute -top-5 right-2 text-base font-light text-gray-400">{unit}</span> + <span class="absolute -top-5 end-2 text-base font-light text-gray-400">{unit}</span> {/if} </div> </div> diff --git a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte index 5380a76286..67da6bb7f2 100644 --- a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte +++ b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte @@ -76,13 +76,13 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" onsubmit={(e) => e.preventDefault()}> - <div class="ml-4 mt-4 flex flex-col"> + <div class="ms-4 mt-4 flex flex-col"> <SettingAccordion key="oauth" title={$t('admin.oauth_settings')} subtitle={$t('admin.oauth_settings_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <p class="text-sm dark:text-immich-dark-fg"> <FormatMessage key="admin.oauth_settings_more_details"> {#snippet children({ message })} @@ -243,8 +243,8 @@ title={$t('admin.password_settings')} subtitle={$t('admin.password_settings_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> - <div class="ml-4 mt-4 flex flex-col"> + <div class="ms-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col"> <SettingSwitch title={$t('admin.password_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte b/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte index 3ec477e29c..61f4cafe87 100644 --- a/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte +++ b/web/src/lib/components/admin-page/settings/backup-settings/backup-settings.svelte @@ -37,7 +37,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.backup_database_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte index 58c4be0ca0..bb9b41f8de 100644 --- a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte +++ b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte @@ -43,7 +43,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <p class="text-sm dark:text-immich-dark-fg"> <Icon path={mdiHelpCircleOutline} class="inline" size="15" /> <FormatMessage key="admin.transcoding_codecs_learn_more"> @@ -70,7 +70,7 @@ title={$t('admin.transcoding_policy')} subtitle={$t('admin.transcoding_policy_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSelect label={$t('admin.transcoding_transcode_policy')} {disabled} @@ -159,7 +159,7 @@ title={$t('admin.transcoding_encoding_options')} subtitle={$t('admin.transcoding_encoding_options_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSelect label={$t('admin.transcoding_video_codec')} {disabled} @@ -302,7 +302,7 @@ title={$t('admin.transcoding_hardware_acceleration')} subtitle={$t('admin.transcoding_hardware_acceleration_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSelect label={$t('admin.transcoding_acceleration_api')} {disabled} @@ -376,7 +376,7 @@ title={$t('advanced')} subtitle={$t('admin.transcoding_advanced_options_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingInputField inputType={SettingInputFieldType.NUMBER} label={$t('admin.transcoding_max_b_frames')} @@ -407,7 +407,7 @@ </SettingAccordion> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingButtonsRow onReset={(options) => onReset({ ...options, configKeys: ['ffmpeg'] })} onSave={() => onSave({ ffmpeg: config.ffmpeg })} diff --git a/web/src/lib/components/admin-page/settings/image/image-settings.svelte b/web/src/lib/components/admin-page/settings/image/image-settings.svelte index 9a66ad9c97..9a32e8e4e0 100644 --- a/web/src/lib/components/admin-page/settings/image/image-settings.svelte +++ b/web/src/lib/components/admin-page/settings/image/image-settings.svelte @@ -40,7 +40,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4"> + <div class="ms-4 mt-4"> <SettingAccordion key="thumbnail-settings" title={$t('admin.image_thumbnail_title')} @@ -195,7 +195,7 @@ </div> </div> - <div class="ml-4 mt-4"> + <div class="ms-4 mt-4"> <SettingButtonsRow onReset={(options) => onReset({ ...options, configKeys: ['image'] })} onSave={() => onSave({ image: config.image })} diff --git a/web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte b/web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte index 5a95dbea30..e9f54e7ee8 100644 --- a/web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte +++ b/web/src/lib/components/admin-page/settings/job-settings/job-settings.svelte @@ -47,7 +47,7 @@ <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> {#each jobNames as jobName (jobName)} - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> {#if isSystemConfigJobDto(jobName)} <SettingInputField inputType={SettingInputFieldType.NUMBER} @@ -71,7 +71,7 @@ </div> {/each} - <div class="ml-4"> + <div class="ms-4"> <SettingButtonsRow onReset={(options) => onReset({ ...options, configKeys: ['job'] })} onSave={() => onSave({ job: config.job })} diff --git a/web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte b/web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte index b1012c0287..390b167a54 100644 --- a/web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte +++ b/web/src/lib/components/admin-page/settings/library-settings/library-settings.svelte @@ -47,14 +47,14 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingAccordion key="library-watching" title={$t('admin.library_watching_settings')} subtitle={$t('admin.library_watching_settings_description')} isOpen={openByDefault} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.library_watching_enable_description')} {disabled} @@ -69,7 +69,7 @@ subtitle={$t('admin.library_scanning_description')} isOpen={openByDefault} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.library_scanning_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte index 29a1c65162..5538183442 100644 --- a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte +++ b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte @@ -27,7 +27,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.logging_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte b/web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte index 59bb798a0b..cd2684a3e3 100644 --- a/web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte +++ b/web/src/lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte @@ -51,7 +51,7 @@ {#if config.machineLearning.urls.length > 1} <CircleIconButton size="24" - class="ml-2" + class="ms-2" padding="2" color="red" title="" @@ -88,7 +88,7 @@ title={$t('admin.machine_learning_smart_search')} subtitle={$t('admin.machine_learning_smart_search_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.machine_learning_smart_search_enabled')} subtitle={$t('admin.machine_learning_smart_search_enabled_description')} @@ -124,7 +124,7 @@ title={$t('admin.machine_learning_duplicate_detection')} subtitle={$t('admin.machine_learning_duplicate_detection_setting_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.machine_learning_duplicate_detection_enabled')} subtitle={$t('admin.machine_learning_duplicate_detection_enabled_description')} @@ -154,7 +154,7 @@ title={$t('admin.machine_learning_facial_recognition')} subtitle={$t('admin.machine_learning_facial_recognition_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.machine_learning_facial_recognition_setting')} subtitle={$t('admin.machine_learning_facial_recognition_setting_description')} diff --git a/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte b/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte index 4a4b23ded2..7046196c31 100644 --- a/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte +++ b/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte @@ -32,7 +32,7 @@ <form autocomplete="off" {onsubmit}> <div class="flex flex-col gap-4"> <SettingAccordion key="map" title={$t('admin.map_settings')} subtitle={$t('admin.map_settings_description')}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.map_enable_description')} subtitle={$t('admin.map_implications')} @@ -78,7 +78,7 @@ </FormatMessage> </p> {/snippet} - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.map_reverse_geocoding_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/metadata-settings/metadata-settings.svelte b/web/src/lib/components/admin-page/settings/metadata-settings/metadata-settings.svelte index 1ba82b2eb9..c5d3860ecd 100644 --- a/web/src/lib/components/admin-page/settings/metadata-settings/metadata-settings.svelte +++ b/web/src/lib/components/admin-page/settings/metadata-settings/metadata-settings.svelte @@ -26,7 +26,7 @@ <div class="mt-2"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit} class="mx-4 mt-4"> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.metadata_faces_import_setting')} subtitle={$t('admin.metadata_faces_import_setting_description')} diff --git a/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte b/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte index 1a6f0ab866..eb032a6115 100644 --- a/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte +++ b/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte @@ -26,7 +26,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4"> + <div class="ms-4 mt-4"> <SettingSwitch title={$t('admin.version_check_enabled_description')} subtitle={$t('admin.version_check_implications')} diff --git a/web/src/lib/components/admin-page/settings/notification-settings/notification-settings.svelte b/web/src/lib/components/admin-page/settings/notification-settings/notification-settings.svelte index 24e672607d..e3bd413900 100644 --- a/web/src/lib/components/admin-page/settings/notification-settings/notification-settings.svelte +++ b/web/src/lib/components/admin-page/settings/notification-settings/notification-settings.svelte @@ -80,7 +80,7 @@ <form autocomplete="off" {onsubmit} class="mt-4"> <div class="flex flex-col gap-4"> <SettingAccordion key="email" title={$t('email')} subtitle={$t('admin.notification_email_setting_description')}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.notification_enable_email_notifications')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/server/server-settings.svelte b/web/src/lib/components/admin-page/settings/server/server-settings.svelte index b9134d1e50..8a1ff807f3 100644 --- a/web/src/lib/components/admin-page/settings/server/server-settings.svelte +++ b/web/src/lib/components/admin-page/settings/server/server-settings.svelte @@ -28,7 +28,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="mt-4 ml-4"> + <div class="mt-4 ms-4"> <SettingInputField inputType={SettingInputFieldType.TEXT} label={$t('admin.server_external_domain_settings')} @@ -52,7 +52,7 @@ bind:checked={config.server.publicUsers} /> - <div class="ml-4"> + <div class="ms-4"> <SettingButtonsRow onReset={(options) => onReset({ ...options, configKeys: ['server'] })} onSave={() => onSave({ server: config.server })} diff --git a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte index 67299d8f6b..efc42bf8b7 100644 --- a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte +++ b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte @@ -141,7 +141,7 @@ </p> </div> {#await getTemplateOptions() then} - <div id="directory-path-builder" class="flex flex-col gap-4 {minified ? '' : 'ml-4 mt-4'}"> + <div id="directory-path-builder" class="flex flex-col gap-4 {minified ? '' : 'ms-4 mt-4'}"> <SettingSwitch title={$t('admin.storage_template_enable_description')} {disabled} diff --git a/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte b/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte index 06d8196935..a294eb1768 100644 --- a/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte +++ b/web/src/lib/components/admin-page/settings/template-settings/template-settings.svelte @@ -76,7 +76,7 @@ title={$t('admin.template_email_settings')} subtitle={$t('admin.template_settings_description')} > - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <p class="text-sm dark:text-immich-dark-fg"> <FormatMessage key="admin.template_email_if_empty"> {$t('admin.template_email_if_empty')} @@ -102,7 +102,7 @@ onclick={() => getTemplate(templateName, config.templates.email[templateKey])} title={$t('admin.template_email_preview')} > - <Icon path={mdiEyeOutline} class="mr-1" /> + <Icon path={mdiEyeOutline} class="me-1" /> {$t('admin.template_email_preview')} </Button> </div> diff --git a/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte b/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte index 79b5f838e3..64b4b92b5e 100644 --- a/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte +++ b/web/src/lib/components/admin-page/settings/theme/theme-settings.svelte @@ -26,7 +26,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingTextarea {disabled} label={$t('admin.theme_custom_css_settings')} diff --git a/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte b/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte index 05979bf9f0..f0f18f5d95 100644 --- a/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte +++ b/web/src/lib/components/admin-page/settings/trash-settings/trash-settings.svelte @@ -28,7 +28,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingSwitch title={$t('admin.trash_enabled_description')} {disabled} bind:checked={config.trash.enabled} /> <hr /> diff --git a/web/src/lib/components/admin-page/settings/user-settings/user-settings.svelte b/web/src/lib/components/admin-page/settings/user-settings/user-settings.svelte index f96c3808a8..422e1ebe49 100644 --- a/web/src/lib/components/admin-page/settings/user-settings/user-settings.svelte +++ b/web/src/lib/components/admin-page/settings/user-settings/user-settings.svelte @@ -24,7 +24,7 @@ <div> <div in:fade={{ duration: 500 }}> <form autocomplete="off" onsubmit={(e) => e.preventDefault()}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingInputField inputType={SettingInputFieldType.NUMBER} min={1} @@ -35,7 +35,7 @@ /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingButtonsRow onReset={(options) => onReset({ ...options, configKeys: ['user'] })} onSave={() => onSave({ user: config.user })} diff --git a/web/src/lib/components/album-page/album-card-group.svelte b/web/src/lib/components/album-page/album-card-group.svelte index 9b2aa11552..3556d9fea4 100644 --- a/web/src/lib/components/album-page/album-card-group.svelte +++ b/web/src/lib/components/album-page/album-card-group.svelte @@ -48,7 +48,7 @@ <button type="button" onclick={() => toggleAlbumGroupCollapsing(group.id)} - class="w-full text-left mt-2 pt-2 pr-2 pb-2 rounded-md transition-colors cursor-pointer dark:text-immich-dark-fg hover:text-immich-primary dark:hover:text-immich-dark-primary hover:bg-immich-gray dark:hover:bg-immich-dark-gray" + class="w-full text-start mt-2 pt-2 pe-2 pb-2 rounded-md transition-colors cursor-pointer dark:text-immich-dark-fg hover:text-immich-primary dark:hover:text-immich-dark-primary hover:bg-immich-gray dark:hover:bg-immich-dark-gray" aria-expanded={!isCollapsed} > <Icon @@ -57,7 +57,7 @@ class="inline-block -mt-2.5 transition-all duration-[250ms] {iconRotation}" /> <span class="font-bold text-3xl text-black dark:text-white">{group.name}</span> - <span class="ml-1.5">({$t('albums_count', { values: { count: albums.length } })})</span> + <span class="ms-1.5">({$t('albums_count', { values: { count: albums.length } })})</span> </button> <hr class="dark:border-immich-dark-gray" /> </div> diff --git a/web/src/lib/components/album-page/album-card.svelte b/web/src/lib/components/album-page/album-card.svelte index cec4919e4e..06ec030bea 100644 --- a/web/src/lib/components/album-page/album-card.svelte +++ b/web/src/lib/components/album-page/album-card.svelte @@ -40,7 +40,7 @@ {#if onShowContextMenu} <div id="icon-{album.id}" - class="absolute right-6 top-6 z-10 opacity-0 group-hover:opacity-100 focus-within:opacity-100" + class="absolute end-6 top-6 z-10 opacity-0 group-hover:opacity-100 focus-within:opacity-100" data-testid="context-button-parent" > <CircleIconButton diff --git a/web/src/lib/components/album-page/album-viewer.svelte b/web/src/lib/components/album-page/album-viewer.svelte index ea9e7e3dd1..09ec67e92b 100644 --- a/web/src/lib/components/album-page/album-viewer.svelte +++ b/web/src/lib/components/album-page/album-viewer.svelte @@ -117,7 +117,7 @@ <!-- ALBUM DESCRIPTION --> {#if album.description} <p - class="whitespace-pre-line mb-12 mt-6 w-full pb-2 text-left font-medium text-base text-black dark:text-gray-300" + class="whitespace-pre-line mb-12 mt-6 w-full pb-2 text-start font-medium text-base text-black dark:text-gray-300" > {album.description} </p> diff --git a/web/src/lib/components/album-page/albums-table-row.svelte b/web/src/lib/components/album-page/albums-table-row.svelte index c900930f8a..034ed62010 100644 --- a/web/src/lib/components/album-page/albums-table-row.svelte +++ b/web/src/lib/components/album-page/albums-table-row.svelte @@ -35,13 +35,13 @@ onclick={() => goto(`${AppRoute.ALBUMS}/${album.id}`)} {oncontextmenu} > - <td class="text-md text-ellipsis text-left w-8/12 sm:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%] items-center"> + <td class="text-md text-ellipsis text-start w-8/12 sm:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%] items-center"> {album.albumName} {#if album.shared} <Icon path={mdiShareVariantOutline} size="16" - class="inline ml-1 opacity-70" + class="inline ms-1 opacity-70" title={album.ownerId === $user.id ? $t('shared_by_you') : $t('shared_by_user', { values: { user: album.owner.name } })} diff --git a/web/src/lib/components/album-page/albums-table.svelte b/web/src/lib/components/album-page/albums-table.svelte index bd7c7fd7f5..9f51f9a19a 100644 --- a/web/src/lib/components/album-page/albums-table.svelte +++ b/web/src/lib/components/album-page/albums-table.svelte @@ -24,7 +24,7 @@ let { groupedAlbums, albumGroupOption = AlbumGroupBy.None, onShowContextMenu }: Props = $props(); </script> -<table class="mt-2 w-full text-left"> +<table class="mt-2 w-full text-start"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -48,18 +48,18 @@ class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg" > <tr - class="flex w-full place-items-center p-2 md:pl-5 md:pr-5 md:pt-3 md:pb-3" + class="flex w-full place-items-center p-2 md:ps-5 md:pe-5 md:pt-3 md:pb-3" onclick={() => toggleAlbumGroupCollapsing(albumGroup.id)} aria-expanded={!isCollapsed} > - <td class="text-md text-left -mb-1"> + <td class="text-md text-start -mb-1"> <Icon path={mdiChevronRight} size="20" class="inline-block -mt-2 transition-all duration-[250ms] {iconRotation}" /> <span class="font-bold text-2xl">{albumGroup.name}</span> - <span class="ml-1.5"> + <span class="ms-1.5"> ({$t('albums_count', { values: { count: albumGroup.albums.length } })}) </span> </td> diff --git a/web/src/lib/components/album-page/user-selection-modal.svelte b/web/src/lib/components/album-page/user-selection-modal.svelte index 1496c1ce66..9ee7cc550d 100644 --- a/web/src/lib/components/album-page/user-selection-modal.svelte +++ b/web/src/lib/components/album-page/user-selection-modal.svelte @@ -94,7 +94,7 @@ </div> <!-- <UserAvatar {user} size="md" /> --> - <div class="text-left flex-grow"> + <div class="text-start flex-grow"> <p class="text-immich-fg dark:text-immich-dark-fg"> {user.name} </p> @@ -136,7 +136,7 @@ class="flex w-full place-items-center gap-4 p-4" > <UserAvatar {user} size="md" /> - <div class="text-left flex-grow"> + <div class="text-start flex-grow"> <p class="text-immich-fg dark:text-immich-dark-fg"> {user.name} </p> diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index caa1ced290..94b66d4c22 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -186,7 +186,7 @@ > {#each reactions as reaction, index (reaction.id)} {#if reaction.type === ReactionType.Comment} - <div class="flex dark:bg-gray-800 bg-gray-200 py-3 pl-3 mt-3 rounded-lg gap-4 justify-start"> + <div class="flex dark:bg-gray-800 bg-gray-200 py-3 ps-3 mt-3 rounded-lg gap-4 justify-start"> <div class="flex items-center"> <UserAvatar user={reaction.user} size="sm" /> </div> @@ -202,7 +202,7 @@ </a> {/if} {#if reaction.user.id === user.id || albumOwnerId === user.id} - <div class="mr-4"> + <div class="me-4"> <ButtonContextMenu icon={mdiDotsVertical} title={$t('comment_options')} @@ -231,7 +231,7 @@ {/if} {:else if reaction.type === ReactionType.Like} <div class="relative"> - <div class="flex py-3 pl-3 mt-3 gap-4 items-center text-sm"> + <div class="flex py-3 ps-3 mt-3 gap-4 items-center text-sm"> <div class="text-red-600"><Icon path={mdiHeart} size={20} /></div> <div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}> @@ -255,7 +255,7 @@ </a> {/if} {#if reaction.user.id === user.id || albumOwnerId === user.id} - <div class="mr-4"> + <div class="me-4"> <ButtonContextMenu icon={mdiDotsVertical} title={$t('reaction_options')} @@ -307,17 +307,17 @@ }} class="h-[18px] {disabled ? 'cursor-not-allowed' - : ''} w-full max-h-56 pr-2 items-center overflow-y-auto leading-4 outline-none resize-none bg-gray-200" + : ''} w-full max-h-56 pe-2 items-center overflow-y-auto leading-4 outline-none resize-none bg-gray-200" ></textarea> </div> {#if isSendingMessage} - <div class="flex items-end place-items-center pb-2 ml-0"> + <div class="flex items-end place-items-center pb-2 ms-0"> <div class="flex w-full place-items-center"> <LoadingSpinner /> </div> </div> {:else if message} - <div class="flex items-end w-fit ml-0"> + <div class="flex items-end w-fit ms-0"> <CircleIconButton title={$t('send_message')} size="15" diff --git a/web/src/lib/components/asset-viewer/album-list-item.svelte b/web/src/lib/components/asset-viewer/album-list-item.svelte index 1d7ee2971a..6c50ecbc1d 100644 --- a/web/src/lib/components/asset-viewer/album-list-item.svelte +++ b/web/src/lib/components/asset-viewer/album-list-item.svelte @@ -43,7 +43,7 @@ type="button" onclick={onAlbumClick} use:scrollIntoViewIfSelected - class="flex w-full gap-4 px-6 py-2 text-left transition-colors hover:bg-gray-200 dark:hover:bg-gray-700 rounded-xl" + class="flex w-full gap-4 px-6 py-2 text-start transition-colors hover:bg-gray-200 dark:hover:bg-gray-700 rounded-xl" class:bg-gray-200={selected} class:dark:bg-gray-700={selected} > diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 91461d574d..98bc087f71 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -422,7 +422,7 @@ <section id="immich-asset-viewer" - class="fixed left-0 top-0 z-[1001] grid size-full grid-cols-4 grid-rows-[64px_1fr] overflow-hidden bg-black" + class="fixed start-0 top-0 z-[1001] grid size-full grid-cols-4 grid-rows-[64px_1fr] overflow-hidden bg-black" use:focusTrap > <!-- Top navigation bar --> @@ -547,7 +547,7 @@ /> {/if} {#if $slideshowState === SlideshowState.None && isShared && ((album && album.isActivityEnabled) || numberOfComments > 0)} - <div class="z-[9999] absolute bottom-0 right-0 mb-20 mr-8"> + <div class="z-[9999] absolute bottom-0 end-0 mb-20 me-8"> <ActivityStatus disabled={!album?.isActivityEnabled} {isLiked} @@ -571,7 +571,7 @@ <div transition:fly={{ duration: 150 }} id="detail-panel" - class="z-[1002] row-start-1 row-span-4 w-[360px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg" + class="z-[1002] row-start-1 row-span-4 w-[360px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg" translate="yes" > <DetailPanel {asset} currentAlbum={album} albums={appearsInAlbums} onClose={() => ($isShowDetail = false)} /> @@ -582,7 +582,7 @@ <div transition:fly={{ duration: 150 }} id="editor-panel" - class="z-[1002] row-start-1 row-span-4 w-[400px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg" + class="z-[1002] row-start-1 row-span-4 w-[400px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg" translate="yes" > <EditorPanel {asset} onUpdateSelectedType={handleUpdateSelectedEditType} onClose={closeEditor} /> @@ -631,7 +631,7 @@ <div transition:fly={{ duration: 150 }} id="activity-panel" - class="z-[1002] row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg" + class="z-[1002] row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg" translate="yes" > <ActivityViewer diff --git a/web/src/lib/components/asset-viewer/detail-panel-location.svelte b/web/src/lib/components/asset-viewer/detail-panel-location.svelte index 9e59243aa1..42cbefadf1 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-location.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-location.svelte @@ -33,7 +33,7 @@ {#if asset.exifInfo?.country} <button type="button" - class="flex w-full text-left justify-between place-items-start gap-4 py-4" + class="flex w-full text-start justify-between place-items-start gap-4 py-4" onclick={() => (isOwner ? (isShowChangeLocation = true) : null)} title={isOwner ? $t('edit_location') : ''} class:hover:dark:text-immich-dark-primary={isOwner} @@ -68,7 +68,7 @@ {:else if !asset.exifInfo?.city && isOwner} <button type="button" - class="flex w-full text-left justify-between place-items-start gap-4 py-4 rounded-lg hover:dark:text-immich-dark-primary hover:text-immich-primary" + class="flex w-full text-start justify-between place-items-start gap-4 py-4 rounded-lg hover:dark:text-immich-dark-primary hover:text-immich-primary" onclick={() => (isShowChangeLocation = true)} title={$t('add_location')} > diff --git a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte index 39ca096efd..592279e353 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte @@ -50,7 +50,7 @@ {#each tags as tag (tag.id)} <div class="flex group transition-all"> <a - class="inline-block h-min whitespace-nowrap pl-3 pr-1 group-hover:pl-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 rounded-tl-full rounded-bl-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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" href={encodeURI(`${AppRoute.TAGS}/?path=${tag.value}`)} > <p class="text-sm"> @@ -60,7 +60,7 @@ <button type="button" - class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-tr-full rounded-br-full place-items-center place-content-center pr-2 pl-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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(tag.id)} > diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index b96a4660ee..5ef0ac0d73 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -296,7 +296,7 @@ {#if dateTime} <button type="button" - class="flex w-full text-left justify-between place-items-start gap-4 py-4" + class="flex w-full text-start justify-between place-items-start gap-4 py-4" onclick={() => (isOwner ? (isShowChangeDate = true) : null)} title={isOwner ? $t('edit_date') : ''} class:hover:dark:text-immich-dark-primary={isOwner} diff --git a/web/src/lib/components/asset-viewer/download-panel.svelte b/web/src/lib/components/asset-viewer/download-panel.svelte index 80a14a5ac3..27e48b0d28 100644 --- a/web/src/lib/components/asset-viewer/download-panel.svelte +++ b/web/src/lib/components/asset-viewer/download-panel.svelte @@ -16,14 +16,14 @@ {#if downloadStore.isDownloading} <div transition:fly={{ x: -100, duration: 350 }} - class="fixed bottom-10 left-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border bg-immich-bg p-4 text-sm shadow-sm" + class="fixed bottom-10 start-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border bg-immich-bg p-4 text-sm shadow-sm" > <p class="mb-2 text-xs text-gray-500">{$t('downloading').toUpperCase()}</p> <div class="my-2 mb-2 flex max-h-[200px] flex-col overflow-y-auto text-sm"> {#each Object.keys(downloadStore.assets) as downloadKey (downloadKey)} {@const download = downloadStore.assets[downloadKey]} <div class="mb-2 flex place-items-center" transition:slide> - <div class="w-full pr-10"> + <div class="w-full pe-10"> <div class="flex place-items-center justify-between gap-2 text-xs font-medium"> <p class="truncate">■ {downloadKey}</p> {#if download.total} @@ -41,7 +41,7 @@ </p> </div> </div> - <div class="absolute right-2"> + <div class="absolute end-2"> <CircleIconButton title={$t('close')} onclick={() => abort(downloadKey, download)} diff --git a/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte b/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte index c50c21bef8..5c50f230cc 100644 --- a/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte +++ b/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte @@ -308,13 +308,13 @@ }; </script> -<div class="absolute left-0 top-0"> - <canvas bind:this={canvasEl} id="face-editor" class="absolute top-0 left-0"></canvas> +<div class="absolute start-0 top-0"> + <canvas bind:this={canvasEl} id="face-editor" class="absolute top-0 start-0"></canvas> <div id="face-selector" bind:this={faceSelectorEl} - class="absolute top-[calc(50%-250px)] left-[calc(50%-125px)] max-w-[250px] w-[250px] bg-white dark:bg-immich-dark-gray dark:text-immich-dark-fg backdrop-blur-sm px-2 py-4 rounded-xl border border-gray-200 dark:border-gray-800" + class="absolute top-[calc(50%-250px)] start-[calc(50%-125px)] max-w-[250px] w-[250px] bg-white dark:bg-immich-dark-gray dark:text-immich-dark-fg backdrop-blur-sm px-2 py-4 rounded-xl border border-gray-200 dark:border-gray-800" > <p class="text-center text-sm">Select a person to tag</p> @@ -329,7 +329,7 @@ <button onclick={() => tagFace(person)} type="button" - class="w-full flex place-items-center gap-2 rounded-lg pl-1 pr-4 py-2 hover:bg-immich-primary/25" + class="w-full flex place-items-center gap-2 rounded-lg ps-1 pe-4 py-2 hover:bg-immich-primary/25" > <ImageThumbnail curve diff --git a/web/src/lib/components/asset-viewer/photo-viewer.svelte b/web/src/lib/components/asset-viewer/photo-viewer.svelte index d3a9da3633..fdb986786e 100644 --- a/web/src/lib/components/asset-viewer/photo-viewer.svelte +++ b/web/src/lib/components/asset-viewer/photo-viewer.svelte @@ -213,7 +213,7 @@ <img src={assetFileUrl} alt={$getAltText(asset)} - class="absolute top-0 left-0 -z-10 object-cover h-full w-full blur-lg" + class="absolute top-0 start-0 -z-10 object-cover h-full w-full blur-lg" draggable="false" /> {/if} diff --git a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte index 55357abbc0..2e8ad6ca32 100644 --- a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte @@ -101,7 +101,7 @@ {/if} {#if hidden} - <div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform"> + <div class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform"> <Icon {title} path={mdiEyeOffOutline} size="2em" class={hiddenIconClass} /> </div> {/if} diff --git a/web/src/lib/components/assets/thumbnail/thumbnail.svelte b/web/src/lib/components/assets/thumbnail/thumbnail.svelte index c21acd8f86..eba10317aa 100644 --- a/web/src/lib/components/assets/thumbnail/thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/thumbnail.svelte @@ -332,20 +332,20 @@ <!-- Favorite asset star --> {#if !isSharedLink() && asset.isFavorite} - <div class="absolute bottom-2 left-2 z-10"> + <div class="absolute bottom-2 start-2 z-10"> <Icon path={mdiHeart} size="24" class="text-white" /> </div> {/if} {#if !isSharedLink() && showArchiveIcon && asset.isArchived} - <div class={['absolute left-2 z-10', asset.isFavorite ? 'bottom-10' : 'bottom-2']}> + <div class={['absolute start-2 z-10', asset.isFavorite ? 'bottom-10' : 'bottom-2']}> <Icon path={mdiArchiveArrowDownOutline} size="24" class="text-white" /> </div> {/if} {#if asset.type === AssetTypeEnum.Image && asset.exifInfo?.projectionType === ProjectionType.EQUIRECTANGULAR} - <div class="absolute right-0 top-0 z-10 flex place-items-center gap-1 text-xs font-medium text-white"> - <span class="pr-2 pt-2"> + <div class="absolute end-0 top-0 z-10 flex place-items-center gap-1 text-xs font-medium text-white"> + <span class="pe-2 pt-2"> <Icon path={mdiRotate360} size="24" /> </span> </div> @@ -356,10 +356,10 @@ <div class={[ 'absolute z-10 flex place-items-center gap-1 text-xs font-medium text-white', - asset.type == AssetTypeEnum.Image && !asset.livePhotoVideoId ? 'top-0 right-0' : 'top-7 right-1', + asset.type == AssetTypeEnum.Image && !asset.livePhotoVideoId ? 'top-0 end-0' : 'top-7 end-1', ]} > - <span class="pr-2 pt-2 flex place-items-center gap-1"> + <span class="pe-2 pt-2 flex place-items-center gap-1"> <p>{asset.stack.assetCount.toLocaleString($locale)}</p> <Icon path={mdiCameraBurst} size="24" /> </span> diff --git a/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte index fc3cb2e951..9959c86548 100644 --- a/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte @@ -55,7 +55,7 @@ }; </script> -<div class="absolute right-0 top-0 z-20 flex place-items-center gap-1 text-xs font-medium text-white"> +<div class="absolute end-0 top-0 z-20 flex place-items-center gap-1 text-xs font-medium text-white"> {#if showTime} <span class="pt-2"> {#if remainingSeconds < 60} @@ -69,7 +69,7 @@ {/if} <!-- svelte-ignore a11y_no_static_element_interactions --> - <span class="pr-2 pt-2" onmouseenter={onMouseEnter} onmouseleave={onMouseLeave}> + <span class="pe-2 pt-2" onmouseenter={onMouseEnter} onmouseleave={onMouseLeave}> {#if enablePlayback} {#if loading} <LoadingSpinner /> diff --git a/web/src/lib/components/elements/buttons/button.svelte b/web/src/lib/components/elements/buttons/button.svelte index 991bbaecee..ac7d9808f3 100644 --- a/web/src/lib/components/elements/buttons/button.svelte +++ b/web/src/lib/components/elements/buttons/button.svelte @@ -79,7 +79,7 @@ }; const sizeClasses: Record<Size, string> = { - tiny: 'p-0 ml-2 mr-0 align-top', + tiny: 'p-0 ms-2 me-0 align-top', icon: 'p-2.5', link: 'p-2 font-medium', sm: 'px-4 py-2 text-sm font-medium', diff --git a/web/src/lib/components/elements/buttons/skip-link.svelte b/web/src/lib/components/elements/buttons/skip-link.svelte index a1a24634c4..40b1b9c526 100644 --- a/web/src/lib/components/elements/buttons/skip-link.svelte +++ b/web/src/lib/components/elements/buttons/skip-link.svelte @@ -50,7 +50,7 @@ }; </script> -<div class="absolute z-50 top-2 left-2 transition-transform {isFocused ? 'translate-y-0' : '-translate-y-10 sr-only'}"> +<div class="absolute z-50 top-2 start-2 transition-transform {isFocused ? 'translate-y-0' : '-translate-y-10 sr-only'}"> <Button size="sm" rounded="none" diff --git a/web/src/lib/components/elements/dropdown.svelte b/web/src/lib/components/elements/dropdown.svelte index 52360f04de..3966ea8310 100644 --- a/web/src/lib/components/elements/dropdown.svelte +++ b/web/src/lib/components/elements/dropdown.svelte @@ -82,10 +82,10 @@ const getAlignClass = (position: 'bottom-left' | 'bottom-right') => { switch (position) { case 'bottom-left': { - return 'left-0'; + return 'start-0'; } case 'bottom-right': { - return 'right-0'; + return 'end-0'; } default: { diff --git a/web/src/lib/components/faces-page/edit-name-input.svelte b/web/src/lib/components/faces-page/edit-name-input.svelte index ebb44c4008..a5d0fdd757 100644 --- a/web/src/lib/components/faces-page/edit-name-input.svelte +++ b/web/src/lib/components/faces-page/edit-name-input.svelte @@ -35,7 +35,7 @@ : 'rounded-lg'} bg-gray-100 p-2 dark:bg-gray-700 border border-gray-200 dark:border-immich-dark-gray" > <ImageThumbnail circle shadow url={thumbnailData} altText={person.name} widthStyle="2rem" heightStyle="2rem" /> - <form class="ml-4 flex w-full justify-between gap-16" autocomplete="off" {onsubmit}> + <form class="ms-4 flex w-full justify-between gap-16" autocomplete="off" {onsubmit}> <SearchPeople bind:searchName={name} bind:searchedPeopleLocal={suggestedPeople} diff --git a/web/src/lib/components/faces-page/face-thumbnail.svelte b/web/src/lib/components/faces-page/face-thumbnail.svelte index cc3fffe5d7..196777f0af 100644 --- a/web/src/lib/components/faces-page/face-thumbnail.svelte +++ b/web/src/lib/components/faces-page/face-thumbnail.svelte @@ -44,7 +44,7 @@ </div> <div - class="absolute left-0 top-0 h-full w-full bg-immich-primary/30 opacity-0" + class="absolute start-0 top-0 h-full w-full bg-immich-primary/30 opacity-0" class:hover:opacity-100={selectable} class:rounded-full={circle} class:rounded-lg={!circle} @@ -52,7 +52,7 @@ {#if selected} <div - class="absolute left-0 top-0 h-full w-full bg-blue-500/80" + class="absolute start-0 top-0 h-full w-full bg-blue-500/80" class:rounded-full={circle} class:rounded-lg={!circle} ></div> @@ -60,7 +60,7 @@ {#if person.name} <span - class="w-100 text-white-shadow absolute bottom-2 left-0 w-full text-ellipsis px-1 text-center font-medium text-white hover:cursor-pointer" + class="w-100 text-white-shadow absolute bottom-2 start-0 w-full text-ellipsis px-1 text-center font-medium text-white hover:cursor-pointer" > {person.name} </span> diff --git a/web/src/lib/components/faces-page/manage-people-visibility.svelte b/web/src/lib/components/faces-page/manage-people-visibility.svelte index 0c2ed7bad0..c3c75d495b 100644 --- a/web/src/lib/components/faces-page/manage-people-visibility.svelte +++ b/web/src/lib/components/faces-page/manage-people-visibility.svelte @@ -117,12 +117,12 @@ <div class="flex items-center"> <CircleIconButton title={$t('close')} icon={mdiClose} onclick={onClose} /> <div class="flex gap-2 items-center"> - <p id={titleId} class="ml-2">{$t('show_and_hide_people')}</p> + <p id={titleId} class="ms-2">{$t('show_and_hide_people')}</p> <p class="text-sm text-gray-400 dark:text-gray-600">({totalPeopleCount.toLocaleString($locale)})</p> </div> </div> <div class="flex items-center justify-end"> - <div class="flex items-center md:mr-4"> + <div class="flex items-center md:me-4"> <CircleIconButton title={$t('reset_people_visibility')} icon={mdiRestart} onclick={handleResetVisibility} /> <CircleIconButton title={toggleButton.label} icon={toggleButton.icon} onclick={handleToggleVisibility} /> </div> @@ -154,7 +154,7 @@ hiddenIconClass="text-white group-hover:text-black transition-colors" /> {#if person.name} - <span class="absolute bottom-2 left-0 w-full select-text px-1 text-center font-medium text-white"> + <span class="absolute bottom-2 start-0 w-full select-text px-1 text-center font-medium text-white"> {person.name} </span> {/if} diff --git a/web/src/lib/components/faces-page/merge-face-selector.svelte b/web/src/lib/components/faces-page/merge-face-selector.svelte index 88576d2845..c2c1c65647 100644 --- a/web/src/lib/components/faces-page/merge-face-selector.svelte +++ b/web/src/lib/components/faces-page/merge-face-selector.svelte @@ -99,7 +99,7 @@ <section transition:fly={{ y: 500, duration: 100, easing: quintOut }} - class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" + class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" > <ControlAppBar onClose={onBack}> {#snippet leading()} @@ -113,7 +113,7 @@ {#snippet trailing()} <Button size="sm" disabled={!hasSelection} onclick={handleMerge}> <Icon path={mdiMerge} size={18} /> - <span class="ml-2">{$t('merge')}</span></Button + <span class="ms-2">{$t('merge')}</span></Button > {/snippet} </ControlAppBar> diff --git a/web/src/lib/components/faces-page/people-card.svelte b/web/src/lib/components/faces-page/people-card.svelte index 4aff4e96f8..b740953340 100644 --- a/web/src/lib/components/faces-page/people-card.svelte +++ b/web/src/lib/components/faces-page/people-card.svelte @@ -54,7 +54,7 @@ circle /> {#if person.isFavorite} - <div class="absolute top-4 left-4"> + <div class="absolute top-4 start-4"> <Icon path={mdiHeart} size="24" class="text-white" /> </div> {/if} @@ -62,7 +62,7 @@ </a> {#if showVerticalDots} - <div class="absolute top-2 right-2"> + <div class="absolute top-2 end-2"> <ButtonContextMenu buttonClass="icon-white-drop-shadow focus:opacity-100 {showVerticalDots ? 'opacity-100' : 'opacity-0'}" color="opaque" diff --git a/web/src/lib/components/faces-page/person-side-panel.svelte b/web/src/lib/components/faces-page/person-side-panel.svelte index 73c3ea7ae5..5e8b35c74b 100644 --- a/web/src/lib/components/faces-page/person-side-panel.svelte +++ b/web/src/lib/components/faces-page/person-side-panel.svelte @@ -227,7 +227,7 @@ <div role="button" tabindex={index} - class="absolute left-0 top-0 h-[90px] w-[90px] cursor-default" + class="absolute start-0 top-0 h-[90px] w-[90px] cursor-default" onfocus={() => ($boundingBoxesArray = [peopleWithFaces[index]])} onmouseover={() => ($boundingBoxesArray = [peopleWithFaces[index]])} onmouseleave={() => ($boundingBoxesArray = [])} @@ -303,7 +303,7 @@ </p> {/if} - <div class="absolute -right-[5px] -top-[5px] h-[20px] w-[20px] rounded-full"> + <div class="absolute -end-[5px] -top-[5px] h-[20px] w-[20px] rounded-full"> {#if selectedPersonToCreate[face.id] || selectedPersonToReassign[face.id]} <CircleIconButton color="primary" @@ -311,7 +311,7 @@ title={$t('reset')} size="18" padding="1" - class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" + class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" onclick={() => handleReset(face.id)} /> {:else} @@ -321,29 +321,29 @@ title={$t('select_new_face')} size="18" padding="1" - class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" + class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" onclick={() => handleFacePicker(face)} /> {/if} </div> - <div class="absolute right-[25px] -top-[5px] h-[20px] w-[20px] rounded-full"> + <div class="absolute end-[25px] -top-[5px] h-[20px] w-[20px] rounded-full"> {#if !selectedPersonToCreate[face.id] && !selectedPersonToReassign[face.id] && !face.person} <div - class="flex place-content-center place-items-center rounded-full bg-[#d3d3d3] p-1 transition-all absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" + class="flex place-content-center place-items-center rounded-full bg-[#d3d3d3] p-1 transition-all absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" > <Icon color="primary" path={mdiAccountOff} ariaHidden size="18" /> </div> {/if} </div> {#if face.person != null} - <div class="absolute -right-[5px] top-[25px] h-[20px] w-[20px] rounded-full"> + <div class="absolute -end-[5px] top-[25px] h-[20px] w-[20px] rounded-full"> <CircleIconButton color="red" icon={mdiTrashCan} title={$t('delete_face')} size="18" padding="1" - class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" + class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" onclick={() => deleteAssetFace(face)} /> </div> diff --git a/web/src/lib/components/faces-page/unmerge-face-selector.svelte b/web/src/lib/components/faces-page/unmerge-face-selector.svelte index e808c98748..41c584d602 100644 --- a/web/src/lib/components/faces-page/unmerge-face-selector.svelte +++ b/web/src/lib/components/faces-page/unmerge-face-selector.svelte @@ -120,7 +120,7 @@ <section transition:fly={{ y: 500, duration: 100, easing: quintOut }} - class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" + class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" > <ControlAppBar {onClose}> {#snippet leading()} @@ -140,7 +140,7 @@ {:else} <LoadingSpinner /> {/if} - <span class="ml-2"> {$t('create_new_person')}</span></Button + <span class="ms-2"> {$t('create_new_person')}</span></Button > <Button size="sm" @@ -155,7 +155,7 @@ {:else} <LoadingSpinner /> {/if} - <span class="ml-2"> {$t('reassign')}</span></Button + <span class="ms-2"> {$t('reassign')}</span></Button > </div> {/snippet} diff --git a/web/src/lib/components/forms/library-import-paths-form.svelte b/web/src/lib/components/forms/library-import-paths-form.svelte index 639b81071f..64c32532ef 100644 --- a/web/src/lib/components/forms/library-import-paths-form.svelte +++ b/web/src/lib/components/forms/library-import-paths-form.svelte @@ -173,7 +173,7 @@ {/if} <form {onsubmit} autocomplete="off" class="m-4 flex flex-col gap-4"> - <table class="text-left"> + <table class="text-start"> <tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray"> {#each validatedPaths as validatedPath, listIndex (validatedPath.importPath)} <tr @@ -183,7 +183,7 @@ : 'bg-immich-bg dark:bg-immich-dark-gray/50' }`} > - <td class="w-1/8 text-ellipsis pl-8 text-sm"> + <td class="w-1/8 text-ellipsis ps-8 text-sm"> {#if validatedPath.isValid} <Icon path={mdiCheckCircleOutline} diff --git a/web/src/lib/components/forms/library-scan-settings-form.svelte b/web/src/lib/components/forms/library-scan-settings-form.svelte index 0ce414c10d..7a021a1c0c 100644 --- a/web/src/lib/components/forms/library-scan-settings-form.svelte +++ b/web/src/lib/components/forms/library-scan-settings-form.svelte @@ -123,7 +123,7 @@ {/if} <form {onsubmit} autocomplete="off" class="m-4 flex flex-col gap-4"> - <table class="w-full text-left"> + <table class="w-full text-start"> <tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray"> {#each exclusionPatterns as exclusionPattern, listIndex (exclusionPattern)} <tr diff --git a/web/src/lib/components/forms/tag-asset-form.svelte b/web/src/lib/components/forms/tag-asset-form.svelte index 9392b1538d..a7f95c03c0 100644 --- a/web/src/lib/components/forms/tag-asset-form.svelte +++ b/web/src/lib/components/forms/tag-asset-form.svelte @@ -72,7 +72,7 @@ {#if tag} <div class="flex group transition-all"> <span - class="inline-block h-min whitespace-nowrap pl-3 pr-1 group-hover:pl-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 rounded-tl-full rounded-bl-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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} @@ -81,7 +81,7 @@ <button type="button" - class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-tr-full rounded-br-full place-items-center place-content-center pr-2 pl-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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)} > diff --git a/web/src/lib/components/layouts/AuthPageLayout.svelte b/web/src/lib/components/layouts/AuthPageLayout.svelte index a30202e468..870a741bd1 100644 --- a/web/src/lib/components/layouts/AuthPageLayout.svelte +++ b/web/src/lib/components/layouts/AuthPageLayout.svelte @@ -17,7 +17,7 @@ alt="Immich logo" /> <div - class="w-full h-[99%] absolute left-0 top-0 backdrop-blur-[200px] bg-transparent dark:bg-immich-dark-bg/20" + class="w-full h-[99%] absolute start-0 top-0 backdrop-blur-[200px] bg-transparent dark:bg-immich-dark-bg/20" ></div> </div> diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte index 45aaf85b67..8d33859fef 100644 --- a/web/src/lib/components/memory-page/memory-viewer.svelte +++ b/web/src/lib/components/memory-page/memory-viewer.svelte @@ -360,8 +360,8 @@ {#each current.memory.assets as asset, index (asset.id)} <a class="relative w-full py-2" href={asHref(asset)} aria-label={$t('view')}> - <span class="absolute left-0 h-[2px] w-full bg-gray-500"></span> - <span class="absolute left-0 h-[2px] bg-white" style:width={`${toProgressPercentage(index)}%`}></span> + <span class="absolute start-0 h-[2px] w-full bg-gray-500"></span> + <span class="absolute start-0 h-[2px] bg-white" style:width={`${toProgressPercentage(index)}%`}></span> </a> {/each} @@ -380,7 +380,7 @@ {#if galleryInView} <div - class="fixed top-20 z-30 left-1/2 -translate-x-1/2 transition-opacity" + class="fixed top-20 z-30 start-1/2 -translate-x-1/2 transition-opacity" class:opacity-0={!galleryInView} class:opacity-100={galleryInView} > @@ -396,7 +396,7 @@ <!-- Viewer --> <section class="overflow-hidden pt-32 md:pt-20" bind:clientHeight={viewerHeight}> <div - class="ml-[-100%] box-border flex h-[calc(100vh_-_224px)] md:h-[calc(100vh_-_180px)] w-[300%] items-center justify-center gap-10 overflow-hidden" + class="ms-[-100%] box-border flex h-[calc(100vh_-_224px)] md:h-[calc(100vh_-_180px)] w-[300%] items-center justify-center gap-10 overflow-hidden" > <!-- PREVIOUS MEMORY --> <div class="h-1/2 w-[20vw] rounded-2xl {current.previousMemory ? 'opacity-25 hover:opacity-70' : 'opacity-0'}"> @@ -424,7 +424,7 @@ {/if} {#if current.previousMemory} - <div class="absolute bottom-4 right-4 text-left text-white"> + <div class="absolute bottom-4 end-4 text-start text-white"> <p class="text-xs font-semibold text-gray-200">{$t('previous').toUpperCase()}</p> <p class="text-xl">{$memoryLaneTitle(current.previousMemory)}</p> </div> @@ -465,7 +465,7 @@ {/key} <div - class="absolute bottom-0 right-0 p-2 transition-all flex h-full justify-between flex-col items-end gap-2" + class="absolute bottom-0 end-0 p-2 transition-all flex h-full justify-between flex-col items-end gap-2" class:opacity-0={galleryInView} class:opacity-100={!galleryInView} > @@ -521,7 +521,7 @@ </div> <!-- CONTROL BUTTONS --> {#if current.previous} - <div class="absolute top-1/2 left-0 ml-4"> + <div class="absolute top-1/2 start-0 ms-4"> <CircleIconButton title={$t('previous_memory')} icon={mdiChevronLeft} @@ -532,7 +532,7 @@ {/if} {#if current.next} - <div class="absolute top-1/2 right-0 mr-4"> + <div class="absolute top-1/2 end-0 me-4"> <CircleIconButton title={$t('next_memory')} icon={mdiChevronRight} @@ -542,7 +542,7 @@ </div> {/if} - <div class="absolute left-8 top-4 text-sm font-medium text-white"> + <div class="absolute start-8 top-4 text-sm font-medium text-white"> <p> {fromLocalDateTime(current.memory.assets[0].localDateTime).toLocaleString(DateTime.DATE_FULL, { locale: $locale, @@ -582,7 +582,7 @@ {/if} {#if current.nextMemory} - <div class="absolute bottom-4 left-4 text-left text-white"> + <div class="absolute bottom-4 start-4 text-start text-white"> <p class="text-xs font-semibold text-gray-200">{$t('up_next').toUpperCase()}</p> <p class="text-xl">{$memoryLaneTitle(current.nextMemory)}</p> </div> diff --git a/web/src/lib/components/photos-page/asset-date-group.svelte b/web/src/lib/components/photos-page/asset-date-group.svelte index e45ebea1e7..ecb25b0697 100644 --- a/web/src/lib/components/photos-page/asset-date-group.svelte +++ b/web/src/lib/components/photos-page/asset-date-group.svelte @@ -149,7 +149,7 @@ </div> {/if} - <span class="w-full truncate first-letter:capitalize ml-2.5" title={getDateLocaleString(dateGroup.date)}> + <span class="w-full truncate first-letter:capitalize ms-2.5" title={getDateLocaleString(dateGroup.date)}> {dateGroup.groupTitle} </span> </div> diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index ccba4c88a8..da4387a490 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -743,7 +743,7 @@ <!-- Right margin MUST be equal to the width of immich-scrubbable-scrollbar --> <section id="asset-grid" - class={['scrollbar-hidden h-full overflow-y-auto outline-none', { 'm-0': isEmpty }, { 'ml-0': !isEmpty }]} + class={['scrollbar-hidden h-full overflow-y-auto outline-none', { 'm-0': isEmpty }, { 'ms-0': !isEmpty }]} style:margin-right={(usingMobileDevice ? 0 : scrubberWidth) + 'px'} tabindex="-1" bind:clientHeight={assetStore.viewportHeight} diff --git a/web/src/lib/components/photos-page/memory-lane.svelte b/web/src/lib/components/photos-page/memory-lane.svelte index 280273d0d1..e94f0af2c4 100644 --- a/web/src/lib/components/photos-page/memory-lane.svelte +++ b/web/src/lib/components/photos-page/memory-lane.svelte @@ -44,9 +44,9 @@ onscroll={onScroll} > {#if canScrollLeft || canScrollRight} - <div class="sticky left-0 z-20"> + <div class="sticky start-0 z-20"> {#if canScrollLeft} - <div class="absolute left-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> + <div class="absolute start-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> <button type="button" class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100" @@ -59,7 +59,7 @@ </div> {/if} {#if canScrollRight} - <div class="absolute right-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> + <div class="absolute end-4 top-[6rem] z-20" transition:fade={{ duration: 200 }}> <button type="button" class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100" @@ -76,7 +76,7 @@ <div class="inline-block" use:resizeObserver={({ width }) => (innerWidth = width)}> {#each memoryStore.memories as memory (memory.id)} <a - class="memory-card relative mr-2 md:mr-4 last:mr-0 inline-block aspect-[3/4] md:aspect-[4/3] max-md:h-[150px] xl:aspect-video h-[215px] rounded-xl" + class="memory-card relative me-2 md:me-4 last:me-0 inline-block aspect-[3/4] md:aspect-[4/3] max-md:h-[150px] xl:aspect-video h-[215px] rounded-xl" href="{AppRoute.MEMORY}?{QueryParameter.ID}={memory.assets[0].id}" > <img @@ -85,11 +85,11 @@ alt={$t('memory_lane_title', { values: { title: $getAltText(memory.assets[0]) } })} draggable="false" /> - <p class="absolute bottom-2 left-4 z-10 text-lg text-white max-md:text-sm"> + <p class="absolute bottom-2 start-4 z-10 text-lg text-white max-md:text-sm"> {$memoryLaneTitle(memory)} </p> <div - class="absolute left-0 top-0 z-0 h-full w-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent transition-all hover:bg-black/20" + class="absolute start-0 top-0 z-0 h-full w-full rounded-xl bg-gradient-to-t from-black/40 via-transparent to-transparent transition-all hover:bg-black/20" ></div> </a> {/each} diff --git a/web/src/lib/components/photos-page/skeleton.svelte b/web/src/lib/components/photos-page/skeleton.svelte index dd32d68842..5c43887450 100644 --- a/web/src/lib/components/photos-page/skeleton.svelte +++ b/web/src/lib/components/photos-page/skeleton.svelte @@ -14,7 +14,7 @@ {title} </div> <div - class="animate-pulse absolute h-full ml-[10px] mr-[10px]" + class="animate-pulse absolute h-full ms-[10px] me-[10px]" style:width="calc(100% - 20px)" data-skeleton="true" ></div> diff --git a/web/src/lib/components/places-page/places-card-group.svelte b/web/src/lib/components/places-page/places-card-group.svelte index 9bd863a95d..78e54e9bb4 100644 --- a/web/src/lib/components/places-page/places-card-group.svelte +++ b/web/src/lib/components/places-page/places-card-group.svelte @@ -25,7 +25,7 @@ <button type="button" onclick={() => togglePlacesGroupCollapsing(group.id)} - class="w-fit mt-2 pt-2 pr-2 mb-2 dark:text-immich-dark-fg" + class="w-fit mt-2 pt-2 pe-2 mb-2 dark:text-immich-dark-fg" aria-expanded={!isCollapsed} > <Icon @@ -34,7 +34,7 @@ class="inline-block -mt-2.5 transition-all duration-[250ms] {iconRotation}" /> <span class="font-bold text-3xl text-black dark:text-white">{group.name}</span> - <span class="ml-1.5">({$t('places_count', { values: { count: places.length } })})</span> + <span class="ms-1.5">({$t('places_count', { values: { count: places.length } })})</span> </button> <hr class="dark:border-immich-dark-gray" /> </div> diff --git a/web/src/lib/components/shared-components/change-date.svelte b/web/src/lib/components/shared-components/change-date.svelte index 13b2752f0c..ef682d9048 100644 --- a/web/src/lib/components/shared-components/change-date.svelte +++ b/web/src/lib/components/shared-components/change-date.svelte @@ -144,7 +144,7 @@ <!-- @migration-task: migrate this slot by hand, `prompt` would shadow a prop on the parent component --> <!-- @migration-task: migrate this slot by hand, `prompt` would shadow a prop on the parent component --> {#snippet promptSnippet()} - <div class="flex flex-col text-left gap-2"> + <div class="flex flex-col text-start gap-2"> <div class="flex flex-col"> <label for="datetime">{$t('date_and_time')}</label> <DateInput class="immich-form-input" id="datetime" type="datetime-local" bind:value={selectedDate} /> diff --git a/web/src/lib/components/shared-components/change-location.svelte b/web/src/lib/components/shared-components/change-location.svelte index a84838f1db..f981e85029 100644 --- a/web/src/lib/components/shared-components/change-location.svelte +++ b/web/src/lib/components/shared-components/change-location.svelte @@ -147,7 +147,7 @@ : ''}" onclick={() => handleUseSuggested(place.latitude, place.longitude)} > - <p class="ml-4 text-sm text-gray-700 dark:text-gray-100 truncate"> + <p class="ms-4 text-sm text-gray-700 dark:text-gray-100 truncate"> {getLocation(place.name, place.admin1name, place.admin2name)} </p> </button> @@ -189,7 +189,7 @@ {/await} </div> - <div class="grid sm:grid-cols-2 gap-4 text-sm text-left mt-4"> + <div class="grid sm:grid-cols-2 gap-4 text-sm text-start mt-4"> <CoordinatesInput lat={point ? point.lat : assetLat} lng={point ? point.lng : assetLng} diff --git a/web/src/lib/components/shared-components/combobox.svelte b/web/src/lib/components/shared-components/combobox.svelte index 3b70b0e859..8be5aabc6c 100644 --- a/web/src/lib/components/shared-components/combobox.svelte +++ b/web/src/lib/components/shared-components/combobox.svelte @@ -258,7 +258,7 @@ > <div> {#if isActive} - <div class="absolute inset-y-0 left-0 flex items-center pl-3"> + <div class="absolute inset-y-0 start-0 flex items-center ps-3"> <div class="dark:text-immich-dark-fg/75"> <Icon path={mdiMagnify} ariaHidden={true} /> </div> @@ -273,11 +273,11 @@ aria-expanded={isOpen} autocomplete="off" bind:this={input} - class:!pl-8={isActive} + class:!ps-8={isActive} class:!rounded-b-none={isOpen && dropdownDirection === 'bottom'} class:!rounded-t-none={isOpen && dropdownDirection === 'top'} class:cursor-pointer={!isActive} - class="immich-form-input text-sm text-left w-full !pr-12 transition-all" + class="immich-form-input text-sm w-full !pe-12 transition-all" id={inputId} onfocus={activate} oninput={onInput} @@ -325,8 +325,8 @@ /> <div - class="absolute right-0 top-0 h-full flex px-4 justify-center items-center content-between" - class:pr-2={selectedOption} + class="absolute end-0 top-0 h-full flex px-4 justify-center items-center content-between" + class:pe-2={selectedOption} class:pointer-events-none={!selectedOption} > {#if selectedOption} @@ -341,7 +341,7 @@ role="listbox" id={listboxId} transition:fly={{ duration: 250 }} - class="fixed text-left text-sm w-full overflow-y-auto bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-900 z-[10000]" + class="fixed text-start text-sm w-full overflow-y-auto bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-900 z-[10000]" class:rounded-b-xl={dropdownDirection === 'bottom'} class:rounded-t-xl={dropdownDirection === 'top'} class:shadow={dropdownDirection === 'bottom'} @@ -360,7 +360,7 @@ role="option" aria-selected={selectedIndex === 0} aria-disabled={true} - class="text-left w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 cursor-default aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700" + class="text-start w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 cursor-default aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700" id={`${listboxId}-${0}`} onclick={closeDropdown} > @@ -372,7 +372,7 @@ <li aria-selected={index === selectedIndex} bind:this={optionRefs[index]} - class="text-left w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all cursor-pointer aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700 break-words" + class="text-start w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all cursor-pointer aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700 break-words" id={`${listboxId}-${index}`} onclick={() => handleSelect(option)} role="option" diff --git a/web/src/lib/components/shared-components/context-menu/button-context-menu.svelte b/web/src/lib/components/shared-components/context-menu/button-context-menu.svelte index a3e12e4f12..67a17db950 100644 --- a/web/src/lib/components/shared-components/context-menu/button-context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/button-context-menu.svelte @@ -7,6 +7,7 @@ } from '$lib/components/elements/buttons/circle-icon-button.svelte'; import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte'; import { optionClickCallbackStore, selectedIdStore } from '$lib/stores/context-menu.store'; + import { languageManager } from '$lib/stores/language-manager.svelte'; import { getContextMenuPositionFromBoundingRect, getContextMenuPositionFromEvent, @@ -26,6 +27,7 @@ /** * The direction in which the context menu should open. */ + // TODO change to start vs end direction?: 'left' | 'right'; color?: Color; size?: string | undefined; @@ -62,7 +64,15 @@ const menuId = `context-menu-${id}`; const openDropdown = (event: KeyboardEvent | MouseEvent) => { - contextMenuPosition = getContextMenuPositionFromEvent(event, align); + let layoutAlign = align; + if (languageManager.rtl) { + if (align.includes('left')) { + layoutAlign = align.replace('left', 'right') as Align; + } else if (align.includes('right')) { + layoutAlign = align.replace('right', 'left') as Align; + } + } + contextMenuPosition = getContextMenuPositionFromEvent(event, layoutAlign); isOpen = true; menuContainer?.focus(); }; diff --git a/web/src/lib/components/shared-components/context-menu/context-menu.svelte b/web/src/lib/components/shared-components/context-menu/context-menu.svelte index 976f86d3e5..a79a3bd385 100644 --- a/web/src/lib/components/shared-components/context-menu/context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/context-menu.svelte @@ -3,6 +3,7 @@ import { slide } from 'svelte/transition'; import { clickOutside } from '$lib/actions/click-outside'; import type { Snippet } from 'svelte'; + import { languageManager } from '$lib/stores/language-manager.svelte'; interface Props { isVisible?: boolean; @@ -41,12 +42,17 @@ $effect(() => { if (menuElement) { + let layoutDirection = direction; + if (languageManager.rtl) { + layoutDirection = direction === 'left' ? 'right' : 'left'; + } + const rect = menuElement.getBoundingClientRect(); - const directionWidth = direction === 'left' ? rect.width : 0; + const directionWidth = layoutDirection === 'left' ? rect.width : 0; const menuHeight = Math.min(menuElement.clientHeight, height) || 0; - left = Math.min(window.innerWidth - rect.width, x - directionWidth); - top = Math.min(window.innerHeight - menuHeight, y); + left = Math.max(8, Math.min(window.innerWidth - rect.width, x - directionWidth)); + top = Math.max(8, Math.min(window.innerHeight - menuHeight, y)); } }); </script> @@ -66,7 +72,7 @@ aria-labelledby={ariaLabelledBy} bind:this={menuElement} class="{isVisible - ? 'max-h-dvh max-h-svh' + ? 'max-h-dvh' : 'max-h-0'} flex flex-col transition-all duration-[250ms] ease-in-out outline-none overflow-auto" role="menu" tabindex="-1" diff --git a/web/src/lib/components/shared-components/context-menu/menu-option.svelte b/web/src/lib/components/shared-components/context-menu/menu-option.svelte index b3a6d41018..b331804958 100644 --- a/web/src/lib/components/shared-components/context-menu/menu-option.svelte +++ b/web/src/lib/components/shared-components/context-menu/menu-option.svelte @@ -53,7 +53,7 @@ onclick={handleClick} onmouseover={() => ($selectedIdStore = id)} onmouseleave={() => ($selectedIdStore = undefined)} - class="w-full p-4 text-left text-sm font-medium {textColor} focus:outline-none focus:ring-2 focus:ring-inset cursor-pointer border-gray-200 flex gap-2 items-center {isActive + class="w-full p-4 text-start text-sm font-medium {textColor} focus:outline-none focus:ring-2 focus:ring-inset cursor-pointer border-gray-200 flex gap-2 items-center {isActive ? activeColor : 'bg-slate-100'}" role="menuitem" @@ -65,7 +65,7 @@ <div class="flex justify-between"> {text} {#if shortcutLabel} - <span class="text-gray-500 pl-4"> + <span class="text-gray-500 ps-4"> {shortcutLabel} </span> {/if} diff --git a/web/src/lib/components/shared-components/context-menu/right-click-context-menu.svelte b/web/src/lib/components/shared-components/context-menu/right-click-context-menu.svelte index 9b9e68b6c5..27d50f4fe5 100644 --- a/web/src/lib/components/shared-components/context-menu/right-click-context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/right-click-context-menu.svelte @@ -38,7 +38,7 @@ const elements = document.elementsFromPoint(event.x, event.y); if (menuContainer && elements.includes(menuContainer)) { - // User right-clicked on the context menu itself, we keep the context + // User end-clicked on the context menu itself, we keep the context // menu as is return; } @@ -91,7 +91,7 @@ }, ]} > - <section class="fixed left-0 top-0 z-10 flex h-dvh w-dvw" {oncontextmenu} role="presentation"> + <section class="fixed start-0 top-0 z-10 flex h-dvh w-dvw" {oncontextmenu} role="presentation"> <ContextMenu {direction} {x} diff --git a/web/src/lib/components/shared-components/control-app-bar.svelte b/web/src/lib/components/shared-components/control-app-bar.svelte index 7c630875c0..a26da45465 100644 --- a/web/src/lib/components/shared-components/control-app-bar.svelte +++ b/web/src/lib/components/shared-components/control-app-bar.svelte @@ -91,7 +91,7 @@ {@render children?.()} </div> - <div class="mr-4 flex place-items-center gap-1 justify-self-end"> + <div class="me-4 flex place-items-center gap-1 justify-self-end"> {@render trailing?.()} </div> </div> diff --git a/web/src/lib/components/shared-components/duplicates-modal.svelte b/web/src/lib/components/shared-components/duplicates-modal.svelte index 96f563989b..c9abea1377 100644 --- a/web/src/lib/components/shared-components/duplicates-modal.svelte +++ b/web/src/lib/components/shared-components/duplicates-modal.svelte @@ -12,7 +12,7 @@ <FullScreenModal title={$t('deduplication_info')} width="auto" {onClose}> <div class="text-sm dark:text-white"> <p>{$t('deduplication_info_description')}</p> - <ol class="ml-8 mt-2" style="list-style: decimal"> + <ol class="ms-8 mt-2" style="list-style: decimal"> <li>{$t('deduplication_criteria_1')}</li> <li>{$t('deduplication_criteria_2')}</li> </ol> diff --git a/web/src/lib/components/shared-components/full-screen-modal.svelte b/web/src/lib/components/shared-components/full-screen-modal.svelte index 9284283f54..1640dad692 100644 --- a/web/src/lib/components/shared-components/full-screen-modal.svelte +++ b/web/src/lib/components/shared-components/full-screen-modal.svelte @@ -77,7 +77,7 @@ role="presentation" in:fade={{ duration: 100 }} out:fade={{ duration: 100 }} - class="fixed left-0 top-0 z-[9999] flex h-dvh w-dvw place-content-center place-items-center bg-black/40" + class="fixed start-0 top-0 z-[9999] flex h-dvh w-dvw place-content-center place-items-center bg-black/40" onkeydown={(event) => { event.stopPropagation(); }} diff --git a/web/src/lib/components/shared-components/immich-logo-small-link.svelte b/web/src/lib/components/shared-components/immich-logo-small-link.svelte index 7f96d88df8..5a940fa278 100644 --- a/web/src/lib/components/shared-components/immich-logo-small-link.svelte +++ b/web/src/lib/components/shared-components/immich-logo-small-link.svelte @@ -3,6 +3,6 @@ import { mobileDevice } from '$lib/stores/mobile-device.svelte'; </script> -<a data-sveltekit-preload-data="hover" class="ml-4" href="/"> +<a data-sveltekit-preload-data="hover" class="ms-4" href="/"> <ImmichLogo class="h-[50px] max-w-none md:w-auto md:max-w-full" noText={mobileDevice.maxMd} /> </a> diff --git a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte index 5bf3f0a621..92db67eba0 100644 --- a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte @@ -48,7 +48,7 @@ in:fade={{ duration: 100 }} out:fade={{ duration: 100 }} id="account-info-panel" - class="absolute right-[25px] top-[75px] z-[100] w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray" + class="absolute end-[25px] top-[75px] z-[100] w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray" use:focusTrap > <div @@ -56,7 +56,7 @@ > <div class="relative"> <UserAvatar user={$user} size="xl" /> - <div class="absolute z-10 bottom-0 right-0 rounded-full w-6 h-6"> + <div class="absolute z-10 bottom-0 end-0 rounded-full w-6 h-6"> <CircleIconButton color="primary" icon={mdiPencil} diff --git a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte index 90f6b3c55b..e91db5cc3a 100644 --- a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte @@ -83,8 +83,8 @@ <ImmichLogo class="max-md:h-[48px] h-[50px]" noText={!mobileDevice.isFullSidebar} /> </a> </div> - <div class="flex justify-between gap-4 lg:gap-8 pr-6"> - <div class="hidden w-full max-w-5xl flex-1 tall:pl-0 sm:block"> + <div class="flex justify-between gap-4 lg:gap-8 pe-6"> + <div class="hidden w-full max-w-5xl flex-1 tall:ps-0 sm:block"> {#if $featureFlags.search} <SearchBar grayTheme={true} /> {/if} @@ -154,7 +154,7 @@ > <button type="button" - class="flex pl-2" + class="flex ps-2" onmouseover={() => (shouldShowAccountInfo = true)} onfocus={() => (shouldShowAccountInfo = true)} onblur={() => (shouldShowAccountInfo = false)} @@ -170,7 +170,7 @@ <div in:fade={{ delay: 500, duration: 150 }} out:fade={{ delay: 200, duration: 150 }} - class="absolute -bottom-12 right-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray" + class="absolute -bottom-12 end-5 rounded-md border bg-gray-500 p-2 text-[12px] text-gray-100 shadow-md dark:border-immich-dark-gray dark:bg-immich-dark-gray" > <p>{$user.name}</p> <p>{$user.email}</p> diff --git a/web/src/lib/components/shared-components/navigation-loading-bar.svelte b/web/src/lib/components/shared-components/navigation-loading-bar.svelte index bd5f15ae4e..afdb8ee967 100644 --- a/web/src/lib/components/shared-components/navigation-loading-bar.svelte +++ b/web/src/lib/components/shared-components/navigation-loading-bar.svelte @@ -26,7 +26,7 @@ </script> {#if showing} - <div class="absolute left-0 top-0 z-[999999999] h-[3px] w-dvw bg-white"> + <div class="absolute start-0 top-0 z-[999999999] h-[3px] w-dvw bg-white"> <span class="absolute h-[3px] bg-immich-primary" style:width={`${$progress}%`}></span> </div> {/if} diff --git a/web/src/lib/components/shared-components/notification/notification-card.svelte b/web/src/lib/components/shared-components/notification/notification-card.svelte index 5054c18695..30c8622bba 100644 --- a/web/src/lib/components/shared-components/notification/notification-card.svelte +++ b/web/src/lib/components/shared-components/notification/notification-card.svelte @@ -100,7 +100,7 @@ /> </div> - <p class="whitespace-pre-wrap pl-[28px] pr-[16px] text-sm" data-testid="message"> + <p class="whitespace-pre-wrap ps-[28px] pe-[16px] text-sm" data-testid="message"> {#if isComponentNotification(notification)} <notification.component.type {...notification.component.props} /> {:else} @@ -109,7 +109,7 @@ </p> {#if notification.button} - <p class="pl-[28px] mt-2.5 text-sm"> + <p class="ps-[28px] mt-2.5 text-sm"> <button type="button" class="{buttonStyle[notification.type]} rounded px-3 pt-1.5 pb-1 transition-all duration-200" diff --git a/web/src/lib/components/shared-components/notification/notification-list.svelte b/web/src/lib/components/shared-components/notification/notification-list.svelte index c7c54be267..6e067e839a 100644 --- a/web/src/lib/components/shared-components/notification/notification-list.svelte +++ b/web/src/lib/components/shared-components/notification/notification-list.svelte @@ -11,7 +11,7 @@ <div role="status" aria-relevant="additions" aria-label={$t('notifications')}> {#if $notificationList.length > 0} - <section transition:fade={{ duration: 250 }} id="notification-list" class="fixed right-5 top-[80px] z-[99999999]"> + <section transition:fade={{ duration: 250 }} id="notification-list" class="fixed end-5 top-[80px] z-[99999999]"> {#each $notificationList as notification (notification.id)} <div animate:flip={{ duration: 250, easing: quintOut }}> <NotificationCard {notification} /> diff --git a/web/src/lib/components/shared-components/password-field.svelte b/web/src/lib/components/shared-components/password-field.svelte index 8519f84134..32879a1755 100644 --- a/web/src/lib/components/shared-components/password-field.svelte +++ b/web/src/lib/components/shared-components/password-field.svelte @@ -19,7 +19,7 @@ <div class="relative w-full"> <input {...rest} - class="immich-form-input w-full !pr-12" + class="immich-form-input w-full !pe-12" type={showPassword ? 'text' : 'password'} {required} value={password} diff --git a/web/src/lib/components/shared-components/progress-bar/progress-bar.svelte b/web/src/lib/components/shared-components/progress-bar/progress-bar.svelte index 5b663bd1a9..2b3abb9708 100644 --- a/web/src/lib/components/shared-components/progress-bar/progress-bar.svelte +++ b/web/src/lib/components/shared-components/progress-bar/progress-bar.svelte @@ -88,5 +88,5 @@ </script> {#if !hidden} - <span class="absolute left-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`}></span> + <span class="absolute start-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`}></span> {/if} diff --git a/web/src/lib/components/shared-components/scrubber/scrubber.svelte b/web/src/lib/components/shared-components/scrubber/scrubber.svelte index f5d9c00768..d7b0dfd28d 100644 --- a/web/src/lib/components/shared-components/scrubber/scrubber.svelte +++ b/web/src/lib/components/shared-components/scrubber/scrubber.svelte @@ -446,7 +446,7 @@ aria-valuemax={toScrollY(1)} aria-valuemin={toScrollY(0)} data-id="immich-scrubbable-scrollbar" - class="absolute right-0 z-[1] select-none bg-immich-bg hover:cursor-row-resize" + class="absolute end-0 z-[1] select-none bg-immich-bg hover:cursor-row-resize" style:padding-top={PADDING_TOP + 'px'} style:padding-bottom={PADDING_BOTTOM + 'px'} style:width @@ -464,7 +464,7 @@ class={[ { 'border-b-2': isDragging }, { 'rounded-bl-md': !isDragging }, - 'truncate opacity-85 pointer-events-none absolute right-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-immich-primary bg-immich-bg py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg', + 'truncate opacity-85 pointer-events-none absolute end-0 z-[100] min-w-20 max-w-64 w-fit rounded-ss-md border-immich-primary bg-immich-bg py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg', ]} style:top="{hoverY + 2}px" > @@ -474,7 +474,7 @@ {#if usingMobileDevice && ((assetStore.scrolling && scrollHoverLabel) || isHover || isDragging)} <div id="time-label" - class="rounded-l-full w-[32px] pl-2 text-white bg-immich-primary dark:bg-gray-600 hover:cursor-pointer select-none" + class="rounded-s-full w-[32px] ps-2 text-white bg-immich-primary dark:bg-gray-600 hover:cursor-pointer select-none" style:top="{PADDING_TOP + (scrollY - 50 / 2)}px" style:height="50px" style:right="0" @@ -482,8 +482,8 @@ in:fade={{ duration: 200 }} out:fade={{ duration: 200 }} > - <Icon path={mdiPlay} size="20" class="-rotate-90 relative top-[9px] -right-[2px]" /> - <Icon path={mdiPlay} size="20" class="rotate-90 relative top-[1px] -right-[2px]" /> + <Icon path={mdiPlay} size="20" class="-rotate-90 relative top-[9px] -end-[2px]" /> + <Icon path={mdiPlay} size="20" class="rotate-90 relative top-[1px] -end-[2px]" /> {#if (assetStore.scrolling && scrollHoverLabel) || isHover || isDragging} <p transition:fade={{ duration: 200 }} @@ -500,13 +500,13 @@ <!-- Scroll Position Indicator Line --> {#if !usingMobileDevice && !isDragging} <div - class="absolute right-0 h-[2px] w-10 bg-immich-primary dark:bg-immich-dark-primary" + class="absolute end-0 h-[2px] w-10 bg-immich-primary dark:bg-immich-dark-primary" style:top="{scrollY + PADDING_TOP - 2}px" > {#if assetStore.scrolling && scrollHoverLabel && !isHover} <p transition:fade={{ duration: 200 }} - class="truncate pointer-events-none absolute right-0 bottom-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-b-2 border-immich-primary bg-immich-bg/80 py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray/80 dark:text-immich-dark-fg" + class="truncate pointer-events-none absolute end-0 bottom-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-b-2 border-immich-primary bg-immich-bg/80 py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray/80 dark:text-immich-dark-fg" > {scrollHoverLabel} </p> @@ -521,7 +521,7 @@ data-label={segments.at(0)?.dateFormatted} > {#if relativeTopOffset > 6} - <div class="absolute right-[0.75rem] h-[4px] w-[4px] rounded-full bg-gray-300"></div> + <div class="absolute end-[0.75rem] h-[4px] w-[4px] rounded-full bg-gray-300"></div> {/if} </div> <!-- Time Segment --> @@ -535,12 +535,12 @@ > {#if !usingMobileDevice} {#if segment.hasLabel} - <div class="absolute right-[1.25rem] top-[-16px] z-10 text-[12px] dark:text-immich-dark-fg font-immich-mono"> + <div class="absolute end-[1.25rem] top-[-16px] z-10 text-[12px] dark:text-immich-dark-fg font-immich-mono"> {segment.date.year} </div> {/if} {#if segment.hasDot} - <div class="absolute right-[0.75rem] bottom-0 h-[4px] w-[4px] rounded-full bg-gray-300"></div> + <div class="absolute end-[0.75rem] bottom-0 h-[4px] w-[4px] rounded-full bg-gray-300"></div> {/if} {/if} </div> diff --git a/web/src/lib/components/shared-components/search-bar/search-bar.svelte b/web/src/lib/components/shared-components/search-bar/search-bar.svelte index a98e2f7882..e01b0edf1b 100644 --- a/web/src/lib/components/shared-components/search-bar/search-bar.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-bar.svelte @@ -261,15 +261,15 @@ /> </div> - <div class="absolute inset-y-0 {showClearIcon ? 'right-14' : 'right-2'} flex items-center pl-6 transition-all"> + <div class="absolute inset-y-0 {showClearIcon ? 'end-14' : 'end-2'} flex items-center ps-6 transition-all"> <CircleIconButton title={$t('show_search_options')} icon={mdiTune} onclick={onFilterClick} size="20" /> </div> {#if isFocus} <div class="absolute inset-y-0 flex items-center" - class:right-16={isFocus} - class:right-28={isFocus && value.length > 0} + class:end-16={isFocus} + class:end-28={isFocus && value.length > 0} > <p class="bg-immich-primary text-white dark:bg-immich-dark-primary/90 dark:text-black/75 rounded-full px-3 py-1 text-xs z-10" @@ -280,11 +280,11 @@ {/if} {#if showClearIcon} - <div class="absolute inset-y-0 right-0 flex items-center pr-2"> + <div class="absolute inset-y-0 end-0 flex items-center pe-2"> <CircleIconButton onclick={onClear} icon={mdiClose} title={$t('clear')} size="20" /> </div> {/if} - <div class="absolute inset-y-0 left-0 flex items-center pl-2"> + <div class="absolute inset-y-0 start-0 flex items-center ps-2"> <CircleIconButton type="submit" disabled={showFilter} diff --git a/web/src/lib/components/shared-components/search-bar/search-history-box.svelte b/web/src/lib/components/shared-components/search-bar/search-history-box.svelte index a6188e46a9..2eb0b06d4b 100644 --- a/web/src/lib/components/shared-components/search-bar/search-history-box.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-history-box.svelte @@ -122,7 +122,7 @@ <!-- svelte-ignore a11y_click_events_have_key_events --> <div id={getId(index)} - class="relative flex w-full cursor-pointer gap-3 py-3 pl-5 hover:bg-gray-100 aria-selected:bg-gray-100 dark:aria-selected:bg-gray-500/30 dark:hover:bg-gray-500/30" + class="relative flex w-full cursor-pointer gap-3 py-3 ps-5 hover:bg-gray-100 aria-selected:bg-gray-100 dark:aria-selected:bg-gray-500/30 dark:hover:bg-gray-500/30" onclick={() => handleSelect(savedSearchTerm)} role="option" tabindex="-1" @@ -132,7 +132,7 @@ <Icon path={mdiMagnify} size="1.5em" ariaHidden={true} /> {savedSearchTerm} </div> - <div aria-hidden={true} class="absolute right-5 top-0 items-center justify-center py-3"> + <div aria-hidden={true} class="absolute end-5 top-0 items-center justify-center py-3"> <CircleIconButton icon={mdiClose} title={$t('remove')} diff --git a/web/src/lib/components/shared-components/search-bar/search-tags-section.svelte b/web/src/lib/components/shared-components/search-bar/search-tags-section.svelte index 6071da1460..0819022ae2 100644 --- a/web/src/lib/components/shared-components/search-bar/search-tags-section.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-tags-section.svelte @@ -57,7 +57,7 @@ {#if tag} <div class="flex group transition-all"> <span - class="inline-block h-min whitespace-nowrap pl-3 pr-1 group-hover:pl-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 rounded-tl-full rounded-bl-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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} @@ -66,7 +66,7 @@ <button type="button" - class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-tr-full rounded-br-full place-items-center place-content-center pr-2 pl-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all" + 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)} > diff --git a/web/src/lib/components/shared-components/settings/setting-accordion.svelte b/web/src/lib/components/shared-components/settings/setting-accordion.svelte index bfa379edcd..5ae41c0551 100755 --- a/web/src/lib/components/shared-components/settings/setting-accordion.svelte +++ b/web/src/lib/components/shared-components/settings/setting-accordion.svelte @@ -73,7 +73,7 @@ type="button" aria-expanded={isOpen} {onclick} - class="flex w-full place-items-center justify-between text-left" + class="flex w-full place-items-center justify-between text-start" > <div> <div class="flex gap-2 place-items-center"> @@ -110,7 +110,7 @@ </button> {#if isOpen} - <ul transition:slide={{ duration: 150 }} class="mb-2 ml-4"> + <ul transition:slide={{ duration: 150 }} class="mb-2 ms-4"> {@render children?.()} </ul> {/if} diff --git a/web/src/lib/components/shared-components/settings/setting-input-field.svelte b/web/src/lib/components/shared-components/settings/setting-input-field.svelte index 9259f59cfb..946f40c08d 100644 --- a/web/src/lib/components/shared-components/settings/setting-input-field.svelte +++ b/web/src/lib/components/shared-components/settings/setting-input-field.svelte @@ -101,7 +101,7 @@ {#if inputType === SettingInputFieldType.COLOR} <input bind:this={input} - class="immich-form-input w-full pb-2 rounded-none mr-1" + class="immich-form-input w-full pb-2 rounded-none me-1" aria-describedby={description ? `${label}-desc` : undefined} aria-labelledby="{label}-label" id={label} diff --git a/web/src/lib/components/shared-components/settings/setting-select.svelte b/web/src/lib/components/shared-components/settings/setting-select.svelte index 1cfd7123ac..87260e6d6a 100644 --- a/web/src/lib/components/shared-components/settings/setting-select.svelte +++ b/web/src/lib/components/shared-components/settings/setting-select.svelte @@ -65,12 +65,12 @@ path={mdiChevronDown} size="1.2em" ariaHidden={true} - class="pointer-events-none right-1 relative col-start-1 row-start-1 self-center justify-self-end {disabled + class="pointer-events-none end-1 relative col-start-1 row-start-1 self-center justify-self-end {disabled ? 'text-immich-bg' : 'text-immich-fg dark:text-immich-bg'}" /> <select - class="immich-form-input w-full appearance-none row-start-1 col-start-1 !pr-6" + class="immich-form-input w-full appearance-none row-start-1 col-start-1 !pe-6" {disabled} aria-describedby={desc ? `${name}-desc` : undefined} {name} diff --git a/web/src/lib/components/shared-components/settings/setting-switch.svelte b/web/src/lib/components/shared-components/settings/setting-switch.svelte index 29c1f213d3..aa165cfaaa 100644 --- a/web/src/lib/components/shared-components/settings/setting-switch.svelte +++ b/web/src/lib/components/shared-components/settings/setting-switch.svelte @@ -33,7 +33,7 @@ </script> <div class="flex place-items-center justify-between"> - <div class="mr-2"> + <div class="me-2"> <div class="flex h-[26px] place-items-center gap-1"> <label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for={sliderId}> {title} diff --git a/web/src/lib/components/shared-components/show-shortcuts.svelte b/web/src/lib/components/shared-components/show-shortcuts.svelte index cee7545f48..e1454b49df 100644 --- a/web/src/lib/components/shared-components/show-shortcuts.svelte +++ b/web/src/lib/components/shared-components/show-shortcuts.svelte @@ -55,7 +55,7 @@ <div class="grid grid-cols-[30%_70%] items-center gap-4 pt-4 text-sm"> <div class="flex justify-self-end"> {#each shortcut.key as key (key)} - <p class="mr-1 flex items-center justify-center justify-self-end rounded-lg bg-immich-primary/25 p-2"> + <p class="me-1 flex items-center justify-center justify-self-end rounded-lg bg-immich-primary/25 p-2"> {key} </p> {/each} @@ -74,7 +74,7 @@ <div class="grid grid-cols-[30%_70%] items-center gap-4 pt-4 text-sm"> <div class="flex justify-self-end"> {#each shortcut.key as key (key)} - <p class="mr-1 flex items-center justify-center justify-self-end rounded-lg bg-immich-primary/25 p-2"> + <p class="me-1 flex items-center justify-center justify-self-end rounded-lg bg-immich-primary/25 p-2"> {key} </p> {/each} diff --git a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte index 67d3eaf523..d94a0c169e 100644 --- a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte +++ b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte @@ -78,7 +78,7 @@ <LicenseModal onClose={() => (isOpen = false)} /> {/if} -<div class="license-status pl-4 text-sm"> +<div class="license-status ps-4 text-sm"> {#if $isPurchased && $preferences.purchase.showSupportBadge} <button onclick={() => goto(`${AppRoute.USER_SETTINGS}?isOpen=user-purchase-settings`)} @@ -123,7 +123,7 @@ {#if showMessage} <dialog open - class="hidden sidebar:block w-[500px] absolute bottom-[75px] left-[255px] bg-gray-50 dark:border-gray-800 border border-gray-200 dark:bg-immich-dark-gray dark:text-white text-black rounded-3xl z-10 shadow-2xl px-8 py-6" + class="hidden sidebar:block w-[500px] absolute bottom-[75px] start-[255px] bg-gray-50 dark:border-gray-800 border border-gray-200 dark:bg-immich-dark-gray dark:text-white text-black rounded-3xl z-10 shadow-2xl px-8 py-6" transition:fade={{ duration: 150 }} onmouseover={() => (hoverMessage = true)} onmouseleave={() => (hoverMessage = false)} diff --git a/web/src/lib/components/shared-components/side-bar/recent-albums.svelte b/web/src/lib/components/shared-components/side-bar/recent-albums.svelte index 9674ed9366..d121f74fdf 100644 --- a/web/src/lib/components/shared-components/side-bar/recent-albums.svelte +++ b/web/src/lib/components/shared-components/side-bar/recent-albums.svelte @@ -27,7 +27,7 @@ <a href={'/albums/' + album.id} title={album.albumName} - class="flex w-full place-items-center justify-between gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary pl-10 group-hover:sm:px-10 md:px-10" + class="flex w-full place-items-center justify-between gap-4 rounded-e-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary ps-10 group-hover:sm:px-10 md:px-10" > <div> <div diff --git a/web/src/lib/components/shared-components/side-bar/server-status.svelte b/web/src/lib/components/shared-components/side-bar/server-status.svelte index 8ca552a1f4..500bce524e 100644 --- a/web/src/lib/components/shared-components/side-bar/server-status.svelte +++ b/web/src/lib/components/shared-components/side-bar/server-status.svelte @@ -42,7 +42,7 @@ {/if} <div - class="text-sm flex md:flex pl-5 pr-1 place-items-center place-content-center justify-between min-w-52 overflow-hidden" + class="text-sm flex md:flex ps-5 pe-1 place-items-center place-content-center justify-between min-w-52 overflow-hidden" > {#if $connected} <div class="flex gap-2 place-items-center place-content-center"> diff --git a/web/src/lib/components/shared-components/side-bar/side-bar-link.svelte b/web/src/lib/components/shared-components/side-bar/side-bar-link.svelte index f8bf89cd29..1be7356e94 100644 --- a/web/src/lib/components/shared-components/side-bar/side-bar-link.svelte +++ b/web/src/lib/components/shared-components/side-bar/side-bar-link.svelte @@ -37,7 +37,7 @@ <div class="relative"> {#if hasDropdown} - <span class="hidden md:block absolute left-1 z-50 h-full"> + <span class="hidden md:block absolute start-1 z-50 h-full"> <button type="button" aria-label={$t('recent-albums')} @@ -59,12 +59,12 @@ data-sveltekit-preload-data={preloadData ? 'hover' : 'off'} draggable="false" aria-current={isSelected ? 'page' : undefined} - class="flex w-full place-items-center gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary + class="flex w-full place-items-center gap-4 rounded-e-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-immich-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary {isSelected ? 'bg-immich-primary/10 text-immich-primary hover:bg-immich-primary/10 dark:bg-immich-dark-primary/10 dark:text-immich-dark-primary' : ''}" > - <div class="flex w-full place-items-center gap-4 pl-5 overflow-hidden truncate"> + <div class="flex w-full place-items-center gap-4 ps-5 overflow-hidden truncate"> <Icon path={icon} size="1.5em" class="shrink-0" flipped={flippedLogo} ariaHidden /> <span class="text-sm font-medium">{title}</span> </div> diff --git a/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte b/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte index 74eb7d266b..9ef0bd1b9f 100644 --- a/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte +++ b/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte @@ -35,7 +35,7 @@ tabindex="-1" class="immich-scrollbar relative z-10 w-0 sidebar:w-[16rem] overflow-y-auto overflow-x-hidden bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg" class:shadow-2xl={isExpanded} - class:dark:border-r-immich-dark-gray={isExpanded} + class:dark:border-e-immich-dark-gray={isExpanded} class:border-r={isExpanded} class:w-[min(100vw,16rem)]={sidebarStore.isOpen} data-testid="sidebar-parent" @@ -43,7 +43,7 @@ use:clickOutside={{ onOutclick: closeSidebar, onEscape: closeSidebar }} use:focusTrap={{ active: isExpanded }} > - <div class="pr-6 flex flex-col gap-1 h-max min-h-full"> + <div class="pe-6 flex flex-col gap-1 h-max min-h-full"> {@render children?.()} </div> </section> diff --git a/web/src/lib/components/shared-components/side-bar/storage-space.svelte b/web/src/lib/components/shared-components/side-bar/storage-space.svelte index 604522c4f0..4a40cbc1e7 100644 --- a/web/src/lib/components/shared-components/side-bar/storage-space.svelte +++ b/web/src/lib/components/shared-components/side-bar/storage-space.svelte @@ -46,7 +46,7 @@ </script> <div - class="storage-status p-4 bg-gray-100 dark:bg-immich-dark-primary/10 ml-4 rounded-lg text-sm min-w-52" + class="storage-status p-4 bg-gray-100 dark:bg-immich-dark-primary/10 ms-4 rounded-lg text-sm min-w-52" title={$t('storage_usage', { values: { used: getByteUnitString(usedBytes, $locale, 3), diff --git a/web/src/lib/components/shared-components/tree/breadcrumbs.svelte b/web/src/lib/components/shared-components/tree/breadcrumbs.svelte index 7da2215a77..a0d4d250f7 100644 --- a/web/src/lib/components/shared-components/tree/breadcrumbs.svelte +++ b/web/src/lib/components/shared-components/tree/breadcrumbs.svelte @@ -23,7 +23,7 @@ icon={mdiArrowUpLeft} title={$t('to_parent')} href={getLink(pathSegments.slice(0, -1).join('/'))} - class="mr-2" + class="me-2" padding="2" onclick={() => {}} /> diff --git a/web/src/lib/components/shared-components/tree/tree-items.svelte b/web/src/lib/components/shared-components/tree/tree-items.svelte index 3b770e47ef..0df71ca605 100644 --- a/web/src/lib/components/shared-components/tree/tree-items.svelte +++ b/web/src/lib/components/shared-components/tree/tree-items.svelte @@ -14,7 +14,7 @@ let { items, parent = '', active = '', icons, getLink, getColor = () => undefined }: Props = $props(); </script> -<ul class="list-none ml-2"> +<ul class="list-none ms-2"> <!-- eslint-disable-next-line svelte/require-each-key --> {#each Object.entries(items).sort() as [path, tree]} {@const value = normalizeTreePath(`${parent}/${path}`)} diff --git a/web/src/lib/components/shared-components/tree/tree.svelte b/web/src/lib/components/shared-components/tree/tree.svelte index ded6f70690..463871154d 100644 --- a/web/src/lib/components/shared-components/tree/tree.svelte +++ b/web/src/lib/components/shared-components/tree/tree.svelte @@ -31,7 +31,7 @@ <a href={getLink(path)} title={value} - class={`flex flex-grow place-items-center pl-2 py-1 text-sm rounded-lg hover:bg-slate-200 dark:hover:bg-slate-800 hover:font-semibold ${isTarget ? 'bg-slate-100 dark:bg-slate-700 font-semibold text-immich-primary dark:text-immich-dark-primary' : 'dark:text-gray-200'}`} + class={`flex flex-grow place-items-center ps-2 py-1 text-sm rounded-lg hover:bg-slate-200 dark:hover:bg-slate-800 hover:font-semibold ${isTarget ? 'bg-slate-100 dark:bg-slate-700 font-semibold text-immich-primary dark:text-immich-dark-primary' : 'dark:text-gray-200'}`} data-sveltekit-keepfocus > <button type="button" {onclick} class={Object.values(tree).length === 0 ? 'invisible' : ''}> @@ -45,7 +45,7 @@ size={20} /> </div> - <span class="text-nowrap overflow-hidden text-ellipsis font-mono pl-1 pt-1 whitespace-pre-wrap">{value}</span> + <span class="text-nowrap overflow-hidden text-ellipsis font-mono ps-1 pt-1 whitespace-pre-wrap">{value}</span> </a> {#if isOpen} diff --git a/web/src/lib/components/shared-components/upload-panel.svelte b/web/src/lib/components/shared-components/upload-panel.svelte index 0eb7d1655c..e7708e5c30 100644 --- a/web/src/lib/components/shared-components/upload-panel.svelte +++ b/web/src/lib/components/shared-components/upload-panel.svelte @@ -48,7 +48,7 @@ } uploadAssetsStore.reset(); }} - class="fixed bottom-6 right-16 z-[10000]" + class="fixed bottom-6 end-16 z-[10000]" > {#if showDetail} <div @@ -136,7 +136,7 @@ type="button" in:scale={{ duration: 250, easing: quartInOut }} onclick={() => (showDetail = true)} - class="absolute -left-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-primary p-5 text-xs text-gray-200" + class="absolute -start-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-primary p-5 text-xs text-gray-200" > {$remainingUploads.toLocaleString($locale)} </button> @@ -145,7 +145,7 @@ type="button" in:scale={{ duration: 250, easing: quartInOut }} onclick={() => (showDetail = true)} - class="absolute -right-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-error p-5 text-xs text-gray-200" + class="absolute -end-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-error p-5 text-xs text-gray-200" > {$stats.errors.toLocaleString($locale)} </button> diff --git a/web/src/lib/components/user-settings-page/app-settings.svelte b/web/src/lib/components/user-settings-page/app-settings.svelte index 63209ca289..5b4a19c34f 100644 --- a/web/src/lib/components/user-settings-page/app-settings.svelte +++ b/web/src/lib/components/user-settings-page/app-settings.svelte @@ -96,8 +96,8 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> - <div class="ml-4 mt-4 flex flex-col gap-4"> - <div class="ml-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> + <div class="ms-4"> <SettingSwitch title={$t('theme_selection')} subtitle={$t('theme_selection_description')} @@ -106,7 +106,7 @@ /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingCombobox comboboxPlaceholder={$t('language')} selectedOption={langOptions.find(({ value }) => value === closestLanguage) || defaultLangOption} @@ -117,7 +117,7 @@ /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('default_locale')} subtitle={$t('default_locale_description')} @@ -128,7 +128,7 @@ </SettingSwitch> </div> {#if $locale !== undefined} - <div class="ml-4"> + <div class="ms-4"> <SettingCombobox comboboxPlaceholder={$t('searching_locales')} {selectedOption} @@ -140,7 +140,7 @@ </div> {/if} - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('display_original_photos')} subtitle={$t('display_original_photos_setting_description')} @@ -148,7 +148,7 @@ onToggle={() => ($alwaysLoadOriginalFile = !$alwaysLoadOriginalFile)} /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('video_hover_setting')} subtitle={$t('video_hover_setting_description')} @@ -156,7 +156,7 @@ onToggle={() => ($playVideoThumbnailOnHover = !$playVideoThumbnailOnHover)} /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('loop_videos')} subtitle={$t('loop_videos_description')} @@ -165,7 +165,7 @@ /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('permanent_deletion_warning')} subtitle={$t('permanent_deletion_warning_setting_description')} diff --git a/web/src/lib/components/user-settings-page/change-password-settings.svelte b/web/src/lib/components/user-settings-page/change-password-settings.svelte index dc8cfac42e..2735c4f13e 100644 --- a/web/src/lib/components/user-settings-page/change-password-settings.svelte +++ b/web/src/lib/components/user-settings-page/change-password-settings.svelte @@ -44,7 +44,7 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingInputField inputType={SettingInputFieldType.PASSWORD} label={$t('password')} diff --git a/web/src/lib/components/user-settings-page/device-card.svelte b/web/src/lib/components/user-settings-page/device-card.svelte index 74e6579dd0..ad0b621921 100644 --- a/web/src/lib/components/user-settings-page/device-card.svelte +++ b/web/src/lib/components/user-settings-page/device-card.svelte @@ -31,7 +31,7 @@ </script> <div class="flex w-full flex-row"> - <div class="hidden items-center justify-center pr-2 text-immich-primary dark:text-immich-dark-primary sm:flex"> + <div class="hidden items-center justify-center pe-2 text-immich-primary dark:text-immich-dark-primary sm:flex"> {#if device.deviceOS === 'Android'} <Icon path={mdiAndroid} size="40" /> {:else if device.deviceOS === 'iOS' || device.deviceOS === 'macOS'} @@ -50,7 +50,7 @@ <Icon path={mdiHelp} size="40" /> {/if} </div> - <div class="flex grow flex-row justify-between gap-1 pl-4 sm:pl-0"> + <div class="flex grow flex-row justify-between gap-1 ps-4 sm:ps-0"> <div class="flex flex-col justify-center gap-1 dark:text-white"> <span class="text-sm"> {#if device.deviceType || device.deviceOS} diff --git a/web/src/lib/components/user-settings-page/download-settings.svelte b/web/src/lib/components/user-settings-page/download-settings.svelte index e2401a8a76..9ed7285aa0 100644 --- a/web/src/lib/components/user-settings-page/download-settings.svelte +++ b/web/src/lib/components/user-settings-page/download-settings.svelte @@ -43,7 +43,7 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingInputField inputType={SettingInputFieldType.NUMBER} label={$t('archive_size')} diff --git a/web/src/lib/components/user-settings-page/feature-settings.svelte b/web/src/lib/components/user-settings-page/feature-settings.svelte index 4fdd8f21d7..d331e40432 100644 --- a/web/src/lib/components/user-settings-page/feature-settings.svelte +++ b/web/src/lib/components/user-settings-page/feature-settings.svelte @@ -63,14 +63,14 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col"> + <div class="ms-4 mt-4 flex flex-col"> <SettingAccordion key="folders" title={$t('folders')} subtitle={$t('folders_feature_description')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={foldersEnabled} /> </div> {#if foldersEnabled} - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('sidebar')} subtitle={$t('sidebar_display_description')} @@ -81,18 +81,18 @@ </SettingAccordion> <SettingAccordion key="memories" title={$t('time_based_memories')} subtitle={$t('photos_from_previous_years')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={memoriesEnabled} /> </div> </SettingAccordion> <SettingAccordion key="people" title={$t('people')} subtitle={$t('people_feature_description')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={peopleEnabled} /> </div> {#if peopleEnabled} - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('sidebar')} subtitle={$t('sidebar_display_description')} @@ -103,17 +103,17 @@ </SettingAccordion> <SettingAccordion key="rating" title={$t('rating')} subtitle={$t('rating_description')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={ratingsEnabled} /> </div> </SettingAccordion> <SettingAccordion key="shared-links" title={$t('shared_links')} subtitle={$t('shared_links_description')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={sharedLinksEnabled} /> </div> {#if sharedLinksEnabled} - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('sidebar')} subtitle={$t('sidebar_display_description')} @@ -124,11 +124,11 @@ </SettingAccordion> <SettingAccordion key="tags" title={$t('tags')} subtitle={$t('tag_feature_description')}> - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('enable')} bind:checked={tagsEnabled} /> </div> {#if tagsEnabled} - <div class="ml-4 mt-6"> + <div class="ms-4 mt-6"> <SettingSwitch title={$t('sidebar')} subtitle={$t('sidebar_display_description')} diff --git a/web/src/lib/components/user-settings-page/notifications-settings.svelte b/web/src/lib/components/user-settings-page/notifications-settings.svelte index 51a6558f43..fe4b51e20a 100644 --- a/web/src/lib/components/user-settings-page/notifications-settings.svelte +++ b/web/src/lib/components/user-settings-page/notifications-settings.svelte @@ -46,14 +46,14 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" {onsubmit}> - <div class="ml-4 mt-4 flex flex-col gap-4"> - <div class="ml-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> + <div class="ms-4"> <SettingSwitch title={$t('notification_toggle_setting_description')} bind:checked={emailNotificationsEnabled} /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('album_added')} subtitle={$t('album_added_notification_setting_description')} @@ -61,7 +61,7 @@ disabled={!emailNotificationsEnabled} /> </div> - <div class="ml-4"> + <div class="ms-4"> <SettingSwitch title={$t('album_updated')} subtitle={$t('album_updated_setting_description')} diff --git a/web/src/lib/components/user-settings-page/partner-selection-modal.svelte b/web/src/lib/components/user-settings-page/partner-selection-modal.svelte index f5f76e099f..37c6580429 100644 --- a/web/src/lib/components/user-settings-page/partner-selection-modal.svelte +++ b/web/src/lib/components/user-settings-page/partner-selection-modal.svelte @@ -54,7 +54,7 @@ <UserAvatar {user} size="lg" /> {/if} - <div class="text-left"> + <div class="text-start"> <p class="text-immich-fg dark:text-immich-dark-fg"> {user.name} </p> diff --git a/web/src/lib/components/user-settings-page/partner-settings.svelte b/web/src/lib/components/user-settings-page/partner-settings.svelte index 909b9ec517..b2238b84e2 100644 --- a/web/src/lib/components/user-settings-page/partner-settings.svelte +++ b/web/src/lib/components/user-settings-page/partner-settings.svelte @@ -130,7 +130,7 @@ <div class="flex gap-4 rounded-lg pb-4 transition-all justify-between"> <div class="flex gap-4"> <UserAvatar user={partner.user} size="md" /> - <div class="text-left"> + <div class="text-start"> <p class="text-immich-fg dark:text-immich-dark-fg"> {partner.user.name} </p> diff --git a/web/src/lib/components/user-settings-page/user-api-key-list.svelte b/web/src/lib/components/user-settings-page/user-api-key-list.svelte index 53e9079bff..6dae502aca 100644 --- a/web/src/lib/components/user-settings-page/user-api-key-list.svelte +++ b/web/src/lib/components/user-settings-page/user-api-key-list.svelte @@ -126,7 +126,7 @@ </div> {#if keys.length > 0} - <table class="w-full text-left"> + <table class="w-full text-start"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > diff --git a/web/src/lib/components/user-settings-page/user-profile-settings.svelte b/web/src/lib/components/user-settings-page/user-profile-settings.svelte index c36c36d7cc..90487f532f 100644 --- a/web/src/lib/components/user-settings-page/user-profile-settings.svelte +++ b/web/src/lib/components/user-settings-page/user-profile-settings.svelte @@ -42,7 +42,7 @@ <section class="my-4"> <div in:fade={{ duration: 500 }}> <form autocomplete="off" onsubmit={preventDefault(bubble('submit'))}> - <div class="ml-4 mt-4 flex flex-col gap-4"> + <div class="ms-4 mt-4 flex flex-col gap-4"> <SettingInputField inputType={SettingInputFieldType.TEXT} label={$t('user_id')} diff --git a/web/src/lib/components/user-settings-page/user-purchase-settings.svelte b/web/src/lib/components/user-settings-page/user-purchase-settings.svelte index 64dac133f2..ba8aadd73f 100644 --- a/web/src/lib/components/user-settings-page/user-purchase-settings.svelte +++ b/web/src/lib/components/user-settings-page/user-purchase-settings.svelte @@ -122,7 +122,7 @@ <!-- PRODUCT KEY INFO CARD --> {#if isServerProduct} <div - class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pr-12 rounded-xl flex place-content-center gap-4" + class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pe-12 rounded-xl flex place-content-center gap-4" > <Icon path={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" /> @@ -152,7 +152,7 @@ {/if} {:else} <div - class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pr-12 rounded-xl flex place-content-center gap-4" + class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pe-12 rounded-xl flex place-content-center gap-4" > <Icon path={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" /> diff --git a/web/src/lib/components/user-settings-page/user-usage-statistic.svelte b/web/src/lib/components/user-settings-page/user-usage-statistic.svelte index f7de1d8f64..ad77516d55 100644 --- a/web/src/lib/components/user-settings-page/user-usage-statistic.svelte +++ b/web/src/lib/components/user-settings-page/user-usage-statistic.svelte @@ -68,7 +68,7 @@ <section class="my-6"> <p class="text-xs dark:text-white uppercase">{$t('photos_and_videos')}</p> <div class="overflow-x-auto"> - <table class="w-full text-left mt-4"> + <table class="w-full text-start mt-4"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -92,7 +92,7 @@ <p class="text-xs dark:text-white uppercase">{$t('albums')}</p> </div> <div class="overflow-x-auto"> - <table class="w-full text-left mt-4"> + <table class="w-full text-start mt-4"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > diff --git a/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte b/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte index 97f44e3ec4..b8409cb0ef 100644 --- a/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte +++ b/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte @@ -44,14 +44,14 @@ <!-- FAVORITE ICON --> {#if asset.isFavorite} - <div class="absolute bottom-2 left-2"> + <div class="absolute bottom-2 start-2"> <Icon path={mdiHeart} size="24" class="text-white" /> </div> {/if} <!-- OVERLAY CHIP --> <div - class="absolute bottom-1 right-3 px-4 py-1 rounded-xl text-xs transition-colors {isSelected + class="absolute bottom-1 end-3 px-4 py-1 rounded-xl text-xs transition-colors {isSelected ? 'bg-green-400/90' : 'bg-red-300/90'}" > @@ -59,7 +59,7 @@ </div> <!-- EXTERNAL LIBRARY / STACK COUNT CHIP --> - <div class="absolute top-2 right-3"> + <div class="absolute top-2 end-3"> {#if isFromExternalLibrary} <div class="bg-immich-primary/90 px-2 py-1 rounded-xl text-xs text-white"> {$t('external')} @@ -68,7 +68,7 @@ {#if asset.stack?.assetCount} <div class="bg-immich-primary/90 px-2 py-1 my-0.5 rounded-xl text-xs text-white"> <div class="flex items-center justify-center"> - <div class="mr-1">{asset.stack.assetCount}</div> + <div class="me-1">{asset.stack.assetCount}</div> <Icon path={mdiImageMultipleOutline} size="18" /> </div> </div> @@ -79,7 +79,7 @@ <button type="button" onclick={() => onViewAsset(asset)} - class="absolute rounded-full top-1 left-1 text-gray-200 p-2 hover:text-white bg-black/35 hover:bg-black/50" + class="absolute rounded-full top-1 start-1 text-gray-200 p-2 hover:text-white bg-black/35 hover:bg-black/50" title={$t('view')} > <Icon ariaLabel={$t('view')} path={mdiMagnifyPlus} flipped size="18" /> diff --git a/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte b/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte index b7cd9aa240..d383ed1b10 100644 --- a/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte +++ b/web/src/lib/components/utilities-page/duplicates/duplicates-compare-control.svelte @@ -130,12 +130,12 @@ <div class="flex text-xs text-black"> <button type="button" - class="px-4 py-3 flex place-items-center gap-2 rounded-tl-full rounded-bl-full dark:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/90 bg-immich-primary/25 hover:bg-immich-primary/50" + class="px-4 py-3 flex place-items-center gap-2 rounded-s-full dark:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/90 bg-immich-primary/25 hover:bg-immich-primary/50" onclick={onSelectAll}><Icon path={mdiCheck} size="20" />{$t('select_keep_all')}</button > <button type="button" - class="px-4 py-3 flex place-items-center gap-2 rounded-tr-full rounded-br-full dark:bg-immich-dark-primary/50 hover:dark:bg-immich-dark-primary/70 bg-immich-primary hover:bg-immich-primary/80 text-white" + class="px-4 py-3 flex place-items-center gap-2 rounded-e-full dark:bg-immich-dark-primary/50 hover:dark:bg-immich-dark-primary/70 bg-immich-primary hover:bg-immich-primary/80 text-white" onclick={onSelectNone}><Icon path={mdiTrashCanOutline} size="20" />{$t('select_trash_all')}</button > </div> @@ -143,21 +143,11 @@ <!-- CONFIRM BUTTONS --> <div class="flex text-xs text-black"> {#if trashCount === 0} - <Button - size="sm" - color="primary" - class="flex place-items-center rounded-tl-full rounded-bl-full gap-2" - onclick={handleResolve} - > + <Button size="sm" color="primary" class="flex place-items-center rounded-s-full gap-2" onclick={handleResolve}> <Icon path={mdiCheck} size="20" />{$t('keep_all')} </Button> {:else} - <Button - size="sm" - color="red" - class="flex place-items-center rounded-tl-full rounded-bl-full gap-2 py-3" - onclick={handleResolve} - > + <Button size="sm" color="red" class="flex place-items-center rounded-s-full gap-2 py-3" onclick={handleResolve}> <Icon path={mdiTrashCanOutline} size="20" />{trashCount === assets.length ? $t('trash_all') : $t('trash_count', { values: { count: trashCount } })} @@ -166,7 +156,7 @@ <Button size="sm" color="primary" - class="flex place-items-center rounded-tr-full rounded-br-full gap-2" + class="flex place-items-center rounded-e-full gap-2" onclick={handleStack} disabled={selectedAssetIds.size !== 1} > diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts index 2c21d04865..f5b044cd41 100644 --- a/web/src/lib/constants.ts +++ b/web/src/lib/constants.ts @@ -268,8 +268,8 @@ export const defaultLang = { name: 'English', code: 'en', loader: () => import(' export const langs = [ { name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') }, - { name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json') }, - { name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json') }, + { name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true }, + { name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true }, { name: 'Belarusian', code: 'be', loader: () => import('$i18n/be.json') }, { name: 'Bulgarian', code: 'bg', loader: () => import('$i18n/bg.json') }, { name: 'Bislama', code: 'bi', loader: () => import('$i18n/bi.json') }, @@ -284,12 +284,12 @@ export const langs = [ { name: 'Spanish', code: 'es', loader: () => import('$i18n/es.json') }, { name: 'Estonian', code: 'et', loader: () => import('$i18n/et.json') }, { name: 'Basque', code: 'eu', loader: () => import('$i18n/eu.json') }, - { name: 'Persian', code: 'fa', loader: () => import('$i18n/fa.json') }, + { name: 'Persian', code: 'fa', loader: () => import('$i18n/fa.json'), rtl: true }, { name: 'Finnish', code: 'fi', loader: () => import('$i18n/fi.json') }, { name: 'Filipino', code: 'fil', loader: () => import('$i18n/fil.json') }, { name: 'French', code: 'fr', loader: () => import('$i18n/fr.json') }, { name: 'Galician', code: 'gl', loader: () => import('$i18n/gl.json') }, - { name: 'Hebrew', code: 'he', loader: () => import('$i18n/he.json') }, + { name: 'Hebrew', code: 'he', loader: () => import('$i18n/he.json'), rtl: true }, { name: 'Hindi', code: 'hi', loader: () => import('$i18n/hi.json') }, { name: 'Croatian', code: 'hr', loader: () => import('$i18n/hr.json') }, { name: 'Hungarian', code: 'hu', loader: () => import('$i18n/hu.json') }, @@ -299,7 +299,7 @@ export const langs = [ { name: 'Japanese', code: 'ja', loader: () => import('$i18n/ja.json') }, { name: 'Georgian', code: 'ka', loader: () => import('$i18n/ka.json') }, { name: 'Kazakh', code: 'kk', loader: () => import('$i18n/kk.json') }, - { name: 'Kurdish (Northern)', code: 'kmr', loader: () => import('$i18n/kmr.json') }, + { name: 'Kurdish (Northern)', code: 'kmr', loader: () => import('$i18n/kmr.json'), rtl: true }, { name: 'Kannada', code: 'kn', loader: () => import('$i18n/kn.json') }, { name: 'Korean', code: 'ko', loader: () => import('$i18n/ko.json') }, { name: 'Luxembourgish', code: 'lb', loader: () => import('$i18n/lb.json') }, @@ -335,7 +335,7 @@ export const langs = [ { name: 'Thai', code: 'th', loader: () => import('$i18n/th.json') }, { name: 'Turkish', code: 'tr', loader: () => import('$i18n/tr.json') }, { name: 'Ukrainian', code: 'uk', loader: () => import('$i18n/uk.json') }, - { name: 'Urdu', code: 'ur', loader: () => import('$i18n/ur.json') }, + { name: 'Urdu', code: 'ur', loader: () => import('$i18n/ur.json'), rtl: true }, { name: 'Vietnamese', code: 'vi', loader: () => import('$i18n/vi.json') }, { name: 'Chinese (Traditional)', diff --git a/web/src/lib/stores/event-manager.svelte.ts b/web/src/lib/stores/event-manager.svelte.ts index 09e9b45c3c..335c5cbefb 100644 --- a/web/src/lib/stores/event-manager.svelte.ts +++ b/web/src/lib/stores/event-manager.svelte.ts @@ -51,4 +51,5 @@ class EventManager<EventMap extends Record<string, unknown[]>> { export const eventManager = new EventManager<{ 'user.login': []; 'auth.logout': []; + 'language.change': [{ name: string; code: string; rtl?: boolean }]; }>(); diff --git a/web/src/lib/stores/language-manager.svelte.ts b/web/src/lib/stores/language-manager.svelte.ts new file mode 100644 index 0000000000..70b3245e0f --- /dev/null +++ b/web/src/lib/stores/language-manager.svelte.ts @@ -0,0 +1,21 @@ +import { langs } from '$lib/constants'; +import { eventManager } from '$lib/stores/event-manager.svelte'; + +class LanguageManager { + rtl = $state(false); + + setLanguage(code: string) { + const item = langs.find((item) => item.code === code); + if (!item) { + return; + } + + this.rtl = item.rtl ?? false; + + document.body.setAttribute('dir', item.rtl ? 'rtl' : 'ltr'); + + eventManager.emit('language.change', item); + } +} + +export const languageManager = new LanguageManager(); diff --git a/web/src/lib/utils/album-utils.ts b/web/src/lib/utils/album-utils.ts index 74a2e3c5e9..a5b830774c 100644 --- a/web/src/lib/utils/album-utils.ts +++ b/web/src/lib/utils/album-utils.ts @@ -59,7 +59,7 @@ export const sortOptionsMetadata: AlbumSortOptionMetadata[] = [ { id: AlbumSortBy.Title, defaultOrder: SortOrder.Asc, - columnStyle: 'text-left w-8/12 sm:w-4/12 md:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%]', + columnStyle: 'text-start w-8/12 sm:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%]', }, { id: AlbumSortBy.ItemCount, diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 818f48fe4a..767902bd94 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -708,7 +708,7 @@ </AssetGrid> {#if showActivityStatus} - <div class="absolute z-[2] bottom-0 right-0 mb-6 mr-6 justify-self-end"> + <div class="absolute z-[2] bottom-0 end-0 mb-6 me-6 justify-self-end"> <ActivityStatus disabled={!album.isActivityEnabled} {isLiked} @@ -725,7 +725,7 @@ <div transition:fly={{ duration: 150 }} id="activity-panel" - class="z-[2] w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg" + class="z-[2] w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg" translate="yes" > <ActivityViewer diff --git a/web/src/routes/(user)/explore/+page.svelte b/web/src/routes/(user)/explore/+page.svelte index ec62d5e869..49d38d0815 100644 --- a/web/src/routes/(user)/explore/+page.svelte +++ b/web/src/routes/(user)/explore/+page.svelte @@ -48,7 +48,7 @@ <p class="mb-4 font-medium dark:text-immich-dark-fg">{$t('people')}</p> <a href={AppRoute.PEOPLE} - class="pr-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary" + class="pe-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary" draggable="false">{$t('view_all')}</a > </div> @@ -64,7 +64,7 @@ widthStyle="100%" /> {#if person.isFavorite} - <div class="absolute top-2 left-2"> + <div class="absolute top-2 start-2"> <Icon path={mdiHeart} size="24" class="text-white" /> </div> {/if} @@ -82,7 +82,7 @@ <p class="mb-4 font-medium dark:text-immich-dark-fg">{$t('places')}</p> <a href={AppRoute.PLACES} - class="pr-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary" + class="pe-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary" draggable="false">{$t('view_all')}</a > </div> diff --git a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte index f5a4f6cd09..d1fc0bcd90 100644 --- a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -87,7 +87,7 @@ </script> {#if assetInteraction.selectionActive} - <div class="fixed z-[910] top-0 left-0 w-full"> + <div class="fixed z-[910] top-0 start-0 w-full"> <AssetSelectControlBar assets={assetInteraction.selectedAssets} clearSelect={() => cancelMultiselect(assetInteraction)} @@ -133,7 +133,7 @@ <SideBarSection> <SkipLink target={`#${headerId}`} text={$t('skip_to_folders')} breakpoint="md" /> <section> - <div class="text-xs pl-4 mb-2 dark:text-white">{$t('explorer').toUpperCase()}</div> + <div class="text-xs ps-4 mb-2 dark:text-white">{$t('explorer').toUpperCase()}</div> <div class="h-full"> <TreeItems icons={{ default: mdiFolderOutline, active: mdiFolder }} diff --git a/web/src/routes/(user)/people/+page.svelte b/web/src/routes/(user)/people/+page.svelte index 3e1b5a774c..fd632fccce 100644 --- a/web/src/routes/(user)/people/+page.svelte +++ b/web/src/routes/(user)/people/+page.svelte @@ -458,7 +458,7 @@ <dialog open transition:fly={{ y: innerHeight, duration: 150, easing: quintOut, opacity: 0 }} - class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" + class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg" aria-modal="true" aria-labelledby="manage-visibility-title" use:focusTrap diff --git a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 36b59e3ace..4c58f52265 100644 --- a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -486,7 +486,7 @@ </header> <main - class="relative h-dvh overflow-hidden bg-immich-bg tall:ml-4 md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg" + class="relative h-dvh overflow-hidden bg-immich-bg tall:ms-4 md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg" use:scrollMemoryClearer={{ routeStartsWith: AppRoute.PEOPLE, beforeClear: () => { @@ -542,7 +542,7 @@ heightStyle="3.375rem" /> <div - class="flex flex-col justify-center text-left px-4 text-immich-primary dark:text-immich-dark-primary" + class="flex flex-col justify-center text-start px-4 text-immich-primary dark:text-immich-dark-primary" > <p class="w-40 sm:w-72 font-medium truncate">{person.name || $t('add_a_name')}</p> <p class="text-sm text-gray-500 dark:text-immich-gray"> @@ -598,7 +598,7 @@ widthStyle="2rem" heightStyle="2rem" /> - <p class="ml-4 text-gray-700 dark:text-gray-100">{person.name}</p> + <p class="ms-4 text-gray-700 dark:text-gray-100">{person.name}</p> </button> {/each} </div> diff --git a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte index c985104e3c..9d427e1ea7 100644 --- a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -251,7 +251,7 @@ <section> {#if assetInteraction.selectionActive} - <div class="fixed z-[100] top-0 left-0 w-full"> + <div class="fixed z-[100] top-0 start-0 w-full"> <AssetSelectControlBar assets={assetInteraction.selectedAssets} clearSelect={() => cancelMultiselect(assetInteraction)} @@ -289,13 +289,13 @@ </AssetSelectControlBar> </div> {:else} - <div class="fixed z-[100] top-0 left-0 w-full"> + <div class="fixed z-[100] top-0 start-0 w-full"> <ControlAppBar onClose={() => goto(previousRoute)} backIcon={mdiArrowLeft}> <div class="-z-[1] bg-immich-bg dark:bg-immich-dark-bg" style="position:absolute;top:0;left:0;right:0;bottom:0;" ></div> - <div class="w-full flex-1 pl-4"> + <div class="w-full flex-1 ps-4"> <SearchBar grayTheme={false} value={terms?.query ?? ''} searchQuery={terms} /> </div> </ControlAppBar> @@ -313,13 +313,13 @@ <div class="flex place-content-center place-items-center text-xs"> <div class="bg-immich-primary py-2 px-4 text-white dark:text-black dark:bg-immich-dark-primary - {value === true ? 'rounded-full' : 'rounded-tl-full rounded-bl-full'}" + {value === true ? 'rounded-full' : 'roudned-s-full'}" > {getHumanReadableSearchKey(key as keyof SearchTerms)} </div> {#if value !== true} - <div class="bg-gray-300 py-2 px-4 dark:bg-gray-800 dark:text-white rounded-tr-full rounded-br-full"> + <div class="bg-gray-300 py-2 px-4 dark:bg-gray-800 dark:text-white rounded-e-full"> {#if (key === 'takenAfter' || key === 'takenBefore') && typeof value === 'string'} {getHumanReadableDate(value)} {:else if key === 'personIds' && Array.isArray(value)} @@ -349,7 +349,7 @@ > {#if searchResultAlbums.length > 0} <section> - <div class="ml-6 text-4xl font-medium text-black/70 dark:text-white/80">{$t('albums').toUpperCase()}</div> + <div class="ms-6 text-4xl font-medium text-black/70 dark:text-white/80">{$t('albums').toUpperCase()}</div> <AlbumCardGroup albums={searchResultAlbums} showDateRange showItemCount /> <div class="m-6 text-4xl font-medium text-black/70 dark:text-white/80"> diff --git a/web/src/routes/(user)/sharing/+page.svelte b/web/src/routes/(user)/sharing/+page.svelte index e3d6ac1ced..a55452b5d1 100644 --- a/web/src/routes/(user)/sharing/+page.svelte +++ b/web/src/routes/(user)/sharing/+page.svelte @@ -68,7 +68,7 @@ class="flex gap-4 rounded-lg px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700" > <UserAvatar user={partner} size="lg" /> - <div class="text-left"> + <div class="text-start"> <p class="text-immich-fg dark:text-immich-dark-fg"> {partner.name} </p> diff --git a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte index 8bb43676e8..8d33a2eb6e 100644 --- a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -146,7 +146,7 @@ <SideBarSection> <SkipLink target={`#${headerId}`} text={$t('skip_to_tags')} breakpoint="md" /> <section> - <div class="text-xs pl-4 mb-2 dark:text-white">{$t('explorer').toUpperCase()}</div> + <div class="text-xs ps-4 mb-2 dark:text-white">{$t('explorer').toUpperCase()}</div> <div class="h-full"> <TreeItems icons={{ default: mdiTag, active: mdiTag }} diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index f3b3930e12..6df1010760 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -11,7 +11,8 @@ import UploadPanel from '$lib/components/shared-components/upload-panel.svelte'; import VersionAnnouncementBox from '$lib/components/shared-components/version-announcement-box.svelte'; import { Theme } from '$lib/constants'; - import { colorTheme, handleToggleTheme, type ThemeSetting } from '$lib/stores/preferences.store'; + import { languageManager } from '$lib/stores/language-manager.svelte'; + import { colorTheme, handleToggleTheme, lang, type ThemeSetting } from '$lib/stores/preferences.store'; import { serverConfig } from '$lib/stores/server-config.store'; import { user } from '$lib/stores/user.store'; import { closeWebsocketConnection, openWebsocketConnection } from '$lib/stores/websocket'; @@ -66,6 +67,8 @@ element?.remove(); // if the browser theme changes, changes the Immich theme too globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', handleChangeTheme); + + return lang.subscribe((lang) => languageManager.setLanguage(lang)); }); onDestroy(() => { diff --git a/web/src/routes/admin/jobs-status/+page.svelte b/web/src/routes/admin/jobs-status/+page.svelte index 21381081e0..07757614e5 100644 --- a/web/src/routes/admin/jobs-status/+page.svelte +++ b/web/src/routes/admin/jobs-status/+page.svelte @@ -107,7 +107,7 @@ > {#snippet promptSnippet()} <form {onsubmit} autocomplete="off" id="create-tag-form" class="w-full"> - <div class="flex flex-col gap-1 text-left"> + <div class="flex flex-col gap-1 text-start"> <Combobox bind:selectedOption={selectedJob} label={$t('jobs')} diff --git a/web/src/routes/admin/library-management/+page.svelte b/web/src/routes/admin/library-management/+page.svelte index 9a598101e1..23ebcfbf0b 100644 --- a/web/src/routes/admin/library-management/+page.svelte +++ b/web/src/routes/admin/library-management/+page.svelte @@ -282,7 +282,7 @@ <section class="my-4"> <div class="flex flex-col gap-2" in:fade={{ duration: 500 }}> {#if libraries.length > 0} - <table class="w-full text-left"> + <table class="w-full text-start"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -369,7 +369,7 @@ {/if} {#if editScanSettings === index} <!-- svelte-ignore node_invalid_placement_ssr --> - <div transition:slide={{ duration: 250 }} class="mb-4 ml-4 mr-4"> + <div transition:slide={{ duration: 250 }} class="mb-4 ms-4 me-4"> <LibraryScanSettingsForm {library} onSubmit={handleUpdate} diff --git a/web/src/routes/admin/repair/+page.svelte b/web/src/routes/admin/repair/+page.svelte index 635a140452..b04d8f1944 100644 --- a/web/src/routes/admin/repair/+page.svelte +++ b/web/src/routes/admin/repair/+page.svelte @@ -228,7 +228,7 @@ </div> {:else} <div class="gap-2"> - <table class="table-fixed mt-5 w-full text-left"> + <table class="table-fixed mt-5 w-full text-start"> <thead class="mb-4 flex w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -265,7 +265,7 @@ </tbody> </table> - <table class="table-fixed mt-5 w-full text-left"> + <table class="table-fixed mt-5 w-full text-start"> <thead class="mb-4 flex w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -295,7 +295,7 @@ <td onclick={() => copyToClipboard(orphan.pathValue)}> <CircleIconButton title={$t('copy_file_path')} icon={mdiContentCopy} size="18" onclick={() => {}} /> </td> - <td class="truncate text-sm font-mono text-left" title={orphan.pathValue}> + <td class="truncate text-sm font-mono text-start" title={orphan.pathValue}> {orphan.pathValue} </td> <td class="text-sm font-mono"> @@ -306,7 +306,7 @@ </tbody> </table> - <table class="table-fixed mt-5 w-full text-left max-h-[300px]"> + <table class="table-fixed mt-5 w-full text-start max-h-[300px]"> <thead class="mb-4 flex w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > @@ -337,11 +337,11 @@ <td onclick={() => copyToClipboard(extra.filename)}> <CircleIconButton title={$t('copy_file_path')} icon={mdiContentCopy} size="18" onclick={() => {}} /> </td> - <td class="w-full text-md text-ellipsis flex justify-between pr-5"> - <span class="text-ellipsis grow truncate font-mono text-sm pr-5" title={extra.filename} + <td class="w-full text-md text-ellipsis flex justify-between pe-5"> + <span class="text-ellipsis grow truncate font-mono text-sm pe-5" title={extra.filename} >{extra.filename}</span > - <span class="text-sm font-mono dark:text-immich-dark-primary text-immich-primary pr-5"> + <span class="text-sm font-mono dark:text-immich-dark-primary text-immich-primary pes-5"> {#if extra.checksum} [sha1:{extra.checksum}] {/if} diff --git a/web/src/routes/admin/user-management/+page.svelte b/web/src/routes/admin/user-management/+page.svelte index 0ca17c4ed8..a25799588a 100644 --- a/web/src/routes/admin/user-management/+page.svelte +++ b/web/src/routes/admin/user-management/+page.svelte @@ -180,7 +180,7 @@ </ConfirmDialog> {/if} - <table class="my-5 w-full text-left"> + <table class="my-5 w-full text-start"> <thead class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary" > diff --git a/web/src/routes/auth/login/+page.svelte b/web/src/routes/auth/login/+page.svelte index c3d01b3c56..aa756ac2e8 100644 --- a/web/src/routes/auth/login/+page.svelte +++ b/web/src/routes/auth/login/+page.svelte @@ -132,7 +132,7 @@ <div class="inline-flex w-full items-center justify-center my-4"> <hr class="my-4 h-px w-3/4 border-0 bg-gray-200 dark:bg-gray-600" /> <span - class="absolute left-1/2 -translate-x-1/2 bg-gray-50 px-3 font-medium text-gray-900 dark:bg-neutral-900 dark:text-white" + class="absolute start-1/2 -translate-x-1/2 bg-gray-50 px-3 font-medium text-gray-900 dark:bg-neutral-900 dark:text-white" > {$t('or').toUpperCase()} </span>