swiftswiftuiaccessibilityswiftui-charts

SwiftUI Charts how to avoid automatically groups accessibility elements on the graph


I have a BarMark Chart and I am using .accessibilityLabel and .accessibilityValue to customize the accessibility Text for each bar. With small number of bar on the graph, this logic works fine, but when there are more bar, they automatically groups and mess-up the accessibility Text. I wonder if there is anyway to avoid this automatic grouping

This is my code

    var body: some View {
        let salesData: [(Date, Double)] = [
                (Date().addingTimeInterval(-1 * 24 * 60 * 60), 120),
                (Date().addingTimeInterval(-2 * 24 * 60 * 60), 150),
                (Date().addingTimeInterval(-3 * 24 * 60 * 60), 100),
                (Date().addingTimeInterval(-4 * 24 * 60 * 60), 50),
                (Date().addingTimeInterval(-5 * 24 * 60 * 60), 150),
                (Date().addingTimeInterval(-6 * 24 * 60 * 60), 140),
                (Date().addingTimeInterval(-7 * 24 * 60 * 60), 130),
                (Date().addingTimeInterval(-8 * 24 * 60 * 60), 180),
                (Date().addingTimeInterval(-9 * 24 * 60 * 60), 50),
                (Date().addingTimeInterval(-10 * 24 * 60 * 60), 80),
                (Date().addingTimeInterval(-11 * 24 * 60 * 60), 80),
                (Date().addingTimeInterval(-12 * 24 * 60 * 60), 100),
                (Date().addingTimeInterval(-13 * 24 * 60 * 60), 150),
                (Date().addingTimeInterval(-14 * 24 * 60 * 60), 150),
                (Date().addingTimeInterval(-15 * 24 * 60 * 60), 90),
            ]

                Chart {
                    ForEach(salesData, id: \.0) {  date, sales in
                        BarMark(
                          x: .value("Day", date),
                          y: .value("Amount", sales)
                        ).accessibilityLabel(date.formatted(date: .abbreviated, time: .omitted))
                            .accessibilityValue("Amount: \(sales.formatted(.currency(code: "USD")))")
                      }
                }
                .accessibilityElement(children: .contain)
                .frame(height: 300)
    }

When running accessibility, it groups 2 columns into one element automatically screenshot from accessibility inspector

I am not sure if any setting to avoid this auto grouping, I need the behavior like the activity chart on the Health-app screenshot from health app


Solution

  • The grouping appears to work fine by formatting the x values as strings rather than leaving the x values as dates:

    x: .value("Day", date.formatted(date: .abbreviated , time: .omitted)),
    

    Then a single day can be selected: grouping gif

    Making that one change did cause other changes that you may want to adjust. Because the x values are strings, the displayed order is the array order rather than date order.

    Label fix: Every day's date is now displayed along the x axis. The following is a fix for those compressed labels, to be added to Chart:

    .chartXAxis(content: {
        AxisMarks { value in
            AxisValueLabel (orientation: .vertical) {
                if let displayValue = value.as(String.self) {
                    Text(displayValue)
                }
            }
        }
    })
    

    better labels