feature/move-styles-to-components (#874)
continuous-integration/drone/push Build is failing Details

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #874
Co-authored-by: dpschen <dpschen@noreply.kolaente.de>
Co-committed-by: dpschen <dpschen@noreply.kolaente.de>
This commit is contained in:
dpschen 2021-10-21 19:11:17 +00:00 committed by konrad
parent e0fe8dc673
commit 5dcb1dd449
105 changed files with 3451 additions and 3296 deletions

View File

@ -117,3 +117,33 @@ export default defineComponent({
},
})
</script>
<style lang="scss">
@import '@/styles/global.scss';
</style>
<style lang="scss" scoped>
.offline {
background: url('@/assets/llama-nightscape.jpg') no-repeat center;
background-size: cover;
height: 100vh;
.offline-message {
text-align: center;
position: absolute;
width: 100vw;
bottom: 5vh;
color: $white;
padding: 0 1rem;
h1 {
font-weight: bold;
font-size: 1.5rem;
text-align: center;
color: $white;
font-weight: 700 !important;
font-size: 1.5rem;
}
}
}
</style>

View File

@ -132,3 +132,74 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.app-container {
min-height: calc(100vh - 65px);
@media screen and (max-width: $tablet) {
padding-top: $navbar-height;
}
.app-content {
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
z-index: 2;
@media screen and (max-width: $tablet) {
margin-left: 0;
padding-top: 1.5rem;
min-height: calc(100vh - 4rem);
}
&.is-menu-enabled {
margin-left: $navbar-width;
@media screen and (max-width: $tablet) {
min-width: 100%;
margin-left: 0;
}
}
&.task\.detail {
padding-left: 0;
padding-right: 0;
}
.card {
background: $white;
}
}
}
.mobile-overlay {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(250, 250, 250, 0.8);
z-index: 5;
opacity: 0;
transition: all $transition;
@media screen and (max-width: $tablet) {
display: block;
opacity: 1;
}
}
.keyboard-shortcuts-button {
position: fixed;
bottom: calc(1rem - 4px);
right: 1rem;
z-index: 4500; // The modal has a z-index of 4000
color: $grey-500;
transition: color $transition;
@media screen and (max-width: $tablet) {
display: none;
}
}
</style>

View File

@ -42,3 +42,34 @@ export default {
}),
}
</script>
<style lang="scss" scoped>
.link-share-container.has-background .view {
background: transparent;
border: none;
.logout .button {
box-shadow: none;
}
}
.link-share-view {
.logo {
max-width: 300px;
width: 90%;
margin: 2rem 0 1.5rem;
}
.column {
max-width: 100%;
}
.card {
background: $white;
}
.title {
text-shadow: 0 0 1rem $white;
}
}
</style>

View File

@ -65,3 +65,17 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.no-auth-wrapper {
background: url('@/assets/llama.svg') no-repeat bottom left fixed $light-background;
min-height: 100vh;
}
.noauth-container {
max-width: 450px;
width: 100%;
margin: 0 auto;
padding: 1rem;
}
</style>

View File

@ -275,7 +275,293 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
$navbar-padding: 2rem;
$vikunja-nav-background: $light-background;
$vikunja-nav-color: $grey-700;
$vikunja-nav-selected-width: 0.4rem;
.namespace-container {
background: $vikunja-nav-background;
z-index: 6;
color: $vikunja-nav-color;
padding: 0;
transition: all $transition;
position: fixed;
bottom: 0;
top: $navbar-height;
overflow-x: auto;
width: $navbar-width;
padding: 0 0 1rem;
left: -147vw;
bottom: 0;
@media screen and (max-width: $tablet) {
top: 0;
width: 70vw;
}
&.is-active {
left: 0;
}
.menu {
.menu-label {
font-size: 1rem;
font-weight: 700;
font-weight: bold;
font-family: $vikunja-font;
color: $vikunja-nav-color;
font-weight: 500;
min-height: 2.5rem;
padding-top: 0;
padding-left: $navbar-padding;
overflow: hidden;
}
.menu-label,
.menu-list span.list-menu-link,
.menu-list a {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
.list-menu-title {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.color-bubble {
height: 12px;
flex: 0 0 12px;
}
.favorite {
margin-left: .25rem;
transition: opacity $transition, color $transition;
opacity: 0;
&:hover {
color: $orange;
}
&.is-favorite {
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
}
.menu-label {
.color-bubble {
width: 14px !important;
height: 14px !important;
}
.is-archived {
min-width: 85px;
}
}
.namespace-title {
display: flex;
align-items: center;
justify-content: space-between;
.menu-label {
margin-bottom: 0;
flex: 1 1 auto;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
a:not(.dropdown-item) {
color: $vikunja-nav-color;
padding: 0 .25rem;
}
:deep(.dropdown-trigger) {
padding: .5rem;
cursor: pointer;
}
.toggle-lists-icon {
svg {
transition: all $transition;
transform: rotate(90deg);
opacity: 1;
}
&.active svg {
transform: rotate(0deg);
opacity: 0;
}
}
&:hover .toggle-lists-icon svg {
opacity: 1;
}
&:not(.has-menu) .toggle-lists-icon {
padding-right: 1rem;
}
}
.menu-label,
.nsettings,
.menu-list span.list-menu-link,
.menu-list a {
color: $vikunja-nav-color;
}
.menu-list {
li {
height: 44px;
display: flex;
align-items: center;
&:hover {
background: $white;
}
:deep(.dropdown-trigger) {
opacity: 0;
padding: .5rem;
cursor: pointer;
transition: $transition;
}
&:hover :deep(.dropdown-trigger) {
opacity: 1;
}
&.loader-container.is-loading:after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
}
.flip-list-move {
transition: transform $transition-duration;
}
.ghost {
background: $grey-200;
* {
opacity: 0;
}
}
a:hover {
background: transparent;
}
span.list-menu-link, li > a {
padding: 0.75rem .5rem 0.75rem ($navbar-padding * 1.5 - 1.75rem);
transition: all 0.2s ease;
border-radius: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
border-left: $vikunja-nav-selected-width solid transparent;
.icon {
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
&.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
}
&:hover .icon.handle {
opacity: 1;
}
&.router-link-exact-active {
color: $primary;
border-left: $vikunja-nav-selected-width solid $primary;
.icon {
color: $primary;
}
}
&:hover {
border-left: $vikunja-nav-selected-width solid $primary;
}
}
}
.logo {
display: none;
@media screen and (max-width: $tablet) {
display: block;
}
}
&.namespaces-lists {
padding-top: math.div($navbar-padding, 2);
}
&.loader-container.is-loading:after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
.icon {
color: $grey-400 !important;
}
}
.top-menu {
margin-top: math.div($navbar-padding, 2);
.menu-list {
li {
font-weight: 500;
font-family: $vikunja-font;
}
span.list-menu-link, li > a {
padding-left: 2rem;
display: inline-block;
.icon {
padding-bottom: .25rem;
}
}
}
}
}
.list-setting-spacer {
width: 32px;
flex-shrink: 0;

View File

@ -149,3 +149,152 @@ export default {
},
}
</script>
<style lang="scss" scoped>
$vikunja-nav-logo-full-width: 164px;
.navbar {
z-index: 4 !important;
.navbar-brand {
display: flex;
align-items: center;
.logo img {
width: $vikunja-nav-logo-full-width;
}
}
&.is-dark .navbar-brand > .navbar-item {
@media screen and (max-width: $tablet) {
margin: 0 auto;
}
}
}
.navbar.main-theme {
background: $light-background;
z-index: 5 !important;
justify-content: space-between;
align-items: center;
@media screen and (max-width: $desktop) {
display: flex;
justify-content: space-between;
}
.title {
margin: 0;
font-size: 1.75rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.navbar-end {
margin-left: 0;
align-items: center;
display: flex;
}
@media screen and (max-width: $tablet) {
.navbar-brand {
display: none;
}
.user {
width: $user-dropdown-width-mobile;
display: flex;
align-items: center;
:deep(.dropdown-trigger) {
line-height: 1;
.button {
padding: 0 0.25rem;
height: 1rem;
.icon {
width: .5rem;
}
}
}
.username {
display: none;
}
}
}
}
.navbar {
// FIXME: notifications should provide a slot for the icon instead, so that we can style it as we want
:deep() {
.trigger-button {
cursor: pointer;
color: $grey-400;
padding: .5rem;
font-size: 1.25rem;
position: relative;
}
> * > .trigger-button {
width: $navbar-icon-width;
}
}
.user {
display: flex;
align-items: center;
span {
font-family: $vikunja-font;
}
.avatar {
border-radius: 100%;
vertical-align: middle;
height: 40px;
}
:deep(.dropdown-trigger .button) {
background: none;
&:focus:not(:active), &:active {
outline: none !important;
box-shadow: none !important;
}
}
}
}
.list-title {
display: flex;
align-items: center;
justify-content: center;
$edit-icon-width: 1rem;
@media screen and (min-width: $tablet) {
// We need a fixed width for overflowing ellipsis to work
--nav-username-width: 0;
width: calc(100vw - #{$user-dropdown-width-mobile} - #{2 * $hamburger-menu-icon-spacing} - #{$hamburger-menu-icon-width} - #{$edit-icon-width} - #{2 * $navbar-icon-width} - #{$vikunja-nav-logo-full-width} - var(--nav-username-width));
}
@media screen and (max-width: $tablet) {
// We need a fixed width for overflowing ellipsis to work
width: calc(100vw - #{$user-dropdown-width-mobile} - #{2 * $hamburger-menu-icon-spacing} - #{$hamburger-menu-icon-width} - #{$edit-icon-width} - #{2 * $navbar-icon-width});
}
h1 {
margin: 0;
}
:deep(.dropdown-trigger) {
color: $grey-400;
margin-left: 1rem;
height: 1rem;
width: 1rem;
cursor: pointer;
}
}
</style>

View File

@ -47,3 +47,42 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.update-notification {
margin: 1rem;
display: flex;
align-items: center;
background: $warning;
padding: 0 0 0 .5rem;
border-radius: $radius;
font-size: .9rem;
color: $grey-900;
justify-content: space-between;
@media screen and (max-width: $desktop) {
position: fixed;
bottom: 1rem;
margin: 0;
width: 450px;
left: calc(50vw - 225px);
}
@media screen and (max-width: $tablet) {
position: fixed;
left: 1rem;
right: 1rem;
bottom: 1rem;
width: auto;
}
p {
text-align: center;
width: 100%;
}
> * + * {
margin-left: .5rem;
}
}
</style>

View File

@ -72,4 +72,46 @@ export default {
},
},
}
</script>
</script>
<style lang="scss" scoped>
.button {
transition: all $transition;
border: 0;
text-transform: uppercase;
font-size: 0.85rem;
font-weight: bold;
height: $button-height;
box-shadow: $shadow-sm;
&.is-hovered,
&:hover {
box-shadow: $shadow-md;
}
&.fullheight {
padding-right: 7px;
height: 100%;
}
&.is-active,
&.is-focused,
&:active,
&:focus,
&:focus:not(:active) {
box-shadow: $shadow-xs !important;
}
&.is-primary.is-outlined:hover {
color: $white;
}
&.is-small {
border-radius: $radius;
}
}
.underline-none {
text-decoration: none !important;
}
</style>

View File

@ -99,4 +99,55 @@ export default {
},
},
}
</script>
</script>
<style lang="scss" scoped>
.color-picker-container {
display: flex;
justify-content: center;
align-items: center;
// reset / see https://stackoverflow.com/a/11471224/15522256
input[type="color"] {
-webkit-appearance: none;
border: none;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch {
border: none;
}
$PICKER_SIZE: 24px;
$BORDER_WIDTH: 1px;
.picker {
display: grid;
width: $PICKER_SIZE;
height: $PICKER_SIZE;
overflow: hidden;
border-radius: 100%;
border: $BORDER_WIDTH solid $grey-300;
box-shadow: $shadow;
& > * {
grid-row: 1;
grid-column: 1;
}
}
input.picker__input {
padding: 0;
width: $PICKER_SIZE - 2 * $BORDER_WIDTH;
height: $PICKER_SIZE - 2 * $BORDER_WIDTH;
}
.picker__input.is-empty {
opacity: 0;
}
.picker__pattern {
pointer-events: none;
}
}
</style>

View File

@ -243,3 +243,74 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.datepicker {
input.input {
display: none;
}
&.disabled a {
cursor: default;
}
.datepicker-popup {
position: absolute;
z-index: 99;
width: 320px;
background: $white;
border-radius: $radius;
box-shadow: $shadow;
@media screen and (max-width: ($tablet)) {
width: calc(100vw - 5rem);
}
a:not(.button) {
display: flex;
align-items: center;
padding: 0 .5rem;
width: 100%;
height: 2.25rem;
color: $text;
transition: all $transition;
&:first-child {
border-radius: $radius $radius 0 0;
}
&:hover {
background: $light;
}
.text {
width: 100%;
font-size: .85rem;
display: flex;
justify-content: space-between;
padding-right: .25rem;
.weekday {
color: $text-light;
text-transform: capitalize;
}
}
.icon {
width: 2rem;
text-align: center;
}
}
a.button {
margin: 1rem;
width: calc(100% - 2rem);
}
:deep(.flatpickr-calendar) {
margin: 0 auto 8px;
box-shadow: none;
}
}
}
</style>

View File

@ -312,6 +312,8 @@ export default {
@import './vue-easymde/vue-easymde.css';
@import 'highlight.js/scss/base16/equilibrium-gray-light';
$editor-border-color: #ddd;
.editor {
.clear {
clear: both;
@ -371,7 +373,7 @@ export default {
}
}
&:after {
&::after {
position: absolute;
top: 24px;
margin-left: -3px;
@ -396,7 +398,7 @@ ul.actions {
li {
display: inline-block;
&:after {
&::after {
content: '·';
padding: 0 .25rem;
}

View File

@ -5,7 +5,6 @@
:disabled="disabled || null"
:id="checkBoxId"
@change="(event) => updateData(event.target.checked)"
style="display: none;"
type="checkbox"/>
<label :for="checkBoxId" class="check">
<svg height="18px" viewBox="0 0 18 18" width="18px">
@ -60,3 +59,84 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.fancycheckbox {
display: inline-block;
padding-right: 5px;
padding-top: 3px;
// FIXME: should be a prop
&.is-block {
margin: .5rem .2rem;
}
}
input[type=checkbox] {
display: none;
}
.check {
cursor: pointer;
position: relative;
margin: auto;
width: 18px;
height: 18px;
-webkit-tap-highlight-color: transparent;
transform: translate3d(0, 0, 0);
}
span {
font-size: 0.8rem;
vertical-align: top;
padding-left: .5rem;
}
svg {
position: relative;
z-index: 1;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke: #c8ccd4;
stroke-width: 1.5;
transform: translate3d(0, 0, 0);
transition: all 0.2s ease;
}
.check:hover svg {
stroke: $primary;
}
.is-disabled .check:hover svg {
stroke: #c8ccd4;
}
path {
stroke-dasharray: 60;
stroke-dashoffset: 0;
}
polyline {
stroke-dasharray: 22;
stroke-dashoffset: 66;
}
input[type=checkbox]:checked + .check {
svg {
stroke: $primary;
}
path {
stroke-dashoffset: 60;
transition: all 0.3s linear;
}
polyline {
stroke-dashoffset: 42;
transition: all 0.2s linear;
transition-delay: 0.15s;
}
}
</style>

View File

@ -365,3 +365,131 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.multiselect {
width: 100%;
position: relative;
.control.is-loading::after {
top: .75rem;
}
&.has-search-results .input-wrapper {
border-radius: $radius $radius 0 0;
border-color: $primary !important;
background: $white !important;
&, &:focus-within {
border-bottom-color: $grey-200 !important;
}
}
.input-wrapper {
padding: 0;
background: $white !important;
border-color: $grey-200 !important;
flex-wrap: wrap;
height: auto;
&:hover {
border-color: $grey-300 !important;
}
.input {
display: flex;
max-width: 100%;
width: 100%;
align-items: center;
border: none !important;
background: transparent;
height: auto;
&::placeholder {
font-style: normal !important;
}
}
&.has-multiple .input {
max-width: 250px;
input {
padding-left: 0;
}
}
&:focus-within {
border-color: $primary !important;
background: $white !important;
}
.loader {
margin: 0 .5rem;
}
}
.search-results {
background: $white;
border-radius: 0 0 $radius $radius;
border: 1px solid $primary;
border-top: none;
max-height: 50vh;
overflow-x: auto;
position: absolute;
z-index: 100;
max-width: 100%;
min-width: 100%;
&-inline {
position: static;
}
button {
background: transparent;
display: block;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem 0;
border: none;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.search-result {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: .5rem .75rem;
}
.hint-text {
font-size: .75rem;
color: transparent;
transition: color $transition;
padding: 0 .5rem;
}
&:focus, &:hover {
background: $grey-100;
box-shadow: none !important;
.hint-text {
color: $text;
}
}
&:active {
background: $grey-200;
}
}
}
}
</style>

View File

@ -81,3 +81,132 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.list-card {
cursor: pointer;
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
height: $list-height;
background: $white;
margin: 0 $list-spacing $list-spacing 0;
padding: 1rem;
border-radius: $radius;
box-shadow: $shadow-sm;
transition: box-shadow $transition;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
&:hover {
box-shadow: $shadow-md;
}
&:active,
&:focus,
&:focus:not(:active) {
box-shadow: $shadow-xs !important;
}
@media screen and (min-width: $widescreen) {
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $widescreen) and (min-width: $tablet) {
$lists-per-row: 3;
& {
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
}
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $tablet) {
$lists-per-row: 2;
& {
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
}
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $mobile) {
$lists-per-row: 1;
& {
width: 100%;
margin-right: 0;
}
}
.is-archived-container {
width: 100%;
text-align: right;
.is-archived {
font-size: .75rem;
float: left;
}
}
.title {
align-self: flex-end;
font-family: $vikunja-font;
font-weight: 400;
font-size: 1.5rem;
color: $text;
width: 100%;
margin-bottom: 0;
max-height: calc(100% - 2rem); // 1rem padding, 1rem height of the "is archived" badge
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
&.has-light-text .title {
color: $light;
}
&.has-background {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
.title {
text-shadow: 0 0 10px $black, 1px 1px 5px $grey-700, -1px -1px 5px $grey-700;
color: $white;
}
}
.favorite {
transition: opacity $transition, color $transition;
opacity: 0;
&:hover {
color: $orange;
}
&.is-archived {
display: none;
}
&.is-favorite {
display: inline-block;
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
}
</style>

View File

@ -171,3 +171,85 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.migration-in-progress-container {
max-width: 400px;
margin: 4rem auto 0;
text-align: center;
}
.migration-in-progress {
text-align: center;
display: flex;
max-width: 400px;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
img {
display: block;
max-height: 100px;
}
.progress-dots {
height: 40px;
width: 140px;
overflow: visible;
span {
transition: all 500ms ease;
background: $grey-500;
height: 10px;
width: 10px;
display: inline-block;
border-radius: 10px;
animation: wave 2s ease infinite;
margin-right: 5px;
&:nth-child(1) {
animation-delay: 0;
}
&:nth-child(2) {
animation-delay: 100ms;
}
&:nth-child(3) {
animation-delay: 200ms;
}
&:nth-child(4) {
animation-delay: 300ms;
}
&:nth-child(5) {
animation-delay: 400ms;
}
&:nth-child(6) {
animation-delay: 500ms;
}
&:nth-child(7) {
animation-delay: 600ms;
}
&:nth-child(8) {
animation-delay: 700ms;
}
}
}
@keyframes wave {
0%, 40%, 100% {
transform: translate(0, 0);
background-color: $primary;
}
10% {
transform: translate(0, -15px);
background-color: $primary-dark;
}
}
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<div
v-if="isDone"
class="is-done"
:class="{ 'is-done--small': variant === variants.SMALL }"
>
{{ $t('task.attributes.done') }}
</div>
</template>
<script>
const VARIANTS = {
DEFAULT: 'default',
SMALL: 'small',
}
export default {
name: 'Done',
data() {
return {
variants: VARIANTS,
}
},
props: {
isDone: {
type: Boolean,
default: false,
},
variant: {
type: String,
default: VARIANTS.DEFAULT,
validator: (variant) => Object.values(VARIANTS).includes(variant),
},
},
}
</script>
<style lang="scss" scoped>
.is-done {
background: $green;
color: $white;
padding: .5rem;
font-weight: bold;
line-height: 1;
border-radius: 4px;
text-align: center;
}
.is-done--small {
padding: .2rem .3rem;
}
</style>

View File

@ -197,3 +197,18 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.api-config {
margin-bottom: .75rem;
}
.api-url-info {
font-size: .9rem;
text-align: right;
span.url {
border-bottom: 1px dashed $primary;
}
}
</style>

View File

@ -54,3 +54,25 @@ export default {
emits: ['close'],
}
</script>
<style lang="scss" scoped>
.card {
background-color: $white;
border-radius: $radius;
margin-bottom: 1rem;
border: 1px solid $grey-200;
box-shadow: $shadow-sm;
}
.card-header {
box-shadow: none;
border-bottom: 1px solid $grey-200;
border-radius: $radius $radius 0 0;
}
// FIXME: should maybe be merged somehow with modal
:deep(.modal-card-foot) {
background-color: $grey-50;
border-top: 0;
}
</style>

View File

@ -17,3 +17,12 @@ export default {
}),
}
</script>
<style lang="scss" scoped>
.legal-links {
margin-top: 1rem;
text-align: right;
color: $grey-300;
font-size: 1rem;
}
</style>

View File

@ -181,7 +181,7 @@ export default {
.hint-modal {
z-index: 4600;
::v-deep.card-content {
:deep(.card-content) {
text-align: left;
.info {

View File

@ -133,3 +133,113 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.notifications {
width: $navbar-icon-width;
.unread-indicator {
position: absolute;
top: .75rem;
right: 1.15rem;
width: .75rem;
height: .75rem;
background: $primary;
border-radius: 100%;
border: 2px solid $white;
}
.notifications-list {
position: fixed;
right: 1rem;
margin-top: 1rem;
max-height: 400px;
overflow-y: auto;
background: $white;
width: 350px;
max-width: calc(100vw - 2rem);
padding: .75rem .25rem;
border-radius: $radius;
box-shadow: $shadow-sm;
font-size: .85rem;
@media screen and (max-width: $tablet) {
max-height: calc(100vh - 1rem - #{$navbar-height});
}
.head {
font-family: $vikunja-font;
font-size: 1rem;
padding: .5rem;
}
.single-notification {
display: flex;
align-items: center;
padding: 0.25rem 0;
transition: background-color $transition;
&:hover {
background: $grey-100;
border-radius: $radius;
}
.read-indicator {
width: .35rem;
height: .35rem;
background: $primary;
border-radius: 100%;
margin-left: .5rem;
&.read {
background: transparent;
}
}
.user {
display: inline-flex;
align-items: center;
width: auto;
margin: 0 .5rem;
span {
font-family: $family-sans-serif;
}
.avatar {
height: 16px;
}
img {
margin-right: 0;
}
}
.created {
color: $grey-400;
}
&:last-child {
margin-bottom: .25rem;
}
a {
color: $grey-800;
}
}
.nothing {
text-align: center;
padding: 1rem 0;
color: $grey-500;
.explainer {
font-size: .75rem;
}
}
}
}
</style>

View File

@ -463,16 +463,75 @@ export default {
<style lang="scss" scoped>
.quick-actions {
// FIXME: changed position should be an option of the modal
::v-deep.modal-content {
:deep(.modal-content) {
top: 3rem;
transform: translate(-50%, 0);
}
.action-input {
display: flex;
align-items: center;
.input {
border: 0;
font-size: 1.5rem;
}
&.has-active-cmd .input {
padding-left: .5rem;
}
.active-cmd {
font-size: 1.25rem;
margin-left: .5rem;
}
}
.results {
text-align: left;
width: 100%;
color: $grey-800;
.result {
&-title {
background: $grey-50;
padding: .5rem;
display: block;
font-size: .75rem;
}
&-items {
button {
font-size: .9rem;
width: 100%;
background: transparent;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem .75rem;
border: none;
cursor: pointer;
&:focus, &:hover {
background: $grey-50;
box-shadow: none !important;
}
&:active {
background: $grey-100;
}
}
}
}
}
}
// HACK:
// FIXME:
.modal-container-smaller ::v-deep.hint-modal .modal-container {
.modal-container-smaller :deep(.hint-modal .modal-container) {
height: calc(100vh - 5rem);
}
</style>
</style>

View File

@ -258,3 +258,10 @@ export default {
},
}
</script>
<style lang="scss" scoped>
// FIXME: I think this is not needed
.sharables-list:not(.card-content) {
overflow-y: auto
}
</style>

View File

@ -71,7 +71,7 @@
<div class="select">
<select
@change="toggleType(s)"
class="button mr-2"
class="mr-2"
v-model="selectedRight[s.id]"
>
<option

View File

@ -142,3 +142,36 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.priority-select {
.select,
select {
width: 100%;
}
}
ul.assingees {
list-style: none;
margin: 0;
li {
padding: 0.5rem 0.5rem 0;
a {
float: right;
color: $red;
transition: all $transition;
}
}
}
.tag {
margin-right: 0.5rem;
margin-bottom: 0.5rem;
&:last-child {
margin-right: 0;
}
}
</style>

View File

@ -445,3 +445,198 @@ export default {
},
}
</script>
<style lang="scss" scoped>
$gantt-border: 1px solid $grey-200;
$gantt-vertical-border-color: $grey-100;
.gantt-chart {
overflow-x: auto;
border-top: 1px solid $grey-200;
.dates {
display: flex;
text-align: center;
.months {
display: flex;
.month {
padding: 0.5rem 0 0;
border-right: $gantt-border;
font-family: $vikunja-font;
font-weight: bold;
&:last-child {
border-right: none;
}
.days {
display: flex;
.day {
padding: 0.5rem 0;
font-weight: normal;
&.today {
background: $primary;
color: $white;
border-radius: 5px 5px 0 0;
font-weight: bold;
}
.theday {
padding: 0 .5rem;
width: 100%;
display: block;
}
.weekday {
font-size: 0.8rem;
}
}
}
}
}
}
.tasks {
max-width: unset !important;
margin: 0;
border-top: $gantt-border;
.row {
height: 45px;
.task {
display: inline-block;
border: 2px solid $primary;
font-size: 0.85rem;
margin: 0.5rem;
border-radius: 6px;
padding: 0.25rem 0.5rem;
cursor: grab;
position: relative;
height: 31px !important;
-webkit-touch-callout: none; // iOS Safari
user-select: none; // Non-prefixed version
&.is-current-edit {
border-color: $orange !important;
}
&.has-light-text {
color: $light;
&.done span:after {
border-top: 1px solid $light;
}
.edit-toggle {
color: $light;
}
}
&.has-dark-text {
color: $text;
&.done span:after {
border-top: 1px solid $dark;
}
.edit-toggle {
color: $text;
}
}
&.done span {
position: relative;
&::after {
content: '';
position: absolute;
right: 0;
left: 0;
top: 57%;
}
}
span:not(.high-priority) {
max-width: calc(100% - 20px);
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
&.has-high-priority {
max-width: calc(100% - 90px);
}
&.has-not-so-high-priority {
max-width: calc(100% - 70px);
}
&.has-super-high-priority {
max-width: calc(100% - 111px);
}
&.icon {
width: 10px;
text-align: center;
}
}
.high-priority {
margin: 0 0 0 .5rem;
vertical-align: bottom;
}
.edit-toggle {
float: right;
cursor: pointer;
margin-right: 4px;
}
&.nodate {
border: 2px dashed $grey-300;
background: $grey-100;
}
&:active {
cursor: grabbing;
}
}
}
}
.taskedit {
position: fixed;
min-height: 0;
top: 10vh;
right: 10vw;
z-index: 5;
// FIXME: should be an option of the card, e.g. overflow
:deep(.card-content) {
max-height: 60vh;
overflow-y: auto;
}
}
.add-new-task {
padding: 1rem .7rem .4rem .7rem;
display: flex;
max-width: 450px;
.input {
margin-right: .7rem;
font-size: .8rem;
}
.button {
font-size: .68rem;
}
}
}
</style>

View File

@ -249,3 +249,137 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.attachments {
input[type=file] {
display: none;
}
.files {
margin-bottom: 1rem;
.attachment {
margin-bottom: .5rem;
display: block;
transition: background-color $transition;
border-radius: $radius;
padding: .5rem;
&:hover {
background-color: $grey-200;
}
.filename {
font-weight: bold;
margin-bottom: .25rem;
color: $text;
}
.info {
color: $grey-500;
font-size: .9rem;
p {
margin-bottom: 0;
display: flex;
> span:not(:last-child):after,
> a:not(:last-child):after {
content: '·';
padding: 0 .25rem;
}
@media screen and (max-width: $mobile) {
&.collapses {
flex-direction: column;
> span:not(:last-child):after,
> a:not(:last-child):after {
display: none;
}
.user .username {
display: none;
}
}
}
}
}
}
}
@media screen and (max-width: $tablet) {
.button {
width: 100%;
}
}
.dropzone {
position: fixed;
background: rgba(250, 250, 250, 0.8);
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 100;
text-align: center;
&.hidden {
display: none;
}
.drop-hint {
position: absolute;
bottom: 0;
left: 0;
right: 0;
.icon {
width: 100%;
font-size: 5rem;
height: auto;
text-shadow: $shadow-md;
animation: bounce 2s infinite;
}
.hint {
margin: .5rem auto 2rem;
border-radius: 2px;
box-shadow: $shadow-md;
background: $primary;
padding: 1rem;
color: $white;
width: 100%;
max-width: 300px;
}
}
}
}
@keyframes bounce {
from,
20%,
53%,
80%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translate3d(0, 0, 0);
}
40%,
43% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -30px, 0);
}
70% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0, -4px, 0);
}
}
</style>

View File

@ -304,3 +304,49 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.media.comment {
align-items: center;
.media-left {
margin: 0 1rem;
}
.comment-info {
display: flex;
align-items: center;
* {
padding-right: .5rem;
}
img {
display: none;
@media screen and (max-width: $tablet) {
display: block;
width: 20px;
height: 20px;
padding-right: 0;
margin-right: .5rem;
}
}
span {
font-size: .75rem;
line-height: 1;
}
}
.editor {
margin-top: .5rem;
}
}
.media-content {
width: calc(100% - 48px - 2rem);
}
</style>

View File

@ -131,3 +131,62 @@ export default {
},
}
</script>
<style lang="scss" scoped>
// 100px is roughly the size the pane is pulled to the right
$defer-task-max-width: 350px + 100px;
.defer-task {
position: absolute;
width: 100%;
max-width: $defer-task-max-width;
border-radius: $radius;
border: 1px solid $grey-200;
padding: 1rem;
margin: 1rem;
background: $white;
color: $text;
cursor: default;
z-index: 10;
box-shadow: $shadow-lg;
@media screen and (max-width: ($defer-task-max-width)) {
left: .5rem;
right: .5rem;
max-width: 100%;
width: calc(100vw - 1rem - 2rem);
}
}
.defer-days {
justify-content: space-between;
display: flex;
margin: .5rem 0;
}
:deep() {
input.input {
display: none;
}
.flatpickr-calendar {
margin: 0 auto;
box-shadow: none;
@media screen and (max-width: ($defer-task-max-width)) {
max-width: 100%;
}
span {
width: auto !important;
}
}
.flatpickr-innerContainer {
@media screen and (max-width: ($defer-task-max-width)) {
overflow: scroll;
}
}
}
</style>

View File

@ -117,3 +117,33 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.assignee {
position: relative;
&:not(:first-child) {
margin-left: -1.5rem;
}
:deep(.user img) {
border: 2px solid $white;
margin-right: 0;
}
.remove-assignee {
position: absolute;
top: 4px;
left: 2px;
color: $red;
background: $white;
padding: 0 4px;
display: block;
border-radius: 100%;
font-size: .75rem;
width: 18px;
height: 18px;
z-index: 100;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="heading">
<h1 class="title task-id">{{ textIdentifier }}</h1>
<div class="is-done" v-if="task.done">Done</div>
<Done class="heading__done" :is-done="task.done" />
<h1
class="title input"
:class="{'disabled': !canWrite}"
@ -28,8 +28,13 @@
<script>
import {mapState} from 'vuex'
import Done from '@/components/misc/Done.vue'
export default {
name: 'heading',
components: {
Done,
},
data() {
return {
showSavedMessage: false,
@ -90,3 +95,8 @@ export default {
}
</script>
<style lang="scss" scoped>
.heading__done {
margin-left: .5rem;
}
</style>

View File

@ -12,7 +12,7 @@
class="task loader-container draggable"
>
<span class="task-id">
<span class="is-done" v-if="task.done">Done</span>
<Done class="kanban-card__done" :is-done="task.done" variant="small" />
<template v-if="task.identifier === ''">
#{{ task.index }}
</template>
@ -66,6 +66,7 @@
import {playPop} from '../../../helpers/playPop'
import PriorityLabel from '../../../components/tasks/partials/priorityLabel'
import User from '../../../components/misc/user'
import Done from '@/components/misc/Done.vue'
import Labels from '../../../components/tasks/partials/labels'
import ChecklistSummary from './checklist-summary'
@ -73,6 +74,7 @@ export default {
name: 'kanban-card',
components: {
ChecklistSummary,
Done,
PriorityLabel,
User,
Labels,
@ -110,3 +112,156 @@ export default {
},
}
</script>
<style lang="scss" scoped>
$task-background: $white;
.task {
-webkit-touch-callout: none; // iOS Safari
user-select: none;
cursor: pointer;
box-shadow: $shadow-xs;
display: block;
border: 3px solid transparent;
font-size: .9rem;
margin: .5rem;
padding: .4rem;
border-radius: $radius;
background: $task-background;
&.loader-container.is-loading::after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
h3 {
font-family: $family-sans-serif;
font-size: .85rem;
word-break: break-word;
}
.progress {
margin: 8px 0 0 0;
width: 100%;
height: 0.5rem;
}
.due-date {
float: right;
display: flex;
align-items: center;
.icon {
margin-right: .25rem;
}
&.overdue {
color: $red;
}
}
.label-wrapper .tag {
margin: .5rem .5rem 0 0;
}
.footer {
background: transparent;
padding: 0;
display: flex;
flex-wrap: wrap;
align-items: center;
:deep(.tag),
.assignees,
.icon,
.priority-label {
margin-top: .25rem;
margin-right: .25rem;
}
.assignees {
display: flex;
.user {
display: inline;
margin: 0;
img {
margin: 0;
}
}
}
// FIXME: should be in labels.vue
:deep(.tag) {
margin-left: 0;
}
.priority-label {
font-size: .75rem;
height: 2rem;
.icon {
height: 1rem;
padding: 0 .25rem;
margin-top: 0;
}
}
}
.footer .icon,
.due-date,
.priority-label {
background: $grey-100;
border-radius: $radius;
padding: 0 .5rem;
}
.due-date {
padding: 0 .25rem;
}
.task-id {
color: $grey-500;
font-size: .8rem;
margin-bottom: .25rem;
display: flex;
}
&.is-moving {
opacity: .5;
}
span {
width: auto;
}
&.has-light-text {
color: $white;
.task-id {
color: $grey-200;
}
.footer .icon,
.due-date,
.priority-label {
background: $grey-800;
}
.footer {
.icon svg {
fill: $white;
}
}
}
}
.kanban-card__done {
margin-right: .25rem;
}
</style>

View File

@ -21,8 +21,14 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
.label-wrapper {
display: inline;
}
.tag {
& + & {
margin-left: 0.5rem;
}
}
</style>

View File

@ -79,3 +79,9 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.list-namespace-title {
color: $grey-500;
}
</style>

View File

@ -248,7 +248,9 @@ export default {
}
</script>
<style lang="scss">
<style lang="scss" scoped>
$remove-icon-width: 24px;
.add-task-relation-button {
margin-top: -3rem;
@ -260,4 +262,72 @@ export default {
transform: rotate(45deg);
}
}
</style>
.task-relations {
&.is-narrow .columns {
display: block;
.column {
width: 100%;
}
}
.different-list {
color: $grey-500;
width: auto;
}
.related-tasks {
.title {
font-size: 1rem;
margin: 0;
}
.tasks {
margin: 0;
a:not(.remove) {
width: calc(100% - #{$remove-icon-width});
}
.task .tasktext {
width: calc(100% - .25rem); // Magic .25rem extra space
}
.remove {
width: $remove-icon-width;
text-align: center;
}
}
.task {
display: flex;
flex-wrap: wrap;
padding: .4rem;
transition: background-color $transition;
align-items: center;
cursor: pointer;
border-radius: $radius;
border: 2px solid transparent;
a {
color: $text;
transition: color ease $transition-duration;
&:hover {
color: $grey-900;
}
}
.remove {
color: $red;
}
}
}
.none {
font-style: italic;
text-align: center;
}
}
</style>

View File

@ -104,3 +104,25 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.reminders {
.reminder-input {
display: flex;
align-items: center;
&.overdue :deep(.datepicker a.show) {
color: $red;
}
&:last-child {
margin-bottom: 0.75rem;
}
a.remove {
color: $red;
padding-left: .5rem;
}
}
}
</style>

View File

@ -30,7 +30,7 @@
{{ task.title }}
</span>
<labels :labels="task.labels"/>
<labels class="labels" :labels="task.labels"/>
<user
:avatar-size="27"
:is-inline="true"
@ -211,3 +211,150 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.task {
display: flex;
flex-wrap: wrap;
padding: .4rem;
transition: background-color $transition;
align-items: center;
cursor: pointer;
border-radius: $radius;
border: 2px solid transparent;
&:hover {
background-color: $grey-100;
}
.tasktext,
&.tasktext {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
flex: 1 0 50%;
.overdue {
color: $red;
}
}
.task-list {
width: auto;
color: $grey-400;
font-size: .9rem;
white-space: nowrap;
}
.color-bubble {
height: 10px;
flex: 0 0 10px;
}
.labels {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.avatar {
border-radius: 50%;
vertical-align: bottom;
margin-left: 5px;
height: 27px;
width: 27px;
}
.list-task-icon {
margin-left: 6px;
&:not(:first-of-type) {
margin-left: 8px;
}
}
a {
color: $text;
transition: color ease $transition-duration;
&:hover {
color: $grey-900;
}
}
.favorite {
opacity: 0;
text-align: center;
width: 27px;
transition: opacity $transition, color $transition;
&:hover {
color: $orange;
}
&.is-favorite {
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
&:hover .handle {
opacity: 1;
}
:deep(.fancycheckbox) {
height: 18px;
padding-top: 0;
padding-right: .5rem;
span {
display: none;
}
}
.tasktext.done {
text-decoration: line-through;
color: $grey-500;
}
span.parent-tasks {
color: $grey-500;
width: auto;
}
.remove {
color: $red;
}
input[type="checkbox"] {
vertical-align: middle;
}
.settings {
float: right;
width: 24px;
cursor: pointer;
}
&.loader-container.is-loading:after {
top: calc(50% - 1rem);
left: calc(50% - 1rem);
width: 2rem;
height: 2rem;
border-left-color: $grey-300;
border-bottom-color: $grey-300;
}
}
</style>

View File

@ -23,8 +23,6 @@ import {formatDate, formatDateShort, formatDateLong, formatDateSince} from '@/he
// @ts-ignore
import {VERSION} from './version.json'
// Add CSS
import './styles/vikunja.scss'
// Notifications
import Notifications from '@kyvg/vue3-notification'

View File

@ -1,25 +0,0 @@
@import 'base/all';
@import 'attachments';
@import 'gantt';
@import 'labels';
@import 'list';
@import 'reminders';
@import 'switch-view';
@import 'task';
@import 'taskRelations';
@import 'tasks';
@import 'teams';
@import 'migrator';
@import 'comments';
@import 'table-view';
@import 'kanban';
@import 'list-backgrounds';
@import 'color-picker';
@import 'namespaces';
@import 'legal';
@import 'keyboard-shortcuts';
@import 'api-config';
@import 'datepicker';
@import 'notifications';
@import 'quick-actions';

View File

@ -0,0 +1,6 @@
@import "tooltip";
@import "labels";
@import "list";
@import "task";
@import "tasks";
@import "namespaces";

View File

@ -1,12 +0,0 @@
.api-config {
margin-bottom: .75rem;
}
.api-url-info {
font-size: .9rem;
text-align: right;
span.url {
border-bottom: 1px dashed $primary;
}
}

View File

@ -1,105 +0,0 @@
.attachments {
input[type=file] {
display: none;
}
.files {
margin-bottom: 1rem;
.attachment {
margin-bottom: .5rem;
display: block;
transition: background-color $transition;
border-radius: $radius;
padding: .5rem;
&:hover {
background-color: $grey-200;
}
.filename {
font-weight: bold;
margin-bottom: .25rem;
color: $text;
}
.info {
color: $grey-500;
font-size: .9rem;
p {
margin-bottom: 0;
display: flex;
> span:not(:last-child):after,
> a:not(:last-child):after {
content: '·';
padding: 0 .25rem;
}
@media screen and (max-width: $mobile) {
&.collapses {
flex-direction: column;
> span:not(:last-child):after,
> a:not(:last-child):after {
display: none;
}
.user .username {
display: none;
}
}
}
}
}
}
}
@media screen and (max-width: $tablet) {
.button {
width: 100%;
}
}
.dropzone {
position: fixed;
background: rgba(250, 250, 250, 0.8);
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 100;
text-align: center;
&.hidden {
display: none;
}
.drop-hint {
position: absolute;
bottom: 0;
left: 0;
right: 0;
.icon {
width: 100%;
font-size: 5rem;
height: auto;
text-shadow: $shadow-md;
animation: bounce 2s infinite;
}
.hint {
margin: .5rem auto 2rem;
border-radius: 2px;
box-shadow: $shadow-md;
background: $primary;
padding: 1rem;
color: $white;
width: 100%;
max-width: 300px;
}
}
}
}

View File

@ -1,5 +0,0 @@
@import 'card';
@import 'fancycheckbox';
@import 'multiselect';
@import 'scrollbars';
@import 'tooltip';

View File

@ -1,27 +0,0 @@
.card {
background-color: $white;
border-radius: $radius;
margin-bottom: 1rem;
.card-image {
img {
border-radius: $radius $radius 0 0;
}
}
.card-header {
box-shadow: none;
border-bottom: 1px solid $grey-200;
border-radius: $radius $radius 0 0;
}
.modal-card-foot {
background: $grey-50;
border-top: 0;
}
}
.box, .card {
border: 1px solid $grey-200;
box-shadow: $shadow-sm;
}

View File

@ -1,75 +0,0 @@
// Fancy Checkboxes
.fancycheckbox {
display: inline-block;
padding-right: 5px;
padding-top: 3px;
input[type=checkbox] {
display: none;
}
&.is-block {
margin: .5rem .2rem;
}
.check {
cursor: pointer;
position: relative;
margin: auto;
width: 18px;
height: 18px;
-webkit-tap-highlight-color: transparent;
transform: translate3d(0, 0, 0);
&:hover svg {
stroke: $primary;
}
span {
font-size: 0.8rem;
vertical-align: top;
padding-left: .5rem;
}
svg {
position: relative;
z-index: 1;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke: #c8ccd4;
stroke-width: 1.5;
transform: translate3d(0, 0, 0);
transition: all 0.2s ease;
path {
stroke-dasharray: 60;
stroke-dashoffset: 0;
}
polyline {
stroke-dasharray: 22;
stroke-dashoffset: 66;
}
}
}
&.is-disabled .check:hover svg {
stroke: #c8ccd4;
}
input[type=checkbox]:checked + .check svg {
stroke: $primary;
}
input[type=checkbox]:checked + .check svg path {
stroke-dashoffset: 60;
transition: all 0.3s linear;
}
input[type=checkbox]:checked + .check svg polyline {
stroke-dashoffset: 42;
transition: all 0.2s linear;
transition-delay: 0.15s;
}
}

View File

@ -1,153 +0,0 @@
.multiselect {
width: 100%;
position: relative;
.control.is-loading::after {
top: .75rem;
}
&.has-search-results .input-wrapper {
border-radius: $radius $radius 0 0;
border-color: $primary !important;
background: $white !important;
&, &:focus-within {
border-bottom-color: $grey-200 !important;
}
}
.input-wrapper {
padding: 0;
background: $white !important;
border-color: $grey-200 !important;
flex-wrap: wrap;
height: auto;
&:hover {
border-color: $grey-300 !important;
}
.input {
display: flex;
max-width: 100%;
width: 100%;
align-items: center;
border: none !important;
background: transparent;
height: auto;
&::placeholder {
font-style: normal !important;
}
}
&.has-multiple .input {
max-width: 250px;
input {
padding-left: 0;
}
}
&:focus-within {
border-color: $primary !important;
background: $white !important;
}
.loader {
margin: 0 .5rem;
}
}
.search-results {
background: $white;
border-radius: 0 0 $radius $radius;
border: 1px solid $primary;
border-top: none;
max-height: 50vh;
overflow-x: auto;
position: absolute;
z-index: 100;
max-width: 100%;
min-width: 100%;
&-inline {
position: static;
}
button {
background: transparent;
display: block;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem 0;
border: none;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.search-result {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: .5rem .75rem;
}
.hint-text {
font-size: .75rem;
color: transparent;
transition: color $transition;
padding: 0 .5rem;
}
&:focus, &:hover {
background: $grey-100;
box-shadow: none !important;
.hint-text {
color: $text;
}
}
&:active {
background: $grey-200;
}
}
}
.assignee {
position: relative;
&:not(:first-child) {
margin-left: -1.5rem;
}
.user img {
border: 2px solid $white;
margin-right: 0;
}
.remove-assignee {
position: absolute;
top: 4px;
left: 2px;
color: $red;
background: $white;
padding: 0 4px;
display: block;
border-radius: 100%;
font-size: .75rem;
width: 18px;
height: 18px;
z-index: 100;
}
}
}

View File

@ -1,48 +0,0 @@
.color-picker-container {
display: flex;
justify-content: center;
align-items: center;
// reset / see https://stackoverflow.com/a/11471224/15522256
input[type="color"] {
-webkit-appearance: none;
border: none;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch {
border: none;
}
$PICKER_SIZE: 24px;
$BORDER_WIDTH: 1px;
.picker {
display: grid;
width: $PICKER_SIZE;
height: $PICKER_SIZE;
overflow: hidden;
border-radius: 100%;
border: $BORDER_WIDTH solid $grey-300;
box-shadow: $card-shadow;
& > * {
grid-row: 1;
grid-column: 1;
}
}
input.picker__input {
padding: 0;
width: $PICKER_SIZE - 2 * $BORDER_WIDTH;
height: $PICKER_SIZE - 2 * $BORDER_WIDTH;
}
.picker__input.is-empty {
opacity: 0;
}
.picker__pattern {
pointer-events: none;
}
}

View File

@ -1,40 +0,0 @@
.media.comment {
align-items: center;
.media-left {
margin: 0 1rem;
}
.comment-info {
display: flex;
align-items: center;
* {
padding-right: .5rem;
}
img {
display: none;
}
@media screen and (max-width: $tablet) {
img {
display: block;
width: 20px;
height: 20px;
padding-right: 0;
margin-right: .5rem;
}
}
span {
font-size: .75rem;
line-height: 1;
}
}
.editor {
margin-top: .5rem;
}
}

View File

@ -1,68 +0,0 @@
.datepicker {
input.input {
display: none;
}
&.disabled a {
cursor: default;
}
.datepicker-popup {
position: absolute;
z-index: 99;
width: 320px;
background: $white;
border-radius: $radius;
box-shadow: $card-shadow;
a:not(.button) {
display: flex;
align-items: center;
padding: 0 .5rem;
width: 100%;
height: 2.25rem;
color: $text;
transition: all $transition;
&:first-child {
border-radius: $radius $radius 0 0;
}
&:hover {
background: $light;
}
.text {
width: 100%;
font-size: .85rem;
display: flex;
justify-content: space-between;
padding-right: .25rem;
.weekday {
color: $text-light;
text-transform: capitalize;
}
}
.icon {
width: 2rem;
text-align: center;
}
}
a.button {
margin: 1rem;
width: calc(100% - 2rem);
}
.flatpickr-calendar {
margin: 0 auto 8px;
box-shadow: none;
}
@media screen and (max-width: ($tablet)) {
width: calc(100vw - 5rem);
}
}
}

View File

@ -1,251 +0,0 @@
$gantt-border: 1px solid $grey-200;
$gantt-vertical-border-color: $grey-100;
.gantt-chart-container {
padding-bottom: 1rem;
}
.gantt-chart {
overflow-x: auto;
border-top: 1px solid $grey-200;
.dates {
display: flex;
text-align: center;
.months {
display: flex;
.month {
padding: 0.5rem 0 0;
border-right: $gantt-border;
font-family: $vikunja-font;
font-weight: bold;
&:last-child {
border-right: none;
}
.days {
display: flex;
.day {
padding: 0.5rem 0;
font-weight: normal;
&.today {
background: $primary;
color: $white;
border-radius: 5px 5px 0 0;
font-weight: bold;
}
.theday {
padding: 0 .5rem;
width: 100%;
display: block;
}
.weekday {
font-size: 0.8rem;
}
}
}
}
}
}
.tasks {
max-width: unset !important;
margin: 0;
border-top: $gantt-border;
.row {
height: 45px;
.task {
display: inline-block;
border: 2px solid $primary;
font-size: 0.85rem;
margin: 0.5rem;
border-radius: 6px;
padding: 0.25rem 0.5rem;
cursor: grab;
position: relative;
height: 31px !important;
user-select: none;
&.is-current-edit {
border-color: $orange !important;
}
&.has-light-text {
color: $light;
&.done span:after {
border-top: 1px solid $light;
}
.edit-toggle {
color: $light;
}
}
&.has-dark-text {
color: $text;
&.done span:after {
border-top: 1px solid $dark;
}
.edit-toggle {
color: $text;
}
}
&.done span {
position: relative;
&:after {
content: '';
position: absolute;
right: 0;
left: 0;
top: 57%;
}
}
span:not(.high-priority) {
max-width: calc(100% - 20px);
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
&.has-high-priority {
max-width: calc(100% - 90px);
}
&.has-not-so-high-priority {
max-width: calc(100% - 70px);
}
&.has-super-high-priority {
max-width: calc(100% - 111px);
}
&.icon {
width: 10px;
text-align: center;
}
}
.high-priority {
margin: 0 0 0 .5rem;
vertical-align: bottom;
}
.edit-toggle {
float: right;
cursor: pointer;
margin-right: 4px;
}
&.nodate {
border: 2px dashed $grey-300;
background: $grey-100;
}
&:active {
cursor: grabbing;
}
}
}
}
.taskedit {
position: fixed;
min-height: 0;
top: 10vh;
right: 10vw;
z-index: 5;
.card-content {
max-height: 60vh;
overflow-y: auto;
}
}
.add-new-task {
padding: 1rem .7rem .4rem .7rem;
display: flex;
max-width: 450px;
.input {
margin-right: .7rem;
font-size: .8rem;
}
.button {
font-size: .68rem;
}
}
}
.gantt-options {
display: flex;
justify-content: space-between;
align-items: center;
@media screen and (max-width: $tablet) {
flex-direction: column;
}
.range-picker {
display: flex;
margin-bottom: 1rem;
width: 50%;
@media screen and (max-width: $tablet) {
flex-direction: column;
width: 100%;
}
.field {
margin-bottom: 0;
width: 33%;
&:not(:last-child) {
padding-right: .5rem;
}
@media screen and (max-width: $tablet) {
width: 100%;
max-width: 100%;
margin-top: .5rem;
padding-right: 0 !important;
}
&, .input {
font-size: .8rem;
}
.select, .select select {
height: auto;
width: 100%;
font-size: .8rem;
}
.label {
font-size: .9rem;
padding-left: .4rem;
}
}
}
}
.vdr.active::before {
display: none;
}

View File

@ -1,328 +0,0 @@
$bucket-background: $grey-100;
$task-background: $white;
$ease-out: all .3s cubic-bezier(0.23, 1, 0.32, 1);
$bucket-width: 300px;
$bucket-header-height: 60px;
$bucket-right-margin: 1rem;
$crazy-height-calculation: '100vh - 4.5rem - 1.5rem - 1rem - 1.5rem - 11px';
$crazy-height-calculation-tasks: '#{$crazy-height-calculation} - 1rem - 2.5rem - 2rem - #{$button-height} - 1rem';
$filter-container-height: '1rem - #{$switch-view-height}';
.app-content.list\.kanban {
padding-bottom: 0;
}
.kanban {
overflow-x: auto;
overflow-y: hidden;
height: calc(#{$crazy-height-calculation});
margin: 0 -1.5rem;
padding: 0 1.5rem;
@media screen and (max-width: $tablet) {
height: calc(#{$crazy-height-calculation} - #{$filter-container-height});
}
&-bucket-container {
display: flex;
align-items: flex-start;
}
.ghost {
background: transparent !important;
border: 3px dashed $grey-300 !important;
box-shadow: none !important;
* {
opacity: 0;
}
}
.bucket {
background-color: $bucket-background;
border-radius: $radius;
position: relative;
margin: 0 $bucket-right-margin 0 0;
max-height: 100%;
min-height: 20px;
width: $bucket-width;
.tasks {
max-height: calc(#{$crazy-height-calculation-tasks});
overflow: auto;
margin-top: 0;
@media screen and (max-width: $tablet) {
max-height: calc(#{$crazy-height-calculation-tasks} - #{$filter-container-height});
}
.task {
user-select: none;
//transition: $ease-out;
cursor: pointer;
box-shadow: $shadow-xs;
display: block;
border: 3px solid transparent;
font-size: .9rem;
margin: .5rem;
border-radius: $radius;
background: $task-background;
padding-bottom: .125rem;
&.loader-container.is-loading:after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
h3 {
font-family: $family-sans-serif;
font-size: .85rem;
word-break: break-word;
}
.progress {
margin: 8px 0 0 0;
width: 100%;
height: 0.5rem;
}
.due-date {
float: right;
display: flex;
align-items: center;
.icon {
margin-right: .25rem;
}
&.overdue {
color: $red;
}
}
.label-wrapper .tag {
margin: .5rem .5rem 0 0;
}
.footer {
background: transparent;
padding: 0;
display: flex;
flex-wrap: wrap;
align-items: center;
margin-top: .25rem;
.tag, .assignees, .icon, .priority-label, .checklist-summary {
margin-top: 0;
margin-right: .25rem;
margin-bottom: .25rem;
}
.checklist-summary {
padding-left: 0;
}
.assignees {
display: flex;
.user {
display: inline;
margin: 0;
img {
margin: 0;
}
}
}
.tag {
margin-left: 0;
}
.priority-label {
font-size: .75rem;
height: 1.5rem;
.icon {
height: 1rem;
padding: 0 .25rem;
margin-top: 0;
}
}
}
.footer .icon,
.due-date,
.priority-label {
background: $grey-100;
border-radius: $radius;
padding: 0 .5rem;
}
.due-date {
padding: 0 .25rem;
}
.task-id {
color: $grey-500;
font-size: .8rem;
margin-bottom: .25rem;
display: flex;
}
.is-done {
font-size: .75rem;
padding: .2rem .3rem;
margin: 0 .25rem 0 0;
}
&.is-moving {
opacity: .5;
}
span {
width: auto;
}
&.has-light-text {
color: $white;
.task-id {
color: $grey-200;
}
.footer .icon,
.due-date,
.priority-label {
background: $grey-800;
}
.footer {
.icon svg {
fill: $white;
}
}
}
&.v-leave-from,
&.v-leave-to,
&.v-leave-active
&.move-card-leave-from,
&.move-card-leave-to,
&.move-card-leave-active {
display: none;
}
}
.dropper {
&, > div {
min-height: 40px;
}
}
}
.move-card-move {
transition: transform $transition-duration;
}
.no-move {
transition: transform 0s;
}
h2 {
font-size: 1rem;
margin: 0;
font-weight: 600 !important;
}
&.new-bucket {
// Because of reasons, this button ignores the margin we gave it to the right.
// To make it still look like it has some, we modify the container to have a padding of 1rem,
// which is the same as the margin it should have. Then we make the container itself bigger
// to hide the fact we just made the button smaller.
min-width: calc(#{$bucket-width} + 1rem);
background: transparent;
padding-right: 1rem;
.button {
background: $bucket-background;
width: 100%;
}
}
a.dropdown-item {
padding-right: 1rem;
}
&.is-collapsed {
transform: rotate(90deg) translateX(math.div($bucket-width, 2) - math.div($bucket-header-height, 2));
// Using negative margins instead of translateY here to make all other buckets fill the empty space
margin-left: (math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1;
margin-right: calc(#{(math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1} + #{$bucket-right-margin});
cursor: pointer;
.tasks, .bucket-footer {
display: none;
}
}
}
.bucket-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: .5rem;
height: $bucket-header-height;
.limit {
padding-left: .5rem;
font-weight: bold;
&.is-max {
color: $red;
}
}
.title.input {
height: auto;
padding: .4rem .5rem;
display: inline-block;
cursor: pointer;
}
}
.dropdown-trigger {
cursor: pointer;
padding: .5rem;
}
.bucket-footer {
padding: .5rem;
.button {
background-color: transparent;
&:hover {
background-color: $white;
}
}
}
}
.task-dragging {
transition: transform 0.18s ease;
transform: rotateZ(3deg)
}
.ghost-task-drop {
transition: transform 0.18s ease-in-out;
transform: rotateZ(0deg)
}

View File

@ -1,13 +0,0 @@
.keyboard-shortcuts-button {
position: fixed;
bottom: calc(1rem - 4px);
right: 1rem;
z-index: 4500; // The modal has a z-index of 4000
color: $grey-500;
transition: color $transition;
@media screen and (max-width: $tablet) {
display: none;
}
}

View File

@ -1,3 +1,4 @@
// FIXME: adapt lables.vue so that it can be used for this aswell
.labels-list {
a, a:hover {
text-decoration: none;
@ -7,6 +8,7 @@
margin: .5rem 0 .5rem .5rem;
background: $grey-200;
// FIXME: only used in ListLabels.vue
&.disabled {
opacity: 0.7;

View File

@ -1,6 +0,0 @@
.legal-links {
margin-top: 1rem;
text-align: right;
color: $grey-300;
font-size: 1rem;
}

View File

@ -1,84 +0,0 @@
.list-background-setting {
.unsplash-link {
text-align: right;
font-size: .8rem;
a {
color: $grey-800;
}
}
.image-search-result {
margin-top: 1rem;
display: flex;
flex-flow: row wrap;
.image {
width: calc(100% / 5 - 1rem);
height: 120px;
margin: .5rem;
background-size: cover;
background-position: center;
display: flex;
@media screen and (min-width: $desktop) {
&:nth-child(5n) {
page-break-after: always; // CSS 2.1 syntax
break-after: always; // New syntax
}
}
@media screen and (max-width: $desktop) {
width: calc(100% / 4 - 1rem);
&:nth-child(4n) {
page-break-after: always; // CSS 2.1 syntax
break-after: always; // New syntax
}
}
@media screen and (max-width: $tablet) {
width: calc(100% / 2 - 1rem);
&:nth-child(2n) {
page-break-after: always; // CSS 2.1 syntax
break-after: always; // New syntax
}
}
@media screen and (max-width: ($mobile)) {
width: calc(100% - 1rem);
&:nth-child(1n) {
page-break-after: always; // CSS 2.1 syntax
break-after: always; // New syntax
}
}
.info {
align-self: flex-end;
display: block;
opacity: 0;
width: 100%;
padding: .25rem 0;
text-align: center;
background: rgba(0, 0, 0, 0.5);
font-size: .75rem;
font-weight: bold;
color: $white;
transition: opacity $transition;
}
&:hover .info {
opacity: 1;
}
}
}
.is-load-more-button {
margin: 1rem auto 0 !important;
display: block;
width: 200px;
}
}

View File

@ -1,53 +1,9 @@
.card.is-fullwidth {
margin-bottom: 1rem;
.add-form {
margin: 1rem;
}
.content {
padding: 0;
}
}
.list-view .task-add {
padding: 1rem 1rem 0;
}
.list-title {
display: flex;
align-items: center;
justify-content: center;
$edit-icon-width: 1rem;
@media screen and (min-width: $tablet) {
// We need a fixed width for overflowing ellipsis to work
--nav-username-width: 0;
width: calc(100vw - #{$user-dropdown-width-mobile} - #{2 * $hamburger-menu-icon-spacing} - #{$hamburger-menu-icon-width} - #{$edit-icon-width} - #{2 * $navbar-icon-width} - #{$vikunja-nav-logo-full-width} - var(--nav-username-width));
}
@media screen and (max-width: $tablet) {
// We need a fixed width for overflowing ellipsis to work
width: calc(100vw - #{$user-dropdown-width-mobile} - #{2 * $hamburger-menu-icon-spacing} - #{$hamburger-menu-icon-width} - #{$edit-icon-width} - #{2 * $navbar-icon-width});
}
h1 {
margin: 0;
}
.dropdown-trigger {
color: $grey-400;
margin-left: 1rem;
height: 1rem;
width: 1rem;
cursor: pointer;
}
}
.edit-list {
padding-bottom: 1rem;
}
// FIXME: should be a component <FilterContainer>
// used in
// - gantt-component.vue
// - Kanban.vue
// - List.vue
// - Table.vue
$filter-container-top-default: -59px;
$filter-container-top-link-share-gantt: -138px;
@ -136,9 +92,6 @@ $filter-container-top-link-share-list: -47px;
}
}
.list-namespace-title {
color: $grey-500;
}
.link-share-container .gantt-chart-container .filter-container,
.gantt-chart-container .filter-container {
@ -153,149 +106,4 @@ $filter-container-top-link-share-list: -47px;
.link-share-container .filter-container {
right: 9rem;
margin-top: $filter-container-top-default;
}
.is-archived .notification.is-warning {
margin-bottom: 1rem;
}
$lists-per-row: 5;
$list-height: 150px;
$list-spacing: 1rem;
.list-card {
cursor: pointer;
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
height: $list-height;
background: $white;
margin: 0 $list-spacing $list-spacing 0;
padding: 1rem;
border-radius: $radius;
box-shadow: $shadow-sm;
transition: box-shadow $transition;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
&:hover {
box-shadow: $shadow-md;
}
&:active,
&:focus,
&:focus:not(:active) {
box-shadow: $shadow-xs !important;
}
@media screen and (min-width: $widescreen) {
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $widescreen) and (min-width: $tablet) {
$lists-per-row: 3;
& {
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
}
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $tablet) {
$lists-per-row: 2;
& {
width: calc((100% - #{($lists-per-row - 1) * 1rem}) / #{$lists-per-row});
}
&:nth-child(#{$lists-per-row}n) {
margin-right: 0;
}
}
@media screen and (max-width: $mobile) {
$lists-per-row: 1;
& {
width: 100%;
margin-right: 0;
}
}
.is-archived-container {
width: 100%;
text-align: right;
.is-archived {
font-size: .75rem;
float: left;
}
}
.title {
align-self: flex-end;
font-family: $vikunja-font;
font-weight: 400;
font-size: 1.5rem;
color: $text;
width: 100%;
margin-bottom: 0;
max-height: calc(100% - 2rem); // 1rem padding, 1rem height of the "is archived" badge
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
&.has-light-text .title {
color: $light;
}
&.has-background {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
.title {
text-shadow: 0 0 10px $black, 1px 1px 5px $grey-700, -1px -1px 5px $grey-700;
color: $white;
}
}
.favorite {
transition: opacity $transition, color $transition;
opacity: 0;
&:hover {
color: $orange;
}
&.is-archived {
display: none;
}
&.is-favorite {
display: inline-block;
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
}
.list-cards-wrapper-2-rows {
flex-wrap: wrap;
max-height: calc(#{$list-height * 2} + #{$list-spacing * 2} - 4px);
overflow: hidden;
@media screen and (max-width: $mobile) {
max-height: calc(#{$list-height * 4} + #{$list-spacing * 4} - 4px);
}
}
}

View File

@ -1,94 +0,0 @@
.migration-services-overview {
text-align: center;
a {
display: inline-block;
width: 100px;
text-transform: capitalize;
margin-right: 1rem;
img {
display: block;
}
}
}
.migration-in-progress-container {
max-width: 400px;
margin: 4rem auto 0;
text-align: center;
}
.migration-in-progress {
text-align: center;
display: flex;
max-width: 400px;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
img {
display: block;
max-height: 100px;
}
.progress-dots {
height: 40px;
width: 140px;
overflow: visible;
span {
transition: all 500ms ease;
background: $grey-500;
height: 10px;
width: 10px;
display: inline-block;
border-radius: 10px;
animation: wave 2s ease infinite;
margin-right: 5px;
&:nth-child(1) {
animation-delay: 0;
}
&:nth-child(2) {
animation-delay: 100ms;
}
&:nth-child(3) {
animation-delay: 200ms;
}
&:nth-child(4) {
animation-delay: 300ms;
}
&:nth-child(5) {
animation-delay: 400ms;
}
&:nth-child(6) {
animation-delay: 500ms;
}
&:nth-child(7) {
animation-delay: 600ms;
}
&:nth-child(8) {
animation-delay: 700ms;
}
}
}
@keyframes wave {
0%, 40%, 100% {
transform: translate(0, 0);
background-color: $primary;
}
10% {
transform: translate(0, -15px);
background-color: $primary-dark;
}
}
}

View File

@ -1,47 +1,4 @@
.namespaces-list {
.button.new-namespace {
float: right;
margin-left: 1rem;
@media screen and (max-width: $mobile) {
float: none;
width: 100%;
margin-bottom: 1rem;
}
}
.show-archived-check {
margin-bottom: 1rem;
}
&.loader-container.is-loading {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem + 1.5rem});
}
.namespace {
&:not(:last-child) {
margin-bottom: 1rem;
}
h1 {
display: flex;
align-items: center;
}
.is-archived {
font-size: 0.75rem;
border: 1px solid $grey-500;
color: $grey !important;
padding: 2px 4px;
border-radius: 3px;
font-family: $vikunja-font;
background: rgba($white, 0.75);
margin-left: .5rem;
}
.lists {
display: flex;
flex-flow: row wrap;
}
}
// FIXME: used in navigation.vue and in ListNamespaces.vue
.namespaces-list.loader-container.is-loading {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem + 1.5rem});
}

View File

@ -1,107 +0,0 @@
.notifications {
width: $navbar-icon-width;
.unread-indicator {
position: absolute;
top: .75rem;
right: 1.15rem;
width: .75rem;
height: .75rem;
background: $primary;
border-radius: 100%;
border: 2px solid $white;
}
.notifications-list {
position: fixed;
right: 1rem;
margin-top: 1rem;
max-height: 400px;
overflow-y: auto;
background: $white;
width: 350px;
max-width: calc(100vw - 2rem);
padding: .75rem .25rem;
border-radius: $radius;
box-shadow: $shadow-sm;
font-size: .85rem;
@media screen and (max-width: $tablet) {
max-height: calc(100vh - 1rem - #{$navbar-height});
}
.head {
font-family: $vikunja-font;
font-size: 1rem;
padding: .5rem;
}
.single-notification {
display: flex;
align-items: center;
padding: 0.25rem 0;
transition: background-color $transition;
&:hover {
background: $grey-100;
border-radius: $radius;
}
.read-indicator {
width: .35rem;
height: .35rem;
background: $primary;
border-radius: 100%;
margin-left: .5rem;
&.read {
background: transparent;
}
}
.user {
display: inline-flex;
align-items: center;
width: auto;
margin: 0 .5rem;
span {
font-family: $family-sans-serif;
}
.avatar {
height: 16px;
}
img {
margin-right: 0;
}
}
.created {
color: $grey-400;
}
&:last-child {
margin-bottom: .25rem;
}
a {
color: $grey-800;
}
}
.nothing {
text-align: center;
padding: 1rem 0;
color: $grey-500;
.explainer {
font-size: .75rem;
}
}
}
}

View File

@ -1,61 +0,0 @@
.quick-actions {
.action-input {
display: flex;
align-items: center;
.input {
border: 0;
font-size: 1.5rem;
}
&.has-active-cmd .input {
padding-left: .5rem;
}
.active-cmd {
font-size: 1.25rem;
margin-left: .5rem;
}
}
.results {
text-align: left;
width: 100%;
color: $grey-800;
.result {
&-title {
background: $grey-50;
padding: .5rem;
display: block;
font-size: .75rem;
}
&-items {
button {
font-size: .9rem;
width: 100%;
background: transparent;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem .75rem;
border: none;
cursor: pointer;
&:focus, &:hover {
background: $grey-50;
box-shadow: none !important;
}
&:active {
background: $grey-100;
}
}
}
}
}
}

View File

@ -1,19 +0,0 @@
.reminders {
.reminder-input {
display: flex;
align-items: center;
&.overdue .datepicker a.show {
color: $red;
}
&:last-child {
margin-bottom: 0.75rem;
}
a.remove {
color: $red;
padding-left: .5rem;
}
}
}

View File

@ -1,43 +0,0 @@
.switch-view {
background: $white;
display: inline-flex;
border-radius: $radius;
font-size: .75rem;
box-shadow: $shadow-sm;
height: $switch-view-height;
margin-bottom: 1rem;
padding: .5rem;
a {
padding: .25rem .5rem;
display: block;
border-radius: $radius;
transition: all 100ms;
&:not(:last-child) {
margin-right: .5rem;
}
&.is-active, &:hover {
color: $white;
}
&.is-active {
background: $primary;
font-weight: bold;
box-shadow: $shadow-xs;
}
&:hover {
background: $primary;
}
}
}
@media screen and (max-width: $tablet) {
.switch-view-container {
display: flex;
justify-content: center;
}
}

View File

@ -1,21 +0,0 @@
.table-view {
.table {
background: transparent;
overflow-x: auto;
overflow-y: hidden;
th {
white-space: nowrap;
}
.user {
margin: 0;
}
.is-done {
font-size: .9rem;
margin: 0;
}
}
}

View File

@ -1,231 +1,9 @@
.task-view {
// This is a workaround to hide the llama background from the top on the task detail page
margin-top: -1.5rem;
padding: 1rem;
background-color: $light-background;
@media screen and (max-width: $desktop) {
padding-bottom: 0;
}
.subtitle {
color: $grey-500;
margin-bottom: 1rem;
a {
color: $grey-800;
}
}
h3 .button {
vertical-align: middle;
}
.icon.is-grey {
color: $grey-400;
}
.heading {
display: flex;
justify-content: space-between;
text-transform: none;
align-items: center;
.title {
margin-bottom: 0;
&.input {
// 1.8rem is the font-size, 1.125 is the line-height, .3rem padding everywhere, 1px border around the whole thing.
min-height: calc(1.8rem * 1.125 + .6rem + 2px);
}
}
.title.task-id {
color: $grey-400;
white-space: nowrap;
}
@media screen and (max-width: $tablet) {
flex-direction: column;
align-items: start;
.title.input {
margin: 0 -.3rem .5rem -.3rem; // the title has 0.3rem padding - this make the text inside of it align with the rest
}
}
}
.date-input {
display: flex;
align-items: center;
a.remove {
color: $red;
vertical-align: middle;
padding-left: .5rem;
line-height: 1;
}
}
.datepicker {
width: 100%;
a.show {
color: $text;
padding: .25rem .5rem;
transition: background-color $transition;
border-radius: $radius;
display: block;
margin: .1rem 0;
&:hover {
background: $white;
}
}
&.disabled a.show:hover {
background: transparent;
}
}
.details {
padding-bottom: 0.75rem;
flex-flow: row wrap;
margin-bottom: 0;
.detail-title {
display: block;
color: $grey-400;
}
.none {
font-style: italic;
}
// Break after the 2nd element
.column:nth-child(2n) {
page-break-after: always; // CSS 2.1 syntax
break-after: always; // New syntax
}
&.labels-list, .assignees {
.multiselect {
.input-wrapper {
&:not(:focus-within):not(:hover) {
background: transparent !important;
border-color: transparent !important;
}
}
}
}
}
.details, .heading {
.input:not(.has-defaults),
.textarea,
.select:not(.has-defaults) select {
border-color: transparent;
background: transparent;
cursor: pointer;
transition: all $transition-duration;
&::placeholder {
color: $text-light;
opacity: 1;
font-style: italic;
}
&:not(:disabled) {
&:hover, &:active {
background: $input-background-color;
border-color: $input-border-color;
cursor: text;
}
&:focus {
background: $input-background-color;
border-color: $input-focus-border-color;
}
}
}
.select:not(.has-defaults):after {
opacity: 0;
}
.select:not(.has-defaults):hover:after {
opacity: 1;
}
}
.attachments {
margin-bottom: 0;
table tr:last-child td {
border-bottom: none;
}
}
.action-buttons {
a.button {
width: 100%;
margin-bottom: .5rem;
justify-content: left;
}
}
.created {
font-size: .75rem;
color: $grey-500;
text-align: right;
}
.checklist-summary {
margin-left: .25rem;
}
}
// FIXME: should be in TaskDetailView.vue
.link-share-container:not(.has-background) .task-view {
background: transparent;
}
.task-view-container {
padding-bottom: 1rem;
@media screen and (max-width: $desktop) {
padding-bottom: 0;
}
.task-view * {
opacity: 0;
transition: opacity 50ms ease;
}
&.is-loading {
opacity: 1;
.task-view * {
opacity: 0;
}
}
&.visible:not(.is-loading) .task-view * {
opacity: 1;
}
}
.is-done {
background: $green;
color: $white;
padding: .5rem;
font-size: 1rem;
margin-left: .5rem;
font-weight: bold;
line-height: 1;
border-radius: 4px;
text-align: center;
}
// FIXME: should be a prop of TaskDetailView.vue
.modal-container .task-view {
border-radius: $radius;
padding: 1rem;
@ -236,18 +14,4 @@
border-radius: 0;
padding-top: 2rem;
}
}
.flash-background-enter-from,
.flash-background-enter-active {
animation: flash-background $flash-background-duration ease 1;
}
@keyframes flash-background {
0% {
background: lighten($primary, 30);
}
100% {
background: transparent;
}
}

View File

@ -1,45 +0,0 @@
$remove-icon-width: 24px;
.task-relations {
&.is-narrow .columns {
display: block;
.column {
width: 100%;
}
}
.different-list {
color: $grey-500;
width: auto;
}
.related-tasks {
.title {
font-size: 1rem;
margin: 0;
}
.tasks {
margin: 0;
a:not(.remove) {
width: calc(100% - #{$remove-icon-width});
}
.task .tasktext {
width: calc(100% - .25rem); // Magic .25rem extra space
}
.remove {
width: $remove-icon-width;
text-align: center;
}
}
}
.none {
font-style: italic;
text-align: center;
}
}

View File

@ -1,211 +1,41 @@
.tasks-container {
display: flex;
.tasks {
width: 100%;
.ghost {
border-radius: $radius;
background: $grey-100;
border: 2px dashed $grey-300;
* {
opacity: 0;
}
}
}
&.has-task-edit-open {
flex-direction: column;
@media screen and (min-width: $tablet) {
flex-direction: row;
.tasks {
width: 66%;
}
}
}
.taskedit {
width: 33%;
margin-right: 1rem;
margin-left: .5rem;
@media screen and (max-width: $tablet) {
width: 100%;
border-radius: 0;
margin: 0;
border-left: 0;
border-right: 0;
border-bottom: 0;
}
}
}
// FIXME: These classes are used all over.
// very hard to untangle
// they have many overwrites at different positions
.tasks {
margin-top: 1rem;
padding: 0;
text-align: left;
@media screen and (max-width: $tablet) {
max-width: 100%;
}
&.short {
@media screen and (min-width: $tablet) {
max-width: 53vw;
}
}
.progress {
// overwrite bulma
margin-bottom: 0;
}
&.noborder {
margin: 1rem -0.5rem;
}
.task {
display: flex;
flex-wrap: wrap;
padding: .4rem;
transition: background-color $transition;
align-items: center;
cursor: pointer;
margin: 0 .5rem;
border-radius: $radius;
border: 2px solid transparent;
&:first-child {
margin-top: .5rem;
}
&:last-child {
margin-bottom: .5rem;
}
&:hover {
background-color: $grey-100;
}
.tasktext,
&.tasktext {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
flex: 1 0 50%;
.overdue {
color: $red;
}
}
.task-list {
width: auto;
color: $grey-400;
font-size: .9rem;
white-space: nowrap;
}
.fancycheckbox span {
display: none;
}
.color-bubble {
height: 10px;
flex: 0 0 10px;
}
.tag {
margin: 0 0.5rem;
}
.avatar {
border-radius: 50%;
vertical-align: bottom;
margin-left: 5px;
height: 27px;
width: 27px;
}
.list-task-icon {
margin-left: 6px;
&:not(:first-of-type) {
margin-left: 8px;
}
}
a {
color: $text;
transition: color ease $transition-duration;
&:hover {
color: $grey-900;
}
}
.favorite {
opacity: 0;
text-align: center;
width: 27px;
transition: opacity $transition, color $transition;
&:hover {
color: $orange;
}
&.is-favorite {
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
&:hover .handle {
opacity: 1;
}
.fancycheckbox {
height: 18px;
padding-top: 0;
padding-right: .5rem;
span {
display: none;
}
}
.tasktext.done {
text-decoration: line-through;
color: $grey-500;
}
span.parent-tasks {
color: $grey-500;
width: auto;
}
.remove {
color: $red;
}
input[type="checkbox"] {
vertical-align: middle;
}
.settings {
float: right;
width: 24px;
cursor: pointer;
}
&.loader-container.is-loading:after {
top: calc(50% - 1rem);
left: calc(50% - 1rem);
width: 2rem;
height: 2rem;
border-left-color: $grey-300;
border-bottom-color: $grey-300;
border-bottom: none;
}
}
@ -214,26 +44,15 @@
font-size: .9rem;
}
.progress {
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%;
}
}
.task:last-child {
border-bottom: none;
}
}
// FIXME: seems only necessary for
// - relatedTasks.vue
// - singleTaskInList.vue
.is-menu-enabled .tasks .task {
span:not(.tag), a {
.tasktext, &.tasktext {
.tasktext,
&.tasktext {
@media screen and (max-width: $desktop) {
max-width: calc(100vw - 27px - 2rem - 1.5rem - 3rem - #{$navbar-width}); // 1.5rem is the padding of the tasks container, 3rem is the padding of .app-container
}
@ -247,128 +66,10 @@
}
}
.taskedit {
.priority-select {
.select, select {
width: 100%;
}
}
ul.assingees {
list-style: none;
margin: 0;
li {
padding: 0.5rem 0.5rem 0;
a {
float: right;
color: $red;
transition: all $transition;
}
}
}
.tag {
margin-right: 0.5rem;
margin-bottom: 0.5rem;
&:last-child {
margin-right: 0;
}
}
}
.show-tasks {
h3 {
text-align: left;
&.nothing {
text-align: center;
margin-top: 3rem;
}
.input {
width: 190px;
vertical-align: middle;
margin: .5rem 0;
}
}
img {
margin-top: 2rem;
}
.user img {
margin: 0;
}
}
.defer-task {
$defer-task-max-width: 350px;
position: absolute;
width: 100%;
max-width: $defer-task-max-width;
border-radius: $radius;
border: 1px solid $grey-200;
padding: 1rem;
margin: 1rem;
background: $white;
color: $text;
cursor: default;
z-index: 10;
box-shadow: $shadow-lg;
input.input {
display: none;
}
.flatpickr-calendar {
margin: 0 auto;
box-shadow: none;
span {
width: auto !important;
}
}
.defer-days {
justify-content: space-between;
display: flex;
margin: .5rem 0;
}
@media screen and (max-width: ($defer-task-max-width + 100px)) { // 100px is roughly the size the pane is pulled to the right
left: .5rem;
right: .5rem;
max-width: 100%;
width: calc(100vw - 1rem - 2rem);
.flatpickr-calendar {
max-width: 100%;
.flatpickr-innerContainer {
overflow: scroll;
}
}
}
}
// FIXME: is only used where <edit-task> is used aswell:
// - gantt-component.vue
// - List.vue
// -> Move the <card> wrapper including this class definition inside <edit-task>
.is-max-width-desktop .tasks .task {
max-width: $desktop;
}
.tasktext {
:focus {
box-shadow: inset 0 0 0 2px rgba($primary, 0.5);
}
:focus:not(:focus-visible) {
outline: 0;
}
:focus-visible, :-moz-focusring {
box-shadow: inset 0 0 0 2px rgba($primary, 0.5);
}
}
}

View File

@ -1,26 +0,0 @@
ul.teams {
padding: 0;
margin-left: 0;
overflow: hidden;
li {
list-style: none;
margin: 0;
border-bottom: 1px solid $border;
a {
color: #363636;
display: block;
padding: 0.5rem 1rem;
transition: background-color $transition;
&:hover {
background: $grey-100;
}
}
}
li:last-child {
border-bottom: none;
}
}

View File

@ -1,3 +1,5 @@
// FIXME: https://www.bram.us/2021/09/13/dont-attach-tooltips-to-document-body/
.tooltip {
visibility: collapse;
z-index: 10000;

17
src/styles/global.scss Normal file
View File

@ -0,0 +1,17 @@
@import "fonts";
@import "transitions";
// This imports are the same as in "bulma/bulma.sass"
// with the expeption of the bulma utilities.
// They are imported globally in variables.scss
@import "bulma/sass/base/_all";
@import "bulma/sass/elements/_all";
@import "bulma/sass/form/_all";
@import "bulma/sass/components/_all";
@import "bulma/sass/grid/_all";
@import "bulma/sass/helpers/_all";
@import "bulma/sass/layout/_all";
@import "theme";
@import "components";

View File

@ -1,11 +0,0 @@
@import 'theme';
@import 'content';
@import 'form';
@import 'link-share';
@import 'loading';
@import 'navigation';
@import 'notification';
@import 'offline';
@import 'update-notification';
@import 'background';

View File

@ -0,0 +1,11 @@
@import "scrollbars";
@import "theme";
@import "background";
@import "content";
@import "form";
@import "link-share";
@import "loading";
@import "navigation";
@import "notification";

View File

@ -1,4 +1,5 @@
.app-container.has-background, .link-share-container.has-background {
.app-container.has-background,
.link-share-container.has-background {
background-position: center;
background-size: cover;
background-repeat: no-repeat;
@ -31,13 +32,4 @@
border-radius: $radius !important;
}
}
}
.link-share-container.has-background .view {
background: transparent;
border: none;
.logout .button {
box-shadow: none;
}
}

View File

@ -1,75 +1,10 @@
.app-container {
min-height: calc(100vh - 65px);
@media screen and (max-width: $tablet) {
padding-top: $navbar-height;
}
.app-content {
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
z-index: 2;
&.is-menu-enabled {
margin-left: $navbar-width;
}
@media screen and (max-width: $tablet) {
margin-left: 0;
padding-top: 1.5rem;
min-height: calc(100vh - 4rem);
&.is-menu-enabled {
min-width: 100%;
margin-left: 0;
}
}
.card {
background: $white;
}
&.task\.detail {
padding-left: 0;
padding-right: 0;
}
}
}
.no-auth-wrapper {
background: url('@/assets/llama.svg') no-repeat bottom left fixed $light-background;
min-height: 100vh;
.noauth-container {
max-width: 450px;
width: 100%;
margin: 0 auto;
padding: 1rem;
@media screen and (max-width: 450px) {
.login-buttons {
flex-direction: column;
.control:first-child {
margin-bottom: 1rem;
}
}
}
}
}
.media-content {
width: calc(100% - 48px - 2rem);
}
.content h3 {
.icon, .is-small {
.icon,
.is-small {
font-size: 1rem;
}
}
.underline-none {
text-decoration: none !important;
}
.table.has-actions {
border-top: 1px solid $grey-100;
border-radius: 4px;

View File

@ -1,39 +1,3 @@
.button {
transition: all $transition;
border: 0;
text-transform: uppercase;
font-size: 0.85rem;
font-weight: bold;
height: $button-height;
box-shadow: $shadow-sm;
&.is-hovered,
&:hover {
box-shadow: $shadow-md;
}
&.fullheight {
padding-right: 7px;
height: 100%;
}
&.is-active,
&.is-focused,
&:active,
&:focus,
&:focus:not(:active) {
box-shadow: $shadow-xs !important;
}
&.is-primary.is-outlined:hover {
color: $white;
}
&.is-small {
border-radius: $radius;
}
}
.field.has-addons .button {
height: 2.5rem;
margin-left: 0 !important;
@ -95,8 +59,9 @@
height: 100%;
}
.control.has-icons-left .icon, .control.has-icons-right .icon {
z-index: 0;
.control.has-icons-left .icon,
.control.has-icons-right .icon {
z-index: 4;
}
// Buttons icons
@ -104,19 +69,9 @@
margin-right: 0.05rem !important;
}
// menu buttons
.button-bottom {
margin-bottom: 1rem;
}
.button-right {
float: right;
}
.control.has-icons-left .icon, .control.has-icons-right .icon {
z-index: 4;
}
// FIXME: used for
// - the <h1> in heading.vue
// - the <h2> in Kanban.vue
// Contenteditable form
.input.title {
font-size: 1.8rem;

View File

@ -1,49 +1,24 @@
.link-share-view {
.logo {
max-width: 300px;
width: 90%;
margin: 2rem 0 1.5rem;
}
.column {
max-width: 100%;
}
.card {
background: $white;
}
.title {
text-shadow: 0 0 1rem $white;
}
}
.field.has-addons.no-input-mobile {
.control:first-child {
width: 100%;
@media screen and (max-width: $tablet) {
display: none;
}
}
.button {
height: 40px;
@media screen and (max-width: $tablet) {
border-radius: $radius !important;
}
}
@media screen and (max-width: $tablet) {
.control:first-child {
display: none;
}
.button {
border-radius: $radius !important;
}
}
}
.sharables-list:not(.card-content) {
overflow-y: auto
}
.link-share-container {
&.has-background,&.list\.kanban-view {
&.has-background,
&.list\.kanban-view {
.container {
max-width: 100vw;
@ -60,14 +35,12 @@
max-width: 100%;
}
.loader-container, .gantt-chart-container {
> .card {
box-shadow: none !important;
border: none;
.loader-container, .gantt-chart-container > .card {
box-shadow: none !important;
border: none;
.task-add {
padding: 1rem 0 0;
}
}
.task-add {
padding: 1rem 0 0;
}
}
}
}

View File

@ -1,32 +1,30 @@
.loader-container {
&.is-loading {
position: relative;
pointer-events: none;
opacity: 0.5;
// FIXME: move to loading.vue
.loader-container.is-loading {
position: relative;
pointer-events: none;
opacity: 0.5;
&:after {
@include loader;
position: absolute;
top: calc(50% - 2.5rem);
left: calc(50% - 2.5rem);
width: 5rem;
height: 5rem;
border-width: 0.25rem;
}
}
&::after {
@include loader;
position: absolute;
top: calc(50% - 2.5rem);
left: calc(50% - 2.5rem);
width: 5rem;
height: 5rem;
border-width: 0.25rem;
}
}
.spinner {
&.is-loading {
pointer-events: none;
// FIXME: move to ShowTasks.vue
.spinner.is-loading {
pointer-events: none;
&:after {
@include loader;
width: 2rem;
height: 2rem;
margin-left: calc(50% - 1rem);
margin-top: 1rem;
border-width: 0.25rem;
}
}
}
&::after {
@include loader;
width: 2rem;
height: 2rem;
margin-left: calc(50% - 1rem);
margin-top: 1rem;
border-width: 0.25rem;
}
}

View File

@ -1,406 +1,7 @@
.navbar {
z-index: 4 !important;
// FIXME: create <MenuButton> component
.navbar-dropdown {
box-shadow: $navbar-dropdown-boxed-shadow;
top: 101%;
}
.navbar-brand {
display: flex;
align-items: center;
.logo img {
width: $vikunja-nav-logo-full-width;
}
}
}
.navbar.main-theme {
background: $light-background;
z-index: 5 !important;
justify-content: space-between;
align-items: center;
.title {
margin: 0;
font-size: 1.75rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.navbar-end {
margin-left: 0;
align-items: center;
display: flex;
}
@media screen and (max-width: $desktop) {
display: flex;
justify-content: space-between;
@media screen and (max-width: $tablet) {
.navbar-brand {
display: none;
}
.user {
width: $user-dropdown-width-mobile;
display: flex;
align-items: center;
.dropdown-trigger {
line-height: 1;
.button {
padding: 0 .5rem;
height: 1rem;
.icon {
width: .5rem;
}
}
}
.username {
display: none;
}
}
}
}
}
.navbar-menu .navbar-item .icon {
margin: 0 0.5rem;
}
.app-container {
.namespace-container {
background: $vikunja-nav-background;
z-index: 6;
color: $vikunja-nav-color;
padding: 0;
transition: all $transition;
position: fixed;
bottom: 0;
top: $navbar-height;
overflow-x: auto;
width: $navbar-width;
padding: 0 0 1rem;
left: -147vw;
bottom: 0;
@media screen and (max-width: $tablet) {
top: 0;
width: 70vw;
}
&.is-active {
left: 0;
}
.menu {
.menu-label {
font-size: 1rem;
font-weight: 700;
font-weight: bold;
font-family: $vikunja-font;
color: $vikunja-nav-color;
font-weight: 500;
min-height: 2.5rem;
padding-top: 0;
padding-left: $navbar-padding;
overflow: hidden;
}
.menu-label, .menu-list span.list-menu-link, .menu-list a {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
.list-menu-title {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.color-bubble {
height: 12px;
flex: 0 0 12px;
}
.favorite {
margin-left: .25rem;
transition: opacity $transition, color $transition;
opacity: 0;
&:hover {
color: $orange;
}
&.is-favorite {
opacity: 1;
color: $orange;
}
}
&:hover .favorite {
opacity: 1;
}
}
.menu-label {
.color-bubble {
width: 14px !important;
height: 14px !important;
}
.is-archived {
min-width: 85px;
}
}
.namespace-title {
display: flex;
align-items: center;
justify-content: space-between;
.menu-label {
margin-bottom: 0;
flex: 1 1 auto;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
a:not(.dropdown-item) {
color: $vikunja-nav-color;
padding: 0 .25rem;
}
.dropdown-trigger {
padding: .5rem;
cursor: pointer;
}
.toggle-lists-icon {
svg {
transition: all $transition;
transform: rotate(90deg);
opacity: 1;
}
&.active svg {
transform: rotate(0deg);
opacity: 0;
}
}
&:hover .toggle-lists-icon svg {
opacity: 1;
}
&:not(.has-menu) .toggle-lists-icon {
padding-right: 1rem;
}
}
.menu-label, .nsettings, .menu-list span.list-menu-link, .menu-list a {
color: $vikunja-nav-color;
}
.menu-list {
li {
height: 44px;
display: flex;
align-items: center;
.dropdown-trigger {
opacity: 0;
padding: .5rem;
cursor: pointer;
transition: $transition;
}
&:hover {
background: $white;
.dropdown-trigger {
opacity: 1;
}
}
&.loader-container.is-loading:after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
}
.flip-list-move {
transition: transform $transition-duration;
}
.ghost {
background: $grey-200;
* {
opacity: 0;
}
}
a:hover {
background: transparent;
}
span.list-menu-link, li > a {
padding: 0.75rem .5rem 0.75rem ($navbar-padding * 1.5 - 1.75rem);
transition: all 0.2s ease;
border-radius: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
border-left: $vikunja-nav-selected-width solid transparent;
.icon {
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
&.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
}
&:hover .icon.handle {
opacity: 1;
}
&.router-link-exact-active {
color: $primary;
border-left: $vikunja-nav-selected-width solid $primary;
.icon {
color: $primary;
}
}
&:hover {
border-left: $vikunja-nav-selected-width solid $primary;
}
}
}
.logo {
display: none;
@media screen and (max-width: $tablet) {
display: block;
}
}
&.namespaces-lists {
padding-top: math.div($navbar-padding, 2);
}
&.loader-container.is-loading:after {
width: 1.5rem;
height: 1.5rem;
top: calc(50% - .75rem);
left: calc(50% - .75rem);
border-width: 2px;
}
.icon {
color: $grey-400 !important;
}
}
.top-menu {
margin-top: math.div($navbar-padding, 2);
.menu-list {
li {
font-weight: 500;
font-family: $vikunja-font;
}
span.list-menu-link, li > a {
padding-left: 2rem;
display: inline-block;
.icon {
padding-bottom: .25rem;
}
}
}
}
}
}
.navbar {
.trigger-button {
cursor: pointer;
color: $grey-400;
padding: .5rem;
font-size: 1.25rem;
position: relative;
}
> * > .trigger-button {
width: $navbar-icon-width;
}
.user {
display: flex;
align-items: center;
span {
font-family: $vikunja-font;
}
.avatar {
border-radius: 100%;
vertical-align: middle;
height: 40px;
}
.logout-icon {
color: $grey-900;
.icon {
vertical-align: middle;
}
}
.dropdown-trigger .button {
background: none;
&:focus:not(:active), &:active {
outline: none !important;
box-shadow: none !important;
}
}
}
}
.menu-hide-button, .menu-show-button {
.menu-hide-button,
.menu-show-button {
display: none;
z-index: 31;
font-weight: bold;
@ -409,7 +10,8 @@
line-height: 1;
transition: all $transition;
&:hover, &:focus {
&:hover,
&:focus {
height: 1rem;
color: $grey-600;
}
@ -419,7 +21,14 @@
height: .75rem;
width: 2rem;
&:before, &:after {
@media screen and (max-width: $tablet) {
display: block;
margin-left: $hamburger-menu-icon-spacing;
}
// menu line icon and animationanimation // START
&::before,
&::after {
display: block;
content: '';
border-top: 3px solid $grey-400;
@ -427,31 +36,38 @@
transition: all $transition;
}
&:before {
&::before {
margin-bottom: .5rem;
}
&:after {
&::after {
margin-top: .5rem;
}
&:hover, &:focus {
color: $grey-600;
&:before {
&:hover,
&:focus {
&::before {
margin-bottom: .75rem;
}
&:after {
&::after {
margin-top: .75rem;
}
}
// menu line animation // END
}
.menu-hide-button {
position: fixed;
&:hover, &:focus {
@media screen and (max-width: $tablet) {
display: block;
top: $hamburger-menu-icon-spacing;
right: $hamburger-menu-icon-spacing;
}
&:hover,
&:focus {
color: $text;
}
}
@ -460,45 +76,12 @@
display: block;
}
.mobile-overlay {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(250, 250, 250, 0.8);
z-index: 5;
opacity: 0;
transition: all $transition;
}
@media screen and (max-width: $tablet) {
.menu-hide-button {
display: block;
top: $hamburger-menu-icon-spacing;
right: $hamburger-menu-icon-spacing;
}
.menu-show-button {
display: block;
margin-left: $hamburger-menu-icon-spacing;
}
.mobile-overlay {
display: block;
opacity: 1;
}
.navbar.is-dark .navbar-brand > .navbar-item {
margin: 0 auto;
}
}
.logout-icon {
margin-right: 0.85rem !important;
}
.menu-bottom-link {
width: 100%;
color: $grey-300;

View File

@ -15,8 +15,6 @@
}
}
.message {
.message-body {
border: $thickness solid;
}
.message .message-body {
border: $thickness solid;
}

View File

@ -1,23 +0,0 @@
.offline {
background: url('@/assets/llama-nightscape.jpg') no-repeat center;
background-size: cover;
height: 100vh;
.offline-message {
text-align: center;
position: absolute;
width: 100vw;
bottom: 5vh;
color: $white;
padding: 0 1rem;
h1 {
font-weight: bold;
font-size: 1.5rem;
text-align: center;
color: $white;
font-weight: 700 !important;
font-size: 1.5rem;
}
}
}

View File

@ -1,3 +1,8 @@
$scrollbar-height: 8px;
$scrollbar-track-color: $grey-200;
$scrollbar-thumb-color: $grey-300;
$scrollbar-hover-color: $grey-500;
// Chrome
::-webkit-scrollbar {
width: $scrollbar-height;

View File

@ -1,18 +1,3 @@
// bulma utilities are imported in variables.scss
@import "bulma/sass/utilities/_all";
@import "bulma/sass/base/_all";
@import "bulma/sass/elements/_all";
@import "bulma/sass/form/_all";
@import "bulma/sass/components/_all";
@import "bulma/sass/grid/_all";
@import "bulma/sass/helpers/_all";
@import "bulma/sass/layout/_all";
@import "fonts";
@import "variables-derived";
*,
*:hover,
*:active,
@ -57,14 +42,29 @@ h6 {
}
}
// FIXME: create <ProgressBar> component. used in
// - attachments.vue
// - kanban-card.vue
// - singleTaskInList.vue
.progress {
border-radius: $radius-large;
width: 50px;
margin: 0 0.5rem 0 0;
flex: 3 1 auto;
&::-moz-progress-bar, &::-webkit-progress-value {
&::-moz-progress-bar,
&::-webkit-progress-value {
background: $grey-500;
}
@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;
}
@ -82,6 +82,7 @@ h6 {
overflow-x: auto;
}
// FIXME: this should be moved in a Avatar component
.image.is-avatar {
border-radius: 100%;
}
@ -90,6 +91,8 @@ button.table {
margin-bottom: 0 !important;
}
// FIXME: merge with dropdown-item.vue
// for this to happen the component has to be used everywhere
.dropdown-item {
display: flex;
align-items: center;
@ -145,10 +148,8 @@ button.table {
margin-right: 4px;
}
.dropdown-menu {
.dropdown-content {
box-shadow: $shadow-md;
}
.dropdown-menu .dropdown-content {
box-shadow: $shadow-md;
}
.is-strikethrough {
@ -162,3 +163,8 @@ button.table {
.dragging-disabled .handle {
opacity: 0 !important;
}
.box {
border: 1px solid $grey-200;
box-shadow: $shadow-sm;
}

View File

@ -1,40 +0,0 @@
.update-notification {
margin: 1rem;
display: flex;
align-items: center;
background: $warning;
padding: 0 0 0 .5rem;
border-radius: $radius;
font-size: .9rem;
color: $grey-900;
justify-content: space-between;
@media screen and (max-width: $desktop) {
& {
position: fixed;
bottom: 1rem;
margin: 0;
width: 450px;
left: calc(50vw - 225px);
}
}
@media screen and (max-width: $tablet) {
& {
position: fixed;
left: 1rem;
right: 1rem;
bottom: 1rem;
width: auto;
}
}
p {
text-align: center;
width: 100%;
}
.button {
margin-left: .5rem;
}
}

View File

@ -1,2 +0,0 @@
// Variables that are derived from bulma variables need to be included after them
$mobile: math.div($tablet, 2);

View File

@ -1,2 +0,0 @@
@import 'animations';
@import 'transitions';

View File

@ -1,25 +0,0 @@
@keyframes bounce {
from,
20%,
53%,
80%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translate3d(0, 0, 0);
}
40%,
43% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -30px, 0);
}
70% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0, -4px, 0);
}
}

View File

@ -1,6 +0,0 @@
@import 'colors';
@import 'shadows';
@import 'variables';
// the default values get overwritten by the definitions above
@import "bulma/sass/utilities/_all";

View File

@ -3,4 +3,10 @@
@import "variables";
// the default values get overwritten by the definitions above
@import "bulma/sass/utilities/_all";
@import "bulma/sass/utilities/_all";
// this is needed so that the shared form variables are globally defined aswell
@import "bulma/sass/form/shared";
// since $tablet is defined by bulma we can just define it after importing the utilities
$mobile: math.div($tablet, 2);

View File

@ -1,5 +1,3 @@
@import 'colors';
$white: #fff;
$black: hsl(0, 0%, 4%) !default;
$orange: #ff851b;
@ -8,34 +6,24 @@ $red: #ff4136;
$blue: #1973ff;
$primary: $blue;
$info-invert: #fff;
$info-invert: $white;
$family-sans-serif: 'Open Sans', Helvetica, Arial, sans-serif;
$vikunja-font: 'Quicksand', sans-serif;
$thickness: 1px;
$pagination-current-border: $primary;
$navbar-item-active-color: $primary;
$dropdown-content-shadow: none;
$navbar-dropdown-boxed-shadow: $dropdown-content-shadow;
$dropdown-item-hover-background-color: $grey-100;
$bulmaswatch-import-font: false !default;
$light-background: $grey-100;
$transition-duration: 100ms;
$flash-background-duration: 750ms;
$vikunja-font: 'Quicksand', sans-serif;
$navbar-padding: 2rem;
$vikunja-nav-background: $light-background;
$vikunja-nav-color: $grey-700;
$vikunja-nav-selected-width: 0.4rem;
$vikunja-nav-logo-full-width: 164px;
$transition-duration: 150ms;
$transition: $transition-duration ease;
$scrollbar-height: 8px;
$scrollbar-track-color: $grey-200;
$scrollbar-thumb-color: $grey-300;
$scrollbar-hover-color: $grey-500;
$button-height: 34px;
$switch-view-height: 2.69rem;
@ -47,6 +35,7 @@ $navbar-height: 4rem;
$navbar-width: 300px;
$navbar-icon-width: 40px;
$editor-border-color: #ddd;
$dropdown-item-hover-background-color: $grey-100;
$lists-per-row: 5;
$list-height: 150px;
$list-spacing: 1rem;

View File

@ -1,3 +0,0 @@
@import 'theme/all';
@import 'utilities/all';
@import 'components/all';

View File

@ -141,3 +141,15 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.list-cards-wrapper-2-rows {
flex-wrap: wrap;
max-height: calc(#{$list-height * 2} + #{$list-spacing * 2} - 4px);
overflow: hidden;
@media screen and (max-width: $mobile) {
max-height: calc(#{$list-height * 4} + #{$list-spacing * 4} - 4px);
}
}
</style>

View File

@ -148,3 +148,54 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.switch-view-container {
@media screen and (max-width: $tablet) {
display: flex;
justify-content: center;
}
}
.switch-view {
background: $white;
display: inline-flex;
border-radius: $radius;
font-size: .75rem;
box-shadow: $shadow-sm;
height: $switch-view-height;
margin-bottom: 1rem;
padding: .5rem;
a {
padding: .25rem .5rem;
display: block;
border-radius: $radius;
transition: all 100ms;
&:not(:last-child) {
margin-right: .5rem;
}
&.is-active,
&:hover {
color: $white;
}
&.is-active {
background: $primary;
font-weight: bold;
box-shadow: $shadow-xs;
}
&:hover {
background: $primary;
}
}
}
.is-archived .notification.is-warning {
margin-bottom: 1rem;
}
</style>

View File

@ -158,3 +158,86 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.list-background-setting {
.unsplash-link {
text-align: right;
font-size: .8rem;
a {
color: $grey-800;
}
}
.image-search-result {
margin-top: 1rem;
display: flex;
flex-flow: row wrap;
.image {
width: calc(100% / 5 - 1rem);
height: 120px;
margin: .5rem;
background-size: cover;
background-position: center;
display: flex;
@media screen and (min-width: $desktop) {
&:nth-child(5n) {
break-after: always;
}
}
@media screen and (max-width: $desktop) {
width: calc(100% / 4 - 1rem);
&:nth-child(4n) {
break-after: always;
}
}
@media screen and (max-width: $tablet) {
width: calc(100% / 2 - 1rem);
&:nth-child(2n) {
break-after: always;
}
}
@media screen and (max-width: ($mobile)) {
width: calc(100% - 1rem);
&:nth-child(1n) {
break-after: always;
}
}
.info {
align-self: flex-end;
display: block;
opacity: 0;
width: 100%;
padding: .25rem 0;
text-align: center;
background: rgba(0, 0, 0, 0.5);
font-size: .75rem;
font-weight: bold;
color: $white;
transition: opacity $transition;
}
&:hover .info {
opacity: 1;
}
}
}
.is-load-more-button {
margin: 1rem auto 0 !important;
display: block;
width: 200px;
}
}
</style>

View File

@ -103,4 +103,68 @@ export default {
},
},
}
</script>
</script>
<style lang="scss">
.gantt-chart-container {
padding-bottom: 1rem;
}
.gantt-options {
display: flex;
justify-content: space-between;
align-items: center;
@media screen and (max-width: $tablet) {
flex-direction: column;
}
.range-picker {
display: flex;
margin-bottom: 1rem;
width: 50%;
@media screen and (max-width: $tablet) {
flex-direction: column;
width: 100%;
}
.field {
margin-bottom: 0;
width: 33%;
&:not(:last-child) {
padding-right: .5rem;
}
@media screen and (max-width: $tablet) {
width: 100%;
max-width: 100%;
margin-top: .5rem;
padding-right: 0 !important;
}
&, .input {
font-size: .8rem;
}
.select, .select select {
height: auto;
width: 100%;
font-size: .8rem;
}
.label {
font-size: .9rem;
padding-left: .4rem;
}
}
}
}
// vue-draggable overwrites
.vdr.active::before {
display: none;
}
</style>

View File

@ -591,3 +591,172 @@ export default {
},
}
</script>
<style lang="scss">
$bucket-background: $grey-100;
$ease-out: all .3s cubic-bezier(0.23, 1, 0.32, 1);
$bucket-width: 300px;
$bucket-header-height: 60px;
$bucket-right-margin: 1rem;
$crazy-height-calculation: '100vh - 4.5rem - 1.5rem - 1rem - 1.5rem - 11px';
$crazy-height-calculation-tasks: '#{$crazy-height-calculation} - 1rem - 2.5rem - 2rem - #{$button-height} - 1rem';
$filter-container-height: '1rem - #{$switch-view-height}';
// FIXME:
.app-content.list\.kanban {
padding-bottom: 0 !important;
}
.kanban {
overflow-x: auto;
overflow-y: hidden;
height: calc(#{$crazy-height-calculation});
margin: 0 -1.5rem;
padding: 0 1.5rem;
@media screen and (max-width: $tablet) {
height: calc(#{$crazy-height-calculation} - #{$filter-container-height});
}
&-bucket-container {
display: flex;
align-items: flex-start;
}
.ghost {
background: transparent !important;
border: 3px dashed $grey-300 !important;
box-shadow: none !important;
* {
opacity: 0;
}
}
.bucket {
background-color: $bucket-background;
border-radius: $radius;
position: relative;
margin: 0 $bucket-right-margin 0 0;
max-height: 100%;
min-height: 20px;
width: $bucket-width;
.tasks {
max-height: calc(#{$crazy-height-calculation-tasks});
overflow: auto;
margin-top: 0;
@media screen and (max-width: $tablet) {
max-height: calc(#{$crazy-height-calculation-tasks} - #{$filter-container-height});
}
.dropper {
&, > div {
min-height: 40px;
}
}
}
.move-card-move {
transition: transform $transition-duration;
}
.no-move {
transition: transform 0s;
}
h2 {
font-size: 1rem;
margin: 0;
font-weight: 600 !important;
}
&.new-bucket {
// Because of reasons, this button ignores the margin we gave it to the right.
// To make it still look like it has some, we modify the container to have a padding of 1rem,
// which is the same as the margin it should have. Then we make the container itself bigger
// to hide the fact we just made the button smaller.
min-width: calc(#{$bucket-width} + 1rem);
background: transparent;
padding-right: 1rem;
.button {
background: $bucket-background;
width: 100%;
}
}
a.dropdown-item {
padding-right: 1rem;
}
&.is-collapsed {
transform: rotate(90deg) translateX(math.div($bucket-width, 2) - math.div($bucket-header-height, 2));
// Using negative margins instead of translateY here to make all other buckets fill the empty space
margin-left: (math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1;
margin-right: calc(#{(math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1} + #{$bucket-right-margin});
cursor: pointer;
.tasks, .bucket-footer {
display: none;
}
}
}
.bucket-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: .5rem;
height: $bucket-header-height;
.limit {
padding-left: .5rem;
font-weight: bold;
&.is-max {
color: $red;
}
}
.title.input {
height: auto;
padding: .4rem .5rem;
display: inline-block;
cursor: pointer;
}
}
:deep(.dropdown-trigger) {
cursor: pointer;
padding: .5rem;
}
.bucket-footer {
padding: .5rem;
.button {
background-color: transparent;
&:hover {
background-color: $white;
}
}
}
}
.task-dragging {
transition: transform 0.18s ease;
transform: rotateZ(3deg)
}
.move-card-leave-from,
.move-card-leave-to,
.move-card-leave-active {
display: none;
}
</style>

View File

@ -309,3 +309,54 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.tasks-container {
display: flex;
&.has-task-edit-open {
flex-direction: column;
@media screen and (min-width: $tablet) {
flex-direction: row;
.tasks {
width: 66%;
}
}
}
.tasks {
width: 100%;
.ghost {
border-radius: $radius;
background: $grey-100;
border: 2px dashed $grey-300;
* {
opacity: 0;
}
}
}
.taskedit {
width: 33%;
margin-right: 1rem;
margin-left: .5rem;
@media screen and (max-width: $tablet) {
width: 100%;
border-radius: 0;
margin: 0;
border-left: 0;
border-right: 0;
border-bottom: 0;
}
}
}
.list-view .task-add {
padding: 1rem 1rem 0;
}
</style>

View File

@ -134,7 +134,7 @@
</router-link>
</td>
<td v-if="activeColumns.done">
<div class="is-done" v-if="t.done">Done</div>
<Done :is-done="t.done" variant="small" />
</td>
<td v-if="activeColumns.title">
<router-link :to="{name: 'task.detail', params: { id: t.id }}">{{ t.title }}</router-link>
@ -190,6 +190,7 @@
<script>
import taskList from '../../../components/tasks/mixins/taskList'
import Done from '@/components/misc/Done.vue'
import User from '../../../components/misc/user'
import PriorityLabel from '../../../components/tasks/partials/priorityLabel'
import Labels from '../../../components/tasks/partials/labels'
@ -203,6 +204,7 @@ import Pagination from '@/components/misc/pagination.vue'
export default {
name: 'Table',
components: {
Done,
FilterPopup,
Sort,
Fancycheckbox,
@ -304,3 +306,21 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.table-view {
.table {
background: transparent;
overflow-x: auto;
overflow-y: hidden;
th {
white-space: nowrap;
}
.user {
margin: 0;
}
}
}
</style>

View File

@ -34,3 +34,20 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.migration-services-overview {
text-align: center;
a {
display: inline-block;
width: 100px;
text-transform: capitalize;
margin-right: 1rem;
img {
display: block;
}
}
}
</style>

View File

@ -101,3 +101,49 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.namespaces-list {
.button.new-namespace {
float: right;
margin-left: 1rem;
@media screen and (max-width: $mobile) {
float: none;
width: 100%;
margin-bottom: 1rem;
}
}
.show-archived-check {
margin-bottom: 1rem;
}
.namespace {
&:not(:last-child) {
margin-bottom: 1rem;
}
h1 {
display: flex;
align-items: center;
}
.is-archived {
font-size: 0.75rem;
border: 1px solid $grey-500;
color: $grey !important;
padding: 2px 4px;
border-radius: 3px;
font-family: $vikunja-font;
background: rgba($white, 0.75);
margin-left: .5rem;
}
.lists {
display: flex;
flex-flow: row wrap;
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More