Skip to content

Commit 1c76593

Browse files
committed
Merge branch 'feat/focusable' into usemylatestchanges
# Conflicts: # Sources/SwiftCrossUI/Environment/EnvironmentValues.swift # Sources/UIKitBackend/UIKitBackend+Control.swift
2 parents 3ad11e6 + cdcd0e1 commit 1c76593

File tree

11 files changed

+361
-69
lines changed

11 files changed

+361
-69
lines changed

Examples/Bundler.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,8 @@ version = '0.1.0'
6464
identifier = 'dev.swiftcrossui.HoverExample'
6565
product = 'HoverExample'
6666
version = '0.1.0'
67+
68+
[apps.ControlFocusabilityTest]
69+
identifier = 'dev.swiftcrossui.ControlFocusabilityTest'
70+
product = 'ControlFocusabilityTest'
71+
version = '0.1.0'

Examples/Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ let package = Package(
7676
.executableTarget(
7777
name: "HoverExample",
7878
dependencies: exampleDependencies
79+
),
80+
.executableTarget(
81+
name: "ControlFocusabilityTest",
82+
dependencies: exampleDependencies
7983
)
8084
]
8185
)
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import DefaultBackend
2+
import SwiftCrossUI
3+
4+
#if canImport(SwiftBundlerRuntime)
5+
import SwiftBundlerRuntime
6+
#endif
7+
8+
@main
9+
@HotReloadable
10+
struct ControlsFocusabilityApp: App {
11+
@State var count = 0
12+
@State var exampleButtonState = false
13+
@State var exampleSwitchState = false
14+
@State var exampleCheckboxState = false
15+
@State var sliderValue = 5.0
16+
@State var text = ""
17+
@State var flavor: String? = nil
18+
@State var enabled = true
19+
@State var isButtonFocusable = true
20+
@State var isToggleButtonFocusable = true
21+
@State var isToggleSwitchFocusable = true
22+
@State var isCheckboxFocusable = true
23+
@State var isSliderFocusable = true
24+
@State var isTextFieldFocusable = true
25+
@State var isPickerFocusable = true
26+
27+
var body: some Scene {
28+
WindowGroup("ControlsApp") {
29+
#hotReloadable {
30+
ScrollView {
31+
VStack(spacing: 30) {
32+
HStack {
33+
VStack {
34+
Text("Button")
35+
Button("Click me!") {
36+
count += 1
37+
}
38+
.focusable(isButtonFocusable)
39+
Text("Count: \(count)")
40+
}
41+
Toggle("focusable", active: $isButtonFocusable)
42+
.focusable(false)
43+
}
44+
.padding(.bottom, 20)
45+
46+
#if !canImport(UIKitBackend)
47+
HStack {
48+
VStack {
49+
Text("Toggle button")
50+
Toggle("Toggle me!", active: $exampleButtonState)
51+
.toggleStyle(.button)
52+
.focusable(isToggleButtonFocusable)
53+
Text("Currently enabled: \(exampleButtonState)")
54+
}
55+
Toggle("focusable", active: $isToggleButtonFocusable)
56+
.focusable(false)
57+
}
58+
.padding(.bottom, 20)
59+
#endif
60+
61+
HStack {
62+
VStack {
63+
Text("Toggle switch")
64+
Toggle("Toggle me:", active: $exampleSwitchState)
65+
.toggleStyle(.switch)
66+
.focusable(isToggleSwitchFocusable)
67+
Text("Currently enabled: \(exampleSwitchState)")
68+
}
69+
Toggle("focusable", active: $isToggleSwitchFocusable)
70+
.focusable(false)
71+
}
72+
73+
#if !canImport(UIKitBackend)
74+
HStack {
75+
VStack {
76+
Text("Checkbox")
77+
Toggle("Toggle me:", active: $exampleCheckboxState)
78+
.toggleStyle(.checkbox)
79+
.focusable(isCheckboxFocusable)
80+
Text("Currently enabled: \(exampleCheckboxState)")
81+
}
82+
Toggle("focusable", active: $isCheckboxFocusable)
83+
.focusable(false)
84+
}
85+
#endif
86+
#if !os(tvOS)
87+
HStack {
88+
VStack {
89+
Text("Slider")
90+
Slider($sliderValue, minimum: 0, maximum: 10)
91+
.frame(maxWidth: 200)
92+
.focusable(isSliderFocusable)
93+
Text("Value: \(String(format: "%.02f", sliderValue))")
94+
}
95+
Toggle("focusable", active: $isSliderFocusable)
96+
.focusable(false)
97+
}
98+
#endif
99+
HStack {
100+
VStack {
101+
Text("Text field")
102+
TextField("Text field", text: $text)
103+
.focusable(isTextFieldFocusable)
104+
Text("Value: \(text)")
105+
}
106+
Toggle("focusable", active: $isTextFieldFocusable)
107+
.focusable(false)
108+
}
109+
110+
HStack {
111+
VStack {
112+
Text("Drop down")
113+
HStack {
114+
Text("Flavor: ")
115+
Picker(
116+
of: ["Vanilla", "Chocolate", "Strawberry"],
117+
selection: $flavor
118+
)
119+
.focusable(isPickerFocusable)
120+
}
121+
Text("You chose: \(flavor ?? "Nothing yet!")")
122+
}
123+
Toggle("focusable", active: $isPickerFocusable)
124+
.focusable(false)
125+
}
126+
}
127+
.padding()
128+
.disabled(!enabled)
129+
130+
Toggle(enabled ? "Disable all" : "Enable all", active: $enabled)
131+
.padding()
132+
.focusable(false)
133+
}
134+
.frame(minHeight: 600)
135+
}
136+
137+
}.defaultSize(width: 400, height: 600)
138+
}
139+
}

Examples/Sources/ControlsExample/ControlsApp.swift

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,72 +16,91 @@ struct ControlsApp: App {
1616
@State var text = ""
1717
@State var flavor: String? = nil
1818
@State var enabled = true
19+
@State var isFocusable = true
1920

2021
var body: some Scene {
2122
WindowGroup("ControlsApp") {
2223
#hotReloadable {
23-
VStack(spacing: 30) {
24-
VStack {
25-
Text("Button")
26-
Button("Click me!") {
27-
count += 1
28-
}
29-
Text("Count: \(count)")
30-
}
31-
.padding(.bottom, 20)
32-
33-
#if !canImport(UIKitBackend)
24+
ScrollView {
25+
VStack(spacing: 30) {
3426
VStack {
35-
Text("Toggle button")
36-
Toggle("Toggle me!", active: $exampleButtonState)
37-
.toggleStyle(.button)
38-
Text("Currently enabled: \(exampleButtonState)")
27+
Text("Button")
28+
Button("Click me!") {
29+
count += 1
30+
}
31+
Text("Count: \(count)")
3932
}
4033
.padding(.bottom, 20)
41-
#endif
4234

43-
VStack {
44-
Text("Toggle switch")
45-
Toggle("Toggle me:", active: $exampleSwitchState)
46-
.toggleStyle(.switch)
47-
Text("Currently enabled: \(exampleSwitchState)")
48-
}
35+
#if !canImport(UIKitBackend)
36+
VStack {
37+
Text("Toggle button")
38+
Toggle("Toggle me!", active: $exampleButtonState)
39+
.toggleStyle(.button)
40+
Text("Currently enabled: \(exampleButtonState)")
41+
}
42+
.padding(.bottom, 20)
43+
#endif
4944

50-
#if !canImport(UIKitBackend)
5145
VStack {
52-
Text("Checkbox")
53-
Toggle("Toggle me:", active: $exampleCheckboxState)
54-
.toggleStyle(.checkbox)
55-
Text("Currently enabled: \(exampleCheckboxState)")
46+
Text("Toggle switch")
47+
Toggle("Toggle me:", active: $exampleSwitchState)
48+
.toggleStyle(.switch)
49+
Text("Currently enabled: \(exampleSwitchState)")
5650
}
57-
#endif
5851

59-
VStack {
60-
Text("Slider")
61-
Slider($sliderValue, minimum: 0, maximum: 10)
62-
.frame(maxWidth: 200)
63-
Text("Value: \(String(format: "%.02f", sliderValue))")
64-
}
52+
#if !canImport(UIKitBackend)
53+
VStack {
54+
Text("Checkbox")
55+
Toggle("Toggle me:", active: $exampleCheckboxState)
56+
.toggleStyle(.checkbox)
57+
Text("Currently enabled: \(exampleCheckboxState)")
58+
}
59+
#endif
60+
#if !os(tvOS)
61+
VStack {
62+
Text("Slider")
63+
Slider($sliderValue, minimum: 0, maximum: 10)
64+
.frame(maxWidth: 200)
65+
Text("Value: \(String(format: "%.02f", sliderValue))")
66+
}
67+
#endif
6568

66-
VStack {
67-
Text("Text field")
68-
TextField("Text field", text: $text)
69-
Text("Value: \(text)")
70-
}
69+
VStack {
70+
Text("Text field")
71+
TextField("Text field", text: $text)
72+
Text("Value: \(text)")
73+
}
7174

72-
VStack {
73-
Text("Drop down")
74-
HStack {
75-
Text("Flavor: ")
76-
Picker(of: ["Vanilla", "Chocolate", "Strawberry"], selection: $flavor)
75+
VStack {
76+
Text("Drop down")
77+
HStack {
78+
Text("Flavor: ")
79+
Picker(
80+
of: ["Vanilla", "Chocolate", "Strawberry"], selection: $flavor)
81+
}
82+
Text("You chose: \(flavor ?? "Nothing yet!")")
7783
}
78-
Text("You chose: \(flavor ?? "Nothing yet!")")
7984
}
80-
}.padding().disabled(!enabled)
85+
.padding()
86+
.disabled(!enabled)
87+
.focusable(isFocusable)
88+
89+
Toggle(enabled ? "Disable all" : "Enable all", active: $enabled)
90+
.padding()
91+
.focusable(isFocusable)
8192

82-
Toggle(enabled ? "Disable all" : "Enable all", active: $enabled)
93+
Toggle(
94+
isFocusable
95+
? "Disable focusability for all" : "Enable focusability for all",
96+
active: $isFocusable
97+
)
8398
.padding()
99+
.focusable(isFocusable)
100+
}
101+
.frame(minHeight: 600)
84102
}
103+
85104
}.defaultSize(width: 400, height: 600)
86105
}
87106
}

0 commit comments

Comments
 (0)