mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
fix(ui): disable unavailable chat navigation
This commit is contained in:
@@ -19,10 +19,12 @@ export function SidebarNavigationModeToggle({
|
||||
isOpen,
|
||||
value,
|
||||
onChange,
|
||||
chatEnabled = true,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
value: SidebarNavigationMode;
|
||||
onChange: (value: SidebarNavigationMode) => void;
|
||||
chatEnabled?: boolean;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const modes = [
|
||||
@@ -38,7 +40,8 @@ export function SidebarNavigationModeToggle({
|
||||
},
|
||||
] as const;
|
||||
|
||||
const handleModeChange = (mode: SidebarNavigationMode) => {
|
||||
const handleModeChange = (mode: SidebarNavigationMode, disabled: boolean) => {
|
||||
if (disabled) return;
|
||||
onChange(mode);
|
||||
if (mode === SIDEBAR_NAVIGATION_MODE.CHAT) {
|
||||
router.push("/lighthouse");
|
||||
@@ -56,11 +59,16 @@ export function SidebarNavigationModeToggle({
|
||||
{modes.map((mode) => {
|
||||
const Icon = mode.icon;
|
||||
const active = value === mode.value;
|
||||
const disabled =
|
||||
mode.value === SIDEBAR_NAVIGATION_MODE.CHAT && !chatEnabled;
|
||||
const button = (
|
||||
<button
|
||||
key={mode.value}
|
||||
type="button"
|
||||
aria-label={mode.label}
|
||||
// aria-disabled (not disabled) keeps the button hoverable and
|
||||
// focusable so the availability tooltip can fire.
|
||||
aria-disabled={disabled || undefined}
|
||||
className={cn(
|
||||
"flex h-8 items-center justify-center rounded-[6px] border px-2 text-sm transition-all duration-200 ease-out",
|
||||
isOpen ? "min-w-0 gap-2" : "w-8",
|
||||
@@ -70,22 +78,30 @@ export function SidebarNavigationModeToggle({
|
||||
? "border-border-input-primary bg-bg-neutral-primary text-text-neutral-primary shadow-md"
|
||||
: "text-text-neutral-secondary hover:text-text-neutral-primary border-transparent",
|
||||
isOpen && (active ? "flex-[11]" : "flex-[9]"),
|
||||
disabled &&
|
||||
"hover:text-text-neutral-secondary cursor-not-allowed opacity-50",
|
||||
)}
|
||||
onClick={() => handleModeChange(mode.value)}
|
||||
onClick={() => handleModeChange(mode.value, disabled)}
|
||||
>
|
||||
<Icon className="size-4 shrink-0" />
|
||||
{isOpen && <span className="truncate">{mode.label}</span>}
|
||||
</button>
|
||||
);
|
||||
|
||||
if (isOpen) {
|
||||
const tooltipContent = disabled
|
||||
? "Available in Prowler Cloud"
|
||||
: !isOpen
|
||||
? mode.label
|
||||
: null;
|
||||
|
||||
if (!tooltipContent) {
|
||||
return button;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip key={mode.value} delayDuration={100}>
|
||||
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
||||
<TooltipContent side="right">{mode.label}</TooltipContent>
|
||||
<TooltipContent side="right">{tooltipContent}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -162,6 +162,19 @@ describe("Menu", () => {
|
||||
).not.toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Home" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows the mode toggle with Chat disabled outside cloud", () => {
|
||||
pathnameValue.current = "/findings";
|
||||
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
|
||||
|
||||
render(<MenuComponent isOpen />);
|
||||
|
||||
expect(screen.getByRole("button", { name: "Home" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Chat" })).toHaveAttribute(
|
||||
"aria-disabled",
|
||||
"true",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("SidebarNavigationModeToggle", () => {
|
||||
@@ -210,4 +223,34 @@ describe("SidebarNavigationModeToggle", () => {
|
||||
expect(onChange).toHaveBeenCalledWith(SIDEBAR_NAVIGATION_MODE.BROWSE);
|
||||
expect(pushMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("blocks Chat and shows the cloud tooltip when chat is unavailable", async () => {
|
||||
// Given
|
||||
const user = userEvent.setup();
|
||||
const onChange = vi.fn();
|
||||
|
||||
render(
|
||||
<SidebarNavigationModeToggleComponent
|
||||
isOpen
|
||||
value={SIDEBAR_NAVIGATION_MODE.BROWSE}
|
||||
onChange={onChange}
|
||||
chatEnabled={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
// When
|
||||
const chatButton = screen.getByRole("button", { name: "Chat" });
|
||||
await user.hover(chatButton);
|
||||
|
||||
// Then
|
||||
const tooltip = await screen.findByRole("tooltip");
|
||||
expect(tooltip).toHaveTextContent("Available in Prowler Cloud");
|
||||
|
||||
// When
|
||||
await user.click(chatButton);
|
||||
|
||||
// Then
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
expect(pushMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -116,13 +116,12 @@ export const Menu = ({ isOpen }: { isOpen: boolean }) => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{isCloudEnv && (
|
||||
<SidebarNavigationModeToggle
|
||||
isOpen={isOpen}
|
||||
value={navigationMode}
|
||||
onChange={setNavigationMode}
|
||||
/>
|
||||
)}
|
||||
<SidebarNavigationModeToggle
|
||||
isOpen={isOpen}
|
||||
value={navigationMode}
|
||||
onChange={setNavigationMode}
|
||||
chatEnabled={isCloudEnv}
|
||||
/>
|
||||
|
||||
{/* Menu Items */}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
|
||||
Reference in New Issue
Block a user