mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(sidebar): use emcn tooltip for workspace switcher disabled reasons (#5670)
This commit is contained in:
+81
-54
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user