feat: swap bootstrap progress bar with step complete one (#52011)

Co-authored-by: Ahmad Abdolsaheb <ahmad.abdolsaheb@gmail.com>
This commit is contained in:
Muhammed Mustafa
2023-10-31 15:08:29 +02:00
committed by GitHub
parent 4816aa972c
commit ff86724b0e
11 changed files with 51 additions and 56 deletions

View File

@@ -0,0 +1 @@
export { default } from './progress';

View File

@@ -0,0 +1,14 @@
import React from 'react';
export function ProgressBar({ now }: { now: number }) {
return (
<>
<div className='progress-bar-background'></div>
<div
className='progress-bar-percent'
data-testid='fcc-progress-bar-percent'
style={{ width: `${now}%` }}
></div>
</>
);
}

View File

@@ -1,8 +1,9 @@
import React, { useState, useEffect, useRef, useMemo } from 'react';
import BezierEasing from 'bezier-easing';
import { ProgressBar } from './progress-bar';
interface ProgressBarInnerProps {
interface ProgressInnerProps {
completedPercent: number;
title: string;
meta: string;
@@ -32,18 +33,17 @@ function useIsInViewport(ref: React.RefObject<HTMLDivElement>) {
return isIntersecting;
}
function ProgressBarInner({
function ProgressInner({
completedPercent,
title,
meta
}: ProgressBarInnerProps): JSX.Element {
}: ProgressInnerProps): JSX.Element {
const [shownPercent, setShownPercent] = useState(0);
const [progressBarInnerWidth, setProgressBarInnerWidth] = useState(0);
const [lastShopwnPercent, setLastShownPercent] = useState(0);
const progressBarInnerWrap = useRef<HTMLDivElement>(null);
const isProgressBarInViewport = useIsInViewport(progressBarInnerWrap);
const progressInnerWrap = useRef<HTMLDivElement>(null);
const isProgressInViewport = useIsInViewport(progressInnerWrap);
const animateProgressBarInner = (completedPercent: number) => {
const animateProgressInner = (completedPercent: number) => {
if (completedPercent > 100) completedPercent = 100;
if (completedPercent < 0) completedPercent = 0;
@@ -66,17 +66,12 @@ function ProgressBarInner({
}, intervalLength);
};
useEffect(() => {
if (lastShopwnPercent !== completedPercent && isProgressBarInViewport) {
if (lastShopwnPercent !== completedPercent && isProgressInViewport) {
setLastShownPercent(completedPercent);
animateProgressBarInner(completedPercent);
animateProgressInner(completedPercent);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isProgressBarInViewport]);
useEffect(() => {
if (progressBarInnerWrap.current)
setProgressBarInnerWidth(progressBarInnerWrap.current.offsetWidth);
}, [progressBarInnerWrap]);
}, [isProgressInViewport]);
return (
<>
@@ -84,25 +79,15 @@ function ProgressBarInner({
<div
className='progress-bar-wrap'
aria-hidden='true'
ref={progressBarInnerWrap}
ref={progressInnerWrap}
>
<div className='progress-bar-background'></div>
<div
className='progress-bar-percent'
data-testid='fcc-progress-bar-percent'
style={{ width: `${shownPercent}%` }}
>
<div
className='progress-bar-foreground'
style={{ width: progressBarInnerWidth }}
></div>
</div>
<ProgressBar now={shownPercent} />
</div>
<div className='completion-block-meta'>{meta}</div>
</>
);
}
ProgressBarInner.displayName = 'ProgressBarInner';
ProgressInner.displayName = 'ProgressInner';
export default ProgressBarInner;
export default ProgressInner;

View File

@@ -10,7 +10,7 @@ import {
completedPercentageSelector
} from '../../templates/Challenges/redux/selectors';
import { liveCerts } from '../../../config/cert-and-project-map';
import ProgressBarInner from './progress-bar-inner';
import ProgressInner from './progress-inner';
const mapStateToProps = createSelector(
currentBlockIdsSelector,
@@ -42,10 +42,10 @@ const mapStateToProps = createSelector(
type StateProps = ReturnType<typeof mapStateToProps>;
interface ProgressBarProps extends StateProps {
interface ProgressProps extends StateProps {
t: TFunction;
}
function ProgressBar({
function Progress({
currentBlockIds,
block,
id,
@@ -53,7 +53,7 @@ function ProgressBar({
completedChallengesInBlock,
completedPercent,
t
}: ProgressBarProps): JSX.Element {
}: ProgressProps): JSX.Element {
const blockTitle = t(`intro:${superBlock}.blocks.${block}.title`);
// Always false for legacy full stack, since it has no projects.
const isCertificationProject = liveCerts.some(
@@ -75,7 +75,7 @@ function ProgressBar({
className='progress-bar-container'
data-playwright-test-label='progress-bar-container'
>
<ProgressBarInner
<ProgressInner
title={blockTitle}
meta={meta}
completedPercent={completedPercent}
@@ -84,6 +84,6 @@ function ProgressBar({
);
}
ProgressBar.displayName = 'ProgressBar';
Progress.displayName = 'Progress';
export default connect(mapStateToProps)(withTranslation()(ProgressBar));
export default connect(mapStateToProps)(withTranslation()(Progress));

View File

@@ -1 +0,0 @@
export { default } from './progress-bar';

View File

@@ -15,7 +15,7 @@ import { apiLocation } from '../../../../config/env.json';
import { ChallengeMeta } from '../../../redux/prop-types';
import { Share } from '../../../components/share';
import { ShareProps } from '../../../components/share/types';
import ProgressBar from '../../../components/ProgressBar';
import Progress from '../../../components/Progress';
import Quote from '../../../assets/icons/quote';
import {
challengeMetaSelector,
@@ -370,7 +370,7 @@ const LowerJaw = ({
<>
<hr></hr>
<div className='progress-bar-container'>
<ProgressBar />
<Progress />
</div>
</>
)}

View File

@@ -97,22 +97,13 @@
}
.progress-bar-percent {
width: 0;
height: 10px;
overflow: hidden;
position: relative;
background-color: var(--primary-color);
transition: width 0ms linear;
}
.progress-bar-foreground {
color: var(--primary-background);
width: 400px;
height: 10px;
display: flex;
align-items: center;
justify-content: center;
}
@media screen and (max-width: 991px) {
.challenge-success-modal .btn-lg {
font-size: 1rem;

View File

@@ -18,7 +18,7 @@ import CompletionModal from './completion-modal';
jest.mock('../../../analytics');
jest.mock('../../../utils/fire-confetti');
jest.mock('../../../components/ProgressBar');
jest.mock('../../../components/Progress');
jest.mock('../redux/selectors');
jest.mock('../utils/build');
const mockFireConfetti = fireConfetti as jest.Mock;

View File

@@ -24,7 +24,7 @@ import {
challengeMetaSelector,
isSubmittingSelector
} from '../redux/selectors';
import ProgressBar from '../../../components/ProgressBar';
import Progress from '../../../components/Progress';
import GreenPass from '../../../assets/icons/green-pass';
import './completion-modal.css';
@@ -189,7 +189,7 @@ class CompletionModal extends Component<
/>
</div>
<div className='completion-block-details'>
<ProgressBar />
<Progress />
</div>
</Modal.Body>
<Modal.Footer>

View File

@@ -1,11 +1,11 @@
import React, { Component } from 'react';
import type { DefaultTFuncReturn, TFunction } from 'i18next';
import { withTranslation } from 'react-i18next';
import { ProgressBar } from '@freecodecamp/react-bootstrap';
import { connect } from 'react-redux';
import ScrollableAnchor from 'react-scrollable-anchor';
import { bindActionCreators, Dispatch } from 'redux';
import { createSelector } from 'reselect';
import { SuperBlocks } from '../../../../../shared/config/superblocks';
import envData from '../../../../config/env.json';
import { isAuditedSuperBlock } from '../../../../../shared/utils/is-audited';
@@ -13,6 +13,7 @@ import Caret from '../../../assets/icons/caret';
import DropDown from '../../../assets/icons/dropdown';
import GreenNotCompleted from '../../../assets/icons/green-not-completed';
import GreenPass from '../../../assets/icons/green-pass';
import { ProgressBar } from '../../../components/Progress/progress-bar';
import { Link, Spacer } from '../../../components/helpers';
import { completedChallengesSelector } from '../../../redux/selectors';
import { ChallengeNode, CompletedChallenge } from '../../../redux/prop-types';
@@ -153,7 +154,9 @@ class Block extends Component<BlockProps> {
const progressBarRender = (
<div aria-hidden='true' className='progress-wrapper'>
<ProgressBar now={percentageCompleted} />
<div>
<ProgressBar now={percentageCompleted} />
</div>
<span>{`${percentageCompleted}%`}</span>
</div>
);

View File

@@ -443,8 +443,10 @@ ToDo: find out why, and remove the need for it */
margin-bottom: 14px;
}
.block-grid .progress-wrapper span {
color: var(--quaternary-color);
.block-grid .progress-wrapper > div {
position: relative;
width: 80%;
padding-inline-end: 0.25em;
}
.block-grid .progress {