Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically grow SwiftUI MacOS TableColumn to fix the text

Tags:

macos

swiftui

I have a table as follows:

var body: some View {
    Table(logs, selection: $selectedLine, sortOrder: $sortOrder) {
        TableColumn("timestamp", value: \.timestamp) {
            Text("\($0.timestamp.formatted(date: .abbreviated, time: .standard))")
        }
        TableColumn("device", value: \.level)
        TableColumn("message", value: \.message)
    }
    .onChange(of: sortOrder) {
        logs.sort(using: $0)
    }
}

Right now the table defaults to splitting each of the columns equally, but I would like it to set the column to fix the size of the data within.

timestamp and device are tiny compared to message, which often needs to scroll scroll to view it all.

How can I make it so that timestamp and device will shrink, and message will grow even if it means scroll would be required? Is it even possible?

like image 728
rj93 Avatar asked Oct 23 '25 15:10

rj93


1 Answers

Use .width() on the Table columns:

        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
            }
            .width(100)
            TableColumn("device", value: \.level)
                .width(50)
            TableColumn("message", value: \.message)
        }

and if you want to size according to content you can use GeometryReader like this:

    @State private var colWidth: CGFloat = 100
    
    var body: some View {
        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth = geo.size.width }})
            }
            .width(min: colWidth, max: colWidth)

Edit: set max, but still be able to shrink

    @State private var colWidth1: CGFloat?
    @State private var colWidth2: CGFloat?

    var body: some View {
        Table(logs) {
            TableColumn("timestamp") { log in
                Text(log.timestamp.formatted(date: .omitted , time: .standard))
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth1 = max(colWidth1 ?? 0, geo.size.width) }})
            }
            .width(ideal: colWidth1, max: colWidth1)
            
            TableColumn("device") { log in
                Text(log.level)
                    .overlay( GeometryReader { geo in Color.clear.onAppear { colWidth2 = max(colWidth2 ?? 0, geo.size.width) }})
            }
            .width(ideal: colWidth2, max: colWidth2)

            TableColumn("message", value: \.message)
                .width(ideal: 200, max: .infinity)
        }
    }
like image 60
ChrisR Avatar answered Oct 26 '25 06:10

ChrisR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!