feat: add ProgressBar component
This commit is contained in:
parent
f148a43390
commit
7bb110b20e
15
src/components/misc/ProgressBar.story.vue
Normal file
15
src/components/misc/ProgressBar.story.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue'
|
||||
|
||||
import ProgressBar from './ProgressBar.vue'
|
||||
|
||||
const value = ref(50)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Story>
|
||||
<Variant title="Default">
|
||||
<ProgressBar :value="value" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
163
src/components/misc/ProgressBar.vue
Normal file
163
src/components/misc/ProgressBar.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<progress
|
||||
class="progress-bar"
|
||||
:class="{
|
||||
'is-small': isSmall,
|
||||
'is-primary': isPrimary,
|
||||
}"
|
||||
:value="value"
|
||||
max="100"
|
||||
>
|
||||
{{ value }}%
|
||||
</progress>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {defineProps} from 'vue'
|
||||
|
||||
defineProps({
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
isSmall: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isPrimary: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.progress-bar {
|
||||
--progress-height: var(--size-normal, #{$size-normal});
|
||||
--progress-bar-background-color: var(--border-light, #{$border-light});
|
||||
--progress-value-background-color: var(--text, #{$text});
|
||||
--progress-border-radius: var(--radius-rounded, #{$radius-rounded});
|
||||
--progress-indeterminate-duration: 1.5s;
|
||||
|
||||
--size-small: #{$size-small};
|
||||
--size-medium: #{$size-medium};
|
||||
--size-large: #{$size-large};
|
||||
|
||||
appearance: none;
|
||||
border: none;
|
||||
border-radius: var(--progress-border-radius);
|
||||
display: block;
|
||||
height: var(--progress-height);
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
&::-webkit-progress-bar {
|
||||
background-color: var(--progress-bar-background-color);
|
||||
}
|
||||
&::-webkit-progress-value {
|
||||
background-color: var(--progress-value-background-color);
|
||||
}
|
||||
&::-moz-progress-bar {
|
||||
background-color: var(--progress-value-background-color);
|
||||
}
|
||||
&::-ms-fill {
|
||||
background-color: var(--progress-value-background-color);
|
||||
border: none;
|
||||
}
|
||||
|
||||
// Colors
|
||||
@each $name, $pair in $colors {
|
||||
$color: nth($pair, 1);
|
||||
&.is-#{$name} {
|
||||
&::-webkit-progress-value {
|
||||
--progress-value-background-color: var(--#{$name}, #{$color});
|
||||
}
|
||||
|
||||
&::-moz-progress-bar {
|
||||
--progress-value-background-color: var(--#{$name}, #{$color});
|
||||
}
|
||||
|
||||
&::-ms-fill {
|
||||
--progress-value-background-color: var(--#{$name}, #{$color});
|
||||
}
|
||||
|
||||
&:indeterminate {
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
var(--#{$name}, #{$color}) 30%,
|
||||
var(--progress-bar-background-color) 30%
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:indeterminate {
|
||||
animation-duration: var(--progress-indeterminate-duration);
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: moveIndeterminate;
|
||||
animation-timing-function: linear;
|
||||
background-color: var(--progress-bar-background-color);
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
var(--text, #{$text}) 30%,
|
||||
var(--progress-bar-background-color) 30%
|
||||
);
|
||||
background-position: top left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 150% 150%;
|
||||
|
||||
&::-webkit-progress-bar {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-moz-progress-bar {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-ms-fill {
|
||||
animation-name: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Sizes
|
||||
&.is-small {
|
||||
--progress-height: var(--size-small, #{$size-small});
|
||||
}
|
||||
&.is-medium {
|
||||
--progress-height: var(--size-medium, #{$size-medium});
|
||||
}
|
||||
&.is-large {
|
||||
--progress-height: var(--size-large, #{$size-large});
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveIndeterminate {
|
||||
from {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
to {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
--progress-height: var(--size-normal, 1rem);
|
||||
|
||||
border-radius: $radius-large;
|
||||
min-width: 6vw;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&::-moz-progress-bar,
|
||||
&::-webkit-progress-value {
|
||||
background: var(--grey-500);
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar.is-small {
|
||||
--progress-height: var(--size-small, 0.75rem);
|
||||
}
|
||||
</style>
|
@ -16,14 +16,12 @@
|
||||
ref="filesRef"
|
||||
type="file"
|
||||
/>
|
||||
<progress
|
||||
|
||||
<ProgressBar
|
||||
v-if="attachmentService.uploadProgress > 0"
|
||||
:value="attachmentService.uploadProgress"
|
||||
class="progress is-primary"
|
||||
max="100"
|
||||
>
|
||||
{{ attachmentService.uploadProgress }}%
|
||||
</progress>
|
||||
:value="attachmentService.uploadProgress * 100"
|
||||
is-primary
|
||||
/>
|
||||
|
||||
<div class="files" v-if="attachments.length > 0">
|
||||
<!-- FIXME: don't use a for element that wraps other links / buttons
|
||||
@ -163,6 +161,7 @@ import {ref, shallowReactive, computed} from 'vue'
|
||||
import {useDropZone} from '@vueuse/core'
|
||||
|
||||
import User from '@/components/misc/user.vue'
|
||||
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
import AttachmentService from '@/services/attachment'
|
||||
|
@ -41,12 +41,13 @@
|
||||
</time>
|
||||
</span>
|
||||
<h3>{{ task.title }}</h3>
|
||||
<progress
|
||||
class="progress is-small"
|
||||
|
||||
<ProgressBar
|
||||
v-if="task.percentDone > 0"
|
||||
:value="task.percentDone * 100" max="100">
|
||||
{{ task.percentDone * 100 }}%
|
||||
</progress>
|
||||
:value="task.percentDone * 100"
|
||||
is-small
|
||||
/>
|
||||
|
||||
<div class="footer">
|
||||
<labels :labels="task.labels"/>
|
||||
<priority-label
|
||||
@ -79,6 +80,7 @@ import {ref, computed, watch} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import PriorityLabel from '@/components/tasks/partials/priorityLabel.vue'
|
||||
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||
import Done from '@/components/misc/Done.vue'
|
||||
import Labels from '@/components/tasks/partials/labels.vue'
|
||||
import ChecklistSummary from './checklist-summary.vue'
|
||||
|
@ -104,13 +104,11 @@
|
||||
<checklist-summary :task="task"/>
|
||||
</div>
|
||||
|
||||
<progress
|
||||
class="progress is-small"
|
||||
<ProgressBar
|
||||
v-if="task.percentDone > 0"
|
||||
:value="task.percentDone * 100" max="100"
|
||||
>
|
||||
{{ task.percentDone * 100 }}%
|
||||
</progress>
|
||||
:value="task.percentDone * 100"
|
||||
is-small
|
||||
/>
|
||||
|
||||
<ColorBubble
|
||||
v-if="showProjectSeparately && projectColor !== '' && currentProject?.id !== task.projectId"
|
||||
@ -166,6 +164,7 @@ import Labels from '@/components/tasks/partials//labels.vue'
|
||||
import DeferTask from '@/components/tasks/partials//defer-task.vue'
|
||||
import ChecklistSummary from '@/components/tasks/partials/checklist-summary.vue'
|
||||
|
||||
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||
@ -495,10 +494,6 @@ function focusTaskLink() {
|
||||
border-left-color: var(--grey-300);
|
||||
border-bottom-color: var(--grey-300);
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.subtask-nested {
|
||||
|
@ -24,7 +24,7 @@
|
||||
@import "bulma-css-variables/sass/elements/icon";
|
||||
@import "bulma-css-variables/sass/elements/image";
|
||||
//@import "bulma-css-variables/sass/elements/notification"; // not used
|
||||
@import "bulma-css-variables/sass/elements/progress";
|
||||
// @import "bulma-css-variables/sass/elements/progress"; // not used
|
||||
@import "bulma-css-variables/sass/elements/table";
|
||||
@import "bulma-css-variables/sass/elements/tag";
|
||||
@import "bulma-css-variables/sass/elements/title";
|
||||
|
@ -42,23 +42,6 @@ h6 {
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
// FIXME: create <ProgressBar> component. used in
|
||||
// - attachments.vue
|
||||
// - kanban-card.vue
|
||||
// - singleTaskInProject.vue
|
||||
.progress {
|
||||
border-radius: $radius-large;
|
||||
width: 50px;
|
||||
margin: 0 0.5rem 0 0;
|
||||
flex: 3 1 auto;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
margin: 0.5rem 0 0 0;
|
||||
order: 1;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: these helpers should be mixins
|
||||
.has-no-border {
|
||||
border: none !important;
|
||||
@ -107,7 +90,6 @@ button.table {
|
||||
.color-bubble {
|
||||
display: inline-block;
|
||||
border-radius: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.is-strikethrough {
|
||||
|
Loading…
x
Reference in New Issue
Block a user