Skip to content
Draft
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
100 changes: 94 additions & 6 deletions AdyenUI/AdyenColors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,31 @@ internal enum DefaultColorsDark {
internal static let supportShadow = UIColor.color(hex: 0x070707)
}

package struct AdyenColors: Equatable {
// TODO: Robert: Theming: Rename this to CheckoutColors??

/// A color palette for customizing the appearance of Adyen checkout UI components.
///
/// Use `AdyenColors` to match the checkout experience with your app's brand identity.
/// All colors support both light and dark mode when using dynamic `UIColor` values.
///
/// ## Usage
/// ```swift
/// let colors = AdyenColors(
/// background: .systemBackground,
/// primary: .systemBlue,
/// text: .label
/// )
/// let theme = AdyenTheme(colors: colors)
/// ```
///
/// ## Color Categories
/// - **Backgrounds**: `background`, `container`, `disabled`
/// - **Text**: `text`, `textSecondary`, `textOnPrimary`, `textOnDestructive`, `textOnDisabled`
/// - **Interactive**: `primary`, `highlight`, `destructive`, `success`
/// - **Structural**: `containerOutline`, `separator`
///
/// - Note: Ensure sufficient contrast ratios (WCAG AA 4.5:1 minimum) between text and background colors.
public struct AdyenColors: Equatable {

package var background: UIColor
package var container: UIColor
Expand All @@ -52,11 +76,13 @@ package struct AdyenColors: Equatable {
package var separator: UIColor
package var text: UIColor
package var textSecondary: UIColor

// TODO: Robert: Theming: support shadow needs to be discussed with design team if we can use any existing colors. This should not be public anyway.
package var supportShadow: UIColor

// MARK: - Initializers

package static var `default`: AdyenColors = .init()
public static var `default`: AdyenColors = .init()

private init() {
self.background = UIColor { traitCollection in
Expand Down Expand Up @@ -119,22 +145,83 @@ package struct AdyenColors: Equatable {
}
}

package init(
/// Creates a custom color palette for Adyen checkout components.
///
/// Pass `nil` for any parameter to use the default color (supports light/dark mode automatically).
///
/// - Parameters:
///
/// - background: **Screen background** — The root background color for all checkout screens.
/// - *Used in:* `SecuredViewController`, `FormViewController`, `ListViewController`, text field backgrounds
/// - *Examples:* Drop-in payment method list background, card entry form background, stored card input screen
///
/// - container: **Grouped content background** — Background for elements containing related content.
/// - *Used in:* Text input field containers, toggle/switch backgrounds, secondary buttons, error message containers
/// - *Examples:* Card number input field container, "Save for my next payment" toggle background, card logo image background
///
/// - containerOutline: **Input borders (unfocused)** — Border color for input fields in their default state.
/// - *Used in:* `AdyenTextFieldStyle.borderColor`
/// - *Examples:* Card number field border (unfocused), expiry date field border (unfocused), CVC field border (unfocused)
///
/// - primary: **Primary action & focused states** — Your brand color for main call-to-action elements and active states.
/// - *Used in:* Primary button backgrounds, focused input field borders, toggle tint color, title/body label colors, chevron icons
/// - *Examples:* "Pay €50.00" button background, card number field border (when focused), "Save for my next payment" toggle tint
///
/// - textOnPrimary: **Text on primary buttons** — Text/icon color on `primary`-colored backgrounds.
/// - *Used in:* Primary button text and icons
/// - *Examples:* "Pay €50.00" button text, "Continue" button text, lock icon on submit button
///
/// - highlight: **Links & tertiary actions** — Accent color for text-only interactive elements.
/// - *Used in:* Tertiary button text color (text-only buttons without background)
/// - *Examples:* "Change payment method" link, "Enter code manually" link, "What is this?" help link
///
/// - destructive: **Error & danger** — Color for destructive actions and error states.
/// - *Used in:* Destructive button backgrounds, validation error messages, text field error color
/// - *Examples:* "Invalid card number" error message, "Remove stored card" button background, "Required field" validation error
///
/// - success: **Success & validation** — Color for successful completion and positive validation.
/// - *Used in:* Reserved for success states (not currently used in SDK components)
/// - *Examples:* Payment success indicators, valid input checkmarks (future use)
///
/// - textOnDestructive: **Text on destructive buttons** — Text/icon color on `destructive`-colored backgrounds.
/// - *Used in:* Destructive button text and icons
/// - *Examples:* "Remove" button text, "Delete stored card" button text
///
/// - disabled: **Disabled background** — Background color for inactive/disabled elements.
/// - *Used in:* All button types when disabled (primary, secondary, tertiary, destructive)
/// - *Examples:* "Pay €50.00" button when card details are incomplete, "Continue" button before form validation passes
///
/// - textOnDisabled: **Disabled text** — Muted text color for disabled elements.
/// - *Used in:* All button types' text when disabled
/// - *Examples:* "Pay €50.00" text when button is disabled, "Continue" text on inactive button
///
/// - separator: **Divider lines & subtle borders** — Color for visual separators and subtle borders.
/// - *Used in:* `FormSeparatorItemView`, payment method list item separators, selectable item borders, logo image borders
/// - *Examples:* Line between "Credit Card" and "iDEAL" options, border around payment method logos
///
/// - text: **Primary text** — Main text color for labels, headings, and body content.
/// - *Used in:* Subheadline labels, emphasized footnotes, secondary button text
/// - *Examples:* "Card Number" label, "Expiry Date" label, "Credit Card" payment method name, secondary button text
///
/// - textSecondary: **Secondary text** — Muted text for less prominent content.
/// - *Used in:* Input field placeholders, footnote labels, section header subtitles, helper/validation text
/// - *Examples:* "1234 5678 9012 3456" placeholder, "MM/YY" placeholder, section subtitle text, "Optional" field hint
public init(
background: UIColor? = nil,
container: UIColor? = nil,
containerOutline: UIColor? = nil,
primary: UIColor? = nil,
textOnPrimary: UIColor? = nil,
highlight: UIColor? = nil,
destructive: UIColor? = nil,
// TODO: Robert: Theming: Success is not available in Android.
success: UIColor? = nil,
textOnDestructive: UIColor? = nil,
disabled: UIColor? = nil,
textOnDisabled: UIColor? = nil,
separator: UIColor? = nil,
text: UIColor? = nil,
textSecondary: UIColor? = nil,
supportShadow: UIColor? = nil
textSecondary: UIColor? = nil
) {
let defaultScheme = AdyenColors.default

Expand All @@ -152,6 +239,7 @@ package struct AdyenColors: Equatable {
self.separator = separator ?? defaultScheme.separator
self.text = text ?? defaultScheme.text
self.textSecondary = textSecondary ?? defaultScheme.textSecondary
self.supportShadow = supportShadow ?? defaultScheme.supportShadow

self.supportShadow = defaultScheme.supportShadow
}
}
1 change: 1 addition & 0 deletions AdyenUI/AdyenFonts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum FontSize: CGFloat {
case footnote = 13.0
}

// TODO: Robert: CheckoutTheme: Why is this exposed? are we giving an option to customize fonts in general?
public struct AdyenFonts {

public var title: UIFont
Expand Down
4 changes: 3 additions & 1 deletion AdyenUI/CheckoutTheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public struct CheckoutTheme {
/// Initializes the theme with optional color overrides.
///
/// - Parameter colors: The color scheme. Defaults to `.default`.
package init(colors: AdyenColors = .default) {
public init(colors: AdyenColors = .default) {
self.colors = colors
self.attributes = .default
self.elements = AdyenElements(colors: colors)
Expand Down Expand Up @@ -66,7 +66,9 @@ extension CheckoutTheme {
/// Returns a new theme with the specified attributes.
/// - Parameter attributes: The UI attributes to apply.
/// - Returns: A new `CheckoutTheme` instance.
///
internal func attributes(_ attributes: AdyenAttributes) -> CheckoutTheme {
// TODO: Robert: Do we even need this method for some reason? Would be easier to read if this file was what was public, without any convenience init stuff.
CheckoutTheme(
colors: colors,
elements: elements,
Expand Down
Loading