Skip to main content

Overview

TableView is a native view component (UIView/NSView) that renders markdown tables with features including header rows, striped styling, grid borders, and interactive cell content. It uses GridView for visual rendering and TableViewCellManager for cell management.

Class Definition

final class TableView: UIView

Type Aliases

typealias Rows = [NSAttributedString]
Represents a single row in the table as an array of attributed strings.

Properties

contents
[Rows]
default:"[]"
A 2D array representing table rows and columns. Each element is an NSAttributedString with rich text formatting.
private(set) var contents: [Rows]
This property is read-only. Use setContents(_:) to update table data.
Closure called when a link in a table cell is tapped.
var linkHandler: ((LinkPayload, NSRange, CGPoint) -> Void)?
Parameters:
  • LinkPayload: Either .url(URL) or .string(String)
  • NSRange: The range of the link in the cell text
  • CGPoint: The tap location in MarkdownView coordinates
numberOfRows
Int
Returns the total number of rows in the table.
private var numberOfRows: Int { contents.count }
numberOfColumns
Int
Returns the number of columns (based on the first row).
private var numberOfColumns: Int { contents.first?.count ?? 0 }
intrinsicContentHeight
CGFloat
The calculated height of the table content.
var intrinsicContentHeight: CGFloat

Methods

setContents(_:)
func
Sets the table contents. Automatically processes <br> tags to newlines.
func setContents(_ contents: [Rows])
Parameters:
  • contents: 2D array of attributed strings representing table cells
setTheme(_:)
func
Updates the table’s visual theme.
func setTheme(_ theme: MarkdownTheme)
Parameters:
  • theme: The markdown theme to apply

Layout Configuration

Internal constants control the table layout:
private let tableViewPadding: CGFloat = 2
private let cellPadding: CGFloat = 10
private let maximumCellWidth: CGFloat = 200

GridView

Overview

GridView renders the visual grid structure including borders, header background, and alternating row stripes.
final class GridView: UIView // or NSView

Properties

padding
CGFloat
default:"2"
Padding around the grid.
var padding: CGFloat

Methods

update(widths:heights:)
func
Updates the grid dimensions with column widths and row heights.
func update(widths: [CGFloat], heights: [CGFloat])
Parameters:
  • widths: Array of column widths
  • heights: Array of row heights
setTheme(_:)
func
Applies theme colors to the grid (borders, backgrounds).
func setTheme(_ theme: MarkdownTheme)
setHeaderRow(_:)
func
Enables or disables header row styling.
func setHeaderRow(_ hasHeader: Bool)

Visual Layers

The grid view uses multiple Core Animation layers:
  • backgroundLayer: Base cell background
  • stripeLayer: Alternating row backgrounds
  • headerBackgroundLayer: First row background
  • shapeLayer: Border lines

TableViewCellManager

Overview

TableViewCellManager manages the creation, reuse, and layout of individual table cells.
final class TableViewCellManager

Properties

cells
[LTXLabel]
Array of cell views.
private(set) var cells: [LTXLabel]
cellSizes
[CGSize]
Array of calculated cell sizes.
private(set) var cellSizes: [CGSize]
widths
[CGFloat]
Array of column widths.
private(set) var widths: [CGFloat]
heights
[CGFloat]
Array of row heights.
private(set) var heights: [CGFloat]

Methods

configureCells(for:in:cellPadding:maximumCellWidth:)
func
Configures cells for the given content. Performs diff-based updates for performance.
func configureCells(
    for contents: [[NSAttributedString]],
    in containerView: PlatformView,
    cellPadding: CGFloat,
    maximumCellWidth: CGFloat
)
Parameters:
  • contents: 2D array of cell contents
  • containerView: Parent view to add cells to
  • cellPadding: Internal cell padding
  • maximumCellWidth: Maximum width constraint for cells
setTheme(_:)
func
Updates the theme for all cells.
func setTheme(_ theme: MarkdownTheme)
setDelegate(_:)
func
Sets the delegate for all cells (for link handling).
func setDelegate(_ delegate: LTXLabelDelegate?)

Theme Configuration

Tables use the MarkdownTheme.Table configuration:
public struct Table: Equatable {
    public var cornerRadius: CGFloat = 8
    public var borderWidth: CGFloat = 1
    public var borderColor: PlatformColor = .separator
    public var headerBackgroundColor: PlatformColor = .systemGray6 // UIKit
    public var cellBackgroundColor: PlatformColor = .clear
    public var stripeCellBackgroundColor: PlatformColor = .systemGray.withAlphaComponent(0.03)
}

Example Usage

let tableView = TableView()

// Prepare table data
let headers: [NSAttributedString] = [
    NSAttributedString(string: "Name"),
    NSAttributedString(string: "Age"),
    NSAttributedString(string: "City")
]

let row1: [NSAttributedString] = [
    NSAttributedString(string: "Alice"),
    NSAttributedString(string: "30"),
    NSAttributedString(string: "New York")
]

let row2: [NSAttributedString] = [
    NSAttributedString(string: "Bob"),
    NSAttributedString(string: "25"),
    NSAttributedString(string: "San Francisco")
]

tableView.setContents([headers, row1, row2])
tableView.setTheme(.default)

// Handle link taps
tableView.linkHandler = { payload, range, location in
    switch payload {
    case .url(let url):
        print("Link tapped: \(url)")
    case .string(let str):
        print("Link string: \(str)")
    }
}

Features

Header Row Styling

The first row is automatically styled as a header with:
  • Bold text
  • Different background color
  • Rounded top corners

Alternating Row Colors

Data rows (excluding header) have alternating background colors for better readability.

Content Processing

<br> tags in cell content are automatically converted to newline characters.

Performance Optimization

The table manager uses diff-based updates:
  • Only changed cells are reconfigured
  • Cell sizes are cached when layout constraints remain the same
  • Content fingerprinting prevents unnecessary updates

Accessibility

  • accessibilityLabel: “Table, rows, columns”
  • Individual cells are selectable and accessible
  • Proper VoiceOver navigation support

Build docs developers (and LLMs) love