fix(sidebar): use emcn tooltip for workspace switcher disabled reasons (#5670)

This commit is contained in:
Theodore Li
2026-07-14 00:22:44 -04:00
committed by GitHub
parent 78777132bd
commit 53bdbf475d
@@ -1,6 +1,6 @@
'use client'
import { memo, useEffect, useRef, useState } from 'react'
import { memo, type ReactElement, useEffect, useRef, useState } from 'react'
import {
ChevronDown,
Chip,
@@ -14,6 +14,7 @@ import {
Plus,
Send,
Skeleton,
Tooltip,
} from '@sim/emcn'
import { ManageWorkspace, PanelLeft } from '@sim/emcn/icons'
import { createLogger } from '@sim/logger'
@@ -33,6 +34,27 @@ import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
const logger = createLogger('WorkspaceHeader')
interface DisabledReasonTooltipProps {
reason: string | null
children: ReactElement
}
/**
* Wraps a menu item in a tooltip explaining why the action is unavailable.
* Renders the child as-is when there is no reason to show.
*/
function DisabledReasonTooltip({ reason, children }: DisabledReasonTooltipProps) {
if (!reason) return children
return (
<Tooltip.Root>
<Tooltip.Trigger asChild>{children}</Tooltip.Trigger>
<Tooltip.Content>
<p>{reason}</p>
</Tooltip.Content>
</Tooltip.Root>
)
}
interface WorkspaceHeaderProps {
/** The active workspace object */
activeWorkspace?: { name: string } | null
@@ -548,62 +570,67 @@ function WorkspaceHeaderImpl({
<DropdownMenuSeparator className='mx-0' />
<div className='flex flex-col gap-0.5'>
<Chip
leftIcon={Plus}
onClick={(e) => {
e.stopPropagation()
setIsWorkspaceMenuOpen(false)
if (!canCreateWorkspace) {
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
return
}
setIsCreateModalOpen(true)
}}
disabled={isCreatingWorkspace}
title={createWorkspaceDisabledReason ?? undefined}
fullWidth
flush
className='w-full select-none disabled:pointer-events-none disabled:opacity-50'
>
New workspace
</Chip>
<DisabledReasonTooltip reason={createWorkspaceDisabledReason}>
<Chip
leftIcon={Plus}
onClick={(e) => {
e.stopPropagation()
if (!canCreateWorkspace) return
setIsWorkspaceMenuOpen(false)
setIsCreateModalOpen(true)
}}
disabled={isCreatingWorkspace}
aria-disabled={!canCreateWorkspace || undefined}
fullWidth
flush
className={cn(
'select-none',
!canCreateWorkspace &&
'cursor-not-allowed opacity-60 hover-hover:bg-transparent'
)}
>
New workspace
</Chip>
</DisabledReasonTooltip>
</div>
<DropdownMenuSeparator className='mx-0' />
<Chip
leftIcon={Send}
onClick={() => {
setIsWorkspaceMenuOpen(false)
if (isInvitationsDisabled) {
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
return
}
setIsInviteModalOpen(true)
}}
title={inviteDisabledReason ?? undefined}
fullWidth
flush
className='w-full select-none'
>
Invite teammates
</Chip>
<Chip
leftIcon={ManageWorkspace}
onClick={() => {
setIsWorkspaceMenuOpen(false)
if (isInvitationsDisabled) {
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
return
}
navigateToSettings({ section: 'teammates' })
}}
title={inviteDisabledReason ?? undefined}
fullWidth
flush
className='w-full select-none'
>
Manage workspace
</Chip>
<DisabledReasonTooltip reason={inviteDisabledReason}>
<Chip
leftIcon={Send}
onClick={() => {
setIsWorkspaceMenuOpen(false)
if (isInvitationsDisabled) {
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
return
}
setIsInviteModalOpen(true)
}}
fullWidth
flush
className='select-none'
>
Invite teammates
</Chip>
</DisabledReasonTooltip>
<DisabledReasonTooltip reason={inviteDisabledReason}>
<Chip
leftIcon={ManageWorkspace}
onClick={() => {
setIsWorkspaceMenuOpen(false)
if (isInvitationsDisabled) {
if (isBillingEnabled) navigateToSettings({ section: 'billing' })
return
}
navigateToSettings({ section: 'teammates' })
}}
fullWidth
flush
className='select-none'
>
Manage workspace
</Chip>
</DisabledReasonTooltip>
</>
)}
</DropdownMenuContent>