オートダークモード


最近、私は私のWebアプリをテーマに themed-jss と呼ばれる小さなライブラリを構築しました.それは簡単で柔軟なテーマを可能にします、そして、より重要なことは、自動的に適切な暗いモード支持のために必要とされるすべてのCSS規則(そして、JS)の世話をします.
このポストでは、解決しようとしていた問題を説明します.ホープは、それはあなたのWebアプリケーションでも役に立つと思います.


テーマ
テーマは、あなたのWebアプリのスタイルで使用される定期的な値のセットです.たとえば、すべてのボタンはthemed-jssであるかもしれません、すべてのテキストはblueであるかもしれません、そして、アプリの一般的な背景はblackであるかもしれません:
const myTheme = {
  buttons: 'blue',
  text: 'black',
  background: 'white'
}
このすべてを1つの場所に保つのは役に立ちます.場合は、緑色のすべてのボタンの色を変更することを決定する例を想像して緑色の代わりに、中央のテーマがない場合は、すべてのアプリケーションと更新スタイルを通過する必要があります.


暗渠
ダークモードのサポートは、単にあなたのアプリケーションのための追加のテーマを指定する(暗い色モードで変更する方法):
const myTheme = {
  button: 'blue',
  background: 'white',
  color: 'black'
}

const myDarkTheme = {
  ...myTheme,
  background: 'black',
  color: 'white'
}
残念ながら、実際には、あなたのWebアプリケーションにダークモードのサポートを追加するより多くの作業が必要です.始めるには、いくつかのメディアクエリが必要です.
const myStyles = {
  button: {
    background: myTheme.background,
    '@media (prefers-color-scheme)': {
      background: myDarkTheme.background
    }
  }
}

☝️ I typically use JSS for styling my web apps. It provides style isolation, nested styling, etc. out of the box, and I am particularly fond of it alongside JSX (so everything is in JS).



いくつかのオペレーティングシステムがそのような設定を持っていないので、暗いモードのシステム設定に依存できないという事実を考慮すると、事態はより複雑になります.
私がしばしば使用するソリューションは、ユーザーが暗いモード設定をオーバーライドできるようにするボタンを追加することです.デフォルトでは、設定はシステム(メディアクエリ)から読み込まれますが、ユーザーがそれをオーバーライドした場合、その設定はローカルストレージに格納され、CSSクラスとして適用されます.
const myStyles = {
  button: {
    background: myTheme.background,
    '@media (prefers-color-scheme)': {
      background: myDarkTheme.background
    },
    'html.--dark &': {
      background: myDarkTheme.background
    }
  }
}
☝️ このコードは実際には完了していません:暗モードでOSが暗いユーザがライトモードに優先している場合、このスタイリングルールはまだ暗黒モードで表示されます.これを修正するには、OS Darkモードがオーバーライドされているかどうかを示す別のクラスを追加できます.
const myStyles = {
  button: {
    background: myTheme.background,
    '@media (prefers-color-scheme)': {
      'html:not(.--dark-mode-override) &': {
        background: myDarkTheme.background
      }
    },
    'html.--dark &': {
      background: myDarkTheme.background
    }
  }
}

これはシンプルなスタイルのためのボイラープレートの多くです.解決策?よく、私のスタイルが平凡な値の代わりにテーマの機能であるならば、すなわち:
const myStyles = theme => {
  button: {
    background: theme.background
  }
}
それから、私が持っている2つのテーマ(ライトモードとダークモード)のスタイルを実行でき、自動的に異なるプロパティの追加のCSS規則を挿入できます.
const stylesInLight = myStyles(myTheme)
const stylesInDark = myStyles(myDarkTheme)

const D = diff(stylesInLight, stylesInDark)
createAndInjectRules(D)

white私がここで述べたことは、基本的に themed-jss がすることです.これは、テーマの機能の面でスタイルを定義することができますし、それが自動的に暗いモードの追加のスタイルを作成することに基づいて.
以下に例を示します.
// my-btn.style.js

import { style } from 'themed-jss'

export default style(theme => ({
  btn: {
    background: theme.primary,
    color: theme.background,
    border: 'none',
    borderRadius: 3
  }
})
// my-btn.jsx

import React from 'react'
import { useThemedStyle } from 'themed-jss/react'

import styles from './my-btn.style'

export default () => {
  const { btn } = useThemedStyle(styles)

  return (
    <button className={btn}>Click ME!</button>
  )
}
このコンポーネントは次のように使用できます.
// app.jsx

import { theme } from 'themed-jss'
import { Themed } from 'themed-jss/react'

import MyBtn from './my-btn'

const myTheme = theme(
  {
    primary: 'green',
    background: 'white',
    text: 'black'
  },
  // --> dark mode overrides:
  {
    background: 'black',
    text: 'white'
  }
)

export default () => (
  <Themed theme={myTheme}>
    <MyBtn/>
  </Themed> 
)

ダークモードの手動制御については、themed-jssからDarkModeをインポートし、初期化する必要があります.
// app.jsx

import { DarkMode } from 'themed-jss/dark-mode'

DarkMode.initialize()

// ...
そして、私は実際に暗いモードを切り替えるthemed-jss/dark-modeを持つことができます
// my-btn.jsx

import { DarkMode } from 'themed-jss/dark-mode'

// ...

export default () => {
  const { btn } = useThemedStyle(styles)

  return (
    <button
      className={btn}
      onClick={() => DarkMode.toggle()}>
      Click ME!
    </button>
  )
}
👉 Try it out for yourself!


とにかく、私はあなたが同様に役に立つ<MyBtn/>を見つけることを望みます.あなたは完全なドキュメントin the readmeを見つけることができますし、ここでコメント(またはGithubなどの問題を作成する)は、これ以上の質問がある場合.これはかなり若いツールですので、フィードバックは非常に有り難いです!