SwiftUI Chip Component

A selectable tag. Filter bars, topic pickers, multi-select.

SwiftUI
Charts
Glass
Haptics

Variants: Default, Removable

Install the free SwiftUI chip

  1. Add SwiftKitUI.swift to your app once. It holds the tokens and motion curves.
  2. Copy SKChip.swift below into your project. It needs nothing else.

Usage

Usage.swift
SKChip("Swift", isSelected: selected.contains("Swift")) { toggle("Swift") }
SKChip("Removable", isSelected: true, onRemove: { })

Full source · 108 lines · MIT

SKChip.swift
//
//  SKChip.swift
//  Swift Kit UI
//
//  Requires: SwiftKitUI.swift
//
//  A selectable tag. Filter bars, topic pickers, multi-select.
//
//  Selection animates on `.snap` and fires a selection haptic, so a row of
//  chips feels like the same control as the toggle and the tab bar rather than
//  a different one that happens to be nearby.
//
//  Usage:
//      SKChip("Swift", isSelected: selected.contains("Swift")) { toggle("Swift") }
//      SKChip("Removable", isSelected: true, onRemove: { })
//

import SwiftUI

public struct SKChip: View {
    private let text: String
    private let systemImage: String?
    private let isSelected: Bool
    private let onTap: (() -> Void)?
    private let onRemove: (() -> Void)?

    public init(
        _ text: String,
        systemImage: String? = nil,
        isSelected: Bool = false,
        onTap: (() -> Void)? = nil,
        onRemove: (() -> Void)? = nil
    ) {
        self.text = text
        self.systemImage = systemImage
        self.isSelected = isSelected
        self.onTap = onTap
        self.onRemove = onRemove
    }

    public var body: some View {
        Button {
            onTap?()
            SK.Haptic.play(.selection)
        } label: {
            HStack(spacing: SK.Space.xs) {
                if let systemImage {
                    Image(systemName: systemImage).font(SK.Icon.symbol(SK.Icon.xs))
                }
                Text(text).font(SK.Type_.caption)
                if onRemove != nil {
                    Image(systemName: "xmark")
                        .font(SK.Icon.symbol(SK.Icon.xs, weight: .bold))
                        .onTapGesture { onRemove?() }
                        .accessibilityLabel("Remove \(text)")
                }
            }
            .foregroundStyle(isSelected ? Color.white : SK.Palette.label)
            .padding(.horizontal, SK.Space.md)
            .padding(.vertical, SK.Space.sm)
            .background {
                Capsule().fill(isSelected ? SK.Palette.accent : SK.Palette.fill)
            }
            .overlay {
                if !isSelected {
                    Capsule().strokeBorder(SK.Palette.separator, lineWidth: SK.Stroke.hairline)
                }
            }
            .contentShape(.capsule)
        }
        .buttonStyle(.skPress(scale: 0.95, haptic: nil))
        .skAnimation(.snap, value: isSelected)
        .accessibilityAddTraits(isSelected ? [.isButton, .isSelected] : .isButton)
    }
}

#Preview("SKChip") {
    @Previewable @State var selected: Set<String> = ["SwiftUI"]
    let tags = ["SwiftUI", "UIKit", "Combine", "SwiftData", "Metal"]

    VStack(spacing: SK.Space.xl) {
        FlowRow(tags: tags, selected: selected) { tag in
            if selected.contains(tag) { selected.remove(tag) } else { selected.insert(tag) }
        }
        HStack(spacing: SK.Space.sm) {
            SKChip("Removable", isSelected: true, onRemove: {})
            SKChip("With icon", systemImage: "star.fill")
        }
    }
    .padding(SK.Space.xl)
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(SK.Palette.surfaceSunken)
}

private struct FlowRow: View {
    let tags: [String]
    let selected: Set<String>
    let onTap: (String) -> Void

    var body: some View {
        HStack(spacing: SK.Space.sm) {
            ForEach(tags.prefix(3), id: \.self) { tag in
                SKChip(tag, isSelected: selected.contains(tag)) { onTap(tag) }
            }
        }
    }
}

Questions

Is this SwiftUI chip free for commercial apps?
Yes. Swift Kit UI is MIT licensed, so you can use it in personal and commercial apps with no payment or sign-up. Keep the licence notice with the code.
What does it depend on?
SKChip.swift depends only on SwiftKitUI.swift, a single foundation file with the design tokens and motion curves. There are no third-party packages.
Which iOS versions does it support?
iOS 17 and later, plus macOS 14.

Related components

Building a whole app? The Swift Kit adds auth, payments and onboarding, ready to ship.