@@ -125,104 +125,104 @@ struct BaseWidget<Content: View>: View {
125125 }
126126
127127 var body : some View {
128- Button { } label: {
129- VStack ( spacing: 0 ) {
130- if type == . suggestions ? isEditing : ( settings. showWidgetTitles || isEditing) {
131- HStack {
132- HStack ( spacing: 16 ) {
133- Image ( metadata. icon)
134- . resizable ( )
135- . frame ( width: 32 , height: 32 )
128+ widgetContent
129+ . accessibilityIdentifierIfPresent ( isEditing ? nil : " \( type. rawValue. capitalized) Widget " )
130+ . frame ( maxWidth: . infinity)
131+ . padding ( ( hasBackground || isEditing) ? 16 : 0 )
132+ . background ( ( hasBackground || isEditing) ? Color . gray6 : Color . clear)
133+ . cornerRadius ( hasBackground || isEditing ? 16 : 0 )
134+ . alert (
135+ t ( " widgets__delete__title " ) ,
136+ isPresented: $showDeleteDialog,
137+ actions: {
138+ Button ( t ( " common__cancel " ) , role: . cancel) {
139+ showDeleteDialog = false
140+ }
136141
137- BodyMSBText ( truncate ( metadata. name, 18 ) )
138- . lineLimit ( 1 )
139- }
142+ Button ( t ( " common__delete_yes " ) , role: . destructive) {
143+ widgets. deleteWidget ( type)
144+ showDeleteDialog = false
145+ }
146+ } ,
147+ message: {
148+ Text ( t ( " widgets__delete__description " , variables: [ " name " : metadata. name] ) )
149+ }
150+ )
151+ }
140152
141- Spacer ( )
142-
143- // Action buttons when in edit mode
144- if isEditing {
145- HStack ( spacing: 8 ) {
146- // Delete button
147- Button {
148- onDelete ( )
149- } label: {
150- Image ( " trash " )
151- . resizable ( )
152- . foregroundColor ( . textPrimary)
153- . frame ( width: 24 , height: 24 )
154- }
155- . frame ( width: 32 , height: 32 )
156- . contentShape ( Rectangle ( ) )
157- . accessibilityIdentifier ( " \( metadata. name) _WidgetActionDelete " )
158-
159- // Edit button
160- Button {
161- onEdit ( )
162- } label: {
163- Image ( " gear-six " )
164- . resizable ( )
165- . foregroundColor ( . textPrimary)
166- . frame ( width: 24 , height: 24 )
167- }
168- . frame ( width: 32 , height: 32 )
169- . contentShape ( Rectangle ( ) )
170- . accessibilityIdentifier ( " \( metadata. name) _WidgetActionEdit " )
153+ private var widgetContent : some View {
154+ VStack ( spacing: 0 ) {
155+ if type == . suggestions ? isEditing : ( settings. showWidgetTitles || isEditing) {
156+ HStack {
157+ HStack ( spacing: 16 ) {
158+ Image ( metadata. icon)
159+ . resizable ( )
160+ . frame ( width: 32 , height: 32 )
161+
162+ BodyMSBText ( truncate ( metadata. name, 18 ) )
163+ . lineLimit ( 1 )
164+ }
165+
166+ Spacer ( )
171167
172- Image ( " burger " )
168+ // Action buttons when in edit mode
169+ if isEditing {
170+ HStack ( spacing: 8 ) {
171+ // Delete button
172+ Button {
173+ onDelete ( )
174+ } label: {
175+ Image ( " trash " )
173176 . resizable ( )
174177 . foregroundColor ( . textPrimary)
175178 . frame ( width: 24 , height: 24 )
176- . frame ( width: 32 , height: 32 )
177- . contentShape ( Rectangle ( ) )
178- . overlay {
179- Color . clear
180- . frame ( width: 44 , height: 44 )
181- . contentShape ( Rectangle ( ) )
182- . trackDragHandle ( )
183- }
184- . accessibilityIdentifier ( " \( metadata. name) _WidgetActionReorder " )
185179 }
186- }
187- }
180+ . frame ( width: 32 , height: 32 )
181+ . contentShape ( Rectangle ( ) )
182+ . accessibilityIdentifier ( " \( metadata. name) _WidgetActionDelete " )
183+
184+ // Edit button
185+ Button {
186+ onEdit ( )
187+ } label: {
188+ Image ( " gear-six " )
189+ . resizable ( )
190+ . foregroundColor ( . textPrimary)
191+ . frame ( width: 24 , height: 24 )
192+ }
193+ . frame ( width: 32 , height: 32 )
194+ . contentShape ( Rectangle ( ) )
195+ . accessibilityIdentifier ( " \( metadata. name) _WidgetActionEdit " )
188196
189- // Add spacer only when showing title and not editing
190- if settings. showWidgetTitles && !isEditing {
191- Spacer ( )
192- . frame ( height: 16 )
197+ Image ( " burger " )
198+ . resizable ( )
199+ . foregroundColor ( . textPrimary)
200+ . frame ( width: 24 , height: 24 )
201+ . frame ( width: 32 , height: 32 )
202+ . contentShape ( Rectangle ( ) )
203+ . overlay {
204+ Color . clear
205+ . frame ( width: 44 , height: 44 )
206+ . contentShape ( Rectangle ( ) )
207+ . trackDragHandle ( )
208+ }
209+ . accessibilityIdentifier ( " \( metadata. name) _WidgetActionReorder " )
210+ }
193211 }
194212 }
195213
196- // Widget content (only shown when not editing)
197- if !isEditing {
198- content
214+ // Add spacer only when showing title and not editing
215+ if settings. showWidgetTitles && !isEditing {
216+ Spacer ( )
217+ . frame ( height: 16 )
199218 }
200219 }
201- . contentShape ( Rectangle ( ) )
202- }
203- . accessibilityIdentifier ( " \( type. rawValue. capitalized) Widget " )
204- . buttonStyle ( WidgetButtonStyle ( ) )
205- . frame ( maxWidth: . infinity)
206- . padding ( ( hasBackground || isEditing) ? 16 : 0 )
207- . background ( ( hasBackground || isEditing) ? Color . gray6 : Color . clear)
208- . cornerRadius ( hasBackground || isEditing ? 16 : 0 )
209- . alert (
210- t ( " widgets__delete__title " ) ,
211- isPresented: $showDeleteDialog,
212- actions: {
213- Button ( t ( " common__cancel " ) , role: . cancel) {
214- showDeleteDialog = false
215- }
216220
217- Button ( t ( " common__delete_yes " ) , role: . destructive) {
218- widgets. deleteWidget ( type)
219- showDeleteDialog = false
220- }
221- } ,
222- message: {
223- Text ( t ( " widgets__delete__description " , variables: [ " name " : metadata. name] ) )
221+ // Widget content (only shown when not editing)
222+ if !isEditing {
223+ content
224224 }
225- )
225+ }
226226 }
227227
228228 /// Truncate a string to a maximum length
@@ -236,14 +236,6 @@ struct BaseWidget<Content: View>: View {
236236 }
237237}
238238
239- /// Custom button style for widgets
240- struct WidgetButtonStyle : ButtonStyle {
241- func makeBody( configuration: Configuration ) -> some View {
242- configuration. label
243- . opacity ( configuration. isPressed ? 0.9 : 1.0 )
244- }
245- }
246-
247239// Preview for the BaseWidget
248240#Preview {
249241 VStack {
0 commit comments