Skip to content

Commit 61e8ea3

Browse files
committed
Exclude ThemeToggle btn from SSR
1 parent 07420f1 commit 61e8ea3

4 files changed

Lines changed: 31 additions & 22 deletions

File tree

apps/site/components/withNavBar.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import LanguageDropdown from '@node-core/ui-components/Common/LanguageDropDown';
44
import Skeleton from '@node-core/ui-components/Common/Skeleton';
5-
import ThemeToggle from '@node-core/ui-components/Common/ThemeToggle';
65
import NavBar from '@node-core/ui-components/Containers/NavBar';
76
// TODO(@AvivKeller): I don't like that we are importing styles from another module
87
import styles from '@node-core/ui-components/Containers/NavBar/index.module.css';
@@ -11,7 +10,6 @@ import type { SimpleLocaleConfig } from '@node-core/ui-components/types';
1110
import dynamic from 'next/dynamic';
1211
import { useLocale, useTranslations } from 'next-intl';
1312
import { useTheme } from 'next-themes';
14-
import { useState, useEffect } from 'react';
1513
import type { FC } from 'react';
1614

1715
import Link from '#site/components/Link';
@@ -28,6 +26,16 @@ const SearchButton = dynamic(() => import('#site/components/Common/Search'), {
2826
),
2927
});
3028

29+
const ThemeToggle = dynamic(
30+
() => import('@node-core/ui-components/Common/ThemeToggle'),
31+
{
32+
ssr: false,
33+
loading: () => (
34+
<Skeleton className={styles.themeToggleSkeleton} loading={true} />
35+
),
36+
}
37+
);
38+
3139
const WithNavBar: FC = () => {
3240
const { navigationItems } = useSiteNavigation();
3341
const { resolvedTheme, setTheme } = useTheme();
@@ -36,16 +44,12 @@ const WithNavBar: FC = () => {
3644
const t = useTranslations();
3745

3846
const locale = useLocale();
39-
const [mounted, setMounted] = useState(false);
40-
41-
useEffect(() => setMounted(true), []);
4247

4348
const toggleCurrentTheme = () =>
4449
setTheme(resolvedTheme === 'dark' ? 'light' : 'dark');
4550

46-
const themeToggleAriaLabel = !mounted
47-
? t('components.common.themeToggle.loading')
48-
: resolvedTheme === 'dark'
51+
const themeToggleAriaLabel =
52+
resolvedTheme === 'dark'
4953
? t('components.common.themeToggle.light')
5054
: t('components.common.themeToggle.dark');
5155

apps/site/tests/e2e/general-behavior.spec.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ const locators = {
1313
navLinksLocator: `[aria-label="${englishLocale.components.containers.navBar.controls.toggle}"] + div`,
1414
// Global UI controls
1515
languageDropdownName: englishLocale.components.common.languageDropdown.label,
16-
// Initially, the themeToggle's name will be the light mode i18n.
17-
themeToggleName: englishLocale.components.common.themeToggle.loading,
1816
themeToggleAriaLabels: {
1917
light: englishLocale.components.common.themeToggle.light,
2018
dark: englishLocale.components.common.themeToggle.dark,
@@ -30,6 +28,11 @@ const getTheme = (page: Page) =>
3028
() => document.documentElement.dataset.theme as 'light' | 'dark'
3129
);
3230

31+
const getCurrentAriaLabel = (theme: string) =>
32+
theme === 'dark'
33+
? locators.themeToggleAriaLabels.light
34+
: locators.themeToggleAriaLabels.dark;
35+
3336
const openLanguageMenu = async (page: Page) => {
3437
const button = page.getByRole('button', {
3538
name: locators.languageDropdownName,
@@ -71,30 +74,27 @@ test.describe('Node.js Website', () => {
7174
test.describe('Theme', () => {
7275
test('should toggle between light/dark themes', async ({ page }) => {
7376
const themeToggle = page.getByRole('button', {
74-
name: locators.themeToggleName,
77+
name: /Switch to (Light|Dark) Mode/i,
7578
});
76-
await expect(themeToggle).toBeVisible();
7779

7880
const initialTheme = await getTheme(page);
79-
const initialAriaLabel = await themeToggle.getAttribute('aria-label');
80-
expect(initialAriaLabel).toBe(
81-
locators.themeToggleAriaLabels[initialTheme]
82-
);
81+
const initialAriaLabel = getCurrentAriaLabel(initialTheme);
82+
let currentAriaLabel = await themeToggle.getAttribute('aria-label');
83+
expect(currentAriaLabel).toBe(initialAriaLabel);
8384

8485
await themeToggle.click();
8586

8687
const newTheme = await getTheme(page);
87-
const newAriaLabel = await themeToggle.getAttribute('aria-label');
88+
const newAriaLabel = getCurrentAriaLabel(newTheme);
89+
currentAriaLabel = await themeToggle.getAttribute('aria-label');
8890

8991
expect(newTheme).not.toBe(initialTheme);
90-
expect(['light', 'dark']).toContain(newTheme);
91-
92-
expect(newAriaLabel).toBe(locators.themeToggleAriaLabels[newTheme]);
92+
expect(currentAriaLabel).toBe(newAriaLabel);
9393
});
9494

9595
test('should persist theme across page navigation', async ({ page }) => {
9696
const themeToggle = page.getByRole('button', {
97-
name: locators.themeToggleName,
97+
name: /Switch to (Light|Dark) Mode/i,
9898
});
9999
await themeToggle.click();
100100
const selectedTheme = await getTheme(page);

packages/i18n/src/locales/en.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@
229229
"label": "Choose Language"
230230
},
231231
"themeToggle": {
232-
"loading": "Loading theme label...",
233232
"light": "Switch to Light Mode",
234233
"dark": "Switch to Dark Mode"
235234
}

packages/ui-components/src/Containers/NavBar/index.module.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ span.searchButtonSkeleton {
108108
}
109109
}
110110

111+
span.themeToggleSkeleton {
112+
@apply size-9
113+
rounded-md
114+
py-4;
115+
}
116+
111117
.ghIconWrapper {
112118
@apply size-9
113119
rounded-md

0 commit comments

Comments
 (0)