---
title: tevelee/swiftui-flow
framework: Swift Package Catalog
role: article
path: packages/tevelee/swiftui-flow
---

# tevelee/swiftui-flow

Introduces `HFlow` and `VFlow` similar to `HStack` and `VStack`.

## Features

- 📐 **Wrapping layout** — items flow onto new lines (or columns) when they run out of space. - ↔️ **Two axes** — `HFlow` wraps rows, `VFlow` wraps columns. - 🎯 **Per-axis alignment** — align items within a line and lines within the layout. - ↕️ **Independent spacing** — set item spacing and line spacing separately. - ⚖️ **Even distribution** — balance items across lines with the Knuth–Plass algorithm. - ↔️ **Justified lines** — stretch lines to fill the available space. - 🪗 **Flexibility model** — let items grow, stay rigid, or claim a whole line. - 📏 **Line limits** — cap a flow to *N* lines with an optional "+N more" overflow indicator. - ➗ **Separators** — draw dividers between items and/or lines (never at the edges); they take part in sizing and wrapping. - ✂️ **Manual line breaks** — force breaks with `LineBreak()` or `.startInNewLine()`. - 🌍 **RTL support** — adapts to the environment's layout direction. - 🧱 **`Layout` conformance** — `HFlowLayout` / `VFlowLayout` for use anywhere a `Layout` is expected.

## Requirements

- iOS 16+, macOS 13+, tvOS 16+, watchOS 9+, visionOS 1+ - Swift 5.9+

## Installation

Add the package to your `Package.swift`:

```swift .package(url: "https://github.com/tevelee/SwiftUI-Flow", from: "3.1.1") ```

then add `"Flow"` to your target's dependencies. In Xcode, choose **File ▸ Add Package Dependencies…** and enter `https://github.com/tevelee/SwiftUI-Flow`.

## Documentation

Full API reference and guides are hosted on the [Swift Package Index](https://swiftpackageindex.com/tevelee/SwiftUI-Flow/documentation/flow).

## HFlow

```swift import Flow

struct Colors: View {     let colors: [Color] = [         .blue,         .orange,         .green,         .yellow,         .brown,         .mint,         .indigo,         .cyan,         .gray,         .pink     ]

var body: some View {         HFlow {             ForEach(colors, id: \.description) { color in                 RoundedRectangle(cornerRadius: 10)                     .fill(color.gradient)                     .frame(width: .random(in: 40...60), height: 50)             }         }         .frame(maxWidth: 300)     } } ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow.1.png)

## VFlow

```swift VFlow {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: 50, height: .random(in: 40...60))     } } .frame(maxHeight: 300) ```

![VFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/vflow.1.png)

## Alignment

Supports the same alignments as HStack and VStack do.

```swift HFlow(alignment: .top) {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: 50, height: .random(in: 40...60))     } } .frame(maxWidth: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_top.1.png)

Additionally, alignment can be specified on both axes. Ideal for tags.

```swift HFlow(horizontalAlignment: .center, verticalAlignment: .top) {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: .random(in: 30...60), height: 30)     } } .frame(maxWidth: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_tag.1.png)

## Spacing

Customize spacing between rows and items separately.

```swift HFlow(itemSpacing: 4, rowSpacing: 20) {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: 50, height: 50)     } } .frame(maxWidth: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_spacing.1.png)

## Distribute items

Distribute items evenly by minimizing the empty spaces left in each row.  Implements the Knuth-Plass line breaking algorithm.

```swift HFlow(distributeItemsEvenly: true) {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: 65, height: 50)     } } .frame(width: 300, alignment: .leading) .border(.gray) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_distributed_evenly.1.png)

## Justified

```swift HFlow(justified: true) {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: 50, height: 50)     } } .frame(width: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_justified.1.png)

## Flexibility

```swift HFlow { // distributes flexible items proportionally     RoundedRectangle(cornerRadius: 10)         .fill(.red)         .frame(minWidth: 50, maxWidth: .infinity)         .frame(height: 50)         .flexibility(.minimum) // takes as little space as possible, rigid     RoundedRectangle(cornerRadius: 10)         .fill(.green)         .frame(minWidth: 50, maxWidth: .infinity)         .frame(height: 50)         .flexibility(.natural) // expands     RoundedRectangle(cornerRadius: 10)         .fill(.blue)         .frame(minWidth: 50, maxWidth: .infinity)         .frame(height: 50)         .flexibility(.natural) // expands     RoundedRectangle(cornerRadius: 10)         .fill(.yellow)         .frame(minWidth: 50, maxWidth: .infinity)         .frame(height: 50) // takes as much space as possible         .flexibility(.maximum) } .frame(width: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_flexibility.1.png)

Use `.grow(_:)` to distribute leftover space proportionally by weight:

```swift HFlow {     RoundedRectangle(cornerRadius: 8).fill(.orange)         .frame(minWidth: 40, maxWidth: .infinity, minHeight: 44, maxHeight: 44)         .flexibility(.grow(2))  // takes 2/3 of leftover space

RoundedRectangle(cornerRadius: 8).fill(.teal)         .frame(minWidth: 40, maxWidth: .infinity, minHeight: 44, maxHeight: 44)         .flexibility(.grow(1))  // takes 1/3 of leftover space } ```

## Line limits

Cap a flow to a maximum number of lines with `.maxLines(_:)`:

```swift HFlow {     ForEach(tags) { tag in TagView(tag) } } .maxLines(2) ```

Add a trailing overflow indicator using the closure overload (available on `HFlow` and `VFlow`):

```swift HFlow {     ForEach(tags) { tag in TagView(tag) } } .maxLines(2) { hidden in     Text("+\(hidden) more").foregroundStyle(.secondary) } ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_maxlines.1.png)

## Separators

Draw separators between items and/or lines. They only appear *between* elements — never at the edges — and they participate in layout: an item separator's width is accounted for when wrapping, and a line separator contributes its height. A gap that wraps onto a new line shows the line separator instead of the item separator.

```swift HFlow {     ForEach(tags, id: \.self) { Text($0) } } .itemSeparator { Text("•").foregroundStyle(.secondary) } .lineSeparator { Divider() } ```

The two modifiers are independent; use either one on its own or both together. They are available on `HFlow` and `VFlow`.

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_separators.1.png)

## Line breaks

```swift HFlow {     RoundedRectangle(cornerRadius: 10)         .fill(.red)         .frame(width: 50, height: 50)     RoundedRectangle(cornerRadius: 10)         .fill(.green)         .frame(width: 50, height: 50)     RoundedRectangle(cornerRadius: 10)         .fill(.blue)         .frame(width: 50, height: 50)     LineBreak() // <--     RoundedRectangle(cornerRadius: 10)         .fill(.yellow)         .frame(width: 50, height: 50) } .frame(width: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_linebreak.1.png)

```swift HFlow {     RoundedRectangle(cornerRadius: 10)         .fill(.red)         .frame(width: 50, height: 50)     RoundedRectangle(cornerRadius: 10)         .fill(.green)         .frame(width: 50, height: 50)         .startInNewLine() // <--      RoundedRectangle(cornerRadius: 10)         .fill(.blue)         .frame(width: 50, height: 50)     RoundedRectangle(cornerRadius: 10)         .fill(.yellow)         .frame(width: 50, height: 50) } .frame(width: 300) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_newline.1.png)

## RTL

Adapts to left-to-right and right-to-left environments too.

```swift HFlow {     ForEach(colors, id: \.description) { color in         RoundedRectangle(cornerRadius: 10)             .fill(color.gradient)             .frame(width: .random(in: 40...60), height: 50)     } } .frame(maxWidth: 300) .environment(\.layoutDirection, .rightToLeft) ```

![HFlow](Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ReadmeSnapshotTests/hflow_rtl.1.png)

## Package Metadata

Repository: tevelee/swiftui-flow

Default branch: main

README: README.md
