Period controls
The bar under a report's header that picks which numbers the page shows: a preset period, a typed range, and whose numbers. Every change reloads every figure on the page.
Playground
Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.
import { PeriodControls } from '@/ui/period-controls';<PeriodControls />Default
The Dashboard bar: Week, Month and Quarter, the From and To days, whose numbers, then Refresh at the right. Type a day and Apply appears; applying a typed range clears the preset. Press Refresh twice to see a failed reload.
import { useState } from 'react';
import { addDays } from '@/lib/dates';
import { PeriodControls, type PeriodPreset, type PeriodRange } from '@/ui/period-controls';
import { toast } from '@/ui/toast';
const today = '2026-10-16';
const presets: Record<PeriodPreset, PeriodRange> = {
week: { from: '2026-10-12', to: '2026-10-18' },
month: { from: '2026-10-01', to: '2026-10-31' },
quarter: { from: '2026-10-01', to: '2026-12-31' },
};
const scopes = [
{ label: 'Agency', options: [{ value: 'agency', label: 'Northbridge Talent' }] },
{ label: 'Teams', options: [{ value: 'team:tech', label: 'Tech and data' }, { value: 'team:finance', label: 'Finance' }] },
{ label: 'People', options: [{ value: 'person:maya', label: 'Maya Chen' }, { value: 'person:minh', label: 'Nguyễn Thị Minh Khai' }] },
];
// The Dashboard bar. Every change reloads every figure; the second Refresh fails, to show the error toast.
export default function Dashboard() {
const [preset, setPreset] = useState<PeriodPreset | null>('month');
const [range, setRange] = useState(presets.month);
const [scope, setScope] = useState('agency');
const [loading, setLoading] = useState(false);
const [loads, setLoads] = useState(0);
const reload = () => {
setLoading(true);
setTimeout(() => {
setLoading(false);
setLoads((n) => n + 1);
if (loads === 1) toast.add({ type: 'error', title: 'Couldn’t load the Dashboard', description: 'Check your connection, then press Refresh.' });
}, 900);
};
return (
<PeriodControls
className="w-full"
today={addDays(today, 0)}
maxDays={366}
preset={preset}
range={range}
scope={scope}
scopes={scopes}
loading={loading}
onPresetChange={(next) => {
setPreset(next);
setRange(presets[next]);
reload();
}}
onRangeApply={(next) => {
setPreset(null);
setRange(next);
reload();
}}
onScopeChange={(next) => {
setScope(next);
reload();
}}
onRefresh={reload}
/>
);
}States
Loading: the bar is busy while the figures reload, the presets wait and Refresh shows its spinner. A typed range whose first day is after the last says so under the bar and Apply stays off. A member who can only see their own numbers gets no scope.
import { PeriodControls } from '@/ui/period-controls';
const noop = () => {};
// Loading: the bar is busy while figures reload. Error: a typed range whose first day is after the last; Apply stays off.
// Own numbers only: a member who can only see their own gets no scope.
export default function States() {
return (
<div className="flex w-full flex-col gap-300">
<PeriodControls preset="week" range={{ from: '2026-10-12', to: '2026-10-18' }} today="2026-10-16" loading onPresetChange={noop} onRangeApply={noop} onRefresh={noop} />
<PeriodControls preset={null} range={{ from: '2026-10-20', to: '2026-10-15' }} today="2026-10-16" onPresetChange={noop} onRangeApply={noop} onRefresh={noop} />
</div>
);
}