diff --git a/__tests__/components/features/sidebar/sidebar.test.tsx b/__tests__/components/features/sidebar/sidebar.test.tsx index 711089fd5..6fa00a40e 100644 --- a/__tests__/components/features/sidebar/sidebar.test.tsx +++ b/__tests__/components/features/sidebar/sidebar.test.tsx @@ -7,6 +7,7 @@ import { type NavigationContextValue, } from "#/context/navigation-context"; import translations from "#/i18n/translation.json"; +import { OPENHANDS_SLACK_INVITE_URL } from "#/utils/constants"; // The global `useTranslation` mock in `vitest.setup.ts` returns the key // as-is. Override it here so `t(...)` resolves keys via the source-of-truth @@ -396,6 +397,26 @@ describe("Sidebar", () => { } }); + it("renders a Join Slack link in the expanded sidebar footer", () => { + renderSidebar("/conversations"); + + const link = screen.getByTestId("sidebar-join-slack-link"); + expect(link).toHaveAttribute("href", OPENHANDS_SLACK_INVITE_URL); + expect(link).toHaveAttribute("target", "_blank"); + expect(link).toHaveAttribute("rel", "noopener noreferrer"); + expect(link).toHaveTextContent("Join Slack"); + }); + + it("renders a Join Slack icon link when the sidebar is collapsed", () => { + window.localStorage.setItem("openhands-sidebar-collapsed", "true"); + renderSidebar("/conversations"); + + const link = screen.getByTestId("collapsed-join-slack-link"); + expect(link).toHaveAttribute("href", OPENHANDS_SLACK_INVITE_URL); + expect(link).toHaveAttribute("target", "_blank"); + expect(link).toHaveAttribute("aria-label", "Join Slack"); + }); + it("renders the renamed top-level nav labels", () => { // Arrange renderSidebar("/conversations"); diff --git a/src/components/features/sidebar/sidebar.tsx b/src/components/features/sidebar/sidebar.tsx index 0fe8a658a..c3b20bda3 100644 --- a/src/components/features/sidebar/sidebar.tsx +++ b/src/components/features/sidebar/sidebar.tsx @@ -7,6 +7,7 @@ import { Server, Settings, } from "lucide-react"; +import { SiSlack } from "react-icons/si"; import { OpenHandsLogoButton } from "#/components/shared/buttons/openhands-logo-button"; import { SidebarNavLink } from "./sidebar-nav-link"; import { getErrorStatus, useSettings } from "#/hooks/query/use-settings"; @@ -23,6 +24,7 @@ import { SidebarCollapseContext } from "./sidebar-collapse-context"; import { useSidebarCollapsedState } from "#/hooks/use-sidebar-collapsed"; import { useClickOutsideElement } from "#/hooks/use-click-outside-element"; import { useBackendsHealth } from "#/hooks/query/use-backends-health"; +import { OPENHANDS_SLACK_INVITE_URL } from "#/utils/constants"; import AutomationsIcon from "#/icons/automations.svg?react"; // The LLM settings modal is only mounted when the settings query 404s and @@ -147,6 +149,7 @@ export function Sidebar() { currentPath.startsWith("/skills") || currentPath === "/plugins" || currentPath === "/mcp"; + const joinSlackLabel = t(I18nKey.SIDEBAR$JOIN_SLACK); return ( @@ -327,6 +330,16 @@ export function Sidebar() { {collapsed && (
+ + +