From 6104452d2ec91fd03ae4ac7e7777b965435eaf9e Mon Sep 17 00:00:00 2001
From: Bryan Van Deusen
Date: Mon, 13 Jul 2026 13:35:01 -0400
Subject: [PATCH] =?UTF-8?q?feat(deps):=20vuetify=203=E2=86=924=20(batch=20?=
=?UTF-8?q?4=20phase=20B,=20#1449)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Vuetify 4 is a Material-Design-3 styling refresh with revert snippets, not a
component-API overhaul. FC's exposure was small:
- Bump vuetify ^4, vite-plugin-vuetify ^2.1.0, vue ^3.5, engines node>=24.
- Restore the dropped global CSS reset (minimal reset from the upgrade guide) in
Vuetify's own low-precedence reset layer, so FC's margin-zeroing assumptions hold.
- v-row prop→utility: 'dense' → density=compact (×3), align=center → class=align-center.
- v-snackbar: multi-line removed → min-height=68.
- v-autocomplete #item slot: item→internalItem (item now aliases raw) in TagPicker
+ GalleryFilterBar (item.raw.* → internalItem.raw.*).
ACCEPTED (cosmetic, operator reviews live per plan #158): MD3 typography
(text-body-2 ×73), non-uppercase buttons (v4 dropped the uppercase default),
MD3 elevation. CI verifies BUILD only — the LOOK is the live-review pass.
Co-Authored-By: Claude Opus 4.8 (1M context)
---
frontend/package.json | 8 ++++----
frontend/src/components/AppSnackbar.vue | 2 +-
frontend/src/components/cleanup/MinDimensionCard.vue | 2 +-
.../src/components/cleanup/SingleColorAuditCard.vue | 2 +-
frontend/src/components/common/TagPicker.vue | 6 +++---
frontend/src/components/gallery/GalleryFilterBar.vue | 10 +++++-----
frontend/src/components/settings/ImportFiltersForm.vue | 2 +-
frontend/src/components/settings/SystemStatsCards.vue | 2 +-
frontend/src/styles/app.css | 10 ++++++++++
9 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/frontend/package.json b/frontend/package.json
index 70cc082..6d9203b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -4,7 +4,7 @@
"private": true,
"type": "module",
"engines": {
- "node": ">=22"
+ "node": ">=24"
},
"scripts": {
"dev": "vite",
@@ -13,16 +13,16 @@
"test:unit": "vitest run"
},
"dependencies": {
- "vue": "^3.4.0",
+ "vue": "^3.5.0",
"vue-router": "^5.0.0",
"pinia": "^3.0.0",
- "vuetify": "^3.5.0",
+ "vuetify": "^4.0.0",
"@mdi/font": "^7.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.0",
"vite": "^8.0.0",
- "vite-plugin-vuetify": "^2.0.0",
+ "vite-plugin-vuetify": "^2.1.0",
"sass": "^1.71.0",
"vitest": "^4.0.0",
"@vue/test-utils": "^2.4.0",
diff --git a/frontend/src/components/AppSnackbar.vue b/frontend/src/components/AppSnackbar.vue
index cf45f16..5b302dd 100644
--- a/frontend/src/components/AppSnackbar.vue
+++ b/frontend/src/components/AppSnackbar.vue
@@ -1,7 +1,7 @@
{{ message }}
diff --git a/frontend/src/components/cleanup/MinDimensionCard.vue b/frontend/src/components/cleanup/MinDimensionCard.vue
index e0aa65d..e4155f1 100644
--- a/frontend/src/components/cleanup/MinDimensionCard.vue
+++ b/frontend/src/components/cleanup/MinDimensionCard.vue
@@ -10,7 +10,7 @@
filter, applied retroactively to the existing library.
-
+
-
+
-
-
+
+
- {{ item.raw.fandom_name ? `character · ${item.raw.fandom_name}` : item.raw.kind }}
+ {{ internalItem.raw.fandom_name ? `character · ${internalItem.raw.fandom_name}` : internalItem.raw.kind }}
diff --git a/frontend/src/components/gallery/GalleryFilterBar.vue b/frontend/src/components/gallery/GalleryFilterBar.vue
index 779a4da..e913a37 100644
--- a/frontend/src/components/gallery/GalleryFilterBar.vue
+++ b/frontend/src/components/gallery/GalleryFilterBar.vue
@@ -13,14 +13,14 @@
@update:search="onSearch"
@update:model-value="onPick"
>
-
-
+
+
- {{ iconFor(item.raw) }}
+ {{ iconFor(internalItem.raw) }}
- {{ item.raw.kind === 'artist' ? 'artist'
- : (item.raw.fandom_name ? `character · ${item.raw.fandom_name}` : item.raw.kind) }}
+ {{ internalItem.raw.kind === 'artist' ? 'artist'
+ : (internalItem.raw.fandom_name ? `character · ${internalItem.raw.fandom_name}` : internalItem.raw.kind) }}
diff --git a/frontend/src/components/settings/ImportFiltersForm.vue b/frontend/src/components/settings/ImportFiltersForm.vue
index 52e3196..0ffb849 100644
--- a/frontend/src/components/settings/ImportFiltersForm.vue
+++ b/frontend/src/components/settings/ImportFiltersForm.vue
@@ -15,7 +15,7 @@
being dropped as duplicates; raise it to collapse more
look-alikes. Applies to new imports.
-
+
-
+
diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css
index 8162633..31712b8 100644
--- a/frontend/src/styles/app.css
+++ b/frontend/src/styles/app.css
@@ -39,3 +39,13 @@
deliberately not used here. `.fc-muted` is a custom class Vuetify never
emits, so no specificity/reorder fight — no !important needed. */
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
+
+/* Vuetify 4 dropped its global CSS reset (normalisation moved into each
+ component). FC's layouts assumed the reset zeroed margins on text elements, so
+ restore just that — the "minimal reset" from the v4 upgrade guide — inside
+ Vuetify's own reset layer, which is low precedence so component + app styles
+ still win over it. Batch-4 Vuetify 3→4 (#1449). */
+@layer vuetify-core.reset {
+ ul, ol, figure, details, summary { padding: 0; margin: 0; }
+ h1, h2, h3, h4, h5, h6, p { margin: 0; }
+}