Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Update the Filters button (#1861)
Browse files Browse the repository at this point in the history
Update the VFilterButton
  • Loading branch information
obulat committed Oct 4, 2022
1 parent 6de7e20 commit 908542f
Show file tree
Hide file tree
Showing 23 changed files with 99 additions and 76 deletions.
58 changes: 13 additions & 45 deletions src/components/VHeader/VFilterButton.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
<template>
<VButton
id="filter-button"
:variant="variant"
:variant="filtersAreApplied ? 'action-menu-muted' : 'action-menu'"
size="disabled"
class="align-center flex-shrink-0 gap-2 self-center py-2 font-semibold focus-visible:border-tx focus-visible:ring focus-visible:ring-pink"
:class="
filtersAreApplied
? 'flex-shrink-0 px-3'
: 'h-10 w-10 px-0 md:h-auto md:w-auto md:px-3'
"
class="align-center label-regular h-12 w-12 gap-2 self-center xl:w-auto xl:ps-3"
:class="[filtersAreApplied ? 'xl:pe-3' : 'xl:pe-4']"
:pressed="pressed"
:disabled="disabled"
aria-controls="filters"
:aria-label="mdMinLabel"
:aria-label="xlMinLabel"
@click="$emit('toggle')"
@keydown.tab.exact="$emit('tab', $event)"
>
<VIcon
:class="filtersAreApplied ? 'hidden' : 'block'"
:icon-path="filterIcon"
/>
<span class="hidden md:inline-block">{{ mdMinLabel }}</span>
<span class="md:hidden" :class="!filtersAreApplied && 'hidden'">{{
smMaxLabel
<span class="hidden xl:inline-block">{{ xlMinLabel }}</span>
<span class="xl:hidden" :class="{ hidden: !filtersAreApplied }">{{
lgMaxLabel
}}</span>
</VButton>
</template>

<script lang="ts">
import { computed, defineComponent, inject, ref } from '@nuxtjs/composition-api'
import { computed, defineComponent } from '@nuxtjs/composition-api'
import { useSearchStore } from '~/stores/search'
import { defineEvent } from '~/types/emits'
import type { ButtonVariant } from '~/types/button'
import { useI18n } from '~/composables/use-i18n'
import VButton from '~/components/VButton.vue'
Expand Down Expand Up @@ -63,55 +58,28 @@ export default defineComponent({
setup() {
const i18n = useI18n()
const searchStore = useSearchStore()
const isMinScreenMd = inject('isMinScreenMd', ref(false))
const isHeaderScrolled = inject('isHeaderScrolled', ref(false))
const filterCount = computed(() => searchStore.appliedFilterCount)
const filtersAreApplied = computed(() => filterCount.value > 0)
/**
* Determine the visual style of the button
* based on the viewport, the application of filters, and scrolling.
*/
const variant = computed(() => {
// Show the bordered state by default, unless below md
let value: ButtonVariant = isMinScreenMd.value
? 'action-menu-bordered'
: 'action-menu'
if (isHeaderScrolled.value) {
value = 'action-menu'
}
if (filtersAreApplied.value) {
value = 'action-menu-muted'
}
return value
})
/**
* This label's verbosity makes it useful for the aria-label
* where it is also used, especially on mobile where the
* label would just be the number of applied filters, and therefore
* basically useless as far as a label is concerned!
*/
const mdMinLabel = computed(() =>
const xlMinLabel = computed(() =>
filtersAreApplied.value
? i18n.tc('header.filter-button.with-count', filterCount.value)
: i18n.t('header.filter-button.simple')
)
const smMaxLabel = computed(() =>
isHeaderScrolled.value
? filterCount.value
: i18n.tc('header.filter-button.with-count', filterCount.value)
const lgMaxLabel = computed(() =>
filtersAreApplied ? filterCount.value : ''
)
return {
filterCount,
filterIcon,
mdMinLabel,
smMaxLabel,
variant,
isHeaderScrolled,
xlMinLabel,
lgMaxLabel,
filtersAreApplied,
}
},
Expand Down
33 changes: 18 additions & 15 deletions src/components/VHeader/meta/VFilterButton.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Meta,
Story,
} from '@storybook/addon-docs'
import { provide, ref } from '@nuxtjs/composition-api'
import VFilterButton from '~/components/VHeader/VFilterButton.vue'
import { useSearchStore } from '~/stores/search'
import { filterData, mediaFilterKeys } from '~/constants/filters'
Expand All @@ -21,23 +20,24 @@ import { IMAGE } from '~/constants/media'
appliedFilters: {
type: 'number',
},
scrolled: {
type: 'boolean',
toggle: {
action: 'toggle',
},
isMinMd: {
type: 'boolean',
tab: {
action: 'tab',
},
}}
/>

export const Template = (args, { argTypes }) => ({
template: `<VFilterButton v-bind="args" />`,
template: `<VFilterButton v-bind="args" v-on="args" />`,
components: { VFilterButton },
props: Object.keys(argTypes),
setup() {
const searchStore = useSearchStore()
searchStore.setSearchType(IMAGE)
function applyNFilters(filterCount) {
searchStore.clearFilters()
const filterTypes = [...mediaFilterKeys[IMAGE]]
let filterIdx = 0
// Skip license type filters as they can disable license filters
Expand All @@ -56,12 +56,6 @@ export const Template = (args, { argTypes }) => ({
}
}
applyNFilters(args.appliedFilters)
if (args.scrolled) {
provide('isHeaderScrolled', ref(true))
}
if (args.isMinMd) {
provide('isMinScreenMd', ref(true))
}
return { args }
},
})
Expand All @@ -78,15 +72,24 @@ the field receives an input. It also emits the `search` event when the search
button is clicked.

<Canvas>
<Story name="Default">{Template.bind({})}</Story>
<Story
name="Default"
parameters={{
viewport: {
defaultViewport: 'lg',
},
}}
>
{Template.bind({})}
</Story>
</Canvas>

<Canvas>
<Story
name="Mobile Scrolled"
name="With text label"
parameters={{
viewport: {
defaultViewport: 'iphonex',
defaultViewport: 'xl',
},
}}
>
Expand Down
60 changes: 60 additions & 0 deletions test/storybook/visual-regression/v-filter-button-old.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { test } from '@playwright/test'

import breakpoints from '~~/test/playwright/utils/breakpoints'
import { makeGotoWithArgs } from '~~/test/storybook/utils/args'

const gotoWithArgs = makeGotoWithArgs(
'components-vheaderold-vfilterbuttonold--default-story'
)

test.describe.configure({ mode: 'parallel' })

test.describe('VFilterButtonOld', () => {
breakpoints.describeMd(({ expectSnapshot }) => {
test('no filters applied', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true })
await expectSnapshot('filter-button-old-at-rest', page)
})

test('no filters pressed', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true, pressed: true })
await expectSnapshot('filter-button-old-pressed', page)
})

test('filters applied', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true, appliedFilters: 2 })
await expectSnapshot('filter-button-old-2-filters', page)
})

test('filters applied and pressed', async ({ page }) => {
await gotoWithArgs(page, {
isMinMd: true,
appliedFilters: 2,
pressed: true,
})
await expectSnapshot('filter-button-old-2-filters-pressed', page)
})
})

breakpoints.describeXs(({ expectSnapshot }) => {
test('no filters applied and not scrolled', async ({ page }) => {
await gotoWithArgs(page)
await expectSnapshot('filter-button-old-no-filters-not-scrolled', page)
})

test('no filters but scrolled', async ({ page }) => {
await gotoWithArgs(page, { scrolled: true })
await expectSnapshot('filter-button-old-no-filters-scrolled', page)
})

test('2 filters not scrolled', async ({ page }) => {
await gotoWithArgs(page, { appliedFilters: 2 })
await expectSnapshot('filter-button-old-2-filters-not-scrolled', page)
})

test('2 filters and scrolled', async ({ page }) => {
await gotoWithArgs(page, { appliedFilters: 2, scrolled: true })
await expectSnapshot('filter-button-old-2-filters-scrolled', page)
})
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 8 additions & 16 deletions test/storybook/visual-regression/v-filter-button.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ const gotoWithArgs = makeGotoWithArgs(
'components-vheader-vfilterbutton--default-story'
)

test.describe.configure({ mode: 'parallel' })

test.describe('VFilterButton', () => {
breakpoints.describeMd(({ expectSnapshot }) => {
breakpoints.describeLg(({ expectSnapshot }) => {
test('no filters applied', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true })
await expectSnapshot('filter-button-at-rest', page)
})

test('no filters pressed', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true, pressed: true })
await gotoWithArgs(page, { pressed: true })
await expectSnapshot('filter-button-pressed', page)
})

test('filters applied', async ({ page }) => {
await gotoWithArgs(page, { isMinMd: true, appliedFilters: 2 })
await gotoWithArgs(page, { appliedFilters: 2 })
await expectSnapshot('filter-button-2-filters', page)
})

Expand All @@ -34,25 +36,15 @@ test.describe('VFilterButton', () => {
})
})

breakpoints.describeXs(({ expectSnapshot }) => {
test('no filters applied and not scrolled', async ({ page }) => {
breakpoints.describeXl(({ expectSnapshot }) => {
test('no filters applied', async ({ page }) => {
await gotoWithArgs(page)
await expectSnapshot('filter-button-no-filters-not-scrolled', page)
})

test('no filters but scrolled', async ({ page }) => {
await gotoWithArgs(page, { scrolled: true })
await expectSnapshot('filter-button-no-filters-scrolled', page)
})

test('2 filters not scrolled', async ({ page }) => {
test('2 filters', async ({ page }) => {
await gotoWithArgs(page, { appliedFilters: 2 })
await expectSnapshot('filter-button-2-filters-not-scrolled', page)
})

test('2 filters and scrolled', async ({ page }) => {
await gotoWithArgs(page, { appliedFilters: 2, scrolled: true })
await expectSnapshot('filter-button-2-filters-scrolled', page)
})
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 908542f

Please sign in to comment.