@scania/tegel
Version:
Tegel Design System
183 lines (182 loc) • 7.41 kB
JavaScript
import { h, Host } from "@stencil/core";
import generateUniqueId from "../../../utils/generateUniqueId";
/**
* @slot <default> - <b>Unnamed slot.</b> For injecting a dropdown list.
* @slot icon - Slot for an Icon in the dropdown button.
* @slot label - Slot for a label text in the dropdown button.
*/
export class TdsHeaderDropdown {
constructor() {
/** If the dropdown icon (downwards chevron) should be hidden. */
this.noDropdownIcon = false;
/** If the button that opens the dropdown should appear selected. */
this.selected = false;
this.open = false;
this.uuid = generateUniqueId();
this.handleSlottedItemClick = (event) => {
const eventSource = event.target.tagName.toLowerCase();
if (['a', 'button'].includes(eventSource)) {
this.open = false;
}
};
}
onAnyClick(event) {
// Source: https://lamplightdev.com/blog/2021/04/10/how-to-detect-clicks-outside-of-a-web-component/
const isClickOutside = !event.composedPath().includes(this.host);
if (isClickOutside) {
this.open = false;
}
}
handleKeyDown(event) {
var _a;
if (event.key === 'Escape' && this.open) {
this.open = false;
(_a = this.buttonEl) === null || _a === void 0 ? void 0 : _a.focus();
}
}
toggleDropdown() {
this.open = !this.open;
if (this.open) {
requestAnimationFrame(() => {
var _a;
const selectors = "a, [tabindex='0']";
const firstFocusableElement = ((_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(selectors)) || this.host.querySelector(selectors);
if (firstFocusableElement instanceof HTMLElement) {
firstFocusableElement.focus();
}
});
}
}
render() {
return (h(Host, { key: '81c477e45d3f6a4614c3928797f900fb9b64ffcc' }, h("div", { key: '2b4a3509254a827fa6d300793b699e57ac36cd9a', class: {
'state-open': this.open,
} }, h("tds-header-item", { key: '4847e06a7b5fdf61642234f7179b01103e34fb38', class: "button", active: this.open, selected: this.selected }, h("button", { key: '8cc7fed2a05c68f0026ef7d4c17400d85d6a40af', ref: (el) => {
this.buttonEl = el;
}, "aria-expanded": `${this.open}`, "aria-controls": `launcher-${this.uuid}`, "aria-current": this.selected ? 'location' : 'false', onClick: () => {
this.toggleDropdown();
}, "aria-label": this.tdsAriaLabel }, h("slot", { key: '8254bfb1f48d193bc0c58363df96fad41b61aad6', name: "icon" }), this.label, h("slot", { key: '5722ecd4748ad029b5b803bb4ff731cca119fc7b', name: "label" }), !this.noDropdownIcon && (h("tds-icon", { key: 'c0c9c51b4705226891b21383ce27c0680113af7c', class: "dropdown-icon", name: "chevron_down", size: "16px", svgTitle: "Dropdown icon" })))), this.buttonEl && (h("tds-popover-canvas", { key: '52e127dbe4eef7082e62f3421d338fa0b44ab919', id: `tds-dropdown-${this.uuid}`, class: "menu", referenceEl: this.buttonEl, placement: "bottom-start", show: this.open, offsetDistance: 0, modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: [],
},
},
] }, this.open ? (h("span", { onClick: (e) => this.handleSlottedItemClick(e), onKeyDown: (e) => e.key === 'Enter' && this.handleSlottedItemClick(e) }, h("slot", null))) : null)))));
}
static get is() { return "tds-header-dropdown"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() {
return {
"$": ["header-dropdown.scss"]
};
}
static get styleUrls() {
return {
"$": ["header-dropdown.css"]
};
}
static get properties() {
return {
"label": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "The label of the button that opens the dropdown.\nThis is an alternative to the label slot."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "label"
},
"noDropdownIcon": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "If the dropdown icon (downwards chevron) should be hidden."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "no-dropdown-icon",
"defaultValue": "false"
},
"selected": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "If the button that opens the dropdown should appear selected."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "selected",
"defaultValue": "false"
},
"tdsAriaLabel": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Value to be used by the aria-label attribute"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "tds-aria-label"
}
};
}
static get states() {
return {
"open": {},
"buttonEl": {}
};
}
static get elementRef() { return "host"; }
static get listeners() {
return [{
"name": "click",
"method": "onAnyClick",
"target": "document",
"capture": false,
"passive": false
}, {
"name": "keydown",
"method": "handleKeyDown",
"target": "window",
"capture": false,
"passive": false
}];
}
}