Tables

Table lets you present structured, tabular data with support for headers, filtering, striped styles, captions, and fine-grained row and column alignment.


Creating a Table

A table is composed of rows and columns, declared using builders. Each row represents a horizontal slice of data, and each column represents one cell within that row.

At its simplest, a table can be defined entirely inline:

Table {
   TableRow {
       "Ada Lovelace"
       "12 Algorithm Way"
       "London"
       "UK"
   }

   TableRow {
       "Grace Hopper"
       "1 Compiler Lane"
       "Arlington"
       "Virginia"
   }

   TableRow {
       "Alan Turing"
       "43 Enigma Road"
       "Manchester"
       "UK"
   }
}
Ada Lovelace 12 Algorithm Way London UK
Grace Hopper 1 Compiler Lane Arlington Virginia
Alan Turing 43 Enigma Road Manchester UK

Rather than hardcoding rows, you can generate them from a collection using a closure. To clarify what each column represents, provide a header builder:

Table(developers) { developer in
   TableRow {
       developer.name
       developer.email
       developer.team
       developer.location
   }
} header: {
   "Name"
   "Email"
   "Team"
   "Location"
}
Name Email Team Location
Alex Morgan alex.morgan@company.com Platform San Francisco
Jamie Chen jamie.chen@company.com Design Systems New York
Riley Patel riley.patel@company.com Infrastructure London
Taylor Brooks taylor.brooks@company.com Developer Experience Remote

Table Styles

Apply striped rows or columns using tableStyle(_:) to improve readability:

Table(projectMembers) { member in
   TableRow {
       member.name
       member.role
       member.primaryLanguage
       member.yearsExperience
   }
} header: {
   "Name"
   "Role"
   "Language"
   "Experience"
}
.tableStyle(.stripedRows)
.tableRowSeparator(.hidden)
Name Role Language Experience
Alex Morgan Engineer Swift 6
Jamie Chen Designer TypeScript 5
Riley Patel SRE Go 8

Available styles include .stripedRows and .stripedColumns. Both optionally support rounded corners depending on your style configuration.


Filtering

To allow users to filter table rows, provide a filterTitle when creating the table:

Table(locations, filterTitle: "Filter locations") { location in
   TableRow {
       location.city
       location.country
       location.region
   }
}
San Francisco USA North America
London UK Europe
Tokyo Japan Asia
Sydney Australia Oceania

This automatically inserts a search field above the table and filters rows based on visible text content.


Row Separators

You can customize the color of the separator that follows an individual row using tableRowSeparatorTint(_:):

Table {
   TableRow {
       "Server Status"
       "Operational"
   }
   .tableRowSeparatorTint(.accent)

   TableRow {
       "Backup Status"
       "Running"
   }
}
Server Status Operational
Backup Status Running

Alignment and Spanning

Alignment

Rows align to the top-leading edge by default. To change alignment for individual columns, wrap content in TableColumn and apply a modifier:

Table {
   TableRow {
       ForEach(Alignment.allCases) { alignment in
           TableColumn {
               String(describing: alignment)
           }
           .alignment(alignment)
       }
   }
}

Top Leading

Top

Top Trailing

Leading

Center

Trailing

Bottom Leading

Bottom

Bottom Trailing

Column Spanning

Columns can span multiple slots using tableCellColumns(_:):

Table {
   TableRow {
       "Q1"
       "Q2"
       "Q3"
   }
   .multilineTextAlignment(.center)

   TableRow {
       TableColumn {
           "Annual summary covering all quarters."
       }
       .tableCellColumns(3)
       .alignment(.center)
   }
}
.tableStyle(.stripedRows)
Q1 Q2 Q3
Annual summary covering all quarters.

Captions and Accessibility

Tables can include an optional caption, which is displayed visually and announced by screen readers:

Table {
   // rows
}
.caption("Deployment environment overview")