Layout and Testing
Understanding how widgets adapt to different screen sizes and ensuring they are accessible and well-tested is crucial for building robust, production-ready widgets. This guide covers responsive design patterns, comprehensive testing strategies, and accessibility best practices.
Layout and Responsive Design
The platform's grid math (how layout maps to pixels, auto-layout) is defined in the Manual: Layout Calculation. This page covers how to use it in your widget.
Layout Props
Widgets receive layout information via props:
interface IWidgetProps {
layout?: {
w: number; // Width in grid units
h: number; // Height in grid units
x: number; // X position in grid
y: number; // Y position in grid
};
}
Layout Constraints
Defined in widget-config.json:
{
"layout": {
"minW": 5,
"maxW": 24,
"minH": 5,
"maxH": 12
}
}
React Grid Layout Integration
The Dashboard Composer (Host application) uses a responsive grid system based on viewport breakpoints. The number of grid columns changes based on the current breakpoint.
Grid Configuration:
const rgl = {
cols: {
lg: 36, // Large screens
md: 24, // Medium screens
sm: 12, // Small screens
xs: 6, // Extra small screens
},
};
Viewport Breakpoints:
const VIEWPORT_BREAKPOINTS = {
EXTRA_EXTRA_SMALL: 0,
EXTRA_SMALL: 320,
SMALL: 768,
MEDIUM: 1220,
LARGE: 1920,
};
Breakpoint Examples:
- Resolution 321px - 767px: Grid has 6 columns (xs)
- Resolution 768px - 1219px: Grid has 12 columns (sm)
- Resolution 1220px - 1919px: Grid has 24 columns (md)
- Resolution 1920px+: Grid has 36 columns (lg)
Dashboard Composer Breakpoint Controls
The Dashboard Composer provides 4 predefined breakpoints for users to switch between during dashboard configuration. When switching to a breakpoint different from the current viewport, the dashboard width is set to a specific value:
- XS: 390px
- SM: 1024px
- MD: 1480px
- LG: 1921px
This allows users to preview and configure their dashboards for different screen sizes.
Responsive Widget Example
Use container queries so the layout adapts to the widget's own width (as it's resized on the dashboard), not to the browser viewport. Opt a subtree in with @container, then use @[width]: variants:
import React from 'react';
const ResponsiveKpiTracker = () => {
return (
<div className="@container h-full w-full p-3">
<div className="grid grid-cols-1 gap-2 @[400px]:grid-cols-2 @[640px]:grid-cols-3">
<div className="rounded-md bg-card p-2 text-card-foreground">Revenue</div>
<div className="rounded-md bg-card p-2 text-card-foreground">Users</div>
<div className="rounded-md bg-card p-2 text-card-foreground">Conversion</div>
</div>
</div>
);
};
export default ResponsiveKpiTracker;
You can also read the widget's grid size from the layout prop (layout.w / layout.h) when you need JS-side branching rather than CSS.
Testing and Accessibility
Component Testing
Test Scenarios:
- Testing new components
- Testing edge cases
- Fixing broken tests
- Refactoring tests
RTL Query Priority:
- Accessible: getByRole, getByLabelText, getByPlaceholderText, getByText
- Semantic: getByAltText, getByTitle
- Test ID: getByTestId (last resort)
Example Test
Widget tests render the component with mocked platform props and assert on states (loading, data, error). The full testing methodology — environment setup, query priorities, mocking httpClient / shared values, and best practices — lives in the Manual, and the widget-testing skill scaffolds specs for you.
UI-Kit Testing — setup, scenarios, RTL query priority, and per-test-type best practices.
Accessibility Testing
Reference: A11y Support
Tools:
- eslint-plugin-jsx-a11y: Linting for accessibility issues
- jest-axe: Automated accessibility testing
- storybook-a11y-addon: Accessibility testing in Storybook
- @react-aria: Accessible React components
- Browser tools: axe DevTools extension, Lighthouse
Jest-Axe Example
import React from "react";
import { render } from "@testing-library/react";
import { axe, toHaveNoViolations } from "jest-axe";
import KpiTracker from "./widget";
expect.extend(toHaveNoViolations);
describe("KpiTracker Accessibility", () => {
it("should have no accessibility violations", async () => {
const { container } = render(<KpiTracker {...defaultProps} />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
Accessible Component Example
import React from 'react';
const AccessibleKpiCard: React.FC<{ label: string; value: string }> = ({ label, value }) => {
return (
<div role="region" aria-labelledby="kpi-label" className="rounded-md bg-card p-4">
<div id="kpi-label" className="text-sm text-muted-foreground">
{label}
</div>
<div aria-live="polite" aria-atomic="true" className="text-2xl font-bold text-foreground">
{value}
</div>
</div>
);
};
export default AccessibleKpiCard;
Code Style
Reference: Code Style
Tools:
- wl-linters: Centralized linting configuration
- eslint: JavaScript/TypeScript linting
- stylelint: CSS linting
- prettier-eslint: Code formatting
- Husky: Pre-commit hooks
Commands:
# Lint JavaScript/TypeScript
npm run lint
# Lint styles
npm run lint:styles
# Format code
npm run format
# Run all checks
npm run lint && npm run lint:styles && npm run format