Team allocation
Current sprint
Members / Projects
Docs
Design system
Jane Cooper
Designer
60%
40%
Wade Warren
Engineer
85%
A specialized widget for visualizing resource allocation across multiple projects and team members.
"use client";
import { AllocationMatrixWidget, type MatrixAllocation, type MatrixMember, type MatrixProject } from '@photonix/ultimate';
const projects: MatrixProject[] = [
{ id: 'docs', name: 'Docs' },
{ id: 'system', name: 'Design system' },
];
const members: MatrixMember[] = [
{ id: 'jane', name: 'Jane Cooper', role: 'Designer' },
{ id: 'wade', name: 'Wade Warren', role: 'Engineer' },
];
const allocations: MatrixAllocation[] = [
{ memberId: 'jane', projectId: 'docs', percentage: 60 },
{ memberId: 'jane', projectId: 'system', percentage: 40 },
{ memberId: 'wade', projectId: 'system', percentage: 85 },
];
export default function AllocationMatrixWidgetBasicExample() {
return (
<AllocationMatrixWidget
title="Team allocation"
subtitle="Current sprint"
projects={projects}
members={members}
allocations={allocations}
height={320}
/>
);
}Prop | Type | Default | Description |
|---|---|---|---|
title | string | - | Header title |
subtitle | string | - | Header subtitle |
projects | MatrixProject[] | [] | Array of project items |
members | MatrixMember[] | [] | Array of member items |
allocations | MatrixAllocation[] | [] | Array of allocation items |
dateRange | AllocationMatrixDateRange | - | Optional date range used to filter or aggregate time-based allocations |
loading | boolean | false | Loading state |
headerExtraContent | React.ReactNode | - | Component to display in the header (e.g., custom filters) |
footer | React.ReactNode | - | Content to display below the matrix |
height | string | number | - | Component height |
onCellClick | ((memberId: string, projectId: string) => void) | - | Click handler for a cell |
appearance | WidgetAppearance | 'outlined' | Widget appearance |
padding | string | number | - | Widget padding (default: 16px) |
className | string | - | Custom class name |
style | React.CSSProperties | - | Custom style |
Use dateRange together with allocations that include startDate and endDate to enable native time filtering.
Selected range: 01/01/2026 - 31/03/2026 • Matching periods: Q1 2026
"use client";
import { useState } from 'react';
import { AllocationMatrixWidget, Box, DateRangePicker, type DateRange } from '@photonix/ultimate';
const PROJECTS = [
{ id: 'p1', name: 'Digital Infrastructure 2026' },
{ id: 'p2', name: 'Brand Identity Reload' },
{ id: 'p3', name: 'Mobile App V2' },
];
const MEMBERS = [
{ id: 'm1', name: 'Sarah Connor', role: 'Frontend Lead' },
{ id: 'm2', name: 'John Reese', role: 'Backend Engineer' },
{ id: 'm3', name: 'Ellen Ripley', role: 'Designer' },
];
const PERIODS = [
{ label: 'Q1 2026', start: new Date(2026, 0, 1), end: new Date(2026, 2, 31), allocations: [
{ projectId: 'p1', memberId: 'm1', percentage: 40 }, { projectId: 'p2', memberId: 'm1', percentage: 60 }, { projectId: 'p1', memberId: 'm2', percentage: 20 }, { projectId: 'p3', memberId: 'm2', percentage: 80 }, { projectId: 'p2', memberId: 'm3', percentage: 100 },
]},
{ label: 'Q2 2026', start: new Date(2026, 3, 1), end: new Date(2026, 5, 30), allocations: [
{ projectId: 'p1', memberId: 'm1', percentage: 25 }, { projectId: 'p3', memberId: 'm1', percentage: 75 }, { projectId: 'p1', memberId: 'm2', percentage: 50 }, { projectId: 'p2', memberId: 'm2', percentage: 25 }, { projectId: 'p3', memberId: 'm2', percentage: 25 }, { projectId: 'p2', memberId: 'm3', percentage: 40 }, { projectId: 'p3', memberId: 'm3', percentage: 60 },
]},
];
const TIMED_ALLOCATIONS = PERIODS.flatMap((period) => period.allocations.map((allocation) => ({ ...allocation, startDate: period.start, endDate: period.end })));
const DEFAULT_RANGE = { start: new Date(2026, 0, 1), end: new Date(2026, 2, 31) };
const getEffectiveRange = (range?: DateRange) => {
const start = range?.start ?? DEFAULT_RANGE.start;
const end = range?.end ?? range?.start ?? DEFAULT_RANGE.end;
return start <= end ? { start, end } : { start: end, end: start };
};
export default function AllocationMatrixWidgetFilterExample() {
const [dateRange, setDateRange] = useState<DateRange | undefined>(DEFAULT_RANGE);
const effectiveRange = getEffectiveRange(dateRange);
const matchedPeriods = PERIODS.filter((period) => period.start <= effectiveRange.end && period.end >= effectiveRange.start);
const matchedPeriodLabel = matchedPeriods.map((period) => period.label).join(', ');
return (
<Box w="100%">
<AllocationMatrixWidget
title="Resource Allocation"
subtitle={`Allocation filtered across ${matchedPeriods.length} matching period(s)`}
projects={PROJECTS}
members={MEMBERS}
allocations={TIMED_ALLOCATIONS}
dateRange={dateRange}
headerExtraContent={(
<DateRangePicker
variant="single"
value={dateRange}
onChange={setDateRange}
labelStyle="outside"
placeholder="Select range"
showPresets
fullWidth={false}
/>
)}
footer={
matchedPeriods.length > 0
? `Selected range: ${effectiveRange.start.toLocaleDateString('en-GB')} - ${effectiveRange.end.toLocaleDateString('en-GB')} • Matching periods: ${matchedPeriodLabel}`
: 'No allocation data overlaps with the selected period.'
}
/>
</Box>
);
}Displays a skeleton preview while data is being fetched.
"use client";
import { AllocationMatrixWidget, Box } from '@photonix/ultimate';
export default function AllocationMatrixWidgetLoadingExample() {
return (
<Box w="100%">
<AllocationMatrixWidget title="Allocation" projects={[]} members={[]} allocations={[]} loading height={300} />
</Box>
);
}Display summary or additional info at the bottom.
Last updated: 5 minutes ago
"use client";
import { AllocationMatrixWidget, Box, type MatrixAllocation, type MatrixMember, type MatrixProject } from '@photonix/ultimate';
const projects: MatrixProject[] = [
{ id: 'docs', name: 'Docs' }, { id: 'system', name: 'Design system' },
];
const members: MatrixMember[] = [
{ id: 'jane', name: 'Jane Cooper', role: 'Designer' }, { id: 'wade', name: 'Wade Warren', role: 'Engineer' },
];
const allocations: MatrixAllocation[] = [
{ memberId: 'jane', projectId: 'docs', percentage: 60 }, { memberId: 'jane', projectId: 'system', percentage: 40 }, { memberId: 'wade', projectId: 'system', percentage: 85 },
];
export default function AllocationMatrixWidgetFooterExample() {
return (
<Box w="100%">
<AllocationMatrixWidget
title="Resource Summary"
projects={projects}
members={members}
allocations={allocations}
footer="Last updated: 5 minutes ago"
height={320}
/>
</Box>
);
}