Thank you for your interest in contributing! SwiftUI-Flow provides HFlow and VFlow — flow layouts for SwiftUI that wrap their content across lines, with control over alignment, spacing, distribution, flexibility, and line breaks. Contributions of all kinds are welcome: bug fixes, new layout capabilities, documentation, and performance work.
Prerequisites:
- Xcode 16+ (Swift 6 toolchain). The full test suite depends on swift-snapshot-testing, which pulls in WebKit — it must be built with the Xcode-bundled toolchain, not a standalone swift.org toolchain.
git clone https://github.com/tevelee/SwiftUI-Flow.git && cd SwiftUI-Flow
Build:
swift buildAll optional dependencies are opt-in. Snapshot, property-based, and documentation libraries are only resolved when you opt in via environment variables. This keeps plain swift build and dependency resolution lean for library consumers. The suites that need them are excluded from the test target unless the matching variable is set:
| Variable | Enables |
|---|---|
FLOW_SNAPSHOT_TESTING |
The SnapshotTests/ suites and all inline ASCII-transcript assertions in IntegrationTests/ |
FLOW_PROPERTY_TESTING |
The property-based suite (FlowInvariantRequirementTests) |
FLOW_DOCC |
The swift-docc-plugin for documentation generation |
Run the test suite (required before submitting a PR) — opt into both so the full suite runs:
FLOW_SNAPSHOT_TESTING=1 FLOW_PROPERTY_TESTING=1 swift testPlain swift test (no variables) still works, but compiles and runs only the dependency-free subset — use the full command above before submitting. SwiftPM caches manifest evaluation, so after toggling a variable on a previously built checkout you may need swift package reset (or a clean checkout) for it to take effect.
The image snapshot suites are part of the contract for this UI library. If a render snapshot fails, either fix the regression or intentionally re-record the affected baseline and review the image diff carefully.
Swift 5.9 (Package.swift) |
Swift 6.0 (Package@swift-6.swift) |
|
|---|---|---|
| Platforms | iOS 16, macOS 13, tvOS 16, watchOS 9 | + visionOS 1 |
| Language mode | 5 | 6 (strict concurrency) |
CI builds the library for every platform on each push, runs the deterministic suite on macOS across Swift 5.9 / 6.0 / latest, and runs it on the iOS Simulator. Keep both manifests in sync when changing dependencies or settings.
- Fork the repository and branch from
main:git checkout -b feature/my-change
- Write a test first (TDD). New behaviour should have a failing test before any implementation.
- Implement the minimal code to make it pass.
- Verify locally:
FLOW_SNAPSHOT_TESTING=1 FLOW_PROPERTY_TESTING=1 swift test swift-format lint --strict --recursive Sources Tests swiftlint lint --strict - Open a PR against
main. Fill in the PR template and add a label so the automated release notes categorise it correctly.
Tests live in Tests/FlowTests/, organized by role:
UnitTests/— pure layout math such as line breaking and sizing. These tests should assert exact output structures, not broad properties.IntegrationTests/— end-to-endLayoutbehavior usingTestSubviewfixtures. Requirement tests should assert exact reported sizes and placements.IntegrationTests/PublicAPI/— public API surface tests: initializer mapping, rendering, layout direction.PropertyTests/— property-based invariant tests (requiresFLOW_PROPERTY_TESTING=1).SnapshotTests/Inline/— ASCII snapshots of computed frames. Use these for broad visual coverage of layout structure (requiresFLOW_SNAPSHOT_TESTING=1).SnapshotTests/Image/— PNG snapshots of rendered SwiftUI views. Use these for render verification and documentation examples (requiresFLOW_SNAPSHOT_TESTING=1).
The library uses Swift Testing (@Suite, @Test, #expect) and suite tags:
.requirements— behavior-defining unit and integration tests..snapshot— text or image snapshot tests..imageSnapshot— pixel-rendered snapshot tests..readmeSnapshot— snapshots used by README examples..lazyLayout— lazy flow layout coverage..regression— tests that lock down a specific past bug.
Prefer exact assertions for requirements. Snapshot tests are still required for render verification, but they should not be the only place a behavioral rule is described.
Running specific tests: Prefix with the opt-in variables (see Getting started) whenever the filter targets a snapshot, ASCII-transcript, or property-based suite — otherwise those tests are excluded and the filter matches nothing.
swift test --filter FlowAlignmentRequirementTests
swift test --filter LineBreakingTests
FLOW_SNAPSHOT_TESTING=1 swift test --filter FlowDistributionRequirementTests
FLOW_SNAPSHOT_TESTING=1 swift test --filter FlowLineBreakRequirementTests
FLOW_SNAPSHOT_TESTING=1 swift test --filter ReadmeSnapshotTests
FLOW_PROPERTY_TESTING=1 swift test --filter FlowInvariantRequirementTestsRe-recording snapshots is allowed when the expected rendering or layout output intentionally changes:
SNAPSHOT_TESTING_RECORD=all FLOW_SNAPSHOT_TESTING=1 swift test --filter ImageSnapshots
SNAPSHOT_TESTING_RECORD=all FLOW_SNAPSHOT_TESTING=1 swift test --filter ReadmeSnapshotTestsReview every changed file under Tests/FlowTests/SnapshotTests/Image/__Snapshots__/ before committing. A PR that re-records snapshots should also include exact requirement tests for the behavior that changed, unless the change is purely visual.
- 4-space indentation.
- All public declarations require
///doc comments. - Prefer early exits (
guard) and small, composable helpers — match the surrounding code.
Linting is enforced by swift-format and SwiftLint. Install both with Homebrew:
brew install swift-format swiftlintCheck for issues:
swift-format lint --strict --recursive Sources Tests
swiftlint lint --strictAuto-fix most issues in one pass:
swift-format format --recursive --in-place Sources Tests
swiftlint --fixCI runs both linters on every PR and will fail on any violation. A bot also applies auto-fixes as a commit when it can resolve issues without ambiguity.
Every public declaration needs a /// doc comment. User-facing guides live in Sources/Flow/Flow.docc/; when you add or change a feature (alignment, distribution, flexibility, spacing, line breaks), update the matching article. DocC is built on every PR and published to GitHub Pages from main.
- Bugs: use the Bug report template — a minimal
HFlow/VFlowreproduction and a screenshot help most. - Features: use the Feature request template.
- Questions: use GitHub Discussions rather than issues.
- Security vulnerabilities: see SECURITY.md — do not open a public issue.