-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #131 from adevinta/feature/component/badge
[Badge] Implemented Badge component
- Loading branch information
Showing
21 changed files
with
1,835 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// | ||
// BadgeUIView_Previews.swift | ||
// SparkCoreDemo | ||
// | ||
// Created by alex.vecherov on 22.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
import SparkCore | ||
|
||
private struct BadgePreviewFormatter: BadgeFormatting { | ||
func formatText(for value: Int?) -> String { | ||
guard let value else { | ||
return "_" | ||
} | ||
return "\(value)€" | ||
} | ||
} | ||
|
||
struct UIBadgeView: UIViewRepresentable { | ||
|
||
var views: [BadgeUIView] | ||
|
||
func makeUIView(context: Context) -> some UIView { | ||
let badgesStackView = UIStackView() | ||
views.enumerated().forEach { index, badgeView in | ||
let containerView = UIView() | ||
containerView.translatesAutoresizingMaskIntoConstraints = false | ||
let label = UILabel() | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
label.text = "badge_\(index)" | ||
containerView.addSubview(label) | ||
containerView.addSubview(badgeView) | ||
containerView.backgroundColor = .blue | ||
|
||
NSLayoutConstraint.activate([ | ||
label.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor), | ||
label.topAnchor.constraint(equalTo: containerView.topAnchor), | ||
label.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) | ||
]) | ||
if index >= 3 && index <= 6 { | ||
NSLayoutConstraint.activate([ | ||
badgeView.centerXAnchor.constraint(equalTo: label.trailingAnchor, constant: 5), | ||
badgeView.centerYAnchor.constraint(equalTo: label.topAnchor, constant: -5) | ||
]) | ||
} else { | ||
NSLayoutConstraint.activate([ | ||
badgeView.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: 5), | ||
badgeView.centerYAnchor.constraint(equalTo: label.centerYAnchor, constant: 0) | ||
]) | ||
} | ||
|
||
badgesStackView.addArrangedSubview(containerView) | ||
} | ||
badgesStackView.axis = .vertical | ||
badgesStackView.alignment = .leading | ||
badgesStackView.spacing = 30 | ||
badgesStackView.distribution = .fill | ||
|
||
return badgesStackView | ||
} | ||
|
||
func updateUIView(_ uiView: UIViewType, context: Context) { | ||
} | ||
} | ||
|
||
struct BadgeUIView_Previews: PreviewProvider { | ||
|
||
struct BadgeUIViewBridge: View { | ||
private var views = [ | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .alert, | ||
value: 6 | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .primary, | ||
badgeSize: .normal, | ||
value: 22, | ||
format: .overflowCounter(maxValue: 20) | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .danger, | ||
value: 10, | ||
format: .custom( | ||
formatter: BadgePreviewFormatter() | ||
) | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .info, | ||
value: 20 | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .primary | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .neutral, | ||
isBadgeOutlined: false | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .secondary, | ||
value: 23 | ||
), | ||
BadgeUIView( | ||
theme: SparkTheme.shared, | ||
badgeType: .success | ||
) | ||
] | ||
|
||
var body: some View { | ||
List { | ||
Button("Change UIKit Badge 0 Type") { | ||
views[0].setBadgeType(BadgeIntentType.allCases.randomElement() ?? .alert) | ||
} | ||
Button("Change UIKit Badge 1 Value") { | ||
views[1].setBadgeValue(2) | ||
} | ||
Button("Change UIKit Badge 2 Outline") { | ||
views[2].setBadgeOutlineEnabled(false) | ||
} | ||
Button("Change UIKit Badge 3 Size") { | ||
views[3].setBadgeSize(.small) | ||
} | ||
UIBadgeView(views: views) | ||
.frame(height: 400) | ||
.listRowBackground(Color.gray.opacity(0.3)) | ||
} | ||
} | ||
} | ||
|
||
static var previews: some View { | ||
BadgeUIViewBridge() | ||
.background(Color.gray.opacity(0.4)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// | ||
// BadgeView_Previews.swift | ||
// SparkCoreDemo | ||
// | ||
// Created by alex.vecherov on 22.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
import SparkCore | ||
|
||
private struct BadgePreviewFormatter: BadgeFormatting { | ||
func formatText(for value: Int?) -> String { | ||
guard let value else { | ||
return "_" | ||
} | ||
return "\(value)€" | ||
} | ||
} | ||
|
||
struct BadgeView_Previews: PreviewProvider { | ||
|
||
struct BadgeContainerView: View { | ||
|
||
@State var theme: Theme = SparkTheme.shared | ||
|
||
@State var standartBadgeValue: Int? = 3 | ||
@State var standartBadgeIsOutlined: Bool = true | ||
|
||
@State var smallCustomBadgeValue: Int? = 14 | ||
@State var smallCustomBadgeSize: BadgeSize = .small | ||
@State var smallCustomBadgeIsOutlined: Bool = true | ||
@State var smallCustomBadgeType: BadgeIntentType = .alert | ||
@State var badgeFormat: BadgeFormat = .default | ||
|
||
@State var standartDangerBadgeType: BadgeIntentType = .danger | ||
|
||
@ScaledMetric var hOffset: CGFloat | ||
@ScaledMetric var vOffset: CGFloat | ||
|
||
var body: some View { | ||
List { | ||
Section(header: Text("SwiftUI Badge")) { | ||
Button("Change Default Badge Value") { | ||
standartBadgeValue = 23 | ||
standartBadgeIsOutlined.toggle() | ||
badgeFormat = .overflowCounter(maxValue: 20) | ||
} | ||
Button("Change Small Custom Badge") { | ||
smallCustomBadgeValue = 18 | ||
smallCustomBadgeSize = .normal | ||
smallCustomBadgeIsOutlined.toggle() | ||
smallCustomBadgeType = .primary | ||
} | ||
Button("Change Dange Badge") { | ||
standartDangerBadgeType = .neutral | ||
} | ||
VStack(spacing: 100) { | ||
HStack(spacing: 50) { | ||
ZStack(alignment: .leading) { | ||
Text("Default Badge") | ||
BadgeView( | ||
theme: theme, | ||
badgeType: .primary, | ||
value: standartBadgeValue | ||
) | ||
.format(badgeFormat) | ||
.outlined(standartBadgeIsOutlined) | ||
.offset(x: 100, y: -15) | ||
} | ||
ZStack(alignment: .leading) { | ||
Text("Small Custom") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: smallCustomBadgeType, | ||
value: 22 | ||
) | ||
.outlined(smallCustomBadgeIsOutlined) | ||
.size(smallCustomBadgeSize) | ||
.offset(x: 100, y: -15) | ||
} | ||
} | ||
|
||
HStack(spacing: 55) { | ||
ZStack(alignment: .leading) { | ||
Text("Danger Badge") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: standartDangerBadgeType, | ||
value: 10 | ||
) | ||
.format(.custom( | ||
formatter: BadgePreviewFormatter() | ||
)) | ||
.offset(x: 100, y: -15) | ||
} | ||
ZStack(alignment: .leading) { | ||
Text("Text") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: .info | ||
) | ||
.offset(x: 25, y: -15) | ||
} | ||
ZStack(alignment: .leading) { | ||
Text("Text") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: .neutral | ||
) | ||
.offset(x: 25, y: -15) | ||
} | ||
} | ||
|
||
HStack(spacing: 50) { | ||
HStack { | ||
Text("Text") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: .primary | ||
) | ||
} | ||
HStack { | ||
Text("Text") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: .secondary | ||
) | ||
} | ||
HStack { | ||
Text("Text") | ||
BadgeView( | ||
theme: SparkTheme.shared, | ||
badgeType: .success | ||
) | ||
} | ||
} | ||
} | ||
.padding(.vertical, 15) | ||
.listRowBackground(Color.gray.opacity(0.3)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
static var previews: some View { | ||
BadgeContainerView(hOffset: SparkTheme.shared.layout.spacing.xxLarge, vOffset: SparkTheme.shared.layout.spacing.medium * 1.5) | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
core/Sources/Components/Badge/AccessibilityIdentifier/BadgeAccessibilityIdentifier.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// BadgeAccessibilityIdentifier.swift | ||
// Spark | ||
// | ||
// Created by alex.vecherov on 04.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
|
||
public enum BadgeAccessibilityIdentifier { | ||
|
||
// MARK: - Properties | ||
|
||
public static let text = "spark-badge-text" | ||
} |
13 changes: 13 additions & 0 deletions
13
core/Sources/Components/Badge/Constants/BadgeConstants.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// BadgeConstants.swift | ||
// SparkCoreDemo | ||
// | ||
// Created by alex.vecherov on 22.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
enum BadgeConstants { | ||
static let emptySize = CGSize(width: 12, height: 12) | ||
} |
20 changes: 20 additions & 0 deletions
20
core/Sources/Components/Badge/Properties/Private/BadgeColors.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// BadgeColors.swift | ||
// Spark | ||
// | ||
// Created by alex.vecherov on 04.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
// sourcery: AutoMockable | ||
struct BadgeColors { | ||
|
||
// MARK: - Properties | ||
|
||
let backgroundColor: ColorToken | ||
let borderColor: ColorToken | ||
let foregroundColor: ColorToken | ||
} | ||
|
29 changes: 29 additions & 0 deletions
29
core/Sources/Components/Badge/Properties/Public/BadgeBorder.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// BadgeBorder.swift | ||
// SparkDemo | ||
// | ||
// Created by alex.vecherov on 17.05.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Structure that is used for configuring border of ``BadgeView`` | ||
/// | ||
/// List of properties: | ||
/// - width | ||
/// - radius | ||
/// - color returned as ColorToken | ||
public struct BadgeBorder { | ||
var width: CGFloat | ||
let radius: CGFloat | ||
var color: ColorToken | ||
|
||
mutating func setWidth(_ width: CGFloat) { | ||
self.width = width | ||
} | ||
|
||
mutating func setColor(_ color: ColorToken) { | ||
self.color = color | ||
} | ||
} |
Oops, something went wrong.