Add dashboard widget customization

This commit is contained in:
Rafael Foster
2026-05-01 08:53:25 -03:00
parent e34ba33f9b
commit 9c5f8c9a99
18 changed files with 534 additions and 70 deletions
+168 -22
View File
@@ -172,10 +172,13 @@
.widget-wrapper {
display: flex;
flex-direction: column;
position: relative;
min-width: 0;
}
.widget-wrapper > .widget {
flex: 1;
min-height: 0;
}
@media (min-width: 768px) {
@@ -183,29 +186,46 @@
grid-template-columns: repeat(2, 1fr);
}
.widget--wide {
grid-column: 1 / -1;
}
/* Sekundäre Widgets bei 2 Spalten: 1 Spalte */
.widget--secondary {
grid-column: span 1;
.widget-size--2x1,
.widget-size--2x2,
.widget-size--3x1,
.widget-size--3x2,
.widget-size--4x1,
.widget-size--4x2 {
grid-column: span 2;
}
}
@media (min-width: 1024px) {
.dashboard__grid {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(132px, auto);
gap: var(--space-5);
}
.widget--wide {
.widget-size--2x1,
.widget-size--2x2 {
grid-column: span 2;
}
/* Sekundäre Widgets: 2 Spalten ab 3-Spalten-Grid */
.widget--secondary {
grid-column: span 2;
.widget-size--3x1,
.widget-size--3x2,
.widget-size--4x1,
.widget-size--4x2 {
grid-column: span 3;
}
.widget-size--1x1,
.widget-size--2x1,
.widget-size--3x1,
.widget-size--4x1 {
grid-row: span 1;
}
.widget-size--2x2,
.widget-size--3x2,
.widget-size--4x2 {
grid-row: span 2;
}
}
@@ -214,24 +234,25 @@
grid-template-columns: repeat(4, 1fr);
}
/* Wide-Widgets nehmen 2 von 4 Spalten ein */
.widget--wide {
.widget-size--1x1 { grid-column: span 1; }
.widget-size--2x1,
.widget-size--2x2 {
grid-column: span 2;
}
/* Im 4-Spalten-Grid: sekundäre Widgets nur 1 Spalte */
.widget--secondary {
grid-column: span 1;
.widget-size--3x1,
.widget-size--3x2 {
grid-column: span 3;
}
/* Greeting-Widget über alle 4 Spalten */
.widget-greeting {
grid-column: 1 / -1;
.widget-size--4x1,
.widget-size--4x2 {
grid-column: span 4;
}
}
/* Primäre Widgets: subtile Akzentlinie oben */
.widget-wrapper.widget--wide > .widget {
.widget-size--2x2 > .widget,
.widget-size--3x2 > .widget,
.widget-size--4x2 > .widget {
border-top: 2px solid var(--active-module-accent, var(--color-accent));
}
@@ -425,6 +446,8 @@
.widget__body {
flex: 1;
padding: var(--space-2) var(--space-4) var(--space-4);
min-height: 0;
overflow: auto;
}
.widget__empty {
@@ -1367,6 +1390,21 @@
font-weight: var(--font-weight-medium);
}
.customize-row__size {
display: flex;
align-items: center;
gap: var(--space-1);
color: var(--color-text-secondary);
font-size: var(--text-xs);
}
.customize-row__select {
min-height: 30px;
width: 86px;
padding: 0 var(--space-1);
font-size: var(--text-xs);
}
.customize-row__actions {
display: flex;
gap: var(--space-1);
@@ -2090,6 +2128,114 @@
height: 18px;
}
.dashboard-customize-toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
gap: var(--space-2);
flex-wrap: wrap;
}
.dashboard-customize-toolbar .btn {
min-height: 36px;
}
.dashboard-customize-toolbar .btn i {
width: 16px;
height: 16px;
}
.dashboard__grid--editing {
padding: var(--space-2);
border: 1px dashed color-mix(in srgb, var(--module-accent) 48%, var(--color-border));
border-radius: 8px;
background: color-mix(in srgb, var(--module-accent) 4%, transparent);
}
.widget-wrapper--editing {
padding-top: 42px;
outline: 1px solid color-mix(in srgb, var(--module-accent) 36%, var(--color-border));
outline-offset: -1px;
border-radius: 8px;
}
.widget-wrapper--editing[draggable="true"] {
cursor: grab;
}
.widget-wrapper--dragging {
opacity: 0.45;
}
.widget-wrapper--drag-over {
outline: 2px dashed var(--module-accent);
background: color-mix(in srgb, var(--module-accent) 9%, transparent);
}
.widget-edit-controls {
position: absolute;
top: 6px;
left: 6px;
right: 6px;
z-index: 4;
display: flex;
align-items: center;
gap: var(--space-2);
padding: 4px;
border: 1px solid var(--color-border);
border-radius: 8px;
background: color-mix(in srgb, var(--color-surface) 96%, transparent);
box-shadow: var(--shadow-xs);
}
.widget-edit-controls__handle,
.widget-edit-controls__hide {
width: 30px;
height: 30px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-surface);
color: var(--color-text-secondary);
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
}
.widget-edit-controls__handle {
cursor: grab;
}
.widget-edit-controls__hide {
cursor: pointer;
}
.widget-edit-controls__handle svg,
.widget-edit-controls__hide svg {
width: 15px;
height: 15px;
}
.widget-edit-controls__size {
display: flex;
align-items: center;
gap: var(--space-1);
min-width: 0;
flex: 1;
color: var(--color-text-secondary);
font-size: var(--text-xs);
}
.widget-edit-controls__select {
min-width: 76px;
height: 30px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-surface);
color: var(--color-text-primary);
font-size: var(--text-xs);
}
.dashboard-kpi-grid {
display: grid;
gap: var(--space-3);