@zeix/ui-element
Version:
UIElement - minimal reactive framework based on Web Components
60 lines (52 loc) • 1.49 kB
text/typescript
import { UIElement, asBoolean, setAttribute, setProperty, toggleAttribute, toggleClass } from '../../../'
export class TabList extends UIElement<{
active: number,
accordion: boolean,
}> {
static readonly localName = 'tab-list'
static observedAttributes = ['accordion']
init = {
active: 0,
accordion: asBoolean,
}
connectedCallback() {
super.connectedCallback()
// Set inital active tab by querying details[open]
const getInitialActive = () => {
const panels = Array.from(this.querySelectorAll('details'))
for (let i = 0; i < panels.length; i++) {
if (panels[i].hasAttribute('open')) return i
}
return 0
}
this.set('active', getInitialActive())
// Reflect accordion attribute (may be used for styling)
this.self.sync(toggleAttribute('accordion'))
// Update active tab state and bind click handlers
this.all('menu button')
.on('click', (_, index) => () => {
this.set('active', index)
})
.sync(setProperty(
'ariaPressed',
(_, index) => String(this.get('active') === index)
))
// Update details panels open, hidden and disabled states
this.all<HTMLDetailsElement>('details').sync(
setProperty(
'open',
(_, index) => !!(this.get('active') === index)
),
setAttribute(
'aria-disabled',
() => String(!this.get('accordion'))
)
)
// Update summary visibility
this.all('summary').sync(toggleClass(
'visually-hidden',
() => !this.get('accordion')
))
}
}
TabList.define()