Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(theme-{classic,common}): refactor ColorModeToggle + useColorMode() hook #6930

Merged
merged 15 commits into from Mar 18, 2022
Merged
6 changes: 3 additions & 3 deletions packages/docusaurus-theme-classic/src/theme-classic.d.ts
Expand Up @@ -746,12 +746,12 @@ declare module '@theme/TOCCollapsible' {
}

declare module '@theme/ColorModeToggle' {
import type {SyntheticEvent} from 'react';
import type {ColorMode} from '@docusaurus/theme-common';

export interface Props {
readonly className?: string;
readonly checked: boolean;
readonly onChange: (e: SyntheticEvent) => void;
readonly value: ColorMode;
readonly onChange: (colorMode: ColorMode) => void;
}

export default function Toggle(props: Props): JSX.Element;
Expand Down
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import React, {useState, useRef, useEffect} from 'react';
import React from 'react';
import type {Props} from '@theme/ColorModeToggle';
import useIsBrowser from '@docusaurus/useIsBrowser';
import {translate} from '@docusaurus/Translate';
Expand All @@ -17,76 +17,55 @@ import styles from './styles.module.css';

function ColorModeToggle({
className,
checked: defaultChecked,
onChange,
value: colorMode,
onChange: setColorMode,
}: Props): JSX.Element {
const isBrowser = useIsBrowser();
const [checked, setChecked] = useState(defaultChecked);
const [focused, setFocused] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
setChecked(defaultChecked);
}, [defaultChecked]);
const title = translate(
{
message: 'Switch between dark and light mode (currently {mode})',
id: 'theme.colorToggle.ariaLabel',
description: 'The ARIA label for the navbar color mode toggle',
},
{
mode:
colorMode === 'dark'
? translate({
message: 'dark mode',
id: 'theme.colorToggle.ariaLabel.mode.dark',
description: 'The name for the dark color mode',
})
: translate({
message: 'light mode',
id: 'theme.colorToggle.ariaLabel.mode.light',
description: 'The name for the light color mode',
}),
},
);

return (
<div
className={clsx(
styles.toggle,
className,
checked && styles.toggleChecked,
focused && styles.toggleFocused,
!isBrowser && styles.toggleDisabled,
)}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
<div
className={styles.toggleButton}
role="button"
tabIndex={-1}
onClick={() => inputRef.current?.click()}>
<div className={clsx(styles.toggle, className)}>
<button
className={clsx(
'clean-btn',
styles.toggleButton,
!isBrowser && styles.toggleButtonDisabled,
)}
type="button"
onClick={() => {
setColorMode(colorMode === 'dark' ? 'light' : 'dark');
}}
disabled={!isBrowser}
title={title}
aria-label={title}>
<IconLightMode
className={clsx(styles.toggleIcon, styles.lightToggleIcon)}
/>
<IconDarkMode
className={clsx(styles.toggleIcon, styles.darkToggleIcon)}
/>
</div>

<input
ref={inputRef}
checked={checked}
type="checkbox"
className={styles.toggleScreenReader}
aria-label={translate(
{
message: 'Switch between dark and light mode (currently {mode})',
id: 'theme.colorToggle.ariaLabel',
description: 'The ARIA label for the navbar color mode toggle',
},
{
mode: checked
? translate({
message: 'dark mode',
id: 'theme.colorToggle.ariaLabel.mode.dark',
description: 'The name for the dark color mode',
})
: translate({
message: 'light mode',
id: 'theme.colorToggle.ariaLabel.mode.light',
description: 'The name for the light color mode',
}),
},
)}
onChange={onChange}
onClick={() => setChecked(!checked)}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
inputRef.current?.click();
}
}}
/>
</button>
</div>
);
}
Expand Down
Expand Up @@ -6,46 +6,30 @@
*/

.toggle {
position: relative;
width: 32px;
height: 32px;
}

.toggleScreenReader {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
position: absolute;
width: 1px;
}

.toggleDisabled {
cursor: not-allowed;
width: 2rem;
height: 2rem;
}

.toggleButton {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
align-items: center;
display: flex;
justify-content: center;
width: 100%;
height: 100%;
border-radius: 50%;
transition: background var(--ifm-transition-fast);
}

.toggleButton:hover {
background-color: #00000010;
}

[data-theme='dark'] .toggleButton:hover {
background-color: #ffffff20;
background: var(--ifm-color-emphasis-200);
}

[data-theme='light'] .darkToggleIcon,
[data-theme='dark'] .lightToggleIcon {
display: none;
}

.toggleButtonDisabled {
cursor: not-allowed;
}
20 changes: 10 additions & 10 deletions packages/docusaurus-theme-classic/src/theme/Navbar/index.tsx
Expand Up @@ -88,12 +88,12 @@ function useColorModeToggle() {
const {
colorMode: {disableSwitch},
} = useThemeConfig();
const {isDarkTheme, setLightTheme, setDarkTheme} = useColorMode();
const toggle = useCallback(
(e) => (e.target.checked ? setDarkTheme() : setLightTheme()),
[setLightTheme, setDarkTheme],
);
return {isDarkTheme, toggle, disabled: disableSwitch};
const {colorMode, setColorMode} = useColorMode();
return {
value: colorMode,
onChange: setColorMode,
disabled: disableSwitch,
};
}

function useSecondaryMenu({
Expand Down Expand Up @@ -173,8 +173,8 @@ function NavbarMobileSidebar({
{!colorModeToggle.disabled && (
<ColorModeToggle
className={styles.navbarSidebarToggle}
checked={colorModeToggle.isDarkTheme}
onChange={colorModeToggle.toggle}
value={colorModeToggle.value}
onChange={colorModeToggle.onChange}
/>
)}
<button
Expand Down Expand Up @@ -279,8 +279,8 @@ export default function Navbar(): JSX.Element {
{!colorModeToggle.disabled && (
<ColorModeToggle
className={styles.toggle}
checked={colorModeToggle.isDarkTheme}
onChange={colorModeToggle.toggle}
value={colorModeToggle.value}
onChange={colorModeToggle.onChange}
/>
)}
{!hasSearchNavbarItem && <SearchBar />}
Expand Down
7 changes: 6 additions & 1 deletion packages/docusaurus-theme-common/src/index.ts
Expand Up @@ -140,7 +140,12 @@ export {
PluginHtmlClassNameProvider,
} from './utils/metadataUtilsTemp';

export {useColorMode, ColorModeProvider} from './utils/colorModeUtils';
export {
useColorMode,
ColorModeProvider,
type ColorMode,
} from './utils/colorModeUtils';

export {
useTabGroupChoice,
TabGroupChoiceProvider,
Expand Down