TallyCounter

Author License Contant

Tally Counter is a customizable counter element written in SwiftUI with a stretchy animation.

Preview

Installation

You can install Tally Counter using Swift Package Manager. Simply add the following line to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/Wsewlad/tally-counter.git", from: "1.0.1"),
    /// ...
]

Usage

To use Tally Counter in your project, first import the module:

import TallyCounter

Then, add a TallyCounter view to your SwiftUI hierarchy:

struct Example: View {
    @State private var count: Int = 0
    
    var body: some View {
        TallyCounter(
            count: $count
        )
    }
}

Parameters:

  • count is a binding Int to the current count value
  • amount is an optional binding Int value. It represents the amount to increment or decrement the count value when the user taps the “-” and “+” buttons or moves the central button left or right.
  • config is an instance of the Configuration struct which allows customization of the counter’s appearance

amount

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

Configuration

The Configuration struct has the following properties:

  • minValue (default: 0): The minimum value that the counter can have.
  • maxValue (default: 999): The maximum value that the counter can have.
  • controlsContainerWidth (default: 300): The width of the controls container.
  • showAmountLabel (default: true): Whether to show the amount label.
  • controlsColor (default: .white): The color of the controls.
  • labelBackgroundColor (default: .labelBackground): The background color of the amount label.
  • controlsBackgroundColor (default: .controlsBackground): The background color of the controls.
  • controlsOnTapCircleColor (default: .white): The color of the controls’ tap circle.
  • controlsBackgroundOverlayColor (default: .black): The background overlay color of the controls.

showAmountLabel

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

controlsColor

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false,
                    controlsColor: .blue
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

labelBackgroundColor

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
                .font(.largeTitle)
                .foregroundColor(.white)
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false,
                    controlsColor: .blue,
                    labelBackgroundColor: .red
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

controlsBackgroundColor

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
                .font(.largeTitle)
                .foregroundColor(.white)
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false,
                    controlsColor: .blue,
                    labelBackgroundColor: .red,
                    controlsBackgroundColor: .green
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

controlsOnTapCircleColor

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
                .font(.largeTitle)
                .foregroundColor(.white)
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false,
                    controlsColor: .blue,
                    labelBackgroundColor: .red,
                    controlsBackgroundColor: .green,
                    controlsOnTapCircleColor: .yellow
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

controlsBackgroundOverlayColor

Example

struct ContentView: View {
    @State private var count: Int = 0
    @State private var amount: Int = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
                .font(.largeTitle)
                .foregroundColor(.white)
            Text("Amount: \(amount)")
                .font(.largeTitle)
                .foregroundColor(.white)
            
            TallyCounter(
                count: $count,
                amount: $amount,
                config: .init(
                    showAmountLabel: false,
                    controlsColor: .blue,
                    labelBackgroundColor: .red,
                    controlsBackgroundColor: .white,
                    controlsOnTapCircleColor: .yellow,
                    controlsBackgroundOverlayColor: .red
                )
            )
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.screenBackground.edgesIgnoringSafeArea(.all))
    }
}

Inspired by Ehsan Rahimi Tally Counter Micro-Interaction concept.

License

TallyCounter is available under the MIT license. See the LICENSE file for more information.

Support

If my work has brought you value or made your day a little brighter, show your appreciation

GitHub

View Github