Skip to content
EspañolEnglish
All components (204)

Calendar

Dates and time · Calendar · .amset-calendar

What it is and when to use it

The month in view, without opening anything: to pick the day for a pickup, an appointment or a period by looking at which days are free. With range it picks two endpoints instead of one day, and with months it shows up to three months in a row.

When to use it

  • When seeing the month is part of the decision: free days, closed days, a period that crosses a month boundary.
  • isDateUnavailable to gray out individual days (weekends, holidays) and legend to explain what they mean. minValue and maxValue limit what can be chosen.

When not to

  • A date inside a form: DatePicker, which is typed with the keyboard without opening anything (and DateRangePicker for two).
  • The month with events and the list for each day beside it: MonthAgenda.
  • Choosing a day and a time from a schedule: SlotPicker.

Keyboard: Tab goes through "Previous month", "Next month" and the grid. In the grid: arrow keys move by days and weeks, Page Up and Page Down change the month (with Shift, the year), Home and End go to the first and last day of the month, and Enter or Space select. With range, the first selection marks the start and the second the end.

Accessibility: label is the name of the calendar (there is no visible label: whoever places it provides one, in a card or a heading). The hint and the error are linked with aria-describedby: they are read together with the calendar, not left loose underneath. With error, the calendar is also marked invalid (data-invalid) and the selected day or days carry aria-invalid and the message as their description. Unavailable days cannot be selected.

Fine-tuning: --amset-calendar-day (side of each day: 28, 32 or 40 px depending on the size, and it shrinks on a narrow screen), --amset-calendar-slot, --amset-calendar-padding, --amset-calendar-font and --amset-calendar-nav (the month buttons). They are the same as in the DatePicker panel. Several months are stacked one below the other when they do not fit side by side.

Context: it goes inside LocaleProvider (or AmsetProvider), which decides the month name and which day the week starts on (firstDayOfWeek sets it by hand).

What it looks like

In-store pickup day, October 2026

27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
The store is closed on weekends

Pickup on 21/10/2026.

<Calendar
  label="In-store pickup day"
  value={dia}
  onChange={setDia}
  isDateUnavailable={esFinDeSemana}
  hint="The store is closed on weekends"
/>

Props

Import it with import { Calendar } from '@amset/ui'. Required props are marked.

PropTypeWhat it does
labelrequiredstringWhat this calendar is for: "Delivery date", "Days with appointments".
classNamestringMerged with the library classes; it does not replace them.
defaultFocusedValuePlainDate—
defaultValueDateRange | PlainDate | null—
disabledboolean—
errorstringError message. When passed, the calendar becomes invalid: the chosen days are marked with `aria-invalid` and the message describes them.
firstDayOfWeekFirstDayOfWeekWhich day the week starts on. Without it the language decides (Monday in Spain, Sunday in the United States), which is right almost always. It is forced when what decides is not the language: shifts that start on Saturday with the interface in Spanish.
focusedValuePlainDateThe day it opens on, if nothing is chosen.
hintstring—
idstring—
invalidboolean—
isDateUnavailable(date: PlainDate) => booleanDays that cannot be chosen even if they fall within the limits.
legendReactNodeLegend below: what the marks mean.
maxValuePlainDate—
minValuePlainDate—
months3 | 2 | 1How many months are shown at once. If they do not fit across, they are placed one below another.
onChange((value: PlainDate) => void) | ((value: DateRange) => void)—
onFocusChange(date: PlainDate) => void—
rangebooleanTwo ends instead of one day: from the 1st to the 30th.
readOnlyboolean—
renderDay(date: PlainDate, number: string) => ReactNodePaints the inside of each day: the number and, below, a price, an event dot, an occupancy. It receives the day and its number already written in the language. The accessible name of the day ("Monday, 12 October 2026") does not change.
size"sm" | "md" | "lg"Side of each day: 28, 32 or 40 px. On a narrow screen it shrinks to fit.
valueDateRange | PlainDate | null—

It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.

CSS variables

These CSS variables are how you adapt it. Declare them on the component's selector, not on :root: the stylesheet redeclares them in the rule itself, and a declaration on the same element always wins.

VariableDefault
--amset-calendar-size2rem
--amset-calendar-daymin(var(--amset-calendar-size), calc((100vw - 7rem) / 7))
--amset-calendar-slot2px
--amset-calendar-paddingvar(--amset-space-3)
--amset-calendar-fontvar(--amset-text-sm)
--amset-calendar-nav1.875rem

How to change it

.amset-calendar {
  --amset-calendar-size: ...;
  --amset-calendar-day: ...;
}

In the test bench

Every state and variant, to try one at a time, on its page at ui.amset.tech: