@magic-spells/collapsible-content 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -57
- package/dist/collapsible-content.cjs.js +79 -52
- package/dist/collapsible-content.cjs.js.map +1 -1
- package/dist/collapsible-content.css +24 -27
- package/dist/collapsible-content.esm.js +79 -52
- package/dist/collapsible-content.esm.js.map +1 -1
- package/dist/collapsible-content.js +79 -52
- package/dist/collapsible-content.js.map +1 -1
- package/dist/collapsible-content.min.css +1 -1
- package/dist/collapsible-content.min.js +1 -1
- package/package.json +6 -10
- package/src/collapsible-content.css +31 -0
- package/src/collapsible-content.js +80 -53
- package/dist/collapsible-content.scss +0 -2
- package/dist/scss/collapsible-content.scss +0 -25
- package/dist/scss/variables.scss +0 -40
- package/src/index.scss +0 -2
- package/src/scss/collapsible-content.scss +0 -25
- package/src/scss/variables.scss +0 -40
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Collapsible Content Web Component
|
|
2
2
|
|
|
3
|
-
A lightweight,
|
|
3
|
+
A lightweight, accessible Web Component for creating collapsible content sections. Perfect for FAQs, accordions, or any content that needs to be toggled.
|
|
4
4
|
|
|
5
5
|
[**Live Demo**](https://magic-spells.github.io/collapsible-content/demo/)
|
|
6
6
|
|
|
@@ -8,10 +8,10 @@ A lightweight, customizable Web Component for creating accessible collapsible co
|
|
|
8
8
|
|
|
9
9
|
- No dependencies
|
|
10
10
|
- Lightweight
|
|
11
|
-
-
|
|
12
|
-
- Smooth
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
- Accessible (ARIA attributes, keyboard support, focus management)
|
|
12
|
+
- Smooth animations with `prefers-reduced-motion` support
|
|
13
|
+
- Prevents rapid click issues during animation
|
|
14
|
+
- Safe to import multiple times (no double-registration errors)
|
|
15
15
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
@@ -20,7 +20,6 @@ npm install @magic-spells/collapsible-content
|
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
```javascript
|
|
23
|
-
// Add to your JavaScript file
|
|
24
23
|
import '@magic-spells/collapsible-content';
|
|
25
24
|
```
|
|
26
25
|
|
|
@@ -34,86 +33,84 @@ Or include directly in your HTML:
|
|
|
34
33
|
|
|
35
34
|
```html
|
|
36
35
|
<collapsible-component>
|
|
37
|
-
<button
|
|
36
|
+
<button type="button">Product Information</button>
|
|
38
37
|
<collapsible-content>
|
|
39
38
|
<div class="content-wrapper">
|
|
40
39
|
<h3>Details</h3>
|
|
41
|
-
<p>
|
|
42
|
-
This product is made with 100% organic materials. It's durable, eco-friendly, and
|
|
43
|
-
stylish.
|
|
44
|
-
</p>
|
|
40
|
+
<p>This product is made with 100% organic materials.</p>
|
|
45
41
|
</div>
|
|
46
42
|
</collapsible-content>
|
|
47
43
|
</collapsible-component>
|
|
48
44
|
```
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
### Start Expanded
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
- Clicking the button toggles the visibility of the content
|
|
54
|
-
- The component handles all the ARIA attributes for accessibility
|
|
55
|
-
- Smooth animations are provided for opening and closing
|
|
48
|
+
Add the `open` attribute to start with content visible:
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
```html
|
|
51
|
+
<collapsible-component>
|
|
52
|
+
<button type="button">Already Open</button>
|
|
53
|
+
<collapsible-content open>
|
|
54
|
+
<p>This content is visible by default.</p>
|
|
55
|
+
</collapsible-content>
|
|
56
|
+
</collapsible-component>
|
|
57
|
+
```
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
## Customization
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Customize the animation with CSS custom properties:
|
|
62
62
|
|
|
63
63
|
```css
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
--
|
|
67
|
-
--cc-button-width: 100%;
|
|
68
|
-
--cc-button-text-align: left;
|
|
69
|
-
|
|
70
|
-
/* Appearance */
|
|
71
|
-
--cc-button-background: none;
|
|
72
|
-
--cc-button-border: none;
|
|
73
|
-
--cc-button-cursor: pointer;
|
|
74
|
-
|
|
75
|
-
/* Animation */
|
|
76
|
-
--cc-content-padding: 10px;
|
|
77
|
-
--cc-transition-duration: 0.5s;
|
|
78
|
-
--cc-transition-timing: ease-in-out;
|
|
64
|
+
collapsible-content {
|
|
65
|
+
--collapsible-duration: 0.5s;
|
|
66
|
+
--collapsible-easing: ease-in-out;
|
|
79
67
|
}
|
|
80
68
|
```
|
|
81
69
|
|
|
82
|
-
|
|
70
|
+
| Property | Default | Description |
|
|
71
|
+
|----------|---------|-------------|
|
|
72
|
+
| `--collapsible-duration` | `0.35s` | Animation duration |
|
|
73
|
+
| `--collapsible-easing` | `ease-out` | Animation timing function |
|
|
83
74
|
|
|
84
|
-
|
|
75
|
+
## Events
|
|
85
76
|
|
|
86
|
-
|
|
87
|
-
// Option 1: Import the compiled CSS
|
|
88
|
-
@import '@magic-spells/collapsible-content/css';
|
|
77
|
+
### collapsible-error
|
|
89
78
|
|
|
90
|
-
|
|
91
|
-
@use '@magic-spells/collapsible-content/scss' with (
|
|
92
|
-
$transition-duration: 0.5s,
|
|
93
|
-
$transition-timing: ease-in-out,
|
|
94
|
-
$content-padding: 10px
|
|
95
|
-
);
|
|
79
|
+
Fired when the component is missing required children:
|
|
96
80
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
);
|
|
101
|
-
|
|
81
|
+
```javascript
|
|
82
|
+
document.addEventListener('collapsible-error', (e) => {
|
|
83
|
+
console.error('Collapsible setup failed:', e.detail.error);
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Programmatic Control
|
|
88
|
+
|
|
89
|
+
Access the `collapsed` property on the `<collapsible-content>` element:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const content = document.querySelector('collapsible-content');
|
|
93
|
+
content.collapsed = true; // collapse
|
|
94
|
+
content.collapsed = false; // expand
|
|
95
|
+
console.log(content.collapsed); // get current state
|
|
102
96
|
```
|
|
103
97
|
|
|
104
98
|
## Accessibility
|
|
105
99
|
|
|
106
|
-
This component follows WCAG guidelines
|
|
100
|
+
This component follows WCAG guidelines:
|
|
107
101
|
|
|
108
|
-
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
102
|
+
- `aria-expanded` on button indicates current state
|
|
103
|
+
- `aria-controls` links button to content
|
|
104
|
+
- `role="region"` and `aria-labelledby` on content
|
|
105
|
+
- `aria-hidden` and `inert` when collapsed
|
|
106
|
+
- Keyboard accessible (Space/Enter to toggle)
|
|
107
|
+
- Focus-visible styling for keyboard users
|
|
108
|
+
- Respects `prefers-reduced-motion`
|
|
112
109
|
|
|
113
110
|
## Browser Support
|
|
114
111
|
|
|
115
|
-
|
|
112
|
+
Modern browsers with Web Components support (Chrome, Firefox, Safari, Edge).
|
|
116
113
|
|
|
117
114
|
## License
|
|
118
115
|
|
|
119
|
-
MIT
|
|
116
|
+
MIT
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
class CollapsibleComponent extends HTMLElement {
|
|
7
7
|
#handleClick;
|
|
8
|
+
#abortController;
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Initializes the component and sets up references to child elements
|
|
@@ -23,7 +24,7 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
23
24
|
// toggle expanded value
|
|
24
25
|
const expanded = _.button.getAttribute('aria-expanded') !== 'true';
|
|
25
26
|
_.button.setAttribute('aria-expanded', expanded);
|
|
26
|
-
_.content.
|
|
27
|
+
_.content.collapsed = !expanded;
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -39,7 +40,16 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
39
40
|
_.content = _.querySelector('collapsible-content');
|
|
40
41
|
|
|
41
42
|
if (!_.button || !_.content) {
|
|
42
|
-
|
|
43
|
+
const error = new Error(
|
|
44
|
+
'CollapsibleComponent requires a <button> and a <collapsible-content>.'
|
|
45
|
+
);
|
|
46
|
+
console.error(error.message);
|
|
47
|
+
_.dispatchEvent(
|
|
48
|
+
new CustomEvent('collapsible-error', {
|
|
49
|
+
bubbles: true,
|
|
50
|
+
detail: { error },
|
|
51
|
+
})
|
|
52
|
+
);
|
|
43
53
|
return;
|
|
44
54
|
}
|
|
45
55
|
|
|
@@ -48,18 +58,20 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
48
58
|
_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;
|
|
49
59
|
|
|
50
60
|
// set accessibility attributes
|
|
61
|
+
_.button.type ||= 'button';
|
|
51
62
|
_.button.setAttribute('aria-controls', _.content.id);
|
|
52
|
-
_.content.setAttribute('role', 'region');
|
|
53
63
|
_.content.setAttribute('aria-labelledby', _.button.id);
|
|
54
64
|
|
|
55
|
-
// set initial state based on
|
|
56
|
-
const
|
|
65
|
+
// set initial state based on open attribute
|
|
66
|
+
const open = _.content.hasAttribute('open');
|
|
67
|
+
_.button.setAttribute('aria-expanded', open);
|
|
68
|
+
_.content.collapsed = !open;
|
|
57
69
|
|
|
58
|
-
//
|
|
59
|
-
_
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
// use AbortController to prevent duplicate listeners on reconnection
|
|
71
|
+
_.#abortController = new AbortController();
|
|
72
|
+
_.button.addEventListener('click', _.#handleClick, {
|
|
73
|
+
signal: _.#abortController.signal,
|
|
74
|
+
});
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
/**
|
|
@@ -68,8 +80,9 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
68
80
|
*/
|
|
69
81
|
disconnectedCallback() {
|
|
70
82
|
const _ = this;
|
|
71
|
-
if (_
|
|
72
|
-
_.
|
|
83
|
+
if (_.#abortController) {
|
|
84
|
+
_.#abortController.abort();
|
|
85
|
+
_.#abortController = null;
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
}
|
|
@@ -79,6 +92,8 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
79
92
|
*/
|
|
80
93
|
class CollapsibleContent extends HTMLElement {
|
|
81
94
|
#handleTransitionEnd;
|
|
95
|
+
#abortController;
|
|
96
|
+
#animating = false;
|
|
82
97
|
|
|
83
98
|
/**
|
|
84
99
|
* Initializes the content element and binds event handlers
|
|
@@ -90,35 +105,30 @@ class CollapsibleContent extends HTMLElement {
|
|
|
90
105
|
// define event handler using arrow function for proper binding
|
|
91
106
|
_.#handleTransitionEnd = (event) => {
|
|
92
107
|
// exit if isn't height property
|
|
93
|
-
if (event.propertyName
|
|
108
|
+
if (event.propertyName !== 'height') return;
|
|
109
|
+
|
|
110
|
+
_.#animating = false;
|
|
94
111
|
|
|
95
112
|
// remove the inline height to allow dynamic content changes
|
|
96
|
-
if (!_.
|
|
113
|
+
if (!_.collapsed) {
|
|
97
114
|
_.style.height = 'auto';
|
|
98
115
|
}
|
|
99
116
|
};
|
|
100
|
-
|
|
101
|
-
// add event listener to remove height after transition
|
|
102
|
-
_.addEventListener('transitionend', _.#handleTransitionEnd);
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
/**
|
|
106
120
|
* Called when element is added to the DOM
|
|
107
|
-
* Sets initial height based on
|
|
121
|
+
* Sets initial height based on open attribute
|
|
108
122
|
*/
|
|
109
123
|
connectedCallback() {
|
|
110
124
|
const _ = this;
|
|
125
|
+
_.style.height = _.hasAttribute('open') ? 'auto' : '0';
|
|
111
126
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (expanded) {
|
|
118
|
-
_.style.height = 'auto';
|
|
119
|
-
} else {
|
|
120
|
-
_.style.height = '0';
|
|
121
|
-
}
|
|
127
|
+
// use AbortController to prevent duplicate listeners on reconnection
|
|
128
|
+
_.#abortController = new AbortController();
|
|
129
|
+
_.addEventListener('transitionend', _.#handleTransitionEnd, {
|
|
130
|
+
signal: _.#abortController.signal,
|
|
131
|
+
});
|
|
122
132
|
}
|
|
123
133
|
|
|
124
134
|
/**
|
|
@@ -127,57 +137,74 @@ class CollapsibleContent extends HTMLElement {
|
|
|
127
137
|
*/
|
|
128
138
|
disconnectedCallback() {
|
|
129
139
|
const _ = this;
|
|
130
|
-
|
|
140
|
+
if (_.#abortController) {
|
|
141
|
+
_.#abortController.abort();
|
|
142
|
+
_.#abortController = null;
|
|
143
|
+
}
|
|
131
144
|
}
|
|
132
145
|
|
|
133
146
|
/**
|
|
134
|
-
* Handles setting the
|
|
135
|
-
* @param {boolean} value - Whether element should be
|
|
147
|
+
* Handles setting the collapsed state with animation
|
|
148
|
+
* @param {boolean} value - Whether element should be collapsed
|
|
136
149
|
*/
|
|
137
|
-
set
|
|
150
|
+
set collapsed(value) {
|
|
138
151
|
const _ = this;
|
|
139
152
|
|
|
140
|
-
//
|
|
153
|
+
// prevent rapid clicking during animation
|
|
154
|
+
if (_.#animating) return;
|
|
155
|
+
|
|
156
|
+
// check if transitions are enabled (respects prefers-reduced-motion)
|
|
157
|
+
const hasTransition = getComputedStyle(_).transitionDuration !== '0s';
|
|
158
|
+
|
|
141
159
|
if (value) {
|
|
142
|
-
|
|
160
|
+
if (hasTransition) {
|
|
161
|
+
_.#animating = true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// animate to closed
|
|
143
165
|
_.style.height = `${_.scrollHeight}px`;
|
|
144
166
|
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
167
|
+
// use requestAnimationFrame for reliable frame timing
|
|
168
|
+
requestAnimationFrame(() => {
|
|
169
|
+
requestAnimationFrame(() => {
|
|
170
|
+
_.style.height = '0px';
|
|
171
|
+
});
|
|
172
|
+
});
|
|
149
173
|
|
|
150
|
-
|
|
174
|
+
_.removeAttribute('open');
|
|
151
175
|
_.setAttribute('aria-hidden', 'true');
|
|
152
176
|
_.setAttribute('inert', '');
|
|
153
|
-
_.setAttribute('hidden', '');
|
|
154
177
|
} else {
|
|
155
|
-
// only animate if not
|
|
178
|
+
// only animate if not already auto
|
|
156
179
|
if (_.style.height !== 'auto') {
|
|
157
|
-
|
|
180
|
+
if (hasTransition) {
|
|
181
|
+
_.#animating = true;
|
|
182
|
+
}
|
|
158
183
|
_.style.height = `${_.scrollHeight}px`;
|
|
159
184
|
}
|
|
160
185
|
|
|
161
|
-
|
|
186
|
+
_.setAttribute('open', '');
|
|
162
187
|
_.removeAttribute('aria-hidden');
|
|
163
188
|
_.removeAttribute('inert');
|
|
164
|
-
_.removeAttribute('hidden');
|
|
165
189
|
}
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
/**
|
|
169
|
-
* Gets the
|
|
170
|
-
* @returns {boolean} Whether element is
|
|
193
|
+
* Gets the collapsed state
|
|
194
|
+
* @returns {boolean} Whether element is collapsed
|
|
171
195
|
*/
|
|
172
|
-
get
|
|
173
|
-
|
|
174
|
-
return _.hasAttribute('hidden');
|
|
196
|
+
get collapsed() {
|
|
197
|
+
return !this.hasAttribute('open');
|
|
175
198
|
}
|
|
176
199
|
}
|
|
177
200
|
|
|
178
|
-
// register custom elements
|
|
179
|
-
customElements.
|
|
180
|
-
customElements.define('collapsible-
|
|
201
|
+
// register custom elements if not already defined
|
|
202
|
+
if (!customElements.get('collapsible-content')) {
|
|
203
|
+
customElements.define('collapsible-content', CollapsibleContent);
|
|
204
|
+
}
|
|
205
|
+
if (!customElements.get('collapsible-component')) {
|
|
206
|
+
customElements.define('collapsible-component', CollapsibleComponent);
|
|
207
|
+
}
|
|
181
208
|
|
|
182
209
|
exports.CollapsibleComponent = CollapsibleComponent;
|
|
183
210
|
exports.CollapsibleContent = CollapsibleContent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible-content.cjs.js","sources":["../src/collapsible-content.js"],"sourcesContent":["import './index.scss';\n\n/**\n * Custom element that creates a collapsible/expandable component with proper accessibility\n */\nclass CollapsibleComponent extends HTMLElement {\n\t#handleClick;\n\n\t/**\n\t * Initializes the component and sets up references to child elements\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// store references to elements once to avoid re-querying\n\t\t_.button = null;\n\t\t_.content = null;\n\n\t\t// define click handler with proper this binding\n\t\t_.#handleClick = (e) => {\n\t\t\te.preventDefault();\n\t\t\t// toggle expanded value\n\t\t\tconst expanded = _.button.getAttribute('aria-expanded') !== 'true';\n\t\t\t_.button.setAttribute('aria-expanded', expanded);\n\t\t\t_.content.hidden = !expanded;\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets up accessibility attributes and event listeners\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// initialize element references once\n\t\t_.button = _.querySelector('button');\n\t\t_.content = _.querySelector('collapsible-content');\n\n\t\tif (!_.button || !_.content) {\n\t\t\tconsole.error('CollapsibleComponent requires a <button> and a <collapsible-content>.');\n\t\t\treturn;\n\t\t}\n\n\t\t// generate ids if not provided\n\t\t_.button.id ||= `collapsible-button-${crypto.randomUUID().slice(0, 8)}`;\n\t\t_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\t// set accessibility attributes\n\t\t_.button.setAttribute('aria-controls', _.content.id);\n\t\t_.content.setAttribute('role', 'region');\n\t\t_.content.setAttribute('aria-labelledby', _.button.id);\n\n\t\t// set initial state based on aria-expanded attribute\n\t\tconst expanded = _.button.getAttribute('aria-expanded') === 'true';\n\n\t\t// make sure content state matches button state\n\t\t_.content.hidden = !expanded;\n\n\t\t// add event listener\n\t\t_.button.addEventListener('click', _.#handleClick);\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.button) {\n\t\t\t_.button.removeEventListener('click', _.#handleClick);\n\t\t}\n\t}\n}\n\n/**\n * Custom element that provides animated collapsible content\n */\nclass CollapsibleContent extends HTMLElement {\n\t#handleTransitionEnd;\n\n\t/**\n\t * Initializes the content element and binds event handlers\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// define event handler using arrow function for proper binding\n\t\t_.#handleTransitionEnd = (event) => {\n\t\t\t// exit if isn't height property\n\t\t\tif (event.propertyName != 'height') return;\n\n\t\t\t// remove the inline height to allow dynamic content changes\n\t\t\tif (!_.hidden) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t}\n\t\t};\n\n\t\t// add event listener to remove height after transition\n\t\t_.addEventListener('transitionend', _.#handleTransitionEnd);\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets initial height based on hidden state\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// get aria-expanded state from button\n\t\tconst component = _.closest('collapsible-component');\n\t\tconst button = component.querySelector('button');\n\t\tconst expanded = button.getAttribute('aria-expanded') === 'true';\n\n\t\tif (expanded) {\n\t\t\t_.style.height = 'auto';\n\t\t} else {\n\t\t\t_.style.height = '0';\n\t\t}\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.removeEventListener('transitionend', _.#handleTransitionEnd);\n\t}\n\n\t/**\n\t * Handles setting the hidden attribute with animation\n\t * @param {boolean} value - Whether element should be hidden\n\t */\n\tset hidden(value) {\n\t\tconst _ = this;\n\n\t\t// animate to closed\n\t\tif (value) {\n\t\t\t// reset height to animate from\n\t\t\t_.style.height = `${_.scrollHeight}px`;\n\n\t\t\t// wait one frame and animate to 0\n\t\t\tsetTimeout(() => {\n\t\t\t\t_.style.height = '0px';\n\t\t\t}, 1);\n\n\t\t\t// set accessibility attributes\n\t\t\t_.setAttribute('aria-hidden', 'true');\n\t\t\t_.setAttribute('inert', '');\n\t\t\t_.setAttribute('hidden', '');\n\t\t} else {\n\t\t\t// only animate if not set to auto\n\t\t\tif (_.style.height !== 'auto') {\n\t\t\t\t// animate to open\n\t\t\t\t_.style.height = `${_.scrollHeight}px`;\n\t\t\t}\n\n\t\t\t// remove accessibility attributes\n\t\t\t_.removeAttribute('aria-hidden');\n\t\t\t_.removeAttribute('inert');\n\t\t\t_.removeAttribute('hidden');\n\t\t}\n\t}\n\n\t/**\n\t * Gets the hidden state from the attribute\n\t * @returns {boolean} Whether element is hidden\n\t */\n\tget hidden() {\n\t\tconst _ = this;\n\t\treturn _.hasAttribute('hidden');\n\t}\n}\n\n// register custom elements\ncustomElements.define('collapsible-content', CollapsibleContent);\ncustomElements.define('collapsible-component', CollapsibleComponent);\n\nexport { CollapsibleContent, CollapsibleComponent };\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"collapsible-content.cjs.js","sources":["../src/collapsible-content.js"],"sourcesContent":["import './collapsible-content.css';\n\n/**\n * Custom element that creates a collapsible/expandable component with proper accessibility\n */\nclass CollapsibleComponent extends HTMLElement {\n\t#handleClick;\n\t#abortController;\n\n\t/**\n\t * Initializes the component and sets up references to child elements\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// store references to elements once to avoid re-querying\n\t\t_.button = null;\n\t\t_.content = null;\n\n\t\t// define click handler with proper this binding\n\t\t_.#handleClick = (e) => {\n\t\t\te.preventDefault();\n\t\t\t// toggle expanded value\n\t\t\tconst expanded = _.button.getAttribute('aria-expanded') !== 'true';\n\t\t\t_.button.setAttribute('aria-expanded', expanded);\n\t\t\t_.content.collapsed = !expanded;\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets up accessibility attributes and event listeners\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// initialize element references once\n\t\t_.button = _.querySelector('button');\n\t\t_.content = _.querySelector('collapsible-content');\n\n\t\tif (!_.button || !_.content) {\n\t\t\tconst error = new Error(\n\t\t\t\t'CollapsibleComponent requires a <button> and a <collapsible-content>.'\n\t\t\t);\n\t\t\tconsole.error(error.message);\n\t\t\t_.dispatchEvent(\n\t\t\t\tnew CustomEvent('collapsible-error', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: { error },\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// generate ids if not provided\n\t\t_.button.id ||= `collapsible-button-${crypto.randomUUID().slice(0, 8)}`;\n\t\t_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\t// set accessibility attributes\n\t\t_.button.type ||= 'button';\n\t\t_.button.setAttribute('aria-controls', _.content.id);\n\t\t_.content.setAttribute('aria-labelledby', _.button.id);\n\n\t\t// set initial state based on open attribute\n\t\tconst open = _.content.hasAttribute('open');\n\t\t_.button.setAttribute('aria-expanded', open);\n\t\t_.content.collapsed = !open;\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.button.addEventListener('click', _.#handleClick, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n}\n\n/**\n * Custom element that provides animated collapsible content\n */\nclass CollapsibleContent extends HTMLElement {\n\t#handleTransitionEnd;\n\t#abortController;\n\t#animating = false;\n\n\t/**\n\t * Initializes the content element and binds event handlers\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// define event handler using arrow function for proper binding\n\t\t_.#handleTransitionEnd = (event) => {\n\t\t\t// exit if isn't height property\n\t\t\tif (event.propertyName !== 'height') return;\n\n\t\t\t_.#animating = false;\n\n\t\t\t// remove the inline height to allow dynamic content changes\n\t\t\tif (!_.collapsed) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets initial height based on open attribute\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.style.height = _.hasAttribute('open') ? 'auto' : '0';\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.addEventListener('transitionend', _.#handleTransitionEnd, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n\n\t/**\n\t * Handles setting the collapsed state with animation\n\t * @param {boolean} value - Whether element should be collapsed\n\t */\n\tset collapsed(value) {\n\t\tconst _ = this;\n\n\t\t// prevent rapid clicking during animation\n\t\tif (_.#animating) return;\n\n\t\t// check if transitions are enabled (respects prefers-reduced-motion)\n\t\tconst hasTransition = getComputedStyle(_).transitionDuration !== '0s';\n\n\t\tif (value) {\n\t\t\tif (hasTransition) {\n\t\t\t\t_.#animating = true;\n\t\t\t}\n\n\t\t\t// animate to closed\n\t\t\t_.style.height = `${_.scrollHeight}px`;\n\n\t\t\t// use requestAnimationFrame for reliable frame timing\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t_.style.height = '0px';\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t_.removeAttribute('open');\n\t\t\t_.setAttribute('aria-hidden', 'true');\n\t\t\t_.setAttribute('inert', '');\n\t\t} else {\n\t\t\t// only animate if not already auto\n\t\t\tif (_.style.height !== 'auto') {\n\t\t\t\tif (hasTransition) {\n\t\t\t\t\t_.#animating = true;\n\t\t\t\t}\n\t\t\t\t_.style.height = `${_.scrollHeight}px`;\n\t\t\t}\n\n\t\t\t_.setAttribute('open', '');\n\t\t\t_.removeAttribute('aria-hidden');\n\t\t\t_.removeAttribute('inert');\n\t\t}\n\t}\n\n\t/**\n\t * Gets the collapsed state\n\t * @returns {boolean} Whether element is collapsed\n\t */\n\tget collapsed() {\n\t\treturn !this.hasAttribute('open');\n\t}\n}\n\n// register custom elements if not already defined\nif (!customElements.get('collapsible-content')) {\n\tcustomElements.define('collapsible-content', CollapsibleContent);\n}\nif (!customElements.get('collapsible-component')) {\n\tcustomElements.define('collapsible-component', CollapsibleComponent);\n}\n\nexport { CollapsibleContent, CollapsibleComponent };\n"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +1,31 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--cc-component-display: block;
|
|
3
|
-
--cc-button-width: 100%;
|
|
4
|
-
--cc-button-text-align: left;
|
|
5
|
-
--cc-button-background: none;
|
|
6
|
-
--cc-button-border: none;
|
|
7
|
-
--cc-button-cursor: pointer;
|
|
8
|
-
--cc-content-padding: 0px;
|
|
9
|
-
--cc-content-display: block;
|
|
10
|
-
--cc-content-overflow: hidden;
|
|
11
|
-
--cc-transition-duration: 0.35s;
|
|
12
|
-
--cc-transition-timing: ease-out;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
1
|
collapsible-component {
|
|
16
|
-
display:
|
|
2
|
+
display: block;
|
|
17
3
|
}
|
|
4
|
+
|
|
18
5
|
collapsible-component button {
|
|
19
|
-
width:
|
|
20
|
-
text-align:
|
|
21
|
-
background:
|
|
22
|
-
border:
|
|
23
|
-
cursor:
|
|
6
|
+
width: 100%;
|
|
7
|
+
text-align: left;
|
|
8
|
+
background: none;
|
|
9
|
+
border: none;
|
|
10
|
+
cursor: pointer;
|
|
24
11
|
}
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
|
|
13
|
+
collapsible-component button:focus-visible {
|
|
14
|
+
outline: 2px solid currentColor;
|
|
15
|
+
outline-offset: 2px;
|
|
27
16
|
}
|
|
28
17
|
|
|
29
18
|
collapsible-content {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
19
|
+
--collapsible-duration: 0.35s;
|
|
20
|
+
--collapsible-easing: ease-out;
|
|
21
|
+
|
|
22
|
+
display: block;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
transition: height var(--collapsible-duration) var(--collapsible-easing);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@media (prefers-reduced-motion: reduce) {
|
|
28
|
+
collapsible-content {
|
|
29
|
+
transition: none;
|
|
30
|
+
}
|
|
31
|
+
}
|