Skip to content

Commit

Permalink
fix(src/modal): modal exceeds browser edge
Browse files Browse the repository at this point in the history
Fix the modal so it doesn’t exceed the browser.
  • Loading branch information
olgahaha committed Jan 17, 2025
1 parent b096ccd commit be17429
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 57 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ jobs:
- run: npm run lint
- run: npm run build
- run: npx playwright install
- run: apt-get install libdbus-glib-1-2
- run: npm run test
45 changes: 29 additions & 16 deletions src/modal/modal-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,43 @@ export function getModalStyles() {
justify-content: flex-start;
align-items: flex-start;
display: none;
opacity: 0;
transform: scale(0.5);
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in,
display 0.3s ease;
transition-behavior: allow-discrete;
position: absolute;
}
.modal-visible {
display: flex;
opacity: 1;
transform: scale(1);
}
@starting-style {
.modal.modal-visible {
opacity: 0;
transform: scale(0.5);
}
}
.modal-hidden {
display: none;
opacity: 0;
transform: scale(0.5);
}
.modal-container {
background-color: var(--background-color);
border-radius: var(--border-radius);
width: 20rem;
box-shadow: var(--box-shadow);
opacity: 0;
transform: scale(0.5);
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in;
transition-behavior: allow-discrete;
}
.modal-visible .modal-container {
opacity: 1;
transform: scale(1);
}
.modal-hidden .modal-container {
opacity: 0;
transform: scale(0.5);
}
@starting-style {
.modal.modal-visible .modal-container {
opacity: 0;
transform: scale(0.5);
}
}
.modal-content {
Expand Down Expand Up @@ -91,6 +96,13 @@ export function getModalStyles() {
transform: scale(0.5) rotate(-90deg);
}
@starting-style {
.close-button {
opacity: 0;
transform: scale(0.5) rotate(0deg);
}
}
.close-button img {
width: 100%;
}
Expand Down Expand Up @@ -304,6 +316,7 @@ export function getModalStyles() {
width: 4rem;
height: 4rem;
margin-right: 1rem;
margin-bottom: 0.375rem;
}
@keyframes shimmer {
Expand Down
71 changes: 45 additions & 26 deletions src/modal/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export class CaptureEyeModal extends LitElement {
@state() protected _engagementZones: EngagementZone[] = [];
@state() protected _engagementZoneIndex = 0;
@state() protected _engagementZoneRotationInterval = 5000;
@state() protected _engagementZoneRotationIntervalId: number | undefined =
undefined;
@state() protected _engagementZoneRotationIntervalId:
number | NodeJS.Timeout | undefined = undefined;
@state() protected _position:
| { top: number; left: number; name: string }
| undefined = undefined;
Expand Down Expand Up @@ -313,7 +313,7 @@ export class CaptureEyeModal extends LitElement {
<div class="headline">
${this._assetLoaded
? this._asset?.headline ?? ''
: html`<div class="shimmer-text"></div>`}
: html`<div class="shimmer-text" style="height: auto;">&nbsp;</div>`}
</div>
</div>
`;
Expand Down Expand Up @@ -344,7 +344,7 @@ export class CaptureEyeModal extends LitElement {
<span class="value-text">${transactionText}</span>
</a>`
: html`<span class="value-text">${transactionText}</span>`}`
: html`<span class="shimmer-text"></span>`}`;
: html`<span class="shimmer-text" style="height: 21.5px;"></span>`}`;
}

private renderDefaultProvenanceZone() {
Expand All @@ -366,7 +366,7 @@ export class CaptureEyeModal extends LitElement {
>${Constant.text.numbersMainnet}</span
>
</a>`
: html`<span class="shimmer-text"></span>`}
: html`<span class="shimmer-text" style="height: 21.5px;"></span>`}
</div>
<div class="middle-row">${this.renderTransaction()}</div>`
: html`<div class="middle-row">
Expand All @@ -375,7 +375,7 @@ export class CaptureEyeModal extends LitElement {
<span class="field-text">
${this._asset?.backendOwnerName ?? ''}
</span>`
: html`<div class="shimmer-text"></div>`}
: html`<div class="shimmer-text" style="height: 21.5px;"></div>`}
</div>`}
</div>`;
}
Expand Down Expand Up @@ -435,7 +435,7 @@ export class CaptureEyeModal extends LitElement {
? html`<a href=${Constant.url.numbersWebsite} target="_blank"
>Powered by Numbers Protocol</a
>`
: html`<div class="shimmer-text"></div>`}
: html`<div class="shimmer-text" style="height: auto;">&nbsp;</div>`}
</div>
</div>
`;
Expand Down Expand Up @@ -506,14 +506,14 @@ export class CaptureEyeModal extends LitElement {
</div>
</div>
${this.renderEngagementZone()}
<div
class="close-button ${this.modalHidden
? 'close-button-hidden'
: 'close-button-visible'}"
@click=${this.emitRemoveEvent}
>
${generateCaptureEyeCloseSvg(color, size)}
</div>
</div>
<div
class="close-button ${this.modalHidden
? 'close-button-hidden'
: 'close-button-visible'}"
@click=${this.emitRemoveEvent}
>
${generateCaptureEyeCloseSvg(color, size)}
</div>
</div>
`;
Expand Down Expand Up @@ -605,30 +605,49 @@ export class CaptureEyeModal extends LitElement {
document.documentElement.scrollHeight)
) {
modelTop -= this.modalElement.offsetHeight;
} else if (
modelTop + this.modalElement.offsetHeight > document.documentElement.scrollHeight
) {
modelTop =
document.documentElement.scrollHeight - this.modalElement.offsetHeight;
}

if (
modelLeft > this.modalElement.offsetWidth &&
(positions.includes('right') ||
modelLeft + this.modalElement.offsetWidth >
document.documentElement.scrollWidth)
) {
modelLeft -= this.modalElement.offsetWidth;
} else if (
modelLeft + this.modalElement.offsetWidth > document.documentElement.scrollWidth
) {
modelLeft = document.documentElement.scrollWidth - this.modalElement.offsetWidth;
}

this.modalElement.style.top = `${modelTop}px`;
this.modalElement.style.left = `${modelLeft}px`;

let transform_origin = top <= modelTop ? 'top' : 'bottom';
transform_origin =
transform_origin + ' ' + (left <= modelLeft ? 'left' : 'right');
this.modalElement.style.transformOrigin = transform_origin;

closeButton.style.top = `${
top - modelTop - closeButton.offsetHeight / 2
}px`;
closeButton.style.left = `${
left - modelLeft - closeButton.offsetWidth / 2
}px`;
let startTop = top - modelTop;
let startLeft = left - modelLeft;
if (
startTop != 0 && startTop != this.modalElement.offsetHeight
&& startLeft != 0 && startLeft != this.modalElement.offsetWidth
) { // The starting position is not aligned with the edge
if (startTop <= startLeft) {
startTop = 0;
} else {
startLeft = 0;
}
}

const modalContainer = this.shadowRoot?.querySelector('.modal-container');
if (modalContainer) {
(modalContainer as HTMLDivElement).style.transformOrigin = `${startLeft}px ${startTop}px`;
}

closeButton.style.top = `${startTop - closeButton.offsetHeight / 2}px`;
closeButton.style.left = `${startLeft - closeButton.offsetWidth / 2}px`;
}
}

Expand Down
67 changes: 52 additions & 15 deletions src/test/modal_test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { html } from 'lit';
import { fixture, assert, expect, waitUntil } from '@open-wc/testing';
import { setViewport } from '@web/test-runner-commands';
import {
CaptureEyeModal,
formatTxHash,
Expand Down Expand Up @@ -42,22 +43,38 @@ suite('capture-eye-modal', () => {
</div>
</div>
<div class="headline">
<div class="shimmer-text"></div>
<div
class="shimmer-text"
style="height: auto;"
>
</div>
</div>
</div>
<div class="section">
<div class="section-title">Origins</div>
<div class="middle-row">
<span class="shimmer-text"></span>
<span
class="shimmer-text"
style="height: 21.5px;"
>
</span>
</div>
<div class="middle-row">
<span class="shimmer-text"></span>
<span
class="shimmer-text"
style="height: 21.5px;"
>
</span>
</div>
</div>
<div class="section">
<a href="https://asset.captureapp.xyz/" target="_blank"><button class="view-more-btn">View More</button></a>
<div class="powered-by">
<div class="shimmer-text"></div>
<div
class="shimmer-text"
style="height: auto;"
>
</div>
</div>
</div>
</div>
Expand All @@ -78,12 +95,12 @@ suite('capture-eye-modal', () => {
</div>
</a>
</div>
<div class="close-button close-button-hidden">
${generateCaptureEyeCloseSvg(
Constant.color.defaultEye,
32
).strings.join()}
</div>
</div>
<div class="close-button close-button-hidden">
${generateCaptureEyeCloseSvg(
Constant.color.defaultEye,
32
).strings.join()}
</div>
</div>
`
Expand Down Expand Up @@ -229,6 +246,10 @@ suite('capture-eye-modal', () => {
<capture-eye-modal></capture-eye-modal>
`);

const originalWidth = window.innerWidth;
const originalHeight = window.innerHeight;
await setViewport({ width: 850, height: 850 });

const position = { top: 100, left: 200, name: '' };

el.updateModalOptions({
Expand All @@ -239,7 +260,7 @@ suite('capture-eye-modal', () => {
el.modalHidden = false;
await el.updateComplete;

let modal = el.shadowRoot?.querySelector('.modal') as HTMLDivElement;
const modal = el.shadowRoot?.querySelector('.modal') as HTMLDivElement;

expect(modal.style.top).to.equal('116px'); // Assuming 1rem = 16px (this may vary)
expect(modal.style.left).to.equal('216px');
Expand All @@ -253,8 +274,6 @@ suite('capture-eye-modal', () => {
});
await el.updateComplete;

modal = el.shadowRoot?.querySelector('.modal') as HTMLDivElement;

expect(modal.style.top).to.equal(`${600 + 16 - modal.offsetHeight}px`);
expect(modal.style.left).to.equal(`${800 + 16 - modal.offsetWidth}px`);

Expand All @@ -267,10 +286,28 @@ suite('capture-eye-modal', () => {
});
await el.updateComplete;

modal = el.shadowRoot?.querySelector('.modal') as HTMLDivElement;

expect(modal.style.top).to.equal('116px');
expect(modal.style.left).to.equal('216px');

// Position is top left without enough space between the modal and the edges
await setViewport({ width: 400, height: 600 });
document.body.style.position = 'fixed';
el.modalHidden = true;
el.modalHidden = false;
el.updateModalOptions({
nid: '123',
position: { top: 100, left: 200, name: '' },
});
await el.updateComplete;

expect(modal.style.top).to.equal(`${600 - modal.offsetHeight}px`);
expect(modal.style.left).to.equal(`${400 - modal.offsetWidth}px`);

// Reset
document.body.style.position = 'static';
await setViewport({ width: originalWidth, height: originalHeight });
expect(window.innerWidth).to.equal(originalWidth);
expect(window.innerHeight).to.equal(originalHeight);
});

test('clears modal options correctly', async () => {
Expand Down

0 comments on commit be17429

Please sign in to comment.