@@ -131,25 +131,46 @@ export function TaskModal({
131131 onSubmit,
132132 onRequestDelete,
133133} : TaskModalProps ) {
134+ const [ submitting , setSubmitting ] = useState ( false )
135+
136+ /**
137+ * While a save is in flight, swallow every dismiss path — Cancel, header X,
138+ * Escape, and overlay click all route through this one handler — so an
139+ * in-progress create/edit can't be abandoned and lose its draft. `submitting`
140+ * lives here (not in the unmounted-on-close content) so this guard can see it.
141+ */
142+ const handleOpenChange = ( next : boolean ) => {
143+ if ( ! next && submitting ) return
144+ onOpenChange ( next )
145+ }
146+
134147 return (
135148 < ChipModal
136149 open = { open }
137- onOpenChange = { onOpenChange }
150+ onOpenChange = { handleOpenChange }
138151 size = 'lg'
139152 srTitle = { edit ? 'Edit scheduled task' : 'New scheduled task' }
140153 >
141154 < TaskModalContent
142- onOpenChange = { onOpenChange }
155+ onOpenChange = { handleOpenChange }
143156 slot = { slot }
144157 edit = { edit }
145158 prefill = { prefill }
146159 onSubmit = { onSubmit }
147160 onRequestDelete = { onRequestDelete }
161+ submitting = { submitting }
162+ setSubmitting = { setSubmitting }
148163 />
149164 </ ChipModal >
150165 )
151166}
152167
168+ interface TaskModalContentProps extends Omit < TaskModalProps , 'open' > {
169+ /** Whether a save is in flight — owned by {@link TaskModal} so the dismiss guard can read it. */
170+ submitting : boolean
171+ setSubmitting : ( submitting : boolean ) => void
172+ }
173+
153174/**
154175 * Inner content, mounted only while the dialog is open (the Radix portal
155176 * unmounts closed content). Holding the editor here keeps its mention-data
@@ -162,7 +183,9 @@ function TaskModalContent({
162183 prefill,
163184 onSubmit,
164185 onRequestDelete,
165- } : Omit < TaskModalProps , 'open' > ) {
186+ submitting,
187+ setSubmitting,
188+ } : TaskModalContentProps ) {
166189 const { workspaceId } = useParams < { workspaceId : string } > ( )
167190 const source = edit ?? prefill
168191 const accountTimezone = useTimezone ( )
@@ -193,7 +216,6 @@ function TaskModalContent({
193216 const [ recurrence , setRecurrence ] = useState < Recurrence > (
194217 ( ) => source ?. recurrence ?? DEFAULT_RECURRENCE
195218 )
196- const [ submitting , setSubmitting ] = useState ( false )
197219 const launchEditedRef = useRef ( false )
198220
199221 /**
@@ -287,6 +309,7 @@ function TaskModalContent({
287309 </ ChipModalPromptBody >
288310 < ChipModalFooter
289311 onCancel = { close }
312+ cancelDisabled = { submitting }
290313 secondaryActions = { secondaryActions }
291314 primaryAction = { {
292315 label : submitting ? ( edit ? 'Saving...' : 'Scheduling...' ) : edit ? 'Save' : 'Schedule' ,
0 commit comments