LavaUI docs GitHub

struct List

Swift

struct List<Data, ID, Row> where Data : RandomAccessCollection, ID : Hashable, Row : View, Data.Index == Int

A scrolling column of rows, one of which is selected.

What every sidebar and result list in the apps was building by hand: rows in a ScrollView, a fill on the selected row and a hover on the rest, a click that selects and a double click that opens, and the arrows, Home, End and Page Up/Down moving the selection with the view following it. The row's contents are the caller's; the row's chrome — fill, rounding, insets, the click target — is the list's, so every list on the desktop selects the same way.

@State private var section: Section? = .appearance
List(Section.allCases, id: \.self, selection: $section,
     onActivate: { open($0) }) { section, selected in
    Text(section.title, color: selected ? .primary : .secondary)
}

The keyboard is the list's once it has been pressed (.focusable), and stays until something else takes it. Keys it does not use — anything but the arrows, Home, End, Page Up/Down and Enter — fall through to the window's shortcuts.

Two ways to lay rows out, chosen by rowHeight. Without one, every row is mounted and takes its natural height, which is what a sidebar of a dozen rows whose subtitles wrap wants. With one, rows are that height and only those on screen are mounted (LazyVStack), which is what a list of ten thousand files wants — and what turns a selection a thousand rows away into one scroll.

Results under a search field — a launcher, a file search — want the other behaviour throughout, and ListBehavior.results is that: the pointer selects what it is over, one click opens, and the list never takes the keyboard, because the field above it keeps it and moves the selection itself.

Single selection only; a file list's Ctrl and Shift ranges are still the explorer's own.

Sources/LavaUI/List.swift:41

Constructors

init(_ data: Data, id: KeyPath<Data.Element, ID>, selection: Binding<ID?>, rowHeight: Float? = nil, spacing: Float = 2, padding: Float = 0, rowInsets: EdgeInsets = EdgeInsets(top: 8, leading: 10, bottom: 8, trailing: 10), behavior: ListBehavior = .standard, selectionFill: Color? = nil, cornerRadius: Float? = nil, indicatorInset: Float = 0, onActivate: ((Data.Element) -> Void)? = nil, @ViewBuilder row: @escaping (Data.Element, Bool) -> Row)

Creates a list. Every parameter matches the property of the same name.

Sources/LavaUI/List.swift:81

init(_ data: Data, id: KeyPath<Data.Element, ID>, selection: Binding<ID>, rowHeight: Float? = nil, spacing: Float = 2, padding: Float = 0, rowInsets: EdgeInsets = EdgeInsets(top: 8, leading: 10, bottom: 8, trailing: 10), behavior: ListBehavior = .standard, selectionFill: Color? = nil, cornerRadius: Float? = nil, indicatorInset: Float = 0, onActivate: ((Data.Element) -> Void)? = nil, @ViewBuilder row: @escaping (Data.Element, Bool) -> Row)

A list whose selection is never empty — a sidebar that always shows some page. Moving off a row writes the new one; nothing writes nil.

Sources/LavaUI/List.swift:113

init(_ data: Data, selection: Binding<ID?>, rowHeight: Float? = nil, spacing: Float = 2, padding: Float = 0, rowInsets: EdgeInsets = EdgeInsets(top: 8, leading: 10, bottom: 8, trailing: 10), behavior: ListBehavior = .standard, selectionFill: Color? = nil, cornerRadius: Float? = nil, indicatorInset: Float = 0, onActivate: ((Data.Element) -> Void)? = nil, @ViewBuilder row: @escaping (Data.Element, Bool) -> Row)

A list of Identifiable elements, selected by id.

Sources/LavaUI/List.swift:260

Properties

var behavior: ListBehavior

How the pointer and the keyboard work it. See ListBehavior.

Sources/LavaUI/List.swift:61

var body: some View { get }

Not documented.

Sources/LavaUI/List.swift:141

var cornerRadius: Float?

Rows' corner radius, or nil for the theme's.

Sources/LavaUI/List.swift:65

var data: Data

The elements, one row each, in order.

Sources/LavaUI/List.swift:44

var id: KeyPath<Data.Element, ID>

What identifies an element. The selection holds one of these, so the selected row stays selected when the data is reordered or filtered.

Sources/LavaUI/List.swift:47

var indicatorInset: Float

How far the scroll indicator sits in from the right edge.

Sources/LavaUI/List.swift:67

var onActivate: ((Data.Element) -> Void)?

Double click, or Enter, on a row. Nil makes both do nothing beyond selecting.

Sources/LavaUI/List.swift:70

var padding: Float

Space around the rows, inside the scrolling area.

Sources/LavaUI/List.swift:57

var row: (Data.Element, Bool) -> Row

Builds one row's contents; the second argument is whether it is the selected row.

Sources/LavaUI/List.swift:73

var rowHeight: Float?

Height of every row, in points — and with it, lazy mounting. Nil lays every row out at its natural height. See the type's notes.

Sources/LavaUI/List.swift:53

var rowInsets: EdgeInsets

Space between a row's edge — its fill — and its contents.

Sources/LavaUI/List.swift:59

@Binding var selection: ID? { get nonmutating set }

The selected element's id, or nil for none. Clicking a row, or moving with the keyboard, writes here.

Sources/LavaUI/List.swift:50

var selectionFill: Color?

The selected row's fill, or nil for the theme's selectionFill.

Sources/LavaUI/List.swift:63

var spacing: Float

Space between rows, in points.

Sources/LavaUI/List.swift:55