mirror of
https://github.com/jakejarvis/dark-mode.git
synced 2025-04-29 12:40:28 -04:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
0328cdb280 | |||
57989cf25f | |||
c62cde5e91 | |||
ce472773c9 | |||
07ce4cab10 | |||
9c9351398d | |||
1c1ff4e186 | |||
45d856cab3 | |||
fba5494cfe | |||
8670de8a30 | |||
e5a76a03b3 | |||
02f772dd46 | |||
![]() |
5fc1bd80b3 | ||
![]() |
ba8cd84d66 | ||
9d599b4675 | |||
8f96d0bb83 | |||
2fcad1a9e7 |
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
|
||||||
|
# this file is the top-most editorconfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# all files
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
# site content
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
@ -1,18 +1,16 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"@jakejarvis/eslint-config",
|
||||||
"plugin:compat/recommended"
|
"plugin:@typescript-eslint/recommended"
|
||||||
],
|
],
|
||||||
|
"plugins": [
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true
|
||||||
"node": true
|
|
||||||
},
|
},
|
||||||
"parserOptions": {
|
"ignorePatterns": [
|
||||||
"ecmaVersion": 2015,
|
"dist/**"
|
||||||
"sourceType": "module"
|
]
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"quotes": ["error", "double"],
|
|
||||||
"semi": ["error", "always"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
* text=auto eol=lf
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: 16.x
|
||||||
- run: yarn install --frozen-lockfile
|
- run: yarn install --frozen-lockfile
|
||||||
- run: yarn lint
|
- run: yarn lint
|
||||||
- run: yarn build
|
- run: yarn build
|
||||||
|
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@ -3,36 +3,18 @@ name: Release
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- 'v*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
npm:
|
npm:
|
||||||
name: Publish to NPM
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 16.x
|
||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- env:
|
- run: yarn install --frozen-lockfile
|
||||||
|
- run: yarn publish
|
||||||
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
run: |
|
|
||||||
yarn install --frozen-lockfile
|
|
||||||
yarn publish
|
|
||||||
|
|
||||||
gpr:
|
|
||||||
name: Publish to GitHub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 14
|
|
||||||
registry-url: https://npm.pkg.github.com/
|
|
||||||
scope: '@jakejarvis'
|
|
||||||
- env:
|
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
yarn install --frozen-lockfile
|
|
||||||
yarn publish
|
|
||||||
|
18
README.md
18
README.md
@ -1,10 +1,9 @@
|
|||||||
# 🌓 Dark Mode Switcheroo™
|
# 🌓 Dark Mode Switcheroo™
|
||||||
|
|
||||||
[](https://github.com/jakejarvis/dark-mode.js/actions/workflows/ci.yml)
|
[](https://github.com/jakejarvis/dark-mode/actions/workflows/ci.yml)
|
||||||
[](https://www.npmjs.com/package/@jakejarvis/dark-mode)
|
[](https://www.npmjs.com/package/dark-mode-switcheroo)
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
Very simple CSS dark/light mode toggler with saved preference via local storage & dynamic OS setting detection. Zero dependencies and [only ~500 bytes gzipped!](https://bundlephobia.com/package/@jakejarvis/dark-mode)
|
Very simple CSS dark/light mode toggler with saved preference via local storage & dynamic OS setting detection. Zero dependencies and [only ~500 bytes gzipped!](https://bundlephobia.com/package/dark-mode-switcheroo)
|
||||||
|
|
||||||
- [View the example.](https://jakejarvis.github.io/dark-mode/)
|
- [View the example.](https://jakejarvis.github.io/dark-mode/)
|
||||||
- [Read the blog post.](https://jarv.is/notes/dark-mode/)
|
- [Read the blog post.](https://jarv.is/notes/dark-mode/)
|
||||||
@ -21,6 +20,7 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
|
|||||||
- **`default`**: The initial `<body>` class hard-coded into the HTML template. (optional, default: `"light"`)
|
- **`default`**: The initial `<body>` class hard-coded into the HTML template. (optional, default: `"light"`)
|
||||||
- **`storageKey`**: Name of the `localStorage` key holding the user's preference. (optional, default: `"dark_mode_pref"`)
|
- **`storageKey`**: Name of the `localStorage` key holding the user's preference. (optional, default: `"dark_mode_pref"`)
|
||||||
- **`onInit([toggle])`**: Callback function executed at the end of initialization. The toggle above is passed in if set. (optional, default: `null`)
|
- **`onInit([toggle])`**: Callback function executed at the end of initialization. The toggle above is passed in if set. (optional, default: `null`)
|
||||||
|
- **`onUserToggle([toggle])`**: Callback function executed when a user manually interacts with the toggle button. The toggle above (if set) is passed in. (optional, default: `null`)
|
||||||
- **`onChange([theme, toggle])`**: Callback function executed when theme is switched. The new theme and the toggle above (if set) are passed in. (optional, default: `null`)
|
- **`onChange([theme, toggle])`**: Callback function executed when theme is switched. The new theme and the toggle above (if set) are passed in. (optional, default: `null`)
|
||||||
|
|
||||||
### Browser
|
### Browser
|
||||||
@ -28,7 +28,7 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
|
|||||||
```html
|
```html
|
||||||
<button class="dark-mode-toggle" style="visibility: hidden;">💡 Click to see the light... or not.</button>
|
<button class="dark-mode-toggle" style="visibility: hidden;">💡 Click to see the light... or not.</button>
|
||||||
|
|
||||||
<script src="https://unpkg.com/@jakejarvis/dark-mode/dist/dark-mode.min.js"></script>
|
<script src="https://unpkg.com/dark-mode-switcheroo/dist/dark-mode.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.darkMode.init({
|
window.darkMode.init({
|
||||||
toggle: document.querySelector(".dark-mode-toggle"),
|
toggle: document.querySelector(".dark-mode-toggle"),
|
||||||
@ -51,15 +51,15 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
|
|||||||
### Node
|
### Node
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @jakejarvis/dark-mode
|
npm install dark-mode-switcheroo
|
||||||
# or...
|
# or...
|
||||||
yarn add @jakejarvis/dark-mode
|
yarn add dark-mode-switcheroo
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Module via `import`
|
#### Module via `import`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init } from "@jakejarvis/dark-mode";
|
import { init } from "dark-mode-switcheroo";
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// ...same as browser.
|
// ...same as browser.
|
||||||
@ -69,7 +69,7 @@ init({
|
|||||||
#### CommonJS via `require()`
|
#### CommonJS via `require()`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const darkMode = require("@jakejarvis/dark-mode");
|
const darkMode = require("dark-mode-switcheroo");
|
||||||
|
|
||||||
darkMode.init({
|
darkMode.init({
|
||||||
// ...same as browser.
|
// ...same as browser.
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<p><a href="https://github.com/jakejarvis/dark-mode" target="_blank" rel="noopener">View the source code</a> or <a href="https://jarv.is/notes/dark-mode/" target="_blank" rel="noopener">read the post</a>.</p>
|
<p><a href="https://github.com/jakejarvis/dark-mode" target="_blank" rel="noopener">View the source code</a> or <a href="https://jarv.is/notes/dark-mode/" target="_blank" rel="noopener">read the post</a>.</p>
|
||||||
|
|
||||||
<script src="../dist/dark-mode.min.js"></script> <!-- or use CDN: https://unpkg.com/@jakejarvis/dark-mode/dist/dark-mode.min.js -->
|
<script src="../dist/dark-mode.min.js"></script> <!-- or use CDN: https://unpkg.com/dark-mode-switcheroo/dist/dark-mode.min.js -->
|
||||||
<script>
|
<script>
|
||||||
window.darkMode.init({
|
window.darkMode.init({
|
||||||
toggle: document.querySelector(".dark-mode-toggle"),
|
toggle: document.querySelector(".dark-mode-toggle"),
|
||||||
|
38
package.json
38
package.json
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "@jakejarvis/dark-mode",
|
"name": "dark-mode-switcheroo",
|
||||||
"version": "0.7.1",
|
"version": "0.10.0",
|
||||||
"description": "🌓 Simple CSS theme switching with saved preferences and automatic OS setting detection",
|
"description": "🌓 Simple CSS theme switching with saved preferences and automatic OS setting detection",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"homepage": "https://jrvs.io/darkmode",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Jake Jarvis",
|
"name": "Jake Jarvis",
|
||||||
"email": "jake@jarv.is",
|
"email": "jake@jarv.is",
|
||||||
@ -13,40 +14,35 @@
|
|||||||
"url": "https://github.com/jakejarvis/dark-mode.git"
|
"url": "https://github.com/jakejarvis/dark-mode.git"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"main": "./dist/dark-mode.cjs.js",
|
"source": "./src/dark-mode.ts",
|
||||||
|
"main": "./dist/dark-mode.cjs",
|
||||||
"module": "./dist/dark-mode.esm.js",
|
"module": "./dist/dark-mode.esm.js",
|
||||||
"unpkg": "./dist/dark-mode.min.js",
|
"unpkg": "./dist/dark-mode.min.js",
|
||||||
"types": "./dist/dark-mode.d.ts",
|
|
||||||
"exports": {
|
"exports": {
|
||||||
"require": "./dist/dark-mode.cjs.js",
|
"require": "./dist/dark-mode.cjs",
|
||||||
"import": "./dist/dark-mode.esm.js",
|
"import": "./dist/dark-mode.esm.js",
|
||||||
"browser": "./dist/dark-mode.min.js"
|
"browser": "./dist/dark-mode.min.js"
|
||||||
},
|
},
|
||||||
|
"types": "./dist/dark-mode.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "microbundle --format cjs,esm,umd --name 'darkMode'",
|
||||||
"lint": "eslint src/**/*.js",
|
"lint": "eslint .",
|
||||||
"prepublishOnly": "rm -rf dist && yarn build"
|
"prepublishOnly": "yarn build"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.15.0",
|
"@jakejarvis/eslint-config": "*",
|
||||||
"@babel/preset-env": "^7.15.0",
|
"@typescript-eslint/eslint-plugin": "^5.3.1",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@typescript-eslint/parser": "^5.3.1",
|
||||||
"@rollup/plugin-eslint": "^8.0.1",
|
"eslint": "^8.2.0",
|
||||||
"@rollup/plugin-node-resolve": "^13.0.4",
|
"microbundle": "^0.14.1",
|
||||||
"eslint": "^7.32.0",
|
"typescript": "^4.4.4"
|
||||||
"eslint-plugin-compat": "^3.13.0",
|
|
||||||
"rollup": "^2.56.3",
|
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
|
||||||
"rollup-plugin-filesize": "^9.1.1",
|
|
||||||
"rollup-plugin-terser": "^7.0.2"
|
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"frontend",
|
"front-end",
|
||||||
"dark mode",
|
"dark mode",
|
||||||
"theme",
|
"theme",
|
||||||
"appearance",
|
"appearance",
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
import pkg from "./package.json";
|
|
||||||
import resolve from "@rollup/plugin-node-resolve";
|
|
||||||
import { babel } from "@rollup/plugin-babel";
|
|
||||||
import { terser } from "rollup-plugin-terser";
|
|
||||||
import eslint from "@rollup/plugin-eslint";
|
|
||||||
import filesize from "rollup-plugin-filesize";
|
|
||||||
import copy from "rollup-plugin-copy";
|
|
||||||
|
|
||||||
const banner = `/*! Dark Mode Switcheroo v${pkg.version} | MIT License | jrvs.io/darkmode */`;
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
// universal (browser and node)
|
|
||||||
input: "src/index.js",
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
name: "darkMode",
|
|
||||||
file: "dist/dark-mode.js",
|
|
||||||
format: "umd",
|
|
||||||
exports: "named",
|
|
||||||
esModule: false,
|
|
||||||
banner: banner,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "darkMode",
|
|
||||||
file: "dist/dark-mode.min.js",
|
|
||||||
format: "umd",
|
|
||||||
exports: "named",
|
|
||||||
esModule: false,
|
|
||||||
plugins: [
|
|
||||||
terser({
|
|
||||||
output: {
|
|
||||||
preamble: banner,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
copy({
|
|
||||||
// clearly this isn't really typescript, so we need to manually copy the type definition file
|
|
||||||
targets: [
|
|
||||||
{
|
|
||||||
src: "src/index.d.ts",
|
|
||||||
dest: "dist",
|
|
||||||
rename: "dark-mode.d.ts",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
resolve(),
|
|
||||||
eslint(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: "bundled",
|
|
||||||
presets: [["@babel/preset-env"]],
|
|
||||||
exclude: ["node_modules/**"],
|
|
||||||
}),
|
|
||||||
filesize(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// modules
|
|
||||||
input: "src/index.js",
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
// ES6 module (import)
|
|
||||||
file: "dist/dark-mode.esm.js",
|
|
||||||
format: "esm",
|
|
||||||
exports: "named",
|
|
||||||
banner: banner,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// commonjs (require)
|
|
||||||
file: "dist/dark-mode.cjs.js",
|
|
||||||
format: "cjs",
|
|
||||||
exports: "named",
|
|
||||||
banner: banner,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
resolve(),
|
|
||||||
babel({
|
|
||||||
babelHelpers: "bundled",
|
|
||||||
exclude: ["node_modules/**"],
|
|
||||||
}),
|
|
||||||
filesize(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
@ -1,4 +1,12 @@
|
|||||||
const init = function (options) {
|
export function init(options: {
|
||||||
|
toggle?: Element | null;
|
||||||
|
classes?: { dark: string, light: string };
|
||||||
|
default?: string;
|
||||||
|
storageKey?: string;
|
||||||
|
onInit?: (toggle?: Element | null) => unknown;
|
||||||
|
onUserToggle?: (toggle?: Element | null) => unknown;
|
||||||
|
onChange?: (theme: string, toggle?: Element | null) => unknown;
|
||||||
|
}): void {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
// use a specified element(s) to trigger swap when clicked
|
// use a specified element(s) to trigger swap when clicked
|
||||||
@ -19,7 +27,12 @@ const init = function (options) {
|
|||||||
let active = defaultTheme === dark;
|
let active = defaultTheme === dark;
|
||||||
|
|
||||||
// receives a class name and switches <body> to it
|
// receives a class name and switches <body> to it
|
||||||
const activateTheme = function (theme, remember) {
|
const activateTheme = function (theme: string, remember?: boolean) {
|
||||||
|
// optional onChange callback function passed as option
|
||||||
|
if (typeof options.onChange === "function") {
|
||||||
|
options.onChange(theme, toggle);
|
||||||
|
}
|
||||||
|
|
||||||
document.body.classList.remove(dark, light);
|
document.body.classList.remove(dark, light);
|
||||||
document.body.classList.add(theme);
|
document.body.classList.add(theme);
|
||||||
active = theme === dark;
|
active = theme === dark;
|
||||||
@ -27,17 +40,17 @@ const init = function (options) {
|
|||||||
if (remember) {
|
if (remember) {
|
||||||
localStorage.setItem(storageKey, theme);
|
localStorage.setItem(storageKey, theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional onChange callback function passed as option
|
|
||||||
if (typeof options.onChange === "function") {
|
|
||||||
options.onChange(theme, toggle);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// optional onInit callback function passed as option
|
||||||
|
if (typeof options.onInit === "function") {
|
||||||
|
options.onInit(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
// user has never clicked the button, so go by their OS preference until/if they do so
|
// user has never clicked the button, so go by their OS preference until/if they do so
|
||||||
if (!pref) {
|
if (!pref) {
|
||||||
// returns media query selector syntax
|
// returns media query selector syntax
|
||||||
const prefers = function (colorScheme) {
|
const prefers = function (colorScheme: "dark" | "light") {
|
||||||
// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
|
// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
|
||||||
return `(prefers-color-scheme: ${colorScheme})`;
|
return `(prefers-color-scheme: ${colorScheme})`;
|
||||||
};
|
};
|
||||||
@ -75,6 +88,11 @@ const init = function (options) {
|
|||||||
if (toggle !== null) {
|
if (toggle !== null) {
|
||||||
// handle toggle click
|
// handle toggle click
|
||||||
toggle.addEventListener("click", function () {
|
toggle.addEventListener("click", function () {
|
||||||
|
// optional onUserToggle callback function passed as option
|
||||||
|
if (typeof options.onUserToggle === "function") {
|
||||||
|
options.onUserToggle(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
// switch to the opposite theme & save preference in local storage
|
// switch to the opposite theme & save preference in local storage
|
||||||
if (active) {
|
if (active) {
|
||||||
activateTheme(light, true);
|
activateTheme(light, true);
|
||||||
@ -83,11 +101,4 @@ const init = function (options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional onInit callback function passed as option
|
|
||||||
if (typeof options.onInit === "function") {
|
|
||||||
options.onInit(toggle);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export { init };
|
|
8
src/index.d.ts
vendored
8
src/index.d.ts
vendored
@ -1,8 +0,0 @@
|
|||||||
export function init(options?: {
|
|
||||||
toggle?: HTMLElement;
|
|
||||||
classes?: { dark: string, light: string };
|
|
||||||
default?: string;
|
|
||||||
storageKey?: string;
|
|
||||||
onInit?: (toggle?: HTMLElement) => unknown;
|
|
||||||
onChange?: (theme?: string, toggle?: HTMLElement) => unknown;
|
|
||||||
}): void;
|
|
Loading…
x
Reference in New Issue
Block a user