outsource styling to FilterMenuSection component

@mattwr18 great work and great styling so far! ;)
fyi: I noticed there was a lot of duplicate CSS and the solution I came up with is this new component, using slots
This commit is contained in:
Alina Beck 2020-03-24 17:44:56 +01:00 committed by mattwr18
parent 863656f718
commit d9c3412b41
8 changed files with 177 additions and 252 deletions

View File

@ -1,15 +1,15 @@
<template> <template>
<section class="categories-filter"> <filter-menu-section :title="$t('filter-menu.categories')" class="categories-filter">
<h4 class="title">{{ $t('filter-menu.categories') }}</h4> <template #sidebar>
<labeled-button <labeled-button
:filled="!filteredCategoryIds.length" :filled="!filteredCategoryIds.length"
:label="$t('filter-menu.all')" :label="$t('filter-menu.all')"
icon="check" icon="check"
@click="resetCategories" @click="resetCategories"
/> />
<div class="divider" /> </template>
<ul class="categories-list"> <template #filter-list>
<li v-for="category in categories" :key="category.id" class="menu-item"> <li v-for="category in categories" :key="category.id" class="item">
<labeled-button <labeled-button
:icon="category.icon" :icon="category.icon"
:filled="filteredCategoryIds.includes(category.id)" :filled="filteredCategoryIds.includes(category.id)"
@ -17,17 +17,19 @@
@click="toggleCategory(category.id)" @click="toggleCategory(category.id)"
/> />
</li> </li>
</ul> </template>
</section> </filter-menu-section>
</template> </template>
<script> <script>
import { mapGetters, mapMutations } from 'vuex' import { mapGetters, mapMutations } from 'vuex'
import CategoryQuery from '~/graphql/CategoryQuery.js' import CategoryQuery from '~/graphql/CategoryQuery.js'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton' import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default { export default {
components: { components: {
FilterMenuSection,
LabeledButton, LabeledButton,
}, },
data() { data() {
@ -60,66 +62,3 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.categories-filter {
display: flex;
flex-wrap: wrap;
margin-top: $space-small;
> .title {
width: 100%;
}
> .labeled-button {
margin-top: $space-small;
}
> .divider {
border-left: $border-size-base solid $border-color-soft;
margin: $space-base;
}
> .categories-list {
display: flex;
flex-wrap: wrap;
flex-basis: 80%;
flex-grow: 1;
> .menu-item {
width: 12.5%;
margin: $space-small 0;
}
}
@media only screen and (max-width: 800px) {
.categories-list > .menu-item {
width: 16%;
}
}
@media only screen and (max-width: 630px) {
flex-direction: column;
> .categories-list > .menu-item {
width: 25%;
margin: $space-x-small 0;
}
> .title {
text-align: center;
}
> .divider {
border-top: $border-size-base solid $border-color-soft;
margin: $space-small;
}
}
@media only screen and (max-width: 440px) {
.categories-list > .menu-item {
width: 50%;
}
}
}
</style>

View File

@ -1,31 +1,36 @@
<template> <template>
<section class="emotions-filter"> <filter-menu-section :title="$t('filter-menu.emotions')" class="emotions-filter">
<h4 class="title">{{ $t('filter-menu.emotions') }}</h4> <template #sidebar>
<labeled-button <labeled-button
:filled="!filteredByEmotions.length" :filled="!filteredByEmotions.length"
icon="check" icon="check"
:label="$t('filter-menu.all')" :label="$t('filter-menu.all')"
@click="resetEmotions" @click="resetEmotions"
/> />
<div class="divider" /> </template>
<template #filter-list>
<li v-for="emotion in emotionsArray" :key="emotion" class="item">
<emotion-button <emotion-button
v-for="emotion in emotionsArray"
:key="emotion"
:emojiPath="iconPath(emotion)" :emojiPath="iconPath(emotion)"
:emotion="emotion" :emotion="emotion"
@toggleEmotion="toogleFilteredByEmotions(emotion)" @toggleEmotion="toogleFilteredByEmotions(emotion)"
/> />
</section> </li>
</template> </template>
</filter-menu-section>
</template>
<script> <script>
import { mapGetters, mapMutations } from 'vuex' import { mapGetters, mapMutations } from 'vuex'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
import EmotionButton from '~/components/EmotionButton/EmotionButton' import EmotionButton from '~/components/EmotionButton/EmotionButton'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default { export default {
components: { components: {
LabeledButton,
EmotionButton, EmotionButton,
FilterMenuSection,
LabeledButton,
}, },
data() { data() {
return { return {
@ -52,44 +57,3 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.emotions-filter {
display: flex;
flex-wrap: wrap;
margin-top: $space-base;
width: 66%;
> .title {
width: 100%;
margin-bottom: $space-base;
}
> .divider {
border-left: $border-size-base solid $border-color-soft;
margin: 0px $space-base;
}
@media only screen and (max-width: 630px) {
width: 100%;
> .title {
text-align: center;
}
.labeled-button {
width: 100%;
margin: $space-x-small 0;
}
> .divider {
width: 100%;
margin: $space-small;
border-top: $border-size-base solid $border-color-soft;
}
> .emotion-button {
margin-top: $space-x-small;
}
}
}
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<dropdown ref="menu" :placement="placement" :offset="offset" class="filter-menu"> <dropdown ref="menu" placement="top-start" :offset="8" class="filter-menu">
<base-button <base-button
slot="default" slot="default"
icon="filter" icon="filter"
@ -11,16 +11,17 @@
<base-icon class="dropdown-arrow" name="angle-down" /> <base-icon class="dropdown-arrow" name="angle-down" />
</base-button> </base-button>
<template slot="popover"> <template slot="popover">
<ds-container class="filter-menu-options"> <div class="filter-menu-options">
<h4 class="title">{{ $t('filter-menu.filter-by') }}</h4> <h2 class="title">{{ $t('filter-menu.filter-by') }}</h2>
<following-filter /> <following-filter />
<categories-filter /> <categories-filter />
<emotions-filter /> <emotions-filter />
<languages-filter /> <languages-filter />
</ds-container> </div>
</template> </template>
</dropdown> </dropdown>
</template> </template>
<script> <script>
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -48,12 +49,14 @@ export default {
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@media only screen and (max-width: 960px) {
.filter-menu-options { .filter-menu-options {
max-width: 1026px;
padding: $space-small $space-x-small;
> .title { > .title {
text-align: center; font-size: $font-size-large;
}
} }
} }
</style> </style>

View File

@ -0,0 +1,94 @@
<template>
<section class="filter-menu-section">
<h3 v-if="title" class="title">{{ title }}</h3>
<aside class="sidebar">
<slot name="sidebar" />
</aside>
<div v-if="divider" class="divider" />
<ul class="filter-list">
<slot name="filter-list" />
</ul>
</section>
</template>
<script>
export default {
props: {
divider: {
type: Boolean,
default: true,
},
title: {
type: String,
},
},
}
</script>
<style lang="scss">
.filter-menu-section {
display: flex;
flex-wrap: wrap;
margin-top: $space-small;
> .title {
width: 100%;
margin-bottom: $space-small;
font-size: $font-size-base;
}
> .sidebar {
flex-basis: 12%;
max-width: 85px;
}
> .divider {
border-left: $border-size-base solid $border-color-soft;
margin: $space-small;
margin-left: 0;
}
> .filter-list {
display: flex;
flex-wrap: wrap;
flex-basis: 80%;
flex-grow: 1;
> .item {
width: 12.5%;
padding: 0 $space-x-small;
margin-bottom: $space-small;
text-align: center;
@media only screen and (max-width: 800px) {
width: 16%;
}
@media only screen and (max-width: 630px) {
width: 25%;
}
@media only screen and (max-width: 440px) {
width: 50%;
}
}
}
@media only screen and (max-width: 630px) {
flex-direction: column;
> .title {
text-align: center;
}
> .sidebar {
max-width: none;
}
> .divider {
border-top: $border-size-base solid $border-color-soft;
margin: $space-small;
}
}
}
</style>

View File

@ -1,25 +1,25 @@
<template> <template>
<section class="following-filter"> <filter-menu-section :divider="false" class="following-filter">
<template #sidebar>
<labeled-button <labeled-button
:filled="filteredByUsersFollowed"
icon="user-plus" icon="user-plus"
:label="$t('filter-menu.following')" :label="$t('filter-menu.following')"
:filled="filteredByUsersFollowed"
:title="$t('contribution.filterFollow')"
@click="toggleFilteredByFollowed(currentUser.id)" @click="toggleFilteredByFollowed(currentUser.id)"
v-tooltip="{
content: this.$t('contribution.filterFollow'),
placement: 'left',
delay: { show: 500 },
}"
/> />
</section> </template>
</filter-menu-section>
</template> </template>
<script> <script>
import { mapGetters, mapMutations } from 'vuex' import { mapGetters, mapMutations } from 'vuex'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton' import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default { export default {
components: { components: {
FilterMenuSection,
LabeledButton, LabeledButton,
}, },
computed: { computed: {
@ -35,21 +35,3 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.following-filter {
display: flex;
flex-wrap: wrap;
margin-top: $space-small;
> .labeled-button {
margin-top: $space-small;
width: 5%;
}
@media only screen and (max-width: 960px) {
.labeled-button {
width: 100%;
}
}
}
</style>

View File

@ -1,15 +1,15 @@
<template> <template>
<section class="languages-filter"> <filter-menu-section :title="$t('filter-menu.languages')" class="languages-filter">
<h4 class="title">{{ $t('filter-menu.languages') }}</h4> <template #sidebar>
<labeled-button <labeled-button
:filled="!filteredLanguageCodes.length" :filled="!filteredLanguageCodes.length"
:label="$t('filter-menu.all')" :label="$t('filter-menu.all')"
icon="check" icon="check"
@click="resetLanguages" @click="resetLanguages"
/> />
<div class="divider" /> </template>
<ul class="languages-list"> <template #filter-list>
<li v-for="language in locales" :key="language.code" class="menu-item"> <li v-for="language in locales" :key="language.code" class="item">
<base-button <base-button
:filled="filteredLanguageCodes.includes(language.code)" :filled="filteredLanguageCodes.includes(language.code)"
circle circle
@ -18,17 +18,20 @@
{{ language.code.toUpperCase() }} {{ language.code.toUpperCase() }}
</base-button> </base-button>
</li> </li>
</ul>
</section>
</template> </template>
</filter-menu-section>
</template>
<script> <script>
import locales from '~/locales'
import orderBy from 'lodash/orderBy'
import { mapGetters, mapMutations } from 'vuex' import { mapGetters, mapMutations } from 'vuex'
import orderBy from 'lodash/orderBy'
import locales from '~/locales'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton' import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default { export default {
components: { components: {
FilterMenuSection,
LabeledButton, LabeledButton,
}, },
computed: { computed: {
@ -49,62 +52,3 @@ export default {
}, },
} }
</script> </script>
<style lang="scss">
.languages-filter {
display: flex;
flex-wrap: wrap;
margin-top: $space-small;
> .title {
width: 100%;
margin: $space-small 0;
}
> .labeled-button {
margin-top: $space-small;
}
> .divider {
border-left: $border-size-base solid $border-color-soft;
margin: $space-x-small $space-base;
}
> .languages-list {
display: flex;
flex-wrap: wrap;
flex-basis: 80%;
flex-grow: 1;
> .menu-item {
width: 11%;
display: flex;
justify-content: center;
margin: $space-small 0;
}
}
@media only screen and (max-width: 630px) {
> .title {
text-align: center;
}
> .languages-list {
justify-content: center;
> .menu-item {
margin: $space-small 12px;
}
}
.labeled-button {
width: 100%;
margin: $space-x-small 0;
}
> .divider {
width: 100%;
margin: $space-small;
border-top: $border-size-base solid $border-color-soft;
}
}
}
</style>

View File

@ -29,7 +29,6 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 0 $space-x-small;
> .label { > .label {
margin-top: $space-x-small; margin-top: $space-x-small;

View File

@ -30,7 +30,7 @@
style="flex-grow: 0; flex-basis: auto;" style="flex-grow: 0; flex-basis: auto;"
> >
<client-only> <client-only>
<filter-menu v-show="showFilterMenuDropdown" placement="top-start" offset="8" /> <filter-menu v-show="showFilterMenuDropdown" />
</client-only> </client-only>
</ds-flex-item> </ds-flex-item>
<ds-flex-item <ds-flex-item