0
Fork 0
mirror of https://github.com/penpot/penpot-plugins.git synced 2025-01-04 13:50:13 -05:00

chore: allow user to resize modal window

This commit is contained in:
Marina López 2024-09-30 11:46:28 +02:00 committed by Xaviju
parent 51625c3e82
commit 13ea206eab
6 changed files with 66 additions and 20 deletions

View file

@ -0,0 +1 @@
<svg width="16.022" xmlns="http://www.w3.org/2000/svg" height="16.022" viewBox="-0.011 -0.011 16.022 16.022" fill="none"><g data-testid="Group"><g data-testid="Path"><path d="M.011 15.917 15.937-.011" class="fills"/><g class="strokes"><path d="M.011 15.917 15.937-.011" style="fill: none; stroke-width: 1; stroke: rgb(111, 111, 111); stroke-opacity: 1; stroke-linecap: round;" class="stroke-shape"/></g></g><g data-testid="Path"><path d="m11.207 14.601 3.361-3.401" class="fills"/><g class="strokes"><path d="m11.207 14.601 3.361-3.401" style="fill: none; stroke-width: 1; stroke: rgb(111, 111, 111); stroke-opacity: 1; stroke-linecap: round;" class="stroke-shape"/></g></g><g data-testid="Path"><path d="m4.884 16.004 11.112-11.17" class="fills"/><g class="strokes"><path d="m4.884 16.004 11.112-11.17" style="fill: none; stroke-width: 1; stroke: rgb(111, 111, 111); stroke-opacity: 1; stroke-linecap: round;" class="stroke-shape"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 951 B

View file

@ -44,10 +44,6 @@ describe('createModal', () => {
'--modal-block-start',
'40px'
);
expect(modal.style.setProperty).toHaveBeenCalledWith(
'--modal-inline-end',
'320px'
);
expect(modal.setAttribute).toHaveBeenCalledWith('title', 'Test Modal');
expect(modal.setAttribute).toHaveBeenCalledWith(
@ -83,7 +79,7 @@ describe('createModal', () => {
options
);
const expectedWidth = 680; // 1000 - 320 (initialPosition.inlineEnd)
const expectedWidth = 710; // 1000 - 270 (initialPosition.inlineEnd)
const expectedHeight = 760; // 800 - 40 (initialPosition.blockStart)
expect(modal.setAttribute).toHaveBeenCalledWith(

View file

@ -18,9 +18,16 @@ export function createModal(
const defaultWidth = 335;
const defaultHeight = 590;
const maxWidth =
(options?.width ?? defaultWidth) > window.innerWidth
? window.innerWidth - 290
: options?.width ?? defaultWidth;
const initialPosition = {
blockStart: 40,
inlineEnd: 320,
// To be able to resize the element as expected the position must be absolute from the right.
// This value is the length of the window minus the width of the element plus the width of the design tab.
inlineStart: window.innerWidth - maxWidth - 290,
};
modal.style.setProperty(
@ -28,11 +35,10 @@ export function createModal(
`${initialPosition.blockStart}px`
);
modal.style.setProperty(
'--modal-inline-end',
`${initialPosition.inlineEnd}px`
'--modal-inline-start',
`${initialPosition.inlineStart}px`
);
const maxWidth = window.innerWidth - initialPosition.inlineEnd;
const maxHeight = window.innerHeight - initialPosition.blockStart;
let width = Math.min(options?.width || defaultWidth, maxWidth);
let height = Math.min(options?.height || defaultHeight, maxHeight);

View file

@ -1,4 +1,4 @@
export const dragHandler = (el: HTMLElement, move?: () => void) => {
export const dragHandler = (el: HTMLElement, target: HTMLElement = el, move?: () => void) => {
let currentTranslate = { x: 0, y: 0 };
let initialTranslate = { x: 0, y: 0 };
let initialClientPosition = { x: 0, y: 0 };
@ -10,7 +10,7 @@ export const dragHandler = (el: HTMLElement, move?: () => void) => {
currentTranslate = { x: deltaX, y: deltaY };
el.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
target.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
move?.();
};

View file

@ -12,6 +12,7 @@ export class PluginModalElement extends HTMLElement {
}
#wrapper: HTMLElement | null = null;
#inner: HTMLElement | null = null;
#dragEvents: ReturnType<typeof dragHandler> | null = null;
setTheme(theme: Theme) {
@ -54,12 +55,20 @@ export class PluginModalElement extends HTMLElement {
}
this.#wrapper = document.createElement('div');
this.#inner = document.createElement('div');
this.#inner.classList.add('inner');
this.#wrapper.classList.add('wrapper');
this.#wrapper.style.inlineSize = `${width}px`;
this.#wrapper.style.minInlineSize = `${width}px`;
this.#wrapper.style.blockSize = `${height}px`;
this.#wrapper.style.minBlockSize = `${height}px`;
this.#wrapper.style.maxInlineSize = '90vw';
this.#wrapper.style.maxBlockSize = '90vh';
// move modal to the top
this.#dragEvents = dragHandler(this.#wrapper, () => {
this.#dragEvents = dragHandler(this.#inner, this.#wrapper, () => {
this.calculateZIndex();
});
@ -124,8 +133,9 @@ export class PluginModalElement extends HTMLElement {
this.shadowRoot.appendChild(this.#wrapper);
this.#wrapper.appendChild(header);
this.#wrapper.appendChild(iframe);
this.#wrapper.appendChild(this.#inner);
this.#inner.appendChild(header);
this.#inner.appendChild(iframe);
const style = document.createElement('style');
style.textContent = modalCss;

View file

@ -25,18 +25,51 @@
color: var(--color-foreground-secondary);
}
::-webkit-resizer {
display: none;
}
.wrapper {
box-sizing: border-box;
display: flex;
flex-direction: column;
position: fixed;
position: absolute;
inset-block-start: var(--modal-block-start);
inset-inline-end: var(--modal-inline-end);
inset-inline-start: var(--modal-inline-start);
z-index: 1000;
padding: 25px;
padding: 10px;
border-radius: 15px;
border: 2px solid var(--color-background-quaternary);
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
overflow: hidden;
min-inline-size: 25px;
min-block-size: 200px;
resize: both;
&:after {
content: '';
cursor: se-resize;
inline-size: 1rem;
block-size: 1rem;
background-image: url('../assets/resize.svg');
background-position: center;
right: 5px;
bottom: 5px;
pointer-events: none;
position: absolute;
}
}
.inner {
padding: 10px;
cursor: grab;
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
block-size: 100%;
& > * {
flex: 1;
}
& > .header {
flex: 0;
}
}
.header {