mirror of
https://github.com/bitwarden/browser.git
synced 2025-03-12 13:39:14 +01:00
[PM-18859] Mobile Viewports - Extension Prompt (#13703)
* remove min-width on body element for extension prompt page * reset meta viewport content for extension prompt page * set max width of svg to avoid any overflow on mobile devices * use inline display to avoid icon overflow on mobile devices * use max width on the icon to fix overflow rather than editing the anon layout
This commit is contained in:
parent
a569dd9ad6
commit
85a5aea897
@ -13,12 +13,27 @@ import { BrowserExtensionPromptComponent } from "./browser-extension-prompt.comp
|
||||
|
||||
describe("BrowserExtensionPromptComponent", () => {
|
||||
let fixture: ComponentFixture<BrowserExtensionPromptComponent>;
|
||||
|
||||
let component: BrowserExtensionPromptComponent;
|
||||
const start = jest.fn();
|
||||
const pageState$ = new BehaviorSubject(BrowserPromptState.Loading);
|
||||
const setAttribute = jest.fn();
|
||||
const getAttribute = jest.fn().mockReturnValue("width=1010");
|
||||
|
||||
beforeEach(async () => {
|
||||
start.mockClear();
|
||||
setAttribute.mockClear();
|
||||
getAttribute.mockClear();
|
||||
|
||||
// Store original querySelector
|
||||
const originalQuerySelector = document.querySelector.bind(document);
|
||||
|
||||
// Mock querySelector while preserving the document context
|
||||
jest.spyOn(document, "querySelector").mockImplementation(function (selector) {
|
||||
if (selector === 'meta[name="viewport"]') {
|
||||
return { setAttribute, getAttribute } as unknown as HTMLMetaElement;
|
||||
}
|
||||
return originalQuerySelector.call(document, selector);
|
||||
});
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
@ -34,9 +49,14 @@ describe("BrowserExtensionPromptComponent", () => {
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BrowserExtensionPromptComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("calls start on initialization", () => {
|
||||
expect(start).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@ -87,6 +107,33 @@ describe("BrowserExtensionPromptComponent", () => {
|
||||
const mobileText = fixture.debugElement.query(By.css("p")).nativeElement;
|
||||
expect(mobileText.textContent.trim()).toBe("reopenLinkOnDesktop");
|
||||
});
|
||||
|
||||
it("sets min-width on the body", () => {
|
||||
expect(document.body.style.minWidth).toBe("auto");
|
||||
});
|
||||
|
||||
it("stores viewport content", () => {
|
||||
expect(getAttribute).toHaveBeenCalledWith("content");
|
||||
expect(component["viewportContent"]).toBe("width=1010");
|
||||
});
|
||||
|
||||
it("sets viewport meta tag to be mobile friendly", () => {
|
||||
expect(setAttribute).toHaveBeenCalledWith("content", "width=device-width, initial-scale=1.0");
|
||||
});
|
||||
|
||||
describe("on destroy", () => {
|
||||
beforeEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it("resets body min-width", () => {
|
||||
expect(document.body.style.minWidth).toBe("");
|
||||
});
|
||||
|
||||
it("resets viewport meta tag", () => {
|
||||
expect(setAttribute).toHaveBeenCalledWith("content", "width=1010");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("manual error state", () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { CommonModule, DOCUMENT } from "@angular/common";
|
||||
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||
|
||||
import { ButtonComponent, IconModule } from "@bitwarden/components";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
@ -16,7 +16,7 @@ import {
|
||||
standalone: true,
|
||||
imports: [CommonModule, I18nPipe, ButtonComponent, IconModule],
|
||||
})
|
||||
export class BrowserExtensionPromptComponent implements OnInit {
|
||||
export class BrowserExtensionPromptComponent implements OnInit, OnDestroy {
|
||||
/** Current state of the prompt page */
|
||||
protected pageState$ = this.browserExtensionPromptService.pageState$;
|
||||
|
||||
@ -25,10 +25,39 @@ export class BrowserExtensionPromptComponent implements OnInit {
|
||||
|
||||
protected BitwardenIcon = VaultIcons.BitwardenIcon;
|
||||
|
||||
constructor(private browserExtensionPromptService: BrowserExtensionPromptService) {}
|
||||
/** Content of the meta[name="viewport"] element */
|
||||
private viewportContent: string | null = null;
|
||||
|
||||
constructor(
|
||||
private browserExtensionPromptService: BrowserExtensionPromptService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.browserExtensionPromptService.start();
|
||||
|
||||
// It is not be uncommon for users to hit this page from a mobile device.
|
||||
// There are global styles and the viewport meta tag that set a min-width
|
||||
// for the page which cause it to render poorly. Remove them here.
|
||||
// https://github.com/bitwarden/clients/blob/main/apps/web/src/scss/base.scss#L6
|
||||
this.document.body.style.minWidth = "auto";
|
||||
|
||||
const viewportMeta = this.document.querySelector('meta[name="viewport"]');
|
||||
|
||||
// Save the current viewport content to reset it when the component is destroyed
|
||||
this.viewportContent = viewportMeta?.getAttribute("content") ?? null;
|
||||
viewportMeta?.setAttribute("content", "width=device-width, initial-scale=1.0");
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
// Reset the body min-width when the component is destroyed
|
||||
this.document.body.style.minWidth = "";
|
||||
|
||||
if (this.viewportContent !== null) {
|
||||
this.document
|
||||
.querySelector('meta[name="viewport"]')
|
||||
?.setAttribute("content", this.viewportContent);
|
||||
}
|
||||
}
|
||||
|
||||
openExtension(): void {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const BrowserExtensionIcon = svgIcon`
|
||||
<svg width="115" height="114" viewBox="0 0 115 114" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="tw-max-w-full" width="115" height="114" viewBox="0 0 115 114" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect class="tw-stroke-art-primary" width="107.16" height="70.68" rx="10" transform="matrix(-1 0 0 1 111.08 21.66)" stroke-width="4"/>
|
||||
<rect class="tw-stroke-art-accent" x="77.88" y="36.91" width="24.79" height="33.34" rx="5" stroke-width="2"/>
|
||||
<rect class="tw-fill-art-primary" x="97.97" y="25.65" width="5.7" height="5.7" rx="2" />
|
||||
|
Loading…
Reference in New Issue
Block a user