@@ -96,7 +96,7 @@ struct TalkProTab: View {
9696 . padding ( . horizontal, OpenClawProMetric . pagePadding)
9797 }
9898 self . voiceHeroCard
99- self . controlsCard
99+ self . controlBar
100100 }
101101 . padding ( . top, 16 )
102102 . padding ( . bottom, 18 )
@@ -156,48 +156,55 @@ struct TalkProTab: View {
156156 . padding ( . horizontal, OpenClawProMetric . pagePadding)
157157 }
158158
159- private var controlsCard : some View {
160- CommandPanel ( padding: 0 ) {
161- VStack ( spacing: 0 ) {
162- self . controlToggleRow ( " Speakerphone " , isOn: self . talkSpeakerphoneBinding)
163- Divider ( ) . padding ( . leading, 14 )
164- self . controlToggleRow ( " Background listening " , isOn: self . $talkBackgroundEnabled)
165- Divider ( ) . padding ( . leading, 14 )
159+ private var controlBar : some View {
160+ OpenClawGlassControlGroup {
161+ HStack ( spacing: 12 ) {
162+ self . iconToggle (
163+ title: " Speakerphone " ,
164+ systemImage: self . talkSpeakerphoneEnabled ? " speaker.wave.2.fill " : " speaker.slash.fill " ,
165+ isOn: self . talkSpeakerphoneBinding,
166+ accessibilityIdentifier: " talk-speakerphone-control " )
167+ self . iconToggle (
168+ title: " Background listening " ,
169+ systemImage: self . talkBackgroundEnabled ? " waveform " : " waveform.slash " ,
170+ isOn: self . $talkBackgroundEnabled,
171+ accessibilityIdentifier: " talk-background-listening-control " )
166172 Button ( action: self . openVoiceSettings) {
167- HStack {
168- Label ( " Voice & Talk settings " , systemImage: " slider.horizontal.3 " )
169- Spacer ( )
170- Image ( systemName: " chevron.right " )
171- . font ( . caption. weight ( . bold) )
172- . foregroundStyle ( . secondary)
173- }
174- . font ( . subheadline. weight ( . semibold) )
175- . padding ( . horizontal, 14 )
176- . padding ( . vertical, 12 )
173+ Image ( systemName: " slider.horizontal.3 " )
174+ . font ( . system( size: 17 , weight: . semibold) )
175+ . frame ( width: 44 , height: 44 )
177176 }
178- . buttonStyle ( . plain)
177+ . buttonBorderShape ( . circle)
178+ . openClawGlassButton ( )
179+ . accessibilityLabel ( " Voice & Talk settings " )
180+ . accessibilityIdentifier ( " talk-voice-settings-control " )
179181 }
180182 }
183+ . frame ( maxWidth: . infinity)
181184 . padding ( . horizontal, OpenClawProMetric . pagePadding)
182185 }
183186
184- private func controlToggleRow( _ title: String , isOn: Binding < Bool > ) -> some View {
185- Toggle ( title, isOn: isOn)
186- . contentShape ( Rectangle ( ) )
187- . padding ( . horizontal, 14 )
188- . padding ( . vertical, 10 )
189- . overlay {
190- // Keep Toggle semantics for accessibility while making the full visual row tappable.
191- Button {
192- isOn. wrappedValue. toggle ( )
193- } label: {
194- Rectangle ( )
195- . fill ( . clear)
196- . contentShape ( Rectangle ( ) )
197- }
198- . buttonStyle ( . plain)
199- . accessibilityHidden ( true )
200- }
187+ private func iconToggle(
188+ title: String ,
189+ systemImage: String ,
190+ isOn: Binding < Bool > ,
191+ accessibilityIdentifier: String ) -> some View
192+ {
193+ Button {
194+ isOn. wrappedValue. toggle ( )
195+ } label: {
196+ Image ( systemName: systemImage)
197+ . font ( . system( size: 17 , weight: . semibold) )
198+ . contentTransition ( . symbolEffect( . replace) )
199+ . frame ( width: 44 , height: 44 )
200+ }
201+ . buttonBorderShape ( . circle)
202+ . openClawGlassButton (
203+ prominent: isOn. wrappedValue,
204+ tint: isOn. wrappedValue ? Color ( uiColor: . systemBlue) : nil )
205+ . accessibilityLabel ( title)
206+ . accessibilityValue ( isOn. wrappedValue ? " On " : " Off " )
207+ . accessibilityIdentifier ( accessibilityIdentifier)
201208 }
202209
203210 private var gatewayConnected : Bool {
0 commit comments