Skip to content

Commit 987a555

Browse files
committed
feat: Toggle favicon by prefer-color-scheme
1 parent eb34043 commit 987a555

File tree

5 files changed

+78
-6
lines changed

5 files changed

+78
-6
lines changed

docs/.vuepress/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = {
55
serviceWorker: true,
66
head: [
77
['meta', { name: 'theme-color', content: '#fff' }],
8+
['link', { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }]
89
],
910
themeConfig: {
1011
home: false,
@@ -41,6 +42,7 @@ module.exports = {
4142
'/guide/modes.md',
4243
'/guide/events.md',
4344
'/guide/storage.md',
45+
'/guide/favicon.md',
4446
'/guide/meta-theme-color.md',
4547
'/guide/accessibility.md',
4648
'/guide/examples.md'
Lines changed: 1 addition & 0 deletions
Loading

docs/.vuepress/public/favicon.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/guide/favicon.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,52 @@
11
# Favicon
22

3-
Coming soon
3+
| prop | Type | default
4+
| ----------- | --------- | ----------
5+
| `favicon` | Boolean | `true`
6+
7+
You can switch the favicon according to the `prefers-color-scheme`.
8+
9+
## Naming favicons
10+
11+
Favicons should be named as follows:
12+
13+
- For `light` the default favicon will be used, for example: `https://example.com/favicon.svg` or `/favicon.svg`
14+
- For `dark` will be used, for example: `https://example.com/favicon-dark.svg` or `/favicon-dark.svg`
15+
16+
::: tip
17+
For `@vue-a11y/dark-mode`:
18+
- You can use absolute URL (`https://example.com/favicon.svg`) or relative (`/favicon.svg`);
19+
- You can use any extension for the favicon. `svg` is currently the most recommended and supported in modern browsers. See more about [svg favicons](https://css-tricks.com/svg-favicons-and-all-the-fun-things-we-can-do-with-them/#why-svg);
20+
:::
21+
22+
Insert default favicon into your `index.html`
23+
24+
e.g.
25+
26+
```html
27+
<!DOCTYPE html>
28+
<html lang="en">
29+
<head>
30+
<!-- omitted -->
31+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
32+
```
33+
34+
If the user has defined in his `dark` operating system as color mode preference for applications. `@vue-a11y/dark-mode` will identify and make the change to your favicon.
35+
36+
e.g.
37+
38+
```html
39+
<!DOCTYPE html>
40+
<html lang="en">
41+
<head>
42+
<!-- omitted -->
43+
<link rel="icon" type="image/svg+xml" href="/favicon-dark.svg">
44+
```
45+
46+
---
47+
48+
::: tip
49+
You can see this working, just go to your operating system's color settings and change to `dark`, go back to that documentation and check the favicon has changed.
50+
51+
This is a practice used by several sites, one of which is github.
52+
:::

src/DarkMode.vue

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,19 @@ export default {
4848
ariaLive: {
4949
type: String,
5050
default: '%cm color mode is enabled'
51+
},
52+
favicon: {
53+
type: Boolean,
54+
default: true
5155
}
5256
},
5357
5458
data () {
5559
return {
56-
elementMetaThemeColor: null,
5760
chosenMode: null,
5861
currentMode: null,
59-
listenerDark: null
62+
listenerDark: null,
63+
metaThemeColorElement: null
6064
}
6165
},
6266
@@ -106,9 +110,10 @@ export default {
106110
},
107111
108112
mounted () {
109-
this.elementMetaThemeColor = document.querySelector('meta[name="theme-color"]')
113+
this.metaThemeColorElement = document.querySelector('meta[name="theme-color"]')
110114
this.listenerDark = this.getMediaQueryList('dark')
111115
this.listenerDark.addListener(this.handlePreferColorScheme)
116+
this.toggleFavicon(this.getPrefersColorScheme)
112117
},
113118
114119
beforeDestroy () {
@@ -131,20 +136,34 @@ export default {
131136
setMetaThemeColor (color) {
132137
if (color) {
133138
this.$nextTick(() => {
134-
if (this.elementMetaThemeColor) this.elementMetaThemeColor.setAttribute('content', color)
139+
if (this.metaThemeColorElement) this.metaThemeColorElement.setAttribute('content', color)
135140
})
136141
}
137142
},
138143
144+
toggleFavicon (mode) {
145+
if (!this.favicon) return
146+
this.$nextTick(() => {
147+
const favicon = document.querySelector('link[rel="icon"]')
148+
if (!favicon) return
149+
const href = favicon.getAttribute('href')
150+
const lastFour = href.substr(-4, 4)
151+
const favDarkStr = `-dark${lastFour}`
152+
favicon.setAttribute('href', mode === 'light' ? href.replace(favDarkStr, lastFour) : href.replace(lastFour, favDarkStr))
153+
})
154+
},
155+
139156
handleColorModeClass (action) {
140157
if (this.$isServer) return
141158
return document.documentElement.classList[action](`${this.className.replace(/%cm/g, this.currentMode)}`)
142159
},
143160
144161
handlePreferColorScheme (e) {
162+
const colorMatch = e.matches ? 'dark' : 'light'
163+
this.toggleFavicon(colorMatch)
145164
if (this.isSystem) {
146165
this.handleColorModeClass('remove')
147-
this.currentMode = e.matches ? 'dark' : 'light'
166+
this.currentMode = colorMatch
148167
this.setMode('system')
149168
}
150169
},

0 commit comments

Comments
 (0)