203 lines
4.7 KiB
TypeScript
203 lines
4.7 KiB
TypeScript
import {
|
|
DeesElement,
|
|
css,
|
|
cssManager,
|
|
customElement,
|
|
html,
|
|
property,
|
|
type TemplateResult,
|
|
} from '@design.estate/dees-element';
|
|
|
|
import { mobileComponentStyles } from '../../00componentstyles.js';
|
|
import '../dees-mobile-icon/dees-mobile-icon.js';
|
|
import { demoFunc } from './dees-mobile-modal.demo.js';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'dees-mobile-modal': DeesMobileModal;
|
|
}
|
|
}
|
|
|
|
@customElement('dees-mobile-modal')
|
|
export class DeesMobileModal extends DeesElement {
|
|
public static demo = demoFunc;
|
|
|
|
@property({ type: Boolean })
|
|
accessor open: boolean = false;
|
|
|
|
@property({ type: String })
|
|
accessor title: string = '';
|
|
|
|
@property({ type: Boolean })
|
|
accessor showCloseButton: boolean = true;
|
|
|
|
public static styles = [
|
|
cssManager.defaultStyles,
|
|
mobileComponentStyles,
|
|
css`
|
|
.modal-backdrop {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: var(--dees-z-modal, 500);
|
|
padding: 1rem;
|
|
animation: fadeIn 200ms ease-out;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.modal {
|
|
background: ${cssManager.bdTheme('#ffffff', '#18181b')};
|
|
border-radius: 0.75rem;
|
|
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
/* Mobile-first defaults */
|
|
max-width: 100%;
|
|
width: 100%;
|
|
max-height: 90vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
animation: slideUp 200ms ease-out;
|
|
}
|
|
|
|
/* Desktop enhancements */
|
|
@media (min-width: 641px) {
|
|
.modal {
|
|
max-width: 500px;
|
|
}
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from {
|
|
transform: translateY(20px);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: translateY(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
/* Mobile-first defaults */
|
|
padding: 1rem;
|
|
border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
}
|
|
|
|
/* Desktop enhancements */
|
|
@media (min-width: 641px) {
|
|
.modal-header {
|
|
padding: 1.5rem;
|
|
}
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: 1.125rem;
|
|
font-weight: 600;
|
|
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
|
margin: 0;
|
|
}
|
|
|
|
.close-button {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 2rem;
|
|
height: 2rem;
|
|
border: none;
|
|
background: transparent;
|
|
border-radius: 0.25rem;
|
|
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
cursor: pointer;
|
|
transition: all 150ms ease;
|
|
}
|
|
|
|
.close-button:hover {
|
|
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
|
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
|
}
|
|
|
|
.modal-content {
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
padding: 1rem;
|
|
}
|
|
|
|
@media (min-width: 641px) {
|
|
.modal-content {
|
|
padding: 1.5rem;
|
|
}
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: 0.5rem;
|
|
padding: 1rem;
|
|
border-top: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
}
|
|
|
|
@media (min-width: 641px) {
|
|
.modal-footer {
|
|
padding: 1.5rem;
|
|
}
|
|
}
|
|
|
|
.modal-footer:empty {
|
|
display: none;
|
|
}
|
|
`,
|
|
];
|
|
|
|
private handleBackdropClick(e: MouseEvent) {
|
|
if (e.target === e.currentTarget) {
|
|
this.handleClose();
|
|
}
|
|
}
|
|
|
|
private handleClose() {
|
|
this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }));
|
|
}
|
|
|
|
public render(): TemplateResult {
|
|
if (!this.open) return html``;
|
|
|
|
return html`
|
|
<div class="modal-backdrop" @click=${this.handleBackdropClick}>
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h2 class="modal-title">${this.title}</h2>
|
|
${this.showCloseButton ? html`
|
|
<button class="close-button" @click=${this.handleClose} aria-label="Close">
|
|
<dees-mobile-icon icon="x" size="20"></dees-mobile-icon>
|
|
</button>
|
|
` : ''}
|
|
</div>
|
|
<div class="modal-content">
|
|
<slot></slot>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<slot name="footer"></slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|