Skip to content

Commit 53bdbf4

Browse files
fix(sidebar): use emcn tooltip for workspace switcher disabled reasons (#5670)
1 parent 7877713 commit 53bdbf4

1 file changed

Lines changed: 74 additions & 47 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx

Lines changed: 74 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { memo, useEffect, useRef, useState } from 'react'
3+
import { memo, type ReactElement, useEffect, useRef, useState } from 'react'
44
import {
55
ChevronDown,
66
Chip,
@@ -14,6 +14,7 @@ import {
1414
Plus,
1515
Send,
1616
Skeleton,
17+
Tooltip,
1718
} from '@sim/emcn'
1819
import { ManageWorkspace, PanelLeft } from '@sim/emcn/icons'
1920
import { createLogger } from '@sim/logger'
@@ -33,6 +34,27 @@ import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
3334

3435
const logger = createLogger('WorkspaceHeader')
3536

37+
interface DisabledReasonTooltipProps {
38+
reason: string | null
39+
children: ReactElement
40+
}
41+
42+
/**
43+
* Wraps a menu item in a tooltip explaining why the action is unavailable.
44+
* Renders the child as-is when there is no reason to show.
45+
*/
46+
function DisabledReasonTooltip({ reason, children }: DisabledReasonTooltipProps) {
47+
if (!reason) return children
48+
return (
49+
<Tooltip.Root>
50+
<Tooltip.Trigger asChild>{children}</Tooltip.Trigger>
51+
<Tooltip.Content>
52+
<p>{reason}</p>
53+
</Tooltip.Content>
54+
</Tooltip.Root>
55+
)
56+
}
57+
3658
interface WorkspaceHeaderProps {
3759
/** The active workspace object */
3860
activeWorkspace?: { name: string } | null
@@ -548,62 +570,67 @@ function WorkspaceHeaderImpl({
548570
<DropdownMenuSeparator className='mx-0' />
549571

550572
<div className='flex flex-col gap-0.5'>
573+
<DisabledReasonTooltip reason={createWorkspaceDisabledReason}>
574+
<Chip
575+
leftIcon={Plus}
576+
onClick={(e) => {
577+
e.stopPropagation()
578+
if (!canCreateWorkspace) return
579+
setIsWorkspaceMenuOpen(false)
580+
setIsCreateModalOpen(true)
581+
}}
582+
disabled={isCreatingWorkspace}
583+
aria-disabled={!canCreateWorkspace || undefined}
584+
fullWidth
585+
flush
586+
className={cn(
587+
'select-none',
588+
!canCreateWorkspace &&
589+
'cursor-not-allowed opacity-60 hover-hover:bg-transparent'
590+
)}
591+
>
592+
New workspace
593+
</Chip>
594+
</DisabledReasonTooltip>
595+
</div>
596+
597+
<DropdownMenuSeparator className='mx-0' />
598+
<DisabledReasonTooltip reason={inviteDisabledReason}>
551599
<Chip
552-
leftIcon={Plus}
553-
onClick={(e) => {
554-
e.stopPropagation()
600+
leftIcon={Send}
601+
onClick={() => {
555602
setIsWorkspaceMenuOpen(false)
556-
if (!canCreateWorkspace) {
603+
if (isInvitationsDisabled) {
557604
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
558605
return
559606
}
560-
setIsCreateModalOpen(true)
607+
setIsInviteModalOpen(true)
561608
}}
562-
disabled={isCreatingWorkspace}
563-
title={createWorkspaceDisabledReason ?? undefined}
564609
fullWidth
565610
flush
566-
className='w-full select-none disabled:pointer-events-none disabled:opacity-50'
611+
className='select-none'
567612
>
568-
New workspace
613+
Invite teammates
569614
</Chip>
570-
</div>
571-
572-
<DropdownMenuSeparator className='mx-0' />
573-
<Chip
574-
leftIcon={Send}
575-
onClick={() => {
576-
setIsWorkspaceMenuOpen(false)
577-
if (isInvitationsDisabled) {
578-
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
579-
return
580-
}
581-
setIsInviteModalOpen(true)
582-
}}
583-
title={inviteDisabledReason ?? undefined}
584-
fullWidth
585-
flush
586-
className='w-full select-none'
587-
>
588-
Invite teammates
589-
</Chip>
590-
<Chip
591-
leftIcon={ManageWorkspace}
592-
onClick={() => {
593-
setIsWorkspaceMenuOpen(false)
594-
if (isInvitationsDisabled) {
595-
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
596-
return
597-
}
598-
navigateToSettings({ section: 'teammates' })
599-
}}
600-
title={inviteDisabledReason ?? undefined}
601-
fullWidth
602-
flush
603-
className='w-full select-none'
604-
>
605-
Manage workspace
606-
</Chip>
615+
</DisabledReasonTooltip>
616+
<DisabledReasonTooltip reason={inviteDisabledReason}>
617+
<Chip
618+
leftIcon={ManageWorkspace}
619+
onClick={() => {
620+
setIsWorkspaceMenuOpen(false)
621+
if (isInvitationsDisabled) {
622+
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
623+
return
624+
}
625+
navigateToSettings({ section: 'teammates' })
626+
}}
627+
fullWidth
628+
flush
629+
className='select-none'
630+
>
631+
Manage workspace
632+
</Chip>
633+
</DisabledReasonTooltip>
607634
</>
608635
)}
609636
</DropdownMenuContent>

0 commit comments

Comments
 (0)