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>
<section class="categories-filter">
<h4 class="title">{{ $t('filter-menu.categories') }}</h4>
<labeled-button
:filled="!filteredCategoryIds.length"
:label="$t('filter-menu.all')"
icon="check"
@click="resetCategories"
/>
<div class="divider" />
<ul class="categories-list">
<li v-for="category in categories" :key="category.id" class="menu-item">
<filter-menu-section :title="$t('filter-menu.categories')" class="categories-filter">
<template #sidebar>
<labeled-button
:filled="!filteredCategoryIds.length"
:label="$t('filter-menu.all')"
icon="check"
@click="resetCategories"
/>
</template>
<template #filter-list>
<li v-for="category in categories" :key="category.id" class="item">
<labeled-button
:icon="category.icon"
:filled="filteredCategoryIds.includes(category.id)"
@ -17,17 +17,19 @@
@click="toggleCategory(category.id)"
/>
</li>
</ul>
</section>
</template>
</filter-menu-section>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import CategoryQuery from '~/graphql/CategoryQuery.js'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default {
components: {
FilterMenuSection,
LabeledButton,
},
data() {
@ -60,66 +62,3 @@ export default {
},
}
</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>
<section class="emotions-filter">
<h4 class="title">{{ $t('filter-menu.emotions') }}</h4>
<labeled-button
:filled="!filteredByEmotions.length"
icon="check"
:label="$t('filter-menu.all')"
@click="resetEmotions"
/>
<div class="divider" />
<emotion-button
v-for="emotion in emotionsArray"
:key="emotion"
:emojiPath="iconPath(emotion)"
:emotion="emotion"
@toggleEmotion="toogleFilteredByEmotions(emotion)"
/>
</section>
<filter-menu-section :title="$t('filter-menu.emotions')" class="emotions-filter">
<template #sidebar>
<labeled-button
:filled="!filteredByEmotions.length"
icon="check"
:label="$t('filter-menu.all')"
@click="resetEmotions"
/>
</template>
<template #filter-list>
<li v-for="emotion in emotionsArray" :key="emotion" class="item">
<emotion-button
:emojiPath="iconPath(emotion)"
:emotion="emotion"
@toggleEmotion="toogleFilteredByEmotions(emotion)"
/>
</li>
</template>
</filter-menu-section>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
import EmotionButton from '~/components/EmotionButton/EmotionButton'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default {
components: {
LabeledButton,
EmotionButton,
FilterMenuSection,
LabeledButton,
},
data() {
return {
@ -52,44 +57,3 @@ export default {
},
}
</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>
<dropdown ref="menu" :placement="placement" :offset="offset" class="filter-menu">
<dropdown ref="menu" placement="top-start" :offset="8" class="filter-menu">
<base-button
slot="default"
icon="filter"
@ -11,16 +11,17 @@
<base-icon class="dropdown-arrow" name="angle-down" />
</base-button>
<template slot="popover">
<ds-container class="filter-menu-options">
<h4 class="title">{{ $t('filter-menu.filter-by') }}</h4>
<div class="filter-menu-options">
<h2 class="title">{{ $t('filter-menu.filter-by') }}</h2>
<following-filter />
<categories-filter />
<emotions-filter />
<languages-filter />
</ds-container>
</div>
</template>
</dropdown>
</template>
<script>
import Dropdown from '~/components/Dropdown'
import { mapGetters } from 'vuex'
@ -48,12 +49,14 @@ export default {
},
}
</script>
<style lang="scss">
@media only screen and (max-width: 960px) {
.filter-menu-options {
> .title {
text-align: center;
}
.filter-menu-options {
max-width: 1026px;
padding: $space-small $space-x-small;
> .title {
font-size: $font-size-large;
}
}
</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>
<section class="following-filter">
<labeled-button
:filled="filteredByUsersFollowed"
icon="user-plus"
:label="$t('filter-menu.following')"
@click="toggleFilteredByFollowed(currentUser.id)"
v-tooltip="{
content: this.$t('contribution.filterFollow'),
placement: 'left',
delay: { show: 500 },
}"
/>
</section>
<filter-menu-section :divider="false" class="following-filter">
<template #sidebar>
<labeled-button
icon="user-plus"
:label="$t('filter-menu.following')"
:filled="filteredByUsersFollowed"
:title="$t('contribution.filterFollow')"
@click="toggleFilteredByFollowed(currentUser.id)"
/>
</template>
</filter-menu-section>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
export default {
components: {
FilterMenuSection,
LabeledButton,
},
computed: {
@ -35,21 +35,3 @@ export default {
},
}
</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>
<section class="languages-filter">
<h4 class="title">{{ $t('filter-menu.languages') }}</h4>
<labeled-button
:filled="!filteredLanguageCodes.length"
:label="$t('filter-menu.all')"
icon="check"
@click="resetLanguages"
/>
<div class="divider" />
<ul class="languages-list">
<li v-for="language in locales" :key="language.code" class="menu-item">
<filter-menu-section :title="$t('filter-menu.languages')" class="languages-filter">
<template #sidebar>
<labeled-button
:filled="!filteredLanguageCodes.length"
:label="$t('filter-menu.all')"
icon="check"
@click="resetLanguages"
/>
</template>
<template #filter-list>
<li v-for="language in locales" :key="language.code" class="item">
<base-button
:filled="filteredLanguageCodes.includes(language.code)"
circle
@ -18,17 +18,20 @@
{{ language.code.toUpperCase() }}
</base-button>
</li>
</ul>
</section>
</template>
</filter-menu-section>
</template>
<script>
import locales from '~/locales'
import orderBy from 'lodash/orderBy'
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'
export default {
components: {
FilterMenuSection,
LabeledButton,
},
computed: {
@ -49,62 +52,3 @@ export default {
},
}
</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;
flex-direction: column;
align-items: center;
padding: 0 $space-x-small;
> .label {
margin-top: $space-x-small;

View File

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