Skip to content

Commit

Permalink
feat: add tiny SBBLoadingIndicator
Browse files Browse the repository at this point in the history
  • Loading branch information
fleuryj committed Jul 8, 2024
1 parent 25dd14e commit 0e7723f
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 32 deletions.
83 changes: 55 additions & 28 deletions SBBDesignSystemMobileSwiftUI/Views/SBBLoadingIndicator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ public struct SBBLoadingIndicator: View {
case normal
/// Small SBBLoadingIndicator Size.
case small
/// Tiny SBBLoadingIndicator Size.
case tiny

var size: CGSize {
switch self {
case .normal:
return CGSize(width: 55, height: 32)
case .small:
return CGSize(width: 31, height: 18)
case .tiny:
return CGSize(width: 15, height: 9)
}
}
}
Expand Down Expand Up @@ -90,7 +94,7 @@ public struct SBBLoadingIndicator: View {

let innerWidth = width / CGFloat(cos(rotationInDegrees * .pi / 180)) * 3.0
self.innerWidth = innerWidth
let paddingBetweenRectangles = size == .normal ? 8.0 : 4.0
let paddingBetweenRectangles = size == .normal ? 8.0 : size == .small ? 4.0 : 2.0
self.rectangleWidth = innerWidth / CGFloat(numberOfRectangles) + paddingBetweenRectangles

rectangleOffsets = [-rectangleWidth, 0, rectangleWidth, 2.0*rectangleWidth, 3.0*rectangleWidth, 4.0*rectangleWidth]
Expand All @@ -99,37 +103,34 @@ public struct SBBLoadingIndicator: View {
}

public var body: some View {
Group {
ZStack {
ForEach(rectangleProperties.indices, id:\.self) { index in
Rectangle()
.fill(style.color(for: colorScheme))
.frame(width: innerWidth / CGFloat(numberOfRectangles), height: height)
.opacity(rectangleProperties[index].opacity)
.offset(x: rectangleProperties[index].offset)
.onAppear {
DispatchQueue.main.async {
withAnimation(Animation.linear(duration: animationDuration)
.repeatForever(autoreverses: false)
)
{
rectangleProperties[index].offset = rectangleOffsets[index]
}

withAnimation(Animation.linear(duration: animationDuration)
.repeatForever(autoreverses: false)
) {
rectangleProperties[index].opacity = rectangleOpacity[index]
}
ZStack {
ForEach(rectangleProperties.indices, id:\.self) { index in
Rectangle()
.fill(style.color(for: colorScheme))
.frame(width: innerWidth / CGFloat(numberOfRectangles), height: height)
.opacity(rectangleProperties[index].opacity)
.offset(x: rectangleProperties[index].offset)
.onAppear {
DispatchQueue.main.async {
withAnimation(Animation.linear(duration: animationDuration)
.repeatForever(autoreverses: false)
)
{
rectangleProperties[index].offset = rectangleOffsets[index]
}

withAnimation(Animation.linear(duration: animationDuration)
.repeatForever(autoreverses: false)
) {
rectangleProperties[index].opacity = rectangleOpacity[index]
}
}
}
}
}
.rotation3DEffect(.degrees(rotationInDegrees), axis: (x: 0, y: 1, z: 0), anchor: .leading)
}
.frame(width: width, height: height, alignment: .leading)
.padding(16)
.rotation3DEffect(.degrees(rotationInDegrees), axis: (x: 0, y: 1, z: 0), anchor: .leading)
.frame(width: width, height: height, alignment: .leading)
.padding(16)
.accessibility(label: Text("Loading.".localized))
}
}
Expand All @@ -138,6 +139,15 @@ public struct SBBLoadingIndicator: View {
struct SBBLoadingIndicator_Previews: PreviewProvider {
static var previews: some View {
Group {
VStack {
SBBLoadingIndicator()
.previewDisplayName("normal, red, light")
SBBLoadingIndicator(size: .small)
.previewDisplayName("normal, red, light")
SBBLoadingIndicator(size: .tiny)
.previewDisplayName("normal, red, light")

}
Group {
SBBLoadingIndicator()
.previewDisplayName("normal, red, light")
Expand Down Expand Up @@ -170,6 +180,23 @@ struct SBBLoadingIndicator_Previews: PreviewProvider {
.previewDisplayName("small, white, dark")
.environment(\.colorScheme, .dark)
}

Group {
SBBLoadingIndicator(size: .tiny)
.previewDisplayName("tiny, red, light")
SBBLoadingIndicator(size: .tiny)
.previewDisplayName("tiny, red, dark")
.environment(\.colorScheme, .dark)
SBBLoadingIndicator(size: .tiny, style: .grey)
.previewDisplayName("tiny, grey, light")
SBBLoadingIndicator(size: .tiny, style: .grey)
.previewDisplayName("tiny, grey, dark")
SBBLoadingIndicator(size: .tiny, style: .primaryBackground)
.previewDisplayName("tiny, white, light")
SBBLoadingIndicator(size: .small, style: .primaryBackground)
.previewDisplayName("tiny, white, dark")
.environment(\.colorScheme, .dark)
}
}
.previewLayout(.sizeThatFits)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,57 @@ import SBBDesignSystemMobileSwiftUI

class SBBLoadingIndicatorTests: XCTestCase {

// WORKAROUND: no 3D rotation applied on standard snapshots but Documentation snapshots renders indicator correctly (e.g. image) -> renders image and compare that
private func renderSBBLoadingIndicator(view: any View, colorScheme: ColorScheme) -> UIViewController {
let controller = view.colorScheme(colorScheme).toVC()
let view = controller.view

let targetSize = controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: .zero, size: targetSize)
view?.backgroundColor = .clear

let renderer = UIGraphicsImageRenderer(size: targetSize)

let image = renderer.image { _ in
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
}

return Image(uiImage: image).toVC()
}

func testLoadingIndicatorNormalPrimary() {
let view = SBBLoadingIndicator(size: .normal, style: .primary)
for colorScheme in ColorScheme.allCases {
view.recordDocumentationSnapshot(name: "SBBLoadingIndicator", colorScheme: colorScheme)
assertSnapshot(matching: view.colorScheme(colorScheme).toVC(), as: imagePortrait, record: recordNewReferenceSnapshots)
assertSnapshot(matching: renderSBBLoadingIndicator(view: view, colorScheme: colorScheme), as: imagePortrait, record: recordNewReferenceSnapshots)
}
}

func testLoadingIndicatorNormalGrey() {
let view = SBBLoadingIndicator(size: .normal, style: .grey)
for colorScheme in ColorScheme.allCases {
assertSnapshot(matching: view.colorScheme(colorScheme).toVC(), as: imagePortrait, record: recordNewReferenceSnapshots)
assertSnapshot(matching: renderSBBLoadingIndicator(view: view, colorScheme: colorScheme), as: imagePortrait, record: recordNewReferenceSnapshots)
}
}

func testLoadingIndicatorNormalWhite() {
let view = SBBLoadingIndicator(size: .normal, style: .primaryBackground)
for colorScheme in ColorScheme.allCases {
assertSnapshot(matching: view.colorScheme(colorScheme).toVC(), as: imagePortrait, record: recordNewReferenceSnapshots)
assertSnapshot(matching: renderSBBLoadingIndicator(view: view, colorScheme: colorScheme), as: imagePortrait, record: recordNewReferenceSnapshots)
}
}

func testLoadingIndicatorSmallPrimary() {
let view = SBBLoadingIndicator(size: .small, style: .primary)
for colorScheme in ColorScheme.allCases {
assertSnapshot(matching: view.colorScheme(colorScheme).toVC(), as: imagePortrait, record: recordNewReferenceSnapshots)
assertSnapshot(matching: renderSBBLoadingIndicator(view: view, colorScheme: colorScheme), as: imagePortrait, record: recordNewReferenceSnapshots)
}
}

func testLoadingIndicatorTineyPrimary() {
let view = SBBLoadingIndicator(size: .tiny, style: .primary)
for colorScheme in ColorScheme.allCases {
assertSnapshot(matching: renderSBBLoadingIndicator(view: view, colorScheme: colorScheme), as: imagePortrait, record: recordNewReferenceSnapshots)
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0e7723f

Please sign in to comment.