DataPage - Details Panel
Overview
Section titled “Overview”The details panel displays detailed information about the selected row in a resizable side panel.
Enabling Details Panel
Section titled “Enabling Details Panel”Provide a detailsComponent prop to enable the details panel:
const ProductDetails = ({ item }) => ( <div className="p-4"> <h2>{item.name}</h2> <p>{item.description}</p> <div className="mt-4"> <p><strong>SKU:</strong> {item.sku}</p> <p><strong>Price:</strong> ${item.price}</p> <p><strong>Stock:</strong> {item.stock} units</p> <p><strong>Category:</strong> {item.category}</p> </div> </div>);
<DataPage title="Products" query={ProductsQuery} emptyMessage="No products" detailsComponent={ProductDetails}> {/* MenuItems and Columns */}</DataPage>Detail Component Props
Section titled “Detail Component Props”Your detail component receives:
item: The selected data itemonRefresh: Optional callback — called when a refresh should be signalled back to the page (e.g. after a mutation in the detail panel)
interface IDetailsComponentProps<TDataType> { item: TDataType; onRefresh?: () => void;}Complex Details Example
Section titled “Complex Details Example”const OrderDetails = ({ item }) => { return ( <div className="order-details p-4"> <div className="header mb-4"> <h2>Order #{item.orderNumber}</h2> <span className={`status-badge ${item.status}`}> {item.status} </span> </div>
<div className="section mb-4"> <h3>Customer Information</h3> <p><strong>Name:</strong> {item.customerName}</p> <p><strong>Email:</strong> {item.customerEmail}</p> <p><strong>Phone:</strong> {item.customerPhone}</p> </div>
<div className="section mb-4"> <h3>Order Items</h3> <table className="w-full"> <thead> <tr> <th>Item</th> <th>Quantity</th> <th>Price</th> </tr> </thead> <tbody> {item.items.map(orderItem => ( <tr key={orderItem.id}> <td>{orderItem.name}</td> <td>{orderItem.quantity}</td> <td>${orderItem.price}</td> </tr> ))} </tbody> </table> </div>
<div className="section"> <h3>Totals</h3> <p><strong>Subtotal:</strong> ${item.subtotal}</p> <p><strong>Tax:</strong> ${item.tax}</p> <p><strong>Total:</strong> ${item.total}</p> </div> </div> );};Panel Layout
Section titled “Panel Layout”Wire the details component into the page:
<DataPage title="Orders" query={OrdersQuery} emptyMessage="No orders" detailsComponent={OrderDetails}> {/* ... */}</DataPage>Interactive Details
Section titled “Interactive Details”Add interactive elements in the details panel:
const ProductDetails = ({ item }) => { const [editing, setEditing] = useState(false);
return ( <div className="p-4"> <div className="flex justify-between items-center mb-4"> <h2>{item.name}</h2> <Button label={editing ? "Save" : "Edit"} onClick={() => setEditing(!editing)} /> </div>
{editing ? ( <div> {/* Edit form */} <InputText value={item.name} onChange={...} /> </div> ) : ( <div> {/* Display view */} <p>{item.description}</p> </div> )} </div> );};Resizable Panels
Section titled “Resizable Panels”The details panel is resizable by default using Allotment. Users can drag the divider to adjust the split.
Disable Resizing
Section titled “Disable Resizing”To disable resizing, you would need to wrap the DataPage or use custom layout.
No Selection State
Section titled “No Selection State”When no row is selected, the details panel is hidden automatically.
Best Practices
Section titled “Best Practices”- Keep it focused: Display essential details, not everything
- Load additional data: Use the item ID to fetch related data if needed
- Provide actions: Include relevant actions (edit, delete, etc.) in the details panel
- Use tabs: For complex details, organize into tabs
- Show relationships: Display related items or hierarchical data
- Include metadata: Creation dates, last modified, version info
- Make it actionable: Add buttons for common operations
- Consider performance: Lazy load heavy content or images