Skip to content

Commit 081a065

Browse files
authored
Merge pull request #76 from yext/popup-stay-closed
Popup stay closed
2 parents f4b6f24 + 095081f commit 081a065

File tree

5 files changed

+62
-10
lines changed

5 files changed

+62
-10
lines changed

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.10.2",
3+
"version": "0.10.3",
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/ChatPopUp.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ const builtInCssClasses: ChatPopUpCssClasses = withStylelessCssClasses(
7474
},
7575
}
7676
);
77+
const popupLocalStorageKey = "YEXT_CHAT_OPEN_ON_LOAD";
7778

7879
/**
7980
* The props for the {@link ChatPopUp} component.
@@ -151,6 +152,7 @@ export function ChatPopUp(props: ChatPopUpProps) {
151152
//only show initial message popup (if specified) when CTA label is not provided
152153
!ctaLabel && showInitialMessagePopUp
153154
);
155+
154156
const onCloseInitialMessage = useCallback(() => {
155157
setshowInitialMessage(false);
156158
}, []);
@@ -162,41 +164,58 @@ export function ChatPopUp(props: ChatPopUpProps) {
162164
// to avoid message requests immediately on load while the popup is still "hidden"
163165
const [renderChat, setRenderChat] = useState(false);
164166

167+
// Set the initial value of the local storage flag for opening on load only if it doesn't already exist
168+
169+
if (window.localStorage.getItem(popupLocalStorageKey) === null) {
170+
window.localStorage.setItem(
171+
popupLocalStorageKey,
172+
openOnLoad ? "true" : "false"
173+
);
174+
}
175+
const openOnLoadLocalStorage =
176+
window.localStorage.getItem(popupLocalStorageKey);
177+
178+
/* Open panel on load if:
179+
- openOnLoad prop is true or there are messages in state (from browser storage), and local storage flag is true */
180+
const isOpenOnLoad =
181+
(messages.length > 1 && openOnLoadLocalStorage === "true") || openOnLoad;
182+
165183
// only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)
166184
useFetchInitialMessage(
167185
showInitialMessagePopUp ? console.error : handleError,
168186
false,
169187
(showUnreadNotification || showInitialMessagePopUp) &&
170188
!renderChat &&
171-
!openOnLoad
189+
!isOpenOnLoad
172190
);
173191

174192
useEffect(() => {
175-
// Open panel on load if openOnLoad prop is true or there are messages in state (from browser storage)
176-
if (!renderChat && (openOnLoad || messages.length > 1)) {
193+
if (!renderChat && isOpenOnLoad) {
177194
setShowChat(true);
178195
setRenderChat(true);
179196
setshowInitialMessage(false);
180197
}
181-
}, [messages.length, openOnLoad, renderChat]);
198+
}, [renderChat, messages.length, isOpenOnLoad]);
182199

183200
const onClick = useCallback(() => {
184201
setShowChat((prev) => !prev);
185202
setRenderChat(true);
186203
setshowInitialMessage(false);
204+
window.localStorage.setItem(popupLocalStorageKey, "true");
187205
}, []);
188206

189207
const onClose = useCallback(() => {
190208
setShowChat(false);
191209
customOnClose?.();
192210
// consider all the messages are read while the panel was open
193211
setNumReadMessagesLength(messages.length);
194-
}, [customOnClose, messages]);
212+
window.localStorage.setItem(popupLocalStorageKey, "false");
213+
}, [customOnClose, messages.length]);
195214

196215
useEffect(() => {
197216
// update number of unread messages if there are new messages added while the panel is closed
198217
setNumUnreadMessagesLength(messages.length - numReadMessages);
199-
}, [messages, numReadMessages]);
218+
}, [messages.length, numReadMessages]);
200219

201220
const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
202221
const panelCssClasses = twMerge(

test-site/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-site/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function App() {
4040
<ChatHeadlessProvider config={config}>
4141
<ChatPopUp
4242
title="Clippy"
43-
openOnLoad={true}
43+
openOnLoad={false}
4444
showInitialMessagePopUp={true}
4545
showHeartBeatAnimation={true}
4646
showUnreadNotification={true}

tests/components/ChatPopUp.test.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe("open on load with state from browser storage", () => {
8282
beforeEach(() => {
8383
localStorage.clear();
8484
});
85-
it("renders panel on load when there are non-initial messages in state", async () => {
85+
it("renders panel on load when there are non-initial messages in state and panel wasn't previously closed", async () => {
8686
localStorage.setItem(
8787
`yext_chat_state__localhost__${dummyConfig.botId}`,
8888
JSON.stringify({
@@ -100,6 +100,7 @@ describe("open on load with state from browser storage", () => {
100100
],
101101
})
102102
);
103+
localStorage.setItem("YEXT_CHAT_OPEN_ON_LOAD", "true");
103104
renderPopUp({}, undefined, { ...dummyConfig, saveToLocalStorage: true });
104105
expect(screen.getByLabelText("Send Message")).toBeTruthy();
105106
});
@@ -110,6 +111,38 @@ describe("open on load with state from browser storage", () => {
110111
});
111112
});
112113

114+
describe("does not open on load with saveToLocalStorage = false", () => {
115+
beforeEach(() => {
116+
localStorage.setItem("YEXT_CHAT_OPEN_ON_LOAD", "false");
117+
});
118+
119+
it("should not open on initial page load", async () => {
120+
renderPopUp({});
121+
expect(screen.queryByLabelText("Send Message")).toBeNull();
122+
});
123+
124+
it("should not open on load even if there are messages", async () => {
125+
localStorage.setItem(
126+
`yext_chat_state__localhost__${dummyConfig.botId}`,
127+
JSON.stringify({
128+
messages: [
129+
{
130+
text: "How can I help you?",
131+
source: MessageSource.BOT,
132+
timestamp: new Date().toISOString(),
133+
},
134+
{
135+
text: "Hello!",
136+
source: MessageSource.USER,
137+
timestamp: new Date().toISOString(),
138+
},
139+
],
140+
})
141+
);
142+
expect(screen.queryByLabelText("Send Message")).toBeNull();
143+
});
144+
});
145+
113146
describe("ctaLabel", () => {
114147
it("renders CTA label when a label is provided", async () => {
115148
renderPopUp({ ctaLabel: "ChatPopUp Test" });

0 commit comments

Comments
 (0)