Skip to content

Commit 4967237

Browse files
authored
feat(ui-components): introduce chat components (#6678)
1 parent 6e5bbe1 commit 4967237

26 files changed

+2994
-4
lines changed

bundlesize.config.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
{
2424
"path": "packages/react-instantsearch/dist/umd/ReactInstantSearch.min.js",
25-
"maxSize": "66.50 kB"
25+
"maxSize": "66.5 kB"
2626
},
2727
{
2828
"path": "packages/vue-instantsearch/vue2/umd/index.js",
@@ -58,11 +58,11 @@
5858
},
5959
{
6060
"path": "./packages/instantsearch.css/themes/satellite.css",
61-
"maxSize": "5.25 kB"
61+
"maxSize": "7 kB"
6262
},
6363
{
6464
"path": "./packages/instantsearch.css/themes/satellite-min.css",
65-
"maxSize": "4.75 kB"
65+
"maxSize": "6.25 kB"
6666
}
6767
]
6868
}

packages/instantsearch-ui-components/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
"watch:es": "yarn --silent build:es:base --watch"
4848
},
4949
"dependencies": {
50-
"@babel/runtime": "^7.27.6"
50+
"@babel/runtime": "^7.27.6",
51+
"ai": "^5.0.18",
52+
"markdown-to-jsx": "^7.1.13"
5153
}
5254
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/** @jsx createElement */
2+
/** @jsxFrag Fragment */
3+
import { cx } from '../../lib';
4+
5+
import { createChatHeaderComponent } from './ChatHeader';
6+
import { createChatMessagesComponent } from './ChatMessages';
7+
import { createChatPromptComponent } from './ChatPrompt';
8+
import { createChatToggleButtonComponent } from './ChatToggleButton';
9+
10+
import type { Renderer } from '../../types';
11+
import type { ChatHeaderProps } from './ChatHeader';
12+
import type { ChatMessagesProps } from './ChatMessages';
13+
import type { ChatPromptProps } from './ChatPrompt';
14+
import type { ChatToggleButtonProps } from './ChatToggleButton';
15+
16+
export type ChatClassNames = {
17+
container?: string | string[];
18+
};
19+
20+
export type ChatProps = {
21+
/*
22+
* Whether the chat is open or closed.
23+
*/
24+
open: boolean;
25+
/*
26+
* Props for the ChatHeader component.
27+
*/
28+
headerProps: ChatHeaderProps;
29+
/*
30+
* Props for the ChatToggleButton component.
31+
*/
32+
toggleButtonProps: ChatToggleButtonProps;
33+
/*
34+
* Props for the ChatMessages component.
35+
*/
36+
messagesProps: ChatMessagesProps;
37+
/*
38+
* Props for the ChatPrompt component.
39+
*/
40+
promptProps: ChatPromptProps;
41+
/**
42+
* Optional class names for elements
43+
*/
44+
classNames?: Partial<ChatClassNames>;
45+
};
46+
47+
export function createChatComponent({ createElement, Fragment }: Renderer) {
48+
const ChatToggleButton = createChatToggleButtonComponent({
49+
createElement,
50+
Fragment,
51+
});
52+
const ChatHeader = createChatHeaderComponent({ createElement, Fragment });
53+
const ChatMessages = createChatMessagesComponent({ createElement, Fragment });
54+
const ChatPrompt = createChatPromptComponent({ createElement, Fragment });
55+
56+
return function Chat({
57+
open,
58+
headerProps,
59+
toggleButtonProps,
60+
messagesProps,
61+
promptProps,
62+
classNames = {},
63+
}: ChatProps) {
64+
return (
65+
<>
66+
{!open ? (
67+
<ChatToggleButton {...toggleButtonProps} />
68+
) : (
69+
<div className={cx('ais-Chat-container', classNames.container)}>
70+
<ChatHeader {...headerProps} />
71+
<ChatMessages {...messagesProps} />
72+
73+
<ChatPrompt {...promptProps} />
74+
</div>
75+
)}
76+
</>
77+
);
78+
};
79+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/** @jsx createElement */
2+
import { cx } from '../../lib';
3+
4+
import type { Renderer, ComponentProps } from '../../types';
5+
6+
export type ChatHeaderClassNames = {
7+
root?: string | string[];
8+
title?: string | string[];
9+
close?: string | string[];
10+
};
11+
12+
export type ChatHeaderProps = Omit<ComponentProps<'div'>, 'title'> & {
13+
/**
14+
* The title to display in the header
15+
*/
16+
title?: string;
17+
/**
18+
* Callback when the close button is clicked
19+
*/
20+
onClose: () => void;
21+
/**
22+
* Accessible label for the close button
23+
*/
24+
closeLabel?: string;
25+
/**
26+
* Optional class names for elements
27+
*/
28+
classNames?: Partial<ChatHeaderClassNames>;
29+
};
30+
31+
export function createChatHeaderComponent({ createElement }: Renderer) {
32+
return function ChatHeader({
33+
title = 'Chat',
34+
onClose,
35+
closeLabel = 'Close chat',
36+
classNames = {},
37+
...props
38+
}: ChatHeaderProps) {
39+
return (
40+
<div
41+
className={cx('ais-ChatHeader', classNames.root, props.className)}
42+
{...props}
43+
>
44+
<span className={cx('ais-ChatHeader-title', classNames.title)}>
45+
{title}
46+
</span>
47+
<button
48+
className={cx('ais-ChatHeader-close', classNames.close)}
49+
onClick={onClose}
50+
aria-label={closeLabel}
51+
type="button"
52+
>
53+
×
54+
</button>
55+
</div>
56+
);
57+
};
58+
}

0 commit comments

Comments
 (0)