| name | panel-visual-badges |
| description | Create visually rich, robust TypeScript UI components with panel architecture, combining enhanced features like retry logic, state persistence, and dynamic styling with a systematic workflow for visual enhancements. |
Robust UI Panel Components
Build visually rich, robust TypeScript UI components using a panel architecture pattern. This skill combines enhanced panel features (retry logic, state persistence) with a systematic workflow for adding visual enhancements (badges, thumbnails, dynamic styling).
Architecture Overview
Core Panel Features
- Retry Logic: Automatically retries failed data fetches with exponential backoff.
- State Persistence: Saves panel state (expanded/collapsed, size) to localStorage.
- Detailed Error Handling: Provides granular error messages and recovery options.
- Visual Enhancements: Systematic approach for adding badges, thumbnails, and dynamic styling.
Panel (base class)
├── element: HTMLElement (outer container, .panel)
│ ├── header: HTMLElement (.panel-header)
│ │ ├── headerLeft (.panel-header-left)
│ │ │ ├── title (.panel-title)
│ │ │ └── newBadge (.panel-new-badge) [optional]
│ │ ├── statusBadge (.panel-data-badge) [optional]
│ │ └── countEl (.panel-count) [optional]
│ ├── content: HTMLElement (.panel-content)
│ └── resizeHandle (.panel-resize-handle)
Implementation Workflow
1. Define Constants and Configuration
const PANEL_DEFAULTS = {
maxRetries: 3,
initialRetryDelay: 1000,
};
const SOURCE_COLORS: { [key: string]: string } = {
'Category A': '#FF6B6B',
'Category B': '#4ECDC4',
'default': '#95A5A6'
};
const THUMBNAIL_SIZE = 48;
2. Base Panel Class with Enhanced Features
export class Panel {
protected element: HTMLElement;
protected content: HTMLElement;
protected panelId: string;
private retryAttempts = 0;
private retryDelay = PANEL_DEFAULTS.initialRetryDelay;
constructor(options: PanelOptions) {
this.loadState();
}
protected async fetchWithRetry(url: string):<any> {
while (this.retryAttempts < PANEL_DEFAULTS.maxRetries) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
this.++;
(. >= .) {
();
}
( (resolve, .));
. *= ;
}
}
}
(): {
.(, .({
: !...(),
: ...,
: ...
}));
}
(): {
savedState = .();
(savedState) {
{ isExpanded, width, height } = .(savedState);
(!isExpanded) ...();
(width) ... = width;
(height) ... = height;
}
}
(: ): {
[source] || [];
}
(?: ): {
imageUrl || ;
}
}
3. Creating Enhanced Components
export class NewsPanel extends Panel {
private refreshTimer: ReturnType<typeof setInterval> | null = null;
constructor() {
super({ id: 'news', title: 'News Feed', showCount: true });
this.fetchData();
this.refreshTimer = setInterval(() => this.fetchData(), 60_000);
}
private async fetchData(): Promise<void> {
try {
const newsItems = await this.fetchWithRetry('/api/news');
this.render(newsItems);
this.setCount(newsItems.length);
this.saveState();
} catch (err) {
this.showError(, {
. = ;
. = .;
.();
});
}
}
(: []): {
html = items.( ).();
.();
}
(): {
(.) (.);
.();
}
}
4. Corresponding CSS
.panel {
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.news-item {
display: flex;
gap: 16px;
padding: 12px;
border-bottom: 1px solid #eee;
}
.news-thumbnail {
width: 48px;
height: 48px;
border-radius: 4px;
object-fit: cover;
}
.news-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
color: white;
margin-right: 8px;
}
Key Patterns
- Panel Architecture: Base class handles core functionality (retry logic, state management)
- Visual Enhancements: Systematic workflow for adding badges, thumbnails, and dynamic styling
- Separation of Concerns:
- TypeScript for logic and data-driven styles
- CSS for structural and static styling
- Error Handling: Built-in retry logic with user-friendly error displays
- State Management: Automatic persistence of UI state
Best Practices
- Constants First: Define colors, sizes, and configuration at the top
- Helper Methods: Create focused methods for visual transformations
- Template Literals: Build HTML with clear conditional rendering
- CSS Coordination: Update stylesheets for every new visual element
- Testing: Verify with edge cases (missing data, network errors)