Shopping Assistant SDK
Chat

Chat

Overview

The Chat component is a core UI component of the Shopping Assistant SDK that renders the complete chat interface, including conversation messages, initial prompts, loading states, and message rendering. It provides a fully functional chat experience with support for user messages, AI responses, product displays, and customizable styling.

Usage

// importing component
import { Chat } from "@unbxd-ui/react-shopping-assistant-components";

Code Example

import { UnbxdShoppingAssistantWrapper } from "@unbxd-ui/react-shopping-assistant-hooks";
import { Chat } from "@unbxd-ui/react-shopping-assistant-components";
 
function ShoppingAssistantApp() {
  return (
    <UnbxdShoppingAssistantWrapper 
      siteKey="YOUR_SITE_KEY" 
      apiKey="YOUR_API_KEY"
      storageType="LOCALSTORAGE"
    >
      <div className="chat-container">
        <Chat />
      </div>
    </UnbxdShoppingAssistantWrapper>
  );
}
⚠️
Note:

The Chat component must be used within the UnbxdShoppingAssistantWrapper to ensure that the component and the shopping assistant functionality work properly.

Props

InitialMessageComponent

optional
React Component
  • A custom component to display an initial welcome message when the chat loads.
  • This component appears above the chat messages and initial prompts.
  • Default Value:
const InitialMessageComponent = () => {
	return (
		<div className="initial-message-component">
			👋 Hi there! I'm your Furniture Shopping Assistant, ready to help you find exactly what you're looking for. ✨ — What would you like to shop for today?
			<br />
			<br />
			Ask me anything, or try one of these to get started:
		</div>
	);
};

InitialPromptsComponent

optional
React Component
  • A custom component that displays clickable prompt suggestions to help users get started with the shopping assistant.
  • Shows predefined example questions that users can click to automatically ask the AI agent.
  • Useful for onboarding new users and showcasing the types of queries the assistant can handle.
  • Each prompt is interactive and will trigger a conversation when clicked.
  • Default Value:
 
const InitialPrompts = (props: InitialPromptsProps) => {
	const {
		onPromptClick = defaultInitialPromptsProps.onPromptClick,
	} = props;
	
	const prompts = [
		"Help me find a dining table for 6 people",
		"What's trending in bedroom furniture?",
		"I need outdoor patio furniture recommendations",
		"Show me modern sofas under $1000",
		"Find storage solutions for small spaces",
		"Suggest ergonomic office chairs"
	]
 
	const { askAgent } = useShoppingAssistant();
 
	const handlePromptClick = (prompt: string) => {
		onPromptClick && onPromptClick(prompt);
		askAgent(prompt);
	};
 
	const renderInitialPrompts = () => {
		if (!prompts) return null;
		return prompts.map((prompt: string) => <InitialPrompt prompt={prompt} onPromptClick={() => handlePromptClick(prompt)} key={prompt} />);
	};
 
	return (
		<div className="initial-prompts-container">
			<div className="initial-prompts-label">{""}</div>
			<div className="initial-prompts-wrapper">{renderInitialPrompts()}</div>
		</div>
	);	
};

LoadingComponent

optional
React Component
  • A custom component to display while the AI is processing and generating responses.
  • Shows during API calls and conversation loading states.
  • Default Value:
const LoadingComponent = () => {
	return <div className="loading-component">Awaiting response...</div>;
};

UserIconComponent

optional
React Component
  • A custom icon component to display next to user messages.
  • Helps distinguish user messages in the conversation.
  • Default Value:
const UserIconComponent = () => {
	return <>Me</>;
};

AIIconComponent

optional
React Component
  • A custom icon component to display next to AI assistant messages.
  • Helps distinguish AI responses in the conversation.
  • Default Value:
const AIIconComponent = () => {
	return <>AI</>;
};

UserMessageComponent

optional
React Component
  • A custom component for rendering user messages in the chat.
  • Receives message and UserIconComponent as props.
  • Default Value:
const UserMessage = ({ message, UserIconComponent }: UserMessageProps) => {
    return <div className="user-message-container">
        <div className="user-message-text">
            {message}
        </div>
        <div className="user-message-icon-wrapper">
            {UserIconComponent && <UserIconComponent />}
        </div>
    </div>;
};

AIMessageComponent

optional
React Component
  • A custom component for rendering AI assistant messages in the chat.
  • Receives response, AIIconComponent, and other props for products and filters.
  • Default Value: Built-in AIMessage component with product display support.
const AIMessage = ({ response, AIIconComponent, viewMore = false, viewMoreLimit = 5, ProductComponent, FiltersComponent = Filters }: AIMessageProps) => {
	const { message, products = [], filters = [] } = response;
 
	const handleFilterClick = (field: string, option: string) => {
		// console.log(field, option);
	};
 
	const renderFilters = () => {
		return filters.map((filter: { [key: string]: any }) => {
			const { field, options } = filter;
			return <FiltersComponent key={field} field={field} options={options} onFilterClick={handleFilterClick} viewMore={viewMore} viewMoreLimit={viewMoreLimit} />;
		});
	};
 
	return (
		<div className="ai-message-container">
			<div className="ai-message-icon-wrapper">
				{AIIconComponent && <AIIconComponent />}
			</div>
			<div className="ai-message-wrapper">
				{message && <div className="ai-message-text">{message}</div>}
				{filters.length > 0 && renderFilters()}
				{products.length > 0 && <ProductCarousel label="Recommended Products:" products={products} ProductComponent={ProductComponent} />}
			</div>
		</div>
	);
};

Products

optional
React Component
  • A custom component for displaying all product recommendations from the AI assistant.
  • Renders products returned by the AI in response to user queries.
  • Includes navigation controls for browsing through multiple products.
  • Default Value:
const ProductCarousel = (props: ProductCarouselProps) => {
	const {
		products = defaultProductCarouselProps.products,
	} = props;
 
	const [currentIndex, setCurrentIndex] = useState(0);
	const productRefs = useRef<(HTMLDivElement | null)[]>([]);
 
	const renderProducts = () => {
		return products.map((product: { [key: string]: any }, idx: number) => (
			<div key={idx} ref={(el) => (productRefs.current[idx] = el)} style={{ display: "inline-block" }}>
				<ProductComponent product={product} />
			</div>
		));
	};
 
	const scrollToProduct = (index: number) => {
		const ref = productRefs.current[index];
		if (ref) {
			ref.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
		}
	};
 
	const handlePrev = () => {
		if (currentIndex > 0) {
			const newIndex = currentIndex - 1;
			setCurrentIndex(newIndex);
			scrollToProduct(newIndex);
		}
	};
 
	const handleNext = () => {
		if (currentIndex < products.length - 1) {
			const newIndex = currentIndex + 1;
			setCurrentIndex(newIndex);
			scrollToProduct(newIndex);
		}
	};
 
	return (
		<div className="product-carousel-container">
			<div className="product-carousel-header">
				<div className="product-carousel-label">{'Recommended Products:'}</div>
				<div className="navigation-buttons">
					<button className="prev-button" onClick={handlePrev} disabled={currentIndex === 0}>
						<ArrowLeftIcon />
					</button>
					<button className="next-button" onClick={handleNext} disabled={currentIndex === products.length - 1}>
						<ArrowRightIcon />
					</button>
				</div>
			</div>
			<div className="product-carousel-products" style={{ overflowX: "auto", width: "100%" }}>
				{renderProducts()}
			</div>
		</div>
	);
};

FiltersComponent

optional
React Component
  • A custom component for rendering filter options in AI responses.
  • Handles filter display and user interaction with search filters.
  • Default Value:
const Filters = ({ field, options, onFilterClick, viewMore = false, viewMoreLimit = 5 }: FiltersProps) => {
    const { askAgent } = useShoppingAssistant();
 
    const [filtersShown, setFiltersShown] = useState(options.slice(0, viewMore ? viewMoreLimit : options.length));
 
    const handleFilterClick = (option: string) => {
        askAgent(option, { field, options: [option] });
        onFilterClick && onFilterClick(field, option);
    };
 
    const handleViewClick = () => {
        setFiltersShown(filtersShown.length === options.length ? options.slice(0, viewMoreLimit) : options);
    }
 
    const renderFilters = () => {
        return filtersShown.map((option: string) => (
            <div
                className={`filter-option`}
                key={option}
                onClick={() => handleFilterClick(option)}
            >
                {option}
            </div>
        ));
    }
 
    const renderViewText = () => {
        const viewText = filtersShown.length === options.length ? "View Less" : "View More";
 
        if (options.length <= viewMoreLimit) return null;
        return <div className="view-more-container" onClick={handleViewClick}>{viewText}</div>
    }
 
    return <div className="filters-container">
        <div className="filter-label">{field}</div>
        <div className="filter-option-wrapper">
            {renderFilters()}
            {viewMore && renderViewText()}
        </div>
    </div>;
};

Related Components