|
diff --git a/packages/lib/src/sidenav/Sidenav.accessibility.test.tsx b/packages/lib/src/sidenav/Sidenav.accessibility.test.tsx
index 157d20d52..7b2ac21e1 100644
--- a/packages/lib/src/sidenav/Sidenav.accessibility.test.tsx
+++ b/packages/lib/src/sidenav/Sidenav.accessibility.test.tsx
@@ -47,7 +47,9 @@ describe("Sidenav component accessibility tests", () => {
],
},
];
- const { container } = render();
+ const { container } = render(
+
+ );
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});
diff --git a/packages/lib/src/sidenav/Sidenav.stories.tsx b/packages/lib/src/sidenav/Sidenav.stories.tsx
index 8c47a0845..e0a68423d 100644
--- a/packages/lib/src/sidenav/Sidenav.stories.tsx
+++ b/packages/lib/src/sidenav/Sidenav.stories.tsx
@@ -140,6 +140,7 @@ const Sidenav = () => (
@@ -169,6 +170,7 @@ const Sidenav = () => (
@@ -208,6 +210,7 @@ const Collapsed = () => {
@@ -261,6 +264,7 @@ const Collapsed = () => {
@@ -314,6 +318,7 @@ const Collapsed = () => {
@@ -373,6 +378,7 @@ const Hovered = () => (
@@ -405,6 +411,7 @@ const SelectedGroup = () => (
diff --git a/packages/lib/src/sidenav/Sidenav.test.tsx b/packages/lib/src/sidenav/Sidenav.test.tsx
index eb0edfc1c..cbbc8c717 100644
--- a/packages/lib/src/sidenav/Sidenav.test.tsx
+++ b/packages/lib/src/sidenav/Sidenav.test.tsx
@@ -1,5 +1,5 @@
import "@testing-library/jest-dom";
-import { render, fireEvent } from "@testing-library/react";
+import { render, fireEvent, waitFor } from "@testing-library/react";
import DxcSidenav from "./Sidenav";
import { ReactNode } from "react";
@@ -103,4 +103,21 @@ describe("DxcSidenav component", () => {
const collapseButton = getByRole("button", { name: "Collapse" });
expect(collapseButton).toBeTruthy();
});
+
+ test("Sidenav renders search bar when searchBar prop is provided", () => {
+ const { getByPlaceholderText } = render();
+ expect(getByPlaceholderText("Search...")).toBeTruthy();
+ });
+
+ test("Sidenav expands and focuses search input when handleExpandSearch is called", async () => {
+ const { getByRole, getByPlaceholderText } = render(
+
+ );
+ const expandButton = getByRole("button", { name: "Search" });
+ fireEvent.click(expandButton);
+ const searchInput = getByPlaceholderText("Search...") as HTMLInputElement;
+ await waitFor(() => {
+ expect(document.activeElement).toBe(searchInput);
+ });
+ });
});
diff --git a/packages/lib/src/sidenav/Sidenav.tsx b/packages/lib/src/sidenav/Sidenav.tsx
index 8d2292058..7481e199e 100644
--- a/packages/lib/src/sidenav/Sidenav.tsx
+++ b/packages/lib/src/sidenav/Sidenav.tsx
@@ -5,10 +5,12 @@ import SidenavPropsType from "./types";
import DxcDivider from "../divider/Divider";
import DxcButton from "../button/Button";
import DxcImage from "../image/Image";
-import { useContext, useState } from "react";
+import { useContext, useRef, useState } from "react";
import DxcNavigationTree from "../navigation-tree/NavigationTree";
import DxcInset from "../inset/Inset";
import ApplicationLayoutContext from "../layout/ApplicationLayoutContext";
+import DxcSearchBar from "../search-bar/SearchBar";
+import DxcSearchBarTrigger from "../search-bar/SearchBarTrigger";
const SidenavContainer = styled.div<{ expanded: boolean }>`
box-sizing: border-box;
@@ -67,16 +69,26 @@ const DxcSidenav = ({
expanded,
defaultExpanded = true,
onExpandedChange,
+ searchBar,
}: SidenavPropsType): JSX.Element => {
const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);
const { logo, headerExists } = useContext(ApplicationLayoutContext);
const isControlled = expanded !== undefined;
const isExpanded = isControlled ? !!expanded : internalExpanded;
+ const shouldFocusSearchBar = useRef(false);
const handleToggle = () => {
const nextState = !isExpanded;
if (!isControlled) setInternalExpanded(nextState);
onExpandedChange?.(nextState);
+ if (searchBar && nextState === false) {
+ shouldFocusSearchBar.current = false;
+ }
+ };
+
+ const handleExpandSearch = () => {
+ shouldFocusSearchBar.current = true;
+ handleToggle();
};
return (
@@ -114,8 +126,14 @@ const DxcSidenav = ({
{appTitle}
- {topContent && (
+ {(topContent || searchBar) && (
+ {searchBar &&
+ (isExpanded ? (
+
+ ) : (
+
+ ))}
{topContent}
)}
diff --git a/packages/lib/src/sidenav/types.ts b/packages/lib/src/sidenav/types.ts
index 378fd196f..5a315b75a 100644
--- a/packages/lib/src/sidenav/types.ts
+++ b/packages/lib/src/sidenav/types.ts
@@ -1,5 +1,6 @@
import { ReactElement, ReactNode } from "react";
import { SVG } from "../common/utils";
+import { SearchBarProps } from "../search-bar/types";
type Section = { items: (Item | GroupItem)[]; title?: string };
@@ -34,6 +35,10 @@ type Props = {
* Function called when the expansion state of the sidenav changes.
*/
onExpandedChange?: (value: boolean) => void;
+ /**
+ * When provided, a search bar will be rendered at the top of the sidenav.
+ */
+ searchBar?: Omit;
/**
* The additional content rendered in the upper part of the sidenav, under the branding.
*/
|