Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

861 add new inkdark button theme #862

Merged
merged 3 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
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
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
Loading