Responsive System
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Widget Responsive System
Overview
The responsive system allows widgets to have different properties (position, size, styles) for each breakpoint. This facilitates the creation of interfaces that automatically adapt to different screen sizes without the need to duplicate widgets.
Components of the responsive system
The responsive system mainly consists of:
- ResponsiveWidgetProps: Directive that provides helper methods to access responsive properties.
- ResponsiveDraggable: Directive that implements fully responsive drag functionality.
- ResponsiveWidgetService: Service for manipulating responsive widget properties.
Data Structure
A responsive widget uses a special format for its properties:
// Non-responsive widget (classic format)
{
position: { x: 100, y: 200 },
size: { width: 300, height: 150 }
}
// Responsive widget
{
position: {
base: { x: 100, y: 200 },
md: { x: 50, y: 100 },
lg: { x: 20, y: 50 }
},
size: {
base: { width: 300, height: 150 },
md: { width: 500, height: 250 },
lg: { width: 700, height: 350 }
}
}
Breakpoints
The system defines a set of standard breakpoints:
| Name | Min Width | Description |
|---|---|---|
base |
0px | Base/mobile (default) |
sm |
640px | Small screens |
md |
768px | Medium screens (tablet) |
lg |
1024px | Large screens (laptop) |
xl |
1280px | Extra large screens (desktop) |
2xl |
1536px | Extra extra large screens |
Utility Functions
Getting Value for Current Breakpoint
import { ResponsiveWidgetService } from '@widgets-editor/core';
@Component({...})
export class MyComponent {
constructor(private responsiveWidgetService: ResponsiveWidgetService) {}
getWidgetSize(widget: Widget): Size {
return this.responsiveWidgetService.getValueForBreakpoint(widget.size);
}
}
Updating Value for Specific Breakpoint
updateWidgetPosition(widget: Widget, breakpoint: BreakpointKey, x: number, y: number): Widget {
return this.responsiveWidgetService.setWidgetPropertyForBreakpoint(
widget,
'position',
{ x, y },
breakpoint
);
}
Integration with Directives
The responsive system is fully integrated with the widget directives, making it easy to work with responsive properties.
Example with ResponsiveWidgetProps
<div
libResponsiveWidgetProps
[widget]="widget"
[activeBreakpoint]="currentBreakpoint"
#widgetProps="responsiveWidgetProps"
>
<div [ngStyle]="widgetProps.getComputedStyles()">Widget content</div>
</div>
Example with ResponsiveDraggable
<div
libResponsiveDraggable
[widget]="widget"
[activeBreakpoint]="currentBreakpoint"
(widgetChanged)="onWidgetChanged($event)"
>
Draggable content
</div>
Full Example
Below is a complete example showing how to implement a responsive widget:
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
ResponsiveWidgetPropsDirective,
ResponsiveDraggableDirective,
} from '@widgets-editor/shared-ui';
import { BreakpointKey, Widget } from '@widgets-editor/core';
@Component({
selector: 'app-responsive-widget',
standalone: true,
imports: [CommonModule, ResponsiveWidgetPropsDirective, ResponsiveDraggableDirective],
template: `
<div
class="widget-container"
libResponsiveWidgetProps
[widget]="widget"
[activeBreakpoint]="activeBreakpoint"
#widgetProps="responsiveWidgetProps"
libResponsiveDraggable
[widget]="widget"
[activeBreakpoint]="activeBreakpoint"
(widgetChanged)="onWidgetChanged($event)"
>
<div class="header">
<span>{{ widget.name }}</span>
</div>
<div
class="content"
[ngStyle]="{
'font-size': widgetProps.getStyleProp('fontSize') + 'px',
color: widgetProps.getStyleProp('color'),
'background-color': widgetProps.getStyleProp('backgroundColor')
}"
>
{{ widget.content }}
</div>
</div>
`,
styles: [
`
.widget-container {
position: absolute;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
padding: 8px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
cursor: move;
}
.content {
padding: 16px;
}
`,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ResponsiveWidgetComponent {
@Input() widget!: Widget;
@Input() activeBreakpoint: BreakpointKey = 'base';
@Output() widgetUpdate = new EventEmitter<Widget>();
onWidgetChanged(updatedWidget: Widget): void {
this.widget = updatedWidget;
this.widgetUpdate.emit(updatedWidget);
}
}
Switching Between Breakpoints
To enable users to switch between breakpoints in the editor, you can use the ResponsiveToolbarComponent:
import { Component, signal } from '@angular/core';
import { BreakpointKey } from '@widgets-editor/core';
@Component({
selector: 'app-responsive-toolbar',
standalone: true,
template: `
<div class="responsive-toolbar">
<button
*ngFor="let bp of breakpoints"
[class.active]="bp === activeBreakpoint()"
(click)="setActiveBreakpoint(bp)"
>
{{ bp }}
</button>
</div>
`,
})
export class ResponsiveToolbarComponent {
private _activeBreakpoint = signal<BreakpointKey>('base');
activeBreakpoint = this._activeBreakpoint.asReadonly();
breakpoints: BreakpointKey[] = ['base', 'sm', 'md', 'lg', 'xl', '2xl'];
setActiveBreakpoint(bp: BreakpointKey): void {
this._activeBreakpoint.set(bp);
// Additional logic to update UI or notify other components
}
}
Best Practices
- Always define base properties: Every responsive property should have a base value.
- Use relative units when possible: Prefer percentage widths for horizontal dimensions.
- Test on real devices: Always test your responsive layouts on actual devices.
- Minimize overrides: Only override properties that need to change at each breakpoint.
- Choose correct breakpoints: Focus on content adaptations, not specific device sizes.