Skip to content

🌺 HypeUI is a implementation of Apple's SwiftUI DSL style based on UIKit

License

Notifications You must be signed in to change notification settings

hyperconnect/HypeUI

Repository files navigation

HypeUI

πŸš€ HypeUI is a implementation of Apple's SwiftUI DSL style based on UIKit Want to enjoy SwiftUI syntax with UIKit? It's time to use HypeUI 😊

Awesome Swift

Why to use HypeUI?
πŸ“± Support iOS 12+
✨ HypeUI is compatible with UIKit based project using SwiftUI style syntax
πŸ„β€β™‚οΈ Reduce UI & Autolayout codes more than 30%
⛳️ Provide UI binding extension with RxSwift and RxCocoa
πŸ¦„ Easy to use!
✈️ Improve readability and intuitiveness of complex layouts
🀩 Have a blast
β›· Customize reusable component, design system
❄️ Test with accessibility Identifier

Contents

Requirements

  • iOS 12.0+
  • XCode 13.0+
  • Swift 5.0+

Installation

Swift Package Manager

Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

Xcode 13+ is required to build HypeUI using Swift Package Manager.

To integrate HypeUI into your Xcode project using Swift Package Manager, add it to the dependencies value of your Package.swift:

dependencies: [
    .package(url: "https://github.com/hyperconnect/HypeUI", .upToNextMajor(from: "0.3.0"))
]

CocoaPod

The preferred installation method is with CocoaPods. Add the following to your Podfile:

pod 'HypeUI'

Supported Features

Supported Features
HStack βœ…
VStack βœ…
ZStack βœ…
Button βœ…
Text βœ…
Image βœ…
ScrollView βœ…
Behavior βœ…
Spacer βœ…
LinearGradient βœ…
AlignmentView βœ…
ViewBuildable βœ…
View Modifier βœ…
Text Modifier βœ…
Stack Modifier βœ…
ScrollView Modifier βœ…

View Modifier

name Description
setHContentHugging Adjusts the priority for a view to resist growing beyond its intrinsic size horizontally.
setVContentHugging Adjusts the priority for a view to resist growing beyond its intrinsic size vertically.
setHContentCompressionResistance Adjusts the priority for a view to resist shrinking below its intrinsic size horizontally.
setVContentCompressionResistance Adjusts the priority for a view to resist shrinking below its intrinsic size vertically.
makeRatio Sets the aspect ratio constraint for the view's size.
cornerRadius Applies a corner radius to the view to create rounded corners.
border Adds a border with specified color and width to the view.
background Sets the background color of the view.
makeContentMode Sets the content mode of the view.
frame Positions the view within a specified frame size.
padding Adds padding around specific edges of the view.
allowsHitTesting Enables or disables the view's interaction with touch events.
masksToBounds Clips the view's sublayers to its boundaries.
accessibilityIdentifier Assigns an identifier used to find this view in tests.
overlay Places specified views in front of the view.
background Layers the views that you specify behind this view.
center Centers the view within a new parent view.
tint Applies a tint color to the view.
opacity Sets the transparency level of the view.
scaleEffect Scales the view by specified factors along the x and y axes.
rotationEffect Rotates the view by a specified angle around a given anchor point.

Text Modifier

name Description
font Sets the font of the text.
foregroundColor Applies a foreground color to the text.
textAligned Sets the alignment of the text within its container.
lineLimit Specifies the maximum number of lines the text can span.
lineBreakMode Defines how text wraps when it reaches the edge of its container.
adjustFontSize Adjusts the font size of the text to fit its width.
minimumScaleFactor Sets the smallest multiplier for text size reduction to fit the width.
preferredMaxLayoutWidth Sets the preferred maximum width for the Text object and enables method chaining.
baselineAdjusted Applies a baseline adjustment to the Text object and enables method chaining.

Stack Modifier

name Description
distributed Modify stack's distribution layout.

ScrollView Modifier

name Description
bounces Modify scroll view bounces.
isPagingEnabled Modify scroll view paging enabled.
isScrollEnabled Modify scroll view enabled.

Usage

HStack

HStack(alinement: .center, spacing: 4) {
    Image(Asset.icStar.image)
        .frame(width: 12, height: 12)
    Text()
        .foregroundColor(UIColor.black)
        .font(UIFont.systemFont(ofSize: 14, weight: .regular))
    Spacer()
}

VStack

VStack(spacing: 8) {
    Text()
        .foregroundColor(UIColor.black)
        .font(UIFont.systemFont(ofSize: 14, weight: .regular))
    Spacer()
}

ZStack

ZStack {
    HStack(alinement: .center, spacing: 4) {
        Image(Asset.icStar.image)
            .frame(width: 12, height: 12)
        Text()
            .foregroundColor(UIColor.black)
            .font(UIFont.systemFont(ofSize: 14, weight: .regular))
        Spacer()
    }
    VStack {
        Text()
            .foregroundColor(UIColor.black)
            .font(UIFont.systemFont(ofSize: 14, weight: .regular))
        Spacer()
    }
}

Button

Button(action: { // DO SOMETHING ex) reactor action, closure }) {
    HStack(alignment: .center, spacing: 5.0) {
        Image("cart")
            .padding(.leading, 10.0)
        Text("Add to Cart")
            .foregroundColor(.black)
            .padding(.all, 10.0)
    }
}
.background(Color.gray)
.cornerRadius(5)

Text

Text("✨")
    .foregroundColor(UIColor.black)
    .font(UIFont.systemFont(ofSize: 14, weight: .regular))
    .textAligned(.center)
    .background(.white)
    .cornerRadius(16)

Image

Image(Resource.Profile.placeholderImage)
    .frame(width: 48, height: 48)
    .cornerRadius(24)

ScrollView

// MARK: Example
ScrollView(.vertical, showsIndicators: false) {
    VStack(alignment: .fill) {
        Image(image: Asset.imgPopupPrivateCall.image)
            .makeRatio(0.46106)
        Spacer()
            .frame(height: 24)
        VStack {
            viewModel.messages.map { message in
                HStack(alignment: .top, spacing: 8) {
                    Text("β€’")
                        .font(UIFont.systemFont(ofSize: 14, weight: .regular))
                        .foregroundColor(.Palette.gray04)
                        .frame(width: 6)
                    Text(message)
                        .font(UIFont.systemFont(ofSize: 14, weight: .regular))
                        .foregroundColor(.Palette.gray04)
                        .lineLimit(2)
                        .lineBreakMode(.byCharWrapping)
                    Spacer()
                        .frame(width: 5)
                }
                .padding(.vertical, 8)
            }
        }
        Spacer()
            .frame(height: 16)
    }
}

@Behavior - It's seems like SwiftUI's @State using DynamicLinkable 😎

@Behavior var isLive: Bool = false
@Behavior var username: String? = nil
@Behavior var profileImageURL: URL? = nil

// MARK Example
final class SearchHostHistoryViewCell: UICollectionViewCell {
    @Behavior var isLive: Bool = false
    @Behavior var username: String? = nil
    @Behavior var profileImageURL: URL? = nil

    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.addSubviewWithFit(
            ZStack {
                VStack(alignment: .center, spacing: 8) {
                    Image(Resource.Profile.placeholderImage)
                        .linked($profileImageURL.flatMapLatest { $0?.getImage(failover: Resource.Profile.placeholderImage) ?? .just(Resource.Profile.placeholderImage) }, keyPath: \.image)
                        .makeContentMode(.scaleAspectFill)
                        .frame(width: 48, height: 48)
                        .cornerRadius(24)
                        .background(.Palette.gray05)
                    Text("")
                        .linked($username, keyPath: \.text)
                        .textAligned(.center)
                        .foregroundColor(.darkModeSupporting(.Palette.gray01, .Palette.dkGray01))
                        .font(UIFont.systemFont(ofSize: 10, weight: .regular))
                        .frame(height: 12)
                }.padding(UIEdgeInsets(top: 12, left: 0, bottom: 4, right: 0))
                VStack(alignment: .center) {
                    Spacer()
                    Text("LIVE")
                        .foregroundColor(.Palette.white)
                        .font(UIFont.systemFont(ofSize: 8, weight: .bold))
                        .padding(UIEdgeInsets(top: 2, left: 4, bottom: 2, right: 4))
                        .background(.Palette.red)
                        .cornerRadius(4)
                        .linked($isLive.not(), keyPath: \.isHidden)
                    Spacer()
                        .frame(height: 20)
                }
            }
        )
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Spacer

Spacer()
    .frame(width: 10)
Spacer()
    .frame(height: 20)

LinearGradient

ProfileView()
    .background(
        LinearGradient(
            gradient: Gradient(
                stops: [
                    Stop(color: UIColor.black, location: 1.0),
                    Stop(color: UIColor.black, location: 0.2),
                    Stop(color: UIColor.black, location: 0.0)
                ]),
            startPoint: .top,
            endPoint: .bottom
        )
    )

ViewBuildable - Customize UI, Make reusable component and Design System by confirming ViewBuildable protocol.

struct ProfileView: ViewBuildable {
    @Behavior var country: String
    @Behavior var name: String

    func build() -> UIView {
        VStack {
            HStack(alignment: .center, spacing: 12) {
                Text("")
                    .linked($country, keyPath: \.text)
                    .font(UIFont.systemFont(ofSize: 20, weight: .regular))
                    .accessibilityIdentifier("country")
                Text("")
                    .linked($name, keyPath: \.text)
                    .font(UIFont.systemFont(ofSize: 20, weight: .regular))
                    .accessibilityIdentifier("name")
            }
        }
    }
}

Main Contributors

[email protected] [email protected] [email protected] [email protected]

Dependencies