feat(dees-statsgrid): add multiPercentage tile type to stats grid

This commit is contained in:
2026-01-06 00:45:10 +00:00
parent e71efd409b
commit c7bff04ae5
5 changed files with 128 additions and 14 deletions

View File

@@ -1,5 +1,14 @@
# Changelog
## 2026-01-06 - 3.33.0 - feat(dees-statsgrid)
add multiPercentage tile type to stats grid
- Add new 'multiPercentage' type to IStatsTile (percentages: [{label, value, color?}])
- Implement renderMultiPercentage() to render up to 3 percentage items with label, value and colored progress bars
- Add CSS styles for multi-percentage layout, bars, labels and values
- Update demo to replace 'Error Rate' tile with a 'Resource Usage' multiPercentage example (CPU, Memory, Disk)
- Change is additive and backward-compatible with existing tile types
## 2026-01-04 - 3.32.0 - feat(demo)
add demoGroup metadata to components and update related dependencies

View File

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@design.estate/dees-catalog',
version: '3.32.0',
version: '3.33.0',
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
}

View File

@@ -64,14 +64,16 @@ class DemoDashboardView extends DeesElement {
color: '#8b5cf6'
},
{
id: 'errors',
title: 'Error Rate',
value: 0.12,
unit: '%',
type: 'number',
icon: 'lucide:alertTriangle',
description: 'Last 24 hours',
color: '#f59e0b'
id: 'resources',
title: 'Resource Usage',
value: '',
type: 'multiPercentage',
icon: 'lucide:server',
percentages: [
{ label: 'CPU', value: 67, color: '#3b82f6' },
{ label: 'Memory', value: 84, color: '#8b5cf6' },
{ label: 'Disk', value: 45, color: '#10b981' }
]
},
{
id: 'requests',

View File

@@ -29,23 +29,30 @@ export interface IStatsTile {
title: string;
value: number | string;
unit?: string;
type: 'number' | 'gauge' | 'percentage' | 'trend' | 'text';
type: 'number' | 'gauge' | 'percentage' | 'trend' | 'text' | 'multiPercentage';
// For gauge type
gaugeOptions?: {
min: number;
max: number;
thresholds?: Array<{value: number; color: string}>;
};
// For trend type
trendData?: number[];
// For multiPercentage type
percentages?: Array<{
label: string;
value: number;
color?: string;
}>;
// Visual customization
color?: string;
icon?: string;
description?: string;
// Tile-specific actions
actions?: plugins.tsclass.website.IMenuItem[];
}
@@ -273,6 +280,9 @@ export class DeesStatsGrid extends DeesElement {
.percentage-wrapper {
width: 100%;
position: relative;
display: flex;
flex-direction: column;
flex: 1;
}
.percentage-value {
@@ -290,6 +300,7 @@ export class DeesStatsGrid extends DeesElement {
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
border-radius: 3px;
overflow: hidden;
margin-top: auto;
}
.percentage-fill {
@@ -299,6 +310,62 @@ export class DeesStatsGrid extends DeesElement {
border-radius: 3px;
}
/* Multi Percentage Styles */
.multi-percentage-wrapper {
width: 100%;
display: flex;
flex-direction: column;
flex: 1;
}
.multi-percentage-items {
display: flex;
flex-direction: column;
gap: 12px;
margin-top: auto;
}
.multi-percentage-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.multi-percentage-header {
display: flex;
justify-content: space-between;
align-items: baseline;
}
.multi-percentage-label {
font-size: 11px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
letter-spacing: -0.01em;
}
.multi-percentage-value {
font-size: 13px;
font-weight: 600;
color: ${cssManager.bdTheme('hsl(215.3 25% 8.8%)', 'hsl(210 40% 98%)')};
letter-spacing: -0.01em;
}
.multi-percentage-bar {
width: 100%;
height: 4px;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
border-radius: 2px;
overflow: hidden;
}
.multi-percentage-fill {
height: 100%;
background: ${cssManager.bdTheme('#333333', '#e0e0e0')};
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 2px;
}
/* Trend Styles */
.trend-container {
width: 100%;
@@ -465,6 +532,9 @@ export class DeesStatsGrid extends DeesElement {
case 'trend':
return this.renderTrend(tile);
case 'multiPercentage':
return this.renderMultiPercentage(tile);
case 'text':
return html`
<div class="text-value" style="${tile.color ? `color: ${tile.color}` : ''}">
@@ -596,6 +666,39 @@ export class DeesStatsGrid extends DeesElement {
`;
}
private renderMultiPercentage(tile: IStatsTile): TemplateResult {
if (!tile.percentages || tile.percentages.length === 0) {
return html`<div class="tile-value">${tile.value}</div>`;
}
// Limit to 3 percentages
const items = tile.percentages.slice(0, 3);
return html`
<div class="multi-percentage-wrapper">
<div class="multi-percentage-items">
${items.map(item => {
const percentage = Math.min(100, Math.max(0, item.value));
return html`
<div class="multi-percentage-item">
<div class="multi-percentage-header">
<span class="multi-percentage-label">${item.label}</span>
<span class="multi-percentage-value">${percentage}%</span>
</div>
<div class="multi-percentage-bar">
<div
class="multi-percentage-fill"
style="width: ${percentage}%; ${item.color ? `background: ${item.color}` : ''}"
></div>
</div>
</div>
`;
})}
</div>
</div>
`;
}
private async handleGridAction(action: plugins.tsclass.website.IMenuItem) {
if (action.action) {
await action.action();