A tiny 153-byte polyfill for Promise.prototype.finally
.
Useful for browsers that support Promise but not the .finally()
method.
npm install finally-polyfill
body {color: #333; background: #fff;} | |
/* Set dark mode styles */ | |
@media (prefers-color-scheme: dark) { | |
body {color: #fff; background: #333;} | |
} |
import React, { useState, useCallback } from 'react'; | |
import DarkModeToggleSwitch from './DarkModeToggleSwitch'; | |
import ThemeContext, { DARK_THEME, LIGHT_THEME, DarkMode } from './theme'; | |
export default function App () { | |
const [ dark, setDark ] = useState(DarkMode.getSetting); | |
const theme = dark ? DARK_THEME : LIGHT_THEME; | |
const toggleDarkMode = useCallback(function () { | |
setDark(prevState => { |
import React from 'react'; | |
import { Sun, Moon } from 'react-feather'; | |
export default function DarkModeToggleSwitch ({ on, toggle }) { | |
const props = { | |
type: 'button', | |
role: 'switch', | |
onClick: (typeof toggle === 'function') ? toggle : () => {}, | |
'aria-checked': (on = on === true) | |
}; |
import React from 'react'; | |
const DARK_MODE_KEY = 'dark_mode'; | |
const DARK_THEME = { color: '#fff', background: '#333' }; | |
const LIGHT_THEME = { color: '#333', background: '#fff' }; | |
const DarkMode = { | |
getSetting: function () { | |
try { | |
return JSON.parse(window.localStorage.getItem(DARK_MODE_KEY)) === true; |
import React, { useState, useCallback } from 'react'; | |
import DarkModeToggleSwitch from './DarkModeToggleSwitch'; | |
import ThemeContext, { DARK_THEME, LIGHT_THEME, DarkMode } from './theme'; | |
export default function App () { | |
const [ dark, setDark ] = useState(DarkMode.getSetting); | |
const theme = dark ? DARK_THEME : LIGHT_THEME; | |
const toggleDarkMode = useCallback(function () { | |
setDark(prevState => { |
import { useState, useEffect, useRef } from 'react'; | |
export default function useColorScheme() { | |
const COLOR_SCHEMES = ['no-preference', 'dark', 'light']; | |
const FALLBACK_COLOR_SCHEME = 'dark'; | |
const resolveColorScheme = () => { | |
for (let scheme of COLOR_SCHEMES) { | |
const mediaQuery = matchMedia(`(prefers-color-scheme: ${scheme})`); |
const item = { | |
quantity: 4, | |
unitPrice: 49.99, | |
discount: 0.24, | |
get price () { return (this.quantity * this.unitPrice * (1 - this.discount)).toFixed(2) } | |
}; | |
// String concatenation | |
const pricing = 'The total price of ' + item.quantity + ' units of this item is $' + item.price + '.'; |
<button type="button" class="ripple btn"> | |
<i class="btn__icon"> | |
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> | |
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z" fill="currentColor"/> | |
</svg> | |
</i> | |
<s |
All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.
elem.offsetLeft
, elem.offsetTop
, elem.offsetWidth
, elem.offsetHeight
, elem.offsetParent
elem.clientLeft
, elem.clientTop
, elem.clientWidth
, elem.clientHeight
elem.getClientRects()
, elem.getBoundingClientRect()