React Dashboard Layout Challenge
This challenge focuses on building a flexible and responsive dashboard layout component in React using TypeScript. A well-structured dashboard is crucial for presenting data and controls in an organized and user-friendly manner. You will create a reusable component that can adapt to different content sizes and screen resolutions.
Problem Description
Your task is to create a React component named DashboardLayout that accepts an array of "widgets" as props. Each widget should be rendered within its own defined container. The layout should automatically arrange these widgets, prioritizing a grid-like structure that scales gracefully.
Key Requirements:
- Component Structure: Create a functional React component named
DashboardLayoutthat accepts awidgetsprop. - Widget Rendering: Each item in the
widgetsprop should be a React element (e.g., a<div>, another custom component) and will be rendered as a distinct "widget" within the layout. - Grid Layout: The widgets should be displayed in a responsive grid. On larger screens, aim for a 3-column layout. As the screen size decreases, the number of columns should adjust (e.g., 2 columns on medium screens, 1 column on small screens).
- Spacing: There should be consistent spacing between widgets (both horizontally and vertically).
- Responsiveness: The layout must adapt to different screen sizes. Use CSS media queries or a responsive CSS framework approach (e.g., CSS Grid's
repeat(auto-fit, minmax(...))). - TypeScript: The component and its props must be defined using TypeScript.
Expected Behavior:
- When provided with several widgets, they should be arranged in a grid.
- On a wide viewport, widgets should fill up to 3 columns.
- On a narrower viewport, widgets should stack into fewer columns or a single column.
- Each widget should have a visually distinct container (e.g., a border, background color, padding).
Edge Cases to Consider:
- No Widgets: The layout should render gracefully (i.e., render nothing or an empty container) if the
widgetsprop is an empty array ornull/undefined. - Odd Number of Widgets: The grid should still arrange widgets as neatly as possible, even with an odd number of items.
- Widget Size Variation: While this challenge doesn't explicitly require dynamic sizing within the layout, assume widgets themselves might have different intrinsic heights. The grid should handle this.
Examples
Example 1:
// Assume these are your widget components
const WidgetA = () => <div style={{ border: '1px solid blue', padding: '10px' }}>Widget A</div>;
const WidgetB = () => <div style={{ border: '1px solid green', padding: '10px' }}>Widget B</div>;
const WidgetC = () => <div style={{ border: '1px solid red', padding: '10px' }}>Widget C</div>;
const WidgetD = () => <div style={{ border: '1px solid orange', padding: '10px' }}>Widget D</div>;
// In your App component or parent
<DashboardLayout widgets={[<WidgetA />, <WidgetB />, <WidgetC />, <WidgetD />]} />
Output: (Conceptual visualization on a wide screen)
+-----------+-----------+-----------+
| Widget A | Widget B | Widget C |
+-----------+-----------+-----------+
| Widget D | | |
+-----------+-----------+-----------+
Explanation: The four widgets are arranged in a 3-column grid. Widget D starts a new row.
Example 2:
// Same widget components as above
// In your App component or parent
<DashboardLayout widgets={[<WidgetA />, <WidgetB />]} />
Output: (Conceptual visualization on a wide screen)
+-----------+-----------+
| Widget A | Widget B |
+-----------+-----------+
Explanation: Two widgets are arranged in the first two columns of the 3-column grid.
Example 3: (Small Screen Behavior)
If the viewport is narrow, the same input from Example 1:
// Assume these are your widget components
const WidgetA = () => <div style={{ border: '1px solid blue', padding: '10px' }}>Widget A</div>;
const WidgetB = () => <div style={{ border: '1px solid green', padding: '10px' }}>Widget B</div>;
const WidgetC = () => <div style={{ border: '1px solid red', padding: '10px' }}>Widget C</div>;
const WidgetD = () => <div style={{ border: '1px solid orange', padding: '10px' }}>Widget D</div>;
// In your App component or parent
<DashboardLayout widgets={[<WidgetA />, <WidgetB />, <WidgetC />, <WidgetD />]} />
Output: (Conceptual visualization on a small screen)
+-----------+
| Widget A |
+-----------+
| Widget B |
+-----------+
| Widget C |
+-----------+
| Widget D |
+-----------+
Explanation: On a small screen, the layout collapses to a single column, with each widget stacking vertically.
Constraints
- The
widgetsprop will be an array of React elements (React.ReactNode[]) ornull/undefined. - The number of widgets will not exceed 50.
- The layout should be implemented using CSS Grid for efficient arrangement.
- Avoid using external CSS framework libraries like Bootstrap or Material UI for the grid layout itself; implement the core grid logic yourself using standard CSS.
Notes
- Consider how you will define the grid columns and rows using CSS Grid properties like
grid-template-columnsandgap. - Think about how to apply different styles based on screen sizes.
- The actual content of the widgets is not your concern; focus on the layout container and arrangement.
- You'll need to define the
DashboardLayoutcomponent and its props interface using TypeScript.