<Feat>:标签基本功能提交

This commit is contained in:
赵帅 2022-10-02 16:38:32 +08:00
parent fc79738ccb
commit 42e6c8c0e6
7 changed files with 201 additions and 29 deletions

View File

@ -8,6 +8,7 @@ export const tabPageProps = {
title: { type: String, default: '' },
selected: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
removeable: { type: Boolean, default: false }
removeable: { type: Boolean, default: false },
show: { type: Boolean, default: true }
};
export type TabPageProps = ExtractPropTypes<typeof tabPageProps>;

View File

@ -0,0 +1,19 @@
import { computed, ComputedRef, Ref, ref, SetupContext, watch } from 'vue';
import { TabsProps } from '../tabs.props';
export function useTabs(
props: TabsProps,
context: SetupContext
): any {
function setActiveId(tabs: Ref<any[]>, activeId: Ref) {
const index = tabs.value.findIndex(tab => tab.show !== false && !activeId.value && !tab.disabled)
if (!activeId.value && index !== -1) {
activeId.value = tabs.value[index].id
}
}
return {
setActiveId
};
}

View File

@ -1,12 +1,14 @@
import { computed, defineComponent, ref, SetupContext } from 'vue';
import { TabsProps, tabsProps } from './tabs.props';
import './tabs.css'
import { useTabs } from './composition/use-tabs';
export default defineComponent({
name: 'FTabs',
props: tabsProps,
emits: [],
setup(props: TabsProps, context: SetupContext) {
const hideButtons = ref(false);
const hideButtons = ref(true);
const hideDropDown = ref(false);
@ -20,7 +22,9 @@ export default defineComponent({
const position = ref(props.position);
const tabs = ref([]);
const tabs = ref([] as any[]);
const activeId = ref(props.activeId);
const shouldShowNavFill = computed(() => {
fill.value || tabType.value === 'fill';
@ -28,6 +32,8 @@ export default defineComponent({
const shouldShowNavPills = computed(() => {});
const { setActiveId } = useTabs(props, context)
const tabsHeaderClass = computed(() => ({
'farris-tabs-header': true,
'farris-tabs-inHead': hasInHeadClass.value,
@ -64,16 +70,39 @@ export default defineComponent({
'flex-row': position.value === 'top' || position.value === 'bottom',
'flex-column': position.value === 'left' || position.value === 'right',
}));
let tabPages = context.slots.default && context.slots.default()
tabPages?.forEach((tabPage: any) => {
tabs.value.push(tabPage.props)
})
setActiveId(tabs, activeId)
const tabsContainerClass = computed(() => ({
'farris-tabs': true,
'farris-tabs-top': position.value === 'top',
'farris-tabs-bottom': position.value === 'bottom',
'farris-tabs-left': position.value === 'left',
'farris-tabs-right': position.value === 'right'
}))
function getTabClass(tab: any) {
return {
'nav-item': true,
'd-none': !tab.show,
'f-state-active': tab.id === activeId,
'd-none': tab.show !== undefined ? !tab.show : false,
'f-state-active': tab.id === activeId.value,
'f-state-disable': tab.disabled,
};
}
function getTabPageStyle(tabPage) {
const props: any = tabPage.props
return {
display: props.id === activeId.value ? '' : 'none'
}
}
function getTabStyle(tab: any) {
return { width: `${tab.tabWidth}px` };
}
@ -81,13 +110,17 @@ export default defineComponent({
function getTabNavLinkClass(tab: any) {
return {
'nav-link': true,
'tabs-text-truncate': true,
active: tab.id === activeId,
// 'tabs-text-truncate': true,
active: tab.id === activeId.value,
disabled: tab.disabled,
};
}
function selectTabByIndex($event: Event, targetTabId: string) {}
function selectTabByIndex($event: Event, targetTabId: string) {
activeId.value = targetTabId
$event.preventDefault();
$event.stopPropagation();
}
function getTabTextClass(tab: any) {
return {
@ -97,33 +130,52 @@ export default defineComponent({
};
}
function removeTab($event: Event, targetTabId: string) {
tabs.value = tabs.value.filter(tab => tab.id !== targetTabId)
tabPages = tabPages?.filter(tabPage => (tabPage.props as any).id !== targetTabId)
if (activeId.value === targetTabId) {
activeId.value = ''
setActiveId(tabs, activeId)
}
$event.preventDefault();
$event.stopPropagation();
}
return () => {
return (
<>
<div class={tabsHeaderClass.value}>
<div class="farris-tabs-title scroll-tabs" style={tabsTitleStyle.value}>
<button type="button" class={tabsTitleButtonClass.value}></button>
<div class={tabParentClass.value} style="width:100%">
<ul class={tabContainerClass.value}>
{tabs.value.forEach((tab: any, tabIndex) => {
return (
<li class={getTabClass(tab)} style={getTabStyle(tab)}>
<a class={getTabNavLinkClass(tab)} onClick={($event) => selectTabByIndex($event, tab.id)}>
<span class={getTabTextClass(tab)}>{tab.title}</span>
{tab.removeable && (
<span class="st-drop-close">
<i class="f-icon f-icon-close"></i>
</span>
)}
</a>
</li>
);
})}
</ul>
<div class={tabsContainerClass.value}>
<div class={tabsHeaderClass.value}>
<div class="farris-tabs-title scroll-tabs" style={tabsTitleStyle.value}>
<button type="button" class={tabsTitleButtonClass.value}></button>
<div class={tabParentClass.value} style="width:100%">
<ul class={tabContainerClass.value}>
{tabs.value.map((tab: any) => {
return (
<li class={getTabClass(tab)} style={getTabStyle(tab)}>
<a class={getTabNavLinkClass(tab)} onClick={($event) => selectTabByIndex($event, tab.id)}>
<span class={getTabTextClass(tab)}>{tab.title}</span>
{tab.removeable && (
<span class="st-drop-close" onClick={($event) => removeTab($event, tab.id)}>
<i class="f-icon f-icon-close"></i>
</span>
)}
</a>
</li>
);
})}
</ul>
</div>
</div>
</div>
<div class="farris-tabs-content">
{
tabPages?.map(tabPage => {
return <div class="farris-tab-page" style={getTabPageStyle(tabPage)}>{tabPage}</div>
})
}
</div>
</div>
{context.slots.default && context.slots.default()}
</>
);
};

View File

@ -0,0 +1,84 @@
.farris-tabs {
box-sizing: border-box;
margin: 0;
padding: 0;
color: #000000d9;
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: "tnum";
display: flex;
overflow: hidden;
}
.farris-tabs.farris-tabs-top {
flex-direction: column;
}
.farris-tabs.farris-tabs-top .farris-tabs-header{
margin-bottom: 12px;
}
.farris-tabs.farris-tabs-bottom {
flex-direction: column-reverse;
}
.farris-tabs.farris-tabs-left {
flex-direction: row;
}
.farris-tabs.farris-tabs-right {
flex-direction: row-reverse;
}
.farris-tabs-header {
position: relative;
display: flex;
flex: none;
align-items: center;
}
.farris-tabs-header .nav-item {
position: relative;
display: inline-flex;
align-items: center;
font-size: 14px;
background: transparent;
border: 1px solid #ddd;
outline: none;
cursor: pointer;
margin-right: 30px;
line-height: 20px;
box-sizing: content-box;
}
.farris-tabs-header .nav-item.f-state-active {
border-bottom: 1px solid #1890ff;
}
.farris-tabs-header .nav-item .nav-link {
font-weight: normal;
}
.farris-tabs-header .nav-item.f-state-active .nav-link {
color: #1890ff;
text-shadow: 0 0 .25px #f1f1f1;
}
.farris-tabs-header .nav-item.f-state-disable {
cursor: not-allowed;
}
.farris-tabs-content {
flex: auto;
min-width: 0;
min-height: 0;
}
.farris-tabs-content .farris-tab-page {
flex: none;
width: 100%;
outline: none;
}

View File

@ -19,6 +19,7 @@ export const tabsProps = {
searchBoxVisible: { type: Boolean, default: true },
titleWidth: { type: Number, default: 0 },
customClass: { type: String, default: '' },
activeId: { type: String }
};
export type TabsProps = ExtractPropTypes<typeof tabsProps>;

View File

@ -5,6 +5,7 @@ import { ref } from "vue";
import HelloWorld from './components/hello-world.vue';
import ButtonEdit from "../components/button-edit/src/button-edit.component";
import Avatar from './components/avatar.vue';
import Tabs from './components/tabs.vue'
const canEdit = ref(true);
const canAutoComplete = ref(false);
@ -27,6 +28,7 @@ const canAutoComplete = ref(false);
<HelloWorld msg="Vite + Vue" />
<ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></ButtonEdit>
<Avatar></Avatar>
<Tabs />
</template>
<style scoped>

View File

@ -0,0 +1,13 @@
<script setup lang="ts">
import FTab from '../../components/tabs/src/tabs.component'
import FTabPage from '../../components/tabs/src/components/tab-page.component'
</script>
<template>
<FTab>
<FTabPage id="Tab0" title="Tab0" :show="false">Content of Tab Page 0</FTabPage>
<FTabPage id="Tab1" title="Tab1" :removeable="true">Content of Tab Page 1</FTabPage>
<FTabPage id="Tab2" title="Tab2" :disabled="true" :removeable="true">Content of Tab Page 2</FTabPage>
<FTabPage id="Tab3" title="Tab3" :removeable="true">Content of Tab Page 3</FTabPage>
</FTab>
</template>