@magic-spells/collapsible-content 0.2.0 → 1.1.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 +110 -62
- package/dist/collapsible-content.cjs.js +183 -64
- package/dist/collapsible-content.cjs.js.map +1 -1
- package/dist/collapsible-content.css +24 -27
- package/dist/collapsible-content.esm.js +183 -64
- package/dist/collapsible-content.esm.js.map +1 -1
- package/dist/collapsible-content.js +183 -64
- 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 +7 -11
- package/src/collapsible-content.css +31 -0
- package/src/collapsible-content.js +184 -65
- 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
|
@@ -1,10 +1,36 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './collapsible-content.css';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_SPEED = 900; // px per second
|
|
4
|
+
const MIN_DURATION = 0.25; // seconds
|
|
5
|
+
const MAX_DURATION = 1.0; // seconds
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
8
|
* Custom element that creates a collapsible/expandable component with proper accessibility
|
|
5
9
|
*/
|
|
6
10
|
class CollapsibleComponent extends HTMLElement {
|
|
11
|
+
static #groups = new Map();
|
|
12
|
+
|
|
13
|
+
static #addToGroup(name, instance) {
|
|
14
|
+
if (!CollapsibleComponent.#groups.has(name)) {
|
|
15
|
+
CollapsibleComponent.#groups.set(name, new Set());
|
|
16
|
+
}
|
|
17
|
+
CollapsibleComponent.#groups.get(name).add(instance);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static #removeFromGroup(name, instance) {
|
|
21
|
+
const group = CollapsibleComponent.#groups.get(name);
|
|
22
|
+
if (group) {
|
|
23
|
+
group.delete(instance);
|
|
24
|
+
if (group.size === 0) CollapsibleComponent.#groups.delete(name);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static get observedAttributes() {
|
|
29
|
+
return ['group'];
|
|
30
|
+
}
|
|
31
|
+
|
|
7
32
|
#handleClick;
|
|
33
|
+
#abortController;
|
|
8
34
|
|
|
9
35
|
/**
|
|
10
36
|
* Initializes the component and sets up references to child elements
|
|
@@ -17,13 +43,12 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
17
43
|
_.button = null;
|
|
18
44
|
_.content = null;
|
|
19
45
|
|
|
20
|
-
// define click handler
|
|
21
|
-
_.#handleClick = (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
_
|
|
26
|
-
_.content.hidden = !expanded;
|
|
46
|
+
// define click handler — content is source of truth
|
|
47
|
+
_.#handleClick = () => {
|
|
48
|
+
const wasCollapsed = _.content.collapsed;
|
|
49
|
+
_.content.collapsed = !wasCollapsed;
|
|
50
|
+
_.button.setAttribute('aria-expanded', !_.content.collapsed);
|
|
51
|
+
if (wasCollapsed) _.#closeSiblings();
|
|
27
52
|
};
|
|
28
53
|
}
|
|
29
54
|
|
|
@@ -39,7 +64,16 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
39
64
|
_.content = _.querySelector('collapsible-content');
|
|
40
65
|
|
|
41
66
|
if (!_.button || !_.content) {
|
|
42
|
-
|
|
67
|
+
const error = new Error(
|
|
68
|
+
'CollapsibleComponent requires a <button> and a <collapsible-content>.'
|
|
69
|
+
);
|
|
70
|
+
console.error(error.message);
|
|
71
|
+
_.dispatchEvent(
|
|
72
|
+
new CustomEvent('collapsible-error', {
|
|
73
|
+
bubbles: true,
|
|
74
|
+
detail: { error },
|
|
75
|
+
})
|
|
76
|
+
);
|
|
43
77
|
return;
|
|
44
78
|
}
|
|
45
79
|
|
|
@@ -48,18 +82,38 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
48
82
|
_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;
|
|
49
83
|
|
|
50
84
|
// set accessibility attributes
|
|
85
|
+
if (!_.button.hasAttribute('type')) {
|
|
86
|
+
_.button.type = 'button';
|
|
87
|
+
}
|
|
51
88
|
_.button.setAttribute('aria-controls', _.content.id);
|
|
52
|
-
_.content.setAttribute('role', 'region');
|
|
53
89
|
_.content.setAttribute('aria-labelledby', _.button.id);
|
|
90
|
+
if (!_.content.hasAttribute('role')) {
|
|
91
|
+
_.content.setAttribute('role', 'region');
|
|
92
|
+
}
|
|
54
93
|
|
|
55
|
-
// set initial state
|
|
56
|
-
const
|
|
94
|
+
// set initial state without triggering an opening/closing animation
|
|
95
|
+
const open = _.content.hasAttribute('open');
|
|
96
|
+
_.button.setAttribute('aria-expanded', open);
|
|
97
|
+
_.content.style.height = open ? 'auto' : '0px';
|
|
98
|
+
if (open) {
|
|
99
|
+
_.content.removeAttribute('aria-hidden');
|
|
100
|
+
_.content.removeAttribute('inert');
|
|
101
|
+
} else {
|
|
102
|
+
_.content.setAttribute('aria-hidden', 'true');
|
|
103
|
+
_.content.setAttribute('inert', '');
|
|
104
|
+
}
|
|
57
105
|
|
|
58
|
-
//
|
|
59
|
-
_
|
|
106
|
+
// use AbortController to prevent duplicate listeners on reconnection
|
|
107
|
+
_.#abortController = new AbortController();
|
|
108
|
+
_.button.addEventListener('click', _.#handleClick, {
|
|
109
|
+
signal: _.#abortController.signal,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
60
112
|
|
|
61
|
-
|
|
62
|
-
|
|
113
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
114
|
+
if (name !== 'group') return;
|
|
115
|
+
if (oldValue) CollapsibleComponent.#removeFromGroup(oldValue, this);
|
|
116
|
+
if (newValue) CollapsibleComponent.#addToGroup(newValue, this);
|
|
63
117
|
}
|
|
64
118
|
|
|
65
119
|
/**
|
|
@@ -68,8 +122,26 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
68
122
|
*/
|
|
69
123
|
disconnectedCallback() {
|
|
70
124
|
const _ = this;
|
|
71
|
-
|
|
72
|
-
|
|
125
|
+
const group = _.getAttribute('group');
|
|
126
|
+
if (group) CollapsibleComponent.#removeFromGroup(group, _);
|
|
127
|
+
if (_.#abortController) {
|
|
128
|
+
_.#abortController.abort();
|
|
129
|
+
_.#abortController = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#closeSiblings() {
|
|
134
|
+
const _ = this;
|
|
135
|
+
const groupName = _.getAttribute('group');
|
|
136
|
+
if (!groupName) return;
|
|
137
|
+
const group = CollapsibleComponent.#groups.get(groupName);
|
|
138
|
+
if (!group) return;
|
|
139
|
+
for (const sibling of group) {
|
|
140
|
+
if (sibling === _) continue;
|
|
141
|
+
if (!sibling.content.collapsed) {
|
|
142
|
+
sibling.content.collapsed = true;
|
|
143
|
+
sibling.button.setAttribute('aria-expanded', 'false');
|
|
144
|
+
}
|
|
73
145
|
}
|
|
74
146
|
}
|
|
75
147
|
}
|
|
@@ -79,6 +151,8 @@ class CollapsibleComponent extends HTMLElement {
|
|
|
79
151
|
*/
|
|
80
152
|
class CollapsibleContent extends HTMLElement {
|
|
81
153
|
#handleTransitionEnd;
|
|
154
|
+
#abortController;
|
|
155
|
+
#animating = false;
|
|
82
156
|
|
|
83
157
|
/**
|
|
84
158
|
* Initializes the content element and binds event handlers
|
|
@@ -89,36 +163,32 @@ class CollapsibleContent extends HTMLElement {
|
|
|
89
163
|
|
|
90
164
|
// define event handler using arrow function for proper binding
|
|
91
165
|
_.#handleTransitionEnd = (event) => {
|
|
92
|
-
|
|
93
|
-
if (event.propertyName
|
|
166
|
+
if (event.target !== _) return;
|
|
167
|
+
if (event.propertyName !== 'height') return;
|
|
168
|
+
|
|
169
|
+
_.#animating = false;
|
|
170
|
+
_.style.removeProperty('--collapsible-duration');
|
|
94
171
|
|
|
95
172
|
// remove the inline height to allow dynamic content changes
|
|
96
|
-
if (!_.
|
|
173
|
+
if (!_.collapsed) {
|
|
97
174
|
_.style.height = 'auto';
|
|
98
175
|
}
|
|
99
176
|
};
|
|
100
|
-
|
|
101
|
-
// add event listener to remove height after transition
|
|
102
|
-
_.addEventListener('transitionend', _.#handleTransitionEnd);
|
|
103
177
|
}
|
|
104
178
|
|
|
105
179
|
/**
|
|
106
180
|
* Called when element is added to the DOM
|
|
107
|
-
* Sets initial height based on
|
|
181
|
+
* Sets initial height based on open attribute
|
|
108
182
|
*/
|
|
109
183
|
connectedCallback() {
|
|
110
184
|
const _ = this;
|
|
185
|
+
_.style.height = _.hasAttribute('open') ? 'auto' : '0';
|
|
111
186
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (expanded) {
|
|
118
|
-
_.style.height = 'auto';
|
|
119
|
-
} else {
|
|
120
|
-
_.style.height = '0';
|
|
121
|
-
}
|
|
187
|
+
// use AbortController to prevent duplicate listeners on reconnection
|
|
188
|
+
_.#abortController = new AbortController();
|
|
189
|
+
_.addEventListener('transitionend', _.#handleTransitionEnd, {
|
|
190
|
+
signal: _.#abortController.signal,
|
|
191
|
+
});
|
|
122
192
|
}
|
|
123
193
|
|
|
124
194
|
/**
|
|
@@ -127,56 +197,105 @@ class CollapsibleContent extends HTMLElement {
|
|
|
127
197
|
*/
|
|
128
198
|
disconnectedCallback() {
|
|
129
199
|
const _ = this;
|
|
130
|
-
_
|
|
200
|
+
_.#animating = false;
|
|
201
|
+
if (_.#abortController) {
|
|
202
|
+
_.#abortController.abort();
|
|
203
|
+
_.#abortController = null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
get #speed() {
|
|
208
|
+
const attr = this.getAttribute('speed');
|
|
209
|
+
if (attr === null) return DEFAULT_SPEED;
|
|
210
|
+
const value = Number(attr);
|
|
211
|
+
return value > 0 ? value : DEFAULT_SPEED;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
get #minDuration() {
|
|
215
|
+
const attr = this.getAttribute('min-duration');
|
|
216
|
+
if (attr === null) return MIN_DURATION;
|
|
217
|
+
const value = Number(attr);
|
|
218
|
+
return value > 0 ? value : MIN_DURATION;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
get #maxDuration() {
|
|
222
|
+
const attr = this.getAttribute('max-duration');
|
|
223
|
+
if (attr === null) return MAX_DURATION;
|
|
224
|
+
const value = Number(attr);
|
|
225
|
+
return value > 0 ? value : MAX_DURATION;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#setDynamicDuration(currentHeight, targetHeight) {
|
|
229
|
+
const _ = this;
|
|
230
|
+
const delta = Math.abs(targetHeight - currentHeight);
|
|
231
|
+
const duration = Math.min(_.#maxDuration, Math.max(_.#minDuration, delta / _.#speed));
|
|
232
|
+
_.style.setProperty('--collapsible-duration', `${duration.toFixed(3)}s`);
|
|
131
233
|
}
|
|
132
234
|
|
|
133
235
|
/**
|
|
134
|
-
* Handles setting the
|
|
135
|
-
* @param {boolean} value - Whether element should be
|
|
236
|
+
* Handles setting the collapsed state with animation
|
|
237
|
+
* @param {boolean} value - Whether element should be collapsed
|
|
136
238
|
*/
|
|
137
|
-
set
|
|
239
|
+
set collapsed(value) {
|
|
138
240
|
const _ = this;
|
|
241
|
+
const collapsed = Boolean(value);
|
|
242
|
+
if (_.collapsed === collapsed) return;
|
|
139
243
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
// reset height to animate from
|
|
143
|
-
_.style.height = `${_.scrollHeight}px`;
|
|
144
|
-
|
|
145
|
-
// wait one frame and animate to 0
|
|
146
|
-
setTimeout(() => {
|
|
147
|
-
_.style.height = '0px';
|
|
148
|
-
}, 1);
|
|
244
|
+
// check if transitions are enabled (respects prefers-reduced-motion)
|
|
245
|
+
const hasTransition = getComputedStyle(_).transitionDuration !== '0s';
|
|
149
246
|
|
|
150
|
-
|
|
247
|
+
if (collapsed) {
|
|
248
|
+
_.removeAttribute('open');
|
|
151
249
|
_.setAttribute('aria-hidden', 'true');
|
|
152
250
|
_.setAttribute('inert', '');
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// animate to open
|
|
158
|
-
_.style.height = `${_.scrollHeight}px`;
|
|
251
|
+
|
|
252
|
+
if (!hasTransition) {
|
|
253
|
+
_.style.height = '0px';
|
|
254
|
+
return;
|
|
159
255
|
}
|
|
160
256
|
|
|
161
|
-
//
|
|
257
|
+
// capture current height in px (converts auto or mid-animation value)
|
|
258
|
+
const currentHeight = _.getBoundingClientRect().height;
|
|
259
|
+
_.style.height = `${currentHeight}px`;
|
|
260
|
+
_.#setDynamicDuration(currentHeight, 0);
|
|
261
|
+
_.#animating = true;
|
|
262
|
+
_.offsetHeight; // force reflow — browser commits the px start value
|
|
263
|
+
_.style.height = '0px';
|
|
264
|
+
} else {
|
|
265
|
+
_.setAttribute('open', '');
|
|
162
266
|
_.removeAttribute('aria-hidden');
|
|
163
267
|
_.removeAttribute('inert');
|
|
164
|
-
|
|
268
|
+
|
|
269
|
+
if (!hasTransition) {
|
|
270
|
+
_.style.height = 'auto';
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// capture current height in px (0px or mid-animation value)
|
|
275
|
+
const currentHeight = _.getBoundingClientRect().height;
|
|
276
|
+
_.style.height = `${currentHeight}px`;
|
|
277
|
+
_.#setDynamicDuration(currentHeight, _.scrollHeight);
|
|
278
|
+
_.#animating = true;
|
|
279
|
+
_.offsetHeight; // force reflow — browser commits the px start value
|
|
280
|
+
_.style.height = `${_.scrollHeight}px`;
|
|
165
281
|
}
|
|
166
282
|
}
|
|
167
283
|
|
|
168
284
|
/**
|
|
169
|
-
* Gets the
|
|
170
|
-
* @returns {boolean} Whether element is
|
|
285
|
+
* Gets the collapsed state
|
|
286
|
+
* @returns {boolean} Whether element is collapsed
|
|
171
287
|
*/
|
|
172
|
-
get
|
|
173
|
-
|
|
174
|
-
return _.hasAttribute('hidden');
|
|
288
|
+
get collapsed() {
|
|
289
|
+
return !this.hasAttribute('open');
|
|
175
290
|
}
|
|
176
291
|
}
|
|
177
292
|
|
|
178
|
-
// register custom elements
|
|
179
|
-
customElements.
|
|
180
|
-
customElements.define('collapsible-
|
|
293
|
+
// register custom elements if not already defined
|
|
294
|
+
if (!customElements.get('collapsible-content')) {
|
|
295
|
+
customElements.define('collapsible-content', CollapsibleContent);
|
|
296
|
+
}
|
|
297
|
+
if (!customElements.get('collapsible-component')) {
|
|
298
|
+
customElements.define('collapsible-component', CollapsibleComponent);
|
|
299
|
+
}
|
|
181
300
|
|
|
182
301
|
export { CollapsibleContent, CollapsibleComponent };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Import variables using the modern @use rule
|
|
2
|
-
@use 'variables' as vars;
|
|
3
|
-
|
|
4
|
-
collapsible-component {
|
|
5
|
-
display: var(--cc-component-display, block);
|
|
6
|
-
|
|
7
|
-
button {
|
|
8
|
-
width: var(--cc-button-width, 100%);
|
|
9
|
-
text-align: var(--cc-button-text-align, left);
|
|
10
|
-
background: var(--cc-button-background, none);
|
|
11
|
-
border: var(--cc-button-border, none);
|
|
12
|
-
cursor: var(--cc-button-cursor, pointer);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
collapsible-content[hidden] {
|
|
16
|
-
display: var(--cc-content-display, block);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
collapsible-content {
|
|
21
|
-
padding: var(--cc-content-padding, 0px);
|
|
22
|
-
display: var(--cc-content-display, block);
|
|
23
|
-
overflow: var(--cc-content-overflow, hidden);
|
|
24
|
-
transition: height var(--cc-transition-duration, 0.35s) var(--cc-transition-timing, ease-out);
|
|
25
|
-
}
|
package/dist/scss/variables.scss
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// Collapsible Content variables
|
|
2
|
-
// SCSS variables for internal component use and customization
|
|
3
|
-
// these variables can be customized by the user
|
|
4
|
-
|
|
5
|
-
// layout
|
|
6
|
-
$component-display: block !default;
|
|
7
|
-
$button-width: 100% !default;
|
|
8
|
-
$button-text-align: left !default;
|
|
9
|
-
|
|
10
|
-
// appearance
|
|
11
|
-
$button-background: none !default;
|
|
12
|
-
$button-border: none !default;
|
|
13
|
-
$button-cursor: pointer !default;
|
|
14
|
-
|
|
15
|
-
// animation
|
|
16
|
-
$content-padding: 0px !default;
|
|
17
|
-
$content-display: block !default;
|
|
18
|
-
$content-overflow: hidden !default;
|
|
19
|
-
$transition-duration: 0.35s !default;
|
|
20
|
-
$transition-timing: ease-out !default;
|
|
21
|
-
|
|
22
|
-
// Define CSS Custom Properties using SCSS values
|
|
23
|
-
:root {
|
|
24
|
-
// layout
|
|
25
|
-
--cc-component-display: #{$component-display};
|
|
26
|
-
--cc-button-width: #{$button-width};
|
|
27
|
-
--cc-button-text-align: #{$button-text-align};
|
|
28
|
-
|
|
29
|
-
// appearance
|
|
30
|
-
--cc-button-background: #{$button-background};
|
|
31
|
-
--cc-button-border: #{$button-border};
|
|
32
|
-
--cc-button-cursor: #{$button-cursor};
|
|
33
|
-
|
|
34
|
-
// animation
|
|
35
|
-
--cc-content-padding: #{$content-padding};
|
|
36
|
-
--cc-content-display: #{$content-display};
|
|
37
|
-
--cc-content-overflow: #{$content-overflow};
|
|
38
|
-
--cc-transition-duration: #{$transition-duration};
|
|
39
|
-
--cc-transition-timing: #{$transition-timing};
|
|
40
|
-
}
|
package/src/index.scss
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Import variables using the modern @use rule
|
|
2
|
-
@use 'variables' as vars;
|
|
3
|
-
|
|
4
|
-
collapsible-component {
|
|
5
|
-
display: var(--cc-component-display, block);
|
|
6
|
-
|
|
7
|
-
button {
|
|
8
|
-
width: var(--cc-button-width, 100%);
|
|
9
|
-
text-align: var(--cc-button-text-align, left);
|
|
10
|
-
background: var(--cc-button-background, none);
|
|
11
|
-
border: var(--cc-button-border, none);
|
|
12
|
-
cursor: var(--cc-button-cursor, pointer);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
collapsible-content[hidden] {
|
|
16
|
-
display: var(--cc-content-display, block);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
collapsible-content {
|
|
21
|
-
padding: var(--cc-content-padding, 0px);
|
|
22
|
-
display: var(--cc-content-display, block);
|
|
23
|
-
overflow: var(--cc-content-overflow, hidden);
|
|
24
|
-
transition: height var(--cc-transition-duration, 0.35s) var(--cc-transition-timing, ease-out);
|
|
25
|
-
}
|
package/src/scss/variables.scss
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// Collapsible Content variables
|
|
2
|
-
// SCSS variables for internal component use and customization
|
|
3
|
-
// these variables can be customized by the user
|
|
4
|
-
|
|
5
|
-
// layout
|
|
6
|
-
$component-display: block !default;
|
|
7
|
-
$button-width: 100% !default;
|
|
8
|
-
$button-text-align: left !default;
|
|
9
|
-
|
|
10
|
-
// appearance
|
|
11
|
-
$button-background: none !default;
|
|
12
|
-
$button-border: none !default;
|
|
13
|
-
$button-cursor: pointer !default;
|
|
14
|
-
|
|
15
|
-
// animation
|
|
16
|
-
$content-padding: 0px !default;
|
|
17
|
-
$content-display: block !default;
|
|
18
|
-
$content-overflow: hidden !default;
|
|
19
|
-
$transition-duration: 0.35s !default;
|
|
20
|
-
$transition-timing: ease-out !default;
|
|
21
|
-
|
|
22
|
-
// Define CSS Custom Properties using SCSS values
|
|
23
|
-
:root {
|
|
24
|
-
// layout
|
|
25
|
-
--cc-component-display: #{$component-display};
|
|
26
|
-
--cc-button-width: #{$button-width};
|
|
27
|
-
--cc-button-text-align: #{$button-text-align};
|
|
28
|
-
|
|
29
|
-
// appearance
|
|
30
|
-
--cc-button-background: #{$button-background};
|
|
31
|
-
--cc-button-border: #{$button-border};
|
|
32
|
-
--cc-button-cursor: #{$button-cursor};
|
|
33
|
-
|
|
34
|
-
// animation
|
|
35
|
-
--cc-content-padding: #{$content-padding};
|
|
36
|
-
--cc-content-display: #{$content-display};
|
|
37
|
-
--cc-content-overflow: #{$content-overflow};
|
|
38
|
-
--cc-transition-duration: #{$transition-duration};
|
|
39
|
-
--cc-transition-timing: #{$transition-timing};
|
|
40
|
-
}
|