fix(views): refactor filter button slot in wrapper
Before this change, the filter button on the top right was positioned using absolute positioning and plenty of tricks, which were brittle and not really maintainable. Now, the buttons are positioned using flexbox, which should make this a lot more maintainable.
This commit is contained in:
parent
13cab62d14
commit
8a72fe26f8
@ -28,7 +28,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<slot />
|
<slot/>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -41,13 +41,13 @@ const BUTTON_TYPES_MAP = {
|
|||||||
|
|
||||||
export type ButtonTypes = keyof typeof BUTTON_TYPES_MAP
|
export type ButtonTypes = keyof typeof BUTTON_TYPES_MAP
|
||||||
|
|
||||||
export default { name: 'XButton' }
|
export default {name: 'XButton'}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, useSlots} from 'vue'
|
import {computed, useSlots} from 'vue'
|
||||||
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
|
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
|
||||||
import type { IconProp } from '@fortawesome/fontawesome-svg-core'
|
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
||||||
|
|
||||||
// extending the props of the BaseButton
|
// extending the props of the BaseButton
|
||||||
export interface ButtonProps extends /* @vue-ignore */ BaseButtonProps {
|
export interface ButtonProps extends /* @vue-ignore */ BaseButtonProps {
|
||||||
@ -86,6 +86,7 @@ const showIconOnly = computed(() => icon !== '' && typeof slots.default === 'und
|
|||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
white-space: var(--button-white-space);
|
white-space: var(--button-white-space);
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-md);
|
||||||
|
@ -149,8 +149,14 @@ function getViewTitle(view: IProjectView) {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.switch-view-container {
|
.switch-view-container {
|
||||||
@media screen and (max-width: $tablet) {
|
min-height: $switch-view-height;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
@media screen and (max-width: $tablet) {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@ -162,8 +168,6 @@ function getViewTitle(view: IProjectView) {
|
|||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
height: $switch-view-height;
|
|
||||||
margin: 0 auto 1rem;
|
|
||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
:project-id="filters.projectId"
|
:project-id="filters.projectId"
|
||||||
:viewId
|
:viewId
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #default>
|
||||||
<card :has-content="false">
|
<card :has-content="false">
|
||||||
<div class="gantt-options">
|
<div class="gantt-options">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -45,9 +45,7 @@
|
|||||||
</Fancycheckbox>
|
</Fancycheckbox>
|
||||||
</div>
|
</div>
|
||||||
</card>
|
</card>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #default>
|
|
||||||
<div class="gantt-chart-container">
|
<div class="gantt-chart-container">
|
||||||
<card
|
<card
|
||||||
:has-content="false"
|
:has-content="false"
|
||||||
@ -79,7 +77,7 @@ import {useI18n} from 'vue-i18n'
|
|||||||
import type {RouteLocationNormalized} from 'vue-router'
|
import type {RouteLocationNormalized} from 'vue-router'
|
||||||
|
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
import {getFlatpickrLanguage} from '@/helpers/flatpickrLanguage'
|
||||||
|
|
||||||
import Foo from '@/components/misc/flatpickr/Flatpickr.vue'
|
import Foo from '@/components/misc/flatpickr/Flatpickr.vue'
|
||||||
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="filter-container">
|
<div class="filter-container">
|
||||||
<div class="items">
|
|
||||||
<Popup>
|
<Popup>
|
||||||
<template #trigger="{toggle}">
|
<template #trigger="{toggle}">
|
||||||
<x-button
|
<x-button
|
||||||
icon="th"
|
icon="th"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@click.prevent.stop="toggle()"
|
@click.prevent.stop="toggle()"
|
||||||
|
class="mr-2"
|
||||||
>
|
>
|
||||||
{{ $t('project.table.columns') }}
|
{{ $t('project.table.columns') }}
|
||||||
</x-button>
|
</x-button>
|
||||||
@ -67,8 +67,7 @@
|
|||||||
</card>
|
</card>
|
||||||
</template>
|
</template>
|
||||||
</Popup>
|
</Popup>
|
||||||
<FilterPopup v-model="params" />
|
<FilterPopup v-model="params"/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -207,7 +206,7 @@
|
|||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="activeColumns.labels">
|
<td v-if="activeColumns.labels">
|
||||||
<Labels :labels="t.labels" />
|
<Labels :labels="t.labels"/>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="activeColumns.assignees">
|
<td v-if="activeColumns.assignees">
|
||||||
<AssigneeList
|
<AssigneeList
|
||||||
@ -397,4 +396,8 @@ const taskDetailRoutes = computed(() => Object.fromEntries(
|
|||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-container :deep(.popup) {
|
||||||
|
top: 7rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -1,5 +1,4 @@
|
|||||||
@import "tooltip";
|
@import "tooltip";
|
||||||
@import "labels";
|
@import "labels";
|
||||||
@import "project";
|
|
||||||
@import "task";
|
@import "task";
|
||||||
@import "tasks";
|
@import "tasks";
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
// FIXME: should be a component <FilterContainer>
|
|
||||||
// used in
|
|
||||||
// - Kanban.vue
|
|
||||||
// - Project.vue
|
|
||||||
// - Table.vue
|
|
||||||
|
|
||||||
$filter-container-top-default: -59px;
|
|
||||||
$filter-container-top-link-share-gantt: -133px;
|
|
||||||
$filter-container-top-link-share-list: -47px;
|
|
||||||
|
|
||||||
.filter-container {
|
|
||||||
text-align: right;
|
|
||||||
width: 100%;
|
|
||||||
min-width: 400px;
|
|
||||||
max-width: 180px;
|
|
||||||
position: absolute;
|
|
||||||
right: 1.5rem;
|
|
||||||
margin-top: $filter-container-top-default;
|
|
||||||
z-index: 4;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.button:not(:last-of-type) {
|
|
||||||
margin-right: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
height: $switch-view-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
|
||||||
position: static;
|
|
||||||
margin: 0 0 1rem 0 !important;
|
|
||||||
max-width: 100%;
|
|
||||||
min-width: auto;
|
|
||||||
|
|
||||||
.items {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.control:first-child {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.link-share-container .gantt-chart-container .filter-container,
|
|
||||||
.gantt-chart-container .filter-container {
|
|
||||||
right: 0;
|
|
||||||
margin-top: calc(#{$filter-container-top-link-share-gantt - 2} - 7rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-share-container .gantt-chart-container .filter-container {
|
|
||||||
margin-top: calc(#{$filter-container-top-link-share-gantt} - 5rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-share-container .list-view .filter-container {
|
|
||||||
margin-top: $filter-container-top-link-share-list - 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-share-container.project\.table-view,
|
|
||||||
.link-share-container.project\.list-view {
|
|
||||||
.filter-container {
|
|
||||||
right: 9rem;
|
|
||||||
margin-top: $filter-container-top-default;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user