@@ -41,6 +41,14 @@ export class Accordion implements ComponentInterface {
4141 private accordionGroupEl ?: HTMLIonAccordionGroupElement | null ;
4242 private updateListener = ( ev : CustomEvent < AccordionGroupChangeEventDetail > ) => {
4343 const initialUpdate = ev . detail ?. initial ?? false ;
44+ /**
45+ * If this is not an initial update (meaning it's from a user interaction
46+ * or programmatic call after load), mark that we've had an interaction.
47+ * This enables animations for this and future updates.
48+ */
49+ if ( ! initialUpdate ) {
50+ this . hasInteracted = true ;
51+ }
4452 this . updateState ( initialUpdate ) ;
4553 } ;
4654 private contentEl : HTMLDivElement | undefined ;
@@ -55,12 +63,18 @@ export class Accordion implements ComponentInterface {
5563 @State ( ) isNext = false ;
5664 @State ( ) isPrevious = false ;
5765 /**
58- * Tracks whether the component has completed its initial render .
59- * Animations are disabled until after the first render completes .
60- * This prevents the accordion from animating when it starts
61- * expanded or collapsed on initial load.
66+ * Tracks whether a user-initiated interaction has occurred .
67+ * Animations are disabled until the first interaction happens .
68+ * This prevents the accordion from animating when it's programmatically
69+ * set to an expanded or collapsed state on initial load.
6270 */
63- @State ( ) hasRendered = false ;
71+ @State ( ) hasInteracted = false ;
72+
73+ /**
74+ * Tracks if this accordion has ever been expanded.
75+ * Used to prevent the first expansion from animating.
76+ */
77+ private hasEverBeenExpanded = false ;
6478
6579 /**
6680 * The value of the accordion. Defaults to an autogenerated
@@ -130,17 +144,6 @@ export class Accordion implements ComponentInterface {
130144 } ) ;
131145 }
132146
133- componentDidRender ( ) {
134- /**
135- * After the first render completes, mark that we've rendered.
136- * Setting this state property triggers a re-render, at which point
137- * animations will be enabled. This ensures animations are disabled
138- * only for the initial render, avoiding unwanted animations on load.
139- */
140- if ( ! this . hasRendered ) {
141- this . hasRendered = true ;
142- }
143- }
144147
145148 private setItemDefaults = ( ) => {
146149 const ionItem = this . getSlottedHeaderIonItem ( ) ;
@@ -239,6 +242,11 @@ export class Accordion implements ComponentInterface {
239242 const { contentEl, contentElWrapper } = this ;
240243 if ( initialUpdate || contentEl === undefined || contentElWrapper === undefined ) {
241244 this . state = AccordionState . Expanded ;
245+ /**
246+ * Mark that this accordion has been expanded at least once.
247+ * Do this even on initial expansion so future interactions animate.
248+ */
249+ this . hasEverBeenExpanded = true ;
242250 return ;
243251 }
244252
@@ -250,6 +258,12 @@ export class Accordion implements ComponentInterface {
250258 cancelAnimationFrame ( this . currentRaf ) ;
251259 }
252260
261+ /**
262+ * Mark that this accordion has been expanded at least once.
263+ * This allows subsequent expansions to animate.
264+ */
265+ this . hasEverBeenExpanded = true ;
266+
253267 if ( this . shouldAnimate ( ) ) {
254268 raf ( ( ) => {
255269 this . state = AccordionState . Expanding ;
@@ -315,11 +329,15 @@ export class Accordion implements ComponentInterface {
315329 */
316330 private shouldAnimate = ( ) => {
317331 /**
318- * Don't animate until after the first render cycle completes .
332+ * Don't animate until after the first user interaction .
319333 * This prevents animations on initial load when accordions
320- * start in an expanded or collapsed state.
334+ * start in an expanded or collapsed state programmatically.
335+ *
336+ * Additionally, don't animate the very first expansion even if
337+ * hasInteracted is true. This handles edge cases like React StrictMode
338+ * where effects run twice and might incorrectly mark as interacted.
321339 */
322- if ( ! this . hasRendered ) {
340+ if ( ! this . hasInteracted || ! this . hasEverBeenExpanded ) {
323341 return false ;
324342 }
325343
@@ -418,6 +436,12 @@ export class Accordion implements ComponentInterface {
418436
419437 if ( disabled || readonly ) return ;
420438
439+ /**
440+ * Mark that the user has interacted with the accordion.
441+ * This enables animations for all future state changes.
442+ */
443+ this . hasInteracted = true ;
444+
421445 if ( accordionGroupEl ) {
422446 /**
423447 * Because the accordion group may or may
0 commit comments