Skip to content

Commit

Permalink
Merge pull request #862 from kiwicom/861-add-new-inkdark-button-theme
Browse files Browse the repository at this point in the history
861 add new inkdark button theme
  • Loading branch information
PavelHolec authored Nov 20, 2024
2 parents 89cde2a + 7acaeee commit f2d1cfd
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 56 deletions.
Binary file modified Snapshots/iPhone/ButtonLinkTests/testButtonLinks.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Snapshots/iPhone/ButtonTests/testButtons.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Sources/Orbit/Components/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public enum ButtonType {
case secondary
case critical
case criticalSubtle
case prominent
case status(Status?, isSubtle: Bool = false)
}

Expand Down Expand Up @@ -307,6 +308,7 @@ struct ButtonPreviews: PreviewProvider {
buttons(.secondary)
buttons(.critical)
buttons(.criticalSubtle)
buttons(.prominent)
}
.padding(.medium)
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/Orbit/Components/ButtonLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public extension ButtonLink where Label == Text, LeadingIcon == Orbit.Icon, Trai
public enum ButtonLinkType: Equatable, Sendable {
case primary
case critical
case prominent
case status(_ status: Status?)
}

Expand Down Expand Up @@ -223,10 +224,12 @@ struct ButtonLinkPreviews: PreviewProvider {
VStack(alignment: .leading, spacing: .large) {
ButtonLink("ButtonLink Primary", type: .primary, action: {})
ButtonLink("ButtonLink Critical", type: .critical, action: {})
ButtonLink("ButtonLink Prominent", type: .prominent, action: {})
}
VStack(alignment: .leading, spacing: .large) {
ButtonLink("ButtonLink Primary", icon: .accommodation, type: .primary, action: {})
ButtonLink("ButtonLink Critical", icon: .alertCircle, type: .critical, action: {})
ButtonLink("ButtonLink Prominent", icon: .alertCircle, type: .prominent, action: {})
}
}
.buttonSize(.compact)
Expand Down
3 changes: 3 additions & 0 deletions Sources/Orbit/Components/Card.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public struct Card<Title: View, Description: View, Content: View, Action: View>:
@ViewBuilder private var topTrailingAction: some View {
action
.buttonSize(.compact)
// Remove any text or background overrides
.environment(\.backgroundShape, nil)
.textColor(nil)
// Prevent the default ButtonLink from vertically expanding the header
.padding(.vertical, -.xSmall)
.accessibility(.cardAction)
Expand Down
55 changes: 30 additions & 25 deletions Sources/Orbit/Support/ButtonStyles/OrbitButtonLinkButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import SwiftUI
/// Button style for Orbit ``ButtonLink`` component.
public struct OrbitButtonLinkButtonStyle<LeadingIcon: View, TrailingIcon: View>: PrimitiveButtonStyle {

@Environment(\.backgroundShape) private var backgroundShape
@Environment(\.buttonSize) private var buttonSize
@Environment(\.idealSize) private var idealSize
@Environment(\.status) private var status
@Environment(\.textColor) private var textColor

private let type: ButtonLinkType
@ViewBuilder private let icon: LeadingIcon
Expand All @@ -28,17 +30,18 @@ public struct OrbitButtonLinkButtonStyle<LeadingIcon: View, TrailingIcon: View>:
disclosureIcon
}
.textFontWeight(.medium)
.textColor(textColor)
.backgroundStyle(.clear, active: backgroundActive)
.textColor(textColor ?? labelColor)
.backgroundStyle(backgroundShape?.inactive ?? .clear, active: backgroundShape?.active ?? backgroundActive)
.buttonSize(resolvedButtonSize)
.idealSize(horizontal: idealSizeHorizontal, vertical: idealSize.vertical)
}

private var backgroundActive: Color {
switch type {
case .primary: return .productLightActive
case .critical: return .redLightActive
case .status(let status): return (status ?? self.status)?.lightActiveColor ?? .productLightActive
case .primary: .productLightActive
case .critical: .redLightActive
case .prominent: .cloudLightActive
case .status(let status): (status ?? self.status)?.lightActiveColor ?? .productLightActive
}
}

Expand All @@ -52,62 +55,64 @@ public struct OrbitButtonLinkButtonStyle<LeadingIcon: View, TrailingIcon: View>:
: (resolvedButtonSize == .compact || idealSize.horizontal == true)
}

private var textColor: Color {
private var labelColor: Color {
switch type {
case .primary: return .productNormal
case .critical: return .redNormal
case .status(let status): return (status ?? self.status)?.color ?? .productNormal
case .primary: .productNormal
case .critical: .redNormal
case .prominent: .inkDark
case .status(let status): (status ?? self.status)?.color ?? .productNormal
}
}

private var textActiveColor: Color {
switch type {
case .primary: return .productDarkActive
case .critical: return .redDarkActive
case .status(let status): return (status ?? self.status)?.darkHoverColor ?? .productDarkActive
case .primary: .productDarkActive
case .critical: .redDarkActive
case .prominent: .inkDarkActive
case .status(let status): (status ?? self.status)?.darkHoverColor ?? .productDarkActive
}
}

private var resolvedStatus: Status {
switch type {
case .status(let status): return status ?? self.status ?? .info
default: return .info
case .status(let status): status ?? self.status ?? .info
default: .info
}
}

private var hapticFeedback: HapticsProvider.HapticFeedbackType {
switch type {
case .primary: return .light(1)
case .critical: return .notification(.error)
case .status: return resolvedStatus.defaultHapticFeedback
case .primary, .prominent: .light(1)
case .critical: .notification(.error)
case .status: resolvedStatus.defaultHapticFeedback
}
}

private var horizontalPadding: CGFloat {
switch resolvedButtonSize {
case .regular: return .small
case .compact: return 0
case .regular: .small
case .compact: 0
}
}

private var verticalPadding: CGFloat {
switch resolvedButtonSize {
case .regular: return .small // = 44 height @ normal size
case .compact: return 6 // = 32 height @ normal size
case .regular: .small // = 44 height @ normal size
case .compact: 6 // = 32 height @ normal size
}
}

private var horizontalBackgroundPadding: CGFloat {
switch resolvedButtonSize {
case .regular: return 0
case .compact: return .xSmall
case .regular: 0
case .compact: .xSmall
}
}

private var verticalBackgroundPadding: CGFloat {
switch resolvedButtonSize {
case .regular: return 0
case .compact: return .xxxSmall
case .regular: 0
case .compact: .xxxSmall
}
}

Expand Down
65 changes: 34 additions & 31 deletions Sources/Orbit/Support/ButtonStyles/OrbitButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,47 @@ public struct OrbitButtonStyle<LeadingIcon: View, TrailingIcon: View>: Primitive

private var background: Color {
switch type {
case .primary: return .productNormal
case .primarySubtle: return .productLight
case .secondary: return .cloudNormal
case .critical: return .redNormal
case .criticalSubtle: return .redLight
case .status(let status, false): return (status ?? self.status)?.color ?? .productNormal
case .status(let status, true): return (status ?? self.status)?.lightHoverColor ?? .productLight
case .primary: .productNormal
case .primarySubtle: .productLight
case .secondary: .cloudNormal
case .critical: .redNormal
case .criticalSubtle: .redLight
case .prominent: .inkDark
case .status(let status, false): (status ?? self.status)?.color ?? .productNormal
case .status(let status, true): (status ?? self.status)?.lightHoverColor ?? .productLight
}
}

private var backgroundActive: Color {
switch type {
case .primary: return .productNormalActive
case .primarySubtle: return .productLightActive
case .secondary: return .cloudNormalActive
case .critical: return .redNormalActive
case .criticalSubtle: return .redLightActive
case .status(let status, false): return (status ?? self.status)?.activeColor ?? .productNormalActive
case .status(let status, true): return (status ?? self.status)?.lightActiveColor ?? .productLightActive
case .primary: .productNormalActive
case .primarySubtle: .productLightActive
case .secondary: .cloudNormalActive
case .critical: .redNormalActive
case .criticalSubtle: .redLightActive
case .prominent: .inkDarkActive
case .status(let status, false): (status ?? self.status)?.activeColor ?? .productNormalActive
case .status(let status, true): (status ?? self.status)?.lightActiveColor ?? .productLightActive
}
}

private var labelColor: Color {
switch type {
case .primary: return .whiteNormal
case .primarySubtle: return .productDark
case .secondary: return .inkDark
case .critical: return .whiteNormal
case .criticalSubtle: return .redDark
case .status(_, false): return .whiteNormal
case .status(let status, true): return (status ?? self.status)?.darkHoverColor ?? .whiteNormal
case .primary: .whiteNormal
case .primarySubtle: .productDark
case .secondary: .inkDark
case .critical: .whiteNormal
case .criticalSubtle: .redDark
case .prominent: .whiteNormal
case .status(_, false): .whiteNormal
case .status(let status, true): (status ?? self.status)?.darkHoverColor ?? .whiteNormal
}
}

private var resolvedStatus: Status {
switch type {
case .status(let status, _): return status ?? self.status ?? .info
default: return .info
case .status(let status, _): status ?? self.status ?? .info
default: .info
}
}

Expand All @@ -80,24 +83,24 @@ public struct OrbitButtonStyle<LeadingIcon: View, TrailingIcon: View>: Primitive

private var hapticFeedback: HapticsProvider.HapticFeedbackType {
switch type {
case .primary: return .light(1)
case .primarySubtle, .secondary: return .light(0.5)
case .critical, .criticalSubtle: return .notification(.error)
case .status: return resolvedStatus.defaultHapticFeedback
case .primary, .prominent: .light(1)
case .primarySubtle, .secondary: .light(0.5)
case .critical, .criticalSubtle: .notification(.error)
case .status: resolvedStatus.defaultHapticFeedback
}
}

private var textSize: Text.Size {
switch resolvedButtonSize {
case .regular: return .normal
case .compact: return .small
case .regular: .normal
case .compact: .small
}
}

private var padding: CGFloat {
switch resolvedButtonSize {
case .regular: return .small // = 44 height @ normal size
case .compact: return .xSmall // = 32 height @ normal size
case .regular: .small // = 44 height @ normal size
case .compact: .xSmall // = 32 height @ normal size
}
}

Expand Down
1 change: 1 addition & 0 deletions Sources/OrbitStorybook/Detail/Items/StorybookButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct StorybookButton {
buttons(.secondary)
buttons(.critical)
buttons(.criticalSubtle)
buttons(.prominent)
}
.previewDisplayName()
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/OrbitStorybook/Detail/Items/StorybookButtonLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ struct StorybookButtonLink {
VStack(alignment: .leading, spacing: .large) {
ButtonLink("ButtonLink Primary", type: .primary, action: {})
ButtonLink("ButtonLink Critical", type: .critical, action: {})
ButtonLink("ButtonLink Prominent", type: .prominent, action: {})
}
VStack(alignment: .leading, spacing: .large) {
ButtonLink("ButtonLink Primary", icon: .accommodation, type: .primary, action: {})
ButtonLink("ButtonLink Critical", icon: .alertCircle, type: .critical, action: {})
ButtonLink("ButtonLink Prominent", icon: .alertCircle, type: .prominent, action: {})
}
}
.buttonSize(.compact)
Expand Down

0 comments on commit f2d1cfd

Please sign in to comment.