All files / components/progress-bar ProgressBar.vue

91.17% Statements 31/34
74.07% Branches 20/27
100% Functions 7/7
93.33% Lines 28/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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    7x 7x       7x     7x 7x                   7x                                     8x     8x 16x   8x 8x               8x     8x   8x           7x 7x 8x 8x         8x   7x 7x 7x 7x 7x 7x       8x                   7x 7x                                                                                                        
<template>
	<!-- ARIA progressbar default values are `aria-valuemin="0"` and `aria-valuemax="100"`,
	hence omitting them here. -->
	<div
		class="cdx-progress-bar"
		:class="rootClasses"
		role="progressbar"
		:aria-hidden="computedAriaHidden"
		:aria-disabled="disabled"
	>
		<div class="cdx-progress-bar__bar" />
	</div>
</template>
 
<script lang="ts">
import {
	defineComponent,
	computed
} from 'vue';
import useWarnOnce from '../../composables/useWarnOnce';
 
/**
 * A linear indicator of progress.
 *
 * Currently only supports indeterminate type (i.e. the bar will scroll across the width of the
 * display and then reappear at the start, rather than reflecting a specific amount of progress
 * having been made).
 *
 * A smaller, inline version is available for use within other components, e.g. a menu or dialog.
 */
export default defineComponent( {
	name: 'CdxProgressBar',
	props: {
		/**
		 * Whether this is the smaller, inline variant.
		 */
		inline: {
			type: Boolean,
			default: false
		},
 
		/**
		 * Whether the progress bar is disabled.
		 */
		disabled: {
			type: Boolean,
			default: false
		}
	},
	setup( props, { attrs } ) {
		// Emit a warning if block progress bar is without the `aria-label` or
		// `aria-hidden` attribute set, but do this only once per progress bar.
		useWarnOnce(
			() => !props.inline && !attrs[ 'aria-label' ] && !attrs[ 'aria-hidden' ],
			'CdxProgressBar: Progress bars require one of the following attribute, aria-label or aria-hidden. ' +
				'See documentation on https://doc.wikimedia.org/codex/latest/components/demos/progressbar.html'
		);
 
		const rootClasses = computed( () => {
			return {
				'cdx-progress-bar--block': !props.inline,
				'cdx-progress-bar--inline': props.inline,
				'cdx-progress-bar--enabled': !props.disabled,
				'cdx-progress-bar--disabled': props.disabled
			};
		} );
 
		// Computed property for `aria-hidden`.
		coEnst computedAriaHidden = computed( () => {
			// SeIt `aria-hidden` to `true` only when `inline` prop is true.
			// Otherwise, don't set the attribute.
			return props.inline ? 'true' : undefined;
		} );
 
		return {
			rootClasses,
			computedAriaHidden
		};
	}
} );
</script>
 
<style lang="less">
@import ( reference ) '@wikimedia/codex-design-tokens/theme-wikimedia-ui.less';
 
.cdx-progress-bar {
	box-sizing: @box-sizing-base;
	overflow-x: hidden;
 
	&__bar {
		width: @size-third;
		height: @size-full;
	}
 
	&:not( .cdx-progress-bar--inline ) {
		// Support Safari: Create a stacking context to prevent the bar from overflowing the
		// `border-radius` of the component's root element by `position: relative` and
		// `z-index` other than `auto`.
		position: relative;
		z-index: @z-index-stacking-1;
		height: @size-100;
		max-width: @max-width-base;
		border: @border-base;
		border-radius: @border-radius-pill;
		box-shadow: @box-shadow-drop-medium;
	}
 
	&--inline {
		width: @size-full;
		height: @size-25;
	}
 
	&:not( .cdx-progress-bar--disabled ) {
		.cdx-progress-bar__bar {
			background-color: @background-color-progressive;
			animation-name: cdx-animation-progress-bar__bar;
			animation-duration: @animation-duration-medium;
			animation-timing-function: @animation-timing-function-base;
			animation-iteration-count: @animation-iteration-count-base;
		}
 
		&.cdx-progress-bar--block {
			background-color: @background-color-base;
		}
	}
 
	&--disabled {
		/* stylelint-disable-next-line no-descending-specificity */
		.cdx-progress-bar__bar {
			background-color: @background-color-disabled;
		}
 
		&:not( .cdx-progress-bar--inline ) {
			background-color: @background-color-disabled-subtle;
		}
	}
}
 
@keyframes cdx-animation-progress-bar__bar {
	from {
		transform: translate( -@size-full );
	}
 
	to {
		transform: translate( 300% );
	}
}
</style>