Skip to content

Commit

Permalink
src/components: update component DrawerMenu styling based on graphic …
Browse files Browse the repository at this point in the history
…design (#576)

* update sidebar color + logo

* update layout background + menu colors

* update tests

* update icons

* unify test data source

* fix padding

* update e2e tests

* src/css: define global SCSS white color var

---------

Co-authored-by: Šimon Macek <[email protected]>
Co-authored-by: Tomas Zigo <[email protected]>
  • Loading branch information
3 people authored Sep 23, 2024
1 parent c238f4c commit 7f03f89
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 96 deletions.
29 changes: 29 additions & 0 deletions public/icons/drawer_menu/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
142 changes: 103 additions & 39 deletions src/components/__tests__/DrawerMenu.cy.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,118 @@
import DrawerMenu from '../global/DrawerMenu.vue';
import { i18n } from '../../boot/i18n';
import { colors } from 'quasar';
import { menuBottom, menuTop } from '../../mocks/layout';

const menuItems = [
{ icon: 'home', name: 'home' },
{ icon: 'route', name: 'routes' },
{ icon: 'emoji_events', name: 'results' },
{ icon: 'people', name: 'community' },
{ icon: 'verified', name: 'discounts' },
{ icon: 'business', name: 'coordinator' },
{ icon: 'account_circle', name: 'profile' },
{
icon: 'email',
name: 'inviteFriends',
},
{
icon: 'volunteer_activism',
name: 'donate',
},
];
// colors
const { getPaletteColor } = colors;
const white = getPaletteColor('white');
const grey4 = getPaletteColor('grey-4');

// selectors
const selectorDrawerMenuItem = 'drawer-menu-item';
const selectorDrawerMenuItemIcon = 'drawer-menu-item-icon';

// variables
const iconSize = 18;
const fontSize = '16px';

describe('DrawerMenu', () => {
beforeEach(() => {
cy.mount(DrawerMenu, {});
});
context('menu top', () => {
beforeEach(() => {
cy.mount(DrawerMenu, {
props: {
items: menuTop,
},
});
cy.wrap(menuTop).as('menu');
});

it('has translation for all strings', () => {
cy.testLanguageStringsInContext(
menuTop.map((item) => item.title),
'drawerMenu',
i18n,
);
});

it('has translation for all strings', () => {
cy.testLanguageStringsInContext(
menuItems.map((item) => item.name),
'drawerMenu',
i18n,
);
coreTests();
});

it('should render the list with the correct number of items', () => {
cy.window().then(() => {
cy.get('.q-item').should('have.length', 9);
context('menu bottom', () => {
beforeEach(() => {
cy.mount(DrawerMenu, {
props: {
items: menuBottom,
},
});
cy.wrap(menuBottom).as('menu');
});

coreTests();
});

it('should render each item with the expected icon and text content', () => {
cy.window().then(() => {
menuItems.forEach((item, index) => {
cy.get('.q-item')
.eq(index)
.within(() => {
cy.get('.q-icon')
.should('be.visible')
.and('contain.text', item.icon);
function coreTests() {
it('should render the list with the correct number of items', () => {
cy.window().then(() => {
cy.get('@menu').then((menu) => {
cy.dataCy(selectorDrawerMenuItem).should('have.length', menu.length);
});
});
});

it('renders items with correct styling', () => {
cy.window().then(() => {
cy.get('@menu').then((menu) => {
cy.dataCy(selectorDrawerMenuItem).each(($item, index) => {
// test if current route
if ($item.hasClass('menu-active-item')) {
// active item
cy.wrap($item)
.should('have.color', white)
.and('have.css', 'font-size', fontSize)
.and('have.css', 'font-weight', '700')
.and(
'contain',
i18n.global.t(`drawerMenu.${menu[index].title}`),
)
.within(() => {
cy.dataCy(selectorDrawerMenuItemIcon).should(
'have.color',
white,
);
cy.dataCy(selectorDrawerMenuItemIcon)
.invoke('width')
.should('be.eq', iconSize);
cy.dataCy(selectorDrawerMenuItemIcon)
.invoke('height')
.should('be.eq', iconSize);
});
} else {
// inactive item
cy.wrap($item)
.should('have.color', white)
.and('have.css', 'font-size', fontSize)
.and('have.css', 'font-weight', '400')
.and(
'contain',
i18n.global.t(`drawerMenu.${menu[index].title}`),
)
.within(() => {
cy.dataCy(selectorDrawerMenuItemIcon).should(
'have.color',
grey4,
);
cy.dataCy(selectorDrawerMenuItemIcon)
.invoke('width')
.should('be.eq', iconSize);
cy.dataCy(selectorDrawerMenuItemIcon)
.invoke('height')
.should('be.eq', iconSize);
});
}
});
});
});
});
});
}
});
2 changes: 1 addition & 1 deletion src/components/global/DrawerHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default defineComponent({
<!-- RTWBB logo -->
<img
class="logo"
src="~assets/svg/logo.svg"
src="~assets/svg/logo-white.svg"
:alt="$t('index.logoAltText')"
data-cy="logo"
/>
Expand Down
61 changes: 28 additions & 33 deletions src/components/global/DrawerMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,66 @@
* Each menu item consists of an icon and a text label, and they are
* displayed in a list format.
*
* @data
* - `menuTop`: Array of menu items to be displayed at the top section.
* - `menuBottom`: Array of menu items to be displayed at the bottom section.
*
* @props
* - `items: (Link[], required) - Array of menu items to be displayed.
*
* @example
* <drawer-menu />
* <drawer-menu :items="menu" />
*
* @see [Figma Design](https://www.figma.com/file/L8dVREySVXxh3X12TcFDdR/Do-pr%C3%A1ce-na-kole?type=design&node-id=5753%3A124675&mode=dev)
*/
// libraries
import { defineComponent } from 'vue';
// mocks
import { menuBottom, menuTop } from '../../mocks/layout';
// types
import { Link } from '../types';
export default defineComponent({
name: 'DrawerMenu',
setup() {
return {
menuTop,
menuBottom,
};
props: {
items: {
type: Array as () => Link[],
required: true,
},
},
});
</script>

<template>
<q-list>
<q-list class="bg-primary">
<!-- Menu: Top items -->
<q-item
v-for="item in menuTop"
v-for="item in items"
:key="item.name"
dark
clickable
:to="{ name: item.name }"
active-class="menu-active-item"
class="flex items-center"
clickable
>
<!-- Link icon -->
<q-icon :name="item.icon" size="xs" color="blue-grey-4" class="q-mr-sm" />
<!-- Link text -->
{{ $t(`drawerMenu.${item.title}`) }}
</q-item>

<q-separator color="blue-grey-2 q-my-sm" />

<!-- Menu: Bottom items -->
<q-item
v-for="item in menuBottom"
:key="item.name"
:to="item.url"
class="flex items-center"
clickable
class="flex text-body1 items-center q-px-lg"
data-cy="drawer-menu-item"
>
<!-- Link icon -->
<q-icon :name="item.icon" size="xs" color="blue-grey-4" class="q-mr-sm" />
<q-icon
:name="item.icon"
size="18px"
color="grey-4"
class="q-mr-md"
data-cy="drawer-menu-item-icon"
/>
<!-- Link text -->
{{ $t(`drawerMenu.${item.title}`) }}
</q-item>
</q-list>
</template>

<style scoped lang="scss">
.menu-active-item {
font-weight: 700;
}
.menu-active-item,
.menu-active-item .q-icon {
color: $blue-grey-10 !important;
color: $white !important;
}
</style>
1 change: 1 addition & 0 deletions src/css/quasar.variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ $accent: #9c27b0;

$dark: #1d1d1d;
$dark-page: #121212;
$white: #fff;

$positive: #21ba45;
$negative: #c10015;
Expand Down
26 changes: 19 additions & 7 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import FooterBar from 'components/global/FooterBar.vue';
import MobileBottomPanel from 'components/global/MobileBottomPanel.vue';
import UserSelect from 'components/global/UserSelect.vue';
// mocks
import { menuBottom, menuTop } from '../mocks/layout';
// config
import { rideToWorkByBikeConfig } from 'src/boot/global_vars';
Expand Down Expand Up @@ -39,6 +42,8 @@ export default defineComponent({
const { containerContentWidth } = rideToWorkByBikeConfig;
return {
containerContentWidth,
menuBottom,
menuTop,
};
},
});
Expand All @@ -64,16 +69,23 @@ export default defineComponent({
show-if-above
side="left"
:width="320"
class="gt-sm bg-info q-py-lg q-px-lg pb-footer"
class="gt-sm bg-primary q-py-lg"
data-cy="q-drawer"
>
<!-- Logo + Buttons (help, notification) -->
<drawer-header :mobile="false" data-cy="drawer-header" />
<!-- User options dropdown -->
<user-select class="q-pt-lg" data-cy="user-select" />
<drawer-toggle-buttons class="q-pt-lg" data-cy="drawer-toggle-buttons" />
<div class="q-px-lg">
<!-- Logo + Buttons (help, notification) -->
<drawer-header :mobile="false" data-cy="drawer-header" />
<!-- User options dropdown -->
<user-select class="q-pt-lg" data-cy="user-select" />
<drawer-toggle-buttons
class="q-pt-lg"
data-cy="drawer-toggle-buttons"
/>
</div>
<!-- Navigation menu -->
<drawer-menu class="q-pt-lg" data-cy="drawer-menu" />
<drawer-menu :items="menuTop" class="q-pt-lg" data-cy="drawer-menu-top" />
<q-separator color="blue-grey-2 q-my-sm q-mx-lg" />
<drawer-menu :items="menuBottom" data-cy="drawer-menu-bottom" />
</q-drawer>

<q-page-container class="bg-white">
Expand Down
Loading

0 comments on commit 7f03f89

Please sign in to comment.