> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trycandid.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Customizing the Candid SDK Appearance

> Override the Candid SDK's primary color, font, and feedback widget placement to match your app's visual identity using the Appearance struct inside Configuration.

The `Candid.Appearance` struct lets you tailor the look of every Candid screen to match your app's visual identity. Pass an `Appearance` value to `Candid.Configuration(appearance:)` when you call `Candid.configure(_:)` at launch. You can change the brand color, the typeface, and where the feedback widget appears independently. All of them default to values that work out of the box if you prefer not to customize them.

```swift theme={null}
Candid.configure(
    Candid.Configuration(
        apiKey: "cpk_your_project_key",
        appearance: Candid.Appearance(
            primaryColor: "#4F46E5",
            font: .system(.rounded),
            widgetPosition: .bottomRight,
            widgetVerticalPadding: 65
        )
    )
)
```

***

## Primary color

<ParamField path="primaryColor" default="#35C884" type="String">
  A hex color string (e.g. `"#35C884"`) that the SDK uses as its brand color. The SDK derives all interactive UI elements (buttons, progress indicators, and highlights) from this single value. Defaults to Candid green (`#35C884`).
</ParamField>

Supply any valid six-digit hex color string, with or without the leading `#`:

```swift theme={null}
Candid.Appearance(primaryColor: "#FF5A5F")
```

<Warning>
  The SDK does not validate the hex string at compile time. Passing a malformed value (e.g. `"red"` or `"#ZZZ"`) will cause the primary color to fall back to the default.
</Warning>

***

## Font

<ParamField path="font" default=".system()" type="FontChoice">
  The typeface applied to all text in the Candid UI. Choose from three options: the system font with a design variant, a named font registered in your app bundle, or a fully custom `FontProvider` implementation.
</ParamField>

### System font with a design variant

Use `.system(_:)` to keep the system font while applying a `Candid.SystemFontDesign` variant. The available designs are `.default`, `.rounded`, `.serif`, and `.monospaced`.

```swift theme={null}
// Rounded system font, softens the UI's feel
Candid.Appearance(font: .system(.rounded))

// Classic serif for editorial or reading-focused apps
Candid.Appearance(font: .system(.serif))

// Explicit default, identical to .system() with no argument
Candid.Appearance(font: .system(.default))
```

### Named custom font

Use `.custom(name:)` to apply a font that is already registered in your app bundle (listed in your `Info.plist` under `UIAppFonts`). Pass the PostScript name of the font exactly as it appears in the bundle.

```swift theme={null}
Candid.Appearance(font: .custom(name: "Nunito-Regular"))
```

<Note>
  The Candid SDK uses the name you provide for all weights and sizes. Ensure that you register all required weight variants in your `Info.plist` so that bold and light styles resolve correctly.
</Note>

### Custom FontProvider

For complete control, for example to integrate a custom font loader or a design-system token, conform a type to `Candid.FontProvider` and pass it to `.custom(_:)`.

```swift theme={null}
public protocol FontProvider: Sendable {
    func font(size: CGFloat, weight: Font.Weight) -> Font
}
```

The SDK calls `font(size:weight:)` every time it needs to render text, forwarding the exact point size and weight it requires. Return any SwiftUI `Font` you like.

Here is a complete example that loads a font from an external design-system package:

```swift theme={null}
import SwiftUI
import CandidSDK

struct BrandFontProvider: Candid.FontProvider {
    func font(size: CGFloat, weight: Font.Weight) -> Font {
        // Map SwiftUI weights to your brand font variant names
        let name: String
        switch weight {
        case .bold, .heavy, .black:
            name = "BrandFont-Bold"
        case .semibold, .medium:
            name = "BrandFont-Medium"
        default:
            name = "BrandFont-Regular"
        }
        return Font.custom(name, size: size)
    }
}
```

Pass the provider instance to `Candid.Appearance`:

```swift theme={null}
Candid.Appearance(font: .custom(BrandFontProvider()))
```

***

## Widget position

During a study, the minimized microphone widget floats above your app so participants can reopen the current question at any time. Two options control where it first appears, so you can keep it clear of tab bars, banners, or floating action buttons.

<ParamField path="widgetPosition" default=".bottomRight" type="WidgetPosition">
  The screen corner where the minimized microphone widget first appears. Available presets: `.topLeft`, `.topRight`, `.bottomLeft`, and `.bottomRight`. Left corners mirror the minimized layout: the microphone sits on the left with the status prompt on its right. Defaults to `.bottomRight`.
</ParamField>

<ParamField path="widgetVerticalPadding" default="172" type="CGFloat">
  The vertical padding in points between the widget and the safe-area edge of the chosen corner: top padding for top corners, bottom padding for bottom corners. Defaults to `172`.
</ParamField>

```swift theme={null}
// Keep the widget just above a standard tab bar (49 pt) plus a margin
Candid.Appearance(
    widgetPosition: .bottomRight,
    widgetVerticalPadding: 49 + 16
)

// Pin the widget near the top-left corner, below the navigation bar
Candid.Appearance(
    widgetPosition: .topLeft,
    widgetVerticalPadding: 60
)
```

<Note>
  These options only set the widget's initial position. Participants can drag the widget anywhere vertically afterwards, and it always stays clamped inside the safe area. The horizontal margin is fixed and cannot be customized.
</Note>

***

## Complete example

The snippet below shows a full `Appearance` configuration combining a custom color, a `FontProvider`, and a custom widget placement:

```swift theme={null}
import CandidSDK
import SwiftUI

// Define the provider once (e.g. in a dedicated file)
struct BrandFontProvider: Candid.FontProvider {
    func font(size: CGFloat, weight: Font.Weight) -> Font {
        let name = weight == .bold ? "BrandFont-Bold" : "BrandFont-Regular"
        return Font.custom(name, size: size)
    }
}

// Apply during SDK configuration
Candid.configure(
    Candid.Configuration(
        apiKey: "cpk_your_project_key",
        appearance: Candid.Appearance(
            primaryColor: "#FF5A5F",
            font: .custom(BrandFontProvider()),
            widgetPosition: .bottomRight,
            widgetVerticalPadding: 65
        )
    )
)
```

<Tip>
  Keep `BrandFontProvider` in a separate file so it can be reused across other third-party SDKs that support the same `FontProvider` pattern.
</Tip>
