Calendar
The calendar displays a monthly view of the user's workout history. Each day is represented by a history day cell (history-day) that reflects the workout status for that date. The header allows navigation between months. The calendar is used exclusively on the workout history screen.
When to use
Use the calendar on the workout history screen to give users a monthly overview of their workout activity.
Don't use the calendar as a date picker or scheduling tool. Use a dedicated date picker component instead.
Structure
Calendar container
A rounded card (responsive/layout/radius/2xl) with a white background and a subtle shadow (shadow/sm). Width is fixed at 329px. Padding and internal gap both use responsive/layout/padding/xl. It contains three sections stacked vertically: the header, the weekday labels row, and the day rows.
Header
A horizontal row with a previous month button on the left, the current month and year label in the centre, and a next month button on the right. The label uses text/content/body/emphasis, coloured broz-content/neutral/primary. Both buttons are circular ghost buttons (36×36px, responsive/layout/radius/rounded) containing a directional arrow icon.
Weekday labels
A single row of seven short day labels (Mo, Tu, We, Th, Fr, Sa, Su) in text/content/note/emphasis, coloured broz-content/neutral/tertiary. Each label takes equal width.
Day rows
Days are laid out in weekly rows of seven cells. Each cell is a history-day component (32×32px, responsive/layout/radius/rounded). Days that fall outside the current month are rendered as empty cells to preserve the grid alignment.
History day states
The history-day nested component has five states controlled by the state prop.
State | When used | Background | Border | Text style | Text colour |
|---|---|---|---|---|---|
| A future day with no workout scheduled or expected | None | None |
|
|
| The current day |
|
|
|
|
| A past day where the user completed a workout |
|
|
|
|
| A past day where the user had a workout planned but did not complete it | None | None |
|
|
| A day outside the current month, used to fill the grid | Invisible ( | None | — | — |
The missed state intentionally uses muted styling with no warning colour. The goal is to avoid making the user feel penalised for a missed session.
Interaction
The calendar is interactive only through its header navigation buttons. Tapping the left arrow navigates to the previous month. Tapping the right arrow navigates to the next month. The day cells themselves are non interactive and display only.
Placement
The calendar is used exclusively on the workout history screen. It always displays one full month at a time, starting on Monday.
Accessibility
The calendar container should carry an accessible label identifying the current month, for example: "Workout history, June 2026."
The previous and next month buttons must have accessible labels: "Previous month" and "Next month."
Each day cell should be announced with its date and status, for example: "3 June, workout completed." / "4 June, today." / "1 June, workout missed." Future days and empty cells can be announced as their date only or excluded from the tab order entirely.
Empty cells must be hidden from the accessibility tree (
aria-hidden).The weekday label row should be marked as presentational since the day cells carry the full date context.
Tokens
Element | Token |
|---|---|
Container background |
|
Container border |
|
Container corner radius |
|
Container shadow |
|
Container padding |
|
Month label |
|
Weekday labels |
|
Day cell size | 32×32px |
Day cell corner radius |
|
Today background |
|
Today border |
|
Done background |
|
Done border |
|
Done text |
|
Nextdays and today text |
|
Missed text |
|
Empty cell opacity |
|
