Skip to content

Commit f96e860

Browse files
committed
docs(theme): add theme for light & dark theme usage
1 parent 2506d6e commit f96e860

File tree

5 files changed

+96
-27
lines changed

5 files changed

+96
-27
lines changed

packages/site-demo/content/menu.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- Typography
66
- Size
77
- Spacing
8+
- Light & Dark Theme
89
- Components: '*'
910
- Patterns:
1011
- Drag and drop
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { ThemeProvider, Button, Chip, Flag, useTheme } from '@lumx/react';
2+
3+
# Light & Dark Theme
4+
5+
By default, all component use a `light` theme that works on light-colored backgrounds.
6+
**Some components** provide an alternative `dark` theme that can be used to adapt to dark backgrounds.
7+
8+
This theme is not synced to the user's preferred color scheme, it **must be activated manually**.
9+
10+
## Activate via prop
11+
12+
On the supported components, use the `theme` prop to activate the desired theme.
13+
14+
<DemoBlock orientation="horizontal" withThemeSwitcher theme="dark" alwaysShowCode>
15+
{function App({ theme }) {
16+
return (
17+
<>
18+
<Button theme={theme}>Button</Button>
19+
<Chip theme={theme}>Chip</Chip>
20+
</>
21+
)
22+
}}
23+
</DemoBlock>
24+
25+
## Activate via context
26+
27+
Use the `ThemeProvider` component to apply the desired theme to all descendants that supports it.
28+
29+
<DemoBlock orientation="horizontal" withThemeSwitcher theme="dark" alwaysShowCode>
30+
{function App({ theme }) {
31+
return (
32+
<ThemeProvider value={theme}>
33+
<Button>Button</Button>
34+
<Chip>Chip</Chip>
35+
</ThemeProvider>
36+
)
37+
}}
38+
</DemoBlock>
39+
40+
Please note **some exceptions** to the theme context propagation:
41+
- The `Popover` ignores the theme context for now because most children that we put inside do not support the `dark` theme (List & ListItem)
42+
- The components `Popover`, `Lightbox` and `Dialog` all stop the propagation of the theme context and reset the theme because their children won't appear on the same background from where they are called
43+
44+
Use the `useTheme()` hook to get the theme from the current theme context when you need to adapt within your custom component.
45+
46+
<DemoBlock orientation="horizontal" withThemeSwitcher theme="dark" alwaysShowCode>
47+
{function App({ theme }) {
48+
function MyComponent() {
49+
const theme = useTheme();
50+
return <Flag theme={theme} label={`Current theme: ${theme}`} />;
51+
}
52+
return <ThemeProvider value={theme}><MyComponent /></ThemeProvider>;
53+
}}
54+
</DemoBlock>

packages/site-demo/plugins/lumx-mdx-preprocessor/mdx-demo-block.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ const removeIndent = (code) => {
2424
return code.trim().replace(new RegExp(`\n${indentMatch[1]}`, 'g'), '\n')
2525
}
2626

27+
// Use a regular expression to remove curly braces at the start and end
28+
function removeCurlyBracesFromJSX(code) {
29+
return code.replace(/^\{|\}$/g, '');
30+
}
31+
2732
/** Update <DemoBlock/> props to import source code. */
2833
async function updateDemoBlock(resourceFolder, addImport, props) {
2934
if (props.children) {
3035
// <DemoBlock> with children already have a demo inside them.
3136
// We copy the demo as string into the `codeString` prop.
32-
props.codeString = JSON.stringify(removeIndent(props.children));
37+
props.codeString = JSON.stringify(removeCurlyBracesFromJSX(removeIndent(props.children)));
3338
return props;
3439
}
3540

packages/site-demo/src/components/content/DemoBlock/DemoBlock.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
&__theme-toggle {
3737
flex-shrink: 0;
38+
margin-left: auto;
3839
}
3940

4041
&__code {

packages/site-demo/src/components/content/DemoBlock/DemoBlock.tsx

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ import './DemoBlock.scss';
2323
interface DemoBlockProps extends FlexBoxProps {
2424
demo?: string;
2525
codeString?: string;
26+
theme?: Theme;
2627
withThemeSwitcher?: boolean;
2728
hasPlayButton?: boolean;
2829
backgroundColor?: { color: ColorPalette; variant: ColorVariant };
30+
alwaysShowCode?: boolean;
2931
}
3032

3133
const DEFAULT_PROPS: Partial<DemoBlockProps> = {
@@ -37,17 +39,19 @@ export const DemoBlock: React.FC<DemoBlockProps> = ({
3739
children,
3840
demo,
3941
codeString,
42+
theme: defaultTheme = Theme.light,
4043
withThemeSwitcher = false,
4144
hasPlayButton = false,
4245
backgroundColor: propBackgroundColor,
46+
alwaysShowCode,
4347
...flexBoxProps
4448
}) => {
45-
const [theme, setTheme] = useState<Theme>(Theme.light);
49+
const [theme, setTheme] = useState<Theme>(defaultTheme);
4650
const toggleTheme = (isChecked: boolean) => {
4751
setTheme(isChecked ? Theme.dark : Theme.light);
4852
};
4953

50-
const [showCode, setShowCode] = useState(false);
54+
const [showCode, setShowCode] = useState(!!alwaysShowCode);
5155
const toggleShowCode = () => setShowCode(!showCode);
5256

5357
if (flexBoxProps.orientation === Orientation.horizontal) {
@@ -74,31 +78,35 @@ export const DemoBlock: React.FC<DemoBlockProps> = ({
7478
)}
7579
{isFunction(children) ? children({ theme }) : children}
7680
</FlexBox>
77-
<div className="demo-block__toolbar">
78-
<div className="demo-block__code-toggle">
79-
<Button
80-
disabled={!codeString}
81-
emphasis={Emphasis.low}
82-
leftIcon={mdiCodeTags}
83-
onClick={toggleShowCode}
84-
>
85-
{showCode ? 'Hide code' : 'Show code'}
86-
</Button>
87-
</div>
81+
{(!alwaysShowCode || withThemeSwitcher) && (
82+
<div className="demo-block__toolbar">
83+
{!alwaysShowCode && (
84+
<div className="demo-block__code-toggle">
85+
<Button
86+
disabled={!codeString}
87+
emphasis={Emphasis.low}
88+
leftIcon={mdiCodeTags}
89+
onClick={toggleShowCode}
90+
>
91+
{showCode ? 'Hide code' : 'Show code'}
92+
</Button>
93+
</div>
94+
)}
8895

89-
{withThemeSwitcher && (
90-
<div className="demo-block__theme-toggle">
91-
<Switch
92-
disabled={!children}
93-
position={Alignment.right}
94-
isChecked={theme === Theme.dark}
95-
onChange={toggleTheme}
96-
>
97-
Dark theme
98-
</Switch>
99-
</div>
100-
)}
101-
</div>
96+
{withThemeSwitcher && (
97+
<div className="demo-block__theme-toggle">
98+
<Switch
99+
disabled={!children}
100+
position={Alignment.right}
101+
isChecked={theme === Theme.dark}
102+
onChange={toggleTheme}
103+
>
104+
Dark theme
105+
</Switch>
106+
</div>
107+
)}
108+
</div>
109+
)}
102110

103111
<CodeBlock
104112
className={classNames('demo-block__code', showCode && codeString && 'demo-block__code--shown')}

0 commit comments

Comments
 (0)