Skip to content

Commit

Permalink
Allow custom views as icons in OnboardingView (#28)
Browse files Browse the repository at this point in the history
# Allow custom views as icons in OnboardingView

## ♻️ Current situation & Problem
The `OnboardingView` has areas comprised of
`OnboardingInformationView`s. Each `OnboardingInformationView` can have
an icon, which must be an `Image`. However, this means we cannot
currently add modifiers to the icon or use other types of views as
icons, which limits the customizability.
See #27.

## ⚙️ Release Notes 
Added a new initializer in the `Content` struct that accepts any `View`
as an icon using `@ViewBuilder`.

## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md):
- [X] I agree to follow the [Code of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
vishnuravi authored Oct 31, 2023
1 parent 0ea46a6 commit b281ff6
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 23 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/monthly-markdown-link-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# This source file is part of the Stanford Spezi open source project
#
# SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md)
#
# SPDX-License-Identifier: MIT
#

name: Monthly Markdown Link Check

on:
# Runs at midnight on the first of every month
schedule:
- cron: "0 0 1 * *"

jobs:
markdown_link_check:
name: Markdown Link Check
uses: StanfordBDHG/.github/.github/workflows/markdown-link-check.yml@v2
3 changes: 3 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ jobs:
swiftlint:
name: SwiftLint
uses: StanfordSpezi/.github/.github/workflows/swiftlint.yml@v2
markdown_link_check:
name: Markdown Link Check
uses: StanfordBDHG/.github/.github/workflows/markdown-link-check.yml@v2
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,19 @@ struct OnboardingViewExample: View {
description: "A Tortoise!"
),
.init(
icon: Image(systemName: "lizard.fill"),
icon: {
Image(systemName: "lizard.fill")
.foregroundColor(.green)
},
title: "Lizard",
description: "A Lizard!"
),
.init(
icon: Image(systemName: "tree.fill"),
title: "Tree",
description: "A Tree!"
icon: {
Circle().fill(.orange)
},
title: "Circle",
description: "A Circle!"
)
],
actionText: "Learn More",
Expand Down
10 changes: 5 additions & 5 deletions Sources/SpeziOnboarding/OnboardingInformationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public struct OnboardingInformationView: View {
/// A ``Content`` defines the way that information is displayed in an ``OnboardingInformationView``.
public struct Content {
/// The icon of the area in the ``OnboardingInformationView``.
public let icon: Image
public let icon: AnyView
/// The title of the area in the ``OnboardingInformationView``.
public let title: String
/// The description of the area in the ``OnboardingInformationView``.
Expand All @@ -47,12 +47,12 @@ public struct OnboardingInformationView: View {
/// - title: The title of the area in the ``OnboardingInformationView`` without localization.
/// - description: The description of the area in the ``OnboardingInformationView`` without localization.
@_disfavoredOverload
public init<Title: StringProtocol, Description: StringProtocol>(
icon: Image,
public init<Icon: View, Title: StringProtocol, Description: StringProtocol>(
@ViewBuilder icon: () -> Icon,
title: Title,
description: Description
) {
self.icon = icon
self.icon = AnyView(icon())
self.title = String(title)
self.description = String(description)
}
Expand All @@ -67,7 +67,7 @@ public struct OnboardingInformationView: View {
title: LocalizedStringResource,
description: LocalizedStringResource
) {
self.init(icon: icon, title: title.localizedString(), description: description.localizedString())
self.init(icon: { icon }, title: title.localizedString(), description: description.localizedString())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Display information to your user during an onboarding flow.

The <doc:OnboardingView> allows you to separate information into areas on a screen, each with a title, description, and icon.

![OnboardingView](OnboardingView.png)
@Image(source: "OnboardingView.png")

The following example demonstrates how the above view is constructed:

Expand Down Expand Up @@ -52,7 +52,7 @@ OnboardingView(

The <doc:SequentialOnboardingView> allows you to display information step-by-step, with each additional area appearing when the user taps the `Continue` button.

![SequentialOnboardingView](SequentialOnboardingView.png)
@Image(source: "SequentialOnboardingView.png")

The following example demonstrates how the above view is constructed:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Present your user a consent document to read and sign.

The ``OnboardingConsentView`` can allow users to read and agree to a document, e.g., a consent document for a research study or a terms and conditions document for an app. The document can be signed using a family and given name and a hand-drawn signature.

![OnboardingConsentView](ConsentView.png)
@Image(source: "ConsentView.png")

The following example demonstrates how the ``OnboardingConsentView`` shown above is constructed by providing a header, markdown content encoded as a [UTF8](https://www.swift.org/blog/utf8-string/) [`Data`](https://developer.apple.com/documentation/foundation/data) instance (which may be provided asynchronously), and an action that should be performed once the consent has been given.

Expand Down
13 changes: 9 additions & 4 deletions Sources/SpeziOnboarding/SpeziOnboarding.docc/SpeziOnboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,19 @@ struct OnboardingViewExample: View {
description: "A Tortoise!"
),
.init(
icon: Image(systemName: "lizard.fill"),
icon: {
Image(systemName: "lizard.fill")
.foregroundColor(.green)
},
title: "Lizard",
description: "A Lizard!"
),
.init(
icon: Image(systemName: "tree.fill"),
title: "Tree",
description: "A Tree!"
icon: {
Circle().fill(.orange)
},
title: "Circle",
description: "A Circle!"
)
],
actionText: "Learn More",
Expand Down
7 changes: 4 additions & 3 deletions Tests/UITests/TestApp/Views/OnboardingWelcomeTestView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ struct OnboardingWelcomeTestView: View {
title: "Welcome",
subtitle: "Spezi UI Tests",
areas: [
.init(icon: Image(systemName: "tortoise.fill"), title: "Tortoise", description: "A Tortoise!"),
.init(icon: Image(systemName: "lizard.fill"), title: "Lizard", description: "A Lizard!"),
.init(icon: Image(systemName: "tree.fill"), title: "Tree", description: "A Tree!")
.init(icon: { Image(systemName: "tortoise.fill").foregroundColor(.green) }, title: "Tortoise", description: "A Tortoise!"),
.init(icon: Image(systemName: "tree.fill"), title: "Tree", description: "A Tree!"),
.init(icon: { Text("A").fontWeight(.light) }, title: "Letter", description: "A letter!"),
.init(icon: { Circle().fill(.orange) }, title: "Circle", description: "A circle!")
],
actionText: "Learn More",
action: {
Expand Down
11 changes: 7 additions & 4 deletions Tests/UITests/TestAppUITests/SpeziOnboardingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ final class OnboardingTests: XCTestCase {
XCTAssert(app.staticTexts["Tortoise"].waitForExistence(timeout: 2))
XCTAssert(app.staticTexts["A Tortoise!"].waitForExistence(timeout: 2))

XCTAssert(app.staticTexts["Lizard"].waitForExistence(timeout: 2))
XCTAssert(app.staticTexts["A Lizard!"].waitForExistence(timeout: 2))

XCTAssert(app.staticTexts["Tree"].waitForExistence(timeout: 2))
XCTAssert(app.staticTexts["A Tree!"].waitForExistence(timeout: 2))


XCTAssert(app.staticTexts["Letter"].waitForExistence(timeout: 2))
XCTAssert(app.staticTexts["A letter!"].waitForExistence(timeout: 2))

XCTAssert(app.staticTexts["Circle"].waitForExistence(timeout: 2))
XCTAssert(app.staticTexts["A circle!"].waitForExistence(timeout: 2))

XCTAssert(app.buttons["Learn More"].waitForExistence(timeout: 2))
app.buttons["Learn More"].tap()

Expand Down

0 comments on commit b281ff6

Please sign in to comment.