VComponents is a SwiftUI collection that contains reusable UI components
VComponents is a SwiftUI
collection that contains reusable UI components.
Components from VComponents
are not meant to be customized the same way you would customize atomic SwiftUI components.
Rather than directly modifying them using ViewModifiers
s, you are supposed to pass an UI model as a parameter to the initializers. All components have default UI models and passing them to initializers is not required. Furthermore, all properties within the UI models have their own default values.
For instance, you can change the foreground color of a VPlainButton
by changing the values.
Not Preferred:
var body: some View {
VPlainButton(
action: doSomething,
title: "Lorem Ipsum"
)
.foregroundStyle(.primary)
}
Preferred:
let uiModel: VPlainButtonUIModel = {
var uiModel: VPlainButtonUIModel = .init()
uiModel.titleTextColors = VPlainButtonUIModel.StateColors(
enabled: Color.primary,
pressed: Color.secondary,
disabled: Color.secondary
)
return uiModel
}()
var body: some View {
VPlainButton(
uiModel: uiModel,
action: doSomething,
title: "Lorem Ipsum"
)
}
Alternately, you can create static
instances of UI models for reusability.
extension VPlainButtonUIModel {
static let someUIModel: Self = {
var uiModel: Self = .init()
uiModel.titleTextColors = StateColors(
enabled: Color.primary,
pressed: Color.secondary,
disabled: Color.secondary
)
return uiModel
}()
}
var body: some View {
VPlainButton(
uiModel: .someUIModel,
action: doSomething,
title: "Lorem Ipsum"
)
}
Frequently, you will discover pre-configured static factory-initialized UI models associated with each component. It’s recommended to investigate UI model files before defining them yourself.
var body: some View {
VWrappingMarquee(
uiModel: .insettedGradientMask,
content: {
HStack(content: {
Image(systemName: "swift")
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
})
.drawingGroup() // For `Image`
}
)
}
VComponents
associates animations directly with the components and their UI models, rather than with the external state.
@State private var isOn: Bool = false
var body: some View {
VStack(content: {
VToggle(isOn: $isOn)
VPlainButton(
action: { isOn.toggle() },
title: "Toggle"
)
})
}
By default, the VToggle
uses an easeIn
animation with a duration of 0.1
to handle state changes. This applies uniformly to both touch interactions, as well as any external modifications of the state. So, to modify state with a different animation, you’ll need to provide a custom UI model.
@State private var isOn: Bool = false
var body: some View {
VStack(content: {
VToggle(
uiModel: {
var uiModel: VToggleUIModel = .init()
uiModel.stateChangeAnimation = .easeIn(duration: 1)
return uiModel
}(),
isOn: $isOn
)
VPlainButton(
action: { isOn.toggle() },
title: "Toggle"
)
})
}
There are two available options for completely cancelling animations.
The first is to set stateChangeAnimation
to nil
. While this does not completely remove animation, it essentially applies a nil
animation.
@State private var isOn: Bool = false
var body: some View {
VStack(content: {
VToggle(
uiModel: {
var uiModel: VToggleUIModel = .init()
uiModel.stateChangeAnimation = nil
return uiModel
}(),
isOn: $isOn
)
VPlainButton(
action: { isOn.toggle() },
title: "Toggle"
)
})
}
The second is to set appliesStateChangeAnimation
to false
. This option ensures that the stateChangeAnimation
is not applied at all, thus effectively removing any animation tied to state changes, even nil
.
@State private var isOn: Bool = false
var body: some View {
VStack(content: {
VToggle(
uiModel: {
var uiModel: VToggleUIModel = .init()
uiModel.appliesStateChangeAnimation = false
return uiModel
}(),
isOn: $isOn
)
VPlainButton(
action: { isOn.toggle() },
title: "Toggle"
)
})
}
In certain scenarios, the distinction between these two can be substantial. For example, we could set the appliesStateChangeAnimation
flag to false
and subsequently mutate the state with an external animation.
@State private var isOn: Bool = false
var body: some View {
VStack(content: {
VToggle(
uiModel: {
var uiModel: VToggleUIModel = .init()
uiModel.appliesStateChangeAnimation = false
return uiModel
}(),
isOn: $isOn
)
VPlainButton(
action: {
withAnimation(.easeInOut(duration: 1), {
isOn.toggle()
})
},
title: "Toggle"
)
})
}
Add https://github.com/VakhoKontridze/VComponents
as a Swift Package in Xcode and follow the instructions.
Package provides limited macOS
, tvOS
, watchOS
, and visionOS
support.
Versions with different majors are not directly compatible. When a new major is released, deprecated symbols are removed.
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
Ver | Release Date | Swift | SDK | VCore | Comment |
---|---|---|---|---|---|
7.0 | 2024 09 20 | 6.0 |
iOS 16.0 macOS 13.0 tvOS 16.0 watchOS 9.0 visionOS 1.0 |
7.0.0 - 7.x.x |
New SDK. API changes. |
6.0 | 2024 02 18 |
5.10 (6.0.1 - 6.x.x) 5.9 (6.0.0) |
iOS 15.0 macOS 12.0 tvOS 15.0 watchOS 8.0 visionOS 1.0 |
6.0.0 - 6.x.x |
API changes. visionOS support. |
5.0 | 2023 10 08 | 5.9 |
iOS 15.0 macOS 12.0 tvOS 15.0 watchOS 8.0 |
5.0.0 - 5.x.x |
New SDK. API changes. |
4.0 | 2023 04 09 | 5.8 |
iOS 13.0 macOS 10.15 tvOS 13.0 watchOS 6.0 |
4.7.0 - 4.x.x |
iOS 13.0 support. Multiplatform support. RTL language support. |
3.0 | 2022 10 02 | 5.7 | iOS 16.0 | 4.1.0 - 4.x.x |
New SDK. API changes. |
2.0 | 2022 05 26 | 5.6 | iOS 15.0 | 3.2.0 - 3.x.x |
New SDK. API changes. SPM support. |
1.0 | 2021 02 07 | 5.3 | iOS 14.0 | - | - |
For additional info, refer to the CHANGELOG.
e-mail: [email protected]