feat(ui): unify logistics-style side panel flow

This commit is contained in:
Ruslan Bakiev
2026-04-21 10:46:35 +07:00
parent d3183bf6ad
commit 54aac790ee
8 changed files with 544 additions and 422 deletions

View File

@@ -0,0 +1,86 @@
<script setup lang="ts">
const props = withDefaults(defineProps<{
title?: string
initialCollapsed?: boolean
collapsible?: boolean
positionClass?: string
topOffsetClass?: string
bottomOffsetClass?: string
widthClass?: string
}>(), {
title: '',
initialCollapsed: false,
collapsible: true,
positionClass: 'left-4',
topOffsetClass: 'top-[96px]',
bottomOffsetClass: 'bottom-4',
widthClass: 'w-[min(calc(100vw-1rem),440px)] md:w-[420px] xl:w-[460px]',
})
const collapsed = ref(props.initialCollapsed)
function toggleCollapsed() {
collapsed.value = !collapsed.value
}
</script>
<template>
<div class="pointer-events-none fixed z-40" :class="[positionClass, topOffsetClass, bottomOffsetClass]">
<section
class="pointer-events-auto flex h-full flex-col overflow-hidden rounded-[28px] border-0 bg-[#f3eee6] text-[#2f2418] shadow-[0_28px_70px_rgba(38,29,18,0.18)]"
:class="collapsible && collapsed ? 'w-16 rounded-full' : widthClass"
style="transition: width 260ms ease;"
>
<template v-if="collapsible && collapsed">
<button
type="button"
class="flex h-full w-full cursor-pointer flex-col items-center justify-between px-3 py-3 text-left transition hover:bg-[#eee6dc]"
:aria-expanded="String(!collapsed)"
:aria-label="$t('ui.expand_panel')"
@click="toggleCollapsed"
>
<span class="flex h-10 w-10 items-center justify-center rounded-full bg-white text-[#5f4b33] transition">
<svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m9 6 6 6-6 6" />
</svg>
</span>
<p v-if="title" class="origin-center whitespace-nowrap -rotate-90 text-[11px] font-bold uppercase tracking-[0.14em] text-[#6f6353]">
{{ title }}
</p>
<div class="h-10 w-10" aria-hidden="true" />
</button>
</template>
<template v-else>
<header v-if="title || $slots.header" class="flex shrink-0 items-start justify-between gap-3 border-b border-[#ded3c2] bg-[#f3eee6] px-5 py-4">
<div class="min-w-0 flex-1">
<slot name="header">
<h1 v-if="title" class="truncate text-xl font-black text-[#2f2418] md:text-2xl">{{ title }}</h1>
</slot>
</div>
<button
v-if="collapsible"
type="button"
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-white text-[#5f4b33] transition hover:bg-[#fbf8f4]"
:aria-label="$t('ui.collapse_panel')"
@click="toggleCollapsed"
>
<svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m15 18-6-6 6-6" />
</svg>
</button>
</header>
<div class="min-h-0 flex-1 overflow-y-auto p-4 md:p-5">
<slot />
</div>
<footer v-if="$slots.footer" class="shrink-0 border-t border-[#ded3c2] bg-[#f3eee6] px-4 py-4 md:px-5 md:py-5">
<slot name="footer" />
</footer>
</template>
</section>
</div>
</template>