-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patharia-collapsible.js
94 lines (64 loc) · 1.92 KB
/
aria-collapsible.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
export default class AriaCollapsible extends HTMLElement {
static tagName = "aria-collapsible";
static observedAttributes = ["open"];
static register(tagName = this.tagName, registry = globalThis.customElements) {
registry?.define(tagName, this);
}
#configured = false;
#open;
#control;
#regions;
constructor() {
super();
this.#control = this.querySelector("[control]");
this.#regions = this.querySelectorAll("[region]");
this.#configured = this.#control && this.#regions.length;
}
#toggle() {
this.#control.setAttribute("aria-expanded", this.open);
for (const region of this.#regions) {
region.toggleAttribute("hidden", !this.open);
}
this.dispatchEvent(new Event("toggle", {
bubbles: true,
cancelable: true,
}));
}
get open() {
return Boolean(this.#open);
}
set open(value) {
this.toggleAttribute("open", Boolean(value));
}
attributeChangedCallback(name, _oldValue, _newValue) {
if (!this.constructor.observedAttributes.includes(name)) return;
this.#open = this.hasAttribute("open");
this.#toggle();
}
connectedCallback() {
if (!this.#configured) return;
this.#control.addEventListener("click", this);
const regionIds = [];
for (const region of this.#regions) {
if (!region.id) {
region.setAttribute("id", `region-${globalThis.crypto.randomUUID()}`);
}
regionIds.push(region.id);
}
this.#control.setAttribute("aria-controls", regionIds.join(" "));
this.#control.removeAttribute("hidden");
this.#toggle();
}
disconnectedCallback() {
if (!this.#configured) return;
this.#control.removeEventListener("click", this);
this.#control.removeAttribute("aria-controls");
this.#control.setAttribute("hidden", true);
this.#toggle();
}
handleEvent(event) {
event.preventDefault();
this.open = !this.open;
}
}
AriaCollapsible.register();