POS Cart: Horizontal scrollable filters (#5391)

This commit is contained in:
d11n 2023-11-02 08:36:27 +01:00 committed by GitHub
parent e82281d273
commit c979c4774c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 196 additions and 125 deletions

View File

@ -28,8 +28,8 @@
}
<div id="PosCart">
<div id="content" class="public-page-wrap">
<div class="container-xl">
<div id="content">
<div class="public-page-wrap container-xl">
<header class="sticky-top bg-body d-flex flex-column py-3 py-lg-4 gap-3">
<div class="d-flex align-items-center justify-content-center gap-3 pe-5 position-relative">
<h1 class="mb-0">@(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title)</h1>
@ -39,11 +39,13 @@
</button>
</div>
<input id="SearchTerm" class="form-control rounded-pill" placeholder="Search…" v-model="searchTerm">
<div v-if="allCategories" class="btcpay-pills d-flex flex-wrap align-items-center justify-content-center gap-3">
<div id="Categories" ref="categories" v-if="allCategories" :class="{ 'scrollable': categoriesScrollable }">
<nav class="btcpay-pills d-flex align-items-center gap-3" ref="categoriesNav">
<template v-for="cat in allCategories">
<input :id="`Category-${cat.value}`" type="radio" name="category" autocomplete="off" v-model="displayCategory" :value="cat.value">
<label :for="`Category-${cat.value}`" class="btcpay-pill">{{ cat.text }}</label>
<label :for="`Category-${cat.value}`" class="btcpay-pill text-nowrap">{{ cat.text }}</label>
</template>
</nav>
</div>
</header>
<main>
@ -122,8 +124,7 @@
</div>
</div>
<aside id="cart" ref="cart" tabindex="-1" aria-labelledby="cartLabel">
<div class="public-page-wrap" v-cloak>
<div class="container-xl">
<div class="public-page-wrap container-xl" v-cloak>
<header class="sticky-top bg-tile offcanvas-header py-3 py-lg-4 d-flex align-items-baseline justify-content-center gap-3 px-5 pe-lg-0">
<h1 class="mb-0" id="cartLabel">Cart</h1>
<button id="CartClear" type="reset" v-on:click="clearCart" class="btn btn-text text-primary p-1" v-if="cartCount > 0">
@ -243,6 +244,5 @@
<p id="CartItems" v-else class="text-muted text-center my-0">There are no items in your cart yet.</p>
</div>
</div>
</div>
</aside>
</div>

View File

@ -3,7 +3,13 @@
}
#PosCart .public-page-wrap {
padding: 0 0 var(--btcpay-space-l);
padding-top: 0;
}
@media (max-width: 400px) {
#PosCart .public-page-wrap {
padding-left: var(--btcpay-space-s);
padding-right: var(--btcpay-space-s);
}
}
#PosCart .offcanvas-backdrop {
@ -11,6 +17,48 @@
transition-duration: var(--btcpay-transition-duration-fast);
}
#Categories nav {
justify-content: center;
}
#Categories.scrollable {
--scroll-bar-spacing: var(--btcpay-space-m);
--scroll-indicator-spacing: var(--btcpay-space-m);
position: relative;
margin-bottom: calc(var(--scroll-bar-spacing) * -1);
}
#Categories.scrollable nav {
justify-content: start;
overflow: auto visible;
-webkit-overflow-scrolling: touch;
margin-left: calc(var(--scroll-indicator-spacing) * -1);
margin-right: calc(var(--scroll-indicator-spacing) * -1);
padding: 0 var(--scroll-indicator-spacing) var(--scroll-bar-spacing);
}
#Categories.scrollable nav::-webkit-scrollbar {
display: none;
}
/* Horizontal scroll indicators */
#Categories.scrollable:before,
#Categories.scrollable:after {
content: '';
position: absolute;
top: 0;
bottom: 0;
width: var(--btcpay-space-m);
}
#Categories.scrollable:before {
background-image: linear-gradient(to right, var(--btcpay-body-bg), rgba(var(--btcpay-body-bg-rgb), 0));
left: calc(var(--scroll-indicator-spacing) * -1);
}
#Categories.scrollable:after {
background-image: linear-gradient(to left, var(--btcpay-body-bg), rgba(var(--btcpay-body-bg-rgb), 0));
right: calc(var(--scroll-indicator-spacing) * -1);
}
.cart-toggle-btn {
--button-width: 40px;
--button-height: 40px;

View File

@ -44,6 +44,7 @@ document.addEventListener("DOMContentLoaded",function () {
displayCategory: '*',
searchTerm: null,
cart: loadState('cart'),
categoriesScrollable: false,
$cart: null
}
},
@ -180,6 +181,28 @@ document.addEventListener("DOMContentLoaded",function () {
mounted() {
this.$cart = new bootstrap.Offcanvas(this.$refs.cart, { backdrop: false })
if (this.$refs.categories) {
const getInnerNavWidth = () => {
// set to inline display, get width to get the real inner width, then set back to flex
this.$refs.categoriesNav.classList.remove('d-flex');
this.$refs.categoriesNav.classList.add('d-inline-flex');
const navWidth = this.$refs.categoriesNav.clientWidth - 32; // 32 is the margin
this.$refs.categoriesNav.classList.remove('d-inline-flex');
this.$refs.categoriesNav.classList.add('d-flex');
return navWidth;
}
const adjustCategories = () => {
const navWidth = getInnerNavWidth();
Vue.set(this, 'categoriesScrollable', this.$refs.categories.clientWidth < navWidth);
const activeEl = document.querySelector('#Categories .btcpay-pills input:checked + label')
if (activeEl) activeEl.scrollIntoView({ block: 'end', inline: 'center' })
}
window.addEventListener('resize', e => {
debounce('resize', adjustCategories, 50)
});
adjustCategories();
}
window.addEventListener('pagehide', () => {
if (this.payButtonLoading) {
this.unsetPayButtonLoading();