feat(progress): add parts for more design customization (#22938)

resolves #20062 fixes #21820
This commit is contained in:
Brandy Carney
2021-03-04 12:48:52 -05:00
committed by GitHub
parent e828a9a693
commit e256d3f09f
6 changed files with 245 additions and 49 deletions

View File

@ -844,6 +844,9 @@ ion-progress-bar,prop,value,number,0,false,false
ion-progress-bar,css-prop,--background ion-progress-bar,css-prop,--background
ion-progress-bar,css-prop,--buffer-background ion-progress-bar,css-prop,--buffer-background
ion-progress-bar,css-prop,--progress-background ion-progress-bar,css-prop,--progress-background
ion-progress-bar,part,progress
ion-progress-bar,part,stream
ion-progress-bar,part,track
ion-radio,shadow ion-radio,shadow
ion-radio,prop,color,string | undefined,undefined,false,false ion-radio,prop,color,string | undefined,undefined,false,false

View File

@ -1,18 +1,19 @@
@import "../../themes/ionic.globals"; @import "../../themes/ionic.globals";
// Progress bar // Progress bar
// -------------------------------------------------- // ------------------------------------------------------------------------
// Host has no background by default - this will be added to the progress-buffer-bar
// Host has no background by default - this will be added to the progress-buffer-bar
:host { :host {
/** /**
* @prop --background: Same as --buffer-background when using a determinate progress bar, otherwise it styles the background of the ion-progress-bar itself. * @prop --background: Background of the progress track, or the buffer bar if `buffer` is set
* @prop --progress-background: Color of the progress bar * @prop --progress-background: Background of the progress bar representing the current value
* @prop --buffer-background: Color of the buffer bar * @prop --buffer-background: DEPRECATED, use `--background` instead
*/ */
--background: #{ion-color(primary, base, 0.3)}; --background: #{ion-color(primary, base, 0.3)};
--progress-background: #{ion-color(primary, base)}; --progress-background: #{ion-color(primary, base)};
--buffer-background: var(--background); --buffer-background: var(--background);
display: block; display: block;
position: relative; position: relative;
@ -25,16 +26,6 @@
overflow: hidden; overflow: hidden;
} }
:host(.ion-color) {
--progress-background: #{current-color(base)};
--buffer-background: #{current-color(base, 0.3)};
}
// indeterminate has no progress-buffer-bar, so it will be added to the host
:host(.progress-bar-indeterminate) {
background: var(--buffer-background);
}
.progress, .progress,
.progress-indeterminate, .progress-indeterminate,
.indeterminate-bar-primary, .indeterminate-bar-primary,
@ -128,27 +119,33 @@
} }
} }
// Buffer style // Progress Bar: Buffer Circles
// -------------------------------------------------- // ------------------------------------------------------------------------
.buffer-circles { .buffer-circles {
background: radial-gradient(ellipse at center, var(--buffer-background) 0%, var(--buffer-background) 30%, transparent 30%) repeat-x 5px center; background-image: radial-gradient(ellipse at center, var(--buffer-background) 0%, var(--buffer-background) 30%, transparent 30%);
/* stylelint-disable property-blacklist */
background-repeat: repeat-x;
background-position: 5px center;
background-size: 10px 10px; background-size: 10px 10px;
/* stylelint-enable property-blacklist */
z-index: 0; z-index: 0;
animation: buffering 450ms infinite linear; animation: buffering 450ms infinite linear;
} }
// Progress Bar: Reversed
// ------------------------------------------------------------------------
// If reversed is set to true, the animation will be reversed // If reversed is set to true, the animation will be reversed
// and the bars starting at the top right // and the bar will start at the top right
// --------------------------------------------------
:host(.progress-bar-reversed) { :host(.progress-bar-reversed) {
transform: scaleX(-1); transform: scaleX(-1);
} }
// Progress paused // Progress Bar: Paused
// -------------------------------------------------- // ------------------------------------------------------------------------
:host(.progress-paused) { :host(.progress-paused) {
.indeterminate-bar-secondary, .indeterminate-bar-secondary,
@ -158,8 +155,27 @@
} }
} }
// Animation Keyframes // Progress Bar: Color
// -------------------------------------------------- // ------------------------------------------------------------------------
:host(.ion-color) .progress-buffer-bar {
background: #{current-color(base, 0.3)};
}
:host(.ion-color) .buffer-circles {
background-image: radial-gradient(ellipse at center, #{current-color(base, 0.3)} 0%, #{current-color(base, 0.3)} 30%, transparent 30%);
}
:host(.ion-color) {
.progress,
.progress-indeterminate {
background: #{current-color(base)};
}
}
// Progress Bar: Animation Keyframes
// ------------------------------------------------------------------------
// Source: https://github.com/material-components/material-components-web/blob/master/packages/mdc-linear-progress/_keyframes.scss // Source: https://github.com/material-components/material-components-web/blob/master/packages/mdc-linear-progress/_keyframes.scss
@keyframes primary-indeterminate-translate { @keyframes primary-indeterminate-translate {
@ -259,3 +275,4 @@
transform: translateX(-10px); transform: translateX(-10px);
} }
} }

View File

@ -8,6 +8,11 @@ import { createColorClasses } from '../../utils/theme';
/** /**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use. * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*
* @part progress - The progress bar that shows the current value when `type` is `"determinate"` and slides back and forth when `type` is `"indeterminate"`.
* @part stream - The animated circles that appear while buffering. This only shows when `buffer` is set and `type` is `"determinate"`.
* @part track - The track bar behind the progress bar. If the `buffer` property is set and `type` is `"determinate"` the track will be the
* width of the `buffer` value.
*/ */
@Component({ @Component({
tag: 'ion-progress-bar', tag: 'ion-progress-bar',
@ -77,10 +82,12 @@ export class ProgressBar implements ComponentInterface {
} }
const renderIndeterminate = () => { const renderIndeterminate = () => {
return [ return (
<div class="indeterminate-bar-primary"><span class="progress-indeterminate"></span></div>, <div part="track" class="progress-buffer-bar">
<div class="indeterminate-bar-secondary"><span class="progress-indeterminate"></span></div> <div class="indeterminate-bar-primary"><span part="progress" class="progress-indeterminate"></span></div>
]; <div class="indeterminate-bar-secondary"><span part="progress" class="progress-indeterminate"></span></div>
</div>
);
}; };
const renderProgress = (value: number, buffer: number) => { const renderProgress = (value: number, buffer: number) => {
@ -88,7 +95,7 @@ const renderProgress = (value: number, buffer: number) => {
const finalBuffer = clamp(0, buffer, 1); const finalBuffer = clamp(0, buffer, 1);
return [ return [
<div class="progress" style={{ transform: `scaleX(${finalValue})` }}></div>, <div part="progress" class="progress" style={{ transform: `scaleX(${finalValue})` }}></div>,
/** /**
* Buffer circles with two container to move * Buffer circles with two container to move
* the circles behind the buffer progress * the circles behind the buffer progress
@ -98,9 +105,9 @@ const renderProgress = (value: number, buffer: number) => {
*/ */
<div class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }} style={{ transform: `translateX(${finalBuffer * 100}%)` }}> <div class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }} style={{ transform: `translateX(${finalBuffer * 100}%)` }}>
<div class="buffer-circles-container" style={{ transform: `translateX(-${finalBuffer * 100}%)` }}> <div class="buffer-circles-container" style={{ transform: `translateX(-${finalBuffer * 100}%)` }}>
<div class="buffer-circles"></div> <div part="stream" class="buffer-circles"></div>
</div> </div>
</div>, </div>,
<div class="progress-buffer-bar" style={{ transform: `scaleX(${finalBuffer})` }}></div>, <div part="track" class="progress-buffer-bar" style={{ transform: `scaleX(${finalBuffer})` }}></div>,
]; ];
}; };

View File

@ -1,20 +1,18 @@
# ion-progress-bar # ion-progress-bar
ion-progress-bar is a horizontal progress bar to visualize the progression of an operation and activity. You can choose between two types: `determinate` and `indeterminate`. Progress bars inform users about the status of ongoing processes, such as loading an app, submitting a form, or saving updates. There are two types of progress bars: `determinate` and `indeterminate`.
## Progress Type ## Progress Type
### Determinate ### Determinate
If the percentage of an operation is known, you should use the determinate type. This is the default type and the progress is represented by the `value` property. Determinate is the default type. It should be used when the percentage of an operation is known. The progress is represented by setting the `value` property. This can be used to show the progress increasing from 0 to 100% of the track.
A buffer shows circles as animation to indicate some activity. If the `buffer` property is smaller than 1 you can show the additional buffering progress. If the `buffer` property is set, a buffer stream will show with animated circles to indicate activity. The value of the `buffer` property will also be represented by how much visible track there is. If the value of `buffer` is less than the `value` property, there will be no visible track. If `buffer` is equal to `1` then the buffer stream will be hidden.
### Indeterminate ### Indeterminate
If an operation is in progress and it's not necessary to indicate how long it will take. The indeterminate type should be used when it is unknown how long the process will take. The progress bar is not tied to the `value`, instead it continually slides along the track until the process is complete.
If you add `reversed="true"`, you receive a query which is used to indicate pre-loading.
<!-- Auto Generated Below --> <!-- Auto Generated Below -->
@ -144,13 +142,22 @@ export default defineComponent({
| `value` | `value` | The value determines how much of the active bar should display when the `type` is `"determinate"`. The value should be between [0, 1]. | `number` | `0` | | `value` | `value` | The value determines how much of the active bar should display when the `type` is `"determinate"`. The value should be between [0, 1]. | `number` | `0` |
## Shadow Parts
| Part | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"progress"` | The progress bar that shows the current value when `type` is `"determinate"` and slides back and forth when `type` is `"indeterminate"`. |
| `"stream"` | The animated circles that appear while buffering. This only shows when `buffer` is set and `type` is `"determinate"`. |
| `"track"` | The track bar behind the progress bar. If the `buffer` property is set and `type` is `"determinate"` the track will be the width of the `buffer` value. |
## CSS Custom Properties ## CSS Custom Properties
| Name | Description | | Name | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | ----------------------- | ---------------------------------------------------------------------- |
| `--background` | Same as --buffer-background when using a determinate progress bar, otherwise it styles the background of the ion-progress-bar itself. | | `--background` | Background of the progress track, or the buffer bar if `buffer` is set |
| `--buffer-background` | Color of the buffer bar | | `--buffer-background` | DEPRECATED, use `--background` instead |
| `--progress-background` | Color of the progress bar | | `--progress-background` | Background of the progress bar representing the current value |
---------------------------------------------- ----------------------------------------------

View File

@ -0,0 +1,10 @@
import { newE2EPage } from '@stencil/core/testing';
test('progress-bar: standalone', async () => {
const page = await newE2EPage({
url: '/src/components/progress-bar/test/standalone?ionic:_testing=true'
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -12,19 +12,171 @@
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head> <script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
<body> <body>
<h1>Default Progress Bar</h1> <h1>Default Progress Bars</h1>
<ion-progress-bar></ion-progress-bar> <ion-progress-bar></ion-progress-bar>
<h1>Default Progress Bar with 50% width</h1>
<ion-progress-bar value="0.5"></ion-progress-bar> <ion-progress-bar value="0.5"></ion-progress-bar>
<ion-progress-bar type="indeterminate"></ion-progress-bar>
<hr>
<h1>Colorize Progress Bar</h1> <h1>Progress Bar: Colors</h1>
<ion-progress-bar color="primary" value="0.5"></ion-progress-bar> <ion-progress-bar color="primary" value="0.5"></ion-progress-bar>
<ion-progress-bar color="secondary" value="0.5"></ion-progress-bar> <ion-progress-bar color="secondary" value="0.5"></ion-progress-bar>
<ion-progress-bar color="tertiary" value="0.5"></ion-progress-bar>
<ion-progress-bar color="success" value="0.5"></ion-progress-bar>
<ion-progress-bar color="warning" value="0.5"></ion-progress-bar>
<ion-progress-bar color="danger" value="0.5"></ion-progress-bar>
<ion-progress-bar color="dark" value="0.5"></ion-progress-bar>
<ion-progress-bar color="light" value="0.5"></ion-progress-bar>
<h1>Other types</h1> <hr>
<ion-progress-bar type="indeterminate"></ion-progress-bar>
<h1>Default Types</h1>
<ion-progress-bar></ion-progress-bar>
<ion-progress-bar value="0.5"></ion-progress-bar>
<ion-progress-bar value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar color="warning" reversed="true" value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar buffer="0"></ion-progress-bar>
<ion-progress-bar color="danger" type="indeterminate"></ion-progress-bar>
<ion-progress-bar type="indeterminate" reversed="true"></ion-progress-bar>
<hr>
<h1>Custom: colors by part</h1>
<ion-progress-bar class="custom-color-parts"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" buffer="0.9"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" value="0.5"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" color="warning" reversed="true" value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" buffer="0"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" color="danger" type="indeterminate"></ion-progress-bar>
<ion-progress-bar class="custom-color-parts" type="indeterminate" reversed="true"></ion-progress-bar>
<hr>
<h1>Custom: colors by css variable</h1>
<ion-progress-bar class="custom-color-variables"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" value="0.5"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" color="warning" reversed="true" value="0.20" buffer="0.4"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" buffer="0"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" color="danger" type="indeterminate"></ion-progress-bar>
<ion-progress-bar class="custom-color-variables" type="indeterminate" reversed="true"></ion-progress-bar>
<hr>
<h1>Custom border radius</h1>
<ion-progress-bar class="custom-border-radius"></ion-progress-bar>
<ion-progress-bar class="custom-border-radius" value="0.5"></ion-progress-bar>
<ion-progress-bar class="custom-border-radius" type="indeterminate"></ion-progress-bar>
<h1>Custom transition</h1>
<ion-progress-bar class="random-value" max="100"></ion-progress-bar>
<ion-progress-bar class="random-value custom-transition" max="100"></ion-progress-bar>
</body> </body>
<script>
let randomValues = document.querySelectorAll('.random-value');
setInterval(() => {
let value = Math.random();
for (let i = 0; i < randomValues.length; i++) {
randomValues[i].value = value;
}
}, 100);
</script>
<style>
h1 {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
font-weight: normal;
color: #a1a7b0;
margin-top: 10px;
margin-left: 5px;
}
hr {
background: #eff1f3;
border: none;
height: 1px;
margin-top: 18px;
margin-bottom: 25px;
}
ion-progress-bar {
margin-bottom: 10px;
}
/*
* Custom progress bar color using parts
* ------------------------------------------------------
* Note: in these examples setting the background on
* each element should override the color prop
*/
/* determinate buffer / track and indeterminate track */
.custom-color-parts::part(track) {
background:rgb(158, 157, 36, 0.2);
}
/* determinate and indeterminate progress background */
.custom-color-parts::part(progress) {
background: #9e9d24;
}
/* buffer stream (animated circles) */
.custom-color-parts::part(stream) {
background-image: radial-gradient(ellipse at center, rgb(158, 157, 36, 0.2) 0%, rgb(158, 157, 36, 0.2) 30%, transparent 30%);
}
/*
* Custom progress bar color using css variables
* ------------------------------------------------------
* Note: in this example setting the background via
* CSS variables should NOT override the color prop
*/
.custom-color-variables {
--background: rgb(158, 157, 36, 0.2);
--progress-background: #9e9d24;
}
/*
* Custom progress bar border radius using parts
* ------------------------------------------------------
*/
.custom-border-radius {
border-radius: 10px;
height: 20px;
}
.custom-border-radius::part(progress) {
border-radius: 0 50% 50% 0;
}
.custom-border-radius[type="indeterminate"]::part(progress) {
border-radius: 8px;
}
/*
* Custom transition for fast value changes
* ------------------------------------------------------
* The first progress bar in the example has the default
* transition, while the second has none. This is
* apparent because they use the same values.
*/
.custom-transition::part(progress) {
transition: none;
}
</style>
</html> </html>