-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(theme): create more generic ThemedComponent util from ThemedImage (
- Loading branch information
Showing
4 changed files
with
105 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
packages/docusaurus-theme-common/src/components/ThemedComponent/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React from 'react'; | ||
import clsx from 'clsx'; | ||
import useIsBrowser from '@docusaurus/useIsBrowser'; | ||
import {useColorMode} from '../../contexts/colorMode'; | ||
|
||
import styles from './styles.module.css'; | ||
|
||
const AllThemes = ['light', 'dark'] as const; | ||
|
||
type Theme = (typeof AllThemes)[number]; | ||
|
||
type RenderFn = ({ | ||
theme, | ||
className, | ||
}: { | ||
theme: Theme; | ||
className: string; | ||
}) => React.ReactNode; | ||
|
||
type Props = { | ||
children: RenderFn; | ||
className?: string; | ||
}; | ||
|
||
/** | ||
* Generic component to render anything themed in light/dark | ||
* Note: it's preferable to use CSS for theming because this component | ||
* will need to render all the variants during SSR to avoid a theme flash. | ||
* | ||
* Use this only when CSS customizations are not convenient or impossible. | ||
* For example, rendering themed images or SVGs... | ||
* | ||
* @param className applied to all the variants | ||
* @param children function to render a theme variant | ||
* @constructor | ||
*/ | ||
export default function ThemedComponent({ | ||
className, | ||
children, | ||
}: Props): JSX.Element { | ||
const isBrowser = useIsBrowser(); | ||
const {colorMode} = useColorMode(); | ||
|
||
function getThemesToRender(): Theme[] { | ||
if (isBrowser) { | ||
return colorMode === 'dark' ? ['dark'] : ['light']; | ||
} | ||
// We need to render both components on the server / hydration to avoid: | ||
// - a flash of wrong theme before hydration | ||
// - React hydration mismatches | ||
// See https://github.com/facebook/docusaurus/pull/3730 | ||
return ['light', 'dark']; | ||
} | ||
|
||
return ( | ||
<> | ||
{getThemesToRender().map((theme) => { | ||
const themedElement = children({ | ||
theme, | ||
className: clsx( | ||
className, | ||
styles.themedComponent, | ||
styles[`themedComponent--${theme}`], | ||
), | ||
}); | ||
return <React.Fragment key={theme}>{themedElement}</React.Fragment>; | ||
})} | ||
</> | ||
); | ||
} |
18 changes: 18 additions & 0 deletions
18
packages/docusaurus-theme-common/src/components/ThemedComponent/styles.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
.themedComponent { | ||
display: none; | ||
} | ||
|
||
[data-theme='light'] .themedComponent--light { | ||
display: initial; | ||
} | ||
|
||
[data-theme='dark'] .themedComponent--dark { | ||
display: initial; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters