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"
|
ref="filesRef"
|
||||||
type="file"
|
type="file"
|
||||||
/>
|
/>
|
||||||
<progress
|
|
||||||
|
<ProgressBar
|
||||||
v-if="attachmentService.uploadProgress > 0"
|
v-if="attachmentService.uploadProgress > 0"
|
||||||
:value="attachmentService.uploadProgress"
|
:value="attachmentService.uploadProgress * 100"
|
||||||
class="progress is-primary"
|
is-primary
|
||||||
max="100"
|
/>
|
||||||
>
|
|
||||||
{{ attachmentService.uploadProgress }}%
|
|
||||||
</progress>
|
|
||||||
|
|
||||||
<div class="files" v-if="attachments.length > 0">
|
<div class="files" v-if="attachments.length > 0">
|
||||||
<!-- FIXME: don't use a for element that wraps other links / buttons
|
<!-- 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 {useDropZone} from '@vueuse/core'
|
||||||
|
|
||||||
import User from '@/components/misc/user.vue'
|
import User from '@/components/misc/user.vue'
|
||||||
|
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
import AttachmentService from '@/services/attachment'
|
import AttachmentService from '@/services/attachment'
|
||||||
|
@ -41,12 +41,13 @@
|
|||||||
</time>
|
</time>
|
||||||
</span>
|
</span>
|
||||||
<h3>{{ task.title }}</h3>
|
<h3>{{ task.title }}</h3>
|
||||||
<progress
|
|
||||||
class="progress is-small"
|
<ProgressBar
|
||||||
v-if="task.percentDone > 0"
|
v-if="task.percentDone > 0"
|
||||||
:value="task.percentDone * 100" max="100">
|
:value="task.percentDone * 100"
|
||||||
{{ task.percentDone * 100 }}%
|
is-small
|
||||||
</progress>
|
/>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<labels :labels="task.labels"/>
|
<labels :labels="task.labels"/>
|
||||||
<priority-label
|
<priority-label
|
||||||
@ -79,6 +80,7 @@ import {ref, computed, watch} from 'vue'
|
|||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
import PriorityLabel from '@/components/tasks/partials/priorityLabel.vue'
|
import PriorityLabel from '@/components/tasks/partials/priorityLabel.vue'
|
||||||
|
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||||
import Done from '@/components/misc/Done.vue'
|
import Done from '@/components/misc/Done.vue'
|
||||||
import Labels from '@/components/tasks/partials/labels.vue'
|
import Labels from '@/components/tasks/partials/labels.vue'
|
||||||
import ChecklistSummary from './checklist-summary.vue'
|
import ChecklistSummary from './checklist-summary.vue'
|
||||||
|
@ -104,13 +104,11 @@
|
|||||||
<checklist-summary :task="task"/>
|
<checklist-summary :task="task"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<progress
|
<ProgressBar
|
||||||
class="progress is-small"
|
|
||||||
v-if="task.percentDone > 0"
|
v-if="task.percentDone > 0"
|
||||||
:value="task.percentDone * 100" max="100"
|
:value="task.percentDone * 100"
|
||||||
>
|
is-small
|
||||||
{{ task.percentDone * 100 }}%
|
/>
|
||||||
</progress>
|
|
||||||
|
|
||||||
<ColorBubble
|
<ColorBubble
|
||||||
v-if="showProjectSeparately && projectColor !== '' && currentProject?.id !== task.projectId"
|
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 DeferTask from '@/components/tasks/partials//defer-task.vue'
|
||||||
import ChecklistSummary from '@/components/tasks/partials/checklist-summary.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 BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
||||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||||
@ -495,10 +494,6 @@ function focusTaskLink() {
|
|||||||
border-left-color: var(--grey-300);
|
border-left-color: var(--grey-300);
|
||||||
border-bottom-color: var(--grey-300);
|
border-bottom-color: var(--grey-300);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtask-nested {
|
.subtask-nested {
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
@import "bulma-css-variables/sass/elements/icon";
|
@import "bulma-css-variables/sass/elements/icon";
|
||||||
@import "bulma-css-variables/sass/elements/image";
|
@import "bulma-css-variables/sass/elements/image";
|
||||||
//@import "bulma-css-variables/sass/elements/notification"; // not used
|
//@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/table";
|
||||||
@import "bulma-css-variables/sass/elements/tag";
|
@import "bulma-css-variables/sass/elements/tag";
|
||||||
@import "bulma-css-variables/sass/elements/title";
|
@import "bulma-css-variables/sass/elements/title";
|
||||||
|
@ -42,23 +42,6 @@ h6 {
|
|||||||
font-weight: 400 !important;
|
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
|
// FIXME: these helpers should be mixins
|
||||||
.has-no-border {
|
.has-no-border {
|
||||||
border: none !important;
|
border: none !important;
|
||||||
@ -107,7 +90,6 @@ button.table {
|
|||||||
.color-bubble {
|
.color-bubble {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
margin-right: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-strikethrough {
|
.is-strikethrough {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user