You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
1.9 KiB
104 lines
1.9 KiB
// composables/useCartUI.ts
|
|
|
|
import { useMediaQuery } from '@vueuse/core'
|
|
|
|
/**
|
|
* Cart UI composable
|
|
*
|
|
* Manages cart sidebar/sheet UI state and responsive behavior
|
|
*
|
|
* Features:
|
|
* - Sidebar/sheet open/close state
|
|
* - Responsive detection (mobile vs desktop)
|
|
* - Body scroll lock when cart is open
|
|
* - Global state (shared across all components)
|
|
*
|
|
* Usage:
|
|
* const { isOpen, isMobile, open, close, toggle } = useCartUI()
|
|
*/
|
|
|
|
// Global cart UI state (shared across all components)
|
|
const isOpen = ref(false)
|
|
|
|
export function useCartUI() {
|
|
// Responsive breakpoint: mobile = width < 1024px (lg breakpoint)
|
|
const isMobile = useMediaQuery('(max-width: 1023px)')
|
|
|
|
/**
|
|
* Open cart sidebar/sheet
|
|
*/
|
|
function open() {
|
|
isOpen.value = true
|
|
lockBodyScroll()
|
|
}
|
|
|
|
/**
|
|
* Close cart sidebar/sheet
|
|
*/
|
|
function close() {
|
|
isOpen.value = false
|
|
unlockBodyScroll()
|
|
}
|
|
|
|
/**
|
|
* Toggle cart sidebar/sheet
|
|
*/
|
|
function toggle() {
|
|
if (isOpen.value) {
|
|
close()
|
|
} else {
|
|
open()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Lock body scroll (prevent scrolling when cart is open)
|
|
*/
|
|
function lockBodyScroll() {
|
|
if (import.meta.client) {
|
|
document.body.style.overflow = 'hidden'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unlock body scroll
|
|
*/
|
|
function unlockBodyScroll() {
|
|
if (import.meta.client) {
|
|
document.body.style.overflow = ''
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up: Ensure body scroll is unlocked when component unmounts
|
|
*/
|
|
onUnmounted(() => {
|
|
unlockBodyScroll()
|
|
})
|
|
|
|
/**
|
|
* Watch for route changes: Close cart when navigating
|
|
*/
|
|
if (import.meta.client) {
|
|
const route = useRoute()
|
|
watch(
|
|
() => route.path,
|
|
() => {
|
|
if (isOpen.value) {
|
|
close()
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
return {
|
|
// State
|
|
isOpen: readonly(isOpen),
|
|
isMobile: readonly(isMobile),
|
|
|
|
// Methods
|
|
open,
|
|
close,
|
|
toggle,
|
|
}
|
|
}
|
|
|