From 53d0384a8359b15c0327e77064fa47ed6da0db21 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Sat, 8 Aug 2026 20:10:46 +0200 Subject: [PATCH 1/2] build(frontend): replace WindiCSS with Tailwind CSS v4 WindiCSS has been unmaintained since 2023, and its Vite plugin is the only thing still holding the dashboard on it. Tailwind v4 covers the same ground through @tailwindcss/vite and is a maintained dependency again. The move is deliberately mechanical, so the diff reads as a toolchain change and nothing else. src/style.css carries the theme that used to live in windi.config.js, and a compatibility block below it reproduces what Windi emitted. That block is scaffolding for the UI work that follows and is marked for deletion. Six things needed handling rather than translation: - Component style blocks sit outside every cascade layer, which ranked .container above the px-15 utilities several views write beside it. The global rules moved out of App.vue into the layer each one needs. - Tailwind accepts spacing only in multiples of 0.25, so nine classes such as pt-0.4 stopped resolving. They are explicit rem values now. - Windi shipped an `indent` utility of its own, which silently added a text-indent to the token routes, whose component class has the same name. - The dark variant uses :is and not :where, because :where adds no specificity and the indicator vue3-tabs styles then wins. - @tailwindcss/forms styles an input written without a type, which Windi's older port did not. Thirteen inputs were laid out against the untouched browser box. - `dark: bg-gray-900` in the settings styles was a typo that Windi swallowed and Tailwind rejects. Verified by running both versions side by side and comparing every view in both themes at two widths: the desktop views outside the dashboard come out pixel identical. One difference is kept on purpose, a select now inherits the interface font instead of falling back to Arial. Signed-off-by: TheMeinerLP --- reposilite-frontend/.vscode/settings.json | 3 +- reposilite-frontend/build.gradle.kts | 4 +- reposilite-frontend/package-lock.json | 596 ++++++++++-------- reposilite-frontend/package.json | 5 +- reposilite-frontend/src/App.vue | 37 +- .../browser/BreadcrumbNavigation.vue | 2 +- .../components/browser/DetailedListEntry.vue | 17 +- .../components/browser/FileBrowserView.vue | 12 +- .../src/components/browser/FileList.vue | 1 + .../src/components/browser/FileUpload.vue | 13 +- .../src/components/card/CardMenu.vue | 12 +- .../src/components/card/SnippetsCard.vue | 5 +- .../src/components/console/ConsoleView.vue | 4 +- .../src/components/dashboard/DashboardBox.vue | 2 +- .../components/dashboard/DashboardView.vue | 2 +- .../dashboard/InstanceStatusCharts.vue | 2 +- .../src/components/header/DefaultHeader.vue | 6 +- .../src/components/header/HeaderHero.vue | 10 +- .../src/components/header/LoginModal.vue | 3 +- .../src/components/header/MenuButton.vue | 2 +- .../src/components/header/MenuPanel.vue | 10 +- .../components/renderers/OneOfRenderer.vue | 3 +- .../components/settings/FactoryResetModal.vue | 1 + .../src/components/settings/SettingsView.vue | 12 +- .../src/components/tokens/TokensView.vue | 14 +- reposilite-frontend/src/main.js | 2 +- reposilite-frontend/src/pages/IndexPage.vue | 8 +- reposilite-frontend/src/style.css | 242 +++++++ reposilite-frontend/vite.config.js | 4 +- reposilite-frontend/windi.config.js | 55 -- 30 files changed, 685 insertions(+), 404 deletions(-) create mode 100644 reposilite-frontend/src/style.css delete mode 100644 reposilite-frontend/windi.config.js diff --git a/reposilite-frontend/.vscode/settings.json b/reposilite-frontend/.vscode/settings.json index 953fe9739..b3aafd3a9 100644 --- a/reposilite-frontend/.vscode/settings.json +++ b/reposilite-frontend/.vscode/settings.json @@ -14,8 +14,7 @@ "signout", "toastify", "vueform", - "vueuse", - "windicss" + "vueuse" ], "vetur.validation.script": false // https://github.com/vuejs/vetur/issues/2296 } diff --git a/reposilite-frontend/build.gradle.kts b/reposilite-frontend/build.gradle.kts index c259e7f1d..35e2e2297 100644 --- a/reposilite-frontend/build.gradle.kts +++ b/reposilite-frontend/build.gradle.kts @@ -32,7 +32,7 @@ node { // dependsOn(tasks.npmInstall) // inputs.dir("src") // inputs.dir("node_modules") -// inputs.files("vite.config.js", "windi.config.js", "index.html", "eslint.config.js") +// inputs.files("vite.config.js", "index.html", "eslint.config.js") // outputs.upToDateWhen { true } //} @@ -44,7 +44,7 @@ val buildTask = tasks.register("buildFrontend") { dependsOn(tasks.npmInstall) inputs.dir(project.fileTree("src")) inputs.dir("node_modules") - inputs.files("vite.config.js", "windi.config.js", "index.html") + inputs.files("vite.config.js", "index.html") outputs.dir("${project.layout.buildDirectory.get()}/frontend") } diff --git a/reposilite-frontend/package-lock.json b/reposilite-frontend/package-lock.json index 9902ead6f..0b976ea19 100644 --- a/reposilite-frontend/package-lock.json +++ b/reposilite-frontend/package-lock.json @@ -32,6 +32,8 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/vite": "^4.3.3", "@vitejs/plugin-vue": "^6.0.7", "@vitejs/plugin-vue-jsx": "^5.1.5", "@vue/compiler-sfc": "^3.5.35", @@ -47,9 +49,8 @@ "license-checker-rseidelsohn": "^5.0.1", "nodemon": "^3.1.14", "rollup-plugin-visualizer": "^7.0.1", + "tailwindcss": "^4.3.3", "vite": "^8.0.16", - "vite-plugin-windicss": "^1.9.4", - "windicss": "^3.5.6", "ws": "^8.21.0" }, "engines": { @@ -57,16 +58,6 @@ "npm": ">=10.0.0" } }, - "node_modules/@antfu/utils": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", - "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -829,44 +820,6 @@ "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@npmcli/agent": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", @@ -1644,6 +1597,303 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.11.tgz", + "integrity": "sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, "node_modules/@tufjs/canonical-json": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", @@ -2252,40 +2502,6 @@ "vue": "^3.5.0" } }, - "node_modules/@windicss/config": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@windicss/config/-/config-1.9.4.tgz", - "integrity": "sha512-vKXJlEC01/LFuYLF6XZsrCv13QKsxByWFqzDRctTva+O4yqr5j0e5VWB4Dr2tgzVbZuYG5ewg7qywAI/9JD0Cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.7", - "jiti": "^1.21.6", - "windicss": "^3.5.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@windicss/plugin-utils": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-1.9.4.tgz", - "integrity": "sha512-GUAX0z+wnq6Rn3+YGJli/keGja73+a6I/PtTpH8EMlNNHrHBbqsbyY5+25QagV39rHwTe/IbkiSdD3csP8L6MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@antfu/utils": "^0.7.10", - "@windicss/config": "1.9.4", - "debug": "^4.3.7", - "fast-glob": "^3.3.2", - "magic-string": "^0.30.14", - "micromatch": "^4.0.8", - "windicss": "^3.5.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/abbrev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", @@ -3482,6 +3698,20 @@ "node": ">= 0.8" } }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", @@ -3999,36 +4229,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4059,16 +4259,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -4789,13 +4979,13 @@ "license": "ISC" }, "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", "devOptional": true, "license": "MIT", "bin": { - "jiti": "bin/jiti.js" + "jiti": "lib/jiti-cli.mjs" } }, "node_modules/jju": { @@ -5317,13 +5507,6 @@ "graceful-fs": "^4.1.9" } }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true, - "license": "MIT" - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5884,16 +6067,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/method-override": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", @@ -5937,20 +6110,6 @@ "node": ">= 0.6" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -5989,6 +6148,16 @@ "url": "https://opencollective.com/express" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", @@ -7169,27 +7338,6 @@ ], "license": "MIT" }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7268,17 +7416,6 @@ "lodash": "^4.17.21" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, "node_modules/rolldown": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", @@ -7533,30 +7670,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -8111,6 +8224,27 @@ "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/tar": { "version": "7.5.22", "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", @@ -8620,25 +8754,6 @@ } } }, - "node_modules/vite-plugin-windicss": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-1.9.4.tgz", - "integrity": "sha512-3t1AUVrs2XBXGc2BefRPRvy1CLy8qA/5A1J1Z73Ej1DIx+puXn39MQSWluxZ2FHEz8z9OEIvsoIIPc/s/P3OmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@windicss/plugin-utils": "1.9.4", - "debug": "^4.3.7", - "kolorist": "^1.8.0", - "windicss": "^3.5.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "*" - } - }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -9029,19 +9144,6 @@ "node": ">= 8" } }, - "node_modules/windicss": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/windicss/-/windicss-3.5.6.tgz", - "integrity": "sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==", - "dev": true, - "license": "MIT", - "bin": { - "windicss": "cli/index.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/reposilite-frontend/package.json b/reposilite-frontend/package.json index 60aa38d40..198c7a083 100644 --- a/reposilite-frontend/package.json +++ b/reposilite-frontend/package.json @@ -41,6 +41,8 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/vite": "^4.3.3", "@vitejs/plugin-vue": "^6.0.7", "@vitejs/plugin-vue-jsx": "^5.1.5", "@vue/compiler-sfc": "^3.5.35", @@ -56,9 +58,8 @@ "license-checker-rseidelsohn": "^5.0.1", "nodemon": "^3.1.14", "rollup-plugin-visualizer": "^7.0.1", + "tailwindcss": "^4.3.3", "vite": "^8.0.16", - "vite-plugin-windicss": "^1.9.4", - "windicss": "^3.5.6", "ws": "^8.21.0" } } diff --git a/reposilite-frontend/src/App.vue b/reposilite-frontend/src/App.vue index 2ad3b7ccd..d4d818706 100644 --- a/reposilite-frontend/src/App.vue +++ b/reposilite-frontend/src/App.vue @@ -50,36 +50,9 @@ initializeSession().catch(() => {}) - diff --git a/reposilite-frontend/src/components/browser/BreadcrumbNavigation.vue b/reposilite-frontend/src/components/browser/BreadcrumbNavigation.vue index a77826823..c69dc8d13 100644 --- a/reposilite-frontend/src/components/browser/BreadcrumbNavigation.vue +++ b/reposilite-frontend/src/components/browser/BreadcrumbNavigation.vue @@ -43,7 +43,7 @@ const breadcrumbs = computed(() => { - {{ crumb.name }} + {{ crumb.name }} diff --git a/reposilite-frontend/src/components/browser/DetailedListEntry.vue b/reposilite-frontend/src/components/browser/DetailedListEntry.vue index 71892fd99..c44b14761 100644 --- a/reposilite-frontend/src/components/browser/DetailedListEntry.vue +++ b/reposilite-frontend/src/components/browser/DetailedListEntry.vue @@ -70,7 +70,7 @@ const defaultMode = computed(() => !props.compactMode) v-if="file.hasOwnProperty('contentLength') && isHumanReadable" :title="`Click to view ${file.name} file content in a new tab`" id="view-button" - class="px-1 mr-6 pt-0.4 rounded-full text-purple-300 hover:(transition-colors duration-200 bg-gray-100 dark:bg-gray-900)" + class="px-1 mr-6 pt-[0.1rem] rounded-full text-purple-300 hover:transition-colors hover:duration-200 hover:bg-gray-100 dark:hover:bg-gray-900" @click.left.prevent="openUrl(url)" v-on:click.stop /> @@ -78,14 +78,14 @@ const defaultMode = computed(() => !props.compactMode) v-if="isJavaDocsAvailable()" :title="`Click to view ${file.name} javadocs in a new tab`" id="javadoc-button" - class="px-1 mr-6 pt-0.4 rounded-full text-purple-300 hover:(transition-colors duration-200 bg-gray-100 dark:bg-gray-900)" + class="px-1 mr-6 pt-[0.1rem] rounded-full text-purple-300 hover:transition-colors hover:duration-200 hover:bg-gray-100 dark:hover:bg-gray-900" @click.left.prevent="openUrl(getJavaDocsUrl())" v-on:click.stop /> @@ -98,24 +98,25 @@ const defaultMode = computed(() => !props.compactMode) diff --git a/reposilite-frontend/src/components/settings/FactoryResetModal.vue b/reposilite-frontend/src/components/settings/FactoryResetModal.vue index 3b8ce795f..9019eae96 100644 --- a/reposilite-frontend/src/components/settings/FactoryResetModal.vue +++ b/reposilite-frontend/src/components/settings/FactoryResetModal.vue @@ -50,6 +50,7 @@ export default { diff --git a/reposilite-frontend/src/store/palette.js b/reposilite-frontend/src/store/palette.js new file mode 100644 index 000000000..1e9ab42fd --- /dev/null +++ b/reposilite-frontend/src/store/palette.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2026 OneLiteFeather + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Colours for everything the dashboard plots. + * + * The two categorical ramps are not a light set and a free-hand dark set: they are the + * same eight hues, each stepped for the surface it is drawn on. Both were checked against + * the surfaces the charts actually use (white cards on #f5f5f5, gray-900 cards on black) + * for the lightness band, a chroma floor, colour-vision separation between neighbouring + * slots, and contrast. Reordering the slots or dropping one in changes those results, so + * treat the order as part of the data and re-validate before touching it. + * + * In light mode aqua, yellow and magenta sit below 3:1 against a white card. That is + * allowed only while every series carries a visible label, which is why the multi-series + * chart always draws its legend. + */ +const CATEGORICAL_LIGHT = [ + '#2a78d6', // blue + '#eb6834', // orange + '#1baf7a', // aqua + '#eda100', // yellow + '#e87ba4', // magenta + '#008300', // green + '#4a3aa7', // violet + '#e34948' // red +] + +const CATEGORICAL_DARK = [ + '#3987e5', + '#d95926', + '#199e70', + '#c98500', + '#d55181', + '#008300', + '#9085e9', + '#e66767' +] + +/** + * Reserved for state, never for a series. Each one is paired with a word in the interface + * so the colour is never the only thing carrying the meaning. + */ +export const STATUS = { + good: '#0ca30c', + warning: '#fab219', + serious: '#ec835a', + critical: '#d03b3b' +} + +/** Axis, grid and label colours. Deliberately recessive: the data is the ink. */ +const CHROME_LIGHT = { + axis: '#898781', + grid: '#e1e0d9', + baseline: '#c3c2b7', + text: '#52514e' +} + +const CHROME_DARK = { + axis: '#898781', + grid: '#2c2c2a', + baseline: '#383835', + text: '#c3c2b7' +} + +export const categorical = (isDark) => (isDark ? CATEGORICAL_DARK : CATEGORICAL_LIGHT) + +export const chrome = (isDark) => (isDark ? CHROME_DARK : CHROME_LIGHT)