diff --git a/app/components/Settings/Toggle.client.vue b/app/components/Settings/Toggle.client.vue
index 29b07f6b62..9a4864b6fb 100644
--- a/app/components/Settings/Toggle.client.vue
+++ b/app/components/Settings/Toggle.client.vue
@@ -54,51 +54,15 @@ const id = useId()
{{ label }}
{{ description }}
-
-
diff --git a/app/plugins/input-switch-polyfill.client.ts b/app/plugins/input-switch-polyfill.client.ts
new file mode 100644
index 0000000000..46dc136dd4
--- /dev/null
+++ b/app/plugins/input-switch-polyfill.client.ts
@@ -0,0 +1,26 @@
+export default defineNuxtPlugin(async () => {
+ if (!('switch' in HTMLInputElement.prototype)) {
+ // @ts-expect-error input-switch-polyfill ships no types; imported for its side effect only
+ await import('input-switch-polyfill')
+
+ // The polyfill reads `accent-color` once at upgrade time and freezes the
+ // resolved color as `--switch-accent` in each element's inline style.
+ // Re-sync whenever the accent or color-mode changes so switches react live.
+ const syncSwitchAccent = () => {
+ const switches = document.querySelectorAll('input.switch')
+ const [first] = switches
+ if (!first) return
+ // All switches share the same cascade; read from the first one.
+ const color = getComputedStyle(first).getPropertyValue('accent-color').trim()
+ if (!color || color === 'auto') return
+ for (const el of switches) {
+ el.style.setProperty('--switch-accent', color)
+ }
+ }
+
+ new MutationObserver(syncSwitchAccent).observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['style', 'class'],
+ })
+ }
+})
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 401dfd006e..ec29109b1a 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -33,7 +33,7 @@ export default defineNuxtConfig({
storageKey: 'npmx-color-mode',
},
- css: ['~/assets/main.css'],
+ css: ['~/assets/main.css', 'input-switch-polyfill/input-switch-polyfill.css'],
runtimeConfig: {
sessionPassword: '',
diff --git a/package.json b/package.json
index a83f9ec1c9..a765e013d2 100644
--- a/package.json
+++ b/package.json
@@ -89,6 +89,7 @@
"focus-trap": "^8.0.0",
"gray-matter": "4.0.3",
"hls.js": "1.6.16",
+ "input-switch-polyfill": "1.12.0",
"ipaddr.js": "2.3.0",
"marked": "18.0.0",
"module-replacements": "3.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4ffe4c756c..6db97f9011 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -186,6 +186,9 @@ importers:
hls.js:
specifier: 1.6.16
version: 1.6.16
+ input-switch-polyfill:
+ specifier: 1.12.0
+ version: 1.12.0
ipaddr.js:
specifier: 2.3.0
version: 2.3.0
@@ -8001,6 +8004,9 @@ packages:
resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ input-switch-polyfill@1.12.0:
+ resolution: {integrity: sha512-4IF+lwC4jjInFPWWjHDcVJWvWiTHm1RnGa+P9uLhOleal69NPbUnrcPHJJhuexyUqOnyA0QenXhtZNuZX4gqWA==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
@@ -19588,6 +19594,8 @@ snapshots:
ini@4.1.1: {}
+ input-switch-polyfill@1.12.0: {}
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0