Skip to content

Commit f25946f

Browse files
Kai Code: Only allow the expanded widget on viewports with room for it
The expanded messenger (max-width 690px, no height cap) was allowed on any viewport of 451px or more. On a phone with the page zoomed out just past the mobile breakpoint (e.g. a 571px-wide CSS viewport), the widget left the full-screen mobile layout, and a stored "expanded" choice made it `calc(100% - 40px)` wide and nearly full height, covering almost the whole page. Expansion now needs a viewport of at least 768px (`widgetExpandMinWidth` in UI.js), used by both the expanded CSS media query and `GleapFrameManager.canExpandWidget()`, so they stay in sync. Narrower viewports show the default 410px widget, hide the expand button, and keep the stored preference for when the window gets wider again. Added tests for 571px, a fractional 767.5px, and the 768px boundary. Gleap ticket #185052.
1 parent 399dd3f commit f25946f

3 files changed

Lines changed: 39 additions & 12 deletions

File tree

‎src/GleapFrameManager.js‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import GleapAgentToolManager from './GleapAgentToolManager';
2222
import { getCaptureCapabilities } from './GleapCaptureSettings';
2323
import { forwardSurveyAnalyticsEvent } from './GleapSurveyAnalyticsForwarder';
2424
import { bootstrapGleapFrame, loadFromGleapCache, runFunctionWhenDomIsReady, saveToGleapCache } from './GleapHelper';
25-
import { widgetLoaderMarkup, widgetMaxHeight } from './UI';
25+
import { widgetExpandMinWidth, widgetLoaderMarkup, widgetMaxHeight } from './UI';
2626

2727
export default class GleapFrameManager {
2828
frameUrl = 'https://messenger-app.gleap.io';
@@ -429,14 +429,15 @@ export default class GleapFrameManager {
429429
}
430430
}
431431

432-
// The widget is full screen at <= 450px and the expanded CSS only applies from
433-
// 451px (see UI.js). Test the same query as that CSS so a fractional (zoomed)
434-
// viewport between the two never counts as expandable.
435-
isMobileViewport() {
432+
// The expanded CSS only applies from widgetExpandMinWidth (see UI.js); narrower
433+
// viewports (mobile full screen, or a zoomed-out phone just past it) keep the
434+
// default size. Test the same query as that CSS so a fractional (zoomed)
435+
// viewport never counts as expandable while the CSS does not apply.
436+
hasRoomToExpand() {
436437
try {
437-
return typeof window.matchMedia === 'function' && !window.matchMedia('(min-width: 451px)').matches;
438+
return typeof window.matchMedia !== 'function' || window.matchMedia(`(min-width: ${widgetExpandMinWidth}px)`).matches;
438439
} catch (e) {
439-
return false;
440+
return true;
440441
}
441442
}
442443

@@ -445,7 +446,7 @@ export default class GleapFrameManager {
445446
if (flowConfig && flowConfig.hideExpandButton) {
446447
return false;
447448
}
448-
return !this.isSurvey() && !this.isMobileViewport();
449+
return !this.isSurvey() && this.hasRoomToExpand();
449450
}
450451

451452
getWidgetExpandedPreference() {

‎src/GleapFrameManager.test.js‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ jest.mock('./GleapHelper', () => ({
4545
jest.mock('./UI', () => ({
4646
widgetLoaderMarkup: jest.fn(() => ''),
4747
widgetMaxHeight: 700,
48+
widgetExpandMinWidth: 768,
4849
}));
4950

5051
const EXPANDED_CLASS = 'gleap-frame-container--expanded';
@@ -178,6 +179,26 @@ describe('GleapFrameManager expand/collapse window', () => {
178179
expect(fm.gleapFrameContainer.classList.contains(EXPANDED_CLASS)).toBe(false);
179180
});
180181

182+
it.each([571, 767.5])('is not expandable on a %spx viewport too narrow for the expanded widget', (width) => {
183+
// E.g. a phone with the page zoomed out: past the mobile breakpoint, so the
184+
// floating widget shows, but an expanded one would cover nearly the whole page.
185+
loadFromGleapCache.mockImplementation((key) => (key === 'widget-expanded' ? true : null));
186+
viewportWidth = width;
187+
const fm = setup();
188+
fm.updateFrameStyle();
189+
190+
expect(fm.canExpandWidget()).toBe(false);
191+
expect(fm.isWidgetExpanded()).toBe(false);
192+
expect(fm.gleapFrameContainer.classList.contains(EXPANDED_CLASS)).toBe(false);
193+
});
194+
195+
it('is expandable from the expand breakpoint on', () => {
196+
viewportWidth = 768;
197+
const fm = setup();
198+
199+
expect(fm.canExpandWidget()).toBe(true);
200+
});
201+
181202
it('collapses and hides the button when a config update turns the setting off', () => {
182203
const fm = setup();
183204
fm.setWidgetExpanded(true);
@@ -224,7 +245,7 @@ describe('GleapFrameManager expand/collapse window', () => {
224245
expect(sentSizeUpdates().pop().data).toEqual({ expandable: true, expanded: false });
225246
});
226247

227-
it('applies a stored expanded choice when the window widens past the mobile breakpoint', () => {
248+
it('applies a stored expanded choice when the window widens past the expand breakpoint', () => {
228249
loadFromGleapCache.mockImplementation((key) => (key === 'widget-expanded' ? true : null));
229250
isMobile = true;
230251
const fm = setup();

‎src/UI.js‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export const calculateContrast = (hex) => {
2929

3030
export const widgetMaxHeight = 700;
3131

32+
// Narrowest viewport that leaves room around the 690px expanded widget. Below it the
33+
// expanded widget would cover nearly the whole page (e.g. a phone with the page zoomed
34+
// out just past the 450px mobile breakpoint), so the widget keeps its default size.
35+
export const widgetExpandMinWidth = 768;
36+
3237
// Builds the loading placeholder shown while the messenger iframe boots.
3338
// Mirrors the Messenger-App home backgrounds (BG.svg / BGclassic.svg /
3439
// BGclassicnofade.svg) so the hand-off from loader to app is seamless.
@@ -806,9 +811,9 @@ export const injectStyledCSS = (
806811
}
807812
808813
/* Expanded by the end user (expand/collapse button in the messenger header).
809-
Below 451px the widget is full screen anyway. The inner max-height must beat
810-
the inline 700px set by GleapFrameManager.setAppMode. */
811-
@media only screen and (min-width: 451px) {
814+
Only on viewports with room for it (see widgetExpandMinWidth). The inner
815+
max-height must beat the inline 700px set by GleapFrameManager.setAppMode. */
816+
@media only screen and (min-width: ${widgetExpandMinWidth}px) {
812817
.gleap-frame-container--expanded {
813818
max-width: 690px !important;
814819
}

0 commit comments

Comments
 (0)