Skip to content

Commit a72fe07

Browse files
authored
revert(client): ensure donate button is always visible (freeCodeCamp#66754)
1 parent 72ddb7a commit a72fe07

5 files changed

Lines changed: 55 additions & 196 deletions

File tree

client/src/components/Header/components/nav-links.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { openSignoutModal, toggleTheme } from '../../../redux/actions';
1313
import { Link } from '../../helpers';
1414
import { LocalStorageThemes } from '../../../redux/types';
1515
import { themeSelector } from '../../../redux/selectors';
16+
import SupporterBadge from '../../../assets/icons/supporter-badge';
1617

1718
export interface NavLinksProps {
1819
displayMenu: boolean;
@@ -35,6 +36,42 @@ const mapStateToProps = createSelector(
3536
(theme: LocalStorageThemes) => ({ theme })
3637
);
3738

39+
interface DonateButtonProps {
40+
isUserDonating: boolean | undefined;
41+
handleMenuKeyDown: (event: React.KeyboardEvent<HTMLAnchorElement>) => void;
42+
}
43+
44+
const DonateButton = ({
45+
isUserDonating,
46+
handleMenuKeyDown
47+
}: DonateButtonProps) => {
48+
const { t } = useTranslation();
49+
return (
50+
<li key={isUserDonating ? 'supporter' : 'donate'}>
51+
<Link
52+
className={`nav-link nav-link-flex nav-link-header ${
53+
isUserDonating && 'nav-link-supporter'
54+
}`}
55+
onKeyDown={handleMenuKeyDown}
56+
sameTab={false}
57+
to={isUserDonating ? '/supporters' : '/donate'}
58+
data-test-label={
59+
isUserDonating ? 'dropdown-support-button' : 'dropdown-donate-button'
60+
}
61+
>
62+
{isUserDonating ? (
63+
<>
64+
{t('buttons.supporters')}
65+
<SupporterBadge />
66+
</>
67+
) : (
68+
<>{t('buttons.donate')}</>
69+
)}
70+
</Link>
71+
</li>
72+
);
73+
};
74+
3875
function NavLinks({
3976
menuButtonRef,
4077
openSignoutModal,
@@ -45,7 +82,7 @@ function NavLinks({
4582
toggleTheme
4683
}: NavLinksProps) {
4784
const { t } = useTranslation();
48-
const { username: currentUserName } = user || {};
85+
const { isDonating: isUserDonating, username: currentUserName } = user || {};
4986

5087
// the accessibility tree just needs a little more time to pick up the change.
5188
// This function allows us to set aria-expanded to false and then delay just a bit before setting focus on the button
@@ -106,6 +143,10 @@ function NavLinks({
106143
data-playwright-test-label='header-menu'
107144
className={`nav-list${displayMenu ? ' display-menu' : ''}`}
108145
>
146+
<DonateButton
147+
isUserDonating={isUserDonating}
148+
handleMenuKeyDown={handleMenuKeyDown}
149+
/>
109150
<li key='learn'>
110151
<Link className='nav-link' onKeyDown={handleMenuKeyDown} to='/learn'>
111152
{t('buttons.curriculum')}

client/src/components/Header/components/universal-nav.css

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,8 @@
8484

8585
/**
8686
* Site header language list
87-
* Using ~ so it still works if more items are added between the button and list.
8887
*/
89-
.lang-button-nav[aria-expanded='true'] ~ .nav-list {
88+
.lang-button-nav[aria-expanded='true'] + .nav-list {
9089
-ms-overflow-style: none;
9190
display: block;
9291
max-height: calc(100vh - var(--header-height));
@@ -95,7 +94,7 @@
9594
top: calc(var(--header-height));
9695
}
9796

98-
.lang-button-nav[aria-expanded='true'] ~ .nav-list::-webkit-scrollbar {
97+
.lang-button-nav[aria-expanded='true'] + .nav-list::-webkit-scrollbar {
9998
display: none;
10099
}
101100

@@ -259,33 +258,6 @@ li > button.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) {
259258
border: 1px solid var(--gray-00);
260259
}
261260

262-
.nav-donate-btn .menu-btn-icon {
263-
display: inline-flex;
264-
align-items: center;
265-
}
266-
267-
.nav-donate-btn .menu-btn-text {
268-
display: none;
269-
}
270-
271-
@media (min-width: 601px) {
272-
.nav-donate-btn .menu-btn-icon {
273-
display: none;
274-
}
275-
.nav-donate-btn .menu-btn-text {
276-
display: inline-block;
277-
}
278-
}
279-
280-
.nav-donate-btn .fa-heart {
281-
color: #ff5e5e;
282-
transition: transform 0.2s ease;
283-
}
284-
285-
.nav-donate-btn:hover .fa-heart {
286-
transform: scale(1.2);
287-
}
288-
289261
/**
290262
* User thumbnail
291263
*/
@@ -395,15 +367,15 @@ li > button.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) {
395367
menu is collapsed. */
396368
.universal-nav-right
397369
#toggle-button-nav[aria-expanded='false']
398-
~ .fcc_searchBar {
370+
+ .fcc_searchBar {
399371
display: none;
400372
}
401373

402374
/* In mobile layout, prevent search results from hanging around if the
403375
menu is collapsed. */
404376
.universal-nav-right
405377
#toggle-button-nav[aria-expanded='false']
406-
~ .fcc_searchBar
378+
+ .fcc_searchBar
407379
.ais-Hits {
408380
display: none;
409381
}
@@ -451,17 +423,12 @@ li > button.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) {
451423

452424
/**
453425
* Handle submenu containers collapsed and expanded states
454-
455-
* We use ~ because the Donate button is now between the toggle button
456-
* and the menu/search elements, so they are no longer right next to each other.
457426
*/
458-
#universal-nav button[aria-expanded='false'] ~ .nav-list,
459-
#universal-nav button[aria-expanded='false'] ~ .fcc_searchBar {
427+
#universal-nav button[aria-expanded='false'] + div {
460428
display: none;
461429
}
462430

463-
#universal-nav button[aria-expanded='true'] ~ .nav-list,
464-
#universal-nav button[aria-expanded='true'] ~ .fcc_searchBar {
431+
#universal-nav button[aria-expanded='true'] + div {
465432
display: block;
466433
}
467434

client/src/components/Header/components/universal-nav.test.tsx

Lines changed: 0 additions & 103 deletions
This file was deleted.

client/src/components/Header/components/universal-nav.tsx

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
2-
import { faHeart } from '@fortawesome/free-solid-svg-icons';
31
import Loadable from '@loadable/component';
42
import React from 'react';
53
import { useTranslation } from 'react-i18next';
@@ -8,7 +6,6 @@ import { isLanding } from '../../../utils/path-parsers';
86
import { Link, SkeletonSprite } from '../../helpers';
97
import { SEARCH_EXPOSED_WIDTH } from '../../../../config/misc';
108
import FreeCodeCampLogo from '../../../assets/icons/freecodecamp-logo';
11-
import SupporterBadge from '../../../assets/icons/supporter-badge';
129
import MenuButton from './menu-button';
1310
import NavLinks from './nav-links';
1411
import AuthOrProfile from './auth-or-profile';
@@ -57,8 +54,6 @@ const UniversalNav = ({
5754
) : (
5855
<SearchBar innerRef={searchBarRef} />
5956
);
60-
61-
const isDonating: boolean = user?.isDonating;
6257
return (
6358
<nav
6459
aria-label={t('aria.primary-nav')}
@@ -91,30 +86,6 @@ const UniversalNav = ({
9186
innerRef={menuButtonRef}
9287
showMenu={showMenu}
9388
/>
94-
<Link
95-
className={`nav-donate-btn signup-btn btn-cta ${
96-
isDonating && 'nav-link-supporter'
97-
}`}
98-
sameTab={false}
99-
to={isDonating ? '/supporters' : '/donate'}
100-
data-playwright-test-label={
101-
isDonating ? 'header-support-button' : 'header-donate-button'
102-
}
103-
>
104-
<span className='menu-btn-icon'>
105-
{isDonating ? (
106-
<SupporterBadge />
107-
) : (
108-
<FontAwesomeIcon icon={faHeart} />
109-
)}
110-
<span className='sr-only'>
111-
{isDonating ? t('buttons.supporters') : t('buttons.donate')}
112-
</span>
113-
</span>
114-
<span className='menu-btn-text'>
115-
{isDonating ? t('buttons.supporters') : t('buttons.donate')}
116-
</span>
117-
</Link>
11889
{!isSearchExposedWidth && search}
11990
<NavLinks
12091
displayMenu={displayMenu}

e2e/header.spec.ts

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,26 +46,6 @@ test.describe('Header', () => {
4646
await expect(skipContent).toHaveAttribute('href', '#content-start');
4747
});
4848

49-
test('Should display universal nav Donate button', async ({ page }) => {
50-
const donateButton = page.getByTestId('header-donate-button');
51-
await expect(donateButton).toBeVisible();
52-
await expect(donateButton).toHaveAttribute('href', '/donate');
53-
});
54-
55-
test('Should show "Donate" text on desktop and Heart icon on mobile in the header', async ({
56-
page,
57-
isMobile
58-
}) => {
59-
const donateButton = page.getByTestId('header-donate-button');
60-
const donateText = donateButton.locator('.menu-btn-text');
61-
62-
if (isMobile) {
63-
await expect(donateText).toBeHidden();
64-
} else {
65-
await expect(donateText).toBeVisible();
66-
}
67-
});
68-
6949
test('Renders universal nav by default', async ({ page }) => {
7050
const universalNavigation = page.getByTestId(
7151
headerComponentElements.universalNav
@@ -149,9 +129,7 @@ test.describe('Header', () => {
149129
await expect(menuButton).toBeVisible();
150130
await menuButton.click();
151131

152-
const link = menu.getByRole('link', {
153-
name: translations.buttons.curriculum
154-
});
132+
const link = menu.getByRole('link', { name: translations.buttons.donate });
155133
await link.focus();
156134

157135
await page.keyboard.press('Escape');
@@ -160,7 +138,7 @@ test.describe('Header', () => {
160138
await expect(menuButton).toBeFocused();
161139
});
162140

163-
test('The menu should contain links to: curriculum, catalog, forum, news, radio, contribute, and podcast', async ({
141+
test('The menu should contain links to: donate, curriculum, catalog, forum, news, radio, contribute, and podcast', async ({
164142
page
165143
}) => {
166144
const menuButton = page.getByTestId(headerComponentElements.menuButton);
@@ -170,6 +148,11 @@ test.describe('Header', () => {
170148
await expect(menu).toBeVisible();
171149

172150
const menuLinks = [
151+
{ name: translations.buttons.profile, href: '/developmentuser' },
152+
{
153+
name: translations.buttons.donate,
154+
href: '/donate'
155+
},
173156
{
174157
name: translations.buttons.curriculum,
175158
href: '/learn'

0 commit comments

Comments
 (0)