Skip to content

Commit

Permalink
feat: add permanent properties & permanentcolorscheme event.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Mar 16, 2022
1 parent 5e27557 commit d1ff9ba
Show file tree
Hide file tree
Showing 4 changed files with 404 additions and 26 deletions.
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,82 @@ Properties can be set directly on the custom element at creation time, or dynami

```typescript
export type ColorScheme = 'light' | 'dark';
export type ColorSchemeChangeEvent = CustomEvent<{ colorScheme: ColorScheme }>;
export class DarkMode extends HTMLElement {
mode?: ColorScheme;
/**
* Defaults to not remember the last choice.
* If present remembers the last selected mode (`dark` or `light`),
* which allows the user to permanently override their usual preferred color scheme.
*/
permanent?: boolean;
/**
* Any string value that represents the label for the "dark" mode.
*/
dark?: string;
/**
* Any string value that represents the label for the "light" mode.
*/
light?: string;
style?: React.CSSProperties;
}
```

## Complete Example

Interacting with the custom element:

```js
const darkMode = document.querySelector('dark-mode');

// Set the mode to dark
darkMode.mode = 'dark';
// Set the mode to light
darkMode.mode = 'light';

// Set the light label to "off"
darkMode.light = 'off';
// Set the dark label to "on"
darkMode.dark = 'on';

// Set a "remember the last selected mode" label
darkMode.permanent = 'on';

// Remember the user's last color scheme choice
darkModeToggle.setAttribute('permanent', false);
// Forget the user's last color scheme choice
darkModeToggle.removeAttribute('permanent');
```

Reacting on color scheme changes:

```js
/* On the page */
document.addEventListener('colorschemechange', (e) => {
console.log(`Color scheme changed to ${e.detail.colorScheme}.`);
});
```

Reacting on "remember the last selected mode" functionality changes:

```js
/* On the page */
document.addEventListener('permanentcolorscheme', (e) => {
console.log(`${e.detail.permanent ? 'R' : 'Not r'}emembering the last selected mode.`);
});
```

## Events

- `colorschemechange`: Fired when the color scheme gets changed.
- `permanentcolorscheme`: Fired when the color scheme should be permanently remembered or not.

## Alternatives

- [dark-mode-toggle](https://github.com/GoogleChromeLabs/dark-mode-toggle) <img align="bottom" height="13" src="https://img.shields.io/github/stars/GoogleChromeLabs/dark-mode-toggle.svg?label=" /> A custom element that allows you to easily put a Dark Mode 🌒 toggle or switch on your site
- [Darkmode.js](https://github.com/sandoche/Darkmode.js) <img align="bottom" height="13" src="https://img.shields.io/github/stars/sandoche/Darkmode.js.svg?label=" /> Add a dark-mode / night-mode to your website in a few seconds
- [darken](https://github.com/ColinEspinas/darken) <img align="bottom" height="13" src="https://img.shields.io/github/stars/ColinEspinas/darken.svg?label=" /> Dark mode made easy
- [use-dark-mode](https://github.com/donavon/use-dark-mode) <img align="bottom" height="13" src="https://img.shields.io/github/stars/donavon/use-dark-mode.svg?label=" /> A custom React Hook to help you implement a "dark mode" component.
- [Dark Mode Switch](https://github.com/coliff/dark-mode-switch) <img align="bottom" height="13" src="https://img.shields.io/github/stars/coliff/dark-mode-switch.svg?label=" /> Add a dark-mode theme toggle with a Bootstrap Custom Switch

## Contributors

Expand Down
214 changes: 210 additions & 4 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
<meta description="🌓 Add dark mode/night mode custom elements to your website." />
<script src="./main.js"></script>
<style>
body {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
}
a {
color: var(--color-thme-text);
}
</style>
</head>
<body>
<body style="margin: 0 auto; max-width: 520px;">
<h1>Hi there!</h1>
<div>I'm your cool new webpage! Use the toggle in the <dark-mode></dark-mode> button to switch my theme.</div>
<div>I'm your cool new webpage! Use the toggle in the <dark-mode style="border: 2px solid blue"></dark-mode> button to switch my theme.</div>
<dark-mode onclick="console.log('Hello')" mode="light"></dark-mode>
<dark-mode onchange="handleDarkMode" dark="Dark" light="Light" style="border: 1px solid red; font-size: 12px;"></dark-mode>
<br /><br />
Expand All @@ -30,13 +33,216 @@ <h1>Hi there!</h1>
button.style = 'line-height: 16px';
button.onclick = () => {
const theme = document.documentElement.dataset.colorMode;
document.documentElement.setAttribute('data-color-mode', theme === 'light' ? 'dark' : 'light');
toggle.mode = theme === 'light' ? 'dark' : 'light';
// document.documentElement.setAttribute('data-color-mode', theme === 'light' ? 'dark' : 'light');
}
document.body.appendChild(button);
document.addEventListener('colorschemechange', (e) => {
console.log(`Color scheme changed to "${e.detail.colorScheme}" or "${toggle.mode}".`);
// console.log(`colorschemechange: Color scheme changed to "${e.detail.colorScheme}" or .`);
button.textContent = toggle.mode === 'dark' ? 'Change Theme 🌞' : 'Change Theme 🌒';
});
document.addEventListener('permanentcolorscheme', (e) => {
// console.log(`~permanentcolorscheme: Color scheme changed to "${e.detail.colorScheme}" or .`);
});
const removePermanent = () => document.querySelectorAll('dark-mode').forEach((item) => item.removeAttribute('permanent'));
</script>
<button onclick="toggle.light = '明(Light)主题';toggle.dark = '暗(Dark)主题'">Change Label</button>
<button onclick="removePermanent();">Change permanent <span id="permanent">false</span></button>
<br />
<br />
<dark-mode permanent></dark-mode>
<span>👈 The <b>mode</b> is remembered after clicking it.</span>
<br /><br />
<script>
const buttonClean = document.createElement('button');
document.body.appendChild(buttonClean);
buttonClean.textContent = `Clean localStorage (${toggle.LOCAL_NANE})`;
buttonClean.style = 'line-height: 16px';
buttonClean.onclick = () => {
localStorage.removeItem(toggle.LOCAL_NANE);
}
</script>
<br /><br />
<link rel="stylesheet" href="https://unpkg.com/@wcj/markdown-to-html/dist/marked.css">
<script src="https://unpkg.com/@wcj/markdown-to-html"></script>
<script type="text/javascript">
;(() => {
const str = `## \`<dark-mode />\`
[![CI](https://github.com/jaywcjlove/dark-mode/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/dark-mode/actions/workflows/ci.yml)
[![jsDelivr CDN](https://data.jsdelivr.com/v1/package/npm/@wcj/dark-mode/badge?style=rounded)](https://www.jsdelivr.com/package/npm/@wcj/dark-mode)
[![npm version](https://img.shields.io/npm/v/@wcj/dark-mode.svg)](https://www.npmjs.com/package/@wcj/dark-mode)
[![Open in unpkg](https://img.shields.io/badge/Open%20in-unpkg-blue)](https://uiwjs.github.io/npm-unpkg/#/pkg/@wcj/dark-mode/file/README.md)
A custom element that allows you to easily put a Dark Mode 🌒 toggle. so you can initially adhere to your users' preferences according to [\`prefers-color-scheme\`](https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme), but also allow them to (optionally permanently) override their system setting for just your site.
## Installation
Install from npm:
\`\`\`bash
npm install --save @wcj/dark-mode
\`\`\`
Or, alternatively, use a \`<script defer>\` tag (served from unpkg's CDN):
CDN: [UNPKG](https://unpkg.com/@wcj/dark-mode/dist/) | [jsDelivr](https://cdn.jsdelivr.net/npm/@wcj/dark-mode/) | [Githack](https://raw.githack.com/jaywcjlove/dark-mode/gh-pages/dark-mode.min.js) | [Statically](https://cdn.statically.io/gh/jaywcjlove/dark-mode/gh-pages/dark-mode.min.js)
\`\`\`html
<script src="https://unpkg.com/@wcj/dark-mode"><\/script>
\`\`\`
## Usage
There are two ways how you can use \`<dark-mode>\`:
\`\`\`html
<dark-mode><\/dark-mode>
<dark-mode light="Dart" dark="Light"><\/dark-mode>
<dark-mode dark="Dark" light="Light" style="border: 1px solid red; font-size: 12px;"><\/dark-mode>
\`\`\`
Use in [React](https://github.com/facebook/react):
\`\`\`jsx
import React from 'react';
import '@wcj/dark-mode';
function Demo() {
return (
<div>
<dark-mode light="Dart" dark="Light"><\/dark-mode>
<\/div>
);
}
\`\`\`
Toggle in JavaScript:
\`\`\`js
const toggle = document.querySelector('dark-mode');
const button = document.createElement('button');
button.textContent = 'Change Theme';
button.onclick = () => {
const theme = document.documentElement.dataset.colorMode;
// or => const theme = toggle.mode
document.documentElement.setAttribute('data-color-mode', theme === 'light' ? 'dark' : 'light');
}
document.body.appendChild(button);
// Listen for toggle changes
// and toggle the \`dark\` class accordingly.
document.addEventListener('colorschemechange', (e) => {
console.log(\`Color scheme changed to "$\{e.detail.colorScheme}" or "$\{toggle.mode}".\`);
button.textContent = toggle.mode === 'dark' ? 'Change Theme 🌞' : 'Change Theme 🌒';
});
\`\`\`
## Properties
Properties can be set directly on the custom element at creation time, or dynamically via JavaScript.
\`\`\`typescript
export type ColorScheme = 'light' | 'dark';
export class DarkMode extends HTMLElement {
mode?: ColorScheme;
/**
* Defaults to not remember the last choice.
* If present remembers the last selected mode (\`dark\` or \`light\`),
* which allows the user to permanently override their usual preferred color scheme.
*/
permanent?: boolean;
/**
* Any string value that represents the label for the "dark" mode.
*/
dark?: string;
/**
* Any string value that represents the label for the "light" mode.
*/
light?: string;
style?: React.CSSProperties;
}
\`\`\`
## Events
- \`colorschemechange\`: Fired when the color scheme gets changed.
- \`permanentcolorscheme\`: Fired when the color scheme should be permanently remembered or not.
## Complete Example
Interacting with the custom element:
\`\`\`js
const darkMode = document.querySelector('dark-mode');
// Set the mode to dark
darkMode.mode = 'dark';
// Set the mode to light
darkMode.mode = 'light';
// Set the light label to "off"
darkMode.light = 'off';
// Set the dark label to "on"
darkMode.dark = 'on';
// Set a "remember the last selected mode" label
darkMode.permanent = 'on';
// Remember the user's last color scheme choice
darkModeToggle.setAttribute('permanent', false);
// Forget the user's last color scheme choice
darkModeToggle.removeAttribute('permanent');
\`\`\`
Reacting on color scheme changes:
\`\`\`js
/* On the page */
document.addEventListener('colorschemechange', (e) => {
console.log(\`Color scheme changed to $\{e.detail.colorScheme}.\`);
});
\`\`\`
Reacting on "remember the last selected mode" functionality changes:
\`\`\`js
/* On the page */
document.addEventListener('permanentcolorscheme', (e) => {
console.log(\`$\{e.detail.permanent ? 'R' : 'Not r'}emembering the last selected mode.\`);
});
\`\`\`
## Alternatives
- [dark-mode-toggle](https://github.com/GoogleChromeLabs/dark-mode-toggle) <img align="bottom" height="13" src="https://img.shields.io/github/stars/GoogleChromeLabs/dark-mode-toggle.svg?label=" /> A custom element that allows you to easily put a Dark Mode 🌒 toggle or switch on your site
- [Darkmode.js](https://github.com/sandoche/Darkmode.js) <img align="bottom" height="13" src="https://img.shields.io/github/stars/sandoche/Darkmode.js.svg?label=" /> Add a dark-mode / night-mode to your website in a few seconds
- [darken](https://github.com/ColinEspinas/darken) <img align="bottom" height="13" src="https://img.shields.io/github/stars/ColinEspinas/darken.svg?label=" /> Dark mode made easy
- [use-dark-mode](https://github.com/donavon/use-dark-mode) <img align="bottom" height="13" src="https://img.shields.io/github/stars/donavon/use-dark-mode.svg?label=" /> A custom React Hook to help you implement a "dark mode" component.
- [Dark Mode Switch](https://github.com/coliff/dark-mode-switch) <img align="bottom" height="13" src="https://img.shields.io/github/stars/coliff/dark-mode-switch.svg?label=" /> Add a dark-mode theme toggle with a Bootstrap Custom Switch
## Contributors
As always, thanks to our amazing contributors!
<a href="https://github.com/jaywcjlove/dark-mode/graphs/contributors">
<img src="https://jaywcjlove.github.io/dark-mode/CONTRIBUTORS.svg" />
</a>
Made with [github-action-contributors](https://github.com/jaywcjlove/github-action-contributors).
## License
Licensed under the [MIT License](https://opensource.org/licenses/MIT).
`;
const div = document.createElement('div');
div.className = 'markdown-body';
div.style = 'padding: 15px 0 25px 0;';
div.innerHTML = markdown.default(str)
document.body.appendChild(div)
})()
</script>
</body>
</html>
34 changes: 34 additions & 0 deletions main.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@

export type ColorScheme = 'light' | 'dark';
export type ColorSchemeChangeEvent = CustomEvent<{ colorScheme: ColorScheme }>;
export type PermanentColorSchemeEvent = CustomEvent<{ colorScheme: ColorScheme, permanent: boolean }>;
export class DarkMode extends HTMLElement {
mode?: ColorScheme;
/**
* Defaults to not remember the last choice.
* If present remembers the last selected mode (`dark` or `light`),
* which allows the user to permanently override their usual preferred color scheme.
*/
permanent?: boolean;
/**
* Any string value that represents the label for the "dark" mode.
*/
dark?: string;
/**
* Any string value that represents the label for the "light" mode.
*/
light?: string;
style?: React.CSSProperties;
}
Expand All @@ -13,7 +26,28 @@ declare global {
'dark-mode': DarkMode;
}
interface GlobalEventHandlersEventMap {
/**
* Fired when the color scheme gets changed.
*
* ```js
* const toggle = document.querySelector('dark-mode');
* document.addEventListener('colorschemechange', (e) => {
* console.log(`Color scheme changed to "${e.detail.colorScheme}".`);
* console.log(toggle.mode === 'dark' ? 'Change Theme 🌞' : 'Change Theme 🌒')
* });
* ```
*/
'colorschemechange': ColorSchemeChangeEvent;
/**
* Fired when the color scheme should be permanently remembered or not.
*
* ```js
* document.addEventListener('permanentcolorscheme', (e) => {
* console.log(`~: Color scheme changed to "${e.detail.colorScheme}" , "${e.detail.permanent}" .`);
* });
* ```
*/
'permanentcolorscheme': PermanentColorSchemeEvent;
}
namespace JSX {
interface IntrinsicElements {
Expand Down

0 comments on commit d1ff9ba

Please sign in to comment.