feat: add ProgressBar component #3321
|
@ -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>
|
|
@ -0,0 +1,139 @@
|
|||
<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: #{$size-normal};
|
||||
--progress-bar-background-color: var(--border-light, #{$border-light});
|
||||
--progress-value-background-color: var(--grey-500, #{$text});
|
||||
--progress-border-radius: #{$radius};
|
||||
--progress-indeterminate-duration: 1.5s;
|
||||
|
||||
appearance: none;
|
||||
border: none;
|
||||
border-radius: var(--progress-border-radius);
|
||||
height: var(--progress-height);
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
min-width: 6vw;
|
||||
|
||||
width: 50px;
|
||||
margin: 0 .5rem 0 0;
|
||||
flex: 3 1 auto;
|
||||
|
||||
&::-moz-progress-bar,
|
||||
&::-webkit-progress-value {
|
||||
background: var(--progress-value-background-color);
|
||||
}
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
margin: 0.5rem 0 0 0;
|
||||
order: 1;
|
||||
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 {
|
||||
konrad marked this conversation as resolved
Outdated
|
||||
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} {
|
||||
--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;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-small {
|
||||
--progress-height: #{$size-small};
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveIndeterminate {
|
||||
from {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
to {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
</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
|
||||
class="task-progress"
|
||||
v-if="task.percentDone > 0"
|
||||
:value="task.percentDone * 100" max="100">
|
||||
{{ task.percentDone * 100 }}%
|
||||
</progress>
|
||||
:value="task.percentDone * 100"
|
||||
/>
|
||||
|
||||
<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'
|
||||
|
@ -187,11 +189,6 @@ $task-background: var(--white);
|
|||
word-break: break-word;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 8px 0 0 0;
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
.due-date {
|
||||
float: right;
|
||||
|
@ -331,4 +328,10 @@ $task-background: var(--white);
|
|||
.kanban-card__done {
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
.task-progress {
|
||||
margin: 8px 0 0 0;
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
}
|
||||
</style>
|
|
@ -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 {
|
||||
|
|
|
@ -182,9 +182,5 @@ const project = computed(() => projectStore.projects[task.projectId])
|
|||
color: var(--grey-500);
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
// overwrite bulma
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.noborder {
|
||||
margin: 1rem -0.5rem;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
konrad
commented
Isn't this still used? Isn't this still used?
dpschen
commented
Yes. Right now. Will remove here and instead move to follow up pr Yes. Right now. Will remove here and instead move to follow up pr
|
||||
}
|
||||
|
||||
.is-strikethrough {
|
||||
|
|
Reference in New Issue
Why the different rules instead of something like
This would be dropped by some browsers because prefixed selectors need individual rules, because invalid rules might make the whole selector invalid.
yeah okay that makes sense