import { css, html, LitElement } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { createRef, ref } from "lit/directives/ref.js"; import { customElement, property, state } from "lit/decorators.js"; import "./entrypoints/custom-icon.ts"; export type TabItem = { icon: string; label: string; value: string; }; export class SelectTabEvent extends Event { value: string; constructor(value: string) { super("select-tab"); this.value = value; } } @customElement("lens-controls-shell") export class LensControlsShell extends LitElement { @property({ attribute: true, type: Array }) tabs: TabItem[] = []; @property({ attribute: "active-tab" }) activeTab?: string; @state() private _isOpen = false; private _controlPanelRef = createRef(); static override styles = css` :host { --shadow: 0 0.5rem 0.5rem #3333; --background: #fff; --border-color: #ccc; --border-radius: 0.5rem; } #container-positioner { position: fixed; bottom: 2rem; display: flex; justify-content: center; align-items: flex-end; overflow: visible; width: 100%; height: 0; } #container { display: grid; grid-template-columns: max-content max-content 1rem max-content; filter: drop-shadow(var(--shadow)); } #tab-box { height: 2rem; display: flex; align-items: center; list-style-type: none; padding: 0.5rem; margin: 0; border: solid 1px var(--border-color); border-right: none; border-top-left-radius: var(--border-radius); border-bottom-left-radius: var(--border-radius); background: var(--background); grid-row: 2; & button { appearance: none; background: none; border: none; font-size: inherit; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-family: inherit; cursor: pointer; height: 2rem; } & button.active { background: #39f3; } } #control-bar { height: 3rem; flex-shrink: 0; border: solid 1px var(--border-color); border-top-right-radius: var(--border-radius); border-bottom-right-radius: var(--border-radius); overflow: hidden; width: 40rem; grid-row: 2; background: var(--background); &.open { border-top-right-radius: 0; } } #control-buttons { height: 3rem; grid-row: 2; grid-column: 4; height: 100%; } #control-panel-positioner { grid-template-columns: subgrid; grid-column: 2; grid-row: 1; position: relative; overflow: visible; /* Flexbox positioning is required for Safari */ display: flex; align-items: flex-end; anchor-name: --control-bar; } #control-panel-container:popover-open { inset: unset; border: solid 1px var(--border-color); border-bottom: none; border-top-left-radius: var(--border-radius); border-top-right-radius: var(--border-radius); margin: 0; position: fixed; display: block; width: 40rem; /* Anchor positioning is required for Chromium */ position-anchor: --control-bar; position-area: top; padding: 0; background: var(--background); box-shadow: var(--shadow); /* Clip drop shadow */ clip-path: polygon( -100% -100%, 200% -100%, 200% 200%, 100% 200%, 100% 100%, -100% 100% ); } #control-panel { padding: 0.5rem; overflow: auto; max-height: 8rem; } `; open(): void { this._controlPanelRef.value?.showPopover(); } protected override render() { return html` ${this.tabs.map(({ icon, label, value }) => html` { this.dispatchEvent(new SelectTabEvent(value)); }}"> ${icon ? html`` : label} ` )} { this._isOpen = ev.newState === "open"; }}" > `; } }