Git Product home page Git Product logo

gatsby-plugin-dark-mode's Introduction

gatsby-plugin-dark-mode

A Gatsby plugin which handles some of the details of implementing a dark mode theme.

It provides:

  • Browser code for toggling and persisting the theme (from Dan Abramov's overreacted.io implementation)
  • Automatic use of a dark mode theme (via the prefers-color-scheme CSS media query) if you've configured your system to use dark colour themes when available.
  • A React component for implementing theme toggling UI in your site.

Install

npm install gatsby-plugin-dark-mode
// gatsby-config.js

module.exports = {
  plugins: ['gatsby-plugin-dark-mode'],
}

How to use

Implement theme toggling UI

The plugin module exports a ThemeToggler component which takes a children render prop, providing the current theme name and a toggleTheme function to change the theme.

Here's an example of using ThemeToggler with a checkbox to toggle the theme:

import React from 'react'
import { ThemeToggler } from 'gatsby-plugin-dark-mode'

class MyComponent extends React.Component {
  render() {
    return (
      <ThemeToggler>
        {({ theme, toggleTheme }) => {
          // Don't render anything at compile time. Deferring rendering until we
          // know which theme to use on the client avoids incorrect initial
          // state being displayed.
          if (theme == null) {
            return null
          }
          return (
            <label>
              <input
                type="checkbox"
                onChange={(e) =>
                  toggleTheme(e.target.checked ? 'dark' : 'light')
                }
                checked={theme === 'dark'}
              />{' '}
              Dark mode
            </label>
          )
        }}
      </ThemeToggler>
    )
  }
}

The toggled theme will be persisted across visits in localStorage.theme.

Implement theming

The default theme names are 'light' and 'dark' - the plugin adds the current theme name to the <body> element's className, so you can use global styles to implement theming.

A nice option is to use CSS variables like so:

/* global.css */

body {
  --bg: white;
  --textNormal: #222;
  --textTitle: #222;
  --textLink: blue;
  --hr: hsla(0, 0%, 0%, 0.2);

  background-color: var(--bg);
}

body.dark {
  -webkit-font-smoothing: antialiased;

  --bg: darkslategray;
  --textNormal: rgba(255, 255, 255, 0.88);
  --textTitle: white;
  --textLink: yellow;
  --hr: hsla(0, 0%, 100%, 0.2);
}

You can then use these variables in your site's components...

class Layout extends React.Component {
  render() {
    return (
      <div
        style={{
          backgroundColor: 'var(--bg)',
          color: 'var(--textNormal)',
          transition: 'color 0.2s ease-out, background 0.2s ease-out',
        }}
      >
        ...
      </div>
    )
  }
}

...and in your Typography config if you're using gatsby-plugin-typography, which is included in the Gatsby Starter Blog:

// typography.js

import './global.css'

import Typography from 'typography'
import Wordpress2016 from 'typography-theme-wordpress-2016'

Wordpress2016.overrideThemeStyles = () => ({
  a: {
    color: 'var(--textLink)',
  },
  // gatsby-remark-autolink-headers - don't underline when hidden
  'a.anchor': {
    boxShadow: 'none',
  },
  // gatsby-remark-autolink-headers - use theme colours for the link icon
  'a.anchor svg[aria-hidden="true"]': {
    stroke: 'var(--textLink)',
  },
  hr: {
    background: 'var(--hr)',
  },
})

Acknowledgements

The theme detecting/switching/persistence code and the suggested theming implementation are entirely from the implementation of overreacted.io by Dan Abramov - I'm just publishing them as a plugin to make them easier to use in my own blog, and for reuse by others.

MIT Licensed

gatsby-plugin-dark-mode's People

Contributors

insin avatar robbinjanssen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

gatsby-plugin-dark-mode's Issues

Hooks support

Would it be okay to open a PR to implement a useThemeToggler React hook so it can be some variables on the side rather than a render prop? I think having both forms would be a good state to have so you can choose a render prop or a react hook depending on your use case

Support for Blockquotes

The Dark mode doesn't support any color change in the Blockquote Section of a Post/Markdown File

Cannot read property '__reactstandin__key' of undefined

Hi! I've seen this plugin and it does exactly what I wanted to do, so I'm giving it a try. However, I'm facing this issue. This is the strack trace I get on runtime.

react-hot-loader.development.js:1229 Uncaught TypeError: Cannot read property '__reactstandin__key' of undefined
    at isProxyType (react-hot-loader.development.js:1229)
    at resolveProxy (react-hot-loader.development.js:1770)
    at resolveSimpleType (react-hot-loader.development.js:1786)
    at React$$1.createElement (react-hot-loader.development.js:2820)
    at jsx (core.browser.esm.js:102)
    at MyThemeToggler (my-theme-toggler.js:1)
    at renderWithHooks (react-dom.development.js:15105)
    at updateFunctionComponent (react-dom.development.js:16922)
    at beginWork$1 (react-dom.development.js:18495)
    at HTMLUnknownElement.callCallback (react-dom.development.js:348)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:398)
    at invokeGuardedCallback (react-dom.development.js:455)
    at beginWork$$1 (react-dom.development.js:23214)
    at performUnitOfWork (react-dom.development.js:22205)
    at workLoopSync (react-dom.development.js:22182)
    at renderRoot (react-dom.development.js:21875)
    at runRootCallback (react-dom.development.js:21551)
    at react-dom.development.js:11354
    at unstable_runWithPriority (scheduler.development.js:643)
    at runWithPriority$2 (react-dom.development.js:11306)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11350)
    at flushSyncCallbackQueue (react-dom.development.js:11339)
    at scheduleUpdateOnFiber (react-dom.development.js:21428)
    at Object.enqueueForceUpdate (react-dom.development.js:13146)
    at ExportedComponent../node_modules/react/cjs/react.development.js.Component.forceUpdate (react.development.js:343)
    at react-hot-loader.development.js:2973
    at Array.forEach (<anonymous>)
    at react-hot-loader.development.js:2972

My dependencies are these:

    "@emotion/core": "10.0.16",
    "@emotion/styled": "10.0.15",
    "gatsby": "^2.13.65",
    "gatsby-image": "^2.2.8",
    "gatsby-plugin-dark-mode": "1.1.0",
    "gatsby-plugin-emotion": "4.1.2",
    "gatsby-plugin-feed": "^2.3.6",
    "gatsby-plugin-google-analytics": "^2.1.7",
    "gatsby-plugin-i18n": "1.0.1",
    "gatsby-plugin-manifest": "^2.2.5",
    "gatsby-plugin-offline": "^2.2.6",
    "gatsby-plugin-react-helmet": "^3.1.3",
    "gatsby-plugin-sharp": "^2.2.11",
    "gatsby-plugin-typography": "^2.3.2",
    "gatsby-remark-copy-linked-files": "^2.1.6",
    "gatsby-remark-images": "^3.1.12",
    "gatsby-remark-prismjs": "^3.3.5",
    "gatsby-remark-responsive-iframe": "^2.2.4",
    "gatsby-remark-smartypants": "^2.1.2",
    "gatsby-source-filesystem": "^2.1.9",
    "gatsby-transformer-remark": "^2.6.14",
    "gatsby-transformer-sharp": "^2.2.6",
    "intl": "1.2.5",
    "intl-pluralrules": "1.0.3",
    "prismjs": "^1.17.1",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-helmet": "^5.2.1",
    "react-intl": "3.1.9",
    "react-typography": "^0.16.19",
    "typeface-merriweather": "0.0.72",
    "typeface-montserrat": "0.0.75",
    "typography": "^0.16.19",
    "typography-theme-wordpress-2016": "^0.16.19"

I'm going to dive into the code to look for the issue.

Make light mode default (avoid preferes-color-scheme)

"Automatic use of a dark mode theme (via the prefers-color-scheme CSS media query) if you've configured your system to use dark colour themes when available."

Is there anyway to avoid this in order to make the light theme always default?

Thanks!

A forked version

Hi, I created a forked version with some improvements

  • Rewrites with typescript so that the code part has typing
  • Removes peer dependency version restrictions
  • exports a hook instead of class component
  • adds rootElement option to specify the DOM node to interact
  • adds script option in case of some custom implementations

the package is published as @skagami/gatsby-plugin-dark-mode: https://www.npmjs.com/package/@skagami/gatsby-plugin-dark-mode

please feel free leave some comments or pick the changes

Double rendering on Gatsby Cloud

Hi. My website, which is not yet ready to the end, runs on Gatsby Cloud. I had the same problem as many - I had to click on toggler several times to change the color theme immediately after loading the site. I added the code from this commit and the problem disappeared, but another problem appeared - now my site is rendered twice after loading. You can see it here. Is there any way to solve this problem?

Errors in the console are shown in the picture below. The error description is as follows:

Hydration failed because the initial UI does not match what was rendered on the server.
&
There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

image

React hook for useTheme?

it would be really nice to have a react hook letting us use the theme instead of using

<ThemeToggler>

...
</ThemeToggler>

Push new release with the deferred rendering tip in README

I came across the same issue mentioned in #10 and #13, and it took me a while to find the solution hidden in 83409b5. Since it is not part of the current release, the plugin's pages in npm and Gatsby docs do not have the "deferred rendering tip".

Even though it's quite minor, I feel like the updated README would be very helpful for anyone integrating this into their project.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.