Widget
Draggable and resizable dashboard widget container with container queries for responsive content. Supports size variants, interactive states, and performance-optimized drag/resize operations.
Example
<div class="omni-widget">
<div class="omni-widget-header">
<h3 class="omni-widget-title">Sales Overview</h3>
<div class="omni-widget-actions">
<button class="omni-button" data-type="icon" aria-label="Settings">...</button>
</div>
</div>
<div class="omni-widget-content">
Widget content...
</div>
<div class="omni-widget-footer">
Last updated: 2 hours ago
</div>
</div>
Structure
A widget consists of four main parts:
Header (Required)
Contains the widget title and optional action buttons. Includes a drag handle for repositioning.
<div class="omni-widget-header">
<h3 class="omni-widget-title">Widget Title</h3>
<div class="omni-widget-actions">
<!-- Action buttons -->
</div>
<div class="omni-widget-handle" aria-label="Drag widget"></div>
</div>
Content (Required)
Main content area with automatic scrolling when content overflows.
<div class="omni-widget-content">
<!-- Your content here -->
</div>
Footer (Optional)
Bottom section for metadata or additional actions.
<div class="omni-widget-footer">
Last updated: 2 hours ago
</div>
Resize Handle (Optional)
Bottom-right corner handle for resizing the widget.
<div class="omni-widget-resize" aria-label="Resize widget"></div>
Sizes
Use data-size to adjust widget padding and typography:
<div class="omni-widget" data-size="sm">...</div>
<div class="omni-widget">...</div> <!-- md (default) -->
<div class="omni-widget" data-size="lg">...</div>
States
Interactive States
Use data-state to indicate widget interaction states:
Dragging
Applied when the widget is being dragged. Elevates z-index and adds visual feedback.
<div class="omni-widget" data-state="dragging">...</div>
Resizing
Applied when the widget is being resized.
<div class="omni-widget" data-state="resizing">...</div>
Loading
<div class="omni-widget" data-state="loading">...</div>
Error
<div class="omni-widget" data-state="error">...</div>
Grid Helper States
Placeholder
Shows where a widget will be dropped in a grid layout.
<div class="omni-widget" data-state="placeholder">...</div>
Collision
Indicates a widget would overlap with another in the grid.
<div class="omni-widget" data-state="collision">...</div>
Dashboard Mode
Enable edit mode by adding data-dashboard-mode="editing" to a parent container. This shows drag and resize handles on hover.
<div class="dashboard-container" data-dashboard-mode="editing">
<div class="omni-widget">
<div class="omni-widget-header">
<h3 class="omni-widget-title">Widget Title</h3>
<div class="omni-widget-actions">...</div>
<div class="omni-widget-handle" aria-label="Drag widget"></div>
</div>
<div class="omni-widget-content">...</div>
<div class="omni-widget-resize" aria-label="Resize widget"></div>
</div>
</div>
Container Queries
Widgets use CSS container queries to adapt their content based on the widget's own size, not the viewport. This allows widgets to be truly responsive regardless of where they're placed.
Automatic Breakpoints
- Small (< 300px): Compact padding, smaller typography
- Medium (default): Standard layout
- Large (> 500px): Spacious padding, larger typography
/* Example: Custom container query styles */
@container widget (max-width: 300px) {
.custom-content { font-size: 0.875rem; }
}
@container widget (min-width: 500px) {
.custom-content { font-size: 1.125rem; }
}
API Reference
Data Attributes
| Attribute | Values | Default | Description |
|---|---|---|---|
data-size |
sm, md, lg | md | Widget padding and typography size |
data-state |
dragging, resizing, loading, error, placeholder, collision | — | Interactive and visual state |
data-dashboard-mode |
editing | — | Applied to parent container to enable edit mode |
draggable |
true, false | — | HTML5 drag and drop support |
CSS Custom Properties
| Property | Description |
|---|---|
--omni-widget-header-padding |
Header padding (changes with data-size) |
--omni-widget-content-padding |
Content padding (changes with data-size) |
--omni-widget-title-size |
Title font size (changes with data-size) |
--omni-widget-footer-padding |
Footer padding (changes with data-size) |
--omni-widget-footer-font-size |
Footer font size (changes with data-size) |
--omni-widget-actions-gap |
Gap between action buttons |
--omni-widget-resize-size |
Resize handle dimensions |
Classes
| Class | Description |
|---|---|
.omni-widget |
Main widget container |
.omni-widget-header |
Header section with title and actions |
.omni-widget-title |
Widget title (h3 recommended) |
.omni-widget-actions |
Container for action buttons |
.omni-widget-handle |
Drag handle (shown in edit mode) |
.omni-widget-content |
Main content area with auto-scroll |
.omni-widget-footer |
Optional footer section |
.omni-widget-resize |
Resize handle (shown in edit mode) |
JavaScript Integration
The widget component provides CSS structure and visual styling. JavaScript is required for:
- Drag and drop functionality
- Resize operations
- Grid positioning and collision detection
- State management (dragging, resizing, etc.)
- Persistence of widget positions and sizes
Accessibility
- Use semantic HTML:
<h3>for widget titles - Provide
aria-labelfor drag and resize handles - Include focus management in JavaScript implementation
- Ensure keyboard navigation for drag/drop operations
- Use appropriate ARIA attributes for dynamic state changes
- Respect
prefers-reduced-motionfor animations - Provide alternative interaction methods for users who cannot drag
- Announce state changes to screen readers (loading, error, etc.)
Performance
The widget component includes built-in performance optimizations:
backface-visibility: hiddenfor smooth transformswill-change: transformfor hardware acceleration during drag- Container queries for efficient responsive behavior
- Minimal reflows with flexbox layout
- Disabled pointer events on children during drag for better performance
will-change properties. Only apply during active drag/resize operations.
Components Used
Other OmniUI components demonstrated on this page: