From d553e38ab4822f2637543105b98677cf25fab68d Mon Sep 17 00:00:00 2001 From: sight <1453017105@qq.com> Date: Tue, 31 May 2022 21:27:04 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=80(component):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20tab=20=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/src/component/tab/index.less | 100 ++++++++++++------ package/component/src/component/tab/index.vue | 49 +++++++++ 2 files changed, 118 insertions(+), 31 deletions(-) diff --git a/package/component/src/component/tab/index.less b/package/component/src/component/tab/index.less index 4bca3d68..0aca8a1e 100644 --- a/package/component/src/component/tab/index.less +++ b/package/component/src/component/tab/index.less @@ -75,15 +75,14 @@ border-bottom-style: none; } -.layui-tab-title.is-left li, -.layui-tab-title.is-right li { - border: none; - border-radius: 0; +.layui-tab-title.is-left li { display: list-item; margin-right: -1px; - margin-left: -1px; } - +.layui-tab-title.is-right li{ + display: list-item; + margin-left: -1px; +} .layui-tab-title.is-right { border-left: 1px solid var(--global-neutral-color-3); @@ -93,14 +92,6 @@ border-right: 1px solid var(--global-neutral-color-3); } -.layui-tab-title.is-right .layui-this { - border-left-color: #FFF; -} - -.layui-tab-title.is-left .layui-this { - border-right-color: #FFF; -} - .layui-tab-title .layui-this { color: #000; background-color: #fff @@ -143,7 +134,6 @@ .layui-tab-brief>.layui-tab-head>.layui-tab-title .layui-this:after { border: none; border-radius: 0; - border-bottom: 2px solid var(--global-checked-color); } .layui-tab-brief>.layui-tab-head.is-right>.layui-tab-title{ @@ -157,20 +147,15 @@ top: -1px; } -.layui-tab-brief > .layui-tab-head.is-left > .layui-tab-more li.layui-this:after, -.layui-tab-brief > .layui-tab-head.is-left > .layui-tab-title .layui-this:after { - border: none; - border-radius: 0; - border-right: 2px solid var(--global-checked-color); - margin-left: 1px; +.layui-tab-brief>.layui-tab-head.is-right>.layui-tab-title li, +.layui-tab-brief>.layui-tab-head.is-left>.layui-tab-title li{ + margin-right: 0px; } -.layui-tab-brief > .layui-tab-head.is-right > .layui-tab-more li.layui-this:after, -.layui-tab-brief > .layui-tab-head.is-right > .layui-tab-title .layui-this:after { - border: none; - border-radius: 0; - border-left: 2px solid var(--global-checked-color); - margin-right: 1px; +.layui-tab-brief>.layui-tab-head.is-top>.layui-tab-title li, +.layui-tab-brief>.layui-tab-head.is-top>.layui-tab-title li { + margin-top: 0px; + margin-bottom: 0px; } .layui-tab-card { @@ -180,15 +165,32 @@ box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1); } -.layui-tab-card>.layui-tab-head>.layui-tab-title li { +.layui-tab-card>.layui-tab-head>.layui-tab-title.is-top { + margin-top: -1px; +} + +.layui-tab-card>.layui-tab-head>.layui-tab-title.is-right, +.layui-tab-card>.layui-tab-head>.layui-tab-title.is-left { margin-right: -1px; margin-left: -1px; } +.layui-tab-card>.layui-tab-head>.layui-tab-title.is-bottom li { + margin-top: -1px; +} + +.layui-tab-card>.layui-tab-head>.layui-tab-title .layui-this:after{ + border-radius: 0; +} +.layui-tab-card>.layui-tab-head>.layui-tab-title.is-bottom{ + border-top: 1px solid var(--global-neutral-color-3); + margin-bottom: -2px; +} + .layui-tab-card>.layui-tab-head>.layui-tab-title.is-left li, .layui-tab-card>.layui-tab-head>.layui-tab-title.is-right li { - margin-top: -1px; - margin-bottom: -1px; + margin-top: -1px; + margin-bottom: -1px; } .layui-tab-card>.layui-tab-head>.layui-tab-title.is-top .layui-this:after { @@ -309,4 +311,40 @@ padding: 0 10px; display: inline-block; vertical-align: top; -} \ No newline at end of file +} + + +.layui-tab-active-bar{ + position: absolute; + bottom: 0px; + left: 0; + height: 1.5px; + background-color: #409eff; + z-index: 2; + transition: transform .3s; + list-style: none; + box-sizing: border-box; + pointer-events: none; +} +.is-top .layui-tab-active-bar{ + bottom: 0px; + height: 1.5px; +} + +.is-left .layui-tab-active-bar { + left: auto; + right: -1px; + top: 0; + bottom: auto; + width: 1.5px; +} + +.is-right .layui-tab-active-bar { + left: -1px; + right: auto; + top: 0; + bottom: auto; + width: 1.5px; +} + + diff --git a/package/component/src/component/tab/index.vue b/package/component/src/component/tab/index.vue index 18d78b03..8d8ce210 100644 --- a/package/component/src/component/tab/index.vue +++ b/package/component/src/component/tab/index.vue @@ -16,7 +16,12 @@ import { Ref, ref, watch, +shallowRef, +onMounted, +nextTick, +CSSProperties, } from "vue"; +import { useResizeObserver } from '@vueuse/core' export type tabPositionType = "top" | "bottom" | "left" | "right"; @@ -81,6 +86,35 @@ const close = function (index: number, id: any) { emit("close", id); }; +const activeBarRef = shallowRef(); +const activeEl = shallowRef(); +const tabBarStyle = ref() +const getBarStyle = () => { + let offset = 0; + let tabSize = 0; + const sizeName = props.tabPosition === "top" || props.tabPosition === "bottom" ? "width" : "height"; + const axis = sizeName === "width" ? "X" : "Y"; + const position = axis === 'X' ? 'left' : 'top' + const el = activeEl.value; + if(!el || !el.parentElement) return; + const rect = el.getBoundingClientRect(); + const parentRect = el.parentElement?.getBoundingClientRect(); + offset = rect[position] - parentRect[position]; + tabSize = el.getBoundingClientRect()[sizeName]; + return { + [sizeName]: `${tabSize}px`, + transform: `translate${axis}(${offset}px)`, + } +} +const update = () => { + const parentEL = activeBarRef.value?.parentNode; + activeEl.value = parentEL?.querySelector(" .layui-this") as HTMLElement; + tabBarStyle.value = getBarStyle(); +} + +const containerSize = ""; +const navSize = ""; + watch( slotsChange, function () { @@ -90,6 +124,18 @@ watch( { immediate: true } ); +watch( + () => [props.modelValue, props.tabPosition, props.type], + async () => { + await nextTick(); + update(); + } +) + +onMounted(() => { + update(); +}) + provide("active", active); provide("slotsChange", slotsChange); @@ -111,11 +157,13 @@ provide("slotsChange", slotsChange); props.tabPosition ? `is-${tabPosition}` : '', ]" > +
  • {{ children.props?.title }}
  • +