Mode Sombre
Vue d'ensemble
Mettre à jour automatiquement les interfaces natives
Les "interfaces natives" incluent le sélecteur de fichiers, la bordure de fenêtre, les dialogues, les menus contextuels et plus encore - tous les éléments de l'interface utilisateur qui provient de votre système d'exploitation et pas de votre application. Le comportement par défaut est d'opter pour le thème automatique de l'OS.
Mettre à jour automatiquement vos propres interfaces
Si votre application dispose de son propre mode sombre, vous devrez l’activer et le désactiver en synchronisation avec le paramètre de mode sombre du système. Vous pouvez le faire en utilisant la media query CSS prefers-color-scheme.
Mettre à jour manuellement vos propres interfaces
Si vous souhaitez basculer manuellement entre les modes clair/sombre, vous pouvez le faire en indiquant le mode souhaité au niveau de la propriété themeSource du module nativeTheme
. La valeur de cette propriété sera propagée à votre processus de rendu. Toutes les règles CSS relatives à prefers-color-scheme
seront mises à jour en conséquence.
paramètres macOS
Dans macOS 10.14 Mojave, Apple a introduit un nouveau mode sombre à l'échelle du système pour tous les ordinateurs macOS. Si votre application Electron a un mode sombre, vous pouvez le faire suivre le réglage du mode sombre à l'échelle du système en utilisant l'API nativeTheme
.
Dans macOS 10.15 Catalina, Apple a introduit une nouvelle option de mode sombre « automatique » pour tous les ordinateurs macOS. Afin que les API nativeTheme.shouldUseDarkColors
et Tray
fonctionnent correctement dans ce mode sur Catalina, vous devez utiliser une version d'Electron >=7.0.0
, ou mettre NSRequiresAquaSystemAppearance
à false
dans votre fichier Info.plist
pour les anciennes versions. Both Electron Packager and Electron Forge have a darwinDarkModeSupport
option to automate the Info.plist
changes during app build time.
Si vous ne souhaitez pas choisir cette option tout en utilisant une version d'’Electron > 8.0.0, vous devez définir la clé NSRequiresAquaSystemAppearance
à true
dans le fichier Info.plist
. . Veuillez noter qu’Electron 8.0.0 et versions ultérieures ne vous permettront pas de vous désinscrire de ce thème, en raison de l’utilisation du SDK macOS 10.14.
Exemple
Cet exemple illustre une application Electron qui tire ses couleurs de thème du nativeTheme
. De plus, il fournit des contrôles de basculement de thème et des contrôles de réinitialisation en utilisant les canaux IPC.
- main.js
- preload.js
- index.html
- renderer.js
- styles.css
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron/main')
const path = require('node:path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSource = 'system'
})
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('darkMode', {
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
system: () => ipcRenderer.invoke('dark-mode:system')
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</html>
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await window.darkMode.toggle()
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await window.darkMode.system()
document.getElementById('theme-source').innerHTML = 'System'
})
:root {
color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
Comment cela fonctionne ?
Commençons avec le fichier index.html
:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</html>
Et le fichier styles.css
:
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
L'exemple produit une page HTML avec quelques éléments. L'élément <strong id="theme-source">
indique quel thème est actuellement sélectionné, et les deux éléments <button>
sont les contrôles. Le fichier CSS utilise la media query prefers-color-scheme
afin de définir les couleurs d'arrière-plan de l'élément <body>
et les couleurs du texte.
Le script preload.js
ajoute une nouvelle API à l'objet window
appelé darkMode
. Cette API expose deux canaux IPC au processus de rendu, 'dark-mode:toggle'
et 'dark-mode:system'
. Il assigne également deux méthodes, toggle
et system
, qui passent des messages du moteur de rendu au processus principal.
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('darkMode', {
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
system: () => ipcRenderer.invoke('dark-mode:system')
})
Maintenant, le processus de rendu peut communiquer avec le processus principal de manière sécurisée et effectuer les mutations nécessaires à l'objet nativeTheme
.
Le fichier renderer.js
est responsable du contrôle de la fonctionnalité <button>
.
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await window.darkMode.toggle()
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await window.darkMode.system()
document.getElementById('theme-source').innerHTML = 'System'
})
En utilisant addEventListener
, le fichier renderer.js
ajoute un event listeners sur 'click'
à chaque élément bouton. Chaque gestionnaire d'écouteur d'événements effectue des appels vers les méthodes API window.darkMode
respectives.
Enfin, le fichier main.js
représente le processus principal et contient l'API nativeTheme
.
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
const path = require('node:path')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSource = 'system'
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
Les méthodes ipcMain.handle
sont la façon dont le processus principal répond aux événements de click des boutons de la page HTML.
La méthode gestionnaire de canaux IPC 'dark-mode:toggle'
vérifie la propriété booléenne shouldUseDarkColors
, définit la themeSource
correspondante , puis renvoie la propriété shouldUseDarkColors
actuelle. En revenant un peu sur l’écouteur d’événements du processus de rendu pour ce canal IPC, la valeur de retour de ce gestionnaire est utilisée pour affecter le texte adequate à l’élément <strong id='theme-source'>
.
La méthode gestionnaire de canaux IPC 'dark-mode:system'
affecte la chaîne 'system'
à la themeSource
et ne renvoie rien. Cela correspond également à l’écouteur d’événement correspondant du processus de rendu, puisque on attend la méthode sans aucune valeur de retour.
Exécutez l’exemple à l’aide d’Electron Fiddle, puis cliquez sur le bouton « Basculer le mode sombre »; l’application devrait commencer à alterner entre un fond clair et un fond sombre.