diff --git a/Sources/Orbit/Components/Alert.swift b/Sources/Orbit/Components/Alert.swift index 76b9b4c853c..e2924a41db0 100644 --- a/Sources/Orbit/Components/Alert.swift +++ b/Sources/Orbit/Components/Alert.swift @@ -1,38 +1,46 @@ import SwiftUI -/// Breaks the main user flow to present information. +/// Orbit component that breaks the main user flow to present information. /// -/// There are times when just simple information isn’t enough and the user needs -/// to take additional steps to resolve the problem or get additional details. -/// -/// In such cases, provide additional actions for your message. -/// Alerts use special status buttons to match the button color with the alert color. -/// -/// Use at most two actions in each Alert: one primary and one subtle. +/// An `Alert` consists of a title, description, icon, optional custom content and at most two actions. /// /// ```swift -/// Alert("Alert", description: "Description") { -/// customContent -/// } buttons: { +/// Alert("Alert") { /// Button("Primary") { /* */ } /// Button("Secondary") { /* */ } /// } -/// .status(.warning) +/// ``` +/// +/// ### Customizing appearance +/// +/// The title and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// A default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// Alert("Alert", description: "Please check your visa") +/// .status(.warning) /// ``` /// -/// The button priority can be overridden by using `buttonPriority()` modifier. +/// The automatic button priority can be overridden by ``buttonPriority(_:)`` modifier: /// /// ```swift /// Alert("Alert") { -/// customContent +/// content /// } buttons: { /// Button("Secondary Only") { /* */ } /// .buttonPriority(.secondary) /// } /// ``` /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/alert/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// For compact variant, use ``AlertInline`` component. +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by native `fixedSize()` or ``idealSize()`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/alert/) public struct Alert: View { private let title: String @@ -56,7 +64,7 @@ public struct Alert: View { public extension Alert { - /// Creates Orbit Alert component. + /// Creates Orbit ``Alert`` component. init( _ title: String = "", description: String = "", @@ -73,7 +81,7 @@ public extension Alert { } } - /// Creates Orbit Alert component with no buttons. + /// Creates Orbit ``Alert`` component with no buttons. init( _ title: String = "", description: String = "", @@ -89,7 +97,7 @@ public extension Alert { } } - /// Creates Orbit Alert component with custom content and icon. + /// Creates Orbit ``Alert`` component with custom content and icon. init( _ title: String = "", description: String = "", diff --git a/Sources/Orbit/Components/AlertInline.swift b/Sources/Orbit/Components/AlertInline.swift index 33807c5ac36..1938660a418 100644 --- a/Sources/Orbit/Components/AlertInline.swift +++ b/Sources/Orbit/Components/AlertInline.swift @@ -1,12 +1,34 @@ import SwiftUI -/// Breaks the main user flow to present information. +/// Orbit component that breaks the main user flow to present information. /// -/// There are times when just simple information isn’t enough and the user needs -/// to take additional steps to resolve the problem or get additional details. +/// An `AlertInline` (an inline variant of ``Alert``) consists of a title, icon and a single action. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/alert/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// ```swift +/// AlertInline("Alert") { +/// Button("Primary") { /* */ } +/// } +/// ``` +/// +/// ### Customizing appearance +/// +/// The title and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// A default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// AlertInline("Alert") { +/// Button("Primary") { /* */ } +/// } +/// .status(.warning) +/// ``` +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by native `fixedSize()` or ``idealSize()`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/alert/) public struct AlertInline: View { private let title: String @@ -28,7 +50,7 @@ public struct AlertInline: View { public extension AlertInline { - /// Creates Orbit AlertInline component. + /// Creates Orbit ``AlertInline`` component. init( _ title: String = "", icon: Icon.Symbol? = nil, @@ -40,7 +62,7 @@ public extension AlertInline { } } - /// Creates Orbit AlertInline component with custom content and icon. + /// Creates Orbit ``AlertInline`` component with custom content and icon. init( _ title: String = "", isSubtle: Bool = false, diff --git a/Sources/Orbit/Components/Badge.swift b/Sources/Orbit/Components/Badge.swift index 6f9cd435c6e..9c5c7d7e2fd 100644 --- a/Sources/Orbit/Components/Badge.swift +++ b/Sources/Orbit/Components/Badge.swift @@ -1,11 +1,26 @@ import SwiftUI -/// Presents users with short, relevant information. +/// Orbit component that displays non-actionable, short and static information. /// -/// Badges are indicators of static information. -/// They can be updated when a status changes, but they should not be actionable. +/// A `Badge` consists of a title and up to two icons. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/badge/) +/// ```swift +/// Badge("Label", icon: .grid, type: .lightInverted) +/// ``` +/// +/// ### Customizing appearance +/// +/// The label and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// When a type is set to ``BadgeType/status(_:inverted:)`` with a `nil` value, the default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// Badge("Label", type: .status(nil)) +/// .status(.warning) +/// ``` +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/badge/) public struct Badge: View, PotentiallyEmptyView { @Environment(\.backgroundShape) private var backgroundShape @@ -47,7 +62,7 @@ public struct Badge: View, PotentiallyEmp } } - @ViewBuilder var resolvedBackground: some View { + @ViewBuilder private var resolvedBackground: some View { if let backgroundShape { backgroundShape.inactiveView } else { @@ -55,11 +70,15 @@ public struct Badge: View, PotentiallyEmp } } - var resolvedLabelColor: Color { + var isEmpty: Bool { + leadingIcon.isEmpty && label.isEmpty && trailingIcon.isEmpty + } + + private var resolvedLabelColor: Color { textColor ?? labelColor } - var labelColor: Color { + private var labelColor: Color { switch type { case .light: return .inkDark case .lightInverted: return .whiteNormal @@ -69,7 +88,7 @@ public struct Badge: View, PotentiallyEmp } } - var defaultBackgroundColor: Color { + private var defaultBackgroundColor: Color { switch type { case .light: return .whiteDarker case .lightInverted: return .inkDark @@ -79,15 +98,11 @@ public struct Badge: View, PotentiallyEmp } } - var minTextWidth: CGFloat { + private var minTextWidth: CGFloat { Text.Size.small.lineHeight * sizeCategory.ratio - .xSmall } - var isEmpty: Bool { - leadingIcon.isEmpty && label.isEmpty && trailingIcon.isEmpty - } - - var defaultStatus: Status { + private var defaultStatus: Status { status ?? .info } } @@ -95,10 +110,7 @@ public struct Badge: View, PotentiallyEmp // MARK: - Inits public extension Badge { - /// Creates Orbit Badge component. - /// - /// - Parameters: - /// - type: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + /// Creates Orbit ``Badge`` component. init( _ label: String = "", icon: Icon.Symbol? = nil, @@ -112,10 +124,7 @@ public extension Badge { } } - /// Creates Orbit Badge component with custom icons. - /// - /// - Parameters: - /// - style: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + /// Creates Orbit ``Badge`` component with custom icons. init( _ label: String = "", type: BadgeType = .neutral, diff --git a/Sources/Orbit/Components/BadgeList.swift b/Sources/Orbit/Components/BadgeList.swift index a94ca280b15..b8146c5cb49 100644 --- a/Sources/Orbit/Components/BadgeList.swift +++ b/Sources/Orbit/Components/BadgeList.swift @@ -1,19 +1,34 @@ import SwiftUI -/// Presents a list of short details with added visual information. +/// Orbit component that displays non-actionable, short details with added visual information. /// -/// The items in the list should all be static information, *not* actionable. +/// A `BadgeList` consists of a description and icon. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/information/badgelist/) +/// ```swift +/// BadgeList("You must collect your baggage", icon: .baggage) +/// ``` +/// +/// ### Customizing appearance +/// +/// The label color can be modified by ``textColor(_:)``. +/// +/// When a type is set to ``BadgeListType/status(_:)`` with a `nil` value, the default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// BadgeList("Does not include guarantee", type: .status(nil)) +/// .status(.warning) +/// ``` +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/information/badgelist/) public struct BadgeList: View, PotentiallyEmptyView { @Environment(\.status) private var status @Environment(\.textAccentColor) private var textAccentColor @Environment(\.textColor) private var textColor - let type: BadgeListType - @ViewBuilder let icon: Icon - @ViewBuilder let content: Content + private let type: BadgeListType + @ViewBuilder private let icon: Icon + @ViewBuilder private let content: Content public var body: some View { if isEmpty == false { @@ -32,7 +47,7 @@ public struct BadgeList: View, PotentiallyEmptyView { } } - @ViewBuilder var badge: some View { + @ViewBuilder private var badge: some View { if icon.isEmpty { Orbit.Icon(.grid) .iconSize(.small) @@ -42,14 +57,18 @@ public struct BadgeList: View, PotentiallyEmptyView { } } - @ViewBuilder var badgeBackground: some View { + @ViewBuilder private var badgeBackground: some View { if icon.isEmpty == false { backgroundColor .clipShape(Circle()) } } + + var isEmpty: Bool { + content.isEmpty && icon.isEmpty + } - public var iconColor: Color { + private var iconColor: Color { switch type { case .neutral: return .inkNormal case .status(let status): return (status ?? defaultStatus).color @@ -57,7 +76,7 @@ public struct BadgeList: View, PotentiallyEmptyView { } } - public var backgroundColor: Color { + private var backgroundColor: Color { switch type { case .neutral: return .cloudLight case .status(let status): return (status ?? defaultStatus).lightColor @@ -65,22 +84,15 @@ public struct BadgeList: View, PotentiallyEmptyView { } } - var defaultStatus: Status { + private var defaultStatus: Status { status ?? .info } - - var isEmpty: Bool { - content.isEmpty && icon.isEmpty - } } // MARK: - Inits public extension BadgeList { - /// Creates Orbit BadgeList component. - /// - /// - Parameters: - /// - type: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + /// Creates Orbit ``BadgeList`` component. init( _ label: String = "", icon: Icon.Symbol? = nil, @@ -92,10 +104,7 @@ public extension BadgeList { } } - /// Creates Orbit BadgeList component with custom icon. - /// - /// - Parameters: - /// - type: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + /// Creates Orbit ``BadgeList`` component with custom icon. init( _ label: String = "", type: BadgeListType = .neutral, diff --git a/Sources/Orbit/Components/Button.swift b/Sources/Orbit/Components/Button.swift index 0ad340a9a7c..bbd3ee2ef74 100644 --- a/Sources/Orbit/Components/Button.swift +++ b/Sources/Orbit/Components/Button.swift @@ -1,9 +1,37 @@ import SwiftUI -/// Displays a single important action a user can take. +/// Orbit component that displays a primary control that initiates an action. A counterpart of the native `SwiftUI.Button`. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/button/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// A `Button` consists of a label and up to two icons. +/// +/// ```swift +/// Button("Continue", icon: .chevronForward) { +/// // Action +/// } +/// ``` +/// +/// ### Customizing appearance +/// +/// The label and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// When a type is set to ``ButtonType/status(_:isSubtle:)`` with a `nil` value, the default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// Button("Delete", type: .status(nil)) { +/// // Action +/// } +/// .status(.critical) +/// ``` +/// +/// Before the action is triggered, a relevant haptic feedback, based on the `Button` type, is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by the native `fixedSize()` or ``idealSize()`` modifier. +/// The default ``ButtonSize/regular`` size can be modified by a ``buttonSize(_:)`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/button/) public struct Button: View, PotentiallyEmptyView { @Environment(\.suppressButtonStyle) private var suppressButtonStyle @@ -47,12 +75,7 @@ public struct Button: View, PotentiallyEm // MARK: - Inits public extension Button { - /// Creates Orbit Button component. - /// - /// Button size can be specified using `.buttonSize()` modifier. - /// - /// - Parameters: - /// - type: A visual style of component. A style can be optionally modified using `status()` modifier when `nil` status value is provided. + /// Creates Orbit ``Button`` component. init( _ label: String = "", icon: Icon.Symbol? = nil, @@ -69,12 +92,7 @@ public extension Button { } } - /// Creates Orbit Button component with custom icons. - /// - /// Button size can be specified using `.buttonSize()` modifier. - /// - /// - Parameters: - /// - type: A visual style of component. A style can be optionally modified using `status()` modifier when `nil` status value is provided. + /// Creates Orbit ``Button`` component with custom icons. init( _ label: String = "", type: ButtonType = .primary, diff --git a/Sources/Orbit/Components/ButtonLink.swift b/Sources/Orbit/Components/ButtonLink.swift index 9e50f69d5de..1daf2109995 100644 --- a/Sources/Orbit/Components/ButtonLink.swift +++ b/Sources/Orbit/Components/ButtonLink.swift @@ -1,8 +1,37 @@ import SwiftUI -/// Displays a single, less important action a user can take. +/// Orbit component that displays a less important control that initiates an action. A counterpart of the native `SwiftUI.Button`. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/buttonlink/) +/// A `ButtonLink` consists of a label and up to two icons. +/// +/// ```swift +/// ButtonLink("Edit", icon: .edit) { +/// // Action +/// } +/// ``` +/// +/// ### Customizing appearance +/// +/// The icon color can be modified by ``iconColor(_:)`` modifier. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// When a type is set to ``ButtonLinkType/status(_:)`` with a `nil` value, the default ``Status/info`` status can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// ButtonLink("Delete", type: .status(nil)) { +/// // Action +/// } +/// .status(.critical) +/// ``` +/// +/// Before the action is triggered, a relevant haptic feedback, based on the `ButtonLink` type, is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by the native `fixedSize()` or ``idealSize()`` modifier or by specifying the ``ButtonSize/compact`` size. +/// The default ``ButtonSize/regular`` size can be modified by a ``buttonSize(_:)`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/buttonlink/) public struct ButtonLink: View, PotentiallyEmptyView { @Environment(\.suppressButtonStyle) var suppressButtonStyle @@ -30,7 +59,7 @@ public struct ButtonLink: View, Potential } } - @ViewBuilder var button: some View { + @ViewBuilder private var button: some View { SwiftUI.Button() { action() } label: { @@ -46,12 +75,7 @@ public struct ButtonLink: View, Potential // MARK: - Inits public extension ButtonLink { - /// Creates Orbit ButtonLink component. - /// - /// Button size can be specified using `.buttonSize()` modifier. - /// - /// - Parameters: - /// - type: A visual style of component. A style can be optionally modified using `status()` modifier when `nil` status value is provided. + /// Creates Orbit ``ButtonLink`` component. init( _ label: String = "", type: ButtonLinkType = .primary, @@ -68,12 +92,7 @@ public extension ButtonLink { } } - /// Creates Orbit ButtonLink component with custom icons. - /// - /// Button size can be specified using `.buttonSize()` modifier. - /// - /// - Parameters: - /// - type: A visual style of component. A style can be optionally modified using `status()` modifier when `nil` status value is provided. + /// Creates Orbit ``ButtonLink`` component with custom icons. init( _ label: String = "", type: ButtonLinkType = .primary, @@ -113,7 +132,7 @@ struct ButtonLinkPreviews: PreviewProvider { static var standalone: some View { VStack(spacing: 0) { - ButtonLink("ButtonLink", action: {}) + ButtonLink("ButtonLink", icon: .grid, action: {}) .buttonSize(.regular) ButtonLink("ButtonLink", type: .critical, action: {}) .buttonSize(.regular) diff --git a/Sources/Orbit/Components/Card.swift b/Sources/Orbit/Components/Card.swift index ad924d29fbe..b952f7dea63 100644 --- a/Sources/Orbit/Components/Card.swift +++ b/Sources/Orbit/Components/Card.swift @@ -1,25 +1,42 @@ import SwiftUI -/// Separates content into sections. +/// Orbit component that separates content into sections. /// -/// Card is a wrapping component around a custom content. +/// A `Card` consists of a title, description, optional action and a custom content. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/card/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// ```swift +/// Card("Card", description: "Description") { +/// content1 +/// content2 +/// } +/// ``` +/// +/// ### Customizing appearance +/// +/// The label color can be modified by ``textColor(_:)`` modifier. +/// +/// The default background can be overridden by ``backgroundStyle(_:)-9odue`` modifier. +/// +/// ### Layout +/// +/// The component automatically adds a vertical stack over the provided content. +/// Component expands horizontally unless prevented by native `fixedSize()` or ``idealSize()`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/card/) public struct Card: View { @Environment(\.backgroundShape) private var backgroundShape @Environment(\.idealSize) private var idealSize - let title: String - let description: String - let action: CardAction - let headerSpacing: CGFloat - let contentLayout: CardContentLayout - let contentAlignment: HorizontalAlignment - let showBorder: Bool - let titleStyle: Heading.Style - @ViewBuilder let content: Content + private let title: String + private let description: String + private let action: CardAction + private let headerSpacing: CGFloat + private let contentLayout: CardContentLayout + private let contentAlignment: HorizontalAlignment + private let showBorder: Bool + private let titleStyle: Heading.Style + @ViewBuilder private let content: Content public var body: some View { VStack(alignment: .leading, spacing: headerSpacing) { @@ -43,7 +60,7 @@ public struct Card: View { .accessibilityElement(children: .contain) } - @ViewBuilder var header: some View { + @ViewBuilder private var header: some View { if isHeaderEmpty == false { HStack(alignment: .top, spacing: 0) { VStack(alignment: .leading, spacing: .xxSmall) { @@ -77,7 +94,7 @@ public struct Card: View { } } - @ViewBuilder var resolvedBackground: some View { + @ViewBuilder private var resolvedBackground: some View { if let backgroundShape { backgroundShape.inactiveView } else { @@ -85,7 +102,7 @@ public struct Card: View { } } - var isHeaderEmpty: Bool { + private var isHeaderEmpty: Bool { if case .none = action, title.isEmpty, description.isEmpty { return true } else { @@ -93,11 +110,11 @@ public struct Card: View { } } - var isContentEmpty: Bool { + private var isContentEmpty: Bool { content is EmptyView } - var contentPadding: CGFloat { + private var contentPadding: CGFloat { switch contentLayout { case .fill: return 0 case .default: return .medium @@ -105,7 +122,7 @@ public struct Card: View { } } - var contentSpacing: CGFloat { + private var contentSpacing: CGFloat { switch contentLayout { case .fill: return 0 case .default(let spacing): return spacing @@ -117,7 +134,7 @@ public struct Card: View { // MARK: - Inits public extension Card { - /// Creates Orbit Card component. + /// Creates Orbit ``Card`` component. init( _ title: String = "", description: String = "", diff --git a/Sources/Orbit/Components/CarrierLogo.swift b/Sources/Orbit/Components/CarrierLogo.swift index 8dd5f50f0e4..06331b13644 100644 --- a/Sources/Orbit/Components/CarrierLogo.swift +++ b/Sources/Orbit/Components/CarrierLogo.swift @@ -1,6 +1,6 @@ import SwiftUI -/// Displays logos of transport carriers. +/// Orbit component that displays one or more logos of transport carriers. /// /// Carrier logos can include up to four logos at once. With one logo, by default it occupies the entire space. /// With multiple logos, the logos are shrunk to the same size (no matter how many more there are). @@ -9,98 +9,104 @@ import SwiftUI /// they’re in the top left and bottom right. With three, the second logo shifts to the bottom left /// and the third is present in the top right. With four, the logos take up all four corners. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/visuals/carrierlogo/) +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/visuals/carrierlogo/) public struct CarrierLogo: View { - struct SingleCarrierImage: View { - - let image: Image - - init(_ image: Image) { - self.image = image - } - - var body: some View { - image - .resizable() - .cornerRadius(BorderRadius.desktop) - } - } - - let images: [Image] - let size: Icon.Size + private let images: [Image] + private let size: Icon.Size public var body: some View { content .frame(width: size.value, height: size.value) } - @ViewBuilder var content: some View { + @ViewBuilder private var content: some View { switch images.count { case 0: EmptyView() - case 1: SingleCarrierImage(images[0]) + case 1: SingleCarrierImage(image: images[0]) case 2: twoImages case 3: threeImages default: fourImages } } - var twoImages: some View { + @ViewBuilder private var twoImages: some View { VStack(spacing: 0) { HStack(spacing: 0) { - SingleCarrierImage(images[0]) + SingleCarrierImage(image: images[0]) Color.clear } HStack(spacing: 0) { Color.clear - SingleCarrierImage(images[1]) + SingleCarrierImage(image: images[1]) } } } - var threeImages: some View { - VStack(spacing: 2) { - HStack(spacing: 2) { - SingleCarrierImage(images[0]) - SingleCarrierImage(images[2]) + @ViewBuilder private var threeImages: some View { + VStack(spacing: .xxxSmall) { + HStack(spacing: .xxxSmall) { + SingleCarrierImage(image: images[0]) + SingleCarrierImage(image: images[2]) } - HStack(spacing: 2) { - SingleCarrierImage(images[1]) + HStack(spacing: .xxxSmall) { + SingleCarrierImage(image: images[1]) Color.clear } } } - var fourImages: some View { - VStack(spacing: 2) { - HStack(spacing: 2) { - SingleCarrierImage(images[0]) - SingleCarrierImage(images[2]) + @ViewBuilder private var fourImages: some View { + VStack(spacing: .xxxSmall) { + HStack(spacing: .xxxSmall) { + SingleCarrierImage(image: images[0]) + SingleCarrierImage(image: images[2]) } - HStack(spacing: 2) { - SingleCarrierImage(images[1]) - SingleCarrierImage(images[3]) + HStack(spacing: .xxxSmall) { + SingleCarrierImage(image: images[1]) + SingleCarrierImage(image: images[3]) } } } +} + +// MARK: - Inits +public extension CarrierLogo { - /// Creates an Orbit `CarrierLogo` component with a single logo image. + /// Creates an Orbit ``CarrierLogo`` component with a single logo image. + /// /// - Parameters: /// - image: a logo image. /// - size: the size of the view. The image will occupy the whole view. - public init(image: Image, size: Icon.Size) { + init(image: Image, size: Icon.Size) { self.images = [image] self.size = size } - /// Creates an Orbit `CarrierLogo` component with multiple images. + /// Creates an Orbit ``CarrierLogo`` component with multiple images. + /// /// - Parameter images: logo images to show in the view. - public init(images: [Image]) { + init(images: [Image]) { self.images = images self.size = .large } } +// MARK: - Types +private extension CarrierLogo { + + struct SingleCarrierImage: View { + + let image: Image + + var body: some View { + image + .resizable() + .cornerRadius(BorderRadius.desktop) + } + } +} + struct CarrierLogoPreviews: PreviewProvider { static let square = Image(systemName: "square.fill") diff --git a/Sources/Orbit/Components/Checkbox.swift b/Sources/Orbit/Components/Checkbox.swift index 1455d5fdcfc..b4f921a2ce3 100644 --- a/Sources/Orbit/Components/Checkbox.swift +++ b/Sources/Orbit/Components/Checkbox.swift @@ -1,20 +1,43 @@ import SwiftUI -/// Enables users to pick multiple options from a group. +/// Orbit input component that displays a selectable option to pick from a multiple selectable options. A counterpart of the native `SwiftUI.Toggle` with `checkbox` style applied. /// -/// Can be also used to display just the checkbox with no label or description. +/// A `Checkbox` consists of a title, description and the checkbox indicator. +/// +/// ```swift +/// Checkbox("Free", isChecked: $isFree) +/// ``` +/// +/// The component can be used as a standalone control by omitting the title and description: +/// +/// ```swift +/// Checkbox(isChecked: $isFree) +/// ``` +/// +/// The component can be disabled by ``disabled(_:)`` modifier: /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/checkbox/) +/// ```swift +/// Checkbox(isChecked: $isFree) +/// .disabled() +/// ``` +/// +/// Before the selection is changed, a haptic feedback is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Customizing appearance +/// +/// The label color can be modified by ``textColor(_:)`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/checkbox/) public struct Checkbox: View { - @Environment(\.isEnabled) var isEnabled - @Environment(\.textColor) var textColor + @Environment(\.isEnabled) private var isEnabled + @Environment(\.textColor) private var textColor @Environment(\.isHapticsEnabled) private var isHapticsEnabled - let title: String - let description: String - let state: State - @Binding var isChecked: Bool + private let title: String + private let description: String + private let state: State + @Binding private var isChecked: Bool public var body: some View { SwiftUI.Button { @@ -43,13 +66,13 @@ public struct Checkbox: View { ) } - var labelColor: Color { + private var labelColor: Color { isEnabled ? textColor ?? .inkDark : .cloudDarkHover } - var descriptionColor: Color { + private var descriptionColor: Color { isEnabled ? .inkNormal : .cloudDarkHover @@ -59,7 +82,7 @@ public struct Checkbox: View { // MARK: - Inits public extension Checkbox { - /// Creates Orbit Checkbox component. + /// Creates Orbit ``Checkbox`` component. init( _ title: String = "", description: String = "", diff --git a/Sources/Orbit/Components/ChoiceTile.swift b/Sources/Orbit/Components/ChoiceTile.swift index ab7bbd79cdd..1b7dd26e91f 100644 --- a/Sources/Orbit/Components/ChoiceTile.swift +++ b/Sources/Orbit/Components/ChoiceTile.swift @@ -1,9 +1,40 @@ import SwiftUI -/// Enables users to encapsulate radio or checkbox to pick exactly one option from a group. +/// Orbit component that displays a rich selectable option to pick from a single or multiple selection group. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/choice-tile/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// A `ChoiceTile` consists of a title, description, icon, content and a selection indicator. +/// +/// ```swift +/// ChoiceTile("Full", isSelected: $isFull) { +/// // Action +/// } content: { +/// // Content +/// } +/// ``` +/// +/// ### Customizing appearance +/// +/// The title and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// The default background can be overridden by ``backgroundStyle(_:)-9odue`` modifier. +/// +/// A ``Status`` can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// ChoiceTile("Not available") { +/// // Action +/// } +/// .status(.critical) +/// ``` +/// +/// Before the action is triggered, a haptic feedback is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by the native `fixedSize()` or ``idealSize()`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/choice-tile/) public struct ChoiceTile: View { @Environment(\.backgroundShape) private var backgroundShape @@ -11,22 +42,20 @@ public struct ChoiceTile Void - @ViewBuilder let content: Content - @ViewBuilder let icon: Icon - @ViewBuilder let header: Header - @ViewBuilder let illustration: Illustration + private let title: String + private let description: String + private let badgeOverlay: String + private let indicator: ChoiceTileIndicator + private let titleStyle: Heading.Style + private let isSelected: Bool + private let isError: Bool + private let message: Message? + private let alignment: ChoiceTileAlignment + private let action: () -> Void + @ViewBuilder private let content: Content + @ViewBuilder private let icon: Icon + @ViewBuilder private let header: Header + @ViewBuilder private let illustration: Illustration public var body: some View { SwiftUI.Button { @@ -37,7 +66,7 @@ public struct ChoiceTile: View { @Environment(\.backgroundShape) private var backgroundShape @@ -10,8 +29,8 @@ public struct NotificationBadge: View { @Environment(\.sizeCategory) private var sizeCategory @Environment(\.textColor) private var textColor - private let type: BadgeType @ViewBuilder private let content: Content + private let type: BadgeType public var body: some View { if isEmpty == false { @@ -29,7 +48,7 @@ public struct NotificationBadge: View { } - @ViewBuilder var resolvedBackground: some View { + @ViewBuilder private var resolvedBackground: some View { if let backgroundShape { backgroundShape.inactiveView } else { @@ -37,7 +56,7 @@ public struct NotificationBadge: View { } } - var defaultBackgroundColor: Color { + private var defaultBackgroundColor: Color { switch type { case .light: return .whiteDarker case .lightInverted: return .inkDark @@ -47,7 +66,7 @@ public struct NotificationBadge: View { } } - @ViewBuilder var background: some View { + @ViewBuilder private var background: some View { switch type { case .light: Color.whiteDarker case .lightInverted: Color.inkDark @@ -57,11 +76,11 @@ public struct NotificationBadge: View { } } - var resolvedTextColor: Color { + private var resolvedTextColor: Color { textColor ?? labelColor } - var labelColor: Color { + private var labelColor: Color { switch type { case .light: return .inkDark case .lightInverted: return .whiteNormal @@ -71,34 +90,28 @@ public struct NotificationBadge: View { } } - var minWidth: CGFloat { + private var minWidth: CGFloat { Text.Size.small.lineHeight * sizeCategory.ratio } - var defaultStatus: Status { + private var defaultStatus: Status { status ?? .info } +} - /// Creates Orbit NotificationBadge component with custom content. - /// - /// - Parameters: - /// - type: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. - public init( +// MARK: - Inits +public extension NotificationBadge { + + /// Creates Orbit ``NotificationBadge`` component with custom content. + init( type: BadgeType = .status(nil), @ViewBuilder content: () -> Content ) { self.type = type self.content = content() } -} - -// MARK: - Inits -public extension NotificationBadge { - - /// Creates Orbit NotificationBadge component containing text. - /// - /// - Parameters: - /// - style: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + + /// Creates Orbit ``NotificationBadge`` component containing text. init( _ label: String, type: BadgeType = .status(nil) @@ -110,10 +123,7 @@ public extension NotificationBadge { } } - /// Creates Orbit NotificationBadge component containing icon. - /// - /// - Parameters: - /// - style: A visual style of component. A `status` style can be optionally modified using `status()` modifier when `nil` value is provided. + /// Creates Orbit ``NotificationBadge`` component containing icon. init( _ icon: Icon.Symbol, type: BadgeType = .status(nil) diff --git a/Sources/Orbit/Components/Radio.swift b/Sources/Orbit/Components/Radio.swift index 531a5919312..71de59637aa 100644 --- a/Sources/Orbit/Components/Radio.swift +++ b/Sources/Orbit/Components/Radio.swift @@ -1,20 +1,43 @@ import SwiftUI -/// Enables users to pick exactly one option from a group. +/// Orbit input component that displays a single selectable option to pick from a group. A counterpart of the native `SwiftUI.Picker` with `radioGroup` style applied. /// -/// Can be also used to display just the radio rounded indicator. +/// A `Radio` consists of a title, description and the radio indicator. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/radio/) +/// ```swift +/// Radio("Free", isChecked: $isFree) +/// ``` +/// +/// The component can be used as a standalone control by omitting the title and description: +/// +/// ```swift +/// Radio(isChecked: $isFree) +/// ``` +/// +/// The component can be disabled by ``disabled(_:)`` modifier: +/// +/// ```swift +/// Radio(isChecked: $isFree) +/// .disabled() +/// ``` +/// +/// Before the selection is changed, a haptic feedback is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Customizing appearance +/// +/// The label color can be modified by ``textColor(_:)`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/radio/) public struct Radio: View { @Environment(\.isEnabled) private var isEnabled @Environment(\.textColor) private var textColor @Environment(\.isHapticsEnabled) private var isHapticsEnabled - let title: String - let description: String - let state: State - @Binding var isChecked: Bool + private let title: String + private let description: String + private let state: State + @Binding private var isChecked: Bool public var body: some View { SwiftUI.Button { @@ -43,13 +66,13 @@ public struct Radio: View { ) } - var labelColor: Color { + private var labelColor: Color { isEnabled ? textColor ?? .inkDark : .cloudDarkHover } - var descriptionColor: Color { + private var descriptionColor: Color { isEnabled ? .inkNormal : .cloudDarkHover @@ -59,7 +82,7 @@ public struct Radio: View { // MARK: - Inits public extension Radio { - /// Creates Orbit Radio component. + /// Creates Orbit ``Radio`` component. init( _ title: String = "", description: String = "", diff --git a/Sources/Orbit/Components/Tile.swift b/Sources/Orbit/Components/Tile.swift index 22d0f6b4d52..2defb189ef4 100644 --- a/Sources/Orbit/Components/Tile.swift +++ b/Sources/Orbit/Components/Tile.swift @@ -1,11 +1,42 @@ import SwiftUI -/// Groups actionable content to make it easy to scan. +/// Orbit component that displays an option to pick from a group. /// -/// Can be used standalone or wrapped inside a ``TileGroup``. +/// A `Tile` consists of a title, description, icon and content. /// -/// - Note: [Orbit definition](https://orbit.kiwi/components/tile/) -/// - Important: Component expands horizontally unless prevented by `fixedSize` or `idealSize` modifier. +/// ```swift +/// Tile("Profile", icon: .user) { +/// // Action +/// } content: { +/// // Content +/// } +/// ``` +/// +/// A `Tile` can be used both standalone or wrapped in a ``TileGroup``. +/// +/// ### Customizing appearance +/// +/// The title and icon colors can be modified by ``textColor(_:)`` and ``iconColor(_:)`` modifiers. +/// The icon size can be modified by ``iconSize(custom:)`` modifier. +/// +/// The default background can be overridden by ``backgroundStyle(_:)-9odue`` modifier. +/// +/// A ``Status`` can be modified by ``status(_:)`` modifier: +/// +/// ```swift +/// Tile("Not available") { +/// // Action +/// } +/// .status(.critical) +/// ``` +/// +/// Before the action is triggered, a haptic feedback is fired via ``HapticsProvider/sendHapticFeedback(_:)``. +/// +/// ### Layout +/// +/// Component expands horizontally unless prevented by the native `fixedSize()` or ``idealSize()`` modifier. +/// +/// - Note: [Orbit.kiwi documentation](https://orbit.kiwi/components/tile/) public struct Tile: View { @Environment(\.idealSize) private var idealSize @@ -40,7 +71,7 @@ public struct Tile: View { .accessibility(addTraits: .isButton) } - @ViewBuilder var buttonContent: some View { + @ViewBuilder private var buttonContent: some View { HStack(spacing: 0) { VStack(alignment: .leading, spacing: 0) { header @@ -61,7 +92,7 @@ public struct Tile: View { .overlay(separator, alignment: .init(horizontal: .listRowSeparatorLeading, vertical: .bottom)) } - @ViewBuilder var header: some View { + @ViewBuilder private var header: some View { if isHeaderEmpty == false { HStack(alignment: .top, spacing: .xSmall) { icon @@ -87,14 +118,14 @@ public struct Tile: View { } } - @ViewBuilder var customContentButtonLinkOverlay: some View { + @ViewBuilder private var customContentButtonLinkOverlay: some View { if isHeaderEmpty { inactiveButtonLink .padding(.medium) } } - @ViewBuilder var inactiveButtonLink: some View { + @ViewBuilder private var inactiveButtonLink: some View { switch disclosure { case .none, .icon: EmptyView() @@ -108,7 +139,7 @@ public struct Tile: View { } } - @ViewBuilder var disclosureIcon: some View { + @ViewBuilder private var disclosureIcon: some View { switch disclosure { case .none, .buttonLink: EmptyView() @@ -121,17 +152,17 @@ public struct Tile: View { } } - @ViewBuilder var separator: some View { + @ViewBuilder private var separator: some View { if isInsideTileGroup, isTileSeparatorVisible { Separator() } } - var tileBorderStyle: TileBorderStyle { + private var tileBorderStyle: TileBorderStyle { showBorder && isInsideTileGroup == false ? .default : .none } - var isHeaderEmpty: Bool { + private var isHeaderEmpty: Bool { title.isEmpty && description.isEmpty && icon.isEmpty } } @@ -139,7 +170,7 @@ public struct Tile: View { // MARK: - Inits public extension Tile { - /// Creates Orbit Tile component. + /// Creates Orbit ``Tile`` component. init( _ title: String = "", description: String = "", @@ -167,7 +198,7 @@ public extension Tile { } } - /// Creates Orbit Tile component with custom icon. + /// Creates Orbit ``Tile`` component with custom icon. init( _ title: String = "", description: String = "", diff --git a/Sources/Orbit/Support/Environment Keys/BackgroundShapeKey.swift b/Sources/Orbit/Support/Environment Keys/BackgroundShapeKey.swift index c4359f120f6..e1273a8761c 100644 --- a/Sources/Orbit/Support/Environment Keys/BackgroundShapeKey.swift +++ b/Sources/Orbit/Support/Environment Keys/BackgroundShapeKey.swift @@ -44,18 +44,18 @@ public extension View { /// Set the inactive and active background shape styles for supported Orbit components within the view hierarchy. /// - /// To restore the default background style, set the `backgroundShape` environment value to nil using the environment(_:_:) modifer. + /// To restore the default background style, set the `backgroundShape` environment value to nil using the `environment(_:_:)` modifer. /// /// - Parameters: /// - shape: A `Color` or a `LinearGradient` that will be used in supported Orbit components such as `Card` or `Badge` as a background style. - /// - shape: A `Color` or a `LinearGradient` that will be used in supported touchable Orbit components such as `Tile` as inactive and active background style. + /// - active: A `Color` or a `LinearGradient` that will be used in supported touchable Orbit components such as `Tile` as active background style. func backgroundStyle(_ shape: any ShapeStyle, active: any ShapeStyle) -> some View { environment(\.backgroundShape, .init(inactive: shape, active: active)) } /// Set the background shape style for supported Orbit components within the view hierarchy. /// - /// To restore the default background style, set the `backgroundShape` environment value to nil using the environment(_:_:) modifer. + /// To restore the default background style, set the `backgroundShape` environment value to nil using the `environment(_:_:)` modifer. /// /// - Parameters: /// - shape: A `Color` or a `LinearGradient` that will be used in supported Orbit components such as `Card` or `Badge` as a background style. diff --git a/Sources/Orbit/Support/Environment Keys/IdealSizeKey.swift b/Sources/Orbit/Support/Environment Keys/IdealSizeKey.swift index eee4e2f81d1..68f3d642b7c 100644 --- a/Sources/Orbit/Support/Environment Keys/IdealSizeKey.swift +++ b/Sources/Orbit/Support/Environment Keys/IdealSizeKey.swift @@ -1,5 +1,6 @@ import SwiftUI +/// The expanding behaviour of Orbit components in a view relative to their ideal size for each axis. public struct IdealSizeValue { public var horizontal: Bool? public var vertical: Bool? @@ -11,6 +12,7 @@ struct IdealSizeKey: EnvironmentKey { public extension EnvironmentValues { + /// The expanding behaviour of Orbit components in a view relative to their ideal size. var idealSize: IdealSizeValue { get { self[IdealSizeKey.self] } set { self[IdealSizeKey.self] = newValue } @@ -19,18 +21,21 @@ public extension EnvironmentValues { public extension View { - /// Sets expanding behaviour of view relative to its ideal size in specified direction. - /// For specified axis, a value of `true` will prevent view from expending beyond its ideal size, - /// while a value of `false` will force view to expand to infinity. + /// Sets the expanding behaviour of Orbit components in a view relative to their ideal size in specified direction. + /// + /// For specified axis, a value of `true` will prevent component from expending beyond its ideal size, + /// while a value of `false` will force component to expand to infinity. A value of `nil` keeps the default behaviour. /// - /// To fix the view exactly to the ideal size, use `fixedSize` modifier instead. + /// - Note: To fix the view exactly to the ideal size, use `fixedSize` modifier instead. func idealSize(horizontal: Bool? = nil, vertical: Bool? = nil) -> some View { environment(\.idealSize, .init(horizontal: horizontal, vertical: vertical)) } - /// Prevents view from additionally expanding beyond its ideal size in both axis. + /// Prevents Orbit component from additionally expanding beyond its ideal size in both axis. /// - /// To fix the view exactly to the ideal size, use `fixedSize` modifier instead. + /// To achieve better control over separate axis and behaviour, use ``idealSize(horizontal:vertical:)`` modifier. + /// + /// - Note: To fix the view exactly to the ideal size, use `fixedSize` modifier instead. func idealSize() -> some View { idealSize(horizontal: true, vertical: true) } diff --git a/Sources/Orbit/Support/HapticsProvider.swift b/Sources/Orbit/Support/HapticsProvider.swift index 3c6e5dede38..7e470e7d778 100644 --- a/Sources/Orbit/Support/HapticsProvider.swift +++ b/Sources/Orbit/Support/HapticsProvider.swift @@ -1,5 +1,9 @@ import UIKit +import SwiftUI +/// Orbit haptics feedback provider. +/// +/// Orbit haptics feedback can be disabled by ``SwiftUI/View/hapticsDisabled(_:)``. public enum HapticsProvider { public enum HapticFeedbackType { diff --git a/Sources/Orbit/Support/Status.swift b/Sources/Orbit/Support/Status.swift index 05cd802b214..3a45751592c 100644 --- a/Sources/Orbit/Support/Status.swift +++ b/Sources/Orbit/Support/Status.swift @@ -1,6 +1,6 @@ import SwiftUI -/// Non-default status of a component. +/// Non-default status of `Orbit` component. public enum Status: Equatable { case info case success