Skip to content
🚀 Grid layouts, shapes, charts, sliders and more...
Swift
Branch: master
Clone or download
Latest commit c875b98 Dec 13, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Create swift.yml Dec 13, 2019
Demo Sliders (#53) Dec 13, 2019
Resources Sliders (#53) Dec 13, 2019
Sources/SwiftUIExtensions tests (#59) Dec 13, 2019
Tests/SwiftUIExtensionsTests/SlidersTests tests (#59) Dec 13, 2019
.gitignore gitignore Jul 31, 2019
LICENSE bundle identifiers (#25) Oct 15, 2019
Package.swift Sliders (#53) Dec 13, 2019
README.md Update README.md Dec 13, 2019

README.md

SwiftUI Extensions

Collection of useful SwiftUI extensions and elements

Build Status

  • Grid based layouts
  • Sliders (horizontal, vertical, point)
  • Custom shapes
  • Data charts
  • Supports all apple platforms
  • SwiftUI code patterns (Styles, EnvironmentValues, ViewBuilder)
  • Active development for production apps

Open /Demo/SwiftUIExtensionsDemo.xcodeproj for more examples for iOS, macOS, watchOS and tvOS

Layouts

Modular Grid

Grid(colors) {
    Rectangle()
        .foregroundColor($0)
}
.gridStyle(
    ModularGridStyle(columns: .min(100), rows: .min(100))
)

Staggered Grid

Grid(1...69, id: \.self) { index in
    Image("\(index)")
        .resizable()
        .scaledToFit()
}
.gridStyle(
    StaggeredGridStyle(tracks: 8, axis: .horizontal, spacing: 4)
)

Tracks

Tracks setting allows you to customize grid behaviour to your specific use-case. Both Modular and Staggered grid use tracks value to calculate layout. In Modular layout both columns and rows are tracks.

public enum Tracks: Hashable {
    case count(Int)
    case fixed(CGFloat)
    case min(CGFloat)
}
Count

Grid is split into equal fractions of size provided by a parent view.

ModularGridStyle(columns: 3, rows: 3)
StaggeredGridStyle(tracks: 8)
Fixed

Item size is fixed to a specific width or height.

ModularGridStyle(columns: .fixed(100), rows: .fixed(100))
StaggeredGridStyle(tracks: .fixed(100))
Min

Autolayout respecting a min item width or height.

ModularGridStyle(columns: .min(100), rows: .min(100))
StaggeredGridStyle(tracks: .min(100))

Preferences

Get item size and position with preferences

struct CardsView: View {
    @State var selection: Int = 0
    
    var body: some View {
        Grid(0..<100) { number in
            Card(title: "\(number)")
                .onTapGesture {
                    self.selection = number
                }
        }
        .padding()
        .overlayPreferenceValue(GridItemBoundsPreferencesKey.self) { preferences in
            RoundedRectangle(cornerRadius: 16)
                .strokeBorder(lineWidth: 4)
                .foregroundColor(.white)
                .frame(
                    width: preferences[self.selection].width,
                    height: preferences[self.selection].height
                )
                .position(
                    x: preferences[self.selection].midX,
                    y: preferences[self.selection].midY
                )
                .animation(.linear)
        }
    }
}

Sliders

Highly customizable sliders and tracks

Simple gradient value slider style

HSlider(value: $value, track:
    LinearGradient(gradient: Gradient(colors: [.red, .orange, .yellow, .green, .blue, .purple, .pink]), startPoint: .leading, endPoint: .trailing)
        .frame(height: 8)
        .cornerRadius(4)
)

Multivalue track

ZStack {
    HTrack(value: value1, view: Capsule().foregroundColor(.red)).opacity(0.5)
    HTrack(value: value2, view: Capsule().foregroundColor(.blue)).opacity(0.5)
    HTrack(value: value3, view: Capsule().foregroundColor(.green)).opacity(0.5)
}
.animation(.spring())
.frame(height: 8)
.background(Color.secondary.opacity(0.25))

Complex range slider style

HRangeSlider(range: $range, in: 0.0...1.0, step: 0.01,
    track:
        HRangeTrack(
            range: range,
            view: LinearGradient(gradient: Gradient(colors: [.yellow, .orange, .red]), startPoint: .leading, endPoint: .trailing),
            mask: Rectangle(),
            configuration: .init(
                offsets: 32
            )
        )
        .background(Color.secondary.opacity(0.25))
        .cornerRadius(16)
        .padding(.vertical, 8)
        .animation(.easeInOut(duration: 0.5)),
    lowerThumb: 
        Capsule()
            .foregroundColor(.white),
    upperThumb:
        Capsule()
            .foregroundColor(.white),
    configuration: .init(
        thumbSize: CGSize(width: 32, height: 64),
        thumbInteractiveSize: CGSize(width: 44, height: 64)
    ),
    onEditingChanged: { print($0) }
)
.frame(height: 64)

Complex point slider style

XYSlider(x: $x, y: $y,
    track:
        RoundedRectangle(cornerRadius: 24)
            .foregroundColor(
                Color(hue: 0.67, saturation: y, brightness: 1.0)
            ),
    thumb:
        ZStack {
            Capsule().frame(width: 12).foregroundColor(.white)
            Capsule().frame(height: 12).foregroundColor(.white)
        }
        .compositingGroup()
        .rotationEffect(Angle(radians: x * 10))
        .shadow(radius: 3),
    configuration: .init(
        options: .interactiveTrack,
        thumbSize: CGSize(width: 48, height: 48)
    )
)
.frame(height: 256)
.shadow(radius: 3)
.padding()

Data Visualization

Build custom charts with SwiftUI

Line Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1])
    .chartStyle(
        LineChartStyle(.quadCurve, lineColor: .blue, lineWidth: 5)
    )

Area Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1])
    .chartStyle(
        AreaChartStyle(.quadCurve, fill:
            LinearGradient(gradient: .init(colors: [Color.blue.opacity(0.2), Color.blue.opacity(0.05)]), startPoint: .top, endPoint: .bottom)
        )
    )

Stacked Area Chart

Chart(data: matrix)
    .chartStyle(
        StackedAreaChartStyle(.quadCurve, colors: [.yellow, .orange, .red])
    )

Column Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1])
    .chartStyle(
        ColumnChartStyle(column: Capsule().foregroundColor(.green), spacing: 2)
    )

Stacked Column Chart

Chart(data: matrix)
    .chartStyle(
        StackedColumnChartStyle(spacing: 2, colors: [.yellow, .orange, .red])
    )

Shapes

Regular Polygons

Pentagon()
Hexagon()
RegularPolygon(sides: 32)

Lines and Curves

QuadCurve(unitPoints: [
    UnitPoint(x: 0.1, y: 0.1),
    UnitPoint(x: 0.5, y: 0.9),
    UnitPoint(x: 0.9, y: 0.1)
])
.stroke(Color.blue, style: .init(lineWidth: 2, lineCap: .round))
.frame(height: 200)

Patterns

GridPattern(horizontalLines: 20, verticalLines: 40)
    .stroke(Color.white.opacity(0.3), style: .init(lineWidth: 1, lineCap: .round))
    .frame(height: 200)
    .background(Color.blue)
    .padding()

SDKs

  • iOS 13+
  • Mac Catalyst 13.0+
  • macOS 10.15+
  • watchOS 6+
  • Xcode 11.0+

Roadmap

  • Animations
  • 'CSS Grid'-like features for Modular Grid
  • View Modifiers
  • Rounded regular polygons
  • Bar chart style

Code Contibutions

Feel free to contribute via fork/pull request to master branch. If you want to request a feature or report a bug please start a new issue.

Coffee Contibutions

If you find this project useful please consider becoming a sponsor.

You can’t perform that action at this time.