Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide the appearance switcher, but still honor the user’s preferred color scheme #3946

Closed
4 tasks done
mbostock opened this issue Jun 8, 2024 · 2 comments
Closed
4 tasks done
Labels
enhancement New feature or request

Comments

@mbostock
Copy link
Contributor

mbostock commented Jun 8, 2024

Is your feature request related to a problem? Please describe.

I would like to hide the appearance switcher (the dark/light mode toggle); however, I would still like VitePress to respect the user’s preferred color scheme. None of the existing appearance settings appear to allow this: enabling responsive light/mark mode also enables the appearance switcher.

Apple’s human interface guidelines expressly discourage in-app appearance switchers, saying:

Avoid offering an app-specific appearance setting. An app-specific appearance mode option creates more work for people because they have to adjust more than one setting to get the appearance they want. Worse, they may think your app is broken because it doesn’t respond to their systemwide appearance choice.

Describe the solution you'd like

Maybe setting appearance: "auto" (ideally the default) would set the dark/light mode based on the user’s preferred color scheme but without rendering the appearance switcher anywhere.

Describe alternatives you've considered

I can suppress the appearance switcher with custom CSS, but it is brittle (particularly in .VPMenu) and likely to break in future releases of VitePress:

.VPNavBarAppearance,
.VPNavScreenAppearance,
.VPMenu > .group:first-child {
  display: none !important;
}

.VPMenu > .group:nth-child(2) {
  margin-top: -13px;
}

Additional context

No response

Validations

@brc-dd
Copy link
Member

brc-dd commented Jun 8, 2024

a better workaround might be to do something like this

export default definConfig({ 
  appearance: false,
  head: [
    [
      'script',
      {},
      `document.documentElement.classList.toggle('dark', window.matchMedia('(prefers-color-scheme: dark)').matches)`
    ]
  ]
})

But yeah there should be a built-in option to do this. Moreover this workaround doesn't watch for changes and if you watch for changes you'll need to handle disabling transitions yourself:

export default defineConfig({
  appearance: false,
  head: [
    [
      'script',
      { id: 'check-dark-mode' },
      `(()=>{function n(e){const t=document.createElement("style");t.appendChild(document.createTextNode("*,*::before,*::after{transition:none!important}")),document.head.appendChild(t),document.documentElement.classList.toggle("dark",e);const a=getComputedStyle(t).opacity;document.head.removeChild(t)}const o=window.matchMedia("(prefers-color-scheme: dark)");o.addEventListener("change",e=>n(e.matches)),n(o.matches)})();`
    ]
  ]
})

@brc-dd brc-dd added the enhancement New feature or request label Jun 8, 2024
@brc-dd brc-dd closed this as completed in 1e8bb48 Jun 9, 2024
@mbostock
Copy link
Contributor Author

mbostock commented Jun 9, 2024

Thanks much, @brc-dd! I’m impressed by how quickly you implemented this. 👏

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants