完成tabs组件

master
yutent 2023-04-17 18:40:45 +08:00
parent bfeb588858
commit 707dd7d8cc
1 changed files with 178 additions and 18 deletions

View File

@ -13,6 +13,7 @@ import {
styleMap, styleMap,
classMap classMap
} from '@bd/core' } from '@bd/core'
import '../icon/index.js'
class Tabs extends Component { class Tabs extends Component {
static props = { static props = {
@ -54,7 +55,12 @@ class Tabs extends Component {
user-select: none; user-select: none;
} }
.navs {
display: flex;
}
.content { .content {
flex: 1;
padding: 16px 0; padding: 16px 0;
} }
@ -62,6 +68,7 @@ class Tabs extends Component {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: space-between;
max-width: 120px; max-width: 120px;
margin: 0 16px; margin: 0 16px;
--size: 16px; --size: 16px;
@ -79,10 +86,38 @@ class Tabs extends Component {
margin-right: 0; margin-right: 0;
} }
&:hover, &:hover:not([disabled]),
&.active { &.active {
color: var(--color-teal-1); color: var(--color-teal-1);
} }
&[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
.close {
display: none;
flex-shrink: 0;
width: 14px;
height: 14px;
margin-left: 4px;
padding: 3px;
border-radius: 50px;
color: var(--color-dark-1);
transition: background 0.2s ease-in, color 0.2s ease-in;
}
&[closable='true'] {
.close:hover {
background: var(--color-red-1);
color: #fff;
}
&:hover .close {
display: inline-flex;
}
}
} }
`, `,
@ -124,6 +159,9 @@ class Tabs extends Component {
max-width: 120px; max-width: 120px;
border-bottom: 0; border-bottom: 0;
} }
.navs {
flex-direction: column;
}
.content { .content {
padding: 0 16px; padding: 0 16px;
} }
@ -179,11 +217,13 @@ class Tabs extends Component {
background: var(--color-plain-1); background: var(--color-plain-1);
} }
} }
`,
// type folder
css`
:host([type='folder']) { :host([type='folder']) {
.header { .header {
overflow: hidden; overflow: hidden;
padding-left: 6px; padding: 0 6px;
} }
.content { .content {
@ -232,8 +272,48 @@ class Tabs extends Component {
} }
} }
} }
&:host([tab-position='left']),
&:host([tab-position='right']) {
.header {
flex-direction: column;
width: auto;
height: auto;
padding: 4px 0;
}
.navs {
flex-direction: column;
}
.label {
height: 38px;
padding-top: 0;
}
} }
&:host([tab-position='left']) {
.label {
justify-content: flex-end;
&::before {
border-radius: 6px 0 0 6px;
transform: perspective(120px) rotateY(-20deg) translateX(-6px);
box-shadow: -1px 0 6px rgba(0, 0, 0, 0.1);
}
}
}
&:host([tab-position='right']) {
.label {
&::before {
border-radius: 0 6px 6px 0;
transform: perspective(120px) rotateY(20deg) translateX(6px);
box-shadow: -1px 0 6px rgba(0, 0, 0, 0.1);
}
}
}
}
`,
// type card
css`
:host([type='card']) { :host([type='card']) {
border: 1px solid var(--color-plain-3); border: 1px solid var(--color-plain-3);
background: #fff; background: #fff;
@ -251,6 +331,63 @@ class Tabs extends Component {
background: #fff; background: #fff;
} }
} }
&:host([tab-position='bottom']) {
.header {
box-shadow: inset 0 1px 0 0px var(--color-plain-3);
}
.label {
border-top: 1px solid var(--color-plain-3);
border-bottom: 0;
&.active {
border-top-color: transparent;
}
}
}
&:host([tab-position='left']),
&:host([tab-position='right']) {
.header {
flex-direction: column;
width: auto;
height: auto;
}
.navs {
flex-direction: column;
}
.label {
height: 38px;
padding-top: 0;
&:last-child {
border-bottom: 0;
}
&.active {
background: #fff;
}
}
}
&:host([tab-position='left']) {
.label {
&.active {
border-bottom-color: var(--color-plain-3);
border-right-color: transparent;
}
}
}
&:host([tab-position='right']) {
.label {
border-left: 1px solid var(--color-plain-3);
border-right: 0;
&.active {
border-bottom-color: var(--color-plain-3);
border-left-color: transparent;
}
}
}
} }
` `
] ]
@ -307,6 +444,10 @@ class Tabs extends Component {
return return
} }
if (this.labels[+elem.dataset.i].disabled) {
return
}
// 非默认类型, 不显示active-bar // 非默认类型, 不显示active-bar
if (gaps) { if (gaps) {
this.#tabWidth = elem.clientWidth this.#tabWidth = elem.clientWidth
@ -328,6 +469,15 @@ class Tabs extends Component {
.then(_ => this.#cache[key].panel.$animate()) .then(_ => this.#cache[key].panel.$animate())
this.tab = key this.tab = key
this.$emit('tab-change', {
data: { name: key, label: this.#cache[key].label }
})
}
removeTab(ev) {
let tab = this.labels[+ev.target.dataset.i]
this.$emit('tab-close', { data: { name: tab.name, label: tab.label } })
} }
created() { created() {
@ -378,7 +528,8 @@ class Tabs extends Component {
} }
return html` return html`
<header class="header" ref="navs" @click=${this.selectTab}> <header class="header">
<section class="navs" ref="navs" @click=${this.selectTab}>
${this.labels.map( ${this.labels.map(
(it, i) => (it, i) =>
html`<label html`<label
@ -386,12 +537,21 @@ class Tabs extends Component {
label: true, label: true,
active: it.name === this.tab active: it.name === this.tab
})} })}
disabled=${it.disabled}
closable=${it.closable}
title=${it.label} title=${it.label}
data-i=${i} data-i=${i}
> >
<span class="ell">${it.label}</span> <span class="ell">${it.label}</span>
<wc-icon
class="close"
name="close"
data-i=${i}
@click.stop=${this.removeTab}
></wc-icon>
</label>` </label>`
)} )}
</section>
<span class="active-bar" style=${styleMap(tabStyle)}></span> <span class="active-bar" style=${styleMap(tabStyle)}></span>
</header> </header>
<div class="content"> <div class="content">