UNPKG

@coderundebug/ui-web

Version:

A collection of UI web components that can be used in any web project.

2 lines 16.8 kB
/* By Stephen Paul Hassall (web: https://coderundebug.com) */ import{UiTools as t}from"./ui-tools.js";export class UiTab extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML=UiTab.uiHtml,this.shadowRoot.adoptedStyleSheets=[UiTab.uiCssStyleSheet],this.t=this.shadowRoot.querySelector('slot[name="tab"]'),this.o=this.shadowRoot.querySelector('slot[name="panel"]'),this.i=this.shadowRoot.querySelector(".panel"),this.l=this.l.bind(this),this.u=this.u.bind(this),this.h=this.h.bind(this),this.v=-1,this.p=-1}get tabNumber(){return this.v}set tabNumber(t){this.m(t)}get tabCount(){return this.p}connectedCallback(){this.t.addEventListener("click",this.l),this.t.addEventListener("keydown",this.u),this.o.addEventListener("slotchange",this.h);const t=this.t.assignedElements();for(let o=0;o<t.length;o++){if(!1!==t[o].hasAttribute("selected")){this.m(o+1);break}}if(-1===this.v){0===this.o.assignedElements().length&&this.m(1)}}disconnectedCallback(){this.t.removeEventListener("click",this.l),this.t.removeEventListener("keydown",this.u),this.o.removeEventListener("slotchange",this.h)}l(t){let o=t.target;for(;"tab"!==o.slot;)if(o=o.parentElement,null===o)return;let r=0;const a=this.t.assignedElements();for(let t=0;t<a.length;t++){if(r++,a[t]===o)break}this.m(r),t.stopPropagation()}h(){-1===this.v&&this.m(1)}u(t){if("ArrowLeft"===t.key||"ArrowUp"===t.key){if(1===this.v)return;this.m(this.v-1,!0),t.preventDefault(),t.stopPropagation()}if("ArrowRight"===t.key||"ArrowDown"===t.key){if(this.v+1>this.p)return;this.m(this.v+1,!0),t.preventDefault(),t.stopPropagation()}}m(t,o){if(t===this.v)return;const r=this.o.assignedElements();let a=0;for(let o=0;o<r.length;o++){const e=r[o];void 0===e.k&&(e.k=e.style.display),a++,t!==a?(!0===e.hasAttribute("open")&&e.removeAttribute("open"),e.style.display="none"):(e.style.display=e.k,e.setAttribute("open",""))}this.i.style.display="block",this.v=t;const e=this.t.assignedElements();this.p=e.length,a=0;for(let r=0;r<e.length;r++){const i=e[r];a++,t!==a?(!0===i.hasAttribute("selected")&&i.removeAttribute("selected"),i.setAttribute("tabindex","-1"),i.setAttribute("aria-selected","false")):(i.setAttribute("selected",""),i.setAttribute("tabindex","0"),i.setAttribute("aria-selected","true"),!0===o&&i.focus()),i.setAttribute("aria-posinset",a.toString()),i.setAttribute("role","tab")}const i=new Event("tabselected");this.dispatchEvent(i)}}UiTab.uiCss=':host{display:block;}.tab{height:100%;width:100%;}.tab-base{position:relative;}.tab-line{position:absolute;}:host(:not([right]):not([left]):not([bottom])), :host([top]){& .tab{display:grid;grid-template-columns:1fr;grid-template-rows:auto 1fr;}& .tab-base{grid-column:1;grid-row:1;}& .panel{grid-column:1;grid-row:2;}& .tab-line{position:absolute;inset-block-end:0;height:var(--ui-tab-bar-width, 2px);width:100%;}& .tab-slot{display:flex;flex-flow:row;gap:var(--ui-tab-gap, 8px);align-items:stretch;}} :host([bottom]){& .tab{display:grid;grid-template-columns:1fr;grid-template-rows:1fr auto;}& .tab-base{grid-column:1;grid-row:2;}& .panel{grid-column:1;grid-row:1;}& .tab-line{position:absolute;inset-block-start:0;height:var(--ui-tab-bar-width, 2px);width:100%;}& .tab-slot{display:flex;flex-flow:row;gap:var(--ui-tab-gap, 8px);align-items:stretch;}} :host([left]){& .tab{display:grid;grid-template-columns:auto 1fr;}& .tab-base{grid-column:1;grid-row:1;}& .panel{grid-column:2;grid-row:1;}& .tab-line{position:absolute;inset-inline-end:0;height:100%;width:var(--ui-tab-bar-width, 2px);}& .tab-slot{display:flex;flex-flow:column;gap:var(--ui-tab-gap, 8px);align-items:stretch;}} :host([right]){& .tab{display:grid;grid-template-columns:1fr auto;}& .tab-base{grid-column:2;grid-row:1;}& .panel{grid-column:1;grid-row:1;}& .tab-line{position:absolute;inset-inline-start:0;height:100%;width:var(--ui-tab-bar-width, 2px);}& .tab-slot{display:flex;flex-flow:column;gap:var(--ui-tab-gap, 8px);align-items:stretch;}} slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button)){position:relative;font-family:inherit;font-size:var(--ui-tab-font-size);font-weight:var(--ui-tab-font-weight, var(--ui-font-weight-normal, normal));line-height:150%;text-wrap:nowrap;white-space:nowrap;text-overflow:ellipsis;user-select:none;-webkit-user-select:none;transition:background-color var(--ui-animation-duration-default, 200ms) ease-in-out, color var(--ui-animation-duration-default, 200ms) ease-in-out;}:host(:not([boxed])){& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button)){background-color:var(--ui-tab-label-background, var(--ui-background, hsl(0 0% 97% / 1)));color:var(--ui-tab-label-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));padding:var(--ui-tab-label-padding, 8px 16px);}& .panel{background-color:var(--ui-tab-panel-background, var(--ui-background, hsl(0 0% 97% / 1)));color:var(--ui-tab-panel-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));}} :host(:not([boxed]):not([right]):not([left]):not([bottom])), :host(:not([boxed])[top]){& .tab-line{border:none;border-block-end-style:var(--ui-tab-bar-style, solid);border-block-end-width:var(--ui-tab-bar-width, 2px);border-block-end-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}& slot[name="tab"]::slotted([selected]){border:none;border-block-end-style:var(--ui-tab-bar-style, solid);border-block-end-width:var(--ui-tab-bar-width, 2px);border-block-end-color:var(--ui-tab-bar-selected-color, var(--ui-selected-foreground, hsl(215 50% 30% / 1)));}& slot[name="tab"]::slotted(*){border-block-end-style:var(--ui-tab-bar-style, solid);border-block-end-width:var(--ui-tab-bar-width, 2px);border-block-end-color:transparent;border-start-start-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));border-start-end-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([ui-tab-button]), slot[name="tab"]::slotted(ui-button), slot[name="tab"]::slotted(ui-link-button), slot[name="tab"]::slotted(ui-icon-button){padding-block:var(--ui-tab-button-padding, 8px);}} :host(:not([boxed])[bottom]){& .tab-line{border:none;border-block-start-style:var(--ui-tab-bar-style, solid);border-block-start-width:var(--ui-tab-bar-width, 2px);border-block-start-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}& slot[name="tab"]::slotted([selected]){border:none;border-block-start-style:var(--ui-tab-bar-style, solid);border-block-start-width:var(--ui-tab-bar-width, 2px);border-block-start-color:var(--ui-tab-bar-selected-color, var(--ui-selected-foreground, hsl(215 50% 30% / 1)));}& slot[name="tab"]::slotted(*){border-block-start-style:var(--ui-tab-bar-style, solid);border-block-start-width:var(--ui-tab-bar-width, 2px);border-block-start-color:transparent;border-end-start-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));border-end-end-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([ui-tab-button]), slot[name="tab"]::slotted(ui-button), slot[name="tab"]::slotted(ui-link-button), slot[name="tab"]::slotted(ui-icon-button){padding-block:var(--ui-tab-button-padding, 8px);}} :host(:not([boxed])[left]){& .tab-line{border:none;border-inline-end-style:var(--ui-tab-bar-style, solid);border-inline-end-width:var(--ui-tab-bar-width, 2px);border-inline-end-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}& slot[name="tab"]::slotted([selected]){border:none;border-inline-end-style:var(--ui-tab-bar-style, solid);border-inline-end-width:var(--ui-tab-bar-width, 2px);border-inline-end-color:var(--ui-tab-bar-selected-color, var(--ui-selected-foreground, hsl(215 50% 30% / 1)));}& slot[name="tab"]::slotted(*){border-inline-end-style:var(--ui-tab-bar-style, solid);border-inline-end-width:var(--ui-tab-bar-width, 2px);border-inline-end-color:transparent;border-start-start-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));border-end-start-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([ui-tab-button]), slot[name="tab"]::slotted(ui-button), slot[name="tab"]::slotted(ui-link-button), slot[name="tab"]::slotted(ui-icon-button){padding-inline:var(--ui-tab-button-padding, 8px);}} :host(:not([boxed])[right]){& .tab-line{border:none;border-inline-start-style:var(--ui-tab-bar-style, solid);border-inline-start-width:var(--ui-tab-bar-width, 2px);border-inline-start-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}& slot[name="tab"]::slotted([selected]){border:none;border-inline-start-style:var(--ui-tab-bar-style, solid);border-inline-start-width:var(--ui-tab-bar-width, 2px);border-inline-start-color:var(--ui-tab-bar-selected-color, var(--ui-selected-foreground, hsl(215 50% 30% / 1)));}& slot[name="tab"]::slotted(*){border-inline-start-style:var(--ui-tab-bar-style, solid);border-inline-start-width:var(--ui-tab-bar-width, 2px);border-inline-start-color:transparent;border-start-end-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));border-end-end-radius:var(--ui-tab-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([ui-tab-button]), slot[name="tab"]::slotted(ui-button), slot[name="tab"]::slotted(ui-link-button), slot[name="tab"]::slotted(ui-icon-button){padding-inline:var(--ui-tab-button-padding, 8px);}} :host([boxed]){& slot[name="tab"]::slotted(*){border-style:var(--ui-tab-bar-style, solid);border-width:var(--ui-tab-bar-width, 2px);border-color:transparent;padding:var(--ui-tab-boxed-label-padding, 8px 16px);}& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button):not([selected])){background-color:var(--ui-tab-boxed-label-background, var(--ui-midground, hsl(0 0% 90% / 1)));color:var(--ui-tab-boxed-label-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));}& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button)[selected]){background-color:var(--ui-tab-boxed-label-selected-background, var(--ui-background, hsl(0 0% 97% / 1)));color:var(--ui-tab-boxed-label-selected-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));}& .panel{position:relative;inset:0;background-color:var(--ui-tab-boxed-panel-background, var(--ui-background, hsl(0 0% 97% / 1)));color:var(--ui-tab-boxed-panel-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));border-radius:var(--ui-tab-boxed-border-radius, var(--ui-border-radius-large, 6px));border-style:var(--ui-tab-boxed-border-style, solid);border-width:var(--ui-tab-boxed-border-width, 2px);border-color:var(--ui-tab-boxed-border-color, var(--ui-midground, hsl(0 0% 90% / 1)))}} :host([boxed]:not([right]):not([left]):not([bottom])), :host([boxed][top]){& slot[name="tab"]::slotted(*){border-start-start-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));border-start-end-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([selected]){border-style:var(--ui-tab-boxed-border-style, solid);border-width:var(--ui-tab-boxed-border-width, 2px);border-color:var(--ui-tab-boxed-border-color, var(--ui-midground, hsl(0 0% 90% / 1)));border-block-end-style:none;}& .panel{inset-block-start:calc(var(--ui-tab-boxed-border-width, 2px) * -1);}& .tab-base{padding-inline:calc(var(--ui-tab-boxed-border-radius, var(--ui-border-radius-large, 6px)) * 1.5);}} :host([boxed][bottom]){& slot[name="tab"]::slotted(*){border-end-start-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));border-end-end-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([selected]){border-style:var(--ui-tab-boxed-border-style, solid);border-width:var(--ui-tab-boxed-border-width, 2px);border-color:var(--ui-tab-boxed-border-color, var(--ui-midground, hsl(0 0% 90% / 1)));border-block-start-style:none;}& .panel{inset-block-start:var(--ui-tab-boxed-border-width, 2px);}& .tab-base{padding-inline:calc(var(--ui-tab-boxed-border-radius, var(--ui-border-radius-large, 6px)) * 1.5);}} :host([boxed][left]){& slot[name="tab"]::slotted(*){border-start-start-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));border-end-start-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([selected]){border-style:var(--ui-tab-boxed-border-style, solid);border-width:var(--ui-tab-boxed-border-width, 2px);border-color:var(--ui-tab-boxed-border-color, var(--ui-midground, hsl(0 0% 90% / 1)));border-inline-end-style:none;}& .panel{inset-inline-start:calc(var(--ui-tab-boxed-border-width, 2px) * -1);}& .tab-base{padding-block:calc(var(--ui-tab-boxed-border-radius, var(--ui-border-radius-large, 6px)) * 1.5);}} :host([boxed][right]){& slot[name="tab"]::slotted(*){border-start-end-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));border-end-end-radius:var(--ui-tab-boxed-label-radius, var(--ui-border-radius-large, 6px));}& slot[name="tab"]::slotted([selected]){border-style:var(--ui-tab-boxed-border-style, solid);border-width:var(--ui-tab-boxed-border-width, 2px);border-color:var(--ui-tab-boxed-border-color, var(--ui-midground, hsl(0 0% 90% / 1)));border-inline-start-style:none;}& .panel{inset-inline-start:var(--ui-tab-boxed-border-width, 2px);}& .tab-base{padding-block:calc(var(--ui-tab-boxed-border-radius, var(--ui-border-radius-large, 6px)) * 1.5);}} :host(:not([boxed])){& .tab{isolation:isolate;}& .tab-line{position:absolute;z-index:1;}& slot[name="tab"]::slotted([selected]){z-index:2;}} :host([boxed]){& .tab{isolation:isolate;}& .tab-line{z-index:0;}& slot[name="tab"]::slotted([selected]){z-index:2;}} :host([bar]:not([boxed]):not([right]):not([left]):not([bottom])), :host([bar]:not([boxed])[top]), :host([bar]:not([boxed])[bottom]){& slot[name="tab"]::slotted(*){position:relative;}& slot[name="tab"]::slotted(*:not(:first-child))::after{content:\' \';position:absolute;inset-inline-start:calc((var(--ui-tab-gap, 8px) * -0.5) - (var(--ui-tab-bar-width, 2px) / 2));inset-block-start:var(--ui-tab-bar-gap, 4px);inset-block-end:var(--ui-tab-bar-gap, 4px);border-inline-end-style:var(--ui-tab-bar-style, solid);border-inline-end-width:var(--ui-tab-bar-width, 2px);border-inline-end-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}} :host([bar]:not([boxed])[left]), :host([bar]:not([boxed])[right]){& slot[name="tab"]::slotted(*){position:relative;}& slot[name="tab"]::slotted(*:not(:first-child))::after{content:\' \';position:absolute;inset-block-start:calc((var(--ui-tab-gap, 8px) * -0.5) - (var(--ui-tab-bar-width, 2px) / 2));inset-inline-start:var(--ui-tab-bar-gap, 4px);inset-inline-end:var(--ui-tab-bar-gap, 4px);border-block-end-style:var(--ui-tab-bar-style, solid);border-block-end-width:var(--ui-tab-bar-width, 2px);border-block-end-color:var(--ui-tab-bar-color, var(--ui-midground, hsl(0 0% 90% / 1)));}} :host([bar]) slot[name="tab"]::slotted(*){overflow:visible;}.panel{display:none;padding:var(--ui-tab-panel-padding, 0);}::slotted(*:not(:defined)){display:none;}@media (hover:hover){slot[name="tab"]::slotted(*:not([selected])){cursor:pointer;}:host(:not([boxed])){& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button):hover){background-color:var(--ui-tab-label-hover-background, var(--ui-midground, hsl(0 0% 90% / 1)));color:var(--ui-tab-label-hover-foreground, var(--ui-foreground, hsl(0 0% 18% / 1)));}} :host([boxed]){& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button):not([selected]):hover){filter:brightness(85%);}& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button)[selected]:hover){cursor:default;}}}:host(:not([boxed])){& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button):not([selected]):active){filter:brightness(65%);}} :host([boxed]){& slot[name="tab"]::slotted(:not([ui-tab-button]):not(ui-button):not(ui-link-button):not(ui-icon-button):not([selected]):active){filter:brightness(65%);}} @media (forced-colors:active) or (prefers-contrast:more){slot[name="tab"]::slotted(:not([ui-tag-button]):not(ui-button):not(ui-link-button):not(ui-icon-button)[selected]){border-style:var(--ui-border-style, solid);border-width:var(--ui-border-width, 1px);}} ',UiTab.uiHtml='<div class="tab"><div class="tab-base"><div class="tab-line"></div><div class="tab-slot" role="tablist"><slot name="tab"></slot></div></div><div class="panel"><slot name="panel"></slot></div></div>',t.createUi(UiTab,"ui-tab",import.meta.url);