Ui componentsReact

Trigger the Inkeep modal with a custom trigger (React)

Copy page

Use the "Custom Trigger" if you want to use your own button, search bar, link, or any other UI element for opening and closing Inkeep's modal. This is an alternative to using the Inkeep SearchBar or ChatButton components.

Overview

The Inkeep modal can contain search, chat, or a combined experience.

The available modal components are:

ComponentDescription
InkeepModalSearchAndChatCombined search and chat experience with a toggle for switching.
InkeepModalSearchSearch-only experience
InkeepModalChatChat-only experience

Quick Start

Install the component library

Define the component

Lets start with the InkeepModalSearchAndChat. To trigger the modal, you configure the isOpen property to be true or false based on whether the user clicks on your own custom trigger.

import React, { useState, useRef, useCallback } from "react";
import {
  InkeepModalSearchAndChat,
  type InkeepModalSearchAndChatProps,
} from "@inkeep/cxkit-react";
 
const App = () => {
  const [isOpen, setIsOpen] = useState(false);
 
  const config: InkeepModalSearchAndChatProps = {
    defaultView: "chat", // or "search"
    forceDefaultView: true, // always open with the `defaultView`
    baseSettings: {
      apiKey: "YOUR_API_KEY",
      primaryBrandColor: "#000000",
    },
    modalSettings: {
      isOpen,
      onOpenChange: handleOpenChange,
    },
    aiChatSettings: {
      aiAssistantName: "Keepie",
    },
    searchSettings: {
      placeholder: "Search...",
    },
  };
 
  const handleOpenChange = useCallback((newOpen: boolean) => {
    setIsOpen(newOpen);
  }, []);
 
  return (
    <>
      {/* Your Custom Trigger */}
      <button onClick={() => setIsOpen(true)}>Open Modal</button>
 
      {/* The Inkeep Modal Component */}
      <InkeepModalSearchAndChat {...config} />
    </>
  );
};

Modal settings control the behavior and interaction of modal components. These settings are passed in the modalSettings prop.

SettingTypeDefaultDescription
isOpenbooleanfalseControls the visibility of the modal. Set to true to show the modal, false to hide it.
onOpenChange(isOpen: boolean) => void-Callback function triggered when the modal's open state changes. Useful for syncing state with your application.
shortcutKeystring | null-The keyboard key that triggers the modal when pressed with Cmd (Mac) or Ctrl (Windows). Set to null to disable the shortcut.
triggerSelectorstring'[data-inkeep-modal-trigger]'The selector for the trigger element that opens the modal. If you add a button with the data-inkeep-modal-trigger attribute, you do not need to implement your own onOpenChange handler or pass the isOpen prop to the modalSettings.

A modal version of the embedded search component. For detailed information about search functionality and available settings, see Embedded Search.

import React, { useState, useRef, useCallback } from "react";
import {
  InkeepModalSearch,
  type InkeepModalSearchProps,
} from "@inkeep/cxkit-react";
 
const App = () => {
  const [isOpen, setIsOpen] = useState(false);
  const searchFunctionsRef = useRef<SearchFunctions | null>(null);
 
  const config: InkeepModalSearchProps = {
    baseSettings: {
      apiKey: "YOUR_API_KEY",
      primaryBrandColor: "#000000",
    },
    searchSettings: {
      placeholder: "Search...",
      searchFunctionsRef,
    },
    modalSettings: {
      isOpen,
      onOpenChange: handleOpenChange,
    },
  };
 
  const handleOpenChange = useCallback((newOpen: boolean) => {
    setIsOpen(newOpen);
  }, []);
 
  // Access search methods
  const updateQuery = () => {
    searchFunctionsRef.current?.updateQuery("Hello!");
  };
 
  return (
    <>
      {/* Custom Trigger */}
      <button onClick={() => setIsOpen(true)}>Open Search Modal</button>
 
      {/* Modal Component */}
      <InkeepModalSearch {...config} />
 
      {/* Update Query */}
      <button onClick={updateQuery}>Update Query</button>
    </>
  );
};

A modal version of the embedded chat component. For detailed information about chat functionality and available settings, see Embedded Chat.

import React, { useState, useRef, useCallback } from "react";
import {
  InkeepModalChat,
  type InkeepModalChatProps,
} from "@inkeep/cxkit-react";
 
const App = () => {
  const [isOpen, setIsOpen] = useState(false);
  const chatFunctionsRef = useRef<ChatFunctions | null>(null);
 
  const config: InkeepModalChatProps = {
    baseSettings: {
      apiKey: "YOUR_API_KEY",
      primaryBrandColor: "#000000",
    },
    aiChatSettings: {
      aiAssistantName: "Keepie",
    },
    modalSettings: {
      isOpen,
      onOpenChange: handleOpenChange,
    },
  };
 
  const handleOpenChange = useCallback((newOpen: boolean) => {
    setIsOpen(newOpen);
  }, []);
 
  // Access chat methods
  const clearChat = () => {
    chatFunctionsRef.current?.clearChat();
  };
 
  return (
    <>
      {/* Custom Trigger */}
      <button onClick={() => setIsOpen(true)}>Open Chat Modal</button>
 
      {/* Modal Component */}
      <InkeepModalChat {...config} />
 
      {/* Clear Chat */}
      <button onClick={clearChat}>Clear Chat</button>
    </>
  );
};

Component Methods

Chat Methods

MethodDescription
submitMessage(message?: string)Programmatically sends a message in chat. If message is omitted, sends the current input value.
updateInputMessage(message: string)Updates the text in chat input field
clearChat()Resets the chat to its initial state
openForm(formSettings: FormSettings)Displays a form overlay in chat interface
focusInput()Sets focus to the chat input field

Refer to the Form Settings reference docs for more details on the available properties for the openForm method.

Search methods

MethodDescription
updateQuery(query: string)Programmatically updates the search query.
focusInput()Sets focus to the search input field

Widget methods

type ModalViewTypes = "search" | "chat";
MethodDescription
setView(view: ModalViewTypes)Set the view of the widget to either search or chat

FAQ

If you use a webpack build. You could come across this error. To fix this you need to create a custom loader for your webpack configuration to disable this behavior.

Since webpack 5.0.0-beta.30, you're required to specify extensions when using imports in .mjs files or any .js files with a package.json with "type": "module". You can still disable the behavior with resolve.fullySpecified set to false if you see any related errors in your project.

We can add a new rule to our webpack configuration to disable this behavior.

module.exports = {
    module: {
        rules: [
            {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false,
                },
            },
        ],
    },
};

Then add this to your webpack.config.js file.

If you use docusaurus, you can add this to your docusaurus.config.js file as a webpack config override with plugins.

/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
plugins: [
    () => {
    return {
        name: "loader",
        configureWebpack() {
        return {
            module: {
            rules: [
                {
                test: /\.m?js/,
                resolve: {
                    fullySpecified: false,
                },
                },
            ],
            },
        };
        },
    };
    },
],
// ...
};
 
module.exports = config;

On this page