summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN/Views/CustomToggleStyle.swift
blob: 2c99dec856ef12f939de318b2da74d3b9290a80b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
//  CustomToggle.swift
//  MullvadVPN
//
//  Created by Jon Petersson on 2024-11-13.
//  Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

/// Custom (default) toggle style used for switches.
struct CustomToggleStyle: ToggleStyle {
    private let width: CGFloat = 48
    private let height: CGFloat = 30
    private let circleRadius: CGFloat = 23

    var disabled = false
    let accessibilityId: AccessibilityIdentifier?
    var infoButtonAction: (() -> Void)?

    func makeBody(configuration: Configuration) -> some View {
        HStack {
            configuration.label
                .opacity(disabled ? 0.2 : 1)

            if let infoButtonAction {
                Button(action: infoButtonAction) {
                    Image(.iconInfo)
                }
                .adjustingTapAreaSize()
                .tint(.white)
            }

            Spacer()

            ZStack(alignment: configuration.isOn ? .trailing : .leading) {
                Capsule(style: .circular)
                    .frame(width: width, height: height)
                    .foregroundColor(.clear)
                    .overlay(
                        RoundedRectangle(cornerRadius: circleRadius)
                            .stroke(
                                Color(.white.withAlphaComponent(0.8)),
                                lineWidth: 2
                            )
                    )
                    .opacity(disabled ? 0.2 : 1)

                Circle()
                    .frame(width: circleRadius, height: circleRadius)
                    .padding(3)
                    .foregroundColor(
                        configuration.isOn
                            ? Color(uiColor: UIColor.Switch.onThumbColor)
                            : Color(uiColor: UIColor.Switch.offThumbColor)
                    )
                    .opacity(disabled ? 0.4 : 1)
            }
            .accessibilityIdentifier(accessibilityId?.asString ?? "")
            .onTapGesture {
                toggle(configuration)
            }
            .adjustingTapAreaSize()
        }
    }

    private func toggle(_ configuration: Configuration) {
        withAnimation(.easeInOut(duration: 0.25)) {
            configuration.isOn.toggle()
        }
    }
}