title: SwiftUI - Dynamic List filtering animation flies to right side when data source is empty
body: <p>I have a <code>List</code> that gets data from my <code>people</code> array and displays their names.</p>
  <p>I'm also filtering the list so that it only shows the names that contain the text field's text, which is <code>searchText</code>. Here's my code:</p>
  <pre><code>struct Person: Identifiable {
      let id = UUID() /// required for the List
      
      var name = &quot;&quot;
  }
  
  struct ContentView: View {
      
      @State var searchText = &quot;&quot;
      
      var people = [ /// the data source
          Person(name: &quot;Alex&quot;),
          Person(name: &quot;Ally&quot;),
          Person(name: &quot;Allie&quot;),
          Person(name: &quot;Bob&quot;),
          Person(name: &quot;Tim&quot;),
          Person(name: &quot;Timothy&quot;)
      ]
      
      var body: some View {
          
          VStack {
              TextField(&quot;Search here&quot;, text: $searchText) /// text field
              .padding()
              
              List {
                  ForEach(
                      people.filter { person in /// filter the people
                          searchText.isEmpty || person.name.localizedStandardContains(searchText)
                      }
                  ) { person in
                      Text(person.name)
                  }
              }
              .animation(.default) /// add the animation
          }
      }
  }
  </code></pre>
  <p>Without <code>.animation(.default)</code>, it doesn't animate the changes (as expected).</p>
  <p><kbd><a href="https://i.stack.imgur.com/81gOu.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/81gOu.gif" alt="Filtering without animation" /></a></kbd></p>
  <p><em><strong>With</strong></em> <code>.animation(.default)</code>, it animates!</p>
  <p><kbd><a href="https://i.stack.imgur.com/38HEk.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/38HEk.gif" alt="Filtering with animation" /></a></kbd></p>
  <p>However, the problem happens when none of the people's names contain <code>searchText</code>. When this happens, the <code>people.filter</code> returns an empty array, and the <code>List</code> freaks out. For example, when I type &quot;q&quot;, this happens:</p>
  <p><kbd><a href="https://i.stack.imgur.com/9s6I2.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/9s6I2.gif" alt="List zooms to the right" /></a></kbd></p>
  <p>The entire list flies to the right, and zooms back in from the left when I delete &quot;q&quot;. <strong>How can I prevent this from happening?</strong> I'm looking for a similar animation to the normal filtering animation (sliding up and disappearing, like in the second gif), or just fading it out.</p>
  <h2>Edit: iOS 13</h2>
  <p>I just tested on iOS 13 and if I remove <code>.animation(.default)</code>, it works perfectly!</p>
  <p><img src="https://i.stack.imgur.com/CqsvO.gif" alt="Desired animation on iOS 13" /></p>
  <p>However, if I add <code>.animation(.default)</code> again, I get the same result as in iOS 14.</p>
  <p><a href="https://i.stack.imgur.com/fnt8w.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/fnt8w.gif" alt="Same result as iOS 14" /></a></p>
  <h2>Edit: List with sections + <a href="https://stackoverflow.com/users/8292178/mahan">@mahan</a>'s answer</h2>
  <p>My actual code groups the people, so I <strong>already</strong> use <code>sections</code> in my <code>List</code>.</p>
  <pre><code>struct Group: Identifiable {
      let id = UUID() /// required for the List
      
      var groupName = &quot;&quot;
      var people = [Person]()
  }
  
  struct Person: Identifiable {
      let id = UUID() /// required for the List
      
      var name = &quot;&quot;
  }
  
  struct ContentView: View {
      
      @State var searchText = &quot;&quot;
  
      /// groups of people
      var groups = [
          Group(groupName: &quot;A People&quot;, people: [
              Person(name: &quot;Alex&quot;),
              Person(name: &quot;Ally&quot;),
              Person(name: &quot;Allie&quot;)
          ]),
          Group(groupName: &quot;B People&quot;, people: [
              Person(name: &quot;Bob&quot;)
          ]),
          Group(groupName: &quot;T People&quot;, people: [
              Person(name: &quot;Tim&quot;),
              Person(name: &quot;Timothy&quot;)
          ])
      ]
      
      var body: some View {
          
          VStack {
              TextField(&quot;Search here&quot;, text: $searchText) /// text field
              .padding()
              
              List {
                  
                  ForEach(
  
                      /// Filter the groups for people that match searchText
                      groups.filter { group in
                          searchText.isEmpty || group.people.contains(where: { person in
                              person.name.localizedStandardContains(searchText)
                          })
                      }
                  ) { group in
                      Section(header: Text(group.groupName)) {
                          ForEach(
  
                              /// filter the people in each group
                              group.people.filter { person in
                                  searchText.isEmpty || person.name.localizedStandardContains(searchText)
                              }
                          ) { person in
                              Text(person.name)
                          }
                      }
                  }
                  
              }
              .animation(.default) /// add the animation
          }
      }
  }
  </code></pre>
  <p><kbd><a href="https://i.stack.imgur.com/LjPFv.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/LjPFv.gif" alt="sorting List with sections" /></a></kbd></p>
  <p>If I wrap the <code>ForEach</code> inside the <code>List</code> as @mahan suggested, this happens:</p>
  <p><kbd><img src="https://i.stack.imgur.com/gdntk.jpg" width="300"></kbd></p>
  <p>The <code>List</code> animates perfectly with no weird zoom animation, but the section headers lose their styles and look like normal rows. But I think we're getting close!</p>