@@ -40,8 +40,38 @@ const enum AccordionState {
4040export  class  Accordion  implements  ComponentInterface  { 
4141  private  accordionGroupEl ?: HTMLIonAccordionGroupElement  |  null ; 
4242  private  updateListener  =  ( ev : CustomEvent < AccordionGroupChangeEventDetail > )  =>  { 
43-     const  initialUpdate  =  ev . detail ?. initial  ??  false ; 
44-     this . updateState ( initialUpdate ) ; 
43+     /** 
44+      * Determine if this update will cause an actual state change. 
45+      * We only want to mark as "interacted" if the state is changing. 
46+      */ 
47+     const  accordionGroup  =  this . accordionGroupEl ; 
48+     if  ( accordionGroup )  { 
49+       const  value  =  accordionGroup . value ; 
50+       const  accordionValue  =  this . value ; 
51+       const  shouldExpand  =  Array . isArray ( value )  ? value . includes ( accordionValue )  : value  ===  accordionValue ; 
52+       const  isExpanded  =  this . state  ===  AccordionState . Expanded  ||  this . state  ===  AccordionState . Expanding ; 
53+       const  stateWillChange  =  shouldExpand  !==  isExpanded ; 
54+ 
55+       /** 
56+        * Only mark as interacted if: 
57+        * 1. This is not the first update we've received with a defined value 
58+        * 2. The state is actually changing (prevents redundant updates from enabling animations) 
59+        */ 
60+       if  ( this . hasReceivedFirstUpdate  &&  stateWillChange )  { 
61+         this . hasInteracted  =  true ; 
62+       } 
63+ 
64+       /** 
65+        * Only count this as the first update if the group value is defined. 
66+        * This prevents the initial undefined value from the group's componentDidLoad 
67+        * from being treated as the first real update. 
68+        */ 
69+       if  ( value  !==  undefined )  { 
70+         this . hasReceivedFirstUpdate  =  true ; 
71+       } 
72+     } 
73+ 
74+     this . updateState ( ) ; 
4575  } ; 
4676  private  contentEl : HTMLDivElement  |  undefined ; 
4777  private  contentElWrapper : HTMLDivElement  |  undefined ; 
@@ -55,12 +85,24 @@ export class Accordion implements ComponentInterface {
5585  @State ( )  isNext  =  false ; 
5686  @State ( )  isPrevious  =  false ; 
5787  /** 
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. 
88+    * Tracks whether a user-initiated interaction  has occurred . 
89+    * Animations are disabled until the first interaction happens . 
90+    * This prevents the accordion from animating when it's programmatically  
91+    * set to an  expanded or collapsed state  on initial load. 
6292   */ 
63-   @State ( )  hasRendered  =  false ; 
93+   @State ( )  hasInteracted  =  false ; 
94+ 
95+   /** 
96+    * Tracks if this accordion has ever been expanded. 
97+    * Used to prevent the first expansion from animating. 
98+    */ 
99+   private  hasEverBeenExpanded  =  false ; 
100+ 
101+   /** 
102+    * Tracks if this accordion has received its first update from the group. 
103+    * Used to distinguish initial programmatic sets from user interactions. 
104+    */ 
105+   private  hasReceivedFirstUpdate  =  false ; 
64106
65107  /** 
66108   * The value of the accordion. Defaults to an autogenerated 
@@ -99,7 +141,7 @@ export class Accordion implements ComponentInterface {
99141  connectedCallback ( )  { 
100142    const  accordionGroupEl  =  ( this . accordionGroupEl  =  this . el ?. closest ( 'ion-accordion-group' ) ) ; 
101143    if  ( accordionGroupEl )  { 
102-       this . updateState ( true ) ; 
144+       this . updateState ( ) ; 
103145      addEventListener ( accordionGroupEl ,  'ionValueChange' ,  this . updateListener ) ; 
104146    } 
105147  } 
@@ -130,18 +172,6 @@ export class Accordion implements ComponentInterface {
130172    } ) ; 
131173  } 
132174
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-   } 
144- 
145175  private  setItemDefaults  =  ( )  =>  { 
146176    const  ionItem  =  this . getSlottedHeaderIonItem ( ) ; 
147177    if  ( ! ionItem )  { 
@@ -235,10 +265,16 @@ export class Accordion implements ComponentInterface {
235265    ionItem . appendChild ( iconEl ) ; 
236266  } ; 
237267
238-   private  expandAccordion  =  ( initialUpdate   =   false )  =>  { 
268+   private  expandAccordion  =  ( )  =>  { 
239269    const  {  contentEl,  contentElWrapper }  =  this ; 
240-     if  ( initialUpdate  ||  contentEl  ===  undefined  ||  contentElWrapper  ===  undefined )  { 
270+ 
271+     /** 
272+      * If the content elements aren't available yet, just set the state. 
273+      * This happens on initial render before the DOM is ready. 
274+      */ 
275+     if  ( contentEl  ===  undefined  ||  contentElWrapper  ===  undefined )  { 
241276      this . state  =  AccordionState . Expanded ; 
277+       this . hasEverBeenExpanded  =  true ; 
242278      return ; 
243279    } 
244280
@@ -250,6 +286,12 @@ export class Accordion implements ComponentInterface {
250286      cancelAnimationFrame ( this . currentRaf ) ; 
251287    } 
252288
289+     /** 
290+      * Mark that this accordion has been expanded at least once. 
291+      * This allows subsequent expansions to animate. 
292+      */ 
293+     this . hasEverBeenExpanded  =  true ; 
294+ 
253295    if  ( this . shouldAnimate ( ) )  { 
254296      raf ( ( )  =>  { 
255297        this . state  =  AccordionState . Expanding ; 
@@ -270,9 +312,14 @@ export class Accordion implements ComponentInterface {
270312    } 
271313  } ; 
272314
273-   private  collapseAccordion  =  ( initialUpdate   =   false )  =>  { 
315+   private  collapseAccordion  =  ( )  =>  { 
274316    const  {  contentEl }  =  this ; 
275-     if  ( initialUpdate  ||  contentEl  ===  undefined )  { 
317+ 
318+     /** 
319+      * If the content element isn't available yet, just set the state. 
320+      * This happens on initial render before the DOM is ready. 
321+      */ 
322+     if  ( contentEl  ===  undefined )  { 
276323      this . state  =  AccordionState . Collapsed ; 
277324      return ; 
278325    } 
@@ -315,11 +362,15 @@ export class Accordion implements ComponentInterface {
315362   */ 
316363  private  shouldAnimate  =  ( )  =>  { 
317364    /** 
318-      * Don't animate until after the first render cycle completes . 
365+      * Don't animate until after the first user interaction . 
319366     * This prevents animations on initial load when accordions 
320-      * start in an expanded or collapsed state. 
367+      * start in an expanded or collapsed state programmatically. 
368+      * 
369+      * Additionally, don't animate the very first expansion even if 
370+      * hasInteracted is true. This handles edge cases like React StrictMode 
371+      * where effects run twice and might incorrectly mark as interacted. 
321372     */ 
322-     if  ( ! this . hasRendered )  { 
373+     if  ( ! this . hasInteracted   ||   ! this . hasEverBeenExpanded )  { 
323374      return  false ; 
324375    } 
325376
@@ -344,7 +395,7 @@ export class Accordion implements ComponentInterface {
344395    return  true ; 
345396  } ; 
346397
347-   private  updateState  =  async  ( initialUpdate   =   false )  =>  { 
398+   private  updateState  =  async  ( )  =>  { 
348399    const  accordionGroup  =  this . accordionGroupEl ; 
349400    const  accordionValue  =  this . value ; 
350401
@@ -357,10 +408,10 @@ export class Accordion implements ComponentInterface {
357408    const  shouldExpand  =  Array . isArray ( value )  ? value . includes ( accordionValue )  : value  ===  accordionValue ; 
358409
359410    if  ( shouldExpand )  { 
360-       this . expandAccordion ( initialUpdate ) ; 
411+       this . expandAccordion ( ) ; 
361412      this . isNext  =  this . isPrevious  =  false ; 
362413    }  else  { 
363-       this . collapseAccordion ( initialUpdate ) ; 
414+       this . collapseAccordion ( ) ; 
364415
365416      /** 
366417       * When using popout or inset, 
@@ -418,6 +469,12 @@ export class Accordion implements ComponentInterface {
418469
419470    if  ( disabled  ||  readonly )  return ; 
420471
472+     /** 
473+      * Mark that the user has interacted with the accordion. 
474+      * This enables animations for all future state changes. 
475+      */ 
476+     this . hasInteracted  =  true ; 
477+ 
421478    if  ( accordionGroupEl )  { 
422479      /** 
423480       * Because the accordion group may or may 
0 commit comments