2025-12-29 23:33:38 +00:00
import { html , cssManager , css , DeesElement , customElement , state } from '@design.estate/dees-element' ;
2025-12-29 01:20:24 +00:00
import * as interfaces from '../../interfaces/index.js' ;
2025-12-29 23:33:38 +00:00
import type { DeesAppuiTabs } from './dees-appui-tabs.js' ;
2026-03-10 12:39:21 +00:00
// Interactive demo component for closeable tabs with action buttons
2025-12-29 23:33:38 +00:00
@customElement ( 'demo-closeable-tabs' )
class DemoCloseableTabs extends DeesElement {
@state ( )
accessor tabs : interfaces.IMenuItem [ ] = [
{ key : 'Main' , iconName : 'lucide:home' , action : ( ) = > console . log ( 'Main clicked' ) } ,
] ;
@state ( )
accessor tabCounter : number = 0 ;
static styles = [
css `
:host {
display: block;
}
.info {
margin-top: 16px;
padding: 12px 16px;
background: ${ cssManager . bdTheme ( 'rgba(0,0,0,0.02)' , 'rgba(255,255,255,0.02)' ) } ;
border-radius: 6px;
font-size: 13px;
color: ${ cssManager . bdTheme ( '#71717a' , '#a1a1aa' ) } ;
}
`
] ;
private addTab() {
this . tabCounter ++ ;
const tabKey = ` Document ${ this . tabCounter } ` ;
this . tabs = [
. . . this . tabs ,
{
key : tabKey ,
iconName : 'lucide:file' ,
action : ( ) = > console . log ( ` ${ tabKey } clicked ` ) ,
closeable : true ,
onClose : ( ) = > this . removeTab ( tabKey )
}
] ;
}
private removeTab ( tabKey : string ) {
this . tabs = this . tabs . filter ( t = > t . key !== tabKey ) ;
}
2026-03-10 12:39:21 +00:00
private clearAll() {
const tabsEl = this . shadowRoot ! . querySelector ( 'dees-appui-tabs' ) as DeesAppuiTabs ;
tabsEl ? . clear ( ) ;
this . tabs = [ ] ;
this . tabCounter = 0 ;
}
2025-12-29 23:33:38 +00:00
render() {
2026-03-10 12:39:21 +00:00
const rightActions : interfaces.ITabAction [ ] = [
{ id : 'add' , iconName : 'lucide:plus' , action : ( ) = > this . addTab ( ) , tooltip : 'New Tab' } ,
{ id : 'clear' , iconName : 'lucide:trash2' , action : ( ) = > this . clearAll ( ) , tooltip : 'Clear All Tabs' } ,
] ;
2025-12-29 23:33:38 +00:00
return html `
<dees-appui-tabs
.tabs= ${ this . tabs }
2026-03-10 12:39:21 +00:00
.actionsRight= ${ rightActions }
2025-12-29 23:33:38 +00:00
@tab-close= ${ ( e : CustomEvent ) = > this . removeTab ( e . detail . tab . key ) }
></dees-appui-tabs>
<div class="info">
2026-03-10 12:39:21 +00:00
Click the X button on tabs to close them. Use the + button to add tabs and the trash button to clear all.
2025-12-29 23:33:38 +00:00
<br>Current tabs: ${ this . tabs . length }
</div>
` ;
}
}
// Interactive demo for auto-hide feature
@customElement ( 'demo-autohide-tabs' )
class DemoAutoHideTabs extends DeesElement {
@state ( )
accessor tabs : interfaces.IMenuItem [ ] = [
{ key : 'Tab 1' , iconName : 'lucide:file' , action : ( ) = > console . log ( 'Tab 1' ) } ,
{ key : 'Tab 2' , iconName : 'lucide:file' , action : ( ) = > console . log ( 'Tab 2' ) } ,
] ;
@state ( )
accessor autoHide : boolean = true ;
@state ( )
accessor threshold : number = 1 ;
static styles = [
css `
:host {
display: block;
}
.tabs-container {
min-height: 60px;
border: 1px dashed ${ cssManager . bdTheme ( '#e5e7eb' , '#27272a' ) } ;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.tabs-container dees-appui-tabs {
width: 100%;
}
.placeholder {
color: ${ cssManager . bdTheme ( '#a1a1aa' , '#71717a' ) } ;
font-size: 13px;
font-style: italic;
}
.controls {
display: flex;
gap: 8px;
margin-top: 16px;
flex-wrap: wrap;
}
button {
background: ${ cssManager . bdTheme ( 'rgba(59, 130, 246, 0.1)' , 'rgba(59, 130, 246, 0.1)' ) } ;
border: 1px solid ${ cssManager . bdTheme ( 'rgba(59, 130, 246, 0.3)' , 'rgba(59, 130, 246, 0.3)' ) } ;
color: ${ cssManager . bdTheme ( '#3b82f6' , '#60a5fa' ) } ;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
transition: all 0.15s ease;
}
button:hover {
background: ${ cssManager . bdTheme ( 'rgba(59, 130, 246, 0.2)' , 'rgba(59, 130, 246, 0.2)' ) } ;
}
button.danger {
background: ${ cssManager . bdTheme ( 'rgba(239, 68, 68, 0.1)' , 'rgba(239, 68, 68, 0.1)' ) } ;
border-color: ${ cssManager . bdTheme ( 'rgba(239, 68, 68, 0.3)' , 'rgba(239, 68, 68, 0.3)' ) } ;
color: ${ cssManager . bdTheme ( '#ef4444' , '#f87171' ) } ;
}
button.danger:hover {
background: ${ cssManager . bdTheme ( 'rgba(239, 68, 68, 0.2)' , 'rgba(239, 68, 68, 0.2)' ) } ;
}
.info {
margin-top: 16px;
padding: 12px 16px;
background: ${ cssManager . bdTheme ( 'rgba(0,0,0,0.02)' , 'rgba(255,255,255,0.02)' ) } ;
border-radius: 6px;
font-size: 13px;
color: ${ cssManager . bdTheme ( '#71717a' , '#a1a1aa' ) } ;
}
`
] ;
private tabCounter = 2 ;
private addTab() {
this . tabCounter ++ ;
this . tabs = [ . . . this . tabs , {
key : ` Tab ${ this . tabCounter } ` ,
iconName : 'lucide:file' ,
action : ( ) = > console . log ( ` Tab ${ this . tabCounter } ` )
} ] ;
}
private removeLastTab() {
if ( this . tabs . length > 0 ) {
this . tabs = this . tabs . slice ( 0 , - 1 ) ;
}
}
private clearTabs() {
this . tabs = [ ] ;
}
render() {
const shouldHide = this . autoHide && this . tabs . length <= this . threshold ;
return html `
<div class="tabs-container">
${ shouldHide
? html ` <span class="placeholder">Tabs hidden ( ${ this . tabs . length } tabs ≤ threshold ${ this . threshold } )</span> `
: html ` <dees-appui-tabs
.tabs= ${ this . tabs }
.autoHide= ${ this . autoHide }
.autoHideThreshold= ${ this . threshold }
></dees-appui-tabs> `
}
</div>
<div class="controls">
<button @click= ${ ( ) = > this . addTab ( ) } >+ Add Tab</button>
<button class="danger" @click= ${ ( ) = > this . removeLastTab ( ) } >- Remove Tab</button>
<button class="danger" @click= ${ ( ) = > this . clearTabs ( ) } >Clear All</button>
<button @click= ${ ( ) = > { this . threshold = 0 ; } }>Threshold: 0</button>
<button @click= ${ ( ) = > { this . threshold = 1 ; } }>Threshold: 1</button>
<button @click= ${ ( ) = > { this . threshold = 2 ; } }>Threshold: 2</button>
</div>
<div class="info">
Auto-hide: ${ this . autoHide ? 'ON' : 'OFF' } | Threshold: ${ this . threshold } | Tabs: ${ this . tabs . length }
<br>Tabs will hide when count ≤ threshold.
</div>
` ;
}
}
2025-12-29 01:20:24 +00:00
export const demoFunc = ( ) = > {
const horizontalTabs : interfaces.IMenuItem [ ] = [
{ key : 'Home' , iconName : 'lucide:home' , action : ( ) = > console . log ( 'Home clicked' ) } ,
{ key : 'Analytics Dashboard' , iconName : 'lucide:lineChart' , action : ( ) = > console . log ( 'Analytics clicked' ) } ,
{ key : 'Reports' , iconName : 'lucide:fileText' , action : ( ) = > console . log ( 'Reports clicked' ) } ,
{ key : 'User Settings' , iconName : 'lucide:settings' , action : ( ) = > console . log ( 'Settings clicked' ) } ,
{ key : 'Help' , iconName : 'lucide:helpCircle' , action : ( ) = > console . log ( 'Help clicked' ) } ,
] ;
const verticalTabs : interfaces.IMenuItem [ ] = [
{ key : 'Profile' , iconName : 'lucide:user' , action : ( ) = > console . log ( 'Profile clicked' ) } ,
{ key : 'Security' , iconName : 'lucide:shield' , action : ( ) = > console . log ( 'Security clicked' ) } ,
{ key : 'Notifications' , iconName : 'lucide:bell' , action : ( ) = > console . log ( 'Notifications clicked' ) } ,
{ key : 'Integrations' , iconName : 'lucide:link' , action : ( ) = > console . log ( 'Integrations clicked' ) } ,
{ key : 'Advanced' , iconName : 'lucide:code' , action : ( ) = > console . log ( 'Advanced clicked' ) } ,
] ;
const noIndicatorTabs : interfaces.IMenuItem [ ] = [
{ key : 'All' , action : ( ) = > console . log ( 'All clicked' ) } ,
{ key : 'Active' , action : ( ) = > console . log ( 'Active clicked' ) } ,
{ key : 'Completed' , action : ( ) = > console . log ( 'Completed clicked' ) } ,
{ key : 'Archived' , action : ( ) = > console . log ( 'Archived clicked' ) } ,
] ;
2026-03-10 12:39:21 +00:00
const actionsLeft : interfaces.ITabAction [ ] = [
{ id : 'back' , iconName : 'lucide:arrowLeft' , action : ( ) = > console . log ( 'Back' ) , tooltip : 'Go Back' } ,
] ;
const actionsRight : interfaces.ITabAction [ ] = [
{ id : 'add' , iconName : 'lucide:plus' , action : ( ) = > console . log ( 'Add tab' ) , tooltip : 'New Tab' } ,
{ id : 'search' , iconName : 'lucide:search' , action : ( ) = > console . log ( 'Search' ) , tooltip : 'Search Tabs' } ,
{ id : 'disabled' , iconName : 'lucide:lock' , action : ( ) = > { } , tooltip : 'Disabled Action' , disabled : true } ,
] ;
2025-12-29 01:20:24 +00:00
const demoContent = ( text : string ) = > html `
<div style="padding: 24px; color: ${ cssManager . bdTheme ( '#71717a' , '#a1a1aa' ) } ;">
${ text }
</div>
` ;
return html `
<style>
.demo-container {
display: flex;
flex-direction: column;
gap: 32px;
padding: 48px;
background: ${ cssManager . bdTheme ( '#f8f9fa' , '#0a0a0a' ) } ;
min-height: 100vh;
}
.section {
background: ${ cssManager . bdTheme ( '#ffffff' , '#18181b' ) } ;
border: 1px solid ${ cssManager . bdTheme ( '#e5e7eb' , '#27272a' ) } ;
border-radius: 8px;
padding: 24px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.section-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 16px;
color: ${ cssManager . bdTheme ( '#09090b' , '#fafafa' ) } ;
}
.two-column {
display: grid;
grid-template-columns: 200px 1fr;
gap: 24px;
align-items: start;
}
</style>
<div class="demo-container">
<div class="section">
<div class="section-title">Horizontal Tabs with Animated Indicator</div>
2025-12-29 11:30:49 +00:00
<dees-appui-tabs .tabs= ${ horizontalTabs } ></dees-appui-tabs>
${ demoContent ( 'Select a tab to see the smooth sliding animation of the indicator. The indicator automatically adjusts its width to match the tab content with minimal padding.' ) }
2025-12-29 01:20:24 +00:00
</div>
2025-12-29 23:33:38 +00:00
<div class="section">
2026-03-10 12:39:21 +00:00
<div class="section-title">Tabs with Action Buttons</div>
<dees-appui-tabs
.tabs= ${ horizontalTabs }
.actionsLeft= ${ actionsLeft }
.actionsRight= ${ actionsRight }
></dees-appui-tabs>
${ demoContent ( 'Action buttons can be placed on either side of the tab bar. They remain fixed while tabs scroll. The lock icon shows a disabled action.' ) }
</div>
<div class="section">
<div class="section-title">Closeable Tabs with Actions</div>
2025-12-29 23:33:38 +00:00
<demo-closeable-tabs></demo-closeable-tabs>
</div>
<div class="section">
<div class="section-title">Auto-hide Tabs</div>
<demo-autohide-tabs></demo-autohide-tabs>
</div>
2025-12-29 01:20:24 +00:00
<div class="section">
<div class="section-title">Vertical Tabs Layout</div>
<div class="two-column">
<dees-appui-tabs .tabStyle= ${ 'vertical' } .tabs= ${ verticalTabs } ></dees-appui-tabs>
${ demoContent ( 'Vertical tabs work great for settings pages and navigation menus. The animated indicator smoothly transitions between selections.' ) }
</div>
</div>
<div class="section">
<div class="section-title">Without Indicator</div>
2025-12-29 11:30:49 +00:00
<dees-appui-tabs .showTabIndicator= ${ false } .tabs= ${ noIndicatorTabs } ></dees-appui-tabs>
${ demoContent ( 'Tabs can also be used without the animated indicator by setting showTabIndicator to false.' ) }
2025-12-29 01:20:24 +00:00
</div>
</div>
` ;
} ;