Swiftpack.co - VakhoKontridze/VComponents as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by VakhoKontridze.
VakhoKontridze/VComponents 3.2.0
VComponents is a SwiftUI package that contains 30+ customizable UI components
⭐️ 231
🕓 2 weeks ago
iOS
.package(url: "https://github.com/VakhoKontridze/VComponents.git", from: "3.2.0")

VComponents

Table of Contents

Description

VComponents is a SwiftUI package that contains 30+ customizable UI components.

Compatibility

Versions with different majors are not compatible.

Ver Release Date iOS SwiftUI VCore Comment
3.0 2022 10 02 16.0 4.0 4.1.0 - 4.x.x New SwiftUI API. API changes.
2.0 2022 05 26 15.0 3.0 3.2.0 - 3.x.x New SwiftUI API. API changes. SPM support.
1.0 2021 02 07 14.0 2.0 - -

Components

Buttons. VPrimaryButton, VSecondaryButton, VRoundedButton, VRoundedLabeledButton, VPlainButton

State Pickers. VToggle, VCheckBox, VRadioButton

Item Pickers. VSegmentedPicker, VWheelPicker

Value Pickers. VStepper, VSlider, VRangeSlider

Inputs. VTextField, VTextView

Containers. VSheet, VDisclosureGroup

Lists. VList

Modals. VModal, VBottomSheet, VSideBar, VAlert, VConfirmationDialog, VMenu, VContextMenu

Messages. VToast

Indicators. VContinuousSpinner, VDashedSpinner, VProgressBar, VPageIndicator, VCompactPageIndicator, VAutomaticPageIndicator

Misc. VText, VWrappingMarquee, VBouncingMarquee

Brand Book

Guidelines

UI Models

Components are not meant to be customized like you would a native SwiftUI component.

Instead, UI model can be passed as parameter to initializers. This parameter has default value, and is not required every time you create a view.

UI Models are structs with default values. They break down into 5 models: Layout, Colors, Fonts, Animations, and Misc.

For instance, changing foreground color of VSecondaryButton can be done by passing an IU model.

Not Preferred:

var body: some View {
    VSecondaryButton(
        action: doSomething,
        title: "Lorem ipsum"
    )
        .foregroundColor(.black)
}

Preferred:

let uiModel: VSecondaryButtonUIModel = {
    var UIModel: VSecondaryButtonUIModel = .init()
    
    uiModel.colors.textContent = .init(
        enabled: .black,
        pressed: .gray,
        disabled: .gray
    )
    
    return uiModel
}()

var body: some View {
    VSecondaryButton(
        uiModel: uiModel,
        action: doSomething,
        title: "Lorem ipsum"
    )
}

Alternately, you can create static instances of UI models for reusability.

extension VSecondaryButtonUIModel {
    static let someUIModel: VSecondaryButtonUIModel = {
        var uiModel: VSecondaryButtonModel = .init()
        
        uiModel.colors.textContent = .init(
            enabled: .black,
            pressed: .gray,
            disabled: .gray
        )
        
        return uiModel
    }()
}

var body: some View {
    VSecondaryButton(
        uiModel: .someUIModel,
        action: doSomething,
        title: "Lorem ipsum"
    )
}

Types

Some components take type as parameter. For instance, VPageIndicator has three types: standard, compact, and automatic

var body: some View {
    VStack(content: {
        VPageIndicator(type: .standard(), total: 9, selectedIndex: 4)
        
        VPageIndicator(type: .compact(), total: 99, selectedIndex: 4)
        
        VPageIndicator(type: .automatic(), total: 99, selectedIndex: 4)
    })
}

Animations

VComponents approaches animations as bound to components and their UI models, and not to state. Which means, that to modify a state of component with an animation, you need to pass a custom UI model.

Not Preferred:

@State var isOn: Bool = false

var body: some View {
    VStack(content: {
        VToggle(
            isOn: $isOn, 
            title: "Lorem ipsum"
        )
        
        VSecondaryButton(
            action: { withAnimation(nil, { isOn.toggle() }) },
            title: "Toggle"
        )
    })
}

Preferred:

@State var isOn: Bool = false

let uiModel: VToggleUIModel = {
    var uiModel: VToggleUIModel = .init()
    uiModel.animations.stateChange = nil
    return uiModel
}()

var body: some View {
    VStack(content: {
        VToggle(
            uiModel: uiModel, 
            isOn: $isOn, 
            title: "Lorem ipsum"
        )
        
        VSecondaryButton(
            action: { isOn.toggle() },
            title: "Toggle"
        )
    })
}

First method is not only not preferred, but it will also not work. Despite specifying nil to change state, VToggle would still use its default animation.

Components manage state parameters internally, and animations used to change them externally do not have any effect.

Thought process behind his design choice was to centralize animations to UI model.

Components also prevent themselves from modifying external state with an animation.

Demo

Package contains demo app, that can be run to showcase all components.

Installation

Swift Package Manager

Add https://github.com/VakhoKontridze/VComponents as a Swift Package in Xcode and follow the instructions.

Versioning

Major. Major changes, such as big overhauls

Minor. Minor changes, such as new component, types, or properties in UI models

Patch. Bug fixes and improvements

Contact

e-mail: [email protected]

GitHub

link
Stars: 231
Last commit: 2 days ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

3.2.0
2 weeks ago

General

  • Issue with tap gesture falling through some contents when presenting modal using PresentationHost is fixed
  • Memory leak caused by forceDismiss(id:) method in PresentationHost is fixed
  • presentationHost(id:allowsHitTests:isPresented:content:) method is added that replaces current PresentationHost API

VRoundedLabeledButton

  • Missing titleLabelLineType from VRoundedLabeledButtonUIModel is now utilized inside the button

VRadioButton

  • Issue with radio button turning off after being tapped is fixed

VTextField

  • VTextFieldType is renamed to ContentType and is moved to VTextFieldUIModel

VTextView

  • TextLineLimitType is removed from init and can now be customized via textLineType in VTextViewUIModel

VList

  • VListRowSeparatorType is renamed to SeparatorType and is moved to VListRowUIModel

VModal

  • Issue with some content not stretching to full width is fixed

VToast

  • VToastTextLineType is renamed to TextLineType and is moved to VToastUIModel

VSpinner

  • VSpinner is split to VContinuousSpinner and VDashedSpinner

VPageIndicator

  • VPageIndicator is split to VPageIndicator, VCompactPageIndicator and VAutomaticPageIndicator

VMarquee

  • VMarquee is split to VWrappingMarquee and VBouncingMarquee

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics