Skip to content

Commit

Permalink
fix: fixed rtl direction in ProgressBar
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Sep 21, 2023
1 parent 0291845 commit 34e148b
Showing 4 changed files with 57 additions and 17 deletions.
23 changes: 16 additions & 7 deletions src/ProgressBar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import ProgressBarBase from 'react-bootstrap/ProgressBar';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@@ -31,18 +31,27 @@ function ProgressBarAnnotated({
thresholdHint,
...props
}) {
const [direction, setDirection] = useState('ltr');
const progressInfoRef = React.useRef();
const thresholdInfoRef = React.useRef();
const progressAnnotatedRef = React.useRef();
const thresholdPercent = (threshold || 0) - (now || 0);
const isProgressHintAfter = now < HINT_SWAP_PERCENT;
const isThresholdHintAfter = threshold < HINT_SWAP_PERCENT;
const progressColor = VARIANTS.includes(variant) ? variant : PROGRESS_DEFAULT_VARIANT;
const thresholdColor = VARIANTS.includes(thresholdVariant) ? thresholdVariant : THRESHOLD_DEFAULT_VARIANT;

useEffect(() => {
if (progressAnnotatedRef.current) {
const pageDirection = window.getComputedStyle(progressAnnotatedRef.current).getPropertyValue('direction');
setDirection(pageDirection);
}
}, []);

const positionAnnotations = useCallback(() => {
placeInfoAtZero(progressInfoRef, isProgressHintAfter, ANNOTATION_CLASS);
placeInfoAtZero(thresholdInfoRef, isThresholdHintAfter, ANNOTATION_CLASS);
}, [isProgressHintAfter, isThresholdHintAfter]);
placeInfoAtZero(progressInfoRef, direction, isProgressHintAfter, ANNOTATION_CLASS);
placeInfoAtZero(thresholdInfoRef, direction, isThresholdHintAfter, ANNOTATION_CLASS);
}, [direction, isProgressHintAfter, isThresholdHintAfter]);

useEffect(() => {
positionAnnotations();
@@ -61,11 +70,11 @@ function ProgressBarAnnotated({
);

return (
<div className="pgn__progress-annotated">
<div ref={progressAnnotatedRef} className="pgn__progress-annotated">
{!!label && (
<div
className="pgn__progress-info"
style={{ left: `${now}%` }}
style={direction === 'rtl' ? { right: `${now}%` } : { left: `${now}%` }}
ref={progressInfoRef}
>
{!isProgressHintAfter && getHint(progressHint)}
@@ -96,7 +105,7 @@ function ProgressBarAnnotated({
{(!!threshold && !!thresholdLabel) && (
<div
className="pgn__progress-info"
style={{ left: `${threshold}%` }}
style={direction === 'rtl' ? { right: `${threshold}%` } : { left: `${threshold}%` }}
ref={thresholdInfoRef}
>
{!isThresholdHintAfter && getHint(thresholdHint)}
16 changes: 14 additions & 2 deletions src/ProgressBar/index.scss
Original file line number Diff line number Diff line change
@@ -11,8 +11,10 @@

.pgn__progress-annotated {
width: 100%;
height: 200px;
position: relative;
overflow: visible;
margin-top: 80px;

.progress {
overflow: visible;
@@ -58,6 +60,11 @@
height: $progress-threshold-circle;
border-radius: calc($progress-threshold-circle / 2);
z-index: 1;

[dir="rtl"] & {
left: -(calc($progress-threshold-circle / 2));
right: auto;
}
}
}
}
@@ -77,8 +84,13 @@
}

.pgn__progress-info {
display: inline-block;
position: relative;
position: absolute;
display: flex;
align-items: baseline;

&:first-child {
top: -49px;
}
}

.pgn__progress-hint {
19 changes: 16 additions & 3 deletions src/ProgressBar/tests/ProgressBar.test.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import React from 'react';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import renderer from 'react-test-renderer';

import ProgressBar, { ANNOTATION_CLASS } from '..';

window.getComputedStyle = jest.fn().mockImplementation(() => ({
getPropertyValue: jest.fn().mockReturnValue('ltr'),
}));

const ref = {
current: {
style: {
@@ -47,9 +52,8 @@ describe('<ProgressBar.Annotated />', () => {
expect(tree).toMatchSnapshot();
});
it('renders info blocks with calculated margins', () => {
const useReferenceSpy = jest.spyOn(React, 'useRef').mockReturnValue(ref);
mount(<ProgressBarElement />);
expect(useReferenceSpy).toHaveBeenCalledTimes(2);
jest.spyOn(React, 'useRef').mockReturnValue(ref);
render(<ProgressBarElement />);
expect(ref.current.style.marginLeft).not.toBeFalsy();
});
it('renders correct variant for progress bar and annotation', () => {
@@ -85,5 +89,14 @@ describe('<ProgressBar.Annotated />', () => {
expect(wrapper.find('.pgn__progress-info').get(0).props.children[2]).toEqual(false);
expect(wrapper.find('.pgn__progress-info').get(1).props.children[2]).toEqual(false);
});
it('should apply styles based on direction for threshold', () => {
window.getComputedStyle = jest.fn().mockReturnValue({ getPropertyValue: () => 'rtl' });
const { container } = render(<ProgressBarElement />);
const progressInfo = container.querySelector('.pgn__progress-info');
const computedStyles = window.getComputedStyle(progressInfo);

expect(computedStyles.getPropertyValue('directory')).toBe('rtl');
window.getComputedStyle.mockRestore();
});
});
});
16 changes: 11 additions & 5 deletions src/ProgressBar/utils.js
Original file line number Diff line number Diff line change
@@ -3,24 +3,30 @@
* that the annotation pointer indicates on zero of the ProgressBar.
*
* @param {object} ref reference to the info block
* @param {string} direction directing elements to pages
* @param {boolean} annotationOnly ignores width of the hint
* @param {string} annotationClass is used to identify the annotation element
*/
// eslint-disable-next-line import/prefer-default-export
export const placeInfoAtZero = (ref, annotationOnly = true, annotationClass = 'pgn__annotation') => {
export const placeInfoAtZero = (
ref,
direction,
annotationOnly = true,
annotationClass = 'pgn__annotation',
) => {
if (!ref.current || !ref.current.style) { return false; }
const { children } = ref.current;
let marginLeft = 0.0;
let horizontalMargin = 0.0;

for (let i = 0; i < children.length || 0; i++) {
const elementParams = children[i].getBoundingClientRect();
if (children[i].className.includes(annotationClass)) {
marginLeft += elementParams.width / 2;
horizontalMargin += elementParams.width / 2;
} else {
marginLeft += annotationOnly ? 0.0 : elementParams.width;
horizontalMargin += annotationOnly ? 0.0 : elementParams.width;
}
}
// eslint-disable-next-line no-param-reassign
ref.current.style.marginLeft = `${-marginLeft}px`;
ref.current.style[direction === 'rtl' ? 'marginRight' : 'marginLeft'] = `${-horizontalMargin}px`;
return true;
};

0 comments on commit 34e148b

Please sign in to comment.