Skip to content

Commit f8d0147

Browse files
committed
WIP 4
1 parent 4fb41b4 commit f8d0147

File tree

3 files changed

+34
-27
lines changed

3 files changed

+34
-27
lines changed

docs/src/app/(private)/experiments/collapsible/new.tsx

+32-25
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ function Collapsible(props: {
118118
* Explicitly set `display` to ensure the panel is actually rendered before
119119
* measuring anything. `!important` is to needed to override a conflicting
120120
* Tailwind v4 default that sets `display: none !important` on `[hidden]`:
121-
* https://github.com/tailwindlabs/tailwindcss/blame/main/packages/tailwindcss/preflight.css#L382
121+
* https://github.com/tailwindlabs/tailwindcss/blob/cd154a4f471e7a63cc27cad15dada650de89d52b/packages/tailwindcss/preflight.css#L320-L326
122122
*/
123123
element.style.setProperty('display', 'block', 'important'); // TODO: maybe this can be set more conditionally
124124

@@ -134,16 +134,11 @@ function Collapsible(props: {
134134
element.setAttribute('data-starting-style', '');
135135
}
136136

137-
if (!shouldCancelInitialOpenTransitionRef.current && hiddenUntilFoundProp) {
138-
element.setAttribute('data-starting-style', '');
139-
}
140-
141137
setHeight(element.scrollHeight);
142138
element.style.removeProperty('display');
143139

144140
if (shouldCancelInitialOpenTransitionRef.current) {
145141
element.style.setProperty('transition-duration', '0s');
146-
// element.style.setProperty('display', 'none');
147142
}
148143
}
149144

@@ -173,7 +168,8 @@ function Collapsible(props: {
173168
const nextOpen = !open;
174169

175170
const panel = panelRef.current;
176-
if (panel && animationTypeRef.current === 'css-animation') {
171+
172+
if (animationTypeRef.current === 'css-animation' && panel != null) {
177173
panel.style.removeProperty('animation-name');
178174
}
179175

@@ -195,23 +191,26 @@ function Collapsible(props: {
195191
}
196192
setOpen(nextOpen);
197193

194+
/**
195+
* When `keepMounted={false}` and when opening, the element isn't inserted
196+
* in the DOM at this point so bail out here and resume in an effect.
197+
*/
198198
if (!panel || animationTypeRef.current !== 'css-transition') {
199199
return;
200200
}
201201

202202
panel.style.setProperty('display', 'block', 'important');
203203

204204
if (nextOpen) {
205+
/* opening */
205206
if (abortControllerRef.current != null) {
206207
abortControllerRef.current.abort();
207208
abortControllerRef.current = null;
208209
}
209210

210211
panel.style.removeProperty('display');
211212
panel.style.removeProperty('content-visibility');
212-
213-
/* opening */
214-
panel.style.height = '0px';
213+
panel.style.setProperty('height', '0px');
215214

216215
requestAnimationFrame(() => {
217216
panel.style.removeProperty('height');
@@ -229,20 +228,19 @@ function Collapsible(props: {
229228
abortControllerRef.current = new AbortController();
230229

231230
runOnceAnimationsFinish(() => {
232-
// TODO: !important may be needed
233-
panel.style.setProperty('display', 'none');
234-
// panel.style.removeProperty('content-visibility');
231+
panel.style.removeProperty('display');
232+
panel.style.removeProperty('content-visibility');
235233
abortControllerRef.current = null;
236234
}, abortControllerRef.current.signal);
237235
}
238236
});
239237

240238
/**
241-
* This only handles `keepMounted={false}` as the state changes can't be done
242-
* in the event handler
239+
* This only handles CSS transitions when `keepMounted={false}` as we may not
240+
* have access to the panel element in the DOM in the trigger event handler.
243241
*/
244242
useEnhancedEffect(() => {
245-
if (animationTypeRef.current !== 'css-transition') {
243+
if (animationTypeRef.current !== 'css-transition' || keepMounted) {
246244
return;
247245
}
248246

@@ -253,10 +251,6 @@ function Collapsible(props: {
253251
}
254252

255253
if (open) {
256-
if (hiddenUntilFoundProp) {
257-
return;
258-
}
259-
console.log('open here');
260254
if (abortControllerRef.current != null) {
261255
abortControllerRef.current.abort();
262256
abortControllerRef.current = null;
@@ -273,7 +267,6 @@ function Collapsible(props: {
273267
panel.style.removeProperty('display');
274268

275269
panel.style.removeProperty('height');
276-
277270
setHeight(panel.scrollHeight);
278271
});
279272
} else {
@@ -363,9 +356,24 @@ function Collapsible(props: {
363356
useEnhancedEffect(() => {
364357
const panel = panelRef.current;
365358

366-
if (panel && hiddenUntilFoundProp && isHidden) {
367-
// @ts-ignore
359+
if (
360+
panel &&
361+
hiddenUntilFoundProp &&
362+
animationTypeRef.current === 'css-transition' &&
363+
isHidden
364+
) {
365+
/**
366+
* React only supports a boolean for the `hidden` attribute and forces
367+
* legit string values to booleans so we have to force it back in the DOM
368+
* when necessary: https://github.com/facebook/react/issues/24740
369+
*/
368370
panel.setAttribute('hidden', 'until-found');
371+
/**
372+
* Set data-starting-style here to persist the closed styles, this is to
373+
* prevent transitions from starting when the `hidden` attribute changes
374+
* to `'until-found'` as they could have different `display` properties:
375+
* https://github.com/tailwindlabs/tailwindcss/pull/14625
376+
*/
369377
panel.setAttribute('data-starting-style', '');
370378
}
371379
}, [hiddenUntilFoundProp, isHidden]);
@@ -378,11 +386,10 @@ function Collapsible(props: {
378386
}
379387

380388
function handleBeforeMatch(event: Event) {
389+
// TODO: probably remove this because beforematch isn't cancellable anyway
381390
event.preventDefault();
382391

383392
isBeforeMatchRef.current = true;
384-
385-
// beforematch only fires if the matching content is initially hidden
386393
setOpen(true);
387394
}
388395

docs/src/app/(private)/experiments/collapsible/transition.module.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
.Root {
1818
--width: 320px;
19-
--duration: 5000ms;
19+
--duration: 1000ms;
2020

2121
width: var(--width);
2222

docs/src/app/(private)/experiments/collapsible/transition.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function Collapsible(props: {
9191
* Explicitly set `display` to ensure the panel is actually rendered before
9292
* measuring anything. `!important` is to needed to override a conflicting
9393
* Tailwind v4 default that sets `display: none !important` on `[hidden]`:
94-
* https://github.com/tailwindlabs/tailwindcss/blame/main/packages/tailwindcss/preflight.css#L382
94+
* https://github.com/tailwindlabs/tailwindcss/blob/cd154a4f471e7a63cc27cad15dada650de89d52b/packages/tailwindcss/preflight.css#L320-L326
9595
*/
9696
element.style.setProperty('display', 'block', 'important'); // TODO: maybe this can be set more conditionally
9797

0 commit comments

Comments
 (0)