Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/js/getting-started/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ <h1 class="header-title">
<div id="trending"></div>
</div>
</div>

<div id="chat"></div>
</div>

<script type="module" src="./src/app.js"></script>
<script type="module" src="./src/app.tsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions examples/js/getting-started/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,25 @@
rgba(255, 255, 255, 1) 100%
);
}

.ais-Chat {
display: flex;
flex-direction: column;
position: fixed;
bottom: 0;
right: 0;
background-color: #fff;
border-radius: 1rem 0 0 0;
border: 1px solid #e0e0e0;
box-shadow: 0 0 0 1px #23263b0d, 0 1px 3px #23263b26;
width: 25%;
height: 700px;
}

.ais-ChatMessages-scroll {
padding: 1rem;
}

.ais-ChatPrompt {
padding: 0 1rem 1rem 1rem;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/** @jsx h */
// @ts-check
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import instantsearch from 'instantsearch.js';
import { carousel } from 'instantsearch.js/es/templates';
Expand Down
2 changes: 2 additions & 0 deletions examples/react/default-theme/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
SearchBox,
SortBy,
ToggleRefinement,
Chat,
} from 'react-instantsearch';

import {
Expand Down Expand Up @@ -68,6 +69,7 @@ export function App() {

<div className="Container">
<div>
<Chat agentId="61a4839d-3caf-4258-bc77-32c790fa0be9" />
<DynamicWidgets>
<Panel header="Brands">
<RefinementList
Expand Down
23 changes: 23 additions & 0 deletions examples/react/e-commerce/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,26 @@ mark {
display: none;
}
}

.ais-Chat-container {
display: flex;
flex-direction: column;
position: fixed;
bottom: 0;
right: 0;
z-index: 1000;
background-color: #fff;
border-radius: 1rem 0 0 0;
border: 1px solid #e0e0e0;
box-shadow: 0 0 0 1px #23263b0d, 0 1px 3px #23263b26;
width: 25%;
height: 700px;
}

.ais-ChatMessages-scroll {
padding: 1rem;
}

.ais-ChatPrompt {
padding: 0 1rem 1rem 1rem;
}
13 changes: 11 additions & 2 deletions examples/react/e-commerce/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Highlight,
Snippet,
} from 'react-instantsearch';
import { Chat } from 'react-instantsearch/src';

import {
AlgoliaSvg,
Expand All @@ -31,7 +32,7 @@ import { ScrollTo } from './components/ScrollTo';
import getRouting from './routing';
import { formatNumber } from './utils';

import 'instantsearch.css/themes/reset.css';
import 'instantsearch.css/themes/satellite.css';

import './Theme.css';
import './App.css';
Expand Down Expand Up @@ -89,6 +90,10 @@ export function App() {
routing={routing}
insights={true}
>
<Chat
agentId="5bc03a4f-4e25-400c-9f52-a7b969d7f3da"
itemComponent={ItemComponent}
/>
<header className="header" ref={headerRef}>
<p className="header-logo">
<AlgoliaSvg />
Expand Down Expand Up @@ -271,6 +276,10 @@ function SubmitIcon() {
);
}

function ItemComponent({ item }: { item: Record<string, unknown> }) {
return <Hit hit={item as HitType} />;
}

type HitType = AlgoliaHit<{
image: string;
name: string;
Expand All @@ -288,7 +297,7 @@ function Hit({ hit }: { hit: HitType }) {
</header>

<div className="hit-info-container">
<p className="hit-category">{hit.categories[0]}</p>
{/* <p className="hit-category">{hit.categories?.[0]}</p> */}
<h1>
<Highlight attribute="name" highlightedTagName="mark" hit={hit} />
</h1>
Expand Down
3 changes: 2 additions & 1 deletion examples/react/e-commerce/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"react": "19.0.0",
"react-compound-slider": "3.4.0",
"react-dom": "19.0.0",
"react-instantsearch": "7.16.2"
"react-instantsearch": "7.16.2",
"zod": "4.0.17"
},
"devDependencies": {
"@parcel/core": "2.10.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/instantsearch-ui-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"watch:es": "yarn --silent build:es:base --watch"
},
"dependencies": {
"@babel/runtime": "^7.27.6"
"@babel/runtime": "^7.27.6",
"ai": "^5.0.18",

Check warning on line 51 in packages/instantsearch-ui-components/package.json

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

packages/instantsearch-ui-components/package.json#L51

Package dependencies with variant versions may lead to dependency hijack and confusion attacks.
"markdown-to-jsx": "^7.1.13"

Check warning on line 52 in packages/instantsearch-ui-components/package.json

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

packages/instantsearch-ui-components/package.json#L52

Package dependencies with variant versions may lead to dependency hijack and confusion attacks.
}
}
61 changes: 61 additions & 0 deletions packages/instantsearch-ui-components/src/components/chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/** @jsx createElement */
/** @jsxFrag Fragment */
import { cx } from '../../lib';

import { createChatHeaderComponent } from './ChatHeader';
import { createChatMessagesComponent } from './ChatMessages';
import { createChatPromptComponent } from './ChatPrompt';
import { createChatToggleButtonComponent } from './ChatToggleButton';

import type { Renderer } from '../../types';
import type { ChatHeaderProps } from './ChatHeader';
import type { ChatMessagesProps } from './ChatMessages';
import type { ChatPromptProps } from './ChatPrompt';
import type { ChatToggleButtonProps } from './ChatToggleButton';

export type ChatClassNames = {
container?: string | string[];
};

export type ChatProps = {
open: boolean;
headerProps: ChatHeaderProps;
toggleButtonProps: ChatToggleButtonProps;
messagesProps: ChatMessagesProps;
promptProps: ChatPromptProps;
classNames?: Partial<ChatClassNames>;
};

export function createChatComponent({ createElement, Fragment }: Renderer) {
const ChatToggleButton = createChatToggleButtonComponent({
createElement,
Fragment,
});
const ChatHeader = createChatHeaderComponent({ createElement, Fragment });
const ChatMessages = createChatMessagesComponent({ createElement, Fragment });
const ChatPrompt = createChatPromptComponent({ createElement, Fragment });

return function Chat({
open,
headerProps,
toggleButtonProps,
messagesProps,
promptProps,
classNames = {},
}: ChatProps) {
return (
<>
{!open ? (
<ChatToggleButton {...toggleButtonProps} />
) : (
<div className={cx('ais-Chat-container', classNames.container)}>
<ChatHeader {...headerProps} />
<ChatMessages {...messagesProps} />

<ChatPrompt {...promptProps} />
</div>
)}
</>
);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/** @jsx createElement */
import { cx } from '../../lib';

import type { Renderer, ComponentProps } from '../../types';

export type ChatHeaderClassNames = {
root?: string | string[];
title?: string | string[];
close?: string | string[];
};

export type ChatHeaderProps = Omit<ComponentProps<'div'>, 'title'> & {
/**
* The title to display in the header
*/
title?: string;
/**
* Callback when the close button is clicked
*/
onClose: () => void;
/**
* Accessible label for the close button
*/
closeLabel?: string;
/**
* Optional class names for elements
*/
classNames?: Partial<ChatHeaderClassNames>;
};

export function createChatHeaderComponent({ createElement }: Renderer) {
return function ChatHeader({
title = 'Chat',
onClose,
closeLabel = 'Close chat',
classNames = {},
...props
}: ChatHeaderProps) {
return (
<div
className={cx('ais-ChatHeader', classNames.root, props.className)}
{...props}
>
<span className={cx('ais-ChatHeader-title', classNames.title)}>
{title}
</span>
<button
className={cx('ais-ChatHeader-close', classNames.close)}
onClick={onClose}
aria-label={closeLabel}
type="button"
>
×
</button>
</div>
);
};
}
Loading