diff --git a/webapp/src/components/backup-center/BackupOperationsSidebar.tsx b/webapp/src/components/backup-center/BackupOperationsSidebar.tsx
index 61390e2..1b9720c 100644
--- a/webapp/src/components/backup-center/BackupOperationsSidebar.tsx
+++ b/webapp/src/components/backup-center/BackupOperationsSidebar.tsx
@@ -41,42 +41,47 @@ export function BackupOperationsSidebar(props: BackupOperationsSidebarProps) {
-
+
+
+
+ {t('txt_backup_recommend_title')}
+ {t('txt_backup_recommend_group_webdav')} · {t('txt_backup_recommend_group_s3')}
+
+
+
-
-
{t('txt_backup_recommend_title')}
-
-
-
{t('txt_backup_recommend_group_webdav')}
-
- {props.recommendedWebDavProviders.map((provider) => (
-
+
+
);
}
diff --git a/webapp/src/components/vault/VaultEditor.tsx b/webapp/src/components/vault/VaultEditor.tsx
index 2648525..42a849e 100644
--- a/webapp/src/components/vault/VaultEditor.tsx
+++ b/webapp/src/components/vault/VaultEditor.tsx
@@ -109,7 +109,13 @@ function WebsiteRow(props: WebsiteRowProps) {
))}
{props.canRemove && (
- props.onRemove(props.index)}>
+ props.onRemove(props.index)}
+ >
{t('txt_remove')}
diff --git a/webapp/src/lib/i18n/locales/en.ts b/webapp/src/lib/i18n/locales/en.ts
index ebb60be..3862ce4 100644
--- a/webapp/src/lib/i18n/locales/en.ts
+++ b/webapp/src/lib/i18n/locales/en.ts
@@ -766,13 +766,13 @@ const en: Record = {
"txt_user_deleted": "User deleted",
"txt_user_status_updated": "User status updated",
"txt_username": "Username",
- "txt_uri_match_default_base_domain": "Default (Base Domain)",
+ "txt_uri_match_default_base_domain": "Default",
"txt_uri_match_base_domain": "Base Domain",
"txt_uri_match_host": "Host",
"txt_uri_match_exact": "Exact",
"txt_uri_match_never": "Never",
"txt_uri_match_starts_with": "Starts With",
- "txt_uri_match_regular_expression": "Regular Expression",
+ "txt_uri_match_regular_expression": "Regex",
"txt_users": "Users",
"txt_vault_synced": "Vault synced",
"txt_verification_code": "Verification Code",
diff --git a/webapp/src/lib/i18n/locales/es.ts b/webapp/src/lib/i18n/locales/es.ts
index b6d968e..5192f4b 100644
--- a/webapp/src/lib/i18n/locales/es.ts
+++ b/webapp/src/lib/i18n/locales/es.ts
@@ -766,13 +766,13 @@ const es: Record = {
"txt_user_deleted": "Usuario eliminado",
"txt_user_status_updated": "Estado del usuario actualizado",
"txt_username": "Nombre de usuario",
- "txt_uri_match_default_base_domain": "Predeterminado (dominio base)",
+ "txt_uri_match_default_base_domain": "Predet.",
"txt_uri_match_base_domain": "Dominio base",
"txt_uri_match_host": "Host",
"txt_uri_match_exact": "Exacto",
"txt_uri_match_never": "Nunca",
"txt_uri_match_starts_with": "Empieza con",
- "txt_uri_match_regular_expression": "Expresión regular",
+ "txt_uri_match_regular_expression": "Regex",
"txt_users": "Usuarios",
"txt_vault_synced": "Bóveda sincronizada",
"txt_verification_code": "Código de verificación",
diff --git a/webapp/src/lib/i18n/locales/ru.ts b/webapp/src/lib/i18n/locales/ru.ts
index ed1fdf7..68b7cde 100644
--- a/webapp/src/lib/i18n/locales/ru.ts
+++ b/webapp/src/lib/i18n/locales/ru.ts
@@ -766,13 +766,13 @@ const ru: Record = {
"txt_user_deleted": "Пользователь удален",
"txt_user_status_updated": "Статус пользователя обновлен",
"txt_username": "Имя пользователя",
- "txt_uri_match_default_base_domain": "По умолчанию (базовый домен)",
+ "txt_uri_match_default_base_domain": "По умолч.",
"txt_uri_match_base_domain": "Базовый домен",
"txt_uri_match_host": "Хост",
"txt_uri_match_exact": "Точный",
"txt_uri_match_never": "Никогда",
"txt_uri_match_starts_with": "Начинается с",
- "txt_uri_match_regular_expression": "Регулярное выражение",
+ "txt_uri_match_regular_expression": "Regex",
"txt_users": "Пользователи",
"txt_vault_synced": "Сейф синхронизирован",
"txt_verification_code": "Код подтверждения",
diff --git a/webapp/src/lib/i18n/locales/zh-CN.ts b/webapp/src/lib/i18n/locales/zh-CN.ts
index cdf373f..d9e2ace 100644
--- a/webapp/src/lib/i18n/locales/zh-CN.ts
+++ b/webapp/src/lib/i18n/locales/zh-CN.ts
@@ -766,13 +766,13 @@ const zhCN: Record = {
"txt_user_deleted": "用户已删除",
"txt_user_status_updated": "用户状态已更新",
"txt_username": "用户名",
- "txt_uri_match_default_base_domain": "默认(基础域名)",
+ "txt_uri_match_default_base_domain": "默认",
"txt_uri_match_base_domain": "基础域名",
"txt_uri_match_host": "主机",
"txt_uri_match_exact": "精确",
"txt_uri_match_never": "从不",
"txt_uri_match_starts_with": "开始于",
- "txt_uri_match_regular_expression": "正则表达式",
+ "txt_uri_match_regular_expression": "正则表达",
"txt_users": "用户",
"txt_vault_synced": "密码库已同步",
"txt_verification_code": "验证码",
diff --git a/webapp/src/lib/i18n/locales/zh-TW.ts b/webapp/src/lib/i18n/locales/zh-TW.ts
index 7d6a240..94092f3 100644
--- a/webapp/src/lib/i18n/locales/zh-TW.ts
+++ b/webapp/src/lib/i18n/locales/zh-TW.ts
@@ -766,13 +766,13 @@ const zhTW: Record = {
"txt_user_deleted": "用戶已刪除",
"txt_user_status_updated": "用戶狀態已更新",
"txt_username": "用戶名",
- "txt_uri_match_default_base_domain": "默認(基礎域名)",
+ "txt_uri_match_default_base_domain": "默認",
"txt_uri_match_base_domain": "基礎域名",
"txt_uri_match_host": "主機",
"txt_uri_match_exact": "精確",
"txt_uri_match_never": "從不",
"txt_uri_match_starts_with": "開始於",
- "txt_uri_match_regular_expression": "正則表達式",
+ "txt_uri_match_regular_expression": "正則表達",
"txt_users": "用戶",
"txt_vault_synced": "密碼庫已同步",
"txt_verification_code": "驗證碼",
diff --git a/webapp/src/styles/dark.css b/webapp/src/styles/dark.css
index b68ac1e..33c63ce 100644
--- a/webapp/src/styles/dark.css
+++ b/webapp/src/styles/dark.css
@@ -208,6 +208,7 @@
:root[data-theme='dark'] .backup-help-bubble,
:root[data-theme='dark'] .backup-recommendation-card,
:root[data-theme='dark'] .backup-recommendation-dav-item,
+:root[data-theme='dark'] .backup-recommendations-summary,
:root[data-theme='dark'] .backup-browser-path,
:root[data-theme='dark'] .backup-browser-list,
:root[data-theme='dark'] .restore-progress-card,
diff --git a/webapp/src/styles/management.css b/webapp/src/styles/management.css
index f22ace6..86e5946 100644
--- a/webapp/src/styles/management.css
+++ b/webapp/src/styles/management.css
@@ -34,6 +34,50 @@
@apply grid gap-2.5;
}
+.backup-recommendations-disclosure {
+ @apply mt-3;
+}
+
+.backup-recommendations-summary {
+ @apply flex cursor-pointer list-none items-center justify-between gap-3 rounded-xl border px-3 py-2.5;
+ border-color: var(--line);
+ background: #f8fafc;
+ color: #0f172a;
+}
+
+.backup-recommendations-summary::-webkit-details-marker {
+ display: none;
+}
+
+.backup-recommendations-summary > span:first-child {
+ @apply grid min-w-0 gap-0.5;
+}
+
+.backup-recommendations-summary strong {
+ @apply text-sm;
+}
+
+.backup-recommendations-summary small {
+ @apply text-xs font-semibold;
+ color: #64748b;
+}
+
+.backup-recommendations-summary-icon {
+ @apply h-2.5 w-2.5 shrink-0;
+ border-right: 2px solid #365fa8;
+ border-bottom: 2px solid #365fa8;
+ transform: rotate(45deg) translateY(-2px);
+ transition: transform var(--dur-fast) var(--ease-out-soft);
+}
+
+.backup-recommendations-disclosure[open] .backup-recommendations-summary-icon {
+ transform: rotate(225deg) translate(-1px, -1px);
+}
+
+.backup-recommendations-body {
+ @apply pt-2.5;
+}
+
.backup-option-field {
@apply inline-flex items-center gap-2;
}
@@ -576,7 +620,7 @@
.website-row {
@apply mb-2 grid items-center gap-2 rounded-[18px] border p-1.5;
- grid-template-columns: auto minmax(0, 1fr) minmax(130px, 160px) auto;
+ grid-template-columns: auto minmax(0, 1fr) minmax(96px, 120px) auto;
border-color: transparent;
background: color-mix(in srgb, var(--panel) 84%, transparent);
transition:
@@ -605,7 +649,7 @@
}
.website-match-select {
- @apply h-12 py-2.5 pr-[38px] text-[13px] leading-[1.2];
+ @apply h-12 py-2.5 pr-[30px] text-[13px] leading-[1.2];
}
.website-match-select option {
@@ -618,30 +662,22 @@
@media (max-width: 760px) {
.website-row {
- grid-template-columns: auto minmax(0, 1fr) auto;
- @apply items-start;
+ grid-template-columns: auto minmax(88px, 1fr) minmax(72px, 84px) auto;
+ @apply items-center;
}
- .website-row > :nth-child(1) {
- grid-column: 1;
- grid-row: 1;
- align-self: center;
+ .website-row .website-remove-btn {
+ width: 30px;
+ min-width: 30px;
+ height: 30px;
+ padding: 0;
+ gap: 0;
+ border-radius: 999px;
+ font-size: 0;
}
- .website-row > :nth-child(2) {
- grid-column: 2 / span 2;
- grid-row: 1;
- }
-
- .website-row > :nth-child(3) {
- grid-column: 1 / span 2;
- grid-row: 2;
- }
-
- .website-row > :nth-child(4) {
- grid-column: 3;
- grid-row: 2;
- justify-self: start;
+ .website-row .website-remove-btn .btn-icon {
+ margin: 0;
}
}
diff --git a/webapp/src/styles/responsive.css b/webapp/src/styles/responsive.css
index 7d29ce2..b5225b5 100644
--- a/webapp/src/styles/responsive.css
+++ b/webapp/src/styles/responsive.css
@@ -360,7 +360,7 @@
}
.list-item {
- @apply rounded-[14px] p-3;
+ @apply rounded-[14px] py-2 px-3;
}
.row-check {
@@ -432,6 +432,163 @@
@apply p-3.5;
}
+ .mobile-detail-sheet {
+ padding-bottom: 10px;
+ }
+
+ .mobile-panel-head {
+ margin: 6px 8px 8px;
+ }
+
+ .mobile-panel-back {
+ min-height: 36px;
+ }
+
+ .mobile-detail-sheet > .detail-switch-stage,
+ .mobile-detail-sheet > .card,
+ .mobile-detail-sheet > .empty {
+ margin-left: 8px;
+ margin-right: 8px;
+ }
+
+ .mobile-detail-sheet .card {
+ margin-bottom: 8px;
+ padding: 10px 12px;
+ border-radius: 14px;
+ }
+
+ .mobile-detail-sheet .card h4 {
+ margin: 0 0 8px;
+ font-size: 15px;
+ line-height: 1.25;
+ }
+
+ .mobile-detail-sheet .detail-title {
+ font-size: 15px;
+ line-height: 1.25;
+ }
+
+ .mobile-detail-sheet .section-head {
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ margin-bottom: 8px;
+ min-width: 0;
+ }
+
+ .mobile-detail-sheet .section-head h3,
+ .mobile-detail-sheet .section-head h4 {
+ margin: 0;
+ min-width: 0;
+ }
+
+ .mobile-detail-sheet .section-head > .btn.small {
+ flex: 0 0 auto;
+ height: 32px;
+ padding: 0 10px;
+ font-size: 13px;
+ }
+
+ .mobile-detail-sheet .field {
+ margin-bottom: 8px;
+ }
+
+ .mobile-detail-sheet .field > span {
+ margin: 0 0 4px;
+ font-size: 13px;
+ line-height: 1.2;
+ }
+
+ .mobile-detail-sheet .field-grid {
+ gap: 0px;
+ }
+
+ .mobile-detail-sheet .input {
+ height: 42px;
+ border-radius: 12px;
+ padding: 8px 11px;
+ font-size: 15px;
+ }
+
+ .mobile-detail-sheet select.input {
+ padding-right: 30px;
+ background-position:
+ calc(100% - 15px) calc(50% - 3px),
+ calc(100% - 9px) calc(50% - 3px);
+ }
+
+ .mobile-detail-sheet .textarea {
+ min-height: 82px;
+ }
+
+ .mobile-detail-sheet .input-action-wrap .input {
+ padding-right: 42px;
+ }
+
+ .mobile-detail-sheet .input-icon-btn {
+ right: 6px;
+ width: 30px;
+ height: 30px;
+ }
+
+ .mobile-detail-sheet .website-row {
+ grid-template-columns: auto minmax(88px, 1fr) minmax(72px, 84px) auto;
+ gap: 5px;
+ align-items: center;
+ margin-bottom: 6px;
+ padding: 4px;
+ border-radius: 12px;
+ }
+
+ .mobile-detail-sheet .website-row > * {
+ grid-column: auto !important;
+ grid-row: auto !important;
+ }
+
+ .mobile-detail-sheet .website-order-actions {
+ gap: 2px;
+ }
+
+ .mobile-detail-sheet .website-order-btn {
+ width: 24px;
+ min-width: 24px;
+ height: 19px;
+ border-radius: 7px;
+ }
+
+ .mobile-detail-sheet .website-match-select {
+ height: 40px;
+ min-width: 0;
+ padding-left: 8px;
+ padding-right: 24px;
+ font-size: 12px;
+ background-position:
+ calc(100% - 12px) calc(50% - 3px),
+ calc(100% - 7px) calc(50% - 3px);
+ background-size: 5px 5px, 5px 5px;
+ }
+
+ .mobile-detail-sheet .website-remove-btn {
+ width: 30px;
+ min-width: 30px;
+ height: 30px;
+ padding: 0;
+ gap: 0;
+ border-radius: 999px;
+ font-size: 0;
+ }
+
+ .mobile-detail-sheet .website-remove-btn .btn-icon {
+ margin: 0;
+ }
+
+ .mobile-detail-sheet .attachment-row,
+ .mobile-detail-sheet .custom-field-card {
+ padding-top: 7px;
+ padding-bottom: 7px;
+ }
+
.section-head {
@apply flex-col items-start gap-2.5;
}
@@ -666,34 +823,71 @@
@media (max-width: 1180px) {
.backup-grid {
grid-template-columns: 1fr;
+ gap: 8px;
}
.backup-operations-sidebar,
- .backup-destination-sidebar {
+ .backup-destination-sidebar,
+ .backup-detail-panel {
position: static;
+ padding: 12px;
+ border-radius: 14px;
}
}
@media (max-width: 640px) {
+ .settings-modules-grid {
+ gap: 8px;
+ }
+
+ .settings-module {
+ padding: 10px 12px;
+ border-radius: 14px;
+ }
+
.settings-module h3 {
- margin-bottom: 12px;
+ margin-bottom: 8px;
+ font-size: 15px;
+ line-height: 1.25;
}
.settings-module .field,
.auth-card .field {
- margin-bottom: 12px;
+ margin-bottom: 8px;
}
.settings-module .field > span,
.auth-card .field > span {
margin-top: 0;
- margin-bottom: 6px;
+ margin-bottom: 4px;
+ font-size: 13px;
+ line-height: 1.2;
}
.settings-module .field-grid,
.auth-card .field-grid,
.session-timeout-fields {
- gap: 12px;
+ gap: 8px;
+ }
+
+ .settings-module .input {
+ height: 42px;
+ border-radius: 12px;
+ padding: 8px 11px;
+ font-size: 15px;
+ }
+
+ .settings-module select.input {
+ padding-right: 30px;
+ background-position:
+ calc(100% - 15px) calc(50% - 3px),
+ calc(100% - 9px) calc(50% - 3px);
+ }
+
+ .settings-module .field-help {
+ margin-top: 5px;
+ font-size: 12px;
+ line-height: 1.35;
}
.settings-module .btn,
@@ -701,6 +895,46 @@
margin-top: 2px;
}
+ .settings-module .actions {
+ gap: 7px;
+ }
+
+ .settings-module .totp-grid {
+ gap: 8px;
+ margin-bottom: 8px;
+ }
+
+ .settings-module .totp-qr {
+ min-height: 132px;
+ padding: 8px;
+ }
+
+ .settings-module .totp-qr svg,
+ .settings-module .totp-qr img {
+ width: 118px;
+ height: 118px;
+ }
+
+ .settings-module .sensitive-actions-grid {
+ gap: 8px;
+ }
+
+ .settings-module .sensitive-action {
+ padding: 10px;
+ border-radius: 12px;
+ }
+
+ .settings-module .sensitive-action h4 {
+ margin-bottom: 4px;
+ font-size: 14px;
+ }
+
+ .settings-field-note {
+ margin-bottom: 7px;
+ font-size: 12px;
+ line-height: 1.35;
+ }
+
.dialog-mask.totp-scan-mask {
display: block;
padding: 0;
@@ -720,6 +954,7 @@
.backup-interval-row {
grid-template-columns: 1fr;
+ gap: 7px;
}
.backup-browser-row,
@@ -727,9 +962,149 @@
grid-template-columns: 1fr;
}
- .backup-destination-top {
- align-items: flex-start;
+ .backup-grid {
+ gap: 8px;
+ padding: 0;
+ }
+
+ .backup-operations-sidebar,
+ .backup-destination-sidebar,
+ .backup-detail-panel {
+ padding: 10px 12px;
+ border-radius: 14px;
+ }
+
+ .backup-operations-sidebar .section-head,
+ .backup-destination-sidebar .section-head,
+ .backup-detail-panel .section-head {
+ flex-direction: row;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 8px;
+ }
+
+ .backup-detail-panel > .section-head {
flex-direction: column;
+ align-items: stretch;
+ }
+
+ .backup-detail-panel > .section-head .actions {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 6px;
+ width: 100%;
+ }
+
+ .backup-detail-panel > .section-head .actions .btn {
+ height: 36px;
+ min-width: 0;
+ padding: 0 8px;
+ font-size: 12px;
+ }
+
+ .backup-operations-sidebar .section-head h3,
+ .backup-destination-sidebar .section-head h3,
+ .backup-detail-panel .section-head h3 {
+ margin: 0;
+ font-size: 15px;
+ line-height: 1.25;
+ }
+
+ .backup-actions-stack,
+ .backup-destination-list,
+ .backup-recommendation-list {
+ gap: 7px;
+ }
+
+ .backup-actions-stack .btn,
+ .backup-destination-addbar .btn {
+ height: 38px;
+ }
+
+ .backup-recommendations-disclosure {
+ margin-top: 8px;
+ }
+
+ .backup-recommendations-summary {
+ padding: 8px 10px;
+ border-radius: 12px;
+ }
+
+ .backup-recommendations-body {
+ padding-top: 8px;
+ }
+
+ .backup-recommendation-group + .backup-recommendation-group {
+ margin-top: 8px;
+ }
+
+ .backup-recommendation-group-title {
+ margin-bottom: 6px;
+ font-size: 13px;
+ }
+
+ .backup-destination-item {
+ padding: 9px 10px;
+ border-radius: 12px;
+ gap: 4px;
+ }
+
+ .backup-destination-meta {
+ font-size: 12px;
+ }
+
+ .backup-name-row,
+ .backup-detail-schedule-grid {
+ gap: 8px;
+ margin-bottom: 8px;
+ }
+
+ .backup-detail-panel .field {
+ margin-bottom: 8px;
+ }
+
+ .backup-detail-panel .field > span {
+ margin: 0 0 4px;
+ font-size: 13px;
+ line-height: 1.2;
+ }
+
+ .backup-detail-panel .input {
+ height: 42px;
+ border-radius: 12px;
+ padding: 8px 11px;
+ font-size: 15px;
+ }
+
+ .backup-detail-panel select.input {
+ padding-right: 30px;
+ background-position:
+ calc(100% - 15px) calc(50% - 3px),
+ calc(100% - 9px) calc(50% - 3px);
+ }
+
+ .backup-schedule-attachments-row {
+ margin-bottom: 8px;
+ }
+
+ .backup-option-label {
+ font-size: 14px;
+ }
+
+ .backup-option-label input[type='checkbox'] {
+ width: 19px;
+ height: 19px;
+ }
+
+ .backup-browser-path,
+ .backup-browser-empty {
+ padding: 9px 10px;
+ border-radius: 12px;
+ }
+
+ .backup-destination-top {
+ align-items: center;
+ flex-direction: row;
}
.backup-add-chooser {