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

nextdays

A future day with no workout scheduled or expected

None

None

text/content/caption/accent

broz-content/neutral/primary

today

The current day

gloabl-bg

broz-borders/selected

text/content/caption/accent

broz-content/neutral/primary

done

A past day where the user completed a workout

broz-bg/success/middle/default

broz-borders/success/middle/default

text/content/caption/emphasis

broz-content/success/primary

missed

A past day where the user had a workout planned but did not complete it

None

None

text/content/caption/accent

broz-content/inverse/secondary

empty

A day outside the current month, used to fill the grid

Invisible (opacity/void)

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

broz-bg/neutral/light/default

Container border

broz-borders/subtler

Container corner radius

responsive/layout/radius/2xl

Container shadow

shadow/sm

Container padding

responsive/layout/padding/xl

Month label

broz-content/neutral/primary, text/content/body/emphasis

Weekday labels

broz-content/neutral/tertiary, text/content/note/emphasis

Day cell size

32×32px

Day cell corner radius

responsive/layout/radius/rounded

Today background

gloabl-bg

Today border

broz-borders/selected

Done background

broz-bg/success/middle/default

Done border

broz-borders/success/middle/default

Done text

broz-content/success/primary, text/content/caption/emphasis

Nextdays and today text

broz-content/neutral/primary, text/content/caption/accent

Missed text

broz-content/inverse/secondary, text/content/caption/accent

Empty cell opacity

responsive/layout/opacity/void