fix zindex

This commit is contained in:
Juergen Kunz
2025-06-26 18:37:49 +00:00
parent 931a760ee1
commit b5a2bd7436
5 changed files with 495 additions and 96 deletions

View File

@ -23,25 +23,92 @@ export const showcasePage = () => html`
overflow-y: auto;
}
.showcase-content {
padding: 40px;
.showcase-container {
max-width: 1200px;
margin: 0 auto;
padding: 48px 24px;
}
h1 {
color: ${cssManager.bdTheme('#333', '#fff')};
margin-bottom: 16px;
font-size: 32px;
.showcase-header {
text-align: center;
margin-bottom: 48px;
}
.intro {
.showcase-title {
font-size: 48px;
font-weight: 700;
margin: 0 0 16px 0;
color: ${cssManager.bdTheme('#1a1a1a', '#ffffff')};
}
.showcase-subtitle {
font-size: 20px;
color: ${cssManager.bdTheme('#666', '#999')};
font-size: 18px;
margin: 0 0 32px 0;
line-height: 1.6;
}
.showcase-section {
margin-bottom: 48px;
}
.showcase-section:last-child {
margin-bottom: 0;
padding-bottom: 48px;
}
/* Ensure all headings are theme-aware */
h1, h2, h3, h4, h5, h6 {
color: ${cssManager.bdTheme('#1a1a1a', '#ffffff')};
margin: 0;
}
p {
color: ${cssManager.bdTheme('#666', '#999')};
line-height: 1.6;
}
strong {
color: ${cssManager.bdTheme('#333', '#e0e0e0')};
}
.section-header {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 32px;
}
.section-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
background: ${cssManager.bdTheme('#e3f2fd', '#1e3a5f')};
}
.section-icon.layers { background: ${cssManager.bdTheme('#f3e5f5', '#4a148c')}; }
.section-icon.registry { background: ${cssManager.bdTheme('#e8f5e9', '#1b5e20')}; }
.section-icon.demo { background: ${cssManager.bdTheme('#fff3e0', '#e65100')}; }
.section-icon.guidelines { background: ${cssManager.bdTheme('#e0f2f1', '#004d40')}; }
.section-title {
font-size: 32px;
font-weight: 600;
margin: 0;
color: ${cssManager.bdTheme('#1a1a1a', '#ffffff')};
}
.section-description {
color: ${cssManager.bdTheme('#666', '#999')};
font-size: 16px;
line-height: 1.6;
margin-bottom: 24px;
}
.demo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
@ -49,17 +116,39 @@ export const showcasePage = () => html`
margin-bottom: 40px;
}
.demo-card {
background: ${cssManager.bdTheme('#fff', '#1a1a1a')};
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
border-radius: 12px;
padding: 24px;
transition: all 0.2s ease;
}
.demo-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px ${cssManager.bdTheme('rgba(0,0,0,0.1)', 'rgba(0,0,0,0.3)')};
}
.demo-card h4 {
margin-bottom: 16px;
font-size: 18px;
font-weight: 600;
}
.hierarchy-visual {
background: ${cssManager.bdTheme('#fff', '#1a1a1a')};
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#333')};
border-radius: 8px;
padding: 24px;
border-radius: 12px;
padding: 32px;
margin-bottom: 40px;
}
.hierarchy-visual h3 {
margin-top: 0;
color: ${cssManager.bdTheme('#333', '#fff')};
margin-bottom: 24px;
font-size: 24px;
font-weight: 600;
color: ${cssManager.bdTheme('#1a1a1a', '#fff')};
}
.layer-stack {
@ -70,19 +159,20 @@ export const showcasePage = () => html`
}
.layer {
padding: 12px 16px;
border-radius: 6px;
padding: 16px 20px;
border-radius: 8px;
display: flex;
justify-content: space-between;
align-items: center;
font-family: 'Geist Mono', monospace;
font-size: 14px;
transition: all 0.2s;
border: 1px solid transparent;
}
.layer:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateX(4px);
border-color: ${cssManager.bdTheme('#e0e0e0', '#444')};
}
.layer.base {
@ -124,16 +214,25 @@ export const showcasePage = () => html`
}
.warning-box {
background: ${cssManager.bdTheme('#fff3cd', '#332701')};
border: 1px solid ${cssManager.bdTheme('#ffeaa7', '#664400')};
border-radius: 6px;
padding: 16px;
margin-bottom: 24px;
color: ${cssManager.bdTheme('#856404', '#ffecb5')};
background: ${cssManager.bdTheme('#fff8e1', '#332701')};
border: 1px solid ${cssManager.bdTheme('#ffe082', '#664400')};
border-radius: 12px;
padding: 20px;
margin-bottom: 32px;
color: ${cssManager.bdTheme('#f57f17', '#ffecb5')};
display: flex;
align-items: flex-start;
gap: 12px;
}
.warning-box::before {
content: '⚠️';
font-size: 20px;
flex-shrink: 0;
}
.warning-box strong {
color: ${cssManager.bdTheme('#856404', '#ffd93d')};
color: ${cssManager.bdTheme('#f57f17', '#ffd93d')};
}
code {
@ -160,56 +259,186 @@ export const showcasePage = () => html`
position: relative;
display: inline-block;
}
.registry-status {
background: ${cssManager.bdTheme('#e8f5e9', '#1a2e1a')};
border: 1px solid ${cssManager.bdTheme('#4caf50', '#2e7d32')};
border-radius: 12px;
padding: 24px;
margin-bottom: 32px;
position: relative;
overflow: hidden;
}
.registry-status::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: ${cssManager.bdTheme('#4caf50', '#2e7d32')};
}
.registry-status h4 {
margin-top: 0;
margin-bottom: 16px;
color: ${cssManager.bdTheme('#2e7d32', '#81c784')};
font-size: 18px;
font-weight: 600;
}
.registry-item {
display: flex;
justify-content: space-between;
padding: 8px 0;
color: ${cssManager.bdTheme('#558b2f', '#aed581')};
font-family: 'Geist Mono', monospace;
font-size: 14px;
border-bottom: 1px solid ${cssManager.bdTheme('#e0f2e1', '#1b5e20')};
}
.registry-item:last-child {
border-bottom: none;
}
.registry-item.active {
color: ${cssManager.bdTheme('#2e7d32', '#4ade80')};
font-weight: 600;
}
.registry-item span:last-child {
font-weight: 600;
}
`}
</style>
<div class="page-wrapper">
<div class="showcase-content">
<h1>Z-Index Hierarchy Showcase</h1>
<p class="intro">
This page demonstrates the z-index management system that ensures proper stacking order for all overlay components.
Test the different scenarios to see how overlays interact with each other.
</p>
<div class="warning-box">
<strong>⚠️ Important:</strong> The z-index values are managed centrally in <code>00zindex.ts</code>.
Never use arbitrary z-index values in components - always import and use the predefined layers.
<div class="showcase-container">
<div class="showcase-header">
<h1 class="showcase-title">Z-Index Management</h1>
<p class="showcase-subtitle">
A comprehensive system for managing overlay stacking order across all components.
Test different scenarios to see how the dynamic z-index registry ensures proper layering.
</p>
</div>
<div class="hierarchy-visual">
<h3>Z-Index Layer Stack (Top to Bottom)</h3>
<div class="layer-stack">
<div class="layer base">
<span class="layer-name">Base Content</span>
<span class="layer-value">z-index: auto</span>
<div class="warning-box">
<div>
<strong>Important:</strong> The z-index values are managed centrally in <code>00zindex.ts</code>.
Never use arbitrary z-index values in components - always import and use the z-index registry.
</div>
</div>
<!-- Registry Status Section -->
<div class="showcase-section">
<div class="section-header">
<div class="section-icon registry">📊</div>
<div>
<h2 class="section-title">Live Registry Status</h2>
</div>
<div class="layer fixed">
<span class="layer-name">Fixed Navigation</span>
<span class="layer-value">z-index: 10-250</span>
</div>
<div class="registry-status" id="registryStatus">
<h4>Z-Index Registry</h4>
<div class="registry-item">
<span>Active Elements:</span>
<span id="activeCount">0</span>
</div>
<div class="layer dropdown">
<span class="layer-name">Dropdown Overlays</span>
<span class="layer-value">z-index: 1999-2000</span>
<div class="registry-item">
<span>Current Z-Index:</span>
<span id="currentZIndex">1000</span>
</div>
<div class="layer modal">
<span class="layer-name">Modal Dialogs</span>
<span class="layer-value">z-index: 2999-3000</span>
</div>
</div>
<script>
// Update registry status periodically
setInterval(() => {
const registryDiv = document.getElementById('registryStatus');
if (registryDiv && window.zIndexRegistry) {
const activeCount = document.getElementById('activeCount');
const currentZIndex = document.getElementById('currentZIndex');
if (activeCount) activeCount.textContent = window.zIndexRegistry.getActiveCount();
if (currentZIndex) currentZIndex.textContent = window.zIndexRegistry.getCurrentZIndex();
// Update active state
const items = registryDiv.querySelectorAll('.registry-item');
const count = window.zIndexRegistry.getActiveCount();
if (count > 0) {
items[0].classList.add('active');
} else {
items[0].classList.remove('active');
}
}
}, 500);
// Make registry available globally for the demo
import('../elements/00zindex.js').then(module => {
window.zIndexRegistry = module.zIndexRegistry;
});
</script>
<!-- Layer Hierarchy Section -->
<div class="showcase-section">
<div class="section-header">
<div class="section-icon layers">📚</div>
<div>
<h2 class="section-title">Layer Hierarchy</h2>
</div>
<div class="layer context">
<span class="layer-name">Context Menus & WYSIWYG</span>
<span class="layer-value">z-index: 4000-4500</span>
</div>
<div class="layer toast">
<span class="layer-name">Toast Notifications</span>
<span class="layer-value">z-index: 5000</span>
</div>
<p class="section-description">
The traditional z-index layers are still defined for reference, but the new registry system
dynamically assigns z-indexes based on creation order.
</p>
<div class="hierarchy-visual">
<h3>Legacy Z-Index Layers (Reference)</h3>
<div class="layer-stack">
<div class="layer base">
<span class="layer-name">Base Content</span>
<span class="layer-value">z-index: auto</span>
</div>
<div class="layer fixed">
<span class="layer-name">Fixed Navigation</span>
<span class="layer-value">z-index: 10-250</span>
</div>
<div class="layer dropdown">
<span class="layer-name">Dropdown Overlays</span>
<span class="layer-value">z-index: 1999-2000</span>
</div>
<div class="layer modal">
<span class="layer-name">Modal Dialogs</span>
<span class="layer-value">z-index: 2999-3000</span>
</div>
<div class="layer context">
<span class="layer-name">Context Menus & WYSIWYG</span>
<span class="layer-value">z-index: 4000-4500</span>
</div>
<div class="layer toast">
<span class="layer-name">Toast Notifications</span>
<span class="layer-value">z-index: 5000</span>
</div>
</div>
</div>
</div>
<dees-panel .title=${'1. Basic Overlay Tests'} .subtitle=${'Test individual overlay components'}>
<div class="demo-grid">
<!-- Interactive Demos Section -->
<div class="showcase-section">
<div class="section-header">
<div class="section-icon demo">🎮</div>
<div>
<h4>Dropdown Test</h4>
<h2 class="section-title">Interactive Demos</h2>
</div>
</div>
<p class="section-description">
Test the z-index registry in action with these interactive examples. Each element gets the next
available z-index when created, ensuring proper stacking order.
</p>
<dees-panel .title=${'Basic Overlay Tests'} .subtitle=${'Test individual overlay components'}>
<div class="demo-grid">
<div class="demo-card">
<h4>Dropdown Test</h4>
<dees-input-dropdown
.label=${'Select Option'}
.options=${[
@ -224,10 +453,10 @@ export const showcasePage = () => html`
}
}}
></dees-input-dropdown>
</div>
</div>
<div>
<h4>Context Menu Test</h4>
<div class="demo-card">
<h4>Context Menu Test</h4>
<div class="test-area" @contextmenu=${(e: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(e, [
{ name: 'Show Toast', iconName: 'bell', action: async () => {
@ -240,18 +469,18 @@ export const showcasePage = () => html`
}}>
<span style="color: ${cssManager.bdTheme('#999', '#666')}">Right-click here for context menu</span>
</div>
</div>
</div>
<div>
<h4>Toast Notification</h4>
<dees-button @click=${async () => {
DeesToast.createAndShow({ message: 'I appear on top of everything!', type: 'success' });
}}>Show Toast</dees-button>
<div class="demo-card">
<h4>Toast Notification</h4>
<dees-button @click=${async () => {
DeesToast.createAndShow({ message: 'I appear on top of everything!', type: 'success' });
}}>Show Toast</dees-button>
</div>
</div>
</div>
</dees-panel>
</dees-panel>
<dees-panel .title=${'2. Modal with Dropdown'} .subtitle=${'Critical test: Dropdown inside modal should appear above modal'}>
<dees-panel .title=${'Modal with Dropdown'} .subtitle=${'Critical test: Dropdown inside modal should appear above modal'}>
<p>This tests the most common z-index conflict scenario.</p>
<dees-button @click=${async () => {
const modal = await DeesModal.createAndShow({
@ -310,11 +539,11 @@ export const showcasePage = () => html`
}}>Open Modal with Dropdown</dees-button>
</dees-panel>
<dees-panel .title=${'3. Complex Stacking Scenario'} .subtitle=${'Multiple overlays active simultaneously'}>
<dees-panel .title=${'Complex Stacking Scenario'} .subtitle=${'Multiple overlays active simultaneously'}>
<p>This creates a complex scenario with multiple overlays to test the complete hierarchy.</p>
<dees-button @click=${async () => {
// Show base modal
const modal1 = await DeesModal.createAndShow({
await DeesModal.createAndShow({
heading: 'Base Modal',
width: 'large',
content: html`
@ -342,7 +571,7 @@ export const showcasePage = () => html`
<div style="margin-top: 16px;">
<dees-button @click=${async () => {
const modal2 = await DeesModal.createAndShow({
await DeesModal.createAndShow({
heading: 'Second Modal',
width: 'small',
content: html`
@ -376,7 +605,7 @@ export const showcasePage = () => html`
}}>Start Complex Stack Test</dees-button>
</dees-panel>
<dees-panel .title=${'4. Profile Dropdown'} .subtitle=${'Testing app UI dropdowns'}>
<dees-panel .title=${'Profile Dropdown'} .subtitle=${'Testing app UI dropdowns'}>
<p>Profile dropdowns and similar UI elements use the dropdown z-index layer.</p>
<div class="profile-demo">
<dees-appui-profiledropdown
@ -384,23 +613,23 @@ export const showcasePage = () => html`
name: 'Test User',
email: 'test@example.com',
avatar: 'https://randomuser.me/api/portraits/lego/1.jpg',
status: 'online'
status: 'online' as const
}}
.menuItems=${[
{ name: 'Show Toast', iconName: 'bell', action: async () => {
{ name: 'Show Toast', iconName: 'bell', shortcut: '', action: async () => {
DeesToast.createAndShow({ message: 'Profile action triggered!', type: 'success' });
}},
{ divider: true },
{ name: 'Settings', iconName: 'settings', action: async () => {} },
{ name: 'Logout', iconName: 'logOut', action: async () => {} }
{ divider: true } as const,
{ name: 'Settings', iconName: 'settings', shortcut: '', action: async () => {} },
{ name: 'Logout', iconName: 'logOut', shortcut: '', action: async () => {} }
]}
></dees-appui-profiledropdown>
</div>
</dees-panel>
<dees-panel .title=${'5. Edge Cases'} .subtitle=${'Special scenarios and gotchas'}>
<dees-panel .title=${'Edge Cases'} .subtitle=${'Special scenarios and gotchas'}>
<div class="demo-grid">
<div>
<div class="demo-card">
<h4>Multiple Toasts</h4>
<dees-button @click=${async () => {
DeesToast.createAndShow({ message: 'First toast', type: 'info' });
@ -413,7 +642,7 @@ export const showcasePage = () => html`
}}>Show Multiple Toasts</dees-button>
</div>
<div>
<div class="demo-card">
<h4>Fullscreen Modal</h4>
<dees-button @click=${async () => {
await DeesModal.createAndShow({
@ -441,24 +670,41 @@ export const showcasePage = () => html`
</div>
</div>
</dees-panel>
</div>
<dees-panel .title=${'Usage Guidelines'}>
<!-- Guidelines Section -->
<div class="showcase-section">
<div class="section-header">
<div class="section-icon guidelines">📖</div>
<div>
<h2 class="section-title">Usage Guidelines</h2>
</div>
</div>
<dees-panel>
<h4>Best Practices:</h4>
<ul>
<li>Always use the predefined z-index values from <code>00zindex.ts</code></li>
<li>Always use the z-index registry from <code>00zindex.ts</code></li>
<li>Never use arbitrary z-index values like <code>z-index: 9999</code></li>
<li>When creating new overlay components, choose the appropriate layer</li>
<li>Get z-index from registry when showing elements: <code>zIndexRegistry.getNextZIndex()</code></li>
<li>Register elements to track them: <code>zIndexRegistry.register(element, zIndex)</code></li>
<li>Unregister on cleanup: <code>zIndexRegistry.unregister(element)</code></li>
<li>Elements created later automatically appear on top</li>
<li>Test overlay interactions, especially dropdowns in modals</li>
<li>Remember that toasts should always be on top</li>
</ul>
<h4>Import Example:</h4>
<pre style="background: ${cssManager.bdTheme('#f5f5f5', '#2a2a2a')}; padding: 16px; border-radius: 6px; overflow-x: auto;">
<code>import { zIndexLayers } from './00zindex.js';
<code>import { zIndexRegistry } from './00zindex.js';
// In your component styles:
z-index: \${zIndexLayers.overlay.modal};</code></pre>
// In your component:
const myZIndex = zIndexRegistry.getNextZIndex();
element.style.zIndex = myZIndex.toString();
zIndexRegistry.register(element, myZIndex);
// On cleanup:
zIndexRegistry.unregister(element);</code></pre>
</dees-panel>
</div>
</div>
</div>
`;