fix(invite-modal): remove custom button heights and useEffect anti-pattern (#3082)

* fix(invite-modal): remove custom button heights and useEffect anti-pattern

* cleanup
This commit is contained in:
Waleed
2026-01-30 12:14:27 -08:00
committed by GitHub
parent 656beb8383
commit 6cf9841b99
2 changed files with 36 additions and 30 deletions

View File

@@ -24,6 +24,7 @@ import {
Cursor,
DatePicker,
DocumentAttachment,
Download,
Duplicate,
Expand,
Eye,
@@ -51,6 +52,7 @@ import {
NoWrap,
PanelLeft,
Play,
PlayOutline,
Popover,
PopoverBackButton,
PopoverContent,
@@ -214,6 +216,9 @@ export default function PlaygroundPage() {
<VariantRow label='primary'>
<Button variant='primary'>Primary</Button>
</VariantRow>
<VariantRow label='destructive'>
<Button variant='destructive'>Destructive</Button>
</VariantRow>
<VariantRow label='secondary'>
<Button variant='secondary'>Secondary</Button>
</VariantRow>
@@ -290,6 +295,9 @@ export default function PlaygroundPage() {
<VariantRow label='outline'>
<Badge variant='outline'>Outline</Badge>
</VariantRow>
<VariantRow label='type'>
<Badge variant='type'>Type</Badge>
</VariantRow>
<VariantRow label='green'>
<Badge variant='green'>Green</Badge>
<Badge variant='green' dot>
@@ -323,6 +331,9 @@ export default function PlaygroundPage() {
<VariantRow label='teal'>
<Badge variant='teal'>Teal</Badge>
</VariantRow>
<VariantRow label='cyan'>
<Badge variant='cyan'>Cyan</Badge>
</VariantRow>
<VariantRow label='gray'>
<Badge variant='gray'>Gray</Badge>
</VariantRow>
@@ -996,6 +1007,7 @@ export default function PlaygroundPage() {
{ Icon: Copy, name: 'Copy' },
{ Icon: Cursor, name: 'Cursor' },
{ Icon: DocumentAttachment, name: 'DocumentAttachment' },
{ Icon: Download, name: 'Download' },
{ Icon: Duplicate, name: 'Duplicate' },
{ Icon: Expand, name: 'Expand' },
{ Icon: Eye, name: 'Eye' },
@@ -1011,6 +1023,7 @@ export default function PlaygroundPage() {
{ Icon: NoWrap, name: 'NoWrap' },
{ Icon: PanelLeft, name: 'PanelLeft' },
{ Icon: Play, name: 'Play' },
{ Icon: PlayOutline, name: 'PlayOutline' },
{ Icon: Redo, name: 'Redo' },
{ Icon: Rocket, name: 'Rocket' },
{ Icon: Trash, name: 'Trash' },

View File

@@ -50,9 +50,8 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
>({})
const [isSubmitting, setIsSubmitting] = useState(false)
const [isSaving, setIsSaving] = useState(false)
const [showSent, setShowSent] = useState(false)
const cooldownIntervalsRef = useRef<Map<string, NodeJS.Timeout>>(new Map())
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [successMessage, setSuccessMessage] = useState<string | null>(null)
const [memberToRemove, setMemberToRemove] = useState<{ userId: string; email: string } | null>(
null
)
@@ -121,10 +120,17 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
useEffect(() => {
if (open) {
setErrorMessage(null)
setSuccessMessage(null)
}
}, [open])
useEffect(() => {
const intervalsRef = cooldownIntervalsRef.current
return () => {
intervalsRef.forEach((interval) => clearInterval(interval))
intervalsRef.clear()
}
}, [])
const addEmail = useCallback(
(email: string) => {
if (!email.trim()) return false
@@ -255,11 +261,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
}
setExistingUserPermissionChanges({})
setSuccessMessage(
`Permission changes saved for ${updates.length} user${updates.length !== 1 ? 's' : ''}!`
)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error saving permission changes:', error)
const errorMsg =
@@ -282,9 +283,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
if (!userPerms.canAdmin || !hasPendingChanges) return
setExistingUserPermissionChanges({})
setSuccessMessage('Changes restored to original permissions!')
setTimeout(() => setSuccessMessage(null), 3000)
}, [userPerms.canAdmin, hasPendingChanges])
const handleRemoveMemberClick = useCallback((userId: string, email: string) => {
@@ -337,9 +335,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
delete updated[memberToRemove.userId]
return updated
})
setSuccessMessage(`${memberToRemove.email} has been removed from the workspace`)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error removing member:', error)
const errorMsg =
@@ -385,9 +380,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setPendingInvitations((prev) =>
prev.filter((inv) => inv.invitationId !== invitationToRemove.invitationId)
)
setSuccessMessage(`Invitation for ${invitationToRemove.email} has been cancelled`)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error cancelling invitation:', error)
const errorMsg =
@@ -427,9 +419,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
throw new Error(data.error || 'Failed to resend invitation')
}
setSuccessMessage(`Invitation resent to ${email}`)
setTimeout(() => setSuccessMessage(null), 3000)
setResentInvitationIds((prev) => ({ ...prev, [invitationId]: true }))
setTimeout(() => {
setResentInvitationIds((prev) => {
@@ -450,6 +439,12 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
return next
})
setResendCooldowns((prev) => ({ ...prev, [invitationId]: 60 }))
const existingInterval = cooldownIntervalsRef.current.get(invitationId)
if (existingInterval) {
clearInterval(existingInterval)
}
const interval = setInterval(() => {
setResendCooldowns((prev) => {
const current = prev[invitationId]
@@ -458,11 +453,14 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
const next = { ...prev }
delete next[invitationId]
clearInterval(interval)
cooldownIntervalsRef.current.delete(invitationId)
return next
}
return { ...prev, [invitationId]: current - 1 }
})
}, 1000)
cooldownIntervalsRef.current.set(invitationId, interval)
}
},
[workspaceId, userPerms.canAdmin, resendCooldowns]
@@ -473,7 +471,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
e.preventDefault()
setErrorMessage(null)
setSuccessMessage(null)
if (validEmails.length === 0 || !workspaceId) {
return
@@ -562,11 +559,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setEmailItems([])
setUserPermissions([])
}
setShowSent(true)
setTimeout(() => {
setShowSent(false)
}, 4000)
}
} catch (err) {
logger.error('Error inviting members:', err)
@@ -588,13 +580,16 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setExistingUserPermissionChanges({})
setIsSubmitting(false)
setIsSaving(false)
setShowSent(false)
setErrorMessage(null)
setSuccessMessage(null)
setMemberToRemove(null)
setIsRemovingMember(false)
setInvitationToRemove(null)
setIsRemovingInvitation(false)
setResendCooldowns({})
setResentInvitationIds({})
cooldownIntervalsRef.current.forEach((interval) => clearInterval(interval))
cooldownIntervalsRef.current.clear()
}, [])
return (
@@ -703,7 +698,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
variant='default'
disabled={isSaving || isSubmitting}
onClick={handleRestoreChanges}
className='h-[32px] gap-[8px] px-[12px] font-medium'
>
Restore Changes
</Button>
@@ -712,7 +706,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
variant='tertiary'
disabled={isSaving || isSubmitting}
onClick={handleSaveChanges}
className='h-[32px] gap-[8px] px-[12px] font-medium'
>
{isSaving ? 'Saving...' : 'Save Changes'}
</Button>