You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ui/src/nav/NavBar.component.ts

145 lines
3.5 KiB

import {ExComponent} from '../ExComponent.js'
import {Attribute, Component, Element, Renders} from '../decorators.js'
export interface NavBarItem {
title: string,
name: string,
href?: string,
right?: boolean,
}
@Component('ex-nav')
export class NavBarComponent extends ExComponent {
protected static styles = `
<style>
nav {
display: flex;
flex-direction: row;
margin-top: 50px;
margin-bottom: 20px;
}
ul {
flex: 1;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
li {
float: left;
}
li.right {
float: right;
}
li:hover {
background: var(--color-background-darkened);
}
li a {
display: block;
text-align: center;
padding: 16px 10px;
text-decoration: none;
color: var(--color-accent-text);
}
li a:visited {
color: var(--color-accent-text);
}
span {
font-size: 1.2em;
font-weight: bold;
padding: 14px;
padding-right: 30px;
padding-left: 0;
}
.items-container {
display: none;
}
</style>
`
protected static html = `
<nav>
<slot name="branding"></slot>
<span class="appName"></span>
<ul></ul>
</nav>
<div class="items-container">
<slot></slot>
</div>
`
@Renders()
public items: NavBarItem[] = []
@Attribute()
public appName = ''
@Element('span.appName')
protected appNameEl!: HTMLSpanElement
@Element('ul')
protected list!: HTMLUListElement
render() {
super.render()
this.appNameEl.hidden = !this.appName
this.appNameEl.innerText = this.appName || ''
this.list.childNodes.forEach(x => x.remove())
for ( const item of this.getItems() ) {
const li = document.createElement('li')
const a = document.createElement('a')
li.appendChild(a)
a.setAttribute('href', item.href ?? '#')
a.innerText = item.title
a.addEventListener('click', () => this.dispatchItemClick(item.name))
if ( item.right ) {
li.classList.add('right')
}
this.list.append(li)
}
}
getItems(): NavBarItem[] {
const itemEls = this.querySelectorAll('ex-nav-item').values()
const items = []
for ( const itemEl of itemEls ) {
const title = itemEl.getAttribute('title')
const name = itemEl.getAttribute('name')
if ( title && name ) {
const item: NavBarItem = {
title,
name,
right: itemEl.hasAttribute('right'),
}
const href = itemEl.getAttribute('href')
if ( href ) {
item.href = href
}
items.push(item)
}
}
return items
}
dispatchItemClick(name: string) {
return this.dispatchCustom('onItemClick', { name })
}
}