UNPKG

@telekom/scale-components

Version:

Scale is the digital design system for Telekom products and experiences.

130 lines (124 loc) 5.86 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const index = require('./index-a0ea3d79.js'); const index$1 = require('./index-53f5a5fc.js'); const sidebarNavItemCss = ":host{--border-bottom-color:var(--telekom-color-ui-faint);--border-left-color-third-nesting:var(--telekom-color-ui-strong);--color-active:var(--telekom-color-text-and-icon-primary-pressed);--color-hover:var(--telekom-color-text-and-icon-primary-hovered);--color-primary:var(--telekom-color-text-and-icon-primary-standard);--background-color-before-active:var(--color-primary);--font-bold:var(--telekom-text-style-ui-bold);--box-shadow-focus:inset 0 0 0 var(--telekom-line-weight-highlight)\n var(--telekom-color-functional-focus-standard)}.sidebar-nav-item{border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:var(--border-bottom-color)}.sidebar-nav-item--active{position:relative;color:var(--color-primary)}.sidebar-nav-item--active::before{content:'';display:block;position:absolute;top:0;left:var(--left-current-border, 0);width:0;height:100%;background-color:var(--background-color-before-active);border-left:2px solid transparent}.sidebar-nav-item:hover.sidebar-nav-item--active::before{background-color:var(--color-hover)}.sidebar-nav-item:active.sidebar-nav-item--active::before{background-color:var(--color-active)}.sidebar-nav-item--condensed.sidebar-nav-item--active::before{left:-1px}:host([nesting-level='1']) .sidebar-nav-item,.sidebar-nav-item--bold{font:var(--font-bold)}:host([nesting-level='3']) .sidebar-nav-item{border-left-color:var(--border-left-color-third-nesting);border-left-style:solid;border-left-width:0.0625rem}::slotted(a){color:currentColor;display:flex;align-items:center;padding-top:1rem;padding-right:1rem;padding-bottom:1rem;padding-left:var(--spacing-indent);border-radius:var(--telekom-radius-small);text-decoration:none;outline:none;min-height:20px}:host([nesting-level='2']) ::slotted(a){padding-left:calc(var(--spacing-indent) + 0.75rem)}::slotted(a:hover){color:var(--color-hover)}::slotted(a:focus){box-shadow:var(--box-shadow-focus)}::slotted(a:active){color:var(--color-active)}.sidebar-nav-item--condensed{border-bottom-width:0}.sidebar-nav-item--condensed ::slotted(a){padding-top:0.5rem;padding-left:0.75rem;padding-right:0.5rem;padding-bottom:0.5rem}"; const SR_ACTIVE_TEXT = ' Zurzeit aktiv'; const isActive = (current) => { try { return !!JSON.parse(current); } catch (e) { if (typeof current === 'string') { return true; } return !!current; } }; const getScreenReaderText = (current) => { let text; try { text = JSON.parse(current); } catch (e) { text = current; } return typeof text === 'string' && text.length > 0 ? ` ${text}` : SR_ACTIVE_TEXT; }; const SidebarNavItem = class { constructor(hostRef) { index.registerInstance(this, hostRef); /** Used normally for third level items, remove the bottom border */ this.condensed = false; /** Bold text */ this.bold = false; /** Text gets the active color */ this.active = false; /** * Mark the child link as "current" with `aria-current=page`. * Provide the text hint if needed, default is: "Zurzeit aktiv" */ this.current = null; } nestingLevelChanged(newValue) { if (newValue === 1) { this.bold = true; } } currentChanged(newValue) { this.handleAriaCurrentInSlottedA(newValue); this.syncActiveToCurrent(newValue); } componentDidLoad() { this.handleAriaCurrentInSlottedA(this.current); if (this.current) { this.syncActiveToCurrent(this.current); } } /** * If an item is `current`, it should be `active` as well */ syncActiveToCurrent(newValue) { this.active = isActive(newValue); } /** * When `current` is set, this will: * - set the aria-current=page attribute on the link * - append a text-only hint for screen readers * so we end up with something like this: * <a href="..." aria-current="page"> * Example<span style="...visible to SR only..."> Active link</span> * </a> * @param current this.current */ handleAriaCurrentInSlottedA(current) { const a = this.el.querySelector('a'); if (this.srOnlyElement != null) { a.removeChild(this.srOnlyElement); this.srOnlyElement = null; } if (a != null) { a.removeAttribute('aria-current'); } if (isActive(current) && a != null) { this.srOnlyElement = this.createScreenReaderOnlySpan(); a.appendChild(this.srOnlyElement); a.setAttribute('aria-current', 'page'); } } createScreenReaderOnlySpan() { const text = getScreenReaderText(this.current); const span = document.createElement('span'); // .sr-only but inline Object.assign(span.style, { position: 'absolute', left: '-10000px', overflow: 'hidden', }); span.textContent = text; return span; } render() { return (index.h(index.Host, null, this.styles && index.h("style", null, this.styles), index.h("li", { part: this.getBasePartMap(), class: this.getCssClassMap(), role: "listitem" }, index.h("slot", null)))); } getBasePartMap() { return this.getCssOrBasePartMap('basePart'); } getCssClassMap() { return this.getCssOrBasePartMap('css'); } getCssOrBasePartMap(mode) { const component = 'sidebar-nav-item'; const prefix = mode === 'basePart' ? '' : `${component}--`; return index$1.classnames(component, this.bold && `${prefix}bold`, this.condensed && `${prefix}condensed`, this.active && `${prefix}active`); } get el() { return index.getElement(this); } static get watchers() { return { "nestingLevel": ["nestingLevelChanged"], "current": ["currentChanged"] }; } }; SidebarNavItem.style = sidebarNavItemCss; exports.scale_sidebar_nav_item = SidebarNavItem;