# v1.2.0 release notes
# Introduction
In this release, we:
- upgraded
@vue-storefront/corepackage to version2.5.12, which added an optionalmiddlewareUrlproperty to define the URL of the Server Middleware. See its migration guide (opens new window) for more information. Cache control is no longer included into@vue-storefront/corepackage. To use caching see tips and tricks. - upgraded
@storefront-ui/vuepackage to version0.13.0, which removedmobileObserverandSfSlidingSectionand requires addingtype="submit"toSfButtons in forms. - fixed an issue with SfSearchBar and
@keydown.enter
# Migration guide
# Migrating to @vue-storefront/core with v2.5.12
# nuxt.config.js
publicRuntimeConfig: {
theme,
+ middlewareUrl:
+ process.env.NODE_ENV === 'production'
+ ? process.env.API_BASE_URL
+ : 'http://localhost:3000/api/'
},
# .env
+ API_BASE_URL=<URL to the Server Middleware>
# Migrating to @storefront-ui/vue with 0.13.0
# Exclude core-js package
Exclude the core-js package from Babel transpilation, as shown below:
# nuxt.config.js
babel: {
plugins: [
[
'@babel/plugin-proposal-private-methods',
{ loose: true }
]
],
+ exclude: [/\bcore-js\b/, /\bwebpack\/buildin\b/]
},
# pages/Home.vue
# pages/Category.vue
# pages/Product.vue
- middleware: cacheControl({
- 'max-age': 60,
- 'stale-when-revalidate': 5
- }),
# Update SfButton
The SfButton component used in forms now requires the type="submit" attribute. The following components use it in the default theme:
AddReviewcomponentReserPasswordFormcomponentProfileUpdateFormcomponentMyNewsletterpage
<form>
- <SfButton>
+ <SfButton type="submit">
Submit
</SfButton>
</form>
# Remove mobileObserver
# components/AppHeader
<template #navigation>
- <HeaderNavigation :categories="navigation" :isMobile="isMobile" />
+ <HeaderNavigation :categories="navigation" />
</template>
...
- import {
- mapMobileObserver,
- unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';
...
- const isMobile = ref(mapMobileObserver().isMobile.get());
...
- const closeOrFocusSearchBar = () => {
- if (isMobile.value) {
- return closeSearch();
- } else {
- term.value = '';
- return searchBarRef.value.$el.children[0].focus();
- }
+ const clearAndFocusSearchBar = () => {
+ term.value = '';
+ return searchBarRef.value.$el.children[0]?.children[0]?.focus();
...
const onSearchBarIconClick = computed(() =>
term.value
- ? closeOrFocusSearchBar
+ ? clearAndFocusSearchBar
: () => {
isSearchOpen.value
? (isSearchOpen.value = false)
...
- watch(
- () => term.value,
- (newVal, oldVal) => {
- const shouldSearchBeOpened =
- !isMobile.value &&
- term.value.length > 0 &&
- ((!oldVal && newVal) ||
- (newVal.length !== oldVal.length && isSearchOpen.value === false));
- if (shouldSearchBeOpened) {
- isSearchOpen.value = true;
- }
- }
- );
- onBeforeUnmount(() => {
- unMapMobileObserver();
- });
...
return {
accountIcon,
cartTotalItems,
handleAccountClick,
toggleCartSidebar,
toggleWishlistSidebar,
term,
isSearchOpen,
isCheckoutPage,
closeSearch,
handleSearch,
loading,
result,
- closeOrFocusSearchBar,
+ clearAndFocusSearchBar,
searchBarRef,
- isMobile,
isMobileMenuOpen,
products,
navigation,
wishlistTotalItems,
searchBarIcon,
onSearchBarIconClick
};
# components/HeaderNavigation.vue
<template>
- <div class="sf-header__navigation desktop" v-if="!isMobile">
- <SfHeaderNavigationItem
- v-for="(category, key) in categories"
- :key="key"
- class="nav-item"
- v-e2e="`app-header-url_${category.slug}`"
- :label="category.label"
- :link="localePath(`/c${category.slug}`)"
- />
- </div>
- <SfModal v-else :visible="isMobileMenuOpen">
+ <div>
+ <div class="sf-header__navigation desktop">
+ <SfHeaderNavigationItem
+ v-for="(category, key) in categories"
+ :key="key"
+ class="nav-item"
+ v-e2e="`app-header-url_${category.slug}`"
+ :label="category.label"
+ :link="localePath(`/c${category.slug}`)"
+ />
+ </div>
+ <SfModal :visible="isMobileMenuOpen" class="smartphone-only">
<SfHeaderNavigationItem
v-for="(category, key) in categories"
:key="key"
class="nav-item"
v-e2e="`app-header-url_${category.slug}`"
>
<template #desktop-navigation-item>
<SfMenuItem
:label="category.label"
class="sf-header-navigation-item__menu-item"
@click="navigate(`/c${category.slug}`)"
/>
</template>
<template #mobile-navigation-item>
<SfMenuItem
:label="category.label"
class="sf-header-navigation-item__menu-item"
@click="navigate(`/c${category.slug}`)"
/>
</template>
</SfHeaderNavigationItem>
</SfModal>
+ </div>
</template>
...
props: {
- isMobile: {
- type: Boolean,
- default: false
- },
categories: {
type: Array as PropType<Array<SearchResultNavigationItem>>,
default: () => []
}
},
# components/RelatedProducts.vue
- :imageWidth="isMobile ? 154 : 216"
- :imageHeight="isMobile ? 154 : 216"
+ :imageWidth="216"
+ :imageHeight="216"
...
- import {
- mapMobileObserver,
- unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';
...
import {
defineComponent,
- onBeforeUnmount,
- PropType,
- ref
+ PropType
} from '@nuxtjs/composition-api';
...
- const isMobile = ref(mapMobileObserver().isMobile.get());
...
- onBeforeUnmount(() => {
- unMapMobileObserver();
- });
return {
productData,
wishlistHelpers,
wishlist,
isInWishlist,
addItemToWishlist,
removeItemFromWishlist,
isInCart,
addItemToCart,
- getPurchasableDefaultVariant,
- isMobile
+ getPurchasableDefaultVariant
};
...
&__item {
margin: 1.9375rem 0 2.4375rem 0;
}
+
+ ::v-deep .sf-product-card__image .sf-image {
+ --image-width: 9.625rem;
+ --image-height: 9.625rem;
+ @include for-desktop {
+ --image-width: 13.5rem;
+ --image-height: 13.5rem;
+ }
+ }
}
</style>
# layouts/error.vue
- :width="isMobile ? 230 : 412"
- :height="isMobile ? 230 : 412"
+ :width="412"
+ :height="412"
...
- import { computed, useRouter } from '@nuxtjs/composition-api';
+ import { useRouter } from '@nuxtjs/composition-api';
-import { mapMobileObserver } from '@storefront-ui/vue/src/utilities/mobile-observer.js';
...
- const isMobile = computed(() => mapMobileObserver().isMobile.get());
return {
router,
- isMobile,
addBasePath
};
...
- .image {
+
+ ::v-deep .sf-image {
--image-width: 14.375rem;
+ --image-height: 14.375rem;
padding: var(--spacer-xl) 0;
@include for-desktop {
--image-width: 25.75rem;
+ --image-height: 25.75rem;
}
}
# pages/Category.vue
- :imageWidth="isMobile ? 150 : 216"
- :imageHeight="isMobile ? 150 : 216"
+ :imageWidth="216"
+ :imageHeight="216"
...
- :imageWidth="isMobile ? 85 : 140"
- :imageHeight="isMobile ? 113 : 200"
+ :imageWidth="140"
+ :imageHeight="200"
...
import {
computed,
defineComponent,
- onBeforeUnmount,
ref,
useContext,
useMeta
} from '@nuxtjs/composition-api';
- import {
- mapMobileObserver,
- unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';
...
- import cacheControl from './../helpers/cacheControl';
...
- const isMobile = ref(mapMobileObserver().isMobile.get());
...
- onBeforeUnmount(() => {
- unMapMobileObserver();
- });
...
&__product-card {
--product-card-title-margin: var(--spacer-base) 0 0 0;
--product-card-title-font-weight: var(--font-weight--medium);
--product-card-title-margin: var(--spacer-xs) 0 0 0;
flex: 1 1 50%;
@include for-desktop {
--product-card-title-font-weight: var(--font-weight--normal);
--product-card-add-button-bottom: var(--spacer-base);
--product-card-title-margin: var(--spacer-sm) 0 0 0;
}
+ ::v-deep .sf-image {
+ --image-width: 9.375rem;
+ --image-height: 9.375rem;
+ @include for-desktop {
+ --image-width: 13.5rem;
+ --image-height: 13.5rem;
+ }
+ }
}
&__product-card-horizontal {
flex: 0 0 100%;
- @include for-mobile {
- ::v-deep .sf-image {
- --image-width: 5.3125rem;
- --image-height: 7.0625rem;
+ ::v-deep .sf-image {
+ --image-width: 5.3125rem;
+ --image-height: 7.0625rem;
+ @include for-desktop {
+ --image-width: 8.75rem;
+ --image-height: 12.5rem;
}
}
}
# Fixing SfSearchBar component
# components/AppHeader.vue
<SfSearchBar
ref="searchBarRef"
:placeholder="$t('Search for items')"
aria-label="Search"
class="sf-header__search"
:class="{ 'search-hidden': isCheckoutPage }"
:value="term"
@input="handleSearch"
- @keydown.enter="handleSearch($event)"
+ @keyup.enter="handleSearch($event)"
@focus="isSearchOpen = true"
@keydown.esc="closeSearch"
:icon="searchBarIcon"
@click:icon="onSearchBarIconClick"
/>