fix(webapp): add responsive mobile menu with locale switching and filter support (#9281)

This commit is contained in:
Ulf Gebhardt 2026-02-21 08:47:14 +01:00 committed by GitHub
parent 30d88e9b41
commit 9548ad6e31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1153 additions and 462 deletions

View File

@ -3,23 +3,40 @@ import gql from 'graphql-tag'
export const UpdateUser = gql`
mutation (
$id: ID!
$slug: String
$name: String
$termsAndConditionsAgreedVersion: String
$locationName: String # empty string '' sets it to null
$about: String
$allowEmbedIframes: Boolean
$showShoutsPublicly: Boolean
$emailNotificationSettings: [EmailNotificationSettingsInput]
$termsAndConditionsAgreedVersion: String
$avatar: ImageInput
$locationName: String # empty string '' sets it to null
$locale: String
) {
UpdateUser(
id: $id
slug: $slug
name: $name
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
locationName: $locationName
about: $about
allowEmbedIframes: $allowEmbedIframes
showShoutsPublicly: $showShoutsPublicly
emailNotificationSettings: $emailNotificationSettings
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
avatar: $avatar
locationName: $locationName
locale: $locale
) {
id
slug
name
about
allowEmbedIframes
showShoutsPublicly
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
locationName
locale
location {
name
nameDE
@ -33,6 +50,18 @@ export const UpdateUser = gql`
value
}
}
avatar {
url
alt
sensitive
aspectRatio
type
}
badgeVerification {
id
description
icon
}
}
}
`

View File

@ -1,7 +1,8 @@
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
defineStep('I select {string} in the language menu', language => {
cy.get('.locale-menu')
cy.get('.locale-menu:visible')
.first()
.click()
cy.contains('.locale-menu-popover a', language)
.click()

View File

@ -1,7 +1,8 @@
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
defineStep('open the notification menu and click on the first item', () => {
cy.get('.notifications-menu')
cy.get('.notifications-menu:visible')
.first()
.invoke('show')
.click() // 'invoke('show')' because of the delay for show the menu
cy.get('.notification-content a')

View File

@ -1,6 +1,7 @@
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
defineStep('see {int} unread notifications in the top menu', count => {
cy.get('.notifications-menu')
cy.get('.notifications-menu:visible')
.first()
.should('contain', count)
})

View File

@ -1,7 +1,8 @@
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
defineStep('the notification menu button links to the all notifications page', () => {
cy.get('.notifications-menu')
cy.get('.notifications-menu:visible')
.first()
.click()
cy.location('pathname')
.should('contain', '/notifications')

View File

@ -0,0 +1,5 @@
<!-- Font Awesome Free 6.7.2 "language" icon (CC BY 4.0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 640 512">
<title>language</title>
<path d="M0 128C0 92.7 28.7 64 64 64l192 0 48 0 16 0 256 0c35.3 0 64 28.7 64 64l0 256c0 35.3-28.7 64-64 64l-256 0-16 0-48 0L64 448c-35.3 0-64-28.7-64-64L0 128zm320 0l0 256 256 0 0-256-256 0zM178.3 175.9c-3.2-7.2-10.4-11.9-18.3-11.9s-15.1 4.7-18.3 11.9l-64 144c-4.5 10.1 .1 21.9 10.2 26.4s21.9-.1 26.4-10.2l8.9-20.1 73.6 0 8.9 20.1c4.5 10.1 16.3 14.6 26.4 10.2s14.6-16.3 10.2-26.4l-64-144zM160 233.2L179 276l-38 0 19-42.8zM448 164c11 0 20 9 20 20l0 4 44 0 16 0c11 0 20 9 20 20s-9 20-20 20l-2 0-1.6 4.5c-8.9 24.4-22.4 46.6-39.6 65.4c.9 .6 1.8 1.1 2.7 1.6l18.9 11.3c9.5 5.7 12.5 18 6.9 27.4s-18 12.5-27.4 6.9l-18.9-11.3c-4.5-2.7-8.8-5.5-13.1-8.5c-10.6 7.5-21.9 14-34 19.4l-3.6 1.6c-10.1 4.5-21.9-.1-26.4-10.2s.1-21.9 10.2-26.4l3.6-1.6c6.4-2.9 12.6-6.1 18.5-9.8l-12.2-12.2c-7.8-7.8-7.8-20.5 0-28.3s20.5-7.8 28.3 0l14.6 14.6 .5 .5c12.4-13.1 22.5-28.3 29.8-45L448 228l-72 0c-11 0-20-9-20-20s9-20 20-20l52 0 0-4c0-11 9-20 20-20z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -359,6 +359,7 @@ $media-query-small: "(min-width: 600px)";
$media-query-medium: "(min-width: 768px)";
$media-query-large: "(min-width: 1024px)";
$media-query-x-large: "(min-width: 1200px)";
$container-max-width-x-large: 1200px;
/**
* @tokens Background Images

View File

@ -1,26 +1,28 @@
<template>
<div class="donation-info">
<page-params-link :pageParams="links.DONATE" class="donation-info">
<progress-bar :label="label" :goal="goal" :progress="progress">
<os-button size="sm" variant="primary" @click="redirectToPage(links.DONATE)">
<os-button size="sm" variant="primary">
{{ $t('donations.donate-now') }}
<template #suffix>
<os-icon :icon="icons.heartO" />
</template>
</os-button>
</progress-bar>
</div>
</page-params-link>
</template>
<script>
import { OsButton, OsIcon } from '@ocelot-social/ui'
import { iconRegistry } from '~/utils/iconRegistry'
import links from '~/constants/links.js'
import PageParamsLink from '~/components/_new/features/PageParamsLink/PageParamsLink.vue'
import ProgressBar from '~/components/ProgressBar/ProgressBar.vue'
export default {
components: {
OsButton,
OsIcon,
PageParamsLink,
ProgressBar,
},
props: {
@ -44,11 +46,6 @@ export default {
})
},
},
methods: {
redirectToPage(pageParams) {
pageParams.redirectToPage(this)
},
},
}
</script>
@ -58,5 +55,6 @@ export default {
flex: 1;
margin-bottom: $space-x-small;
margin-top: 16px;
cursor: pointer;
}
</style>

View File

@ -1,16 +1,16 @@
<template>
<dropdown ref="menu" placement="top-start" :offset="8" class="filter-menu">
<dropdown ref="menu" :placement="placement" :offset="offset" class="filter-menu">
<template #default="{ toggleMenu }">
<os-button
variant="primary"
:appearance="filterActive ? 'filled' : 'ghost'"
circle
:aria-label="$t('common.filter')"
@click.prevent="toggleMenu()"
>
<template #icon>
<os-icon :icon="icons.filter" />
</template>
<os-icon class="dropdown-arrow" :icon="icons.angleDown" />
</os-button>
</template>
<template #popover>
@ -34,8 +34,8 @@ export default {
OsIcon,
},
props: {
placement: { type: String },
offset: { type: [String, Number] },
placement: { type: String, default: 'top-start' },
offset: { type: [String, Number], default: 8 },
},
computed: {
...mapGetters({

View File

@ -61,6 +61,7 @@ export default {
> .filter-list {
display: flex;
flex-wrap: wrap;
flex-basis: 100%;
flex-grow: 1;
padding-left: $space-base;

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,11 @@ import Vuex from 'vuex'
const localVue = global.localVue
const stubs = {
'client-only': true,
'client-only': { template: '<div><slot /></div>' },
}
describe('LocaleSwitch.vue', () => {
let wrapper, mocks, computed, deutschLanguageItem, getters
let wrapper, mocks, computed, getters
beforeEach(() => {
mocks = {
@ -48,10 +48,12 @@ describe('LocaleSwitch.vue', () => {
{
name: 'English',
path: 'en',
flag: '🇬🇧',
},
{
name: 'Deutsch',
path: 'de',
flag: '🇩🇪',
},
]
},
@ -71,37 +73,61 @@ describe('LocaleSwitch.vue', () => {
}
describe('with current user', () => {
beforeEach(() => {
let toggleMenu
beforeEach(async () => {
toggleMenu = jest.fn()
wrapper = Wrapper()
wrapper.find('.locale-menu').trigger('click')
deutschLanguageItem = wrapper.findAll('li').at(1)
deutschLanguageItem.trigger('click')
await wrapper.vm.changeLanguage('de', toggleMenu)
})
it("sets a user's locale", () => {
expect(mocks.$i18n.set).toHaveBeenCalledTimes(1)
expect(mocks.$i18n.set).toHaveBeenCalledWith('de')
})
it("updates the user's locale in the database", () => {
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
})
it('closes the menu', () => {
expect(toggleMenu).toHaveBeenCalled()
})
})
describe('when apollo mutation fails', () => {
beforeEach(async () => {
wrapper = Wrapper()
// First call succeeds (consumes mockResolvedValueOnce)
await wrapper.vm.changeLanguage('de', jest.fn())
// Second call fails (consumes mockRejectedValueOnce)
await wrapper.vm.changeLanguage('en', jest.fn())
})
it('shows an error toast', () => {
expect(mocks.$toast.error).toHaveBeenCalledWith('Please log in!')
})
})
describe('no current user', () => {
beforeEach(() => {
let toggleMenu
beforeEach(async () => {
toggleMenu = jest.fn()
getters = {
'auth/user': () => {
return null
},
}
wrapper = Wrapper()
wrapper.find('.locale-menu').trigger('click')
deutschLanguageItem = wrapper.findAll('li').at(1)
deutschLanguageItem.trigger('click')
await wrapper.vm.changeLanguage('de', toggleMenu)
})
it('does not send a UpdateUser mutation', () => {
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('still closes the menu', () => {
expect(toggleMenu).toHaveBeenCalled()
})
})
})

View File

@ -2,18 +2,22 @@
<client-only>
<dropdown ref="menu" :placement="placement" :offset="offset">
<template #default="{ toggleMenu }">
<a
<os-button
class="locale-menu"
href="#"
variant="primary"
appearance="ghost"
circle
:aria-label="$t('localeSwitch.tooltip')"
v-tooltip="{
content: $t('localeSwitch.tooltip'),
placement: 'bottom-start',
}"
@click.prevent="toggleMenu()"
>
<span class="label">{{ current.code.toUpperCase() }}</span>
<os-icon class="dropdown-arrow" :icon="icons.angleDown" />
</a>
<template #icon>
<os-icon :icon="icons.language" />
</template>
</os-button>
</template>
<template #popover="{ toggleMenu }">
<ds-menu class="locale-menu-popover" :matcher="matcher" :routes="routes">
@ -24,6 +28,7 @@
:parents="item.parents"
@click.stop.prevent="changeLanguage(item.route.path, toggleMenu)"
>
<span class="locale-flag">{{ item.route.flag }}</span>
{{ item.route.name }}
</ds-menu-item>
</template>
@ -34,18 +39,19 @@
</template>
<script>
import { OsIcon } from '@ocelot-social/ui'
import { OsButton, OsIcon } from '@ocelot-social/ui'
import { iconRegistry } from '~/utils/iconRegistry'
import gql from 'graphql-tag'
import Dropdown from '~/components/Dropdown'
import find from 'lodash/find'
import orderBy from 'lodash/orderBy'
import locales from '~/locales'
import { mapGetters, mapMutations } from 'vuex'
import localeUpdate from '~/mixins/localeUpdate.js'
export default {
mixins: [localeUpdate],
components: {
Dropdown,
OsButton,
OsIcon,
},
props: {
@ -62,17 +68,12 @@ export default {
return find(this.locales, { code: this.$i18n.locale() })
},
routes() {
const routes = this.locales.map((locale) => {
return {
return this.locales.map((locale) => ({
name: locale.name,
path: locale.code,
}
})
return routes
flag: locale.flag,
}))
},
...mapGetters({
currentUser: 'auth/user',
}),
},
created() {
this.icons = iconRegistry
@ -86,57 +87,11 @@ export default {
matcher(locale) {
return locale === this.$i18n.locale()
},
...mapMutations({
setCurrentUser: 'auth/SET_USER',
}),
async updateUserLocale() {
if (!this.currentUser || !this.currentUser.id) return null
try {
await this.$apollo.mutate({
mutation: gql`
mutation ($id: ID!, $locale: String) {
UpdateUser(id: $id, locale: $locale) {
id
locale
}
}
`,
variables: {
id: this.currentUser.id,
locale: this.$i18n.locale(),
},
update: (store, { data: { UpdateUser } }) => {
const { locale } = UpdateUser
this.setCurrentUser({
...this.currentUser,
locale,
})
},
})
this.$toast.success(this.$t('contribution.success'))
} catch (err) {
this.$toast.error(err.message)
}
},
},
}
</script>
<style lang="scss">
.locale-menu {
user-select: none;
display: flex;
align-items: center;
height: 100%;
padding: $space-xx-small;
color: $color-locale-menu;
> .label {
margin: 0 $space-xx-small;
}
}
nav.locale-menu-popover {
margin-left: -$space-small !important;
margin-right: -$space-small !important;
@ -146,4 +101,10 @@ nav.locale-menu-popover {
padding-right: $space-base;
}
}
.locale-flag {
margin-right: $space-xx-small;
font-size: 1.2em;
line-height: 1;
}
</style>

View File

@ -118,5 +118,9 @@ export default {
.progress-bar-button {
position: relative;
float: right;
@media (max-width: 810px) {
display: none;
}
}
</style>

View File

@ -358,6 +358,7 @@ export const updateUserMutation = () => {
$termsAndConditionsAgreedVersion: String
$avatar: ImageInput
$locationName: String # empty string '' sets it to null
$locale: String
) {
UpdateUser(
id: $id
@ -370,6 +371,7 @@ export const updateUserMutation = () => {
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
avatar: $avatar
locationName: $locationName
locale: $locale
) {
id
slug

View File

@ -1,14 +1,14 @@
<template>
<div class="layout-default">
<div class="main-navigation">
<header-menu :showMobileMenu="isMobile" />
<header-menu />
</div>
<div class="ds-container ds-container-x-large">
<div class="main-container">
<nuxt />
</div>
</div>
<page-footer v-if="!isMobile" />
<page-footer class="desktop-footer" />
<div id="overlay" />
<client-only>
<modal />
@ -66,6 +66,12 @@ export default {
padding-bottom: 8rem;
}
.desktop-footer {
@media (max-width: 810px) {
display: none;
}
}
.chat-modul {
background-color: rgb(233, 228, 228);
width: 355px;

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": "Landkarte"
},
"more": "Mehr",
"notifications": {
"tooltip": "Benachrichtigungen"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": "Map"
},
"more": "More",
"notifications": {
"tooltip": "Notifications"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": "Mapa"
},
"more": "Más",
"notifications": {
"tooltip": "Notificaciones"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": "Carte"
},
"more": "Plus",
"notifications": {
"tooltip": "Notifications"
}

View File

@ -6,6 +6,7 @@ const locales = [
name: 'English',
code: 'en',
iso: 'en-US',
flag: '🇬🇧',
enabled: true,
dateFnsLocale: enUS,
},
@ -13,6 +14,7 @@ const locales = [
name: 'Deutsch',
code: 'de',
iso: 'de-DE',
flag: '🇩🇪',
enabled: true,
dateFnsLocale: de,
},
@ -20,6 +22,7 @@ const locales = [
name: 'Nederlands',
code: 'nl',
iso: 'nl-NL',
flag: '🇳🇱',
enabled: true,
dateFnsLocale: nl,
},
@ -27,6 +30,7 @@ const locales = [
name: 'Français',
code: 'fr',
iso: 'fr-FR',
flag: '🇫🇷',
enabled: true,
dateFnsLocale: fr,
},
@ -34,6 +38,7 @@ const locales = [
name: 'Italiano',
code: 'it',
iso: 'it-IT',
flag: '🇮🇹',
enabled: true,
dateFnsLocale: it,
},
@ -41,6 +46,7 @@ const locales = [
name: 'Español',
code: 'es',
iso: 'es-ES',
flag: '🇪🇸',
enabled: true,
dateFnsLocale: es,
},
@ -48,6 +54,7 @@ const locales = [
name: 'Português',
code: 'pt',
iso: 'pt-PT',
flag: '🇵🇹',
enabled: true,
dateFnsLocale: pt,
},
@ -55,6 +62,7 @@ const locales = [
name: 'Polski',
code: 'pl',
iso: 'pl-PL',
flag: '🇵🇱',
enabled: true,
dateFnsLocale: pl,
},
@ -62,6 +70,7 @@ const locales = [
name: 'Русский',
code: 'ru',
iso: 'ru-RU',
flag: '🇷🇺',
enabled: true,
dateFnsLocale: ru,
},

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": null
},
"more": "Altro",
"notifications": {
"tooltip": "Notifiche"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": null
},
"more": "Meer",
"notifications": {
"tooltip": "Notificaties"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": null
},
"more": "Więcej",
"notifications": {
"tooltip": "Powiadomienia"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": null
},
"more": "Mais",
"notifications": {
"tooltip": "Notificações"
}

View File

@ -661,6 +661,7 @@
"map": {
"tooltip": null
},
"more": "Ещё",
"notifications": {
"tooltip": "Уведомления"
}

View File

@ -0,0 +1,36 @@
import { mapGetters, mapMutations } from 'vuex'
import { updateUserMutation } from '~/graphql/User.js'
export default {
computed: {
...mapGetters({
currentUser: 'auth/user',
}),
},
methods: {
...mapMutations({
setCurrentUser: 'auth/SET_USER',
}),
async updateUserLocale() {
if (!this.currentUser || !this.currentUser.id) return
try {
await this.$apollo.mutate({
mutation: updateUserMutation(),
variables: {
id: this.currentUser.id,
locale: this.$i18n.locale(),
},
update: (_store, { data: { UpdateUser } }) => {
this.setCurrentUser({
...this.currentUser,
locale: UpdateUser.locale,
})
},
})
this.$toast.success(this.$t('contribution.success'))
} catch (err) {
this.$toast.error(err.message)
}
},
},
}

View File

@ -1,35 +1,8 @@
<template>
<div>
<!-- create post -->
<div :class="POST_ADD_BUTTON_POSITION_TOP ? 'box-add-button-top' : ''">
<client-only>
<os-button
as="nuxt-link"
:to="{ name: 'post-create-type' }"
v-tooltip="{
content: $t('contribution.newPost'),
placement: 'left',
}"
class="post-add-button"
:class="[
POST_ADD_BUTTON_POSITION_TOP ? 'post-add-button-top' : 'post-add-button-bottom',
{ 'hide-filter': hideByScroll },
]"
variant="primary"
appearance="filled"
circle
size="xl"
>
<template #icon>
<os-icon :icon="icons.plus" />
</template>
</os-button>
</client-only>
</div>
<div>
<div v-if="SHOW_CONTENT_FILTER_MASONRY_GRID" class="top-filter-menu">
<div class="filterButtonBox">
<div class="filterButtonMenu" :class="{ 'hide-filter': hideByScroll }">
<!-- feed top row: filter (left) + create post (right) -->
<div class="feed-top-row">
<div v-if="SHOW_CONTENT_FILTER_MASONRY_GRID" class="filterButtonMenu">
<os-button
class="my-filter-button"
v-if="
@ -93,11 +66,33 @@
</div>
</div>
</div>
</div>
</div>
<client-only>
<os-button
as="nuxt-link"
:to="{ name: 'post-create-type' }"
v-tooltip="{
content: $t('contribution.newPost'),
placement: 'left',
}"
class="post-add-button"
:class="{ 'hide-filter': hideByScroll }"
variant="primary"
appearance="filled"
circle
size="xl"
>
<template #icon>
<os-icon :icon="icons.plus" />
</template>
</os-button>
</client-only>
</div>
<div v-if="hashtag || showDonations" class="newsfeed-controls">
<div
v-if="hashtag || showDonations"
class="newsfeed-controls"
:class="{ 'newsfeed-controls--no-filter': !SHOW_CONTENT_FILTER_MASONRY_GRID }"
>
<div v-if="hashtag">
<hashtags-filter :hashtag="hashtag" @clearSearch="clearSearch" />
</div>
@ -171,7 +166,6 @@ import { filterPosts } from '~/graphql/PostQuery.js'
import UpdateQuery from '~/components/utils/UpdateQuery'
import FilterMenuComponent from '~/components/FilterMenu/FilterMenuComponent'
import { SHOW_CONTENT_FILTER_MASONRY_GRID } from '~/constants/filter.js'
import { POST_ADD_BUTTON_POSITION_TOP } from '~/constants/posts.js'
import GetCategories from '~/mixins/getCategoriesMixin.js'
export default {
@ -206,7 +200,6 @@ export default {
pageSize: 12,
hashtag,
SHOW_CONTENT_FILTER_MASONRY_GRID,
POST_ADD_BUTTON_POSITION_TOP,
}
},
computed: {
@ -364,65 +357,59 @@ export default {
display: none;
}
.box-add-button-top {
float: right;
.feed-top-row {
display: flex;
align-items: flex-start;
gap: 16px;
margin-top: 0px;
}
.post-add-button-bottom {
.filterButtonMenu {
flex: 1 1 auto;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
.post-add-button {
height: 54px !important;
width: 54px !important;
min-height: 54px !important;
min-width: 54px !important;
font-size: 26px !important;
box-shadow: $box-shadow-x-large !important;
z-index: $z-index-sticky-float !important;
position: fixed !important;
bottom: -5px !important;
left: 98vw !important;
transform: translate(-120%, -120%) !important;
box-shadow: $box-shadow-x-large !important;
right: max(20px, calc((100vw - $container-max-width-x-large) / 2 + 48px)) !important;
top: 81px !important;
transition: top 0.3s ease !important;
}
.post-add-button-top {
height: 54px !important;
width: 54px !important;
min-height: 54px !important;
min-width: 54px !important;
font-size: 26px !important;
z-index: $z-index-sticky-float !important;
position: fixed !important;
top: 80px !important;
box-shadow: $box-shadow-x-large !important;
.main-navigation:has(.hide-navbar) ~ .ds-container .post-add-button {
top: 20px !important;
}
.top-filter-menu {
margin-top: 16px;
}
.top-info-bar,
.top-filter-menu {
.top-info-bar {
display: flex;
align-items: center;
}
.filterButtonMenu {
width: 95%;
position: fixed;
z-index: $z-index-sticky;
margin-top: -45px;
padding: 30px 0px 20px 0px;
background-color: #f5f4f6;
}
.newsfeed-controls {
margin-top: 46px;
margin-top: 8px;
&.newsfeed-controls--no-filter {
margin-top: -16px;
margin-bottom: 16px;
.top-info-bar {
padding-right: 70px;
}
}
}
.main-container .grid-column-helper {
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 357px)) !important;
}
@media screen and (max-width: 656px) {
.filterButtonMenu {
margin-top: -50px;
}
}
#my-filter {
max-width: 1028px;
background-color: white;
@ -433,7 +420,7 @@ export default {
z-index: $z-index-page-submenu;
}
.grid-margin-top {
margin-top: 26px;
margin-top: 8px;
}
@media screen and (min-height: 401px) {
#my-filter {
@ -475,25 +462,9 @@ export default {
padding-bottom: 80px;
}
}
@media screen and (max-width: 1200px) {
.box-add-button-top {
padding-right: 40px;
}
.post-add-button-top {
height: 44px !important;
width: 44px !important;
min-height: 44px !important;
min-width: 44px !important;
font-size: 23px;
}
}
@media screen and (max-width: 650px) {
// .top-filter-menu{
// margin-top: 24px;
// }
.newsfeed-controls {
margin-top: 32px;
margin-top: 8px;
}
}
</style>