Skip to content

Commit ee2e5a9

Browse files
committed
feat(chat): fixed reaction icons and suggestions generation in AI story
1 parent 65ea59d commit ee2e5a9

File tree

3 files changed

+43
-45
lines changed

3 files changed

+43
-45
lines changed

src/components/chat/chat-message.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,14 @@ import { addThemingController } from '../../theming/theming-controller.js';
66
import IgcAvatarComponent from '../avatar/avatar.js';
77
import { chatContext } from '../common/context.js';
88
import { registerComponent } from '../common/definitions/register.js';
9-
import { registerIconFromText } from '../icon/icon.registry.js';
9+
import IgcTooltipComponent from '../tooltip/tooltip.js';
1010
import type { DefaultChatRenderer } from './chat-renderer.js';
1111
import type { ChatState } from './chat-state.js';
1212
import IgcMessageAttachmentsComponent from './message-attachments.js';
1313
import { styles } from './themes/message.base.css.js';
1414
import { all } from './themes/message.js';
1515
import { styles as shared } from './themes/shared/chat-message/chat-message.common.css.js';
16-
import '../tooltip/tooltip.js';
17-
import IgcTooltipComponent from '../tooltip/tooltip.js';
18-
import {
19-
thumbDownIcon as badResponseIcon,
20-
copyIcon as copyResponseIcon,
21-
thumbUpIcon as goodResponseIcon,
22-
type IgcMessage,
23-
regenerateIcon as redoIcon,
24-
} from './types.js';
16+
import type { IgcMessage } from './types.js';
2517

2618
/**
2719
* A chat message component for displaying individual messages in `<igc-chat>`.
@@ -88,10 +80,6 @@ export default class IgcChatMessageComponent extends LitElement {
8880
constructor() {
8981
super();
9082
addThemingController(this, all);
91-
registerIconFromText('copy-response', copyResponseIcon, 'material');
92-
registerIconFromText('good-response', goodResponseIcon, 'material');
93-
registerIconFromText('bad-response', badResponseIcon, 'material');
94-
registerIconFromText('redo', redoIcon, 'material');
9583
}
9684

9785
/**

src/components/chat/chat-state.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@ import { createRef, type Ref, ref } from 'lit/directives/ref.js';
44
import { enterKey } from '../common/controllers/key-bindings.js';
55
import { IgcChatResourceStringEN } from '../common/i18n/chat.resources.js';
66
import { partMap } from '../common/part-map.js';
7+
import { registerIconFromText } from '../icon/icon.registry.js';
78
import type IgcTextareaComponent from '../textarea/textarea.js';
89
import type IgcTooltipComponent from '../tooltip/tooltip.js';
910
import type IgcChatComponent from './chat.js';
1011
import type { IgcChatComponentEventMap } from './chat.js';
1112
import { DefaultChatRenderer } from './chat-renderer.js';
1213
import { PlainTextRenderer } from './plain-text-renderer.js';
13-
import type {
14-
IgcChatOptions,
15-
IgcChatTemplates,
16-
IgcMessage,
17-
IgcMessageAttachment,
14+
import {
15+
copyIcon,
16+
type IgcChatOptions,
17+
type IgcChatTemplates,
18+
type IgcMessage,
19+
type IgcMessageAttachment,
20+
regenerateIcon,
21+
thumbDownIcon,
22+
thumbUpIcon,
1823
} from './types.js';
1924

2025
/**
@@ -328,7 +333,7 @@ export class ChatState {
328333
'copy-response-button',
329334
this.resourceStrings.reactionCopyResponse
330335
)}
331-
name="copy"
336+
name="copy-response"
332337
collection="material"
333338
variant="flat"
334339
@click=${(e: MouseEvent) =>
@@ -341,7 +346,7 @@ export class ChatState {
341346
'good-response-button',
342347
this.resourceStrings.reactionGoodResponse
343348
)}
344-
name="thumb_up"
349+
name="good-response"
345350
collection="material"
346351
variant="flat"
347352
@click=${(e: MouseEvent) =>
@@ -354,7 +359,7 @@ export class ChatState {
354359
'bad-response-button',
355360
this.resourceStrings.reactionBadResponse
356361
)}
357-
name="thumb_down"
362+
name="bad-response"
358363
variant="flat"
359364
collection="material"
360365
@click=${(e: MouseEvent) =>
@@ -367,7 +372,7 @@ export class ChatState {
367372
'redo-button',
368373
this.resourceStrings.reactionRedo
369374
)}
370-
name="regenerate"
375+
name="redo"
371376
variant="flat"
372377
collection="material"
373378
@click=${(e: MouseEvent) =>
@@ -424,6 +429,7 @@ export class ChatState {
424429
private showTooltip(elementId: string, text: string) {
425430
if (!this._sharedTooltip) return;
426431
this._sharedTooltip.message = text;
432+
this._sharedTooltip.hideDelay = 300;
427433
this._sharedTooltip.show(elementId);
428434
}
429435

@@ -591,6 +597,10 @@ export class ChatState {
591597
*/
592598
constructor(chat: IgcChatComponent) {
593599
this._host = chat;
600+
registerIconFromText('copy-response', copyIcon, 'material');
601+
registerIconFromText('good-response', thumbUpIcon, 'material');
602+
registerIconFromText('bad-response', thumbDownIcon, 'material');
603+
registerIconFromText('redo', regenerateIcon, 'material');
594604
}
595605

596606
//#region Event handlers

stories/chat.stories.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Meta, StoryObj } from '@storybook/web-components-vite';
22
import { html } from 'lit';
3-
43
import { GoogleGenAI, Modality } from '@google/genai';
54
import {
65
IgcChatComponent,
@@ -118,11 +117,11 @@ const _messageActionsTemplate = (msg: any) => {
118117
: html``;
119118
};
120119

121-
const _typingIndicatorTemplate = html`<span>LOADING...</span>`;
122-
const _textInputTemplate = (text: string) =>
123-
html`<igc-input placeholder="Type text here..." .value=${text}></igc-input>`;
124-
const _textAreaActionsTemplate = () =>
125-
html`<igc-button @click=${handleCustomSendClick}>Send</igc-button>`;
120+
// const _typingIndicatorTemplate = html`<span>LOADING...</span>`;
121+
// const _textInputTemplate = (text: string) =>
122+
// html`<igc-input placeholder="Type text here..." .value=${text}></igc-input>`;
123+
// const _textAreaActionsTemplate = () =>
124+
// html`<igc-button @click=${handleCustomSendClick}>Send</igc-button>`;
126125
const _textAreaAttachmentsTemplate = (attachments: IgcMessageAttachment[]) => {
127126
return html`<div>
128127
${attachments.map(
@@ -178,11 +177,11 @@ const chat_options = {
178177
// languages: ['typescript']
179178
// theme: 'github-dark'
180179
}),
181-
templates: {
182-
messageActionsTemplate: _messageActionsTemplate,
183-
textAreaAttachmentsTemplate: _textAreaAttachmentsTemplate,
184-
textAreaActionsTemplate: _textAreaActionsTemplate,
185-
},
180+
// templates: {
181+
// messageActionsTemplate: _messageActionsTemplate,
182+
// textAreaAttachmentsTemplate: _textAreaAttachmentsTemplate,
183+
// textAreaActionsTemplate: _textAreaActionsTemplate,
184+
// },
186185
};
187186

188187
function handleCustomSendClick() {
@@ -334,7 +333,6 @@ async function handleAIMessageSend(e: CustomEvent) {
334333

335334
chat.options = { ...ai_chat_options, suggestions: [], isTyping: true };
336335
setTimeout(async () => {
337-
chat.options = { ...ai_chat_options, suggestions: [], isTyping: false };
338336
let response: any;
339337
let responseText = '';
340338
const attachments: IgcMessageAttachment[] = [];
@@ -364,7 +362,7 @@ async function handleAIMessageSend(e: CustomEvent) {
364362

365363
if (newMessage.text.includes('image')) {
366364
response = await ai.models.generateContent({
367-
model: 'gemini-2.0-flash-preview-image-generation',
365+
model: 'gemini-2.5-flash-preview-image-generation',
368366
contents: userMessages,
369367
config: {
370368
responseModalities: [Modality.TEXT, Modality.IMAGE],
@@ -401,11 +399,12 @@ async function handleAIMessageSend(e: CustomEvent) {
401399

402400
botResponse.text = responseText;
403401
botResponse.attachments = attachments;
402+
chat.options = { ...ai_chat_options, isTyping: false };
404403
chat.messages = [...chat.messages, botResponse];
405404
} else {
406405
chat.messages = [...chat.messages, botResponse];
407406
response = await ai.models.generateContentStream({
408-
model: 'gemini-2.0-flash',
407+
model: 'gemini-2.5-flash',
409408
contents: userMessages,
410409
config: {
411410
responseModalities: [Modality.TEXT],
@@ -423,10 +422,10 @@ async function handleAIMessageSend(e: CustomEvent) {
423422

424423
const messagesForSuggestions = [
425424
...chat.messages,
426-
`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: '...'`,
425+
`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: ***...***`,
427426
];
428427
const responseWithSuggestions = await ai.models.generateContent({
429-
model: 'gemini-2.0-flash',
428+
model: 'gemini-2.5-flash',
430429
contents: messagesForSuggestions,
431430
config: {
432431
responseModalities: [Modality.TEXT],
@@ -435,19 +434,20 @@ async function handleAIMessageSend(e: CustomEvent) {
435434
response = responseWithSuggestions?.candidates?.[0]?.content?.parts;
436435
if (response && response.length === 1) {
437436
const responseText = response[0]?.text ?? '';
438-
const regex: RegExp = /'(.*?)'/g;
439-
440-
// Use String.prototype.matchAll() to get an iterator of all matches, including captured groups.
437+
const regex: RegExp = /\*\*\*(.*?)\*\*\*/g; // suggestions between *** and ***
441438
const matches: IterableIterator<RegExpMatchArray> =
442439
responseText.matchAll(regex);
443440

444-
// Map the matches to an array, extracting the first capturing group (the content).
445441
const suggestions: string[] = Array.from(
446442
matches,
447443
(match: RegExpMatchArray) => match[1]
448444
);
449445

450-
chat.options = { ...ai_chat_options, suggestions: suggestions };
446+
chat.options = {
447+
...ai_chat_options,
448+
suggestions: suggestions,
449+
isTyping: false,
450+
};
451451
}
452452
}
453453
}, 2000);
@@ -503,7 +503,6 @@ export const Chat_Templates: Story = {
503503
const chat = document.querySelector('igc-chat');
504504
if (chat) {
505505
const actionsTemplate = () => html`
506-
<!-- ${chat.defaultFileUploadButton} -->
507506
<igc-icon-button variant="flat">🎤</igc-icon-button>
508507
<div style="margin-inline-start: auto;">
509508
<igc-button @click=${handleCustomSendClick}>Ask</igc-button>
@@ -517,6 +516,7 @@ export const Chat_Templates: Story = {
517516
suggestions: ['Hello', 'Hi', 'Generate an image!'],
518517
templates: {
519518
messageActionsTemplate: _messageActionsTemplate,
519+
textAreaAttachmentsTemplate: _textAreaAttachmentsTemplate,
520520
textAreaActionsTemplate: actionsTemplate,
521521
suggestionPrefixTemplate: html`✨`,
522522
},

0 commit comments

Comments
 (0)