Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
27414e0284 | |||
d63bc762d0 | |||
505e40a57f | |||
d1ea10d8c6 |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@design.estate/dees-catalog",
|
"name": "@design.estate/dees-catalog",
|
||||||
"version": "1.9.4",
|
"version": "1.9.5",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
||||||
"main": "dist_ts_web/index.js",
|
"main": "dist_ts_web/index.js",
|
||||||
|
@ -514,3 +514,94 @@ The refactoring follows the principles in instructions.md:
|
|||||||
- Uses static templates with manual DOM operations
|
- Uses static templates with manual DOM operations
|
||||||
- Maintains separated concerns in different classes
|
- Maintains separated concerns in different classes
|
||||||
- Results in clean, concise, and manageable code
|
- Results in clean, concise, and manageable code
|
||||||
|
|
||||||
|
## Z-Index Management System (2025-12-24)
|
||||||
|
|
||||||
|
A comprehensive z-index management system has been implemented to fix overlay stacking conflicts:
|
||||||
|
|
||||||
|
### The Problem:
|
||||||
|
- Modals were hiding dropdown overlays
|
||||||
|
- Context menus appeared behind modals
|
||||||
|
- Inconsistent z-index values across components
|
||||||
|
- No clear hierarchy for overlay stacking
|
||||||
|
|
||||||
|
### The Solution:
|
||||||
|
|
||||||
|
#### 1. Central Z-Index Constants (`00zindex.ts`):
|
||||||
|
Created a centralized file defining all z-index layers:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const zIndexLayers = {
|
||||||
|
// Base layer: Regular content
|
||||||
|
base: {
|
||||||
|
content: 'auto',
|
||||||
|
inputElements: 1,
|
||||||
|
},
|
||||||
|
// Fixed UI elements
|
||||||
|
fixed: {
|
||||||
|
appBar: 10,
|
||||||
|
sideMenu: 10,
|
||||||
|
mobileNav: 250,
|
||||||
|
},
|
||||||
|
// Overlay backdrops
|
||||||
|
backdrop: {
|
||||||
|
dropdown: 1999,
|
||||||
|
modal: 2999,
|
||||||
|
contextMenu: 3999,
|
||||||
|
},
|
||||||
|
// Interactive overlays
|
||||||
|
overlay: {
|
||||||
|
dropdown: 2000, // Dropdowns and select menus
|
||||||
|
modal: 3000, // Modal dialogs
|
||||||
|
contextMenu: 4000, // Context menus and tooltips
|
||||||
|
toast: 5000, // Toast notifications
|
||||||
|
},
|
||||||
|
// Special cases
|
||||||
|
modalDropdown: 3500, // Dropdowns inside modals
|
||||||
|
wysiwygMenus: 4500, // Editor formatting menus
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Updated Components:
|
||||||
|
- **dees-modal**: Changed from 2000 to 3000
|
||||||
|
- **dees-windowlayer**: Changed from 200-201 to 1999-2000 (used by dropdowns)
|
||||||
|
- **dees-contextmenu**: Changed from 10000 to 4000
|
||||||
|
- **dees-toast**: Changed from 10000 to 5000
|
||||||
|
- **wysiwyg menus**: Changed from 10000 to 4500
|
||||||
|
- **dees-appui-profiledropdown**: Uses new dropdown z-index (2000)
|
||||||
|
|
||||||
|
#### 3. Stacking Order (bottom to top):
|
||||||
|
1. Regular page content (auto)
|
||||||
|
2. Fixed navigation elements (10-250)
|
||||||
|
3. Dropdown backdrop (1999)
|
||||||
|
4. Dropdown content (2000)
|
||||||
|
5. Modal backdrop (2999)
|
||||||
|
6. Modal content (3000)
|
||||||
|
7. Context menu (4000)
|
||||||
|
8. WYSIWYG menus (4500)
|
||||||
|
9. Toast notifications (5000)
|
||||||
|
|
||||||
|
#### 4. Key Benefits:
|
||||||
|
- Dropdowns now appear above modals
|
||||||
|
- Context menus appear above dropdowns and modals
|
||||||
|
- Toast notifications always appear on top
|
||||||
|
- Consistent and predictable stacking behavior
|
||||||
|
- Easy to adjust hierarchy by modifying central constants
|
||||||
|
|
||||||
|
#### 5. Testing:
|
||||||
|
Created `test-zindex.demo.ts` to verify stacking behavior with:
|
||||||
|
- Modal containing dropdown
|
||||||
|
- Context menu on modal
|
||||||
|
- Toast notifications
|
||||||
|
- Complex overlay combinations
|
||||||
|
|
||||||
|
### Usage:
|
||||||
|
Import and use the z-index constants in any component:
|
||||||
|
```typescript
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
|
|
||||||
|
// In styles
|
||||||
|
z-index: ${zIndexLayers.overlay.modal};
|
||||||
|
```
|
||||||
|
|
||||||
|
This system ensures proper stacking order for all overlay components and prevents z-index conflicts.
|
59
ts_web/elements/00zindex.ts
Normal file
59
ts_web/elements/00zindex.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Central z-index management for consistent stacking order
|
||||||
|
* Higher numbers appear on top of lower numbers
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const zIndexLayers = {
|
||||||
|
// Base layer: Regular content
|
||||||
|
base: {
|
||||||
|
content: 'auto',
|
||||||
|
inputElements: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Fixed UI elements
|
||||||
|
fixed: {
|
||||||
|
appBar: 10,
|
||||||
|
sideMenu: 10,
|
||||||
|
mobileNav: 250,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Overlay backdrops (semi-transparent backgrounds)
|
||||||
|
backdrop: {
|
||||||
|
dropdown: 1999, // Below modals but above fixed elements
|
||||||
|
modal: 2999, // Below dropdowns on modals
|
||||||
|
contextMenu: 3999, // Below critical overlays
|
||||||
|
},
|
||||||
|
|
||||||
|
// Interactive overlays
|
||||||
|
overlay: {
|
||||||
|
dropdown: 2000, // Dropdowns and select menus
|
||||||
|
modal: 3000, // Modal dialogs
|
||||||
|
contextMenu: 4000, // Context menus and tooltips
|
||||||
|
toast: 5000, // Toast notifications (highest priority)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Special cases for nested elements
|
||||||
|
modalDropdown: 3500, // Dropdowns inside modals
|
||||||
|
wysiwygMenus: 4500, // Editor formatting menus
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// Helper function to get z-index value
|
||||||
|
export function getZIndex(category: keyof typeof zIndexLayers, subcategory?: string): number | string {
|
||||||
|
const categoryObj = zIndexLayers[category];
|
||||||
|
if (typeof categoryObj === 'object' && subcategory) {
|
||||||
|
return categoryObj[subcategory as keyof typeof categoryObj] || 'auto';
|
||||||
|
}
|
||||||
|
return typeof categoryObj === 'number' ? categoryObj : 'auto';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z-index assignments for components
|
||||||
|
export const componentZIndex = {
|
||||||
|
'dees-modal': zIndexLayers.overlay.modal,
|
||||||
|
'dees-windowlayer': zIndexLayers.overlay.dropdown,
|
||||||
|
'dees-contextmenu': zIndexLayers.overlay.contextMenu,
|
||||||
|
'dees-toast': zIndexLayers.overlay.toast,
|
||||||
|
'dees-appui-mainmenu': zIndexLayers.fixed.appBar,
|
||||||
|
'dees-mobilenavigation': zIndexLayers.fixed.mobileNav,
|
||||||
|
'dees-slash-menu': zIndexLayers.wysiwygMenus,
|
||||||
|
'dees-formatting-menu': zIndexLayers.wysiwygMenus,
|
||||||
|
} as const;
|
@ -1,5 +1,6 @@
|
|||||||
import * as plugins from './00plugins.js';
|
import * as plugins from './00plugins.js';
|
||||||
import * as interfaces from './interfaces/index.js';
|
import * as interfaces from './interfaces/index.js';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -46,7 +47,7 @@ export class DeesAppuiMainmenu extends DeesElement {
|
|||||||
.mainContainer {
|
.mainContainer {
|
||||||
--menuSize: 60px;
|
--menuSize: 60px;
|
||||||
color: ${cssManager.bdTheme('#666', '#ccc')};
|
color: ${cssManager.bdTheme('#666', '#ccc')};
|
||||||
z-index: 10;
|
z-index: ${zIndexLayers.fixed.appBar};
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: var(--menuSize);
|
width: var(--menuSize);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from './00plugins.js';
|
import * as plugins from './00plugins.js';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -73,7 +74,7 @@ export class DeesAppuiProfileDropdown extends DeesElement {
|
|||||||
'0 4px 12px rgba(0, 0, 0, 0.15)',
|
'0 4px 12px rgba(0, 0, 0, 0.15)',
|
||||||
'0 4px 12px rgba(0, 0, 0, 0.3)'
|
'0 4px 12px rgba(0, 0, 0, 0.3)'
|
||||||
)};
|
)};
|
||||||
z-index: 1000;
|
z-index: ${zIndexLayers.overlay.dropdown};
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.95) translateY(-10px);
|
transform: scale(0.95) translateY(-10px);
|
||||||
transition: opacity 0.2s, transform 0.2s;
|
transition: opacity 0.2s, transform 0.2s;
|
||||||
@ -258,7 +259,7 @@ export class DeesAppuiProfileDropdown extends DeesElement {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
z-index: 999;
|
z-index: ${zIndexLayers.backdrop.dropdown};
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s;
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
|
|
||||||
import * as domtools from '@design.estate/dees-domtools';
|
import * as domtools from '@design.estate/dees-domtools';
|
||||||
import { DeesWindowLayer } from './dees-windowlayer.js';
|
import { DeesWindowLayer } from './dees-windowlayer.js';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
import './dees-icon.js';
|
import './dees-icon.js';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -74,7 +75,7 @@ export class DeesContextmenu extends DeesElement {
|
|||||||
eventArg.stopPropagation();
|
eventArg.stopPropagation();
|
||||||
const contextMenu = new DeesContextmenu();
|
const contextMenu = new DeesContextmenu();
|
||||||
contextMenu.style.position = 'fixed';
|
contextMenu.style.position = 'fixed';
|
||||||
contextMenu.style.zIndex = '10000';
|
contextMenu.style.zIndex = String(zIndexLayers.overlay.contextMenu);
|
||||||
contextMenu.style.opacity = '0';
|
contextMenu.style.opacity = '0';
|
||||||
contextMenu.style.transform = 'scale(0.95) translateY(-10px)';
|
contextMenu.style.transform = 'scale(0.95) translateY(-10px)';
|
||||||
contextMenu.menuItems = menuItemsArg;
|
contextMenu.menuItems = menuItemsArg;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from './00plugins.js';
|
import * as plugins from './00plugins.js';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
import {
|
import {
|
||||||
cssManager,
|
cssManager,
|
||||||
css,
|
css,
|
||||||
@ -83,7 +84,7 @@ export class DeesMobilenavigation extends DeesElement {
|
|||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
transform: translateX(200px);
|
transform: translateX(200px);
|
||||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||||
z-index: 250;
|
z-index: ${zIndexLayers.fixed.mobileNav};
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
padding: 16px 32px;
|
padding: 16px 32px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
|
@ -1,37 +1,356 @@
|
|||||||
import { html } from '@design.estate/dees-element';
|
import { html, css, cssManager } from '@design.estate/dees-element';
|
||||||
import { DeesModal } from './dees-modal.js';
|
import { DeesModal } from './dees-modal.js';
|
||||||
|
|
||||||
export const demoFunc = () => html`
|
export const demoFunc = () => html`
|
||||||
|
<style>
|
||||||
|
${css`
|
||||||
|
.demo-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 24px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-section {
|
||||||
|
background: ${cssManager.bdTheme('#f8f9fa', '#1a1a1a')};
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px;
|
||||||
|
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-section h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-section p {
|
||||||
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="demo-container">
|
||||||
|
<div class="demo-section">
|
||||||
|
<h3>Header Buttons</h3>
|
||||||
|
<p>Modals can have optional header buttons for help and closing.</p>
|
||||||
|
<div class="button-grid">
|
||||||
<dees-button @click=${() => {
|
<dees-button @click=${() => {
|
||||||
DeesModal.createAndShow({
|
DeesModal.createAndShow({
|
||||||
heading: 'This is a heading',
|
heading: 'With Help Button',
|
||||||
|
showHelpButton: true,
|
||||||
|
onHelp: async () => {
|
||||||
|
const helpModal = await DeesModal.createAndShow({
|
||||||
|
heading: 'Help',
|
||||||
|
width: 'small',
|
||||||
|
showCloseButton: true,
|
||||||
|
showHelpButton: false,
|
||||||
|
content: html`
|
||||||
|
<p>This is the help content for the modal.</p>
|
||||||
|
<p>You can provide context-specific help here.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Got it',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
content: html`
|
||||||
|
<p>This modal has a help button in the header. Click it to see help content.</p>
|
||||||
|
<p>The close button is also visible by default.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'OK',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>With Help Button</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'No Close Button',
|
||||||
|
showCloseButton: false,
|
||||||
|
content: html`
|
||||||
|
<p>This modal has no close button in the header.</p>
|
||||||
|
<p>You must use the action buttons or click outside to close it.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Close',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>No Close Button</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Both Buttons',
|
||||||
|
showHelpButton: true,
|
||||||
|
showCloseButton: true,
|
||||||
|
onHelp: () => alert('Help clicked!'),
|
||||||
|
content: html`
|
||||||
|
<p>This modal has both help and close buttons.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Done',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Both Buttons</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Clean Header',
|
||||||
|
showCloseButton: false,
|
||||||
|
showHelpButton: false,
|
||||||
|
content: html`
|
||||||
|
<p>This modal has a clean header with no buttons.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Close',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Clean Header</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-section">
|
||||||
|
<h3>Modal Width Variations</h3>
|
||||||
|
<p>Modals can have different widths: small, medium, large, fullscreen, or custom pixel values.</p>
|
||||||
|
<div class="button-grid">
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Small Modal',
|
||||||
|
width: 'small',
|
||||||
|
content: html`
|
||||||
|
<p>This is a small modal with a width of 380px. Perfect for simple confirmations or brief messages.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Cancel',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'OK',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Small Modal</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Medium Modal (Default)',
|
||||||
|
width: 'medium',
|
||||||
content: html`
|
content: html`
|
||||||
<dees-form>
|
<dees-form>
|
||||||
<dees-input-text
|
<dees-input-text .label=${'Username'}></dees-input-text>
|
||||||
.label=${'Username'}
|
<dees-input-text .label=${'Email'} .inputType=${'email'}></dees-input-text>
|
||||||
>
|
<dees-input-text .label=${'Password'} .inputType=${'password'}></dees-input-text>
|
||||||
</dees-input-text>
|
|
||||||
<dees-input-text
|
|
||||||
.label=${'Password'}
|
|
||||||
>
|
|
||||||
</dees-input-text>
|
|
||||||
</dees-form>
|
</dees-form>
|
||||||
`,
|
`,
|
||||||
menuOptions: [{
|
menuOptions: [{
|
||||||
name: 'Cancel',
|
name: 'Cancel',
|
||||||
iconName: null,
|
action: async (modal) => modal.destroy()
|
||||||
action: async (deesModalArg) => {
|
|
||||||
deesModalArg.destroy();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
name: 'Ok',
|
name: 'Sign Up',
|
||||||
iconName: null,
|
action: async (modal) => modal.destroy()
|
||||||
action: async (deesModalArg) => {
|
|
||||||
deesModalArg.destroy();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
}}>open modal</dees-button>
|
}}>Medium Modal</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Large Modal',
|
||||||
|
width: 'large',
|
||||||
|
content: html`
|
||||||
|
<h4>Wide Content Area</h4>
|
||||||
|
<p>This large modal is 800px wide and perfect for displaying more complex content like forms with multiple columns, tables, or detailed information.</p>
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 16px;">
|
||||||
|
<dees-input-text .label=${'First Name'}></dees-input-text>
|
||||||
|
<dees-input-text .label=${'Last Name'}></dees-input-text>
|
||||||
|
<dees-input-text .label=${'Company'}></dees-input-text>
|
||||||
|
<dees-input-text .label=${'Position'}></dees-input-text>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Cancel',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'Save',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Large Modal</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Fullscreen Editor',
|
||||||
|
width: 'fullscreen',
|
||||||
|
showHelpButton: true,
|
||||||
|
onHelp: async () => {
|
||||||
|
alert('In a real app, this would show editor documentation');
|
||||||
|
},
|
||||||
|
content: html`
|
||||||
|
<h4>Fullscreen Experience with Header Controls</h4>
|
||||||
|
<p>This modal takes up almost the entire viewport with a 20px margin on all sides. The header buttons are particularly useful in fullscreen mode.</p>
|
||||||
|
<p>The content area can be as tall as needed and will scroll if necessary.</p>
|
||||||
|
<div style="height: 200px; background: ${cssManager.bdTheme('#f0f0f0', '#2a2a2a')}; border-radius: 8px; display: flex; align-items: center; justify-content: center; margin-top: 16px;">
|
||||||
|
<span style="color: ${cssManager.bdTheme('#999', '#666')}">Large content area</span>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Save',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'Cancel',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Fullscreen Modal</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-section">
|
||||||
|
<h3>Custom Width & Constraints</h3>
|
||||||
|
<p>You can also set custom pixel widths and min/max constraints.</p>
|
||||||
|
<div class="button-grid">
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Custom Width (700px)',
|
||||||
|
width: 700,
|
||||||
|
content: html`
|
||||||
|
<p>This modal has a custom width of exactly 700 pixels.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Close',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Custom 700px</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'With Max Width',
|
||||||
|
width: 'large',
|
||||||
|
maxWidth: 600,
|
||||||
|
content: html`
|
||||||
|
<p>This modal is set to 'large' but constrained by a maxWidth of 600px.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Got it',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Max Width 600px</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'With Min Width',
|
||||||
|
width: 300,
|
||||||
|
minWidth: 400,
|
||||||
|
content: html`
|
||||||
|
<p>This modal width is set to 300px but has a minWidth of 400px, so it will be 400px wide.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'OK',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Min Width 400px</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-section">
|
||||||
|
<h3>Button Variations</h3>
|
||||||
|
<p>Modals can have different button configurations with proper spacing.</p>
|
||||||
|
<div class="button-grid">
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Multiple Actions',
|
||||||
|
content: html`
|
||||||
|
<p>This modal demonstrates multiple buttons with proper spacing between them.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Delete',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'Cancel',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'Save Changes',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Three Buttons</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Single Action',
|
||||||
|
content: html`
|
||||||
|
<p>Sometimes you just need one button.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Acknowledge',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Single Button</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'No Actions',
|
||||||
|
content: html`
|
||||||
|
<p>This modal has no bottom buttons. Use the X button or click outside to close.</p>
|
||||||
|
<p style="margin-top: 16px; color: ${cssManager.bdTheme('#666', '#999')};">This is useful for informational modals that don't require user action.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [],
|
||||||
|
});
|
||||||
|
}}>No Buttons</dees-button>
|
||||||
|
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Long Button Labels',
|
||||||
|
content: html`
|
||||||
|
<p>Testing button layout with longer labels.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Discard All Changes',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}, {
|
||||||
|
name: 'Save and Continue Editing',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Long Labels</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-section">
|
||||||
|
<h3>Responsive Behavior</h3>
|
||||||
|
<p>All modals automatically become full-width on mobile devices (< 768px viewport width) for better usability.</p>
|
||||||
|
<dees-button @click=${() => {
|
||||||
|
DeesModal.createAndShow({
|
||||||
|
heading: 'Responsive Modal',
|
||||||
|
width: 'large',
|
||||||
|
showHelpButton: true,
|
||||||
|
onHelp: () => console.log('Help requested for responsive modal'),
|
||||||
|
content: html`
|
||||||
|
<p>Resize your browser window to see how this modal adapts. On mobile viewports, it will automatically take the full width minus margins.</p>
|
||||||
|
<p>The header buttons remain accessible at all viewport sizes.</p>
|
||||||
|
`,
|
||||||
|
menuOptions: [{
|
||||||
|
name: 'Close',
|
||||||
|
action: async (modal) => modal.destroy()
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}}>Test Responsive</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`
|
`
|
@ -1,5 +1,6 @@
|
|||||||
import * as colors from './00colors.js';
|
import * as colors from './00colors.js';
|
||||||
import * as plugins from './00plugins.js';
|
import * as plugins from './00plugins.js';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
|
|
||||||
import { demoFunc } from './dees-modal.demo.js';
|
import { demoFunc } from './dees-modal.demo.js';
|
||||||
import {
|
import {
|
||||||
@ -18,6 +19,7 @@ import {
|
|||||||
|
|
||||||
import * as domtools from '@design.estate/dees-domtools';
|
import * as domtools from '@design.estate/dees-domtools';
|
||||||
import { DeesWindowLayer } from './dees-windowlayer.js';
|
import { DeesWindowLayer } from './dees-windowlayer.js';
|
||||||
|
import './dees-icon.js';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
@ -34,12 +36,24 @@ export class DeesModal extends DeesElement {
|
|||||||
heading: string;
|
heading: string;
|
||||||
content: TemplateResult;
|
content: TemplateResult;
|
||||||
menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[];
|
menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[];
|
||||||
|
width?: 'small' | 'medium' | 'large' | 'fullscreen' | number;
|
||||||
|
maxWidth?: number;
|
||||||
|
minWidth?: number;
|
||||||
|
showCloseButton?: boolean;
|
||||||
|
showHelpButton?: boolean;
|
||||||
|
onHelp?: () => void | Promise<void>;
|
||||||
}) {
|
}) {
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
const modal = new DeesModal();
|
const modal = new DeesModal();
|
||||||
modal.heading = optionsArg.heading;
|
modal.heading = optionsArg.heading;
|
||||||
modal.content = optionsArg.content;
|
modal.content = optionsArg.content;
|
||||||
modal.menuOptions = optionsArg.menuOptions;
|
modal.menuOptions = optionsArg.menuOptions;
|
||||||
|
if (optionsArg.width) modal.width = optionsArg.width;
|
||||||
|
if (optionsArg.maxWidth) modal.maxWidth = optionsArg.maxWidth;
|
||||||
|
if (optionsArg.minWidth) modal.minWidth = optionsArg.minWidth;
|
||||||
|
if (optionsArg.showCloseButton !== undefined) modal.showCloseButton = optionsArg.showCloseButton;
|
||||||
|
if (optionsArg.showHelpButton !== undefined) modal.showHelpButton = optionsArg.showHelpButton;
|
||||||
|
if (optionsArg.onHelp) modal.onHelp = optionsArg.onHelp;
|
||||||
modal.windowLayer = await DeesWindowLayer.createAndShow({
|
modal.windowLayer = await DeesWindowLayer.createAndShow({
|
||||||
blur: true,
|
blur: true,
|
||||||
});
|
});
|
||||||
@ -48,6 +62,7 @@ export class DeesModal extends DeesElement {
|
|||||||
});
|
});
|
||||||
body.append(modal.windowLayer);
|
body.append(modal.windowLayer);
|
||||||
body.append(modal);
|
body.append(modal);
|
||||||
|
return modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
@ -63,6 +78,24 @@ export class DeesModal extends DeesElement {
|
|||||||
@state({})
|
@state({})
|
||||||
public menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[] = [];
|
public menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[] = [];
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
public width: 'small' | 'medium' | 'large' | 'fullscreen' | number = 'medium';
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public maxWidth: number;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public minWidth: number;
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
public showCloseButton: boolean = true;
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
public showHelpButton: boolean = false;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public onHelp: () => void | Promise<void>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -85,13 +118,12 @@ export class DeesModal extends DeesElement {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 2000;
|
z-index: ${zIndexLayers.overlay.modal};
|
||||||
}
|
}
|
||||||
.modal {
|
.modal {
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
transform: translateY(0px) scale(0.95);
|
transform: translateY(0px) scale(0.95);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 480px;
|
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
background: ${cssManager.bdTheme('#ffffff', '#111')};
|
background: ${cssManager.bdTheme('#ffffff', '#111')};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -99,6 +131,33 @@ export class DeesModal extends DeesElement {
|
|||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: ${cssManager.bdTheme('0px 2px 10px rgba(0, 0, 0, 0.1)', '0px 2px 5px rgba(0, 0, 0, 0.5)')};
|
box-shadow: ${cssManager.bdTheme('0px 2px 10px rgba(0, 0, 0, 0.1)', '0px 2px 5px rgba(0, 0, 0, 0.5)')};
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Width variations */
|
||||||
|
.modal.width-small {
|
||||||
|
width: 380px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.width-medium {
|
||||||
|
width: 560px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.width-large {
|
||||||
|
width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.width-fullscreen {
|
||||||
|
width: calc(100vw - 40px);
|
||||||
|
height: calc(100vh - 40px);
|
||||||
|
max-height: calc(100vh - 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.modal {
|
||||||
|
width: calc(100vw - 40px) !important;
|
||||||
|
max-width: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.show {
|
.modal.show {
|
||||||
@ -112,13 +171,61 @@ export class DeesModal extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal .heading {
|
.modal .heading {
|
||||||
height: 32px;
|
height: 40px;
|
||||||
font-family: 'Geist Sans', sans-serif;
|
font-family: 'Geist Sans', sans-serif;
|
||||||
line-height: 32px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .header-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .header-button {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
background: transparent;
|
||||||
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .header-button:hover {
|
||||||
|
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.08)')};
|
||||||
|
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .header-button:active {
|
||||||
|
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.12)', 'rgba(255, 255, 255, 0.12)')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .header-button dees-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .heading .heading-text {
|
||||||
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
line-height: 40px;
|
||||||
|
padding: 0 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .content {
|
.modal .content {
|
||||||
@ -129,26 +236,22 @@ export class DeesModal extends DeesElement {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
border-top: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
border-top: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .bottomButtons .bottomButton {
|
.modal .bottomButtons .bottomButton {
|
||||||
margin: 8px 0px;
|
padding: 8px 16px;
|
||||||
padding: 8px 12px;
|
border-radius: 6px;
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.05)', 'rgba(255, 255, 255, 0.05)')};
|
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.05)', 'rgba(255, 255, 255, 0.05)')};
|
||||||
}
|
white-space: nowrap;
|
||||||
|
|
||||||
.modal .bottomButtons .bottomButton:first-child {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
.modal .bottomButtons .bottomButton:last-child {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .bottomButtons .bottomButton:hover {
|
.modal .bottomButtons .bottomButton:hover {
|
||||||
@ -177,16 +280,36 @@ export class DeesModal extends DeesElement {
|
|||||||
];
|
];
|
||||||
|
|
||||||
public render(): TemplateResult {
|
public render(): TemplateResult {
|
||||||
|
const widthClass = typeof this.width === 'string' ? `width-${this.width}` : '';
|
||||||
|
const customWidth = typeof this.width === 'number' ? `${this.width}px` : '';
|
||||||
|
const maxWidthStyle = this.maxWidth ? `${this.maxWidth}px` : '';
|
||||||
|
const minWidthStyle = this.minWidth ? `${this.minWidth}px` : '';
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
.modal .bottomButtons {
|
${customWidth ? `.modal { width: ${customWidth}; }` : ''}
|
||||||
grid-template-columns: ${cssManager.cssGridColumns(this.menuOptions.length, 0)};
|
${maxWidthStyle ? `.modal { max-width: ${maxWidthStyle}; }` : ''}
|
||||||
}
|
${minWidthStyle ? `.modal { min-width: ${minWidthStyle}; }` : ''}
|
||||||
</style>
|
</style>
|
||||||
<div class="modalContainer" @click=${this.handleOutsideClick}>
|
<div class="modalContainer" @click=${this.handleOutsideClick}>
|
||||||
<div class="modal">
|
<div class="modal ${widthClass}">
|
||||||
<div class="heading">${this.heading}</div>
|
<div class="heading">
|
||||||
|
<div class="heading-text">${this.heading}</div>
|
||||||
|
<div class="header-buttons">
|
||||||
|
${this.showHelpButton ? html`
|
||||||
|
<div class="header-button" @click=${this.handleHelp} title="Help">
|
||||||
|
<dees-icon .icon=${'lucide:helpCircle'}></dees-icon>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
${this.showCloseButton ? html`
|
||||||
|
<div class="header-button" @click=${() => this.destroy()} title="Close">
|
||||||
|
<dees-icon .icon=${'lucide:x'}></dees-icon>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="content">${this.content}</div>
|
<div class="content">${this.content}</div>
|
||||||
|
${this.menuOptions.length > 0 ? html`
|
||||||
<div class="bottomButtons">
|
<div class="bottomButtons">
|
||||||
${this.menuOptions.map(
|
${this.menuOptions.map(
|
||||||
(actionArg, index) => html`
|
(actionArg, index) => html`
|
||||||
@ -196,6 +319,7 @@ export class DeesModal extends DeesElement {
|
|||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -226,4 +350,10 @@ export class DeesModal extends DeesElement {
|
|||||||
document.body.removeChild(this);
|
document.body.removeChild(this);
|
||||||
await this.windowLayer.destroy();
|
await this.windowLayer.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async handleHelp() {
|
||||||
|
if (this.onHelp) {
|
||||||
|
await this.onHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { customElement, DeesElement, type TemplateResult, html, css, property, cssManager } from '@design.estate/dees-element';
|
import { customElement, DeesElement, type TemplateResult, html, css, property, cssManager } from '@design.estate/dees-element';
|
||||||
|
|
||||||
import * as domtools from '@design.estate/dees-domtools';
|
import * as domtools from '@design.estate/dees-domtools';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
import { demoFunc } from './dees-toast.demo.js';
|
import { demoFunc } from './dees-toast.demo.js';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -32,7 +33,7 @@ export class DeesToast extends DeesElement {
|
|||||||
container.className = `toast-container toast-container-${position}`;
|
container.className = `toast-container toast-container-${position}`;
|
||||||
container.style.cssText = `
|
container.style.cssText = `
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 10000;
|
z-index: ${zIndexLayers.overlay.toast};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { customElement, DeesElement, domtools, type TemplateResult, html, property, type CSSResult, state, } from '@design.estate/dees-element';
|
import { customElement, DeesElement, domtools, type TemplateResult, html, property, type CSSResult, state, } from '@design.estate/dees-element';
|
||||||
|
import { zIndexLayers } from './00zindex.js';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
@ -62,7 +63,7 @@ export class DeesWindowLayer extends DeesElement {
|
|||||||
background: rgba(0, 0, 0, 0.0);
|
background: rgba(0, 0, 0, 0.0);
|
||||||
backdrop-filter: brightness(1) ${this.options.blur ? 'blur(0px)' : ''};
|
backdrop-filter: brightness(1) ${this.options.blur ? 'blur(0px)' : ''};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 200;
|
z-index: ${zIndexLayers.backdrop.dropdown};
|
||||||
}
|
}
|
||||||
.slotContent {
|
.slotContent {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -71,7 +72,7 @@ export class DeesWindowLayer extends DeesElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 201;
|
z-index: ${zIndexLayers.overlay.dropdown};
|
||||||
}
|
}
|
||||||
|
|
||||||
.visible {
|
.visible {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
export * from './00zindex.js';
|
||||||
export * from './dees-appui-activitylog.js';
|
export * from './dees-appui-activitylog.js';
|
||||||
export * from './dees-appui-appbar.js';
|
export * from './dees-appui-appbar.js';
|
||||||
export * from './dees-appui-base.js';
|
export * from './dees-appui-base.js';
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
state,
|
state,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
import { zIndexLayers } from '../00zindex.js';
|
||||||
|
|
||||||
import { WysiwygFormatting } from './wysiwyg.formatting.js';
|
import { WysiwygFormatting } from './wysiwyg.formatting.js';
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ export class DeesFormattingMenu extends DeesElement {
|
|||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 10000;
|
z-index: ${zIndexLayers.wysiwygMenus};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
state,
|
state,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
import { zIndexLayers } from '../00zindex.js';
|
||||||
|
|
||||||
import { type ISlashMenuItem } from './wysiwyg.types.js';
|
import { type ISlashMenuItem } from './wysiwyg.types.js';
|
||||||
import { WysiwygShortcuts } from './wysiwyg.shortcuts.js';
|
import { WysiwygShortcuts } from './wysiwyg.shortcuts.js';
|
||||||
@ -49,7 +50,7 @@ export class DeesSlashMenu extends DeesElement {
|
|||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 10000;
|
z-index: ${zIndexLayers.wysiwygMenus};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user