-
Notifications
You must be signed in to change notification settings - Fork 0
/
rem-details.js
127 lines (104 loc) · 2.77 KB
/
rem-details.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// // ES6 class
const css = /* css */ `
button {
appearance: none;
border: none;
background: none;
all: inherit;
padding-top: 16px;
border-top: 1px solid #333;
margin-top: 24px;
}
button:focus [name="summary"] {
outline: 1px solid blue;
}
[name="summary"] {
background: none;
display: block;
cursor: pointer;
user-select: none;
display: block;
font-family: 'Inter Tight', sans-serif;
font-size: 16px;
line-height: 24px;
position: relative;
}
[name="summary"]:after {
content: "";
display: block;
position: absolute;
right: 0;
top: 0px;
width: 16px;
height: 24px;
background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10 2 6 6 2 2' stroke='%23D4AF37' stroke-width='2' stroke-miterlimit='10' stroke-linecap='square'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
transition: transform 100ms ease-out;
}
/* kept because it's nice to know
::slotted([slot="details"]) {
text-decoration: underline;
}
*/
:host([open]) [name="summary"]:after {
transform: rotate(180deg);
}
:host([open]) button {
margin-top: 0px;
}
.details {
display: flex;
flex-direction: column-reverse;
}
@media screen and (min-width: 420px) {
[name="summary"], button {
display: none;
}
[name="details"] {
display: block !important;
}
}
`;
const template = document.createElement('template');
template.innerHTML = /*html*/ `
<style>
${css}
</style>
<div class="details">
<button><slot name="summary">More details</slot></button>
<slot name="details"></slot>
</div>`;
class RemDetails extends HTMLElement {
_open = false;
constructor() {
super();
const children = template.content.cloneNode(true);
// parent node gets us the button it's wrapped in
const summary = children.querySelector('slot[name="summary"]').parentNode;
summary.onclick = (e) => (this.open = !this.open);
this.details = children.querySelector('slot[name="details"]');
// mode: open - means accessed in user code
const shadow = this.attachShadow({
mode: 'open',
delegatesFocus: true,
}).appendChild(children);
const title = this.shadowRoot.host.getAttribute('title');
const open = !!this.shadowRoot.host.getAttribute('open');
this.open = open;
}
get open() {
return this._open;
}
set open(value) {
const open = value;
this.details.hidden = !open;
if (open) {
this.shadowRoot.host.setAttribute('open', '');
} else {
this.shadowRoot.host.removeAttribute('open');
}
this._open = open;
}
}
window.customElements.define('rem-details', RemDetails);