@design.estate/dees-catalog 3.45.1 → 3.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist_bundle/bundle.js +107 -172
  2. package/dist_ts_web/00_commitinfo_data.js +1 -1
  3. package/dist_ts_web/elements/00group-media/dees-tile-audio/component.d.ts +1 -0
  4. package/dist_ts_web/elements/00group-media/dees-tile-audio/component.js +12 -5
  5. package/dist_ts_web/elements/00group-media/dees-tile-folder/component.d.ts +1 -0
  6. package/dist_ts_web/elements/00group-media/dees-tile-folder/component.js +12 -5
  7. package/dist_ts_web/elements/00group-media/dees-tile-image/component.d.ts +1 -0
  8. package/dist_ts_web/elements/00group-media/dees-tile-image/component.js +14 -22
  9. package/dist_ts_web/elements/00group-media/dees-tile-note/component.d.ts +1 -0
  10. package/dist_ts_web/elements/00group-media/dees-tile-note/component.js +16 -18
  11. package/dist_ts_web/elements/00group-media/dees-tile-pdf/component.d.ts +2 -0
  12. package/dist_ts_web/elements/00group-media/dees-tile-pdf/component.js +35 -16
  13. package/dist_ts_web/elements/00group-media/dees-tile-pdf/demo.js +5 -3
  14. package/dist_ts_web/elements/00group-media/dees-tile-pdf/styles.js +3 -2
  15. package/dist_ts_web/elements/00group-media/dees-tile-shared/DeesTileBase.d.ts +2 -0
  16. package/dist_ts_web/elements/00group-media/dees-tile-shared/DeesTileBase.js +6 -4
  17. package/dist_ts_web/elements/00group-media/dees-tile-shared/styles.js +23 -102
  18. package/dist_ts_web/elements/00group-media/dees-tile-video/component.d.ts +1 -0
  19. package/dist_ts_web/elements/00group-media/dees-tile-video/component.js +12 -5
  20. package/dist_watch/bundle.js +105 -170
  21. package/dist_watch/bundle.js.map +3 -3
  22. package/package.json +3 -3
  23. package/ts_web/00_commitinfo_data.ts +1 -1
  24. package/ts_web/elements/00group-media/dees-tile-audio/component.ts +11 -4
  25. package/ts_web/elements/00group-media/dees-tile-folder/component.ts +11 -4
  26. package/ts_web/elements/00group-media/dees-tile-image/component.ts +13 -21
  27. package/ts_web/elements/00group-media/dees-tile-note/component.ts +15 -17
  28. package/ts_web/elements/00group-media/dees-tile-pdf/component.ts +28 -14
  29. package/ts_web/elements/00group-media/dees-tile-pdf/demo.ts +4 -2
  30. package/ts_web/elements/00group-media/dees-tile-pdf/styles.ts +2 -1
  31. package/ts_web/elements/00group-media/dees-tile-shared/DeesTileBase.ts +6 -3
  32. package/ts_web/elements/00group-media/dees-tile-shared/styles.ts +22 -101
  33. package/ts_web/elements/00group-media/dees-tile-video/component.ts +11 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design.estate/dees-catalog",
3
- "version": "3.45.1",
3
+ "version": "3.46.0",
4
4
  "private": false,
5
5
  "description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
6
6
  "main": "dist_ts_web/index.js",
@@ -47,9 +47,9 @@
47
47
  "@git.zone/tsbuild": "^4.3.0",
48
48
  "@git.zone/tsbundle": "^2.9.1",
49
49
  "@git.zone/tstest": "^3.3.2",
50
- "@git.zone/tswatch": "^3.2.5",
50
+ "@git.zone/tswatch": "^3.3.0",
51
51
  "@push.rocks/projectinfo": "^5.0.2",
52
- "@types/node": "^25.3.5"
52
+ "@types/node": "^25.4.0"
53
53
  },
54
54
  "files": [
55
55
  "ts/**/*",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-catalog',
6
- version: '3.45.1',
6
+ version: '3.46.0',
7
7
  description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
8
8
  }
@@ -162,10 +162,6 @@ export class DeesTileAudio extends DeesTileBase {
162
162
  ` : ''}
163
163
  </div>
164
164
 
165
- ${this.duration > 0 ? html`
166
- <div class="tile-badge-corner">${this.formatTime(this.duration)}</div>
167
- ` : ''}
168
-
169
165
  <div class="play-overlay">
170
166
  <div class="play-circle">
171
167
  <dees-icon icon="lucide:Play"></dees-icon>
@@ -181,6 +177,17 @@ export class DeesTileAudio extends DeesTileBase {
181
177
  `;
182
178
  }
183
179
 
180
+ protected renderBottomBar(): TemplateResult | string {
181
+ if (!this.label && !this.duration) return '';
182
+ return html`
183
+ <div class="tile-info-bar">
184
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
185
+ <span class="info-spacer"></span>
186
+ ${this.duration > 0 ? html`<span class="info-detail">${this.formatTime(this.duration)}</span>` : ''}
187
+ </div>
188
+ `;
189
+ }
190
+
184
191
  protected getTileClickDetail(): Record<string, unknown> {
185
192
  return {
186
193
  src: this.src,
@@ -145,10 +145,6 @@ export class DeesTileFolder extends DeesTileBase {
145
145
  </div>
146
146
  </div>
147
147
 
148
- <div class="tile-badge-corner">
149
- ${this.items.length} item${this.items.length !== 1 ? 's' : ''}
150
- </div>
151
-
152
148
  ${this.clickable ? html`
153
149
  <div class="tile-overlay">
154
150
  <dees-icon icon="lucide:FolderOpen"></dees-icon>
@@ -158,6 +154,17 @@ export class DeesTileFolder extends DeesTileBase {
158
154
  `;
159
155
  }
160
156
 
157
+ protected renderBottomBar(): TemplateResult | string {
158
+ if (!this.label && !this.items.length) return '';
159
+ return html`
160
+ <div class="tile-info-bar">
161
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
162
+ <span class="info-spacer"></span>
163
+ <span class="info-detail">${this.items.length} item${this.items.length !== 1 ? 's' : ''}</span>
164
+ </div>
165
+ `;
166
+ }
167
+
161
168
  protected getTileClickDetail(): Record<string, unknown> {
162
169
  return {
163
170
  name: this.name,
@@ -55,14 +55,6 @@ export class DeesTileImage extends DeesTileBase {
55
55
  opacity: 0;
56
56
  }
57
57
 
58
- .tile-badge-topright.dimension-badge {
59
- opacity: 0;
60
- transition: opacity 0.2s ease;
61
- }
62
-
63
- .tile-container.clickable:hover .tile-badge-topright.dimension-badge {
64
- opacity: 1;
65
- }
66
58
  `,
67
59
  ] as any;
68
60
 
@@ -97,19 +89,6 @@ export class DeesTileImage extends DeesTileBase {
97
89
  ` : ''}
98
90
  </div>
99
91
 
100
- ${this.imageWidth > 0 && this.imageHeight > 0 ? html`
101
- <div class="tile-badge-topright dimension-badge">
102
- ${this.imageWidth} × ${this.imageHeight}
103
- </div>
104
- ` : ''}
105
-
106
- ${this.imageLoaded ? html`
107
- <div class="tile-info">
108
- <dees-icon icon="lucide:Image"></dees-icon>
109
- <span class="tile-info-text">${this.imageWidth} × ${this.imageHeight}</span>
110
- </div>
111
- ` : ''}
112
-
113
92
  ${this.clickable ? html`
114
93
  <div class="tile-overlay">
115
94
  <dees-icon icon="lucide:Eye"></dees-icon>
@@ -119,6 +98,19 @@ export class DeesTileImage extends DeesTileBase {
119
98
  `;
120
99
  }
121
100
 
101
+ protected renderBottomBar(): TemplateResult | string {
102
+ if (!this.label && !(this.imageWidth > 0)) return '';
103
+ return html`
104
+ <div class="tile-info-bar">
105
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
106
+ <span class="info-spacer"></span>
107
+ ${this.imageWidth > 0 && this.imageHeight > 0
108
+ ? html`<span class="info-detail">${this.imageWidth} × ${this.imageHeight}</span>`
109
+ : ''}
110
+ </div>
111
+ `;
112
+ }
113
+
122
114
  protected getTileClickDetail(): Record<string, unknown> {
123
115
  return {
124
116
  src: this.src,
@@ -81,14 +81,6 @@ export class DeesTileNote extends DeesTileBase {
81
81
  pointer-events: none;
82
82
  }
83
83
 
84
- .tile-badge-topright.note-language {
85
- background: ${cssManager.bdTheme('hsl(215 20% 92%)', 'hsl(215 20% 88%)')};
86
- color: ${cssManager.bdTheme('hsl(215 16% 50%)', 'hsl(215 16% 40%)')};
87
- font-size: 9px;
88
- text-transform: uppercase;
89
- z-index: 5;
90
- }
91
-
92
84
  .note-lines {
93
85
  position: absolute;
94
86
  top: 0;
@@ -132,10 +124,6 @@ export class DeesTileNote extends DeesTileBase {
132
124
 
133
125
  return html`
134
126
  <div class="note-content">
135
- ${this.language ? html`
136
- <div class="tile-badge-topright note-language">${this.language}</div>
137
- ` : ''}
138
-
139
127
  ${this.title ? html`
140
128
  <div class="note-header">
141
129
  <div class="note-title">${this.title}</div>
@@ -147,11 +135,6 @@ export class DeesTileNote extends DeesTileBase {
147
135
  ${!this.isHovering ? html`<div class="note-fade"></div>` : ''}
148
136
  </div>
149
137
 
150
- ${this.isHovering && lines.length > 12 ? html`
151
- <div class="tile-badge-corner">
152
- Line ${this.getVisibleLineRange(lines.length)}
153
- </div>
154
- ` : ''}
155
138
  </div>
156
139
 
157
140
  ${this.clickable ? html`
@@ -163,6 +146,21 @@ export class DeesTileNote extends DeesTileBase {
163
146
  `;
164
147
  }
165
148
 
149
+ protected renderBottomBar(): TemplateResult | string {
150
+ const lines = this.content.split('\n');
151
+ if (!this.label && !this.language && !lines.length) return '';
152
+ return html`
153
+ <div class="tile-info-bar">
154
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
155
+ <span class="info-spacer"></span>
156
+ ${this.language ? html`<span class="info-detail">${this.language.toUpperCase()}</span>` : ''}
157
+ ${this.isHovering && lines.length > 12
158
+ ? html`<span class="info-detail">Line ${this.getVisibleLineRange(lines.length)}</span>`
159
+ : html`<span class="info-detail">${lines.length} lines</span>`}
160
+ </div>
161
+ `;
162
+ }
163
+
166
164
  protected getTileClickDetail(): Record<string, unknown> {
167
165
  return {
168
166
  title: this.title,
@@ -1,9 +1,9 @@
1
- import { property, html, customElement, type TemplateResult, type CSSResult } from '@design.estate/dees-element';
1
+ import { property, state, html, customElement, type TemplateResult, type CSSResult } from '@design.estate/dees-element';
2
2
  import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
3
3
  import { tileBaseStyles } from '../dees-tile-shared/styles.js';
4
4
  import { PdfManager } from '../dees-pdf-shared/PdfManager.js';
5
5
  import { CanvasPool, type PooledCanvas } from '../dees-pdf-shared/CanvasPool.js';
6
- import { PerformanceMonitor, throttle } from '../dees-pdf-shared/utils.js';
6
+ import { PerformanceMonitor, throttle, formatFileSize } from '../dees-pdf-shared/utils.js';
7
7
  import { tilePdfStyles } from './styles.js';
8
8
  import { demo as demoFunc } from './demo.js';
9
9
 
@@ -37,6 +37,9 @@ export class DeesTilePdf extends DeesTileBase {
37
37
  @property({ type: Boolean })
38
38
  accessor isA4Format: boolean = true;
39
39
 
40
+ @state()
41
+ accessor fileSize: number = 0;
42
+
40
43
  private renderPagesTask: Promise<void> | null = null;
41
44
  private renderPagesQueued: boolean = false;
42
45
  private pdfDocument: any;
@@ -54,18 +57,6 @@ export class DeesTilePdf extends DeesTileBase {
54
57
  ></canvas>
55
58
  </div>
56
59
 
57
- ${this.pageCount > 1 && this.isHovering ? html`
58
- <div class="tile-badge">
59
- Page ${this.currentPreviewPage} of ${this.pageCount}
60
- </div>
61
- ` : ''}
62
-
63
- ${this.pageCount > 0 && !this.isHovering ? html`
64
- <div class="tile-badge-corner">
65
- ${this.pageCount} page${this.pageCount > 1 ? 's' : ''}
66
- </div>
67
- ` : ''}
68
-
69
60
  ${this.clickable ? html`
70
61
  <div class="tile-overlay">
71
62
  <dees-icon icon="lucide:Eye"></dees-icon>
@@ -75,6 +66,22 @@ export class DeesTilePdf extends DeesTileBase {
75
66
  `;
76
67
  }
77
68
 
69
+ protected renderBottomBar(): TemplateResult | string {
70
+ if (!this.pageCount && !this.label) return '';
71
+ return html`
72
+ <div class="tile-info-bar">
73
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
74
+ <span class="info-spacer"></span>
75
+ ${this.pageCount > 1 && this.isHovering
76
+ ? html`<span class="info-detail">${this.currentPreviewPage}/${this.pageCount}</span>`
77
+ : this.pageCount > 0
78
+ ? html`<span class="info-detail">${this.pageCount} pg</span>`
79
+ : ''}
80
+ ${this.fileSize > 0 ? html`<span class="info-detail">${formatFileSize(this.fileSize)}</span>` : ''}
81
+ </div>
82
+ `;
83
+ }
84
+
78
85
  protected getTileClickDetail(): Record<string, unknown> {
79
86
  return {
80
87
  pdfUrl: this.pdfUrl,
@@ -141,6 +148,13 @@ export class DeesTilePdf extends DeesTileBase {
141
148
  this.pdfDocument = await PdfManager.loadDocument(this.pdfUrl);
142
149
  this.pageCount = this.pdfDocument.numPages;
143
150
  this.currentPreviewPage = 1;
151
+
152
+ try {
153
+ const downloadInfo = await this.pdfDocument.getDownloadInfo();
154
+ this.fileSize = downloadInfo.length;
155
+ } catch {
156
+ // File size unavailable — not critical
157
+ }
144
158
  this.loadedPdfUrl = this.pdfUrl;
145
159
 
146
160
  this.loading = false;
@@ -1,4 +1,4 @@
1
- import { html } from '@design.estate/dees-element';
1
+ import { html, cssManager } from '@design.estate/dees-element';
2
2
 
3
3
  export const demo = () => {
4
4
  const samplePdfs = [
@@ -29,7 +29,7 @@ export const demo = () => {
29
29
  <style>
30
30
  .demo-container {
31
31
  padding: 40px;
32
- background: #f5f5f5;
32
+ background: ${cssManager.bdTheme('#f5f5f5', '#0a0a0a')};
33
33
  }
34
34
 
35
35
  .demo-section {
@@ -40,6 +40,7 @@ export const demo = () => {
40
40
  margin-bottom: 20px;
41
41
  font-size: 18px;
42
42
  font-weight: 600;
43
+ color: ${cssManager.bdTheme('#09090b', '#fafafa')};
43
44
  }
44
45
 
45
46
  .preview-grid {
@@ -59,6 +60,7 @@ export const demo = () => {
59
60
  font-size: 14px;
60
61
  font-weight: 500;
61
62
  min-width: 100px;
63
+ color: ${cssManager.bdTheme('#09090b', '#fafafa')};
62
64
  }
63
65
  </style>
64
66
 
@@ -10,10 +10,11 @@ export const tilePdfStyles = css`
10
10
  justify-content: center;
11
11
  box-sizing: border-box;
12
12
  overflow: hidden;
13
+ padding: 8px 8px 28px 8px;
13
14
  }
14
15
 
15
16
  .preview-stack.non-a4 {
16
- padding: 12px;
17
+ padding: 12px 12px 28px 12px;
17
18
  }
18
19
 
19
20
  .preview-canvas {
@@ -59,9 +59,7 @@ export abstract class DeesTileBase extends DeesElement {
59
59
 
60
60
  ${!this.loading && !this.error ? this.renderTileContent() : ''}
61
61
 
62
- ${this.label ? html`
63
- <div class="tile-label">${this.label}</div>
64
- ` : ''}
62
+ ${this.renderBottomBar()}
65
63
  </div>
66
64
  `;
67
65
  }
@@ -69,6 +67,11 @@ export abstract class DeesTileBase extends DeesElement {
69
67
  /** Subclasses implement this to render their specific content */
70
68
  protected abstract renderTileContent(): TemplateResult;
71
69
 
70
+ /** Subclasses override this to render a bottom info bar with metadata */
71
+ protected renderBottomBar(): TemplateResult | string {
72
+ return '';
73
+ }
74
+
72
75
  public async connectedCallback(): Promise<void> {
73
76
  await super.connectedCallback();
74
77
  this.setupIntersectionObserver();
@@ -15,8 +15,9 @@ export const tileBaseStyles = [
15
15
  background: ${cssManager.bdTheme('hsl(0 0% 98%)', 'hsl(215 20% 14%)')};
16
16
  border-radius: 4px;
17
17
  overflow: hidden;
18
- transition: transform 0.2s ease, box-shadow 0.2s ease;
18
+ transition: box-shadow 0.2s ease;
19
19
  box-shadow: 0 1px 3px ${cssManager.bdTheme('rgba(0, 0, 0, 0.12)', 'rgba(0, 0, 0, 0.24)')};
20
+
20
21
  }
21
22
 
22
23
  .tile-container.clickable {
@@ -24,7 +25,6 @@ export const tileBaseStyles = [
24
25
  }
25
26
 
26
27
  .tile-container.clickable:hover {
27
- transform: translateY(-2px);
28
28
  box-shadow: 0 8px 24px ${cssManager.bdTheme('rgba(0, 0, 0, 0.12)', 'rgba(0, 0, 0, 0.3)')};
29
29
  }
30
30
 
@@ -71,90 +71,39 @@ export const tileBaseStyles = [
71
71
  color: white;
72
72
  }
73
73
 
74
- .tile-info {
74
+ .tile-info-bar {
75
75
  position: absolute;
76
- bottom: 8px;
77
- left: 8px;
78
- right: 8px;
79
- padding: 6px 10px;
80
- background: ${cssManager.bdTheme('hsl(0 0% 100% / 0.92)', 'hsl(215 20% 12% / 0.92)')};
81
- border-radius: 6px;
76
+ bottom: 0;
77
+ left: 0;
78
+ right: 0;
79
+ padding: 4px 8px;
80
+ background: ${cssManager.bdTheme('hsl(0 0% 100% / 0.95)', 'hsl(215 20% 12% / 0.95)')};
82
81
  display: flex;
83
82
  align-items: center;
84
83
  gap: 6px;
85
- font-size: 12px;
86
- color: ${cssManager.bdTheme('hsl(215 16% 45%)', 'hsl(215 16% 75%)')};
87
- backdrop-filter: blur(12px);
88
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
89
- z-index: 10;
90
- }
91
-
92
- .tile-info dees-icon {
93
- font-size: 13px;
94
- color: ${cssManager.bdTheme('hsl(217 91% 60%)', 'hsl(213 93% 68%)')};
95
- }
96
-
97
- .tile-info-text {
84
+ font-size: 10px;
98
85
  font-weight: 500;
99
- font-size: 11px;
100
- }
101
-
102
- .tile-badge {
103
- position: absolute;
104
- top: 8px;
105
- left: 8px;
106
- right: 8px;
107
- padding: 5px 8px;
108
- background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.7)', 'hsl(0 0% 100% / 0.9)')};
109
- color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
110
- border-radius: 4px;
111
- font-size: 11px;
112
- font-weight: 600;
113
- text-align: center;
86
+ color: ${cssManager.bdTheme('hsl(215 16% 45%)', 'hsl(215 16% 75%)')};
114
87
  backdrop-filter: blur(12px);
115
- z-index: 15;
116
- pointer-events: none;
117
- animation: fadeIn 0.2s ease;
118
- }
119
-
120
- .tile-badge-corner {
121
- position: absolute;
122
- bottom: 8px;
123
- right: 8px;
124
- padding: 3px 8px;
125
- background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
126
- color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
127
- border-radius: 4px;
128
- font-size: 10px;
129
- font-weight: 600;
88
+ z-index: 25;
130
89
  font-variant-numeric: tabular-nums;
131
- backdrop-filter: blur(8px);
132
- z-index: 10;
133
- pointer-events: none;
134
90
  }
135
91
 
136
- .tile-badge-topright {
137
- position: absolute;
138
- top: 8px;
139
- right: 8px;
140
- padding: 3px 8px;
141
- background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.6)', 'hsl(0 0% 100% / 0.85)')};
142
- color: ${cssManager.bdTheme('white', 'hsl(215 20% 12%)')};
143
- border-radius: 4px;
144
- font-size: 10px;
145
- font-weight: 600;
146
- backdrop-filter: blur(8px);
147
- z-index: 15;
148
- pointer-events: none;
92
+ .info-label {
93
+ white-space: nowrap;
94
+ overflow: hidden;
95
+ text-overflow: ellipsis;
96
+ min-width: 0;
149
97
  }
150
98
 
151
- /* Shift bottom badges up when label is present */
152
- .tile-container:has(.tile-label) .tile-badge-corner {
153
- bottom: 33px;
99
+ .info-spacer {
100
+ flex: 1;
154
101
  }
155
102
 
156
- .tile-container:has(.tile-label) .tile-info {
157
- bottom: 33px;
103
+ .info-detail {
104
+ white-space: nowrap;
105
+ opacity: 0.7;
106
+ flex-shrink: 0;
158
107
  }
159
108
 
160
109
  .tile-loading,
@@ -200,40 +149,12 @@ export const tileBaseStyles = [
200
149
  font-weight: 500;
201
150
  }
202
151
 
203
- .tile-label {
204
- position: absolute;
205
- bottom: 0;
206
- left: 0;
207
- right: 0;
208
- padding: 6px 10px;
209
- background: ${cssManager.bdTheme('hsl(0 0% 100% / 0.95)', 'hsl(215 20% 12% / 0.95)')};
210
- font-size: 11px;
211
- font-weight: 500;
212
- color: ${cssManager.bdTheme('hsl(215 16% 35%)', 'hsl(215 16% 75%)')};
213
- white-space: nowrap;
214
- overflow: hidden;
215
- text-overflow: ellipsis;
216
- z-index: 10;
217
- backdrop-filter: blur(12px);
218
- }
219
-
220
152
  @keyframes spin {
221
153
  to {
222
154
  transform: rotate(360deg);
223
155
  }
224
156
  }
225
157
 
226
- @keyframes fadeIn {
227
- from {
228
- opacity: 0;
229
- transform: translateY(-4px);
230
- }
231
- to {
232
- opacity: 1;
233
- transform: translateY(0);
234
- }
235
- }
236
-
237
158
  /* Size variants */
238
159
  :host([size="small"]) .tile-container {
239
160
  width: 150px;
@@ -140,10 +140,6 @@ export class DeesTileVideo extends DeesTileBase {
140
140
  ` : ''}
141
141
  </div>
142
142
 
143
- ${this.duration > 0 ? html`
144
- <div class="tile-badge-corner">${this.formatTime(this.duration)}</div>
145
- ` : ''}
146
-
147
143
  ${!this.isHovering ? html`
148
144
  <div class="play-overlay">
149
145
  <dees-icon icon="lucide:Play"></dees-icon>
@@ -159,6 +155,17 @@ export class DeesTileVideo extends DeesTileBase {
159
155
  `;
160
156
  }
161
157
 
158
+ protected renderBottomBar(): TemplateResult | string {
159
+ if (!this.label && !this.duration) return '';
160
+ return html`
161
+ <div class="tile-info-bar">
162
+ ${this.label ? html`<span class="info-label" title="${this.label}">${this.label}</span>` : ''}
163
+ <span class="info-spacer"></span>
164
+ ${this.duration > 0 ? html`<span class="info-detail">${this.formatTime(this.duration)}</span>` : ''}
165
+ </div>
166
+ `;
167
+ }
168
+
162
169
  protected getTileClickDetail(): Record<string, unknown> {
163
170
  return {
164
171
  src: this.src,