diff --git a/app/javascript/sdk/sdk.js b/app/javascript/sdk/sdk.js
index 44473c8c8..82f72b81e 100644
--- a/app/javascript/sdk/sdk.js
+++ b/app/javascript/sdk/sdk.js
@@ -12,8 +12,9 @@ export const SDK_CSS = `
overflow: hidden !important;
position: fixed !important;
transition: opacity 0.2s linear, transform 0.25s linear,
- width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
- height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ width 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ height 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ max-height 0.2s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 2147483000 !important;
}
@@ -293,7 +294,7 @@ export const SDK_CSS = `
.woot-widget-holder.has-article-view {
width: min(640px, max(0px, -20px + 100dvw)) !important;
height: calc(100% - 125px) !important;
- max-height: none !important;
+ max-height: calc(100% - 125px) !important;
}
}
diff --git a/app/javascript/widget/App.vue b/app/javascript/widget/App.vue
index c5ed2f9cc..0fc9f12aa 100755
--- a/app/javascript/widget/App.vue
+++ b/app/javascript/widget/App.vue
@@ -16,7 +16,12 @@ import {
ON_AGENT_MESSAGE_RECEIVED,
ON_CAMPAIGN_MESSAGE_CLICK,
ON_UNREAD_MESSAGE_CLICK,
+ ON_ARTICLE_VIEW_RESIZING,
} from './constants/widgetBusEvents';
+
+// Keep in sync with the widget holder width/height transition in sdk.js. The
+// article view is masked for this long so the iframe can reflow off-screen.
+const ARTICLE_VIEW_RESIZE_DURATION = 200;
import { useDarkMode } from 'widget/composables/useDarkMode';
import { useRouter } from 'vue-router';
import { useAvailability } from 'widget/composables/useAvailability';
@@ -44,6 +49,7 @@ export default {
return {
isMobile: false,
campaignsSnoozedTill: undefined,
+ isArticleView: false,
};
},
computed: {
@@ -87,6 +93,7 @@ export default {
// Here we just collapse when leaving the article view, since the iframe is
// torn down then and can no longer signal.
if (this.isIFrame && previousRouteName === 'article-viewer') {
+ this.isArticleView = false;
IFrameHelper.sendMessage({ event: 'collapseWidget' });
}
},
@@ -193,6 +200,23 @@ export default {
query: { link, v: Date.now() },
});
},
+ setArticleView(isArticle) {
+ // Only resize when the page type actually changes, so navigating between
+ // two articles (or two listing pages) doesn't trigger a needless mask.
+ if (!this.isIFrame || isArticle === this.isArticleView) return;
+ this.isArticleView = isArticle;
+
+ // Mask the iframe while the widget resizes so its text reflow happens
+ // off-screen, then reveal it once the size transition has settled.
+ emitter.emit(ON_ARTICLE_VIEW_RESIZING, true);
+ IFrameHelper.sendMessage({
+ event: isArticle ? 'expandWidget' : 'collapseWidget',
+ });
+ setTimeout(
+ () => emitter.emit(ON_ARTICLE_VIEW_RESIZING, false),
+ ARTICLE_VIEW_RESIZE_DURATION
+ );
+ },
registerUnreadEvents() {
emitter.on(ON_AGENT_MESSAGE_RECEIVED, () => {
const { name: routeName } = this.$route;
@@ -352,9 +376,7 @@ export default {
} else if (message.event === 'open-article') {
this.openArticle(message.slug);
} else if (message.event === 'portalPageLoaded') {
- IFrameHelper.sendMessage({
- event: message.isArticle ? 'expandWidget' : 'collapseWidget',
- });
+ this.setArticleView(message.isArticle);
} else if (message.event === 'toggle-open') {
this.$store.dispatch('appConfig/toggleWidgetOpen', message.isOpen);
diff --git a/app/javascript/widget/constants/widgetBusEvents.js b/app/javascript/widget/constants/widgetBusEvents.js
index 1ffcd3d51..1f3f573c3 100644
--- a/app/javascript/widget/constants/widgetBusEvents.js
+++ b/app/javascript/widget/constants/widgetBusEvents.js
@@ -2,3 +2,4 @@ export const ON_AGENT_MESSAGE_RECEIVED = 'ON_AGENT_MESSAGE_RECEIVED';
export const ON_UNREAD_MESSAGE_CLICK = 'ON_UNREAD_MESSAGE_CLICK';
export const ON_CAMPAIGN_MESSAGE_CLICK = 'ON_CAMPAIGN_MESSAGE_CLICK';
export const ON_CONVERSATION_CREATED = 'ON_CONVERSATION_CREATED';
+export const ON_ARTICLE_VIEW_RESIZING = 'ON_ARTICLE_VIEW_RESIZING';
diff --git a/app/javascript/widget/views/ArticleViewer.vue b/app/javascript/widget/views/ArticleViewer.vue
index bb04efcc4..b4ce2be2e 100644
--- a/app/javascript/widget/views/ArticleViewer.vue
+++ b/app/javascript/widget/views/ArticleViewer.vue
@@ -1,21 +1,41 @@
-
-