Skip to content

Commit

Permalink
feat: add toggle theme button (#18)
Browse files Browse the repository at this point in the history
* feat: read theme cookies

* styled the toggle theme buutton

* fix: update test snapshots
  • Loading branch information
hinakhadim committed Aug 15, 2024
1 parent f25b9b3 commit 48428ac
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 22 deletions.
56 changes: 35 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"babel-polyfill": "6.26.0",
"jest-environment-jsdom": "^29.7.0",
"react-responsive": "8.2.0",
"react-transition-group": "4.4.5"
"react-transition-group": "4.4.5",
"universal-cookie": "^7.2.0"
},
"peerDependencies": {
"@edx/frontend-platform": "^7.0.0 || ^8.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/DesktopHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import ThemeToggleButton from './ThemeToggleButton';

// Local Components
import { Menu, MenuTrigger, MenuContent } from './Menu';
Expand Down Expand Up @@ -156,6 +157,7 @@ class DesktopHeader extends React.Component {
aria-label={intl.formatMessage(messages['header.label.secondary.nav'])}
className="nav secondary-menu-container align-items-center ml-auto"
>
<ThemeToggleButton />
{loggedIn
? (
<>
Expand Down
2 changes: 2 additions & 0 deletions src/MobileHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getConfig } from '@edx/frontend-platform';
// Local Components
import { Menu, MenuTrigger, MenuContent } from './Menu';
import { LinkedLogo, Logo } from './Logo';
import ThemeToggleButton from './ThemeToggleButton';

// i18n
import messages from './Header.messages';
Expand Down Expand Up @@ -154,6 +155,7 @@ class MobileHeader extends React.Component {
<div className={`logo-holder ${logoClasses}`}>
{ logoDestination === null ? <Logo className="logo" src={logo} alt={logoAltText} /> : <LinkedLogo className="logo" {...logoProps} itemType="http://schema.org/Organization" />}
</div>
<ThemeToggleButton />
{userMenu.length > 0 || loggedOutItems.length > 0 ? (
<div className="mobile-menu">
<Menu tag="nav" aria-label={intl.formatMessage(messages['header.label.secondary.nav'])} className="position-static">
Expand Down
47 changes: 47 additions & 0 deletions src/ThemeToggleButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';

const ThemeToggleButton = () => {
const getNextWeek = () => {
const today = new Date();
return new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
};

const onToggleTheme = () => {
const cookies = new Cookies();
const serverURL = new URL(getConfig().LMS_BASE_URL);
const themeCookieName = getConfig().THEME_COOKIE_NAME;

const options = { domain: serverURL.hostname, path: '/', expires: getNextWeek() };
let themeName = '';

if (cookies.get(themeCookieName) === 'dark') {
document.body.classList.remove('indigo-dark-theme');
themeName = 'light';
} else {
document.body.classList.add('indigo-dark-theme');
themeName = 'dark';
}
cookies.set(themeCookieName, themeName, options);
};

return (
<div className="theme-toggle-button">
<span id="darkmode" role="button" tabIndex="0" onClick={onToggleTheme} onKeyDown={onToggleTheme}>
<div className="darkmode_icon">
<span className="ray" />
<span className="ray" />
<span className="ray" />
<span className="ray" />
<span className="ray" />
<span className="ray" />
<span className="ray" />
<span className="ray" />
</div>
</span>
</div>
);
};

export default ThemeToggleButton;
160 changes: 160 additions & 0 deletions src/__snapshots__/Header.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,46 @@ exports[`<Header /> renders correctly for anonymous desktop 1`] = `
aria-label="Secondary"
className="nav secondary-menu-container align-items-center ml-auto"
>
<div
className="theme-toggle-button"
>
<span
id="darkmode"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex="0"
>
<div
className="darkmode_icon"
>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
</div>
</span>
</div>
<a
className="btn mr-2 btn-link"
href="http://localhost:18000/login"
Expand Down Expand Up @@ -143,6 +183,46 @@ exports[`<Header /> renders correctly for anonymous mobile 1`] = `
/>
</a>
</div>
<div
className="theme-toggle-button"
>
<span
id="darkmode"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex="0"
>
<div
className="darkmode_icon"
>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
</div>
</span>
</div>
<div
className="mobile-menu"
>
Expand Down Expand Up @@ -225,6 +305,46 @@ exports[`<Header /> renders correctly for authenticated desktop 1`] = `
aria-label="Secondary"
className="nav secondary-menu-container align-items-center ml-auto"
>
<div
className="theme-toggle-button"
>
<span
id="darkmode"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex="0"
>
<div
className="darkmode_icon"
>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
</div>
</span>
</div>
<div
className="menu null"
onKeyDown={[Function]}
Expand Down Expand Up @@ -376,6 +496,46 @@ exports[`<Header /> renders correctly for authenticated mobile 1`] = `
/>
</a>
</div>
<div
className="theme-toggle-button"
>
<span
id="darkmode"
onClick={[Function]}
onKeyDown={[Function]}
role="button"
tabIndex="0"
>
<div
className="darkmode_icon"
>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
<span
className="ray"
/>
</div>
</span>
</div>
<div
className="mobile-menu"
>
Expand Down
2 changes: 2 additions & 0 deletions src/learning-header/LearningHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AppContext } from '@edx/frontend-platform/react';

import AnonymousUserMenu from './AnonymousUserMenu';
import AuthenticatedUserDropdown from './AuthenticatedUserDropdown';
import ThemeToggleButton from '../ThemeToggleButton';
import messages from './messages';

const LinkedLogo = ({
Expand Down Expand Up @@ -60,6 +61,7 @@ const LearningHeader = ({
</a>
</div>
</div>
<ThemeToggleButton />
{showUserDropdown && authenticatedUser && (
<AuthenticatedUserDropdown
username={authenticatedUser.username}
Expand Down

0 comments on commit 48428ac

Please sign in to comment.