# How to Customize the Appearance of CodexBar's UI: A SwiftUI Guide

> Customize CodexBar's UI appearance effortlessly. Modify BurnTheme for colors, adapt to dark mode with colorScheme, and adjust settings layouts in PreferencesView and PreferencesSidebar.

- Repository: [Peter Steinberger/CodexBar](https://github.com/steipete/CodexBar)
- Tags: tutorial
- Published: 2026-07-10

---

**CodexBar's visual layer is built entirely with SwiftUI, and you can customize its appearance by modifying the `BurnTheme` struct for widget colors, adjusting `@Environment(\.colorScheme)` responses for dark mode, and editing [`PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesView.swift) and [`PreferencesSidebar.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesSidebar.swift) for the settings window layout.**

CodexBar is a macOS status bar application developed by steipete that displays burn-down charts and provider statistics using native SwiftUI components. To customize the appearance of CodexBar's UI, you must work within its SwiftUI-based architecture, modifying theme structs, environment values, and view layouts across several key source files. All visual customization happens through SwiftUI view modifications rather than external configuration files.

## Understanding CodexBar's Visual Architecture

### The BurnTheme Struct

The `BurnTheme` struct in [`Sources/CodexBarWidget/BurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarWidget/BurnDownWidgetViews.swift) (line 447) serves as the central authority for all widget styling. This struct calculates provider-specific brand colors, text colors, chart line colors, background shades, and rendering modes. It evaluates both the `dark` boolean flag and the `isMonochrome` widget rendering mode to determine appropriate color values.

### Environment-Driven Color Schemes

Every view that adapts to Light/Dark mode reads the `@Environment(\.colorScheme) private var colorScheme` property. The UI automatically swaps colors based on this environment value, ensuring real-time updates when the system appearance changes. In [`PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesView.swift) (line 43), this environment value drives the root color scheme of the settings window.

## Customizing Colors and Themes

### Modifying Widget Colors

To change chart line colors, brand dots, or background shades, edit the computed properties inside `BurnTheme`. The struct provides properties like `brandDot`, `chartLine`, `chartNowDot`, and `chartNowRing` that return `Color` values based on the current theme state.

```swift
// In BurnDownWidgetViews.swift, extend BurnTheme for custom colors
extension BurnTheme {
    var brandDot: Color { dark ? Color.purple : Color.yellow }
    var chartLine: Color { dark ? Color.white : Color.black }
}

```

### Overriding Dark Mode Palettes

Replace the default ternary expressions that check `colorScheme == .dark` with custom color definitions. This affects how backgrounds, text, and separators render in each mode.

```swift
let background = colorScheme == .dark 
    ? Color.black.opacity(0.85) 
    : Color.white.opacity(0.85)

```

## Customizing the Settings Window

### Modifying the Sidebar Layout

The settings sidebar is defined in [`Sources/CodexBar/PreferencesSidebar.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/PreferencesSidebar.swift) using `SettingsSidebarPaneRow` and `SettingsSidebarProviderRow`. Adjust icon sizes, row spacing, and padding within these private view structs to change the sidebar's visual density.

```swift
private struct SettingsSidebarPaneRow: View {
    var body: some View {
        HStack(spacing: 8) {
            SettingsIconChip(systemImage: systemImage, color: color)
                .frame(width: 24, height: 24) // Custom icon size
            Text(title)
        }
        .padding(.vertical, 4) // Custom vertical padding
    }
}

```

### Adding New Settings Panes

Extend the `SettingsPane` enum in [`PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesView.swift) to add new configuration sections. Each new case requires a corresponding view implementation in the `detailView` computed property.

```swift
// 1. Extend SettingsPane in PreferencesView.swift
enum SettingsPane: Hashable {
    case general, providers, about
    case theme // New custom pane
}

// 2. Provide view implementation
private var detailView: some View {
    switch selection.pane {
    case .theme:
        ThemeCustomizationPane(settings: settings)
    default:
        EmptyView()
    }
}

// 3. Add sidebar row in PreferencesSidebar.swift
SettingsSidebarPaneRow(
    pane: .theme,
    systemImage: "paintbrush.fill",
    color: .orange
)

```

### Synchronizing Native Window Chrome

The `SettingsWindowAppearanceBridge` class in [`Sources/CodexBar/PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/PreferencesView.swift) (lines 12-22) bridges SwiftUI color scheme changes to the underlying `NSWindow`. This ensures the title bar, separator lines, and native AppKit components stay synchronized with the SwiftUI theme.

## Practical Customization Examples

### Example 1: Custom Widget Theme

Override the default `BurnTheme` initialization to inject custom brand colors for specific providers.

```swift
let customTheme = BurnTheme(
    provider: provider,
    geom: geom,
    dark: dark,
    isMonochrome: isMonochrome)

// Override specific color properties
extension BurnTheme {
    var brandDot: Color { isEnabled ? Color.orange : Color.gray }
    var chartLine: Color { dark ? Color.green : Color.blue }
}

```

### Example 2: Sidebar Provider Row Styling

Reduce vertical padding in provider rows to create a more compact sidebar appearance.

```swift
private struct SettingsSidebarProviderRow: View {
    let provider: Provider
    let isEnabled: Bool
    
    var body: some View {
        HStack(spacing: 8) {
            SettingsSidebarBrandIcon(provider: provider, isEnabled: isEnabled)
            Text(store.metadata(for: provider).displayName)
            Spacer()
        }
        .padding(.vertical, 4) // Reduced from default
    }
}

```

### Example 3: Combined Widget Layout Changes

Modify `CombinedBurnDownLayout` in [`Sources/CodexBarWidget/CombinedBurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarWidget/CombinedBurnDownWidgetViews.swift) to adjust the arrangement of session and weekly burn-down rows.

```swift
var body: some View {
    VStack(alignment: .leading, spacing: 12) {
        Text("Custom Header") // Added headline
            .font(.headline)
        BurnDownRow(theme: theme, data: sessionData)
        BurnDownRow(theme: theme, data: weeklyData)
    }
    .padding(.horizontal, 16) // Custom padding
}

```

## Summary

- **Color customization** happens primarily in `BurnTheme` within [`BurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/BurnDownWidgetViews.swift), where you can override brand colors, chart lines, and background shades.
- **Dark mode support** relies on the `@Environment(\.colorScheme)` property, which views read to adapt their palettes automatically.
- **Settings window modifications** require editing [`PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesView.swift) for pane logic and [`PreferencesSidebar.swift`](https://github.com/steipete/CodexBar/blob/main/PreferencesSidebar.swift) for sidebar row styling.
- **Native window synchronization** is handled by `SettingsWindowAppearanceBridge`, ensuring the title bar matches the SwiftUI theme.
- All UI components are standard SwiftUI views, enabling customization through standard view modifiers and struct extensions.

## Frequently Asked Questions

### Where are CodexBar's color definitions stored?

Color definitions reside in the `BurnTheme` struct inside [`Sources/CodexBarWidget/BurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarWidget/BurnDownWidgetViews.swift). This struct provides computed properties like `brandDot`, `chartLine`, and `backgroundColor` that return SwiftUI `Color` values based on the current `dark` mode flag and `isMonochrome` rendering state.

### How do I add a new settings category to CodexBar?

Add a new case to the `SettingsPane` enum in [`Sources/CodexBar/PreferencesView.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/PreferencesView.swift), then implement the corresponding view in the `detailView` computed property. Finally, add a `SettingsSidebarPaneRow` entry in [`Sources/CodexBar/PreferencesSidebar.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/PreferencesSidebar.swift) to display the new category in the sidebar.

### Can I change the status bar icon appearance?

The status bar icon rendering depends on the widget views defined in [`Sources/CodexBarWidget/BurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarWidget/BurnDownWidgetViews.swift) and [`CombinedBurnDownWidgetViews.swift`](https://github.com/steipete/CodexBar/blob/main/CombinedBurnDownWidgetViews.swift). You can modify the `BurnTheme` struct to change icon colors or edit the layout structs to adjust icon sizing and spacing within the menu bar extra.

### Does CodexBar support external theme files or CSS?

No, CodexBar does not support external CSS or JSON theme files. All theming is compile-time SwiftUI code. To apply custom themes, you must fork the repository and modify the SwiftUI view code directly, specifically the `BurnTheme` struct and individual view implementations in the `Sources/CodexBar` and `Sources/CodexBarWidget` directories.