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

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

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

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 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;

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

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

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[] = [

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 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

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

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.'
} }

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>
` : ''} ` : ''}

View File

@@ -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>
` : ''} ` : ''}

View File

@@ -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>
` : ''} ` : ''}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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`