Swift Charts: Jumpy, unpredictable chart when using .chartXSelection(value:)

I'm seeing an issue related to Swift Charts when I use a @Binding to dynamically change the selection of the chart. Below is a quick example View that demonstrates the issue. This example is a chart that shows a count of events that happened in a day, and the user can touch a bar to reveal the count as an annotation above the bar.

The expected behavior is that as the user can touch a bar and see the annotation appear above the bar. In some cases, the chart scale may need to change to allow space for the annotation, which is expected.

However, unexpectedly, the whole chart's width changes unexpectedly by a few points, sometimes, when touching a bar. It would be fine if this was consistent with times when the updated scale needs to include an additional digit, however even when that's not the case the whole chart's width seems to change by a few points, and then inconsistently sometimes change back (or not) with subsequent touches.

This behavior is not present in all cases, so you may need to run the preview a few times to get data where it's reproducible.

Is there something I can do here to fix the issue? Or is it just a bug in Swift Charts?

import SwiftUI
import Charts

struct ContentView: View {
    var body: some View {
        VStack {
            WeekHistogram()
                .frame(maxHeight: 180)
        }
            .padding()
    }
}

#Preview {
    ContentView()
}

// A simple struct to contain the data for the chart.
public struct EventCount: Identifiable
{
    /// Start date of a day
    let date: Date

    /// Counts of events on that day
    public let count: Int

    /// The ID: date stored as a string
    public var id: String { date.ISO8601Format() }
    // Storing a Date as the ID changes how Swift Charts lays them out along the axis to an undesired way.

    init(day: Date, count: Int)
    {
        self.date = day
        self.count = count
    }
}


struct WeekHistogram: View
{
    // Dummy data that gets refreshed every time you run the preview
    private let countByDay: [EventCount] = EventCount.dummyData

    // Used to extract the date back from the EventCount.id
    private let formatter = ISO8601DateFormatter()

    // The currently selected bar (while user is touching the bar)
    @State private var selection: String? = nil

    var body: some View
    {
        Chart(countByDay)
        { element in

            // X-axis: Date of the event count
            // Y-axis: Count of events on that date
            BarMark(
                x: .value("Day", element.id),
                y: .value("Count", element.count)
            )
                .annotation(position: .top)
            {
                // Only show the annotation when this bar is being touched
                if element.id == selection
                {
                    Text("\(element.count)")
                        .font(.headline)
                }
            }
        }
            .chartXSelection(value: $selection)
            .chartXAxis
        {
            // Custom view to show the weekday and day of the month
            // Removing this custom .chartXAxis does not fix the issue
            AxisMarks { value in

                // Convert the text of the date back to an actual date
                let date = formatter.date(from: value.as(String.self)!)!

                AxisValueLabel
                {
                    VStack
                    {
                        Text(date.formatted(.dateTime.weekday()))

                        Text(date.formatted(.dateTime.day()))
                            .font(.headline)
                    }
                }
            }
        }

    }
}

// Generate dummy data
extension EventCount
{
    static let dummyData: [EventCount] =
    {
        let startOfToday = Calendar.current.startOfDay(for: .now)

        let secondsPerDay = 24 * 60 * 60

        // Generate [EventCount] with a random count from 3–8 for toady and each of the past 7 days.
        var counts = [EventCount]()
        for i in 0...7
        {
            let day = startOfToday
                .addingTimeInterval(TimeInterval(-i * secondsPerDay))
            let count = Int.random(in: 3...8)

            let eventCount = EventCount(day: day,
                                        count: count)

            counts.append(eventCount)
        }

        // Reverse the direction to order it for the chart
        counts.reverse()

        return counts
    }()
}
Swift Charts: Jumpy, unpredictable chart when using .chartXSelection(value:)
 
 
Q