forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgress.tsx
More file actions
164 lines (151 loc) · 5.57 KB
/
Progress.tsx
File metadata and controls
164 lines (151 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import { Component } from 'react';
import styles from '@patternfly/react-styles/css/components/Progress/progress';
import { css } from '@patternfly/react-styles';
import { ProgressContainer, ProgressMeasureLocation } from './ProgressContainer';
import { AriaProps } from './ProgressBar';
import { getUniqueId } from '../../helpers/util';
export enum ProgressSize {
sm = 'sm',
md = 'md',
lg = 'lg'
}
export interface ProgressProps extends Omit<React.HTMLProps<HTMLDivElement>, 'size' | 'label' | 'title'> {
/** Classname for progress component. */
className?: string;
/** Size variant of progress. */
size?: 'sm' | 'md' | 'lg';
/** Where the measure percent will be located. */
measureLocation?: 'outside' | 'inside' | 'top' | 'none';
/** Status variant of progress. */
variant?: 'danger' | 'success' | 'warning';
/** Title above progress. The isTitleTruncated property will only affect string titles. Node title truncation must be handled manually. */
title?: React.ReactNode;
/** Text description of current progress value to display instead of percentage. */
label?: React.ReactNode;
/** Actual value of progress. */
value?: number;
/** DOM id for progress component. */
id?: string;
/** Minimal value of progress. */
min?: number;
/** Maximum value of progress. */
max?: number;
/** Accessible text description of current progress value, for when value is not a percentage. Use with label. */
valueText?: string;
/** Indicate whether to truncate the string title */
isTitleTruncated?: boolean;
/** Position of the tooltip which is displayed if title is truncated */
tooltipPosition?: 'auto' | 'top' | 'bottom' | 'left' | 'right';
/** Adds accessible text to the ProgressBar. Required when title not used and there is not any label associated with the progress bar */
'aria-label'?: string;
/** Associates the ProgressBar with it's label for accessibility purposes. Required when title not used */
'aria-labelledby'?: string;
/** Adds an accessible description to the ProgressBar via space separated list of ids. Required when helperText is passed in. */
'aria-describedby'?: string;
/** Content which can be used to convey additional information about the progress component.
* We recommend the helper text component as it was designed for this purpose.
*/
helperText?: React.ReactNode;
/** Flag indicating whether the status icon should be hidden, helpful when space is limited (such as within table cells). When set to true, you must ensure the context of the status is provided in another way, such as via the progress measure. */
hideStatusIcon?: boolean;
}
class Progress extends Component<ProgressProps> {
static displayName = 'Progress';
static defaultProps: ProgressProps = {
className: '',
measureLocation: ProgressMeasureLocation.top,
variant: null,
id: '',
title: '',
min: 0,
max: 100,
size: null as ProgressSize,
label: null as React.ReactNode,
value: 0,
valueText: null as string,
isTitleTruncated: false,
tooltipPosition: 'top' as 'auto' | 'top' | 'bottom' | 'left' | 'right',
'aria-label': null as string,
'aria-labelledby': null as string,
'aria-describedby': null as string
};
id = this.props.id || getUniqueId();
render() {
const {
/* eslint-disable @typescript-eslint/no-unused-vars */
id,
size,
/* eslint-enable @typescript-eslint/no-unused-vars */
className,
value,
title,
label,
variant,
measureLocation,
min,
max,
valueText,
isTitleTruncated,
tooltipPosition,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
'aria-describedby': ariaDescribedBy,
helperText,
hideStatusIcon,
...props
} = this.props;
const progressBarAriaProps: AriaProps = {
'aria-valuemin': min,
'aria-valuenow': value,
'aria-valuemax': max
};
if (title || ariaLabelledBy) {
progressBarAriaProps['aria-labelledby'] = title ? `${this.id}-description` : ariaLabelledBy;
}
if (ariaLabel) {
progressBarAriaProps['aria-label'] = ariaLabel;
}
if (ariaDescribedBy) {
progressBarAriaProps['aria-describedby'] = ariaDescribedBy;
}
if (valueText) {
progressBarAriaProps['aria-valuetext'] = valueText;
}
if (!title && !ariaLabelledBy && !ariaLabel) {
/* eslint-disable no-console */
console.warn(
'One of aria-label or aria-labelledby properties should be passed when using the progress component without a title.'
);
}
const scaledValue = Math.min(100, Math.max(0, Math.floor(((value - min) / (max - min)) * 100))) || 0;
return (
<div
{...props}
className={css(
styles.progress,
styles.modifiers[variant],
['inside', 'outside'].includes(measureLocation) && styles.modifiers[measureLocation as 'inside' | 'outside'],
measureLocation === 'inside' ? styles.modifiers[ProgressSize.lg] : styles.modifiers[size as 'sm' | 'lg'],
!title && styles.modifiers.singleline,
className
)}
id={this.id}
>
<ProgressContainer
parentId={this.id}
value={scaledValue}
title={title}
label={label}
variant={variant}
measureLocation={measureLocation}
progressBarAriaProps={progressBarAriaProps}
isTitleTruncated={isTitleTruncated}
tooltipPosition={tooltipPosition}
helperText={helperText}
hideStatusIcon={hideStatusIcon}
/>
</div>
);
}
}
export { Progress };