88import React from 'react' ;
99import PropTypes from 'prop-types' ;
1010import classNames from 'classnames' ;
11+ import { CheckmarkFilled16 , ErrorFilled16 } from '@carbon/icons-react' ;
1112import { useId } from '../../internal/useId' ;
1213import { usePrefix } from '../../internal/usePrefix' ;
1314
@@ -18,14 +19,19 @@ function ProgressBar({
1819 label,
1920 max = 100 ,
2021 size = 'big' ,
22+ status = 'active' ,
2123 type = 'default' ,
2224 value,
2325} ) {
2426 const labelId = useId ( 'progress-bar' ) ;
2527 const helperId = useId ( 'progress-bar-helper' ) ;
2628 const prefix = usePrefix ( ) ;
2729
28- const indeterminate = value === null || value === undefined ;
30+ const isFinished = status === 'finished' ;
31+ const isError = status === 'error' ;
32+
33+ const indeterminate =
34+ ! isFinished && ! isError && ( value === null || value === undefined ) ;
2935
3036 let cappedValue = value ;
3137 if ( cappedValue > max ) {
@@ -34,6 +40,11 @@ function ProgressBar({
3440 if ( cappedValue < 0 ) {
3541 cappedValue = 0 ;
3642 }
43+ if ( isError ) {
44+ cappedValue = 0 ;
45+ } else if ( isFinished ) {
46+ cappedValue = max ;
47+ }
3748
3849 const percentage = cappedValue / max ;
3950
@@ -43,6 +54,8 @@ function ProgressBar({
4354 `${ prefix } --progress-bar--${ type } ` ,
4455 {
4556 [ `${ prefix } --progress-bar--indeterminate` ] : indeterminate ,
57+ [ `${ prefix } --progress-bar--finished` ] : isFinished ,
58+ [ `${ prefix } --progress-bar--error` ] : isError ,
4659 } ,
4760 className
4861 ) ;
@@ -51,22 +64,39 @@ function ProgressBar({
5164 [ `${ prefix } --visually-hidden` ] : hideLabel ,
5265 } ) ;
5366
67+ let StatusIcon = null ;
68+
69+ if ( isError ) {
70+ StatusIcon = ErrorFilled16 ;
71+ } else if ( isFinished ) {
72+ StatusIcon = CheckmarkFilled16 ;
73+ }
74+
5475 return (
5576 < div className = { wrapperClasses } >
56- < span className = { labelClasses } id = { labelId } >
57- { label }
58- </ span >
77+ < div className = { labelClasses } id = { labelId } >
78+ < span className = { `${ prefix } --progress-bar__label-text` } > { label } </ span >
79+ { StatusIcon && (
80+ < StatusIcon className = { `${ prefix } --progress-bar__status-icon` } />
81+ ) }
82+ </ div >
83+ { /* eslint-disable-next-line jsx-a11y/role-supports-aria-props */ }
5984 < div
6085 className = { `${ prefix } --progress-bar__track` }
6186 role = "progressbar"
87+ aria-invalid = { isError }
6288 aria-labelledby = { labelId }
6389 aria-describedby = { helperText ? helperId : null }
6490 aria-valuemin = { ! indeterminate ? 0 : null }
6591 aria-valuemax = { ! indeterminate ? max : null }
6692 aria-valuenow = { ! indeterminate ? cappedValue : null } >
6793 < div
6894 className = { `${ prefix } --progress-bar__bar` }
69- style = { { transform : `scaleX(${ percentage } )` } }
95+ style = {
96+ ! isFinished && ! isError
97+ ? { transform : `scaleX(${ percentage } )` }
98+ : null
99+ }
70100 />
71101 </ div >
72102 { helperText && (
@@ -109,6 +139,11 @@ ProgressBar.propTypes = {
109139 */
110140 size : PropTypes . oneOf ( [ 'small' , 'big' ] ) ,
111141
142+ /**
143+ * Specify the status.
144+ */
145+ status : PropTypes . oneOf ( [ 'active' , 'finished' , 'error' ] ) ,
146+
112147 /**
113148 * Defines the alignment variant of the progress bar.
114149 */
0 commit comments