fix: tabhead and scrolling issue (#2966)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
Anwarul Islam
2023-04-05 21:56:42 +06:00
committed by GitHub
parent 1d397af674
commit 62058d5dfe
6 changed files with 128 additions and 50 deletions

View File

@@ -4,6 +4,7 @@
"version": "0.0.1",
"type": "module",
"scripts": {
"watch": "vite build --watch",
"build": "vite build",
"story:dev": "histoire dev",
"story:build": "histoire build",

View File

@@ -21,23 +21,32 @@ import { TabMeta, TabProvider } from "./Windows.vue"
const slots = useSlots()
const props = defineProps({
label: { type: String, default: null },
info: { type: String, default: null },
id: { type: String, default: null, required: true },
isRemovable: { type: Boolean, default: true },
selected: {
type: Boolean,
default: false,
},
})
const props = withDefaults(
defineProps<{
label: string | null
info: string | null
id: string
isRemovable: boolean
closeVisibility: "hover" | "always" | "never"
selected: boolean
}>(),
{
label: null,
info: null,
isRemovable: true,
closeVisibility: "always",
selected: false,
}
)
const tabMeta = computed<TabMeta>(() => ({
info: props.info,
label: props.label,
isRemovable: props.isRemovable,
icon: slots.icon,
tabhead: slots.tabhead
suffix: slots.suffix,
tabhead: slots.tabhead,
closeVisibility: props.closeVisibility,
}))
const {

View File

@@ -1,43 +1,95 @@
<template>
<div class="flex flex-col flex-1 h-auto overflow-y-hidden flex-nowrap">
<div class="relative sticky top-0 z-10 flex-shrink-0 overflow-x-auto tabs bg-primaryLight">
<div class="flex flex-1 flex-shrink-0 w-0 overflow-x-auto" ref="scrollContainer">
<div class="flex justify-between divide-x divide-dividerLight" @wheel="scrollOnWindows">
<div
class="relative sticky top-0 z-10 flex-shrink-0 overflow-x-auto tabs bg-primaryLight"
>
<div
class="flex flex-1 flex-shrink-0 w-0 overflow-x-auto"
ref="scrollContainer"
>
<div
class="flex justify-between divide-x divide-dividerLight"
@wheel.prevent="scroll"
>
<div class="flex">
<draggable v-bind="dragOptions" :list="tabEntries" :style="tabStyles" :item-key="'window-'"
class="flex flex-shrink-0 overflow-x-auto transition divide-x divide-dividerLight" @sort="sortTabs">
<draggable
v-bind="dragOptions"
:list="tabEntries"
:style="tabStyles"
:item-key="'window-'"
class="flex flex-shrink-0 overflow-x-auto transition divide-x divide-dividerLight"
@sort="sortTabs"
>
<template #item="{ element: [tabID, tabMeta] }">
<button :key="`removable-tab-${tabID}`" class="tab" :class="[{ active: modelValue === tabID }]"
:aria-label="tabMeta.label || ''" role="button" @keyup.enter="selectTab(tabID)"
@click="selectTab(tabID)">
<button
:key="`removable-tab-${tabID}`"
class="tab group px-2"
:class="[{ active: modelValue === tabID }]"
:aria-label="tabMeta.label || ''"
role="button"
@keyup.enter="selectTab(tabID)"
@click="selectTab(tabID)"
>
<span
v-if="tabMeta.icon"
class="flex items-center justify-center cursor-pointer"
>
<component :is="tabMeta.icon" class="w-4 h-4 svg-icons" />
</span>
<div v-if="!tabMeta.tabhead" class="flex items-stretch truncate">
<span v-if="tabMeta.icon" class="flex items-center justify-center mx-4 cursor-pointer">
<component :is="tabMeta.icon" class="w-4 h-4 svg-icons" />
</span>
<span class="truncate pl-4">
<div
v-if="!tabMeta.tabhead"
class="truncate w-full text-left px-2"
>
<span class="truncate">
{{ tabMeta.label }}
</span>
</div>
<div v-else class="truncate flex items-center justify-start mx-4">
<div v-else class="truncate w-full text-left">
<component :is="tabMeta.tabhead" />
</div>
<HoppButtonSecondary v-tippy="{ theme: 'tooltip', delay: [500, 20] }" :icon="IconX" :style="{
display: tabMeta.isRemovable ? 'flex' : 'none',
}" :title="closeText ?? t?.('action.close') ?? 'Close'"
:class="[{ active: modelValue === tabID }, 'close']" class="mx-2 !p-0.5"
@click.stop="emit('removeTab', tabID)" />
<component v-if="tabMeta.suffix" :is="tabMeta.suffix" />
<HoppButtonSecondary
v-if="tabMeta.isRemovable"
v-tippy="{ theme: 'tooltip', delay: [500, 20] }"
:icon="IconX"
:title="closeText ?? t?.('action.close') ?? 'Close'"
:class="[
{ active: modelValue === tabID },
{
flex: tabMeta.closeVisibility === 'always',
'group-hover:flex hidden':
tabMeta.closeVisibility === 'hover',
hidden: tabMeta.closeVisibility === 'never',
},
'close',
]"
class="!p-0.5"
@click.stop="emit('removeTab', tabID)"
/>
</button>
</template>
</draggable>
</div>
<div class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-8">
<div
class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-8"
>
<slot name="actions">
<span v-if="canAddNewTab" class="flex items-center justify-center px-2 py-1.5 bg-primaryLight z-8">
<HoppButtonSecondary v-tippy="{ theme: 'tooltip' }" :title="newText ?? t?.('action.new') ?? 'New'"
:icon="IconPlus" class="rounded !p-1" filled @click="addTab" />
<span
v-if="canAddNewTab"
class="flex items-center justify-center px-2 py-1.5 bg-primaryLight z-8 h-full"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="newText ?? t?.('action.new') ?? 'New'"
:icon="IconPlus"
class="rounded !p-1"
filled
@click="addTab"
/>
</span>
</slot>
</div>
@@ -66,9 +118,11 @@ import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
export type TabMeta = {
label: string | null
icon: Slot | undefined
suffix: Slot | undefined
tabhead: Slot | undefined
info: string | null
isRemovable: boolean
closeVisibility: "hover" | "always" | "never"
}
export type TabProvider = {
// Whether inactive tabs should remain rendered
@@ -187,12 +241,11 @@ const addTab = () => {
emit("addTab")
}
const scrollContainer = ref<HTMLElement|null>(null)
const scrollContainer = ref<HTMLElement | null>(null)
const scrollOnWindows = (event: WheelEvent) => {
event.preventDefault()
if(scrollContainer.value)
scrollContainer.value.scrollLeft += event.deltaY
const scroll = (e: WheelEvent) => {
scrollContainer.value!.scrollLeft += e.deltaY
scrollContainer.value!.scrollLeft += e.deltaX
}
</script>