Skip to content

Commit 91e89f4

Browse files
waleedlatif1claude
andcommitted
fix: keep modal errors inside the modal instead of a screen-corner toast
Per the toast spec (modal errors stay in the modal; only page errors go to the corner), route two in-modal failures inline: - add-people-modal: failures now render via ChipModalError in the modal body (the modal stays open with the failed emails), not toast.error. - slack setup wizard: a clipboard-copy failure shows inline beneath the copy button (mirroring the existing 'copied' state), not a toast. Left as-is (verified correct, not violations): credential-detail save error (a routed page, not a modal — page toast is correct) and import-csv success (fires as the dialog closes — inline isn't possible). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 779a8ed commit 91e89f4

2 files changed

Lines changed: 19 additions & 8 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]

apps/sim/app/workspace/[workspaceId]/components/credential-detail/components/add-people-modal.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
import { useCallback, useMemo, useState } from 'react'
44
import { createLogger } from '@sim/logger'
5-
import { getErrorMessage } from '@sim/utils/errors'
65
import {
76
ChipModal,
87
ChipModalBody,
8+
ChipModalError,
99
ChipModalField,
1010
ChipModalFooter,
1111
ChipModalHeader,
12-
toast,
1312
} from '@/components/emcn'
1413
import { useWorkspacePermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
1514
import {
@@ -42,6 +41,7 @@ export function AddPeopleModal({ credentialId, open, onOpenChange }: AddPeopleMo
4241
const [emailsToAdd, setEmailsToAdd] = useState<string[]>([])
4342
const [roleToAdd, setRoleToAdd] = useState<WorkspaceCredentialRole>('member')
4443
const [isAdding, setIsAdding] = useState(false)
44+
const [submitError, setSubmitError] = useState<string | null>(null)
4545

4646
const workspaceUserIdByEmail = useMemo(
4747
() =>
@@ -73,11 +73,13 @@ export function AddPeopleModal({ credentialId, open, onOpenChange }: AddPeopleMo
7373
const handleClose = useCallback(() => {
7474
setEmailsToAdd([])
7575
setRoleToAdd('member')
76+
setSubmitError(null)
7677
onOpenChange(false)
7778
}, [onOpenChange])
7879

7980
const handleAddPeople = useCallback(async () => {
8081
if (emailsToAdd.length === 0 || isAdding) return
82+
setSubmitError(null)
8183
const targets = emailsToAdd
8284
.map((email) => {
8385
const result = resolveAddEmail(email, { workspaceUserIdByEmail, existingMemberEmails })
@@ -103,11 +105,10 @@ export function AddPeopleModal({ credentialId, open, onOpenChange }: AddPeopleMo
103105
(result): result is PromiseRejectedResult => result.status === 'rejected'
104106
)
105107
logger.error('Failed to add some credential members', firstError?.reason)
106-
toast.error(
108+
setSubmitError(
107109
failures.length === targets.length
108-
? "Couldn't add people"
109-
: `Couldn't add ${failures.length} of ${targets.length} people`,
110-
{ description: getErrorMessage(firstError?.reason, 'Please try again in a moment.') }
110+
? "Couldn't add people. Please try again in a moment."
111+
: `Couldn't add ${failures.length} of ${targets.length} people. Please try again in a moment.`
111112
)
112113
} finally {
113114
setIsAdding(false)
@@ -152,6 +153,7 @@ export function AddPeopleModal({ credentialId, open, onOpenChange }: AddPeopleMo
152153
onChange={(role) => setRoleToAdd(role as WorkspaceCredentialRole)}
153154
disabled={isAdding}
154155
/>
156+
<ChipModalError>{submitError}</ChipModalError>
155157
</ChipModalBody>
156158
<ChipModalFooter
157159
onCancel={handleClose}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/slack-setup-wizard/slack-setup-wizard.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { type ReactNode, useCallback, useMemo, useState } from 'react'
44
import { Check, ChevronRight, Clipboard, Info } from 'lucide-react'
55
import { useShallow } from 'zustand/react/shallow'
6-
import { Checkbox, Input, Label, SecretInput, Tooltip, toast, Wizard } from '@/components/emcn'
6+
import { Checkbox, Input, Label, SecretInput, Tooltip, Wizard } from '@/components/emcn'
77
import { cn } from '@/lib/core/utils/cn'
88
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
99
import { useWebhookManagement } from '@/hooks/use-webhook-management'
@@ -263,15 +263,19 @@ interface StepCreateProps {
263263

264264
function StepCreate({ manifestJson, canCopy }: StepCreateProps) {
265265
const [copied, setCopied] = useState<boolean>(false)
266+
const [copyFailed, setCopyFailed] = useState<boolean>(false)
266267

267268
const handleCopy = useCallback(async () => {
268269
if (!canCopy) return
269270
try {
270271
await navigator.clipboard.writeText(manifestJson)
272+
setCopyFailed(false)
271273
setCopied(true)
272274
setTimeout(() => setCopied(false), 2000)
273275
} catch {
274-
toast.error("Couldn't copy manifest — copy it manually from the developer console.")
276+
// Keep the failure inside the wizard rather than firing a toast that
277+
// escapes to the screen corner.
278+
setCopyFailed(true)
275279
}
276280
}, [canCopy, manifestJson])
277281

@@ -301,6 +305,11 @@ function StepCreate({ manifestJson, canCopy }: StepCreateProps) {
301305
<Clipboard className='size-[12px] text-[var(--text-muted)]' />
302306
))}
303307
</button>
308+
{copyFailed ? (
309+
<p className='mt-1.5 text-[var(--text-error)] text-xs'>
310+
Couldn't copy manifest — copy it manually from the developer console.
311+
</p>
312+
) : null}
304313
</SubStep>
305314
<SubStep n={2}>
306315
Open the{' '}

0 commit comments

Comments
 (0)