UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

147 lines (128 loc) 4.77 kB
import { PktElementWithSlot } from '@/base-elements/element-with-slot' import { slotContent } from '@/directives/slot-content' import { html } from 'lit' import { customElement, property } from 'lit/decorators.js' import { consume } from '@lit/context' import { createRef, Ref, ref } from 'lit/directives/ref.js' import { ifDefined } from 'lit/directives/if-defined.js' import { tabsContext, type TabsContext } from './tabs-context' export type TSkin = 'blue' | 'green' | 'red' | 'beige' | 'yellow' | 'grey' | 'gray' | 'blue-light' export interface IPktTabItem { active?: boolean disabled?: boolean href?: string icon?: string controls?: string tag?: string tagSkin?: TSkin index?: number } export class PktTabItem extends PktElementWithSlot<IPktTabItem> implements IPktTabItem { @property({ type: Boolean, reflect: true }) active: boolean = false @property({ type: Boolean, reflect: true }) disabled: boolean = false @property({ type: String, reflect: true }) href: string = '' @property({ type: String, reflect: true }) icon: string = '' @property({ type: String, reflect: true }) controls: string = '' @property({ type: String, reflect: true }) tag: string = '' @property({ type: String, reflect: true, attribute: 'tag-skin' }) tagSkin: TSkin = 'blue' @property({ type: Number, reflect: true }) index: number = 0 // Consume context from parent pkt-tabs @consume({ context: tabsContext, subscribe: true }) @property({ attribute: false }) context?: TabsContext elementRef: Ref<HTMLAnchorElement | HTMLButtonElement> = createRef() constructor() { super() } connectedCallback() { super.connectedCallback() // Wait for element to be fully initialized this.updateComplete.then(() => { if (this.elementRef.value && this.context) { this.context.registerTab(this.elementRef.value, this.index, this.disabled) } }) } updated() { if (this.elementRef.value && this.context) { this.context.registerTab(this.elementRef.value, this.index, this.disabled) } } private handleClick(event: Event) { if (this.disabled) { event.preventDefault() event.stopPropagation() return } if (this.context) { this.context.handleClick(this.index) } } private handleKeyDown(event: KeyboardEvent) { if (this.disabled && (event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar')) { event.preventDefault() event.stopPropagation() return } if (this.context) { this.context.handleKeyUp(event, this.index) } } render() { const useArrowNav = this.context?.useArrowNav ?? true const isActive = this.active && !this.disabled const commonClasses = [isActive ? 'active' : '', this.disabled ? 'pkt-tabs__item--disabled' : ''] .filter(Boolean) .join(' ') const role = useArrowNav ? 'tab' : undefined const ariaSelected = useArrowNav ? isActive : undefined const tabIndex = this.disabled ? -1 : isActive || !useArrowNav ? undefined : -1 const iconClasses = `pkt-icon--small ${this.icon === 'check' ? 'pkt-tabs__status-icon' : ''}` const content = html` ${this.icon ? html`<pkt-icon name=${this.icon} class=${iconClasses}></pkt-icon>` : ''} <span>${slotContent(this)}</span> ${this.tag ? html`<pkt-tag skin=${this.tagSkin} size="small">${this.tag}</pkt-tag>` : ''} ` if (this.href) { return html` <a ${ref(this.elementRef)} href=${ifDefined(this.disabled ? undefined : this.href)} class="pkt-tabs__link ${commonClasses}" role=${ifDefined(role)} aria-selected=${ifDefined(ariaSelected)} aria-disabled=${ifDefined(this.disabled ? 'true' : undefined)} aria-controls=${ifDefined(this.controls || undefined)} tabindex=${ifDefined(tabIndex)} @click=${this.handleClick} @keydown=${this.handleKeyDown} > ${content} </a> ` } return html` <button ${ref(this.elementRef)} type="button" class="pkt-tabs__button pkt-link-button ${commonClasses}" ?disabled=${this.disabled} aria-disabled=${ifDefined(this.disabled ? 'true' : undefined)} role=${ifDefined(role)} aria-selected=${ifDefined(ariaSelected)} aria-controls=${ifDefined(this.controls || undefined)} tabindex=${ifDefined(tabIndex)} @click=${this.handleClick} @keydown=${this.handleKeyDown} > ${content} </button> ` } } export default PktTabItem try { customElement('pkt-tab-item')(PktTabItem) } catch (e) { console.warn('Forsøker å definere <pkt-tab-item>, men den er allerede definert') }