Playground
An earlier release
These pages document @evanion/react-widget 0.2.0. npm install @evanion/react-widget gives you 0.3.3, documented here. Values on this page were produced by running 0.2.0 in CI at d50a1c6 and are not re-executed.
Experiment with the React Widget System. Try the live demos below or copy the examples to learn how the system works.
Interactive Demo
Try these live examples to experiment with different widget configurations:
The interactive example this release showed here runs against the current source, so it is on the same page under /next/ and not on this one.
Basic Widget System
Start with a simple widget system:
import { createWidgets } from '@evanion/react-widget';
// Define your widget components
const NewsTeaser = ({ title, publishedAt, body }) => (
<article className="news-teaser">
<h3>{title}</h3>
<time>{publishedAt.toLocaleDateString()}</time>
<p>{body}</p>
</article>
);
const UserSidebar = ({ username, avatar, messages }) => (
<div className="user-info">
<img src={avatar} alt={username} />
<span>{username}</span>
<span>{messages} messages</span>
</div>
);
// Create the widget system
const { Widgets } = createWidgets({
components: {
news: NewsTeaser,
userInfo: UserSidebar,
},
});
// Define your layout data
const items = [
{
id: 'userinfo',
type: 'userInfo',
props: {
username: 'Evanion',
avatar: 'https://evanion.com/avatar.jpg',
messages: 5,
},
},
{
id: 'news1',
type: 'news',
props: {
title: 'Breaking News',
publishedAt: new Date('2024-01-15'),
body: 'This is a sample news article...',
},
},
];
// Render your widgets
function PlaygroundExample() {
return <Widgets items={items} />;
}Custom Chrome Example
Try adding custom wrappers:
const { Widgets } = createWidgets({
components: {
news: NewsTeaser,
userInfo: UserSidebar,
},
chrome: {
wrapper: ({ children }) => (
<aside className="blog-sidebar">
<header>Latest Updates</header>
<div className="widget-container">{children}</div>
</aside>
),
item: ({ children }) => <div className="widget-item">{children}</div>,
},
});Nested Widgets
Experiment with nested widgets:
const CardWidget = ({ title, Output }) => (
<div className="card">
<h3>{title}</h3>
<div className="card-content">
<Output />
</div>
</div>
);
const TextWidget = ({ content }) => <p>{content}</p>;
const { Widgets } = createWidgets({
components: {
card: CardWidget,
text: TextWidget,
},
});
const nestedItems = [
{
id: 'card1',
type: 'card',
props: {
title: 'My Card',
},
children: [
{
id: 'text1',
type: 'text',
props: { content: 'Nested text content' },
},
],
},
];Dynamic Widgets
Create dynamic widget systems:
import { useState } from 'react';
function DynamicPlayground() {
const [widgetType, setWidgetType] = useState('news');
const [widgetData, setWidgetData] = useState({
title: 'Dynamic News',
publishedAt: new Date(),
body: 'This widget is dynamically configured!',
});
const { Widgets } = createWidgets({
components: {
news: NewsTeaser,
userInfo: UserSidebar,
},
});
const dynamicItems = [
{
id: 'dynamic1',
type: widgetType,
props: widgetData,
},
];
return (
<div>
<div className="controls">
<select
value={widgetType}
onChange={(e) => setWidgetType(e.target.value)}
>
<option value="news">News</option>
<option value="userInfo">User Info</option>
</select>
<input
type="text"
value={widgetData.title}
onChange={(e) =>
setWidgetData({ ...widgetData, title: e.target.value })
}
placeholder="Widget title"
/>
</div>
<Widgets items={dynamicItems} />
</div>
);
}Error Handling
Test error handling:
const { Widgets } = createWidgets({
components: {
news: NewsTeaser,
// Intentionally missing 'userInfo' component
},
});
const errorItems = [
{
id: 'valid1',
type: 'news',
props: {
title: 'Valid News',
publishedAt: new Date(),
body: 'This will render',
},
},
{
id: 'invalid1',
type: 'userInfo', // This type is not defined
props: {
username: 'Test User',
avatar: '/avatar.jpg',
messages: 3,
},
},
];
// Only the valid widget will render
// The invalid one will be skipped with a console warning
function ErrorHandlingExample() {
return <Widgets items={errorItems} />;
}Tips for Experimenting
- Start simple - Begin with basic widget components
- Add complexity gradually - Add chrome, then nesting, then dynamic features
- Use TypeScript - Get better IntelliSense and error checking
- Check the console - Look for warnings about unknown widget types
- Copy working examples - Use the examples from the documentation as starting points
Common Patterns to Try
Conditional Widgets
const conditionalItems = [
...(showNews
? [
{
id: 'news1',
type: 'news',
props: { title: 'News', publishedAt: new Date(), body: 'Content' },
},
]
: []),
];Dynamic Props
const dynamicItems = items.map((item) => ({
...item,
props: {
...item.props,
className: isActive ? 'active' : 'inactive',
},
}));Component Overrides
// Use different components for different contexts
<Widgets
items={items}
components={{
news: isHomePage ? FeaturedNews : RegularNews,
}}
/>Last updated on