Skip to content

Commit 4c07914

Browse files
authored
update footer implementation (#64)
- footer in ChatPanel will now report analytics event with `WEBSITE` action for any link click - refactor footer to use the existing Markdown component NOTE: will publish a new version after merge J=CLIP-909 TEST=manual see that footer is rendered as expected and sent an analytics event on click ![Screenshot 2024-01-10 at 1 34 30 PM](https://github.com/yext/chat-ui-react/assets/36055303/c751af55-adea-4de9-ac6b-104a66a8bed4)
1 parent b7e2c85 commit 4c07914

File tree

10 files changed

+72
-59
lines changed

10 files changed

+72
-59
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
22

3-
[Home](./index.md) &gt; [@yext/chat-ui-react](./chat-ui-react.md) &gt; [ChatPanelCssClasses](./chat-ui-react.chatpanelcssclasses.md) &gt; [footerCssClasses](./chat-ui-react.chatpanelcssclasses.footercssclasses.md)
3+
[Home](./index.md) &gt; [@yext/chat-ui-react](./chat-ui-react.md) &gt; [ChatPanelCssClasses](./chat-ui-react.chatpanelcssclasses.md) &gt; [footer](./chat-ui-react.chatpanelcssclasses.footer.md)
44

5-
## ChatPanelCssClasses.footerCssClasses property
5+
## ChatPanelCssClasses.footer property
66

77
**Signature:**
88

99
```typescript
10-
footerCssClasses?: string;
10+
footer?: string;
1111
```

docs/chat-ui-react.chatpanelcssclasses.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export interface ChatPanelCssClasses
1717
| Property | Modifiers | Type | Description |
1818
| --- | --- | --- | --- |
1919
| [container?](./chat-ui-react.chatpanelcssclasses.container.md) | | string | _(Optional)_ |
20-
| [footerCssClasses?](./chat-ui-react.chatpanelcssclasses.footercssclasses.md) | | string | _(Optional)_ |
20+
| [footer?](./chat-ui-react.chatpanelcssclasses.footer.md) | | string | _(Optional)_ |
2121
| [inputContainer?](./chat-ui-react.chatpanelcssclasses.inputcontainer.md) | | string | _(Optional)_ |
2222
| [inputCssClasses?](./chat-ui-react.chatpanelcssclasses.inputcssclasses.md) | | [ChatInputCssClasses](./chat-ui-react.chatinputcssclasses.md) | _(Optional)_ |
2323
| [messageBubbleCssClasses?](./chat-ui-react.chatpanelcssclasses.messagebubblecssclasses.md) | | [MessageBubbleCssClasses](./chat-ui-react.messagebubblecssclasses.md) | _(Optional)_ |

etc/chat-ui-react.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export interface ChatPanelCssClasses {
7171
// (undocumented)
7272
container?: string;
7373
// (undocumented)
74-
footerCssClasses?: string;
74+
footer?: string;
7575
// (undocumented)
7676
inputContainer?: string;
7777
// (undocumented)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@yext/chat-ui-react",
3-
"version": "0.8.5",
3+
"version": "0.8.6",
44
"description": "A library of React Components for powering Yext Chat integrations.",
55
"author": "clippy@yext.com",
66
"main": "./lib/commonjs/src/index.js",

src/components/ChatPanel.tsx

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
MessageSuggestionCssClasses,
2222
MessageSuggestions,
2323
} from "./MessageSuggestions";
24-
import ReactMarkdown, { ReactMarkdownOptions } from "react-markdown";
24+
import { Markdown, MarkdownCssClasses } from "./Markdown";
2525

2626
/**
2727
* The CSS class interface for the {@link ChatPanel} component.
@@ -36,7 +36,7 @@ export interface ChatPanelCssClasses {
3636
inputCssClasses?: ChatInputCssClasses;
3737
messageBubbleCssClasses?: MessageBubbleCssClasses;
3838
messageSuggestionClasses?: MessageSuggestionCssClasses;
39-
footerCssClasses?: string;
39+
footer?: string;
4040
}
4141

4242
const builtInCssClasses: ChatPanelCssClasses = withStylelessCssClasses(
@@ -49,8 +49,7 @@ const builtInCssClasses: ChatPanelCssClasses = withStylelessCssClasses(
4949
messageBubbleCssClasses: {
5050
topContainer: "first:mt-4",
5151
},
52-
footerCssClasses:
53-
"text-center text-slate-400 rounded-b-3xl px-4 pb-4 text-[12px]",
52+
footer: "text-center text-slate-400 rounded-b-3xl px-4 pb-4 text-[12px]",
5453
}
5554
);
5655

@@ -148,6 +147,14 @@ export function ChatPanel(props: ChatPanelProps) {
148147
return (message) => (messagesRef.current[index] = message);
149148
}, []);
150149

150+
const footerCssClasses: MarkdownCssClasses = useMemo(
151+
() => ({
152+
container: cssClasses.footer,
153+
link: "cursor-pointer hover:underline text-blue-600",
154+
}),
155+
[cssClasses]
156+
);
157+
151158
return (
152159
<div className="yext-chat w-full h-full">
153160
<div className={cssClasses.container}>
@@ -176,42 +183,13 @@ export function ChatPanel(props: ChatPanelProps) {
176183
<ChatInput {...props} customCssClasses={cssClasses.inputCssClasses} />
177184
</div>
178185
{footer && (
179-
<Footer footer={footer} className={cssClasses.footerCssClasses} />
186+
<Markdown
187+
content={footer}
188+
linkClickEvent="WEBSITE"
189+
customCssClasses={footerCssClasses}
190+
/>
180191
)}
181192
</div>
182193
</div>
183194
);
184195
}
185-
186-
const Footer = ({
187-
footer,
188-
className,
189-
}: {
190-
footer: string;
191-
className?: string;
192-
}) => {
193-
const components: ReactMarkdownOptions["components"] = useMemo(() => {
194-
return {
195-
a: ({ node: _, children, ...props }) => {
196-
return (
197-
<a
198-
{...props}
199-
target="_blank"
200-
rel="noopener noreferrer"
201-
className="cursor-pointer hover:underline text-blue-600"
202-
>
203-
{children}
204-
</a>
205-
);
206-
},
207-
};
208-
}, []);
209-
210-
return (
211-
<ReactMarkdown
212-
children={footer}
213-
className={className}
214-
components={components}
215-
/>
216-
);
217-
};

src/components/ChatPopUp.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ export function ChatPopUp(props: ChatPopUpProps) {
256256
onClick={onClick}
257257
className={
258258
cssClasses.button +
259-
(showHeartBeatAnimation && !!numUnreadMessages ? " animate-heartbeat" : "")
259+
(showHeartBeatAnimation && !!numUnreadMessages
260+
? " animate-heartbeat"
261+
: "")
260262
}
261263
>
262264
{openPanelButtonIcon ?? (

src/components/Markdown.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import rehypeRaw from "rehype-raw";
77
import rehypeSanitize from "rehype-sanitize";
88
import React, { useMemo } from "react";
99
import { useReportAnalyticsEvent } from "../hooks/useReportAnalyticsEvent";
10+
import { useComposedCssClasses } from "../hooks/useComposedCssClasses";
1011

1112
// The Remark and Rehype plugins to use in conjunction with ReactMarkdown.
1213
const unifiedPlugins: { remark?: PluggableList; rehype: PluggableList } = {
@@ -19,13 +20,32 @@ const unifiedPlugins: { remark?: PluggableList; rehype: PluggableList } = {
1920
],
2021
};
2122

23+
/**
24+
* The CSS class interface for the Markdown component.
25+
*
26+
* @internal
27+
*/
28+
export interface MarkdownCssClasses {
29+
container?: string;
30+
link?: string;
31+
}
32+
33+
const builtInCssClasses: MarkdownCssClasses = {
34+
link: "cursor-pointer",
35+
};
36+
2237
interface MarkdownProps {
2338
/** Stringified markdown. */
2439
content: string;
2540
/** The response ID correlates to the current message. */
2641
responseId?: string;
27-
/** Classnames for the container. */
28-
className?: string;
42+
/** CSS classes for customizing the component styling. */
43+
customCssClasses?: MarkdownCssClasses;
44+
/**
45+
* Action to report for analytics event when a link is clicked.
46+
* Defaults to 'CHAT_LINK_CLICK'.
47+
*/
48+
linkClickEvent?: "WEBSITE" | "CHAT_LINK_CLICK";
2949
}
3050

3151
/**
@@ -37,13 +57,19 @@ interface MarkdownProps {
3757
*
3858
* @internal
3959
*/
40-
export function Markdown({ content, responseId, className }: MarkdownProps) {
60+
export function Markdown({
61+
content,
62+
responseId,
63+
customCssClasses,
64+
linkClickEvent = "CHAT_LINK_CLICK",
65+
}: MarkdownProps) {
4166
const reportAnalyticsEvent = useReportAnalyticsEvent();
67+
const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
4268

4369
const components: ReactMarkdownOptions["components"] = useMemo(() => {
4470
const createClickHandlerFn = (href?: string) => () => {
4571
reportAnalyticsEvent({
46-
action: "CHAT_LINK_CLICK",
72+
action: linkClickEvent,
4773
destinationUrl: href,
4874
chat: {
4975
responseId,
@@ -58,18 +84,18 @@ export function Markdown({ content, responseId, className }: MarkdownProps) {
5884
onClick={createClickHandlerFn(props.href)}
5985
target="_blank"
6086
rel="noopener noreferrer"
61-
className="cursor-pointer"
87+
className={cssClasses.link}
6288
>
6389
{children}
6490
</a>
6591
);
6692
},
6793
};
68-
}, [reportAnalyticsEvent, responseId]);
94+
}, [reportAnalyticsEvent, linkClickEvent, responseId, cssClasses]);
6995

7096
return (
7197
<ReactMarkdown
72-
className={className}
98+
className={cssClasses.container}
7399
children={content}
74100
remarkPlugins={unifiedPlugins.remark}
75101
rehypePlugins={unifiedPlugins.rehype}

src/components/MessageBubble.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React from "react";
1+
import React, { useMemo } from "react";
22
import { Message, MessageSource } from "@yext/chat-headless-react";
33
import { useComposedCssClasses } from "../hooks";
44
import { twMerge } from "tailwind-merge";
5-
import { Markdown } from "./Markdown";
5+
import { Markdown, MarkdownCssClasses } from "./Markdown";
66
import { withStylelessCssClasses } from "../utils/withStylelessCssClasses";
77
import { FeedbackButtons, FeedbackButtonsCssClasses } from "./FeedbackButtons";
88

@@ -117,6 +117,13 @@ export function MessageBubble({
117117
: cssClasses.timestamp__bot
118118
);
119119

120+
const markdownCssClasses: MarkdownCssClasses = useMemo(
121+
() => ({
122+
container: textCssClasses,
123+
}),
124+
[textCssClasses]
125+
);
126+
120127
return (
121128
<div className={cssClasses.topContainer}>
122129
<div className={subContainerCssClasses}>
@@ -130,7 +137,7 @@ export function MessageBubble({
130137
<Markdown
131138
content={message.text}
132139
responseId={message.responseId}
133-
className={textCssClasses}
140+
customCssClasses={markdownCssClasses}
134141
/>
135142
</div>
136143
{/* fallback on empty space here to perserve the height for timestamp div */}

test-site/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)