Skip to content

Commit 5058940

Browse files
committed
Merge branch 'dmdimitrov/chat-ai-component' of https://github.com/IgniteUI/igniteui-webcomponents into dmdimitrov/chat-ai-component
2 parents 860fb63 + e02457d commit 5058940

File tree

9 files changed

+78
-49
lines changed

9 files changed

+78
-49
lines changed

src/components/chat/chat.ts

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -325,36 +325,33 @@ export default class IgcChatComponent extends EventEmitterMixin<
325325
}
326326

327327
private renderSuggestions() {
328-
const hasContent = this._slots.hasAssignedElements('suggestions-header');
329-
return html` <igc-list
330-
part="suggestions-container"
331-
role="list"
332-
aria-label="Suggestions"
333-
>
334-
<igc-list-header part="suggestions-header" ?hidden=${!hasContent}>
335-
<slot name="suggestions-header"></slot>
336-
</igc-list-header>
337-
<slot name="suggestions" part="suggestions">
338-
${this._chatState.options?.suggestions?.map(
339-
(suggestion) => html`
340-
<slot name="suggestion" part="suggestion" role="listitem">
341-
<igc-list-item
342-
@click=${() =>
343-
this._chatState?.handleSuggestionClick(suggestion)}
344-
>
345-
<igc-icon
346-
slot="start"
347-
name="star-icon"
348-
collection="material"
349-
></igc-icon>
350-
<span>${suggestion}</span>
351-
</igc-list-item>
352-
</slot>
353-
`
354-
)}
355-
</slot>
356-
<slot name="suggestions-actions" part="suggestions-actions"></slot>
357-
</igc-list>`;
328+
return html`<div part="suggestions-container">
329+
<igc-list role="list" aria-label="Suggestions">
330+
<igc-list-header part="suggestions-header">
331+
<slot name="suggestions-header">Suggestions</slot>
332+
</igc-list-header>
333+
<slot name="suggestions" part="suggestions">
334+
${this._chatState.options?.suggestions?.map(
335+
(suggestion) => html`
336+
<slot name="suggestion" part="suggestion" role="listitem">
337+
<igc-list-item
338+
@click=${() =>
339+
this._chatState?.handleSuggestionClick(suggestion)}
340+
>
341+
<igc-icon
342+
slot="start"
343+
name="star-icon"
344+
collection="material"
345+
></igc-icon>
346+
<span slot="title">${suggestion}</span>
347+
</igc-list-item>
348+
</slot>
349+
`
350+
)}
351+
</slot>
352+
<slot name="suggestions-actions" part="suggestions-actions"></slot>
353+
</igc-list>
354+
</div>`;
358355
}
359356

360357
protected override firstUpdated() {

src/components/chat/themes/chat.base.scss

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ $inline-inset: rem(16px);
99
width: 100%;
1010
height: var(--igc-chat-height);
1111
overflow: hidden;
12-
box-shadow: var(--ig-elevation-24);
1312
display: flex;
1413
flex-direction: column;
1514
}
@@ -70,15 +69,16 @@ $inline-inset: rem(16px);
7069
igc-list {
7170
--ig-size: 3;
7271

73-
min-height: fit-content;
7472
padding-block-end: rem(24px);
75-
}
76-
77-
igc-list-header,
78-
igc-list-item {
73+
min-height: fit-content;
74+
width: fit-content;
7975
max-width: rem(576px);
8076
}
8177

8278
igc-list-item {
8379
cursor: pointer;
8480
}
81+
82+
igc-list-item::part(title) {
83+
@include line-clamp(2, true, true);
84+
}

src/components/chat/themes/input.base.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
max-width: rem(760px);
1616
width: 100%;
1717
margin-inline: rem(16px);
18-
gap: rem(8px);
18+
border-radius: rem(4px);
19+
padding: rem(16px);
20+
gap: rem(12px);
1921
}
2022

2123
[part='buttons-container'] {

src/components/chat/themes/message.base.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
padding: rem(12px) rem(16px);
1515
border-radius: rem(24px) rem(24px) 0;
1616
max-width: rem(576px);
17+
width: fit-content;
1718
}
1819

1920
[part~='bubble'] {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@use 'styles/utilities' as *;
22

33
[part~='sent'] {
4-
border-radius: rem(4px);
4+
border-radius: rem(8px) rem(8px) 0;
55
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@use 'styles/utilities' as *;
22

3-
[part~='sent'] {
4-
border-radius: rem(2px);
5-
}
3+
// [part~='sent'] {
4+
// border-radius: rem(2px);
5+
// }

src/components/chat/themes/shared/chat.bootstrap.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ igc-list {
44
border: none;
55
}
66

7-
igc-list-item {
7+
igc-list-item:not(:hover),
8+
igc-list-header {
89
background: initial;
910
}

src/components/chat/themes/shared/input/input.common.scss

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
$theme: $material;
55

6-
:host {
7-
// border-block-start: rem(1px) solid var-get($theme, 'chat-input-border');
8-
border-block-start: rem(1px) solid color(gray, 300);
6+
[part~='input-container'] {
7+
border: rem(1px) solid var-get($theme, 'chat-input-border');
98
}

stories/chat.stories.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import type {
1212
IgcMessageAttachment,
1313
} from '../src/components/chat/types.js';
1414

15+
const googleGenAIKey = import.meta.env.VITE_GOOGLE_GEN_AI_KEY;
1516
const ai = new GoogleGenAI({
16-
apiKey: 'googleGenAIKey',
17+
apiKey: googleGenAIKey,
1718
});
1819

1920
defineComponents(IgcChatComponent);
@@ -379,7 +380,35 @@ async function handleAIMessageSend(e: CustomEvent) {
379380
};
380381
chat.messages = [...chat.messages];
381382
}
382-
chat.options = { ...ai_chat_options, suggestions: ['Thank you!'] };
383+
384+
const messagesForSuggestions = [
385+
...chat.messages,
386+
`Based on all my previous prompts give me 3 strings that would act like a suggestions for my next prompt. Don't repeat my previous prompts, I want just the suggestions in the format "suggestion1: '...', suggestion2: '...', suggestion3: '...'`,
387+
];
388+
const responseWithSuggestions = await ai.models.generateContent({
389+
model: 'gemini-2.0-flash',
390+
contents: messagesForSuggestions,
391+
config: {
392+
responseModalities: [Modality.TEXT],
393+
},
394+
});
395+
response = responseWithSuggestions?.candidates?.[0]?.content?.parts;
396+
if (response && response.length === 1) {
397+
const responseText = response[0]?.text ?? '';
398+
const regex: RegExp = /'(.*?)'/g;
399+
400+
// Use String.prototype.matchAll() to get an iterator of all matches, including captured groups.
401+
const matches: IterableIterator<RegExpMatchArray> =
402+
responseText.matchAll(regex);
403+
404+
// Map the matches to an array, extracting the first capturing group (the content).
405+
const suggestions: string[] = Array.from(
406+
matches,
407+
(match: RegExpMatchArray) => match[1]
408+
);
409+
410+
chat.options = { ...ai_chat_options, suggestions: suggestions };
411+
}
383412
}
384413
}, 2000);
385414
}
@@ -438,7 +467,7 @@ export const Chat_Templates: Story = {
438467
<igc-icon-button variant="flat">🎤</igc-icon-button>
439468
<div style="margin-inline-start: auto;">
440469
<igc-button @click=${handleCustomSendClick}>Ask</igc-button>
441-
<igc-button variant="flat">...</igc-button>
470+
<igc-icon-button variant="flat">...</igc-icon-button>
442471
</div>
443472
`;
444473
options = {
@@ -473,7 +502,7 @@ export const Chat_Templates: Story = {
473502
variant="flat"
474503
name="search"
475504
></igc-icon-button>
476-
<div slot="suggestions-header">Suggestions</div>
505+
<div slot="suggestions-header">Get Inspired</div>
477506
</igc-chat>
478507
`;
479508
},

0 commit comments

Comments
 (0)