Skip to content

Commit 3cd2d6d

Browse files
feat(themeToggle): introduce (#6007)
* feat(themeToggle): introduce * fix * remove `ThemeProvider` from `preview.tsx` * update to use focus and `onKeyDown` * fix: code format * use classname instead of css module * remove toggling * fix: indentation * test: render put on `beforeEach` * separate icon * update * chore: code review changes * fix: style indentation * meta: corrected designs of themetoggle and languagedropdown --------- Co-authored-by: Claudio Wunder <[email protected]>
1 parent ff41772 commit 3cd2d6d

File tree

9 files changed

+125
-5
lines changed

9 files changed

+125
-5
lines changed

components/Common/AvatarGroup/__tests__/index.test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const avatars = names.map(name => ({
2626
alt: name,
2727
}));
2828

29-
describe('AvatarGroup component', () => {
29+
describe('AvatarGroup', () => {
3030
it('renders the AvatarGroup component properly', () => {
3131
const { getByText } = render(<AvatarGroup avatars={avatars} limit={2} />);
3232

components/Common/LanguageDropDown/index.module.css

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
.iconWrapper {
1+
.languageDropdown {
22
@apply h-9
33
w-9
44
rounded-md
5-
bg-neutral-100
65
p-2
76
text-neutral-700
8-
dark:bg-neutral-900
97
dark:text-neutral-300;
8+
9+
&:hover {
10+
@apply bg-neutral-100
11+
dark:bg-neutral-900;
12+
}
1013
}
1114

1215
.dropDownContent {

components/Common/LanguageDropDown/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const LanguageDropdown: FC<LanguageDropDownProps> = ({
3030
return (
3131
<DropdownMenu.Root>
3232
<DropdownMenu.Trigger asChild>
33-
<button className={styles.iconWrapper} aria-label={ariaLabel}>
33+
<button className={styles.languageDropdown} aria-label={ariaLabel}>
3434
<LanguageIcon height="20" />
3535
</button>
3636
</DropdownMenu.Trigger>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { render, screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
4+
import { LocaleProvider } from '@/providers/localeProvider';
5+
6+
import ThemeToggle from '../';
7+
8+
let mockCurrentTheme = 'light';
9+
10+
const toggleTheme = () => {
11+
mockCurrentTheme = mockCurrentTheme === 'light' ? 'dark' : 'light';
12+
};
13+
14+
describe('ThemeToggle', () => {
15+
let toggle;
16+
17+
beforeEach(() => {
18+
mockCurrentTheme = 'light';
19+
20+
render(
21+
<LocaleProvider>
22+
<ThemeToggle onClick={toggleTheme} />
23+
</LocaleProvider>
24+
);
25+
toggle = screen.getByRole('button');
26+
});
27+
28+
it('switches dark theme to light theme', async () => {
29+
mockCurrentTheme = 'dark';
30+
await userEvent.click(toggle);
31+
expect(mockCurrentTheme).toBe('light');
32+
});
33+
34+
it('switches light theme to dark theme', async () => {
35+
await userEvent.click(toggle);
36+
expect(mockCurrentTheme).toBe('dark');
37+
});
38+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.themeToggle {
2+
@apply h-9
3+
w-9
4+
rounded-md
5+
p-2
6+
text-neutral-700
7+
dark:text-neutral-300;
8+
9+
&:hover {
10+
@apply bg-neutral-100
11+
dark:bg-neutral-900;
12+
}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
2+
3+
import ThemeToggle from '@/components/Common/ThemeToggle';
4+
5+
type Story = StoryObj<typeof ThemeToggle>;
6+
type Meta = MetaObj<typeof ThemeToggle>;
7+
8+
export const Default: Story = {};
9+
10+
export default { component: ThemeToggle } as Meta;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { MoonIcon, SunIcon } from '@heroicons/react/24/outline';
2+
import type { FC, MouseEvent } from 'react';
3+
import { useIntl } from 'react-intl';
4+
5+
import styles from './index.module.css';
6+
7+
type ThemeToggleProps = {
8+
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
9+
};
10+
11+
const ThemeToggle: FC<ThemeToggleProps> = ({ onClick = () => {} }) => {
12+
const { formatMessage } = useIntl();
13+
14+
const ariaLabel = formatMessage({
15+
id: 'components.header.buttons.toggleDarkMode',
16+
});
17+
18+
return (
19+
<button
20+
type="button"
21+
onClick={onClick}
22+
className={styles.themeToggle}
23+
aria-label={ariaLabel}
24+
>
25+
<MoonIcon className="block dark:hidden" height="20" />
26+
<SunIcon className="hidden dark:block" height="20" />
27+
</button>
28+
);
29+
};
30+
31+
export default ThemeToggle;

package-lock.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@heroicons/react": "~2.0.18",
4444
"@mdx-js/react": "^2.3.0",
4545
"@nodevu/core": "~0.1.0",
46+
"@radix-ui/react-accessible-icon": "^1.0.3",
4647
"@radix-ui/react-avatar": "^1.0.4",
4748
"@radix-ui/react-dropdown-menu": "^2.0.6",
4849
"@radix-ui/react-select": "^2.0.0",

0 commit comments

Comments
 (0)