import * as interfaces from './interfaces/index.js'; import { DeesElement, type TemplateResult, property, customElement, html, css, cssManager, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; @customElement('dees-appui-tabs') export class DeesAppuiTabs extends DeesElement { public static demo = () => html` console.log('Tab 1 clicked') }, { key: 'Tab 2', action: () => console.log('Tab 2 clicked') }, { key: 'Tab 3', action: () => console.log('Tab 3 clicked') }, ]} > `; // INSTANCE @property({ type: Array, }) public tabs: interfaces.ITab[] = []; @property({ type: Object }) public selectedTab: interfaces.ITab | null = null; @property({ type: Boolean }) public showTabIndicator: boolean = true; @property({ type: String }) public tabStyle: 'horizontal' | 'vertical' = 'horizontal'; public static styles = [ cssManager.defaultStyles, css` :host { display: block; position: relative; width: 100%; } .tabs-wrapper { position: relative; background: ${cssManager.bdTheme('#f5f5f5', '#000000')}; height: 52px; } .tabsContainer { position: relative; z-index: 1; user-select: none; } .tabsContainer.horizontal { display: grid; padding-top: 20px; padding-bottom: 0px; margin-left: 24px; font-size: 14px; } .tabsContainer.vertical { display: flex; flex-direction: column; padding: 20px; font-size: 14px; } .tab { color: ${cssManager.bdTheme('#666', '#a0a0a0')}; white-space: nowrap; cursor: default; transition: color 0.1s; } .horizontal .tab { margin-right: 30px; padding-top: 4px; padding-bottom: 12px; } .vertical .tab { padding: 12px 16px; margin-bottom: 4px; border-radius: 4px; width: 100%; display: flex; align-items: center; gap: 8px; } .tab:hover { color: ${cssManager.bdTheme('#000', '#ffffff')}; } .vertical .tab:hover { background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.05)', 'rgba(255, 255, 255, 0.05)')}; } .tab.selectedTab { color: ${cssManager.bdTheme('#333', '#e0e0e0')}; } .vertical .tab.selectedTab { background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')}; color: ${cssManager.bdTheme('#000', '#ffffff')}; } .tab dees-icon { font-size: 16px; } .tabs-wrapper .tabIndicator { position: absolute; z-index: 0; left: 40px; bottom: 0px; height: 40px; width: 40px; background: ${cssManager.bdTheme('#ffffff', '#161616')}; transition: all 0.1s; border-top-left-radius: 8px; border-top-right-radius: 8px; border-top: 1px solid ${cssManager.bdTheme('#e0e0e0', '#444444')}; } .vertical .tabIndicator { display: none; } .content { margin-top: 20px; } `, ]; public render(): TemplateResult { return html` ${this.tabStyle === 'horizontal' ? html`
${this.tabs.map((tabArg) => { return html`
${tabArg.key}
`; })}
${this.showTabIndicator ? html`
` : ''}
` : html`
${this.tabs.map((tabArg) => { return html`
${tabArg.iconName ? html`` : ''} ${tabArg.key}
`; })}
`}
`; } private selectTab(tabArg: interfaces.ITab) { this.selectedTab = tabArg; this.updateTabIndicator(); tabArg.action(); // Emit tab-select event this.dispatchEvent(new CustomEvent('tab-select', { detail: { tab: tabArg }, bubbles: true, composed: true })); } /** * updates the indicator position */ private updateTabIndicator() { if (!this.showTabIndicator || this.tabStyle !== 'horizontal' || !this.selectedTab) { return; } const tabIndex = this.tabs.indexOf(this.selectedTab); const selectedTabElement: HTMLElement = this.shadowRoot.querySelector( `.tabs-wrapper .tabsContainer .tab:nth-child(${tabIndex + 1})` ); if (!selectedTabElement) return; const tabsContainer: HTMLElement = this.shadowRoot.querySelector('.tabs-wrapper .tabsContainer'); const marginLeft = parseInt(window.getComputedStyle(tabsContainer).getPropertyValue("margin-left")); const tabIndicator: HTMLElement = this.shadowRoot.querySelector('.tabs-wrapper .tabIndicator'); if (tabIndicator) { tabIndicator.style.width = selectedTabElement.clientWidth + 24 + 'px'; tabIndicator.style.left = selectedTabElement.offsetLeft + marginLeft - 12 + 'px'; } } firstUpdated() { if (this.tabs && this.tabs.length > 0) { this.selectTab(this.tabs[0]); } } async updated(changedProperties: Map) { super.updated(changedProperties); if (changedProperties.has('tabs') && this.tabs && this.tabs.length > 0 && !this.selectedTab) { this.selectTab(this.tabs[0]); } if (changedProperties.has('selectedTab') || changedProperties.has('tabs')) { this.updateTabIndicator(); } } }