feat(dees-tile): unify tile badge styling and markup; replace component-specific badge classes with shared tile-badge classes and update related imports/tests

This commit is contained in:
2026-01-27 11:36:24 +00:00
parent 825a74b810
commit bfda6b75e7
17 changed files with 71 additions and 115 deletions
+9
View File
@@ -1,5 +1,14 @@
# Changelog # Changelog
## 2026-01-27 - 3.40.0 - feat(dees-tile)
unify tile badge styling and markup; replace component-specific badge classes with shared tile-badge classes and update related imports/tests
- Add shared badge styles: .tile-badge-corner, .tile-badge-topright, .tile-badge and layout rules in dees-tile-shared/styles.ts
- Update tile components (audio, video, image, folder, note, pdf) to use new badge markup and remove duplicated badge CSS
- Shift badge positioning when a tile label is present (.tile-container:has(.tile-label))
- Remove older per-component badge rules (duration-badge, item-count-badge, dimension-badge, note-language/note-line-indicator, preview-page-indicator) and replace with unified classes
- Update tests to import dees-contextmenu and dees-dashboardgrid from new 00group-overlay / 00group-layout paths to reflect folder reorganization
## 2026-01-27 - 3.39.1 - fix(dees-tile-note) ## 2026-01-27 - 3.39.1 - fix(dees-tile-note)
use horizontal pointer position to scroll note body by computing percentage from clientX and element width instead of clientY and height use horizontal pointer position to scroll note body by computing percentage from clientX and element width instead of clientY and height
+2 -2
View File
@@ -1,6 +1,6 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
import { demoFunc } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.demo.js'; import { demoFunc } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.demo.js';
tap.test('should render context menu demo', async () => { tap.test('should render context menu demo', async () => {
// Create demo container // Create demo container
@@ -1,5 +1,5 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
tap.test('should close all parent menus when clicking action in nested submenu', async () => { tap.test('should close all parent menus when clicking action in nested submenu', async () => {
let actionCalled = false; let actionCalled = false;
+1 -1
View File
@@ -1,5 +1,5 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
import { DeesElement, customElement, html } from '@design.estate/dees-element'; import { DeesElement, customElement, html } from '@design.estate/dees-element';
// Create a test element with shadow DOM // Create a test element with shadow DOM
+1 -1
View File
@@ -1,5 +1,5 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
tap.test('should show context menu with nested submenu', async () => { tap.test('should show context menu with nested submenu', async () => {
// Create a test element with context menu items // Create a test element with context menu items
+2 -2
View File
@@ -3,8 +3,8 @@ import { tap, expect } from '@git.zone/tstest/tapbundle';
import { import {
resolveWidgetPlacement, resolveWidgetPlacement,
collectCollisions, collectCollisions,
} from '../ts_web/elements/dees-dashboardgrid/layout.ts'; } from '../ts_web/elements/00group-layout/dees-dashboardgrid/layout.ts';
import type { DashboardWidget } from '../ts_web/elements/dees-dashboardgrid/types.ts'; import type { DashboardWidget } from '../ts_web/elements/00group-layout/dees-dashboardgrid/types.ts';
tap.test('dashboardgrid does not overlap widgets after swap attempt', async () => { tap.test('dashboardgrid does not overlap widgets after swap attempt', async () => {
const widgets: DashboardWidget[] = [ const widgets: DashboardWidget[] = [
@@ -1,6 +1,6 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesInputWysiwyg } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.js'; import { DeesInputWysiwyg } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.js';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
tap.test('should change block type via context menu', async () => { tap.test('should change block type via context menu', async () => {
// Create WYSIWYG editor with a paragraph // Create WYSIWYG editor with a paragraph
+1 -1
View File
@@ -1,6 +1,6 @@
import { expect, tap } from '@git.zone/tstest/tapbundle'; import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DeesInputWysiwyg } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.js'; import { DeesInputWysiwyg } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.js';
import { DeesContextmenu } from '../ts_web/elements/dees-contextmenu/dees-contextmenu.js'; import { DeesContextmenu } from '../ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js';
tap.test('should show context menu on WYSIWYG blocks', async () => { tap.test('should show context menu on WYSIWYG blocks', async () => {
// Create WYSIWYG editor // Create WYSIWYG editor
+1 -1
View File
@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@design.estate/dees-catalog', name: '@design.estate/dees-catalog',
version: '3.39.1', version: '3.40.0',
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.'
} }
@@ -84,20 +84,6 @@ export class DeesTileAudio extends DeesTileBase {
display: block; display: block;
} }
.duration-badge {
position: absolute;
bottom: 8px;
right: 8px;
padding: 3px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 10px;
font-weight: 600;
font-variant-numeric: tabular-nums;
backdrop-filter: blur(8px);
z-index: 10;
}
.play-overlay { .play-overlay {
position: absolute; position: absolute;
@@ -177,7 +163,7 @@ export class DeesTileAudio extends DeesTileBase {
</div> </div>
${this.duration > 0 ? html` ${this.duration > 0 ? html`
<div class="duration-badge">${this.formatTime(this.duration)}</div> <div class="tile-badge-corner">${this.formatTime(this.duration)}</div>
` : ''} ` : ''}
<div class="play-overlay"> <div class="play-overlay">
@@ -109,19 +109,6 @@ export class DeesTileFolder extends DeesTileBase {
background: ${cssManager.bdTheme('hsl(215 15% 96%)', 'hsl(215 20% 16%)')}; background: ${cssManager.bdTheme('hsl(215 15% 96%)', 'hsl(215 20% 16%)')};
} }
.item-count-badge {
position: absolute;
bottom: 8px;
right: 8px;
padding: 3px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 10px;
font-weight: 600;
backdrop-filter: blur(8px);
z-index: 10;
}
`, `,
] as any; ] as any;
@@ -158,7 +145,7 @@ export class DeesTileFolder extends DeesTileBase {
</div> </div>
</div> </div>
<div class="item-count-badge"> <div class="tile-badge-corner">
${this.items.length} item${this.items.length !== 1 ? 's' : ''} ${this.items.length} item${this.items.length !== 1 ? 's' : ''}
</div> </div>
@@ -55,24 +55,12 @@ export class DeesTileImage extends DeesTileBase {
opacity: 0; opacity: 0;
} }
.dimension-badge { .tile-badge-topright.dimension-badge {
position: absolute;
top: 8px;
right: 8px;
padding: 3px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 10px;
font-weight: 600;
backdrop-filter: blur(8px);
z-index: 15;
pointer-events: none;
opacity: 0; opacity: 0;
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
} }
.tile-container.clickable:hover .dimension-badge { .tile-container.clickable:hover .tile-badge-topright.dimension-badge {
opacity: 1; opacity: 1;
} }
`, `,
@@ -110,7 +98,7 @@ export class DeesTileImage extends DeesTileBase {
</div> </div>
${this.imageWidth > 0 && this.imageHeight > 0 ? html` ${this.imageWidth > 0 && this.imageHeight > 0 ? html`
<div class="dimension-badge"> <div class="tile-badge-topright dimension-badge">
${this.imageWidth} × ${this.imageHeight} ${this.imageWidth} × ${this.imageHeight}
</div> </div>
` : ''} ` : ''}
@@ -81,16 +81,10 @@ export class DeesTileNote extends DeesTileBase {
pointer-events: none; pointer-events: none;
} }
.note-language { .tile-badge-topright.note-language {
position: absolute;
top: 8px;
right: 8px;
padding: 2px 6px;
background: ${cssManager.bdTheme('hsl(215 20% 92%)', 'hsl(215 20% 88%)')}; background: ${cssManager.bdTheme('hsl(215 20% 92%)', 'hsl(215 20% 88%)')};
color: ${cssManager.bdTheme('hsl(215 16% 50%)', 'hsl(215 16% 40%)')}; color: ${cssManager.bdTheme('hsl(215 16% 50%)', 'hsl(215 16% 40%)')};
border-radius: 3px;
font-size: 9px; font-size: 9px;
font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
z-index: 5; z-index: 5;
} }
@@ -116,21 +110,6 @@ export class DeesTileNote extends DeesTileBase {
padding-right: 6px; padding-right: 6px;
} }
.note-line-indicator {
position: absolute;
bottom: 8px;
right: 8px;
padding: 3px 8px;
background: rgba(0, 0, 0, 0.6);
color: white;
border-radius: 4px;
font-size: 9px;
font-weight: 600;
font-variant-numeric: tabular-nums;
backdrop-filter: blur(8px);
z-index: 10;
pointer-events: none;
}
`, `,
] as any; ] as any;
@@ -154,7 +133,7 @@ export class DeesTileNote extends DeesTileBase {
return html` return html`
<div class="note-content"> <div class="note-content">
${this.language ? html` ${this.language ? html`
<div class="note-language">${this.language}</div> <div class="tile-badge-topright note-language">${this.language}</div>
` : ''} ` : ''}
${this.title ? html` ${this.title ? html`
@@ -169,7 +148,7 @@ export class DeesTileNote extends DeesTileBase {
</div> </div>
${this.isHovering && lines.length > 12 ? html` ${this.isHovering && lines.length > 12 ? html`
<div class="note-line-indicator"> <div class="tile-badge-corner">
Line ${this.getVisibleLineRange(lines.length)} Line ${this.getVisibleLineRange(lines.length)}
</div> </div>
` : ''} ` : ''}
@@ -55,15 +55,14 @@ export class DeesTilePdf extends DeesTileBase {
</div> </div>
${this.pageCount > 1 && this.isHovering ? html` ${this.pageCount > 1 && this.isHovering ? html`
<div class="preview-page-indicator"> <div class="tile-badge">
Page ${this.currentPreviewPage} of ${this.pageCount} Page ${this.currentPreviewPage} of ${this.pageCount}
</div> </div>
` : ''} ` : ''}
${this.pageCount > 0 && !this.isHovering ? html` ${this.pageCount > 0 && !this.isHovering ? html`
<div class="tile-info"> <div class="tile-badge-corner">
<dees-icon icon="lucide:FileText"></dees-icon> ${this.pageCount} page${this.pageCount > 1 ? 's' : ''}
<span class="tile-info-text">${this.pageCount} page${this.pageCount > 1 ? 's' : ''}</span>
</div> </div>
` : ''} ` : ''}
@@ -35,24 +35,6 @@ export const tilePdfStyles = css`
border-radius: 4px; border-radius: 4px;
} }
.preview-page-indicator {
position: absolute;
top: 8px;
left: 8px;
right: 8px;
padding: 5px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.7)', 'hsl(0 0% 100% / 0.9)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 11px;
font-weight: 600;
text-align: center;
backdrop-filter: blur(12px);
z-index: 15;
pointer-events: none;
animation: fadeIn 0.2s ease;
}
/* Grid optimizations */ /* Grid optimizations */
:host([grid-mode]) .preview-canvas { :host([grid-mode]) .preview-canvas {
image-rendering: -webkit-optimize-contrast; image-rendering: -webkit-optimize-contrast;
@@ -117,6 +117,46 @@ export const tileBaseStyles = [
animation: fadeIn 0.2s ease; animation: fadeIn 0.2s ease;
} }
.tile-badge-corner {
position: absolute;
bottom: 8px;
right: 8px;
padding: 3px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 10px;
font-weight: 600;
font-variant-numeric: tabular-nums;
backdrop-filter: blur(8px);
z-index: 10;
pointer-events: none;
}
.tile-badge-topright {
position: absolute;
top: 8px;
right: 8px;
padding: 3px 8px;
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
border-radius: 4px;
font-size: 10px;
font-weight: 600;
backdrop-filter: blur(8px);
z-index: 15;
pointer-events: none;
}
/* Shift bottom badges up when label is present */
.tile-container:has(.tile-label) .tile-badge-corner {
bottom: 33px;
}
.tile-container:has(.tile-label) .tile-info {
bottom: 33px;
}
.tile-loading, .tile-loading,
.tile-error { .tile-error {
position: absolute; position: absolute;
@@ -54,20 +54,6 @@ export class DeesTileVideo extends DeesTileBase {
display: block; display: block;
} }
.duration-badge {
position: absolute;
bottom: 8px;
right: 8px;
padding: 3px 8px;
background: rgba(0, 0, 0, 0.7);
color: white;
border-radius: 4px;
font-size: 10px;
font-weight: 600;
font-variant-numeric: tabular-nums;
backdrop-filter: blur(8px);
z-index: 10;
}
.play-overlay { .play-overlay {
position: absolute; position: absolute;
@@ -155,7 +141,7 @@ export class DeesTileVideo extends DeesTileBase {
</div> </div>
${this.duration > 0 ? html` ${this.duration > 0 ? html`
<div class="duration-badge">${this.formatTime(this.duration)}</div> <div class="tile-badge-corner">${this.formatTime(this.duration)}</div>
` : ''} ` : ''}
${!this.isHovering ? html` ${!this.isHovering ? html`