Skip to content

Commit 9966ab7

Browse files
shairezitaim18shiroinegai
committed
refactor: use tailwind css theme toggle
Co-authored-by: Itai Mizlish <[email protected]> Co-authored-by: Shiroi Negai <[email protected]>
1 parent 8675f1c commit 9966ab7

File tree

14 files changed

+100
-58
lines changed

14 files changed

+100
-58
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createContextId } from '@builder.io/qwik';
2+
import { AppState } from './app-state.type';
3+
4+
export const APP_STATE_CONTEXT_ID = createContextId<AppState>(
5+
'app-state-context-id'
6+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface AppState {
2+
mode: 'light' | 'dark';
3+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useTask$ } from '@builder.io/qwik';
2+
import { isBrowser } from '@builder.io/qwik/build';
3+
import { AppState } from './app-state.type';
4+
5+
export const THEME_STORAGE_KEY = 'theme-preference';
6+
7+
export const useCSSTheme = (appState: AppState) => {
8+
useTask$(({ track }) => {
9+
track(() => appState.mode);
10+
11+
if (isBrowser) {
12+
document.documentElement.setAttribute('class', appState.mode);
13+
localStorage.setItem(THEME_STORAGE_KEY, appState.mode);
14+
}
15+
});
16+
};

apps/website/src/components/header/header.tsx

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,27 @@
1-
import {
2-
$,
3-
component$,
4-
useContext,
5-
useSignal,
6-
useTask$,
7-
} from '@builder.io/qwik';
1+
import { $, component$, useContext, useSignal } from '@builder.io/qwik';
82
import { useLocation } from '@builder.io/qwik-city';
9-
import { isBrowser } from '@builder.io/qwik/build';
103
import { version } from '../../../../../package.json';
11-
import { APP_STATE } from '../../constants';
124
import { CloseIcon } from '../icons/CloseIcon';
135
import { GitHubIcon } from '../icons/GitHubIcon';
146
import { MenuIcon } from '../icons/MenuIcon';
157
import { MoonIcon } from '../icons/MoonIcon';
168
import { SunIcon } from '../icons/SunIcon';
179
import { Menu } from '../menu/menu';
1810
import { SelectTheme } from '../selectTheme/selectTheme';
11+
import { APP_STATE_CONTEXT_ID } from '../../_state/app-state-context-id';
12+
import { useCSSTheme } from '../../_state/use-css-theme';
1913

2014
export default component$(() => {
2115
const location = useLocation();
22-
const appState = useContext(APP_STATE);
16+
const appState = useContext(APP_STATE_CONTEXT_ID);
2317
const menuOpenSignal = useSignal(false);
2418

2519
const toggleMenu$ = $(() => {
2620
menuOpenSignal.value = !menuOpenSignal.value;
2721
});
2822

2923
const toggleDarkMode = $(() => {
30-
appState.darkMode = !appState.darkMode;
31-
});
32-
33-
const setThemeClass = $(() => {
34-
if (isBrowser) {
35-
const theme = appState.darkMode ? 'dark' : 'light';
36-
document.documentElement.setAttribute('class', theme);
37-
document.documentElement.setAttribute('data-theme', theme);
38-
localStorage.setItem('theme', theme);
39-
}
40-
});
41-
42-
useTask$(({ track }) => {
43-
track(() => appState.darkMode);
44-
setThemeClass();
24+
appState.mode = appState.mode === 'light' ? 'dark' : 'light';
4525
});
4626

4727
const isDocsRoute = location.url.pathname.indexOf('/docs/') !== -1;
@@ -80,7 +60,7 @@ export default component$(() => {
8060
aria-label="Toggle dark mode"
8161
onClick$={toggleDarkMode}
8262
>
83-
{appState.darkMode ? <MoonIcon /> : <SunIcon />}
63+
{appState.mode === 'dark' ? <MoonIcon /> : <SunIcon />}
8464
</button>
8565
<div class="px-2 pt-2">
8666
<a

apps/website/src/components/menu/menu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { $, component$, PropFunction, useContext } from '@builder.io/qwik';
22
import { Link } from '@builder.io/qwik-city';
33

4-
import { APP_STATE } from '../../constants';
4+
import { OLD_APP_STATE_CONTEXT_ID } from '../../constants';
55
import { CloseIcon } from '../icons/CloseIcon';
66

77
type Props = {
88
onClose$?: PropFunction<() => void>;
99
};
1010

1111
export const Menu = component$<Props>(({ onClose$ }) => {
12-
const appState = useContext(APP_STATE);
12+
const appState = useContext(OLD_APP_STATE_CONTEXT_ID);
1313

1414
const menu = [
1515
{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { THEME_STORAGE_KEY } from '../../_state/use-css-theme';
2+
3+
export const CSSThemeScript = () => {
4+
const themeScript = `
5+
document.documentElement
6+
.setAttribute('class',
7+
localStorage.getItem('${THEME_STORAGE_KEY}') ??
8+
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
9+
)`;
10+
return <script dangerouslySetInnerHTML={themeScript} />;
11+
};

apps/website/src/components/router-head/router-head.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { component$ } from '@builder.io/qwik';
22
import { useDocumentHead, useLocation } from '@builder.io/qwik-city';
3+
import { CSSThemeScript } from './css-theme-script';
34

45
/**
56
* The RouterHead component is placed inside of the document `<head>` element.
@@ -39,19 +40,7 @@ export const RouterHead = component$(() => {
3940
<style {...s.props} dangerouslySetInnerHTML={s.style} />
4041
))}
4142

42-
{
43-
<script
44-
dangerouslySetInnerHTML={`
45-
if (!localStorage.getItem('theme')) {
46-
localStorage.setItem('theme', 'dark');
47-
}
48-
const darkMode = localStorage.getItem('theme') === 'dark';
49-
const theme = darkMode ? 'dark' : 'light';
50-
document.documentElement.setAttribute('class', theme);
51-
document.documentElement.setAttribute('data-theme', theme);
52-
`}
53-
/>
54-
}
43+
<CSSThemeScript />
5544
</>
5645
);
5746
});

apps/website/src/components/selectTheme/selectTheme.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { $, component$, useContext, useId, useSignal } from '@builder.io/qwik';
22
import { useLocation } from '@builder.io/qwik-city';
3-
import { APP_STATE } from '../../constants';
3+
import { OLD_APP_STATE_CONTEXT_ID } from '../../constants';
44
import { ThemeIcon } from '../icons/ThemeIcon';
55

66
export type Theme = 'HEADLESS' | 'DAISY' | 'MATERIAL' | 'NOT_DEFINED';
77

88
export const SelectTheme = component$(() => {
99
const location = useLocation();
10-
const appState = useContext(APP_STATE);
10+
const appState = useContext(OLD_APP_STATE_CONTEXT_ID);
1111
const openThemeSignal = useSignal<boolean>(false);
1212

1313
const themes: Theme[] = ['HEADLESS', 'DAISY', 'MATERIAL'];

apps/website/src/constants.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createContextId } from '@builder.io/qwik';
2-
import { AppState } from './types';
2+
import { OldAppState } from './types';
33

4-
export const APP_STATE = createContextId<AppState>('app_state');
4+
export const OLD_APP_STATE_CONTEXT_ID =
5+
createContextId<OldAppState>('app_state');

apps/website/src/global.css

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,27 @@
77
--qwik-light-blue: #18b6f6;
88
--qwik-light-purple: #ac7ff4;
99
--qwik-dark-purple: #713fc2;
10+
--dark-color-bg: rgb(30 41 59);
11+
--dark-color-text: rgb(203 213 225);
12+
--light-color-bg: rgb(203 213 225);
13+
--light-color-text: #333;
14+
}
15+
16+
.light {
17+
--color-bg: rgb(203 213 225);
18+
--color-text: #333;
19+
}
20+
21+
.dark {
22+
--color-bg: rgb(30 41 59);
23+
--color-text: rgb(203 213 225);
1024
}
1125

1226
html {
1327
height: 100%;
1428
min-height: 100%;
1529
scroll-behavior: smooth;
30+
1631
background-color: var(--color-bg) !important;
1732
color: var(--color-text) !important;
1833
}
@@ -35,7 +50,3 @@ body {
3550
grid-template-columns: 25% auto;
3651
grid-template-areas: 'sidebar content';
3752
}
38-
39-
header {
40-
background-color: var(--color-bg) !important;
41-
}

0 commit comments

Comments
 (0)