-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(community-progress): implement new design standards
feat: new size prop has been added with mini variant of progress bar feat: progress bars now have proper aria attributes BREAKING CHANGE: progress bar height has been adjusted and no longer changes with viewport BREAKING CHANGE: allyLabel prop in Progress is required to aid assistive technology BREAKING CHANGE: 'primary' variant is now named 'positive' BREAKING CHANGE: 'error' variant is now named 'negative' BREAKING CHANGE: removed 'secondary' variant BREAKING CHANGE: styled components is now a peer dependency
- Loading branch information
1 parent
35da02d
commit 7eaf907
Showing
14 changed files
with
227 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,81 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import styled from 'styled-components' | ||
|
||
import { colorAccessibleGreen, colorCardinal, colorGainsboro } from '@tds/core-colours' | ||
import { safeRest } from '@tds/util-helpers' | ||
|
||
import styles from '../Progress.scss' | ||
import Negative from './textures/Negative' | ||
import Disabled from './textures/Disabled' | ||
|
||
const MIN_NON_ZERO_PROGRESS_PERCENTAGE = 5 | ||
const MAX_PROGRESS_PERCENTAGE = 100 | ||
|
||
const ProgressBar = styled.div(({ progress, zIndex, variant }) => ({ | ||
width: `${progress}%`, | ||
height: '100%', | ||
zIndex, | ||
display: 'block', | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
overflow: 'hidden', | ||
boxShadow: 'inset 0 -1px 1px rgba(255,255,255,0.3)', | ||
|
||
...(variant === 'positive' && { backgroundColor: colorAccessibleGreen }), | ||
...(variant === 'negative' && { backgroundColor: colorCardinal }), | ||
...(variant === 'disabled' && { backgroundColor: colorGainsboro }), | ||
})) | ||
|
||
const constrainNonZeroPercentage = (minNonZeroPercentage, maxPercentage, percentage) => { | ||
if (percentage <= 0) return 0 | ||
else if (percentage < minNonZeroPercentage) return minNonZeroPercentage | ||
else if (percentage > maxPercentage) return maxPercentage | ||
return percentage | ||
} | ||
|
||
const Bar = ({ percentage, variant, ...rest }) => { | ||
const Bar = ({ percentage, variant, a11yLabel, ...rest }) => { | ||
const percent = constrainNonZeroPercentage( | ||
MIN_NON_ZERO_PROGRESS_PERCENTAGE, | ||
MAX_PROGRESS_PERCENTAGE, | ||
percentage | ||
) | ||
const zIndex = 100 - percent // z-index order is inverse of percentage | ||
return ( | ||
<div | ||
<ProgressBar | ||
{...safeRest(rest)} | ||
className={[styles.progressBar, styles[variant]].join(' ')} | ||
style={{ width: `${percent}%`, zIndex }} | ||
/> | ||
variant={variant} | ||
progress={percent} | ||
zIndex={zIndex} | ||
role="progressbar" | ||
aria-valuenow={percentage} | ||
aria-valuemin="0" | ||
aria-valuemax="100" | ||
aria-valuetext={a11yLabel} | ||
> | ||
{variant === 'negative' && <Negative />} | ||
{variant === 'disabled' && <Disabled />} | ||
</ProgressBar> | ||
) | ||
} | ||
|
||
Bar.propTypes = { | ||
/** | ||
* Specifies how much of the task has been completed | ||
* A number from 0 to 100 that specifies amount of progress. | ||
*/ | ||
percentage: PropTypes.number.isRequired, | ||
variant: PropTypes.oneOf(['primary', 'secondary', 'error', 'disabled']), | ||
/** | ||
* The style of the `Progress.Bar`. | ||
*/ | ||
variant: PropTypes.oneOf(['positive', 'negative', 'disabled']), | ||
/** | ||
* A label to be read by assistive technology. Meant to give context about the `Progress.Bar`. | ||
*/ | ||
a11yLabel: PropTypes.string.isRequired, | ||
} | ||
|
||
Bar.defaultProps = { | ||
variant: 'primary', | ||
variant: 'positive', | ||
} | ||
|
||
export default Bar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 35 additions & 8 deletions
43
packages/Progress/Bar/__tests__/__snapshots__/Bar.spec.jsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,40 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Progress has a width of 5% if value is equal or less than 5 1`] = ` | ||
<Bar__ProgressBar | ||
aria-valuemax="100" | ||
aria-valuemin="0" | ||
aria-valuenow={5} | ||
aria-valuetext="Data Usage" | ||
progress={5} | ||
role="progressbar" | ||
variant="positive" | ||
zIndex={95} | ||
/> | ||
`; | ||
|
||
exports[`Progress has a width that is a percentage proportional to its value 1`] = ` | ||
<Bar__ProgressBar | ||
aria-valuemax="100" | ||
aria-valuemin="0" | ||
aria-valuenow={50} | ||
aria-valuetext="Data Usage" | ||
progress={50} | ||
role="progressbar" | ||
variant="positive" | ||
zIndex={50} | ||
/> | ||
`; | ||
|
||
exports[`Progress renders 1`] = ` | ||
<div | ||
className="progressBar primary" | ||
style={ | ||
Object { | ||
"width": "5%", | ||
"zIndex": 95, | ||
} | ||
} | ||
<Bar__ProgressBar | ||
aria-valuemax="100" | ||
aria-valuemin="0" | ||
aria-valuenow={3} | ||
aria-valuetext="Data Usage" | ||
progress={5} | ||
role="progressbar" | ||
variant="positive" | ||
zIndex={95} | ||
/> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react' | ||
|
||
const Disabled = () => ( | ||
<svg width="100%" height="24"> | ||
<defs> | ||
<pattern id="zohoz" patternUnits="userSpaceOnUse" width="8" height="8"> | ||
<rect width="8" height="8" fill="#D8D8D8" /> | ||
<circle cx="4" cy="4" r="2" fill="#71757B" stroke="#71757B" strokeWidth="0" /> | ||
<circle cx="0" cy="0" r="2" fill="#71757B" stroke="#71757B" strokeWidth="0" /> | ||
<circle cx="0" cy="8" r="2" fill="#71757B" stroke="#71757B" strokeWidth="0" /> | ||
<circle cx="8" cy="0" r="2" fill="#71757B" stroke="#71757B" strokeWidth="0" /> | ||
<circle cx="8" cy="8" r="2" fill="#71757B" stroke="#71757B" strokeWidth="0" /> | ||
</pattern> | ||
</defs> | ||
<path d="M 0 0 L 0 140 L 2000 2000 L 2000 0 Z" style={{ fill: 'url("#zohoz")' }} /> | ||
</svg> | ||
) | ||
|
||
export default Disabled |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from 'react' | ||
|
||
const Negative = () => ( | ||
<svg width="100%" height="24"> | ||
<defs> | ||
<pattern id="sasmd" patternUnits="userSpaceOnUse" width="8" height="8"> | ||
<rect width="8" height="8" fill="#C12335" /> | ||
<path | ||
d="M 0,8 l 8,-8 M -2,2 l 4,-4 M 6,10 l 4,-4" | ||
strokeWidth="2" | ||
shapeRendering="auto" | ||
stroke="#e7adb4" | ||
strokeLinecap="square" | ||
/> | ||
</pattern> | ||
</defs> | ||
<path d="M 0 0 L 0 140 L 2000 2000 L 2000 0 Z" style={{ fill: 'url("#sasmd")' }} /> | ||
</svg> | ||
) | ||
|
||
export default Negative |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,47 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import styled from 'styled-components' | ||
|
||
import { colorGainsboro, colorWhite } from '@tds/core-colours' | ||
import { safeRest } from '@tds/util-helpers' | ||
|
||
import styles from './Progress.scss' | ||
|
||
import Bar from './Bar/Bar' | ||
|
||
const ProgressBarContainer = styled.div(({ size }) => ({ | ||
display: 'inline-block', | ||
position: 'relative', | ||
background: colorWhite, | ||
width: '100%', | ||
height: size === 'mini' ? '12px' : '24px', | ||
borderRadius: size === 'mini' ? '12px' : '24px', | ||
borderWidth: 'thin', | ||
borderStyle: 'solid', | ||
borderColor: colorGainsboro, | ||
overflow: 'hidden', | ||
transform: 'translateZ(-99999999px)', // Fix for safari overflow bug | ||
})) | ||
|
||
/** | ||
* @version ./package.json | ||
*/ | ||
|
||
const Progress = ({ children, ...rest }) => ( | ||
<div {...safeRest(rest)} className={styles.progressBarContainer}> | ||
const Progress = ({ size, children, ...rest }) => ( | ||
<ProgressBarContainer {...safeRest(rest)} size={size}> | ||
{children} | ||
</div> | ||
</ProgressBarContainer> | ||
) | ||
|
||
Progress.propTypes = { | ||
/** | ||
* The size of the progress bar where the default is 24px tall and mini is 12px tall. | ||
*/ | ||
size: PropTypes.oneOf(['default', 'mini']), | ||
children: PropTypes.element.isRequired, | ||
} | ||
|
||
Progress.defaultProps = { | ||
size: 'default', | ||
} | ||
|
||
Progress.Bar = Bar | ||
export default Progress |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,67 @@ | ||
The Progress component is a wrapper-container for an number of Progress.Bar components. | ||
The Progress Bar is a visual representation of linear progression. They provide simple but important information at a quick glance. | ||
|
||
A Progress component can contain any number of progress bars, which will be | ||
stacked where shorter bars appears in front of longer bars. | ||
### Usage Criteria | ||
|
||
- Use to indicate progress within a single limit | ||
- Available in 2 sizes: `default` and `mini` | ||
- Use the `default` size when displaying ProgressBar with supporting content | ||
- Use the `mini` size when displaying ProgressBar with minimal supporting content in a condensed layout | ||
- Limit the use of `mini` size for overview views | ||
- Use variants to provide immediate recognition of status: | ||
- Will display in Positive variant by default | ||
- Positive variant indicates account in good standing | ||
- Negative variant indicates account meeting or exceeding limit | ||
- Disabled variant indicates account is paused, unavailable, or inactive | ||
- Use the `percentage` prop to indicate completion | ||
- Limit the use of stacked bars (displaying multiple progress/limits within a single `ProgressBar`) | ||
|
||
### Minimal Usage | ||
|
||
```jsx | ||
<Progress> | ||
<Progress.Bar percentage={20} variant="error" /> | ||
<Progress.Bar percentage={25} variant="positive" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress> | ||
<Progress.Bar percentage={50} variant="primary" /> | ||
<Progress.Bar percentage={50} variant="negative" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress> | ||
<Progress.Bar percentage={70} variant="secondary" /> | ||
<Progress.Bar percentage={100} variant="disabled" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress> | ||
<Progress.Bar percentage={100} variant="disabled" /> | ||
<Progress.Bar percentage={30} variant="positive" a11yLabel="Data Used" /> | ||
<Progress.Bar percentage={75} variant="negative" a11yLabel="Data Unavailable" /> | ||
</Progress> | ||
``` | ||
|
||
### Mini Size | ||
|
||
```jsx | ||
<Progress size="mini"> | ||
<Progress.Bar percentage={25} variant="positive" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress size="mini"> | ||
<Progress.Bar percentage={50} variant="negative" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress size="mini"> | ||
<Progress.Bar percentage={100} variant="disabled" a11yLabel="Data Usage" /> | ||
</Progress> | ||
<Progress size="mini"> | ||
<Progress.Bar percentage={30} variant="negative" a11yLabel="Data Used" /> | ||
<Progress.Bar percentage={75} variant="disabled" a11yLabel="Data Unavailable" /> | ||
</Progress> | ||
``` | ||
|
||
### Accessibility | ||
|
||
#### Accessibility features | ||
|
||
- `a11yLabel` prop is required to add context to assistive technology | ||
- This prop should be applied on a per `Progress.Bar` basis to provide maximum context for stacked bars | ||
- Patterns provide additional visual difference between states aside from colour alone | ||
- Progress Bars make use of the ‘progressbar’ role and set related attributes to communicate progress to assistive technology. We chose `<div>` elements instead of `<progress>` for visual parity across all target browsers | ||
|
||
#### Accessibility guidelines | ||
|
||
- Include a label adjacent or in close proximity to the ProgressBar to provide clear context | ||
- Build components in logical reading order |
Oops, something went wrong.