Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 7 additions & 33 deletions app/components/Settings/Toggle.client.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ const id = useId()
{{ label }}
</span>
<input
role="switch"
switch
type="checkbox"
role="switch"
:id="id"
v-model="checked"
class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg/50 transition-colors duration-200 ease-in-out checked:bg-fg [@media(hover:hover)]:hover:bg-fg/60 [@media(hover:hover)]:checked:hover:(bg-fg/80 after:opacity-50) focus-visible:(outline-2 outline-accent outline-offset-2) before:(content-[''] absolute h-5 w-5 top-px start-px rounded-full bg-bg transition-transform duration-200 ease-in-out) checked:before:translate-x-[20px] rtl:checked:before:-translate-x-[20px] after:(content-[''] absolute h-3.5 w-3.5 top-[4px] start-[4px] i-lucide:check bg-fg opacity-0 transition-all duration-200 ease-in-out) checked:after:opacity-100 checked:after:translate-x-[20px] rtl:checked:after:-translate-x-[20px]"
style="grid-area: toggle; justify-self: end"
class="shrink-0 focus-visible:(outline-2 outline-accent outline-offset-2)"
style="grid-area: toggle; justify-self: end; accent-color: var(--accent)"
/>
</label>
<p v-if="description" class="text-sm text-fg-muted mt-2">
Expand All @@ -68,37 +69,10 @@ const id = useId()
</template>

<style scoped>
/* Support forced colors */
@media (forced-colors: active) {
.toggle {
background: Canvas;
border-color: CanvasText;
}

.toggle:checked {
background: Highlight;
border-color: CanvasText;
}

.toggle::before {
background-color: CanvasText;
}

.toggle:checked::before {
background-color: Canvas;
}

.toggle::after {
background-color: Highlight;
}
}

/* The switch polyfill animates its thumb without honouring reduced motion. */
@media (prefers-reduced-motion: reduce) {
.toggle,
.toggle::before,
.toggle::after {
transition: none !important;
animation: none !important;
input.switch:is(:hover, :active, :focus) {
transition: none;
}
}
</style>
30 changes: 30 additions & 0 deletions app/plugins/input-switch-polyfill.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export default defineNuxtPlugin({
// Don't hold up hydration for a polyfill that only the settings page needs.
parallel: true,
async setup() {
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<HTMLInputElement>('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'],
})
}
},
})
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,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: '',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"forges": "^0.3.2",
"gray-matter": "4.0.3",
"hls.js": "1.7.0",
"input-switch-polyfill": "1.12.0",
"ipaddr.js": "2.5.0",
"marked": "18.0.9",
"module-replacements": "3.3.0",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading