2 min read

Introducing Expandable: A Little SwiftUI View for Expandable Text

Open sourcing a tiny SwiftUI view for expandable text.

The most recent update to Foodnoms introduced a notes field for recipes. When logging a recipe in the app, I wanted to make the recipe's notes accessible and discoverable. However, notes can be arbitrarily long, and I didn't want them to push down important content below the fold.

I immediately thought of the App Store UI for app descriptions, where the description is truncated to three lines and can be expanded by tapping a "more" button.

Screenshot of the App Store page for Foodnoms, scrolled down to the truncated app description

I searched the web for solutions and asked ChatGPT. There are some decent ones available, but they didn't seem to be leveraging all of the latest APIs that SwiftUI has to offer to achieve a more robust and elegant solution.

Editor's note: After already doing most of the work to open source this code and write this blog post, I discovered ExpandableText, which seems like a solid implementation that achieves the same goal. If I had discovered this package a few weeks ago, I likely wouldn't have made my own! 😅 You may want to use ExpandableText instead, as it's arguably more "battle tested" and seems to offer more customizability.

I don't always jump to open sourcing my code, due to a variety of reasons. However, I felt that this SwiftUI view was a good candidate because it's small, elegant, opinionated, and potentially useful to others. It also demonstrates some of my favorite strategies for building complex views in SwiftUI.

You can view, fork, or download the source on the GitHub repository. MIT licensed. You can also add the repository as a Swift package dependency to your Xcode project.

The package has one goal: to provide a SwiftUI view that recreates this specific component in the App Store app. Nothing more.

Notable Features

  • Cross platform: iOS 16, watchOS 9, macOS 13
  • No UIKit dependency
  • No external dependencies
  • Ergonomic, SwiftUI-y API
  • Customizable expand button
  • VoiceOver and Dynamic Type support
  • Right-to-left (RTL) layout support

Example Usage

import Expandable
import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView {
            Expandable {
                Text("Here’s to the crazy ones. The misfits. The rebels. The troublemakers. The round pegs in the square holes. The ones who see things differently. They’re not fond of rules. And they have no respect for the status quo.")
            } buttonLabel: {
                Text("more")
            }
            .lineLimit(3)
        }
    }
}

Screenshots

Expandable demo on iOS
Expandable demo on macOS
Expandable demo on watchOS