diff --git a/packages/lib/src/search-bar/SearchBar.accessibility.test.tsx b/packages/lib/src/search-bar/SearchBar.accessibility.test.tsx
new file mode 100644
index 000000000..36671272f
--- /dev/null
+++ b/packages/lib/src/search-bar/SearchBar.accessibility.test.tsx
@@ -0,0 +1,58 @@
+import { render } from "@testing-library/react";
+import DxcSearchBar from "./SearchBar";
+import DxcSearchBarTrigger from "./SearchBarTrigger";
+import { axe } from "../../test/accessibility/axe-helper";
+
+describe("SearchBar component accessibility tests", () => {
+ it("Should not have basic accessibility issues", async () => {
+ const { container } = render();
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+
+ it("Should not have basic accessibility issues with placeholder", async () => {
+ const { container } = render();
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+
+ it("Should not have basic accessibility issues with disabled state", async () => {
+ const { container } = render();
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+
+ it("Should not have basic accessibility issues with cancel button", async () => {
+ const { container } = render( {}} />);
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+
+ it("Should not have basic accessibility issues with all props", async () => {
+ const { container } = render(
+ {}}
+ onEnter={() => {}}
+ onBlur={() => {}}
+ onCancel={() => {}}
+ />
+ );
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+});
+
+describe("SearchBarTrigger component accessibility tests", () => {
+ it("Should not have basic accessibility issues", async () => {
+ const { container } = render();
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+
+ it("Should not have basic accessibility issues with onTriggerClick", async () => {
+ const { container } = render( {}} />);
+ const results = await axe(container);
+ expect(results.violations).toHaveLength(0);
+ });
+});
diff --git a/packages/lib/src/search-bar/SearchBar.stories.tsx b/packages/lib/src/search-bar/SearchBar.stories.tsx
new file mode 100644
index 000000000..048145b97
--- /dev/null
+++ b/packages/lib/src/search-bar/SearchBar.stories.tsx
@@ -0,0 +1,126 @@
+import { Meta, StoryObj } from "@storybook/react-vite";
+import ExampleContainer from "../../.storybook/components/ExampleContainer";
+import Title from "../../.storybook/components/Title";
+import DxcSearchBarTrigger from "./SearchBarTrigger";
+import { useState } from "react";
+import DxcSearchBar from "./SearchBar";
+import DxcFlex from "../flex/Flex";
+import DxcContainer from "../container/Container";
+
+export default {
+ title: "Searchbar",
+ component: DxcSearchBar,
+} satisfies Meta;
+
+const SearchBarComponent = () => {
+ const [showSearch, setShowSearch] = useState(false);
+
+ return (
+
+ {!showSearch ? (
+ setShowSearch(!showSearch)} />
+ ) : (
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ setShowSearch(false);
+ }}
+ onCancel={() => setShowSearch(false)}
+ />
+ )}
+
+ );
+};
+
+const SearchBar = () => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ }}
+ />
+
+
+
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ }}
+ />
+
+
+
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ }}
+ />
+
+
+
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ }}
+ disabled
+ />
+
+
+
+
+
+ {
+ console.log("onBlur", value);
+ }}
+ onChange={(value) => console.log("onChange", value)}
+ onEnter={(value) => {
+ console.log("onEnter", value);
+ }}
+ />
+
+
+ >
+ );
+};
+
+type Story = StoryObj;
+
+export const Chromatic: Story = {
+ render: SearchBar,
+};
diff --git a/packages/lib/src/search-bar/SearchBar.test.tsx b/packages/lib/src/search-bar/SearchBar.test.tsx
new file mode 100644
index 000000000..2a59203c0
--- /dev/null
+++ b/packages/lib/src/search-bar/SearchBar.test.tsx
@@ -0,0 +1,99 @@
+import { render, fireEvent } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import DxcSearchBar from "./SearchBar";
+import DxcSearchBarTrigger from "./SearchBarTrigger";
+
+describe("SearchBarTrigger component tests", () => {
+ test("Renders correctly", () => {
+ const { getByRole } = render();
+
+ const button = getByRole("button");
+ expect(button).toBeTruthy();
+ });
+
+ test("Calls onTriggerClick when button is clicked", () => {
+ const onTriggerClick = jest.fn();
+ const { getByRole } = render();
+
+ const button = getByRole("button");
+ userEvent.click(button);
+
+ expect(onTriggerClick).toHaveBeenCalledTimes(1);
+ });
+});
+
+describe("SearchBar component tests", () => {
+ test("Renders correctly", () => {
+ const { getByPlaceholderText } = render();
+
+ const text = getByPlaceholderText("Search...");
+ expect(text).toBeTruthy();
+ });
+
+ test("Calls onChange when typing", () => {
+ const onChange = jest.fn();
+ const { getByRole } = render();
+
+ const input = getByRole("textbox") as HTMLInputElement;
+ userEvent.type(input, "hello");
+
+ expect(onChange).toHaveBeenCalled();
+ expect(onChange).toHaveBeenLastCalledWith("hello");
+ });
+
+ test("Calls onEnter with value when pressing Enter", () => {
+ const onEnter = jest.fn();
+ const { getByRole } = render();
+
+ const input = getByRole("textbox") as HTMLInputElement;
+ userEvent.type(input, "search text");
+ fireEvent.keyDown(input, { key: "Enter" });
+
+ expect(onEnter).toHaveBeenCalledTimes(1);
+ expect(onEnter).toHaveBeenCalledWith("search text");
+ });
+
+ test("Clears value when clicking clear icon", () => {
+ const { getByRole } = render();
+
+ const input = getByRole("textbox") as HTMLInputElement;
+ userEvent.type(input, "abc");
+
+ const clearButton = getByRole("button");
+ expect(clearButton).toBeTruthy();
+
+ userEvent.click(clearButton);
+ expect(input.value).toBe("");
+ });
+
+ test("Clears value when pressing Escape", () => {
+ const { getByRole } = render();
+
+ const input = getByRole("textbox") as HTMLInputElement;
+ userEvent.type(input, "xyz");
+ fireEvent.keyDown(input, { key: "Escape" });
+
+ expect(input.value).toBe("");
+ });
+
+ test("Calls onBlur with current value when blurred", () => {
+ const onBlur = jest.fn();
+ const { getByRole } = render();
+
+ const input = getByRole("textbox") as HTMLInputElement;
+ userEvent.type(input, "blur me");
+ fireEvent.blur(input);
+
+ expect(onBlur).toHaveBeenCalledWith("blur me");
+ });
+
+ test("Calls onCancel when Cancel button is clicked", () => {
+ const onCancel = jest.fn();
+ const { getByRole } = render();
+
+ const cancelButton = getByRole("button", { name: /Cancel/i });
+ userEvent.click(cancelButton);
+
+ expect(onCancel).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/packages/lib/src/search-bar/SearchBar.tsx b/packages/lib/src/search-bar/SearchBar.tsx
new file mode 100644
index 000000000..fe3b8e058
--- /dev/null
+++ b/packages/lib/src/search-bar/SearchBar.tsx
@@ -0,0 +1,138 @@
+import styled from "@emotion/styled";
+import DxcButton from "../button/Button";
+import DxcFlex from "../flex/Flex";
+import { SearchBarProps } from "./types";
+import DxcActionIcon from "../action-icon/ActionIcon";
+import { KeyboardEvent, useContext, useRef, useState } from "react";
+import { HalstackLanguageContext } from "../HalstackContext";
+import { css } from "@emotion/react";
+import DxcIcon from "../icon/Icon";
+
+const SearchBarContainer = styled.div<{ disabled: Required["disabled"] }>`
+ width: 100%;
+ min-width: 200px;
+ max-width: 720px;
+ height: var(--height-m);
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-gap-s);
+ border-radius: var(--border-radius-xl);
+ border: var(--border-width-s) var(--border-style-default) var(--border-color-neutral-dark);
+ box-sizing: border-box;
+ padding: 0 var(--spacing-padding-s);
+ color: var(--color-fg-neutral-dark);
+
+ ${({ disabled }) =>
+ !disabled
+ ? css`
+ &:hover {
+ border-color: var(--border-color-primary-strong);
+ }
+ &:focus,
+ &:focus-within,
+ &:focus-visible {
+ border-color: transparent;
+ outline-offset: -2px;
+ outline: var(--border-width-m) var(--border-style-default) var(--border-color-secondary-medium);
+ }
+ `
+ : css`
+ color: var(--color-fg-neutral-medium);
+ border-color: var(--border-color-neutral-strong);
+ cursor: not-allowed;
+ `}
+`;
+
+const SearchBarInput = styled.input<{ disabled: Required["disabled"] }>`
+ width: 100%;
+ max-width: 100%;
+ background: none;
+ border: none;
+ outline: none;
+ padding: 0;
+ font-family: var(--typography-font-family);
+ font-size: var(--typography-label-m);
+ font-weight: var(--typography-label-regular);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ cursor: ${({ disabled }) => (disabled ? "not-allowed" : "text")};
+`;
+
+const DxcSearchBar = ({
+ autoFocus,
+ disabled = false,
+ onBlur,
+ onCancel,
+ onChange,
+ onEnter,
+ placeholder,
+}: SearchBarProps) => {
+ const translatedLabels = useContext(HalstackLanguageContext);
+ const inputRef = useRef(null);
+ const [innerValue, setInnerValue] = useState("");
+
+ const handleClearActionOnClick = () => {
+ setInnerValue("");
+ inputRef.current?.focus();
+ };
+
+ const handleSearchChangeValue = (value: string) => {
+ setInnerValue(value);
+ if (typeof onChange === "function") {
+ onChange(value);
+ }
+ };
+
+ const handleInputOnKeyDown = (e: KeyboardEvent) => {
+ switch (e.key) {
+ case "Esc":
+ case "Escape":
+ e.preventDefault();
+ if (innerValue.length > 0) {
+ handleClearActionOnClick();
+ }
+ break;
+ case "Enter":
+ if (typeof onEnter === "function") {
+ onEnter(innerValue);
+ }
+ break;
+ default:
+ break;
+ }
+ };
+
+ return (
+
+
+
+ typeof onBlur === "function" && onBlur(e.target.value)}
+ onChange={(e) => handleSearchChangeValue(e.target.value)}
+ onKeyDown={handleInputOnKeyDown}
+ disabled={disabled}
+ />
+ {!disabled && innerValue.length > 0 && (
+
+ )}
+
+
+ {typeof onCancel === "function" && (
+
+ )}
+
+ );
+};
+
+export default DxcSearchBar;
diff --git a/packages/lib/src/search-bar/SearchBarTrigger.tsx b/packages/lib/src/search-bar/SearchBarTrigger.tsx
new file mode 100644
index 000000000..26b647747
--- /dev/null
+++ b/packages/lib/src/search-bar/SearchBarTrigger.tsx
@@ -0,0 +1,15 @@
+import DxcButton from "../button/Button";
+import { SearchBarTriggerProps } from "./types";
+
+const DxcSearchBarTrigger = ({ onTriggerClick }: SearchBarTriggerProps) => (
+
+);
+
+export default DxcSearchBarTrigger;
diff --git a/packages/lib/src/search-bar/types.ts b/packages/lib/src/search-bar/types.ts
new file mode 100644
index 000000000..5d67a8f39
--- /dev/null
+++ b/packages/lib/src/search-bar/types.ts
@@ -0,0 +1,36 @@
+export type SearchBarTriggerProps = {
+ /**
+ * Function invoked when the trigger button is clicked.
+ */
+ onTriggerClick?: () => void;
+};
+export type SearchBarProps = {
+ /**
+ * If true, the search bar input will be focused when rendered.
+ */
+ autoFocus?: boolean;
+ /**
+ * If true, the component will be disabled.
+ */
+ disabled?: boolean;
+ /**
+ * Function invoked when the search bar loses focus.
+ */
+ onBlur?: (value: string) => void;
+ /**
+ * Function invoked when the user cancels the search.
+ */
+ onCancel?: () => void;
+ /**
+ * Function invoked when the user changes the input value.
+ */
+ onChange?: (value: string) => void;
+ /**
+ * Function invoked when the Enter key is pressed.
+ */
+ onEnter?: (value: string) => void;
+ /**
+ * Placeholder text displayed in the search bar input field.
+ */
+ placeholder?: string;
+};