Skip to content

Commit 9af46b8

Browse files
authored
Set min and max on nested Progress bars (#986)
* Pass min and max props to child progress bars with context * Add tests
1 parent 9bb7785 commit 9af46b8

File tree

2 files changed

+64
-23
lines changed

2 files changed

+64
-23
lines changed

src/components/progress/Progress.js

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import React, {cloneElement} from 'react';
1+
import React, {cloneElement, useContext} from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44
import {map} from 'react-bootstrap/ElementChildren';
55
import {omit} from 'ramda';
66

77
import {bootstrapColors} from '../../private/BootstrapColors';
88

9+
export const ProgressContext = React.createContext({});
10+
911
/*
1012
* Bulk of this file is vendored from react-bootstrap/src/ProgressBar, but we
1113
* add the ability to style the bar which is needed for setting colors more
@@ -59,15 +61,17 @@ function renderProgressBar(
5961
);
6062
}
6163

62-
const ProgressBar = React.forwardRef(({isChild, ...props}, ref) => {
64+
const ProgressBar = React.forwardRef(({isChild, min, max, ...props}, ref) => {
6365
if (isChild) {
64-
return renderProgressBar(props, ref);
66+
const context = useContext(ProgressContext);
67+
return renderProgressBar(
68+
{...props, max: max || context.max, min: min || context.min},
69+
ref
70+
);
6571
}
6672

6773
const {
68-
min,
6974
now,
70-
max,
7175
label,
7276
visuallyHidden,
7377
striped,
@@ -79,35 +83,38 @@ const ProgressBar = React.forwardRef(({isChild, ...props}, ref) => {
7983
...wrapperProps
8084
} = props;
8185

86+
min = min === undefined ? 0 : min;
87+
max = max === undefined ? 100 : max;
88+
8289
return (
8390
<div
8491
ref={ref}
8592
{...wrapperProps}
8693
className={classNames(className, 'progress')}
8794
>
88-
{children
89-
? map(children, child => cloneElement(child, {isChild: true}))
90-
: renderProgressBar(
91-
{
92-
min,
93-
now,
94-
max,
95-
label,
96-
visuallyHidden,
97-
striped,
98-
animated,
99-
variant,
100-
barStyle
101-
},
102-
ref
103-
)}
95+
<ProgressContext.Provider value={{min, max}}>
96+
{children
97+
? map(children, child => cloneElement(child, {isChild: true}))
98+
: renderProgressBar(
99+
{
100+
min,
101+
now,
102+
max,
103+
label,
104+
visuallyHidden,
105+
striped,
106+
animated,
107+
variant,
108+
barStyle
109+
},
110+
ref
111+
)}
112+
</ProgressContext.Provider>
104113
</div>
105114
);
106115
});
107116

108117
ProgressBar.defaultProps = {
109-
min: 0,
110-
max: 100,
111118
animated: false,
112119
isChild: false,
113120
visuallyHidden: false,

src/components/progress/__tests__/Progress.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,40 @@ describe('Progress', () => {
8585
});
8686
});
8787

88+
test('nested bars parent width', () => {
89+
const {
90+
container: {firstChild: progress}
91+
} = render(
92+
<Progress min={10} max={50}>
93+
<Progress value={30} bar />
94+
<Progress value={20} bar />
95+
</Progress>
96+
);
97+
98+
// bar has width 50 - 10 = 40
99+
// subbars have width 30 - 10 = 20, and 20 - 10 = 10 respectively
100+
// so expected widths are 50% and 25%
101+
102+
expect(progress.children[0]).toHaveStyle({width: '50%'});
103+
expect(progress.children[1]).toHaveStyle({width: '25%'});
104+
105+
const {
106+
container: {firstChild: progress2}
107+
} = render(
108+
<Progress min={10} max={50}>
109+
<Progress value={30} bar />
110+
<Progress value={20} min={15} max={25} bar />
111+
</Progress>
112+
);
113+
114+
// this bar we check that props on the child override those of the parent
115+
// second subbar has width 25 - 15 = 10 and value 20 - 15
116+
// so expected width is 50%
117+
118+
expect(progress2.children[0]).toHaveStyle({width: '50%'});
119+
expect(progress2.children[1]).toHaveStyle({width: '50%'});
120+
});
121+
88122
test('applies additional CSS classes when props are set', () => {
89123
// striped progress
90124
const {

0 commit comments

Comments
 (0)