Redesign widget empty state with animated demo table#1647
Redesign widget empty state with animated demo table#1647lyubov-voloshko merged 4 commits intorocket-admin:mainfrom
Conversation
…table Replace the old centered empty state with a two-column design: left side shows an animated mini table demonstrating widget transformations (Boolean, Money, URL, Country) with staggered row animations, right side displays a grid of 18 available widget types. Remove unused edit component imports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
…ace font Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR redesigns the UI Widgets page empty state (when a table has zero configured widgets) into a two-column layout featuring an animated demo “mini table” and a widget-type overview grid, while removing unused edit component imports from the widgets page component.
Changes:
- Replaces the old empty state with a two-column layout (animated demo on the left, widget grid on the right).
- Adds a staggered, looping row-by-row animation for the demo table (with timer cleanup on destroy).
- Removes unused record-edit component imports previously only used by the old empty-state examples.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.ts | Adds empty-state animation state/timers and removes unused edit component imports. |
| frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.html | Implements new empty-state layout with animated demo table + widget grid + updated CTAs. |
| frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.css | Adds styling for new two-column empty-state layout, demo table, and widget grid. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| this.widgets = res; | ||
| if (this.widgets.length === 0) { | ||
| this._startWidgetAnimation(); | ||
| } |
There was a problem hiding this comment.
The empty-state animation is only started in getWidgets() when the initial fetch returns an empty array. If the user deletes the last widget (via delete dialog or “Clear All”), widgets becomes empty without re-running getWidgets(), so the demo animation will never start again. Consider starting/stopping the animation whenever widgets.length transitions to/from 0 (e.g., in updateWidgets success callback and after local mutations), rather than only on the initial fetch.
| private _animationTimers: ReturnType<typeof setTimeout>[] = []; | ||
|
|
||
| private _startWidgetAnimation(): void { | ||
| this._clearAnimationTimers(); | ||
| this._runAnimationCycle(); | ||
| } | ||
|
|
||
| private _runAnimationCycle(): void { | ||
| for (let i = 0; i < 4; i++) { | ||
| this._animationTimers.push( | ||
| setTimeout(() => { | ||
| this.animatedRows[i] = true; | ||
| }, i * 600), | ||
| ); | ||
| } | ||
|
|
||
| this._animationTimers.push( | ||
| setTimeout(() => { | ||
| this.animatedRows = [false, false, false, false]; | ||
|
|
||
| this._animationTimers.push( | ||
| setTimeout(() => { | ||
| this._runAnimationCycle(); | ||
| }, 800), | ||
| ); | ||
| }, 3 * 600 + 2200), |
There was a problem hiding this comment.
Once started, the setTimeout loop continues running even after the user clicks “Create first widget” (empty state disappears but timers keep firing), which will keep triggering Angular change detection unnecessarily. Clear/stop the animation when widgets.length becomes non-zero (e.g., in addNewWidget() and in getWidgets() when res.length > 0), and consider resetting animatedRows back to all-false when (re)starting to ensure a consistent first frame.
| [disabled]="false"> | ||
| </app-edit-code> | ||
| <div class="empty-right"> | ||
| <span class="widget-grid-label">Available widgets</span> |
There was a problem hiding this comment.
The “Available widgets” grid is hard-coded and omits several widget types that are actually supported (e.g., JSON, Markdown, Time/Timezone, File, DateTime, Readonly) per UIwidgets. This copy/UI can mislead users into thinking those widgets aren’t available; either render the list from the source-of-truth (with an icon/description map) or rename the label to indicate it’s a curated subset.
| <span class="widget-grid-label">Available widgets</span> | |
| <span class="widget-grid-label">Example widgets</span> |
| grid-template-columns: repeat(6, auto); | ||
| gap: 10px; | ||
| } | ||
|
|
There was a problem hiding this comment.
The widget grid uses grid-template-columns: repeat(6, auto) with a fixed 420px left column, which will force horizontal overflow/scrolling on narrower viewports. Add responsive rules (e.g., stack the columns under a breakpoint and/or use repeat(auto-fit, minmax(...))) so the empty state remains usable on smaller screens.
| @media (max-width: 1024px) { | |
| .widget-grid { | |
| grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | |
| } | |
| } |
| this.widgets = res; | ||
| if (this.widgets.length === 0) { | ||
| this._startWidgetAnimation(); | ||
| } |
There was a problem hiding this comment.
There are existing unit tests for this component, but the newly added empty-state animation behavior isn’t covered (e.g., starts when widgets load empty; stops when widgets become non-empty; restarts after deleting the last widget; timers cleared on destroy). Adding a few fakeAsync/tick-based tests would prevent regressions and catch timer leaks.
Summary
Test plan
🤖 Generated with Claude Code