Bug 213349

Summary: <summary> transitions not when <details> is opened
Product: WebKit Reporter: Bouke <bouke>
Component: AnimationsAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: ahmad.saleem792, bouke, dino, geoffrey.pursell, graouts, graouts, koivisto, mic.gallego, rik, simon.fraser, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: Safari 13   
Hardware: Mac   
OS: macOS 10.15   
URL: https://jsfiddle.net/Lzw1rkqn/1/
Bug Depends on:    
Bug Blocks: 252223    

Description Bouke 2020-06-18 13:20:44 PDT
Say I have implemented a custom disclosure triangle for my <summary> element:

details summary {
  list-style: none;
}

details summary::-webkit-details-marker {
  display: none;
}

details summary::before {
  content: ">";
  display: inline-block;
  transition: transform 0.5s ease;
  width: 1em;
  vertical-align: baseline;
  text-align: center;
}

details[open] summary::before {
  transform: rotate(90deg);
}

And it is used like this:

<details>
  <summary>System Information</summary>
  <p>
    macOS Catalina
  </p>
</details>

Expected behaviour:
As soon as I click the <summary> element, the transition from > to ⌄ should start, and vice versa.

Actual behaviour:
The transition doesn't start when the <summary> element is clicked. The exact conditions that are triggering the transition are somewhat unclear to me. It seems to start only after giving another element focus or moving the cursor outside of the parent element.
Comment 1 Radar WebKit Bug Importer 2020-06-19 17:29:16 PDT
<rdar://problem/64550434>
Comment 2 Ahmad Saleem 2022-10-08 08:44:19 PDT
I am able to reproduce this bug in Safari Technology Preview 155 using the testcase from Comment 0 and I have changed it into JSFiddle and added to URL Field.

It does not do transition animation when clicking / expanding to show details while Chrome Canary 108 and Firefox Nightly 107 does. Thanks!
Comment 3 mic.gallego 2022-12-08 23:08:14 PST
I am facing the same issue. It seems it was fixed from iOS14 (I had my animation working properly on the <summary> element). However, starting from iOS16.1 (or 16 maybe), this stopped working.
Comment 4 Antoine Quint 2022-12-11 05:51:54 PST
We don't seem to even generate a CSS Transition internally, at least Web Inspector does not indicate one.
Comment 5 Antoine Quint 2022-12-11 10:31:47 PST
So we create the transition correctly, but it gets canceled later in the same style update.

In Document::resolveStyle(), we end up calling Style::TreeResolver::createAnimatedElementUpdate() with this stack:

#0	0x00000002856970c4 in WebCore::Style::TreeResolver::createAnimatedElementUpdate(std::__1::unique_ptr<WebCore::RenderStyle, std::__1::default_delete<WebCore::RenderStyle> >, WebCore::Styleable const&, WebCore::Style::Change, WebCore::Style::ResolutionContext const&) at WebCore/style/StyleTreeResolver.cpp:586
#1	0x0000000285697950 in WebCore::Style::TreeResolver::resolvePseudoElement(WebCore::Element&, WebCore::PseudoId, WebCore::Style::ElementUpdate const&) at WebCore/style/StyleTreeResolver.cpp:347
#2	0x00000002856974b4 in WebCore::Style::TreeResolver::resolveElement(WebCore::Element&, WebCore::RenderStyle const*, WebCore::Style::TreeResolver::ResolutionType)::$_5::operator()(WebCore::PseudoId) const at WebCore/style/StyleTreeResolver.cpp:262
#3	0x0000000285696cc4 in WebCore::Style::TreeResolver::resolveElement(WebCore::Element&, WebCore::RenderStyle const*, WebCore::Style::TreeResolver::ResolutionType) at WebCore/style/StyleTreeResolver.cpp:286
#4	0x000000028569a70c in WebCore::Style::TreeResolver::resolveComposedTree() at WebCore/style/StyleTreeResolver.cpp:826
#5	0x000000028569ba48 in WebCore::Style::TreeResolver::resolve() at WebCore/style/StyleTreeResolver.cpp:942
#6	0x00000002837f6e4c in WebCore::Document::resolveStyle(WebCore::Document::ResolveStyleType) at WebCore/dom/Document.cpp:2121
#7	0x00000002837f7cf4 in WebCore::Document::updateStyleIfNeeded() at WebCore/dom/Document.cpp:2257
#8	0x000000028385f52c in WebCore::Document::Document(WebCore::Frame*, WebCore::Settings const&, WTF::URL const&, WTF::OptionSet<WebCore::Document::DocumentClass>, unsigned int, WebCore::ProcessQualified<WTF::UUID>)::$_7::operator()() const at WebCore/dom/Document.cpp:558

But then later on we call Styleable::cancelDeclarativeAnimations() in this stack:

#0	0x000000028569df68 in WebCore::Styleable::cancelDeclarativeAnimations() const at WebCore/style/Styleable.cpp:261
#1	0x000000028569deac in WebCore::Styleable::elementWasRemoved() const at WebCore/style/Styleable.cpp:245
#2	0x00000002839f4ffc in WebCore::PseudoElement::clearHostElement() at WebCore/dom/PseudoElement.cpp:77
#3	0x00000002838ecffc in WebCore::disconnectPseudoElement(WebCore::PseudoElement*) at WebCore/dom/Element.cpp:4004
#4	0x00000002838eced4 in WebCore::Element::clearBeforePseudoElementSlow() at WebCore/dom/Element.cpp:4010
#5	0x00000002838e49ec in WebCore::Element::clearBeforePseudoElement() at WebCore/dom/Element.h:846
#6	0x00000002855b6fb8 in WebCore::RenderTreeUpdater::GeneratedContent::removeBeforePseudoElement(WebCore::Element&, WebCore::RenderTreeBuilder&) at WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp:224
#7	0x00000002855b63ec in WebCore::RenderTreeUpdater::tearDownRenderers(WebCore::Element&, WebCore::RenderTreeUpdater::TeardownType, WebCore::RenderTreeBuilder&)::$_5::operator()(unsigned int) const at WebCore/rendering/updating/RenderTreeUpdater.cpp:600
#8	0x00000002855b4eb4 in WebCore::RenderTreeUpdater::tearDownRenderers(WebCore::Element&, WebCore::RenderTreeUpdater::TeardownType, WebCore::RenderTreeBuilder&) at WebCore/rendering/updating/RenderTreeUpdater.cpp:617
#9	0x00000002855b3e5c in WebCore::RenderTreeUpdater::updateElementRenderer(WebCore::Element&, WebCore::Style::ElementUpdate const&) at WebCore/rendering/updating/RenderTreeUpdater.cpp:325
#10	0x00000002855b33f4 in WebCore::RenderTreeUpdater::updateRenderTree(WebCore::ContainerNode&) at WebCore/rendering/updating/RenderTreeUpdater.cpp:187
#11	0x00000002855b2ca8 in WebCore::RenderTreeUpdater::commit(std::__1::unique_ptr<WebCore::Style::Update const, std::__1::default_delete<WebCore::Style::Update const> >) at WebCore/rendering/updating/RenderTreeUpdater.cpp:114
#12	0x00000002837f69a8 in WebCore::Document::updateRenderTree(std::__1::unique_ptr<WebCore::Style::Update const, std::__1::default_delete<WebCore::Style::Update const> >) at WebCore/dom/Document.cpp:2048
#13	0x00000002837f6fa8 in WebCore::Document::resolveStyle(WebCore::Document::ResolveStyleType) at WebCore/dom/Document.cpp:2147
#14	0x00000002837f7cf4 in WebCore::Document::updateStyleIfNeeded() at WebCore/dom/Document.cpp:2257
#15	0x000000028385f52c in WebCore::Document::Document(WebCore::Frame*, WebCore::Settings const&, WTF::URL const&, WTF::OptionSet<WebCore::Document::DocumentClass>, unsigned int, WebCore::ProcessQualified<WTF::UUID>)::$_7::operator()() const at WebCore/dom/Document.cpp:558

We need to either avoid tearing down the ::before renderer or ensure its transitions are preserved when the new ::before renderer is created.
Comment 6 geoffrey.pursell 2023-05-23 09:28:37 PDT
Just wanted to chime in that I'm running into exactly this myself. It would be great to be able to adopt the web standard elements for this UI pattern.