fix: compact widget empty states, view transitions for reordering, widget body padding
- widget__empty: column → row layout, icon 28→20px, padding space-5 → space-3 saves ~40px vertical space per empty widget on mobile, keeps populated widgets visible above the fold - widget__body: bottom padding space-3 → space-4 for slightly more breathing room - rebuildList() now uses document.startViewTransition with prefers-reduced-motion guard; each customize-row gets a stable view-transition-name for smooth reorder animation without a JS animation library Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,5 +47,5 @@
|
||||
2. **Lack of Visual Feedback in Customization**: Reordering widgets in the customize modal (`rebuildList()`) happens instantly without transition, feeling jarring.
|
||||
|
||||
### Implementation Steps
|
||||
- [ ] **Compact Empty States (`dashboard.js`)**: Offen — `.widget__empty` hat bereits reduziertes Padding (`space-5`), aber kein echtes Row-Layout. Niedrige Priorität.
|
||||
- [ ] **Animate Widget Reordering (`dashboard.js`)**: Offen — View Transition API wäre sinnvoll, aber kein Bug. Niedrige Priorität.
|
||||
- [x] **Compact Empty States (`dashboard.css`)**: `.widget__empty` auf horizontales Row-Layout umgestellt, Icon 28→20px, Padding reduziert — spart ~40px vertikalen Platz pro leerem Widget.
|
||||
- [x] **Animate Widget Reordering (`dashboard.js`)**: `rebuildList()` nutzt nun `document.startViewTransition()` mit `prefers-reduced-motion`-Guard und `view-transition-name` je Row.
|
||||
|
||||
@@ -546,7 +546,7 @@ function openCustomizeModal(currentConfig, onSave) {
|
||||
const isFirst = i === 0;
|
||||
const isLast = i === draft.length - 1;
|
||||
return `
|
||||
<div class="customize-row" data-id="${w.id}">
|
||||
<div class="customize-row" data-id="${esc(w.id)}" style="view-transition-name: widget-row-${esc(w.id)}">
|
||||
<label class="customize-row__toggle">
|
||||
<input type="checkbox" class="customize-row__check" data-id="${w.id}"
|
||||
${w.visible ? 'checked' : ''} aria-label="${widgetLabel(w.id)}">
|
||||
@@ -584,10 +584,18 @@ function openCustomizeModal(currentConfig, onSave) {
|
||||
function rebuildList() {
|
||||
const list = panel.querySelector('#customize-list');
|
||||
if (!list) return;
|
||||
list.replaceChildren();
|
||||
list.insertAdjacentHTML('beforeend', buildRows());
|
||||
if (window.lucide) window.lucide.createIcons({ el: list });
|
||||
wireRows();
|
||||
const doRebuild = () => {
|
||||
list.replaceChildren();
|
||||
list.insertAdjacentHTML('beforeend', buildRows());
|
||||
if (window.lucide) window.lucide.createIcons({ el: list });
|
||||
wireRows();
|
||||
};
|
||||
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
if (document.startViewTransition && !reducedMotion) {
|
||||
document.startViewTransition(doRebuild);
|
||||
} else {
|
||||
doRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
function wireRows() {
|
||||
|
||||
@@ -267,25 +267,25 @@
|
||||
|
||||
.widget__body {
|
||||
flex: 1;
|
||||
padding: var(--space-2) var(--space-4) var(--space-3);
|
||||
padding: var(--space-2) var(--space-4) var(--space-4);
|
||||
}
|
||||
|
||||
.widget__empty {
|
||||
padding: var(--space-5) var(--space-4);
|
||||
text-align: center;
|
||||
padding: var(--space-3) var(--space-4);
|
||||
color: var(--color-text-tertiary);
|
||||
font-size: var(--text-sm);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.widget__empty .empty-state__icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
color: var(--color-text-tertiary);
|
||||
margin-bottom: var(--space-1);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* Widget hover lift (desktop) */
|
||||
|
||||
Reference in New Issue
Block a user