BrickclayDesign System

Availability timeline

A reusable Teams-style day grid: attendee rows, their busy blocks, and a drag-to-select/resize/move time slot picker. It owns grid layout, day navigation, drag mechanics, and the "everyone free" window math, every attendee row, busy block, suggested-slot button, legend, and empty/error state is entirely yours via templates, same content-agnostic split as bk-schedule-calendar.

Date and timeAngular

Preview

A working preview of Availability timeline in the Brickclay style. Try it.

AvailabilitySunday, November 8, 2026
AAAsif AleemCoach
SKSara KhanCoachee
MZM. ZaidiParticipant
Available windows (everyone free)
Interact with the preview to see events here.

Playground

Exactly the config add-coaching-session uses, Coach/Employee/Participant rows behind a role rail labeled COACH/COACHEE/PART, drag to select a slot, resize/move the ghost, suggested "everyone free" windows underneath. No templates at all here, every visual is this component's own built-in default.

Available windows (everyone free)

Custom templates

Same component, a completely different domain: three conference rooms instead of people, no role grouping, and every visual slot templated, laneCellTemplate shows room + capacity instead of name + Available/Unavailable, busyChipTemplate shows the meeting subject and dims Tentative bookings, suggestedSlotTemplate restyles the quick-pick buttons, and headerActionsTemplate adds a "+ New meeting" button next to the day-nav controls.

+ New meeting clicked: 0 · Last slotSelected:, drag or click an empty span

API reference

Inputs

NameTypeDefaultNote
enabledbooleanfalsefalse shows emptyTitle/emptyMessage (or emptyStateTemplate) instead of the grid, e.g. before a coach/room is picked.
dataAvailabilityTimelineData<T>null | null{ people, busyBlocks, freeSlots, unresolvedPeople }. AvailabilityPerson<T>.data is a fully opaque, consumer-owned payload.
loading / errorMessageboolean / stringnullfalse / null | loading shows the built-in overlay while people is still empty; errorMessage shows the built-in banner (or errorStateTemplate) once it isn't.
durationMinutes / selectedDatenumber / Datestring | null30 / null | Drives the selection ghost's width/position and the click-to-select duration. Rebind selectedDate from slotSelected for the ghost to persist (controlled, same pattern as bk-schedule-calendar's view).
disabledbooleanfalseRead-only: no click-to-select, no drag/resize/move.
groupBy / showGroupRail / groupLabelFn / groupTitleFn'none' | 'role''role' / true / none / none'role' groups consecutive rows sharing person.role behind a vertical rail label. Falls back to defaultAvailabilityGroupLabel/Title when the fn inputs are omitted.
gridStartHour / gridHoursnumber0 / 24First hour shown and how many hours the grid spans, independent of businessWindow.
businessWindow{ startHour, endHour }{ 8, 20 }Window scanned for "everyone free" suggested slots, recomputed locally from busyBlocks whenever durationMinutes changes.
slotSnapMinutesnumber15Minute granularity click/drag/resize/move snap to.
disallowPastbooleanfalseadd-coaching-session uses [disallowPast]="true": Previous day stops at today, an overlay covers the already-past part of today, and click/drag/resize/move/suggested-slot selection can't start before now. Editing a session whose own date is already past still shows that day via selectedDate, this only blocks picking a new past time.
hourWidthPx / rowHeightPx / roleRailWidthPx / peopleRailWidthPxnumber72 / 58 / 22 / 200Grid sizing knobs.
laneCellTemplateTemplateRef<AvailabilityLaneCellContext<T>>noneReplaces the sticky attendee cell's built-in name + Available/Unavailable content. Context: { person, state, stateLabel, unresolved, unresolvedReason, conflict, placeholder }.
busyChipTemplateTemplateRef<AvailabilityBusyChipContext<T>>noneReplaces a positioned busy block's built-in plain colored bar. The timeline still owns position/width/click-swallowing. Context: { person, block, conflictsSelection }.
suggestedSlotTemplateTemplateRef<AvailabilitySuggestedSlotContext>noneReplaces an "everyone free" quick-pick button. Context: { slot, label, disabled, select() }.
legendTemplate / emptyStateTemplate / errorStateTemplate / headerActionsTemplateTemplateRef<voidAvailabilityErrorStateContext>none | Replace the Busy/Selected/Conflict legend, the empty state, the error banner, and add extra content next to the day-nav controls, respectively.
placeholderLanes{ key, role }[][{ key: 'placeholder-1', role: 'Attendee' }]Skeleton rows shown while loading and people is still empty.

Outputs

NamePayloadNote
slotSelected{ start: Date; end: Date }A click, or a completed drag/resize/move, on an available span. Rebind selectedDate from this, a resize/move's own span keeps showing on the ghost until the next click/drag, independent of durationMinutes.
dayChangedDatePrev/Today/Next in the built-in day-nav header.