balochcodes/interactiveticket
A realistic, perforated event ticket and flight boarding pass card for SwiftUI featuring authentic vector circular notch cutouts, dashed tear lines, two-compartment architecture, and interactive 3D perspective tilt physics.
β¨ Features
- βοΈ Authentic Vector Cutout Notches: Smooth inward semicircular arc cutouts on both left and right ticket edges using native vector path geometry.
- βΏ Dashed Perforation Tear Line: Realistic dashed divider line spanning between the side notches.
- πΉοΈ Interactive 3D Perspective Tilt: Smooth touch drag gestures tilt the ticket card in 3D perspective space with natural spring-back dampening upon release.
- π Two-Compartment Architecture: Separates primary upper content (
body) from the validation stub/barcode area (stub). - π¨ Rich Styling: Solid backgrounds, multi-stop gradients, customizable shadows, corner radiuses, and notch sizes.
- β‘ Zero External Dependencies: Built 100% on native SwiftUI primitives.
π¦ Installation
In Xcode (Recommended)
- Open your project in Xcode and go to File β Add Package Dependencies...
- In the search box, paste:
``text https://github.com/BalochCodes/InteractiveTicket.git ``
- Select Up to Next Major Version (
1.0.0) and click Add Package.
In Package.swift
Add InteractiveTicket to your dependencies:
dependencies: [
.package(url: "https://github.com/BalochCodes/InteractiveTicket.git", from: "1.0.0")
]Import the framework:
import SwiftUI
import InteractiveTicketπ Usage Examples
1. Airline Flight Boarding Pass
import SwiftUI
import InteractiveTicket
struct BoardingPassView: View {
var body: some View {
InteractiveTicketView(
width: 320,
height: 460,
splitFraction: 0.72,
notchRadius: 14,
cornerRadius: 20,
backgroundColor: .white,
body: {
VStack(alignment: .leading, spacing: 18) {
HStack {
Text("FLIGHT EK-204")
.font(.caption.bold())
.foregroundColor(.blue)
Spacer()
Text("GATE B12")
.font(.caption.bold())
}
HStack {
VStack(alignment: .leading) {
Text("DXB")
.font(.system(size: 34, weight: .heavy, design: .rounded))
Text("Dubai, UAE")
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
Image(systemName: "airplane")
.font(.title2)
.foregroundColor(.blue)
Spacer()
VStack(alignment: .trailing) {
Text("LHR")
.font(.system(size: 34, weight: .heavy, design: .rounded))
Text("London, UK")
.font(.caption)
.foregroundColor(.secondary)
}
}
Divider()
HStack {
VStack(alignment: .leading, spacing: 2) {
Text("PASSENGER")
.font(.system(size: 9, weight: .bold))
.foregroundColor(.secondary)
Text("Shahzain B.")
.font(.subheadline.bold())
}
Spacer()
VStack(alignment: .trailing, spacing: 2) {
Text("SEAT")
.font(.system(size: 9, weight: .bold))
.foregroundColor(.secondary)
Text("14A (Window)")
.font(.subheadline.bold())
}
}
}
.padding(22)
},
stub: {
VStack(spacing: 6) {
Image(systemName: "qrcode")
.font(.system(size: 48))
Text("SCAN AT BOARDING GATE")
.font(.system(size: 10, weight: .bold, design: .rounded))
.foregroundColor(.secondary)
}
.padding(.vertical, 12)
}
)
}
}2. VIP Music Festival Ticket with Gradient
InteractiveTicketView(
width: 320,
height: 420,
splitFraction: 0.68,
gradient: LinearGradient(
colors: [Color(red: 0.12, green: 0.11, blue: 0.29), Color(red: 0.19, green: 0.18, blue: 0.51)],
startPoint: .topLeading,
endPoint: .bottomTrailing
),
perforationColor: Color(red: 0.39, green: 0.40, blue: 0.95),
body: {
VStack(alignment: .leading, spacing: 10) {
Text("VIP ACCESS PASS")
.font(.caption.bold())
.foregroundColor(Color(red: 0.65, green: 0.71, blue: 0.99))
Text("Electric Horizon 2026")
.font(.title2.bold())
.foregroundColor(.white)
Text("SECTION: FRONT STAGE β’ ROW: A β’ SEAT: 01")
.font(.footnote)
.foregroundColor(.white.opacity(0.75))
}
.padding(24)
},
stub: {
Text("#EH-2026-9812-VIP")
.font(.system(size: 13, weight: .bold, design: .monospaced))
.foregroundColor(.white.opacity(0.85))
}
)3. Flat Discount Promo Coupon Voucher
InteractiveTicketView(
width: 300,
height: 200,
splitFraction: 0.70,
enableTilt: false, // Disables touch 3D tilt
backgroundColor: Color(red: 0.99, green: 0.95, blue: 0.78),
perforationColor: Color(red: 0.96, green: 0.62, blue: 0.04),
body: {
VStack(spacing: 4) {
Text("SPECIAL OFFER")
.font(.caption.bold())
.foregroundColor(.orange)
Text("GET 30% OFF")
.font(.title.bold())
.foregroundColor(Color(red: 0.57, green: 0.25, blue: 0.05))
}
},
stub: {
Text("CODE: SAVE30")
.font(.subheadline.bold())
.foregroundColor(Color(red: 0.71, green: 0.33, blue: 0.04))
}
)π οΈ API Reference
InteractiveTicketView
| Parameter | Type | Default | Description | | :--- | :--- | :--- | :--- | | body | () -> BodyContent | Required | The upper primary content compartment of the ticket. | | stub | () -> StubContent | Required | The lower tear-off coupon / barcode compartment. | | height | CGFloat | 460.0 | Total height of the ticket card view. | | width | CGFloat? | 320.0 | Fixed width (or container width if nil). | | splitFraction | CGFloat | 0.70 | Fractional position (0.0 - 1.0) where the tear line sits. | | notchRadius | CGFloat | 14.0 | Radius of the circular side cutouts. | | cornerRadius | CGFloat | 18.0 | Outer border radius for all four corners. | | backgroundColor| Color | .white | Ticket surface fill color. | | gradient | LinearGradient?| nil | Optional gradient fill overriding background color. | | shadowColor | Color | black.opacity(0.18) | Dropshadow color beneath the ticket shape. | | shadowRadius | CGFloat | 16.0 | Blur radius of the elevation dropshadow. | | enableTilt | Bool | true | Enables interactive 3D perspective tilt on touch drag. | | perforationColor | Color | primary.opacity(0.18)| Color of the dashed tear line dividing body and stub. |
π License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Created by Shahzain Baloch.
Package Metadata
Repository: balochcodes/interactiveticket
Default branch: main
README: README.md