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.
isDateUnavailableto gray out individual days (weekends, holidays) andlegendto explain what they mean.minValueandmaxValuelimit what can be chosen.
When not to
- A date inside a form:
DatePicker, which is typed with the keyboard without opening anything (andDateRangePickerfor 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
October 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
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 |
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.
| Prop | Type | What it does |
|---|---|---|
labelrequired | string | What this calendar is for: "Delivery date", "Days with appointments". |
className | string | Merged with the library classes; it does not replace them. |
defaultFocusedValue | PlainDate | — |
defaultValue | DateRange | PlainDate | null | — |
disabled | boolean | — |
error | string | Error message. When passed, the calendar becomes invalid: the chosen days are marked with `aria-invalid` and the message describes them. |
firstDayOfWeek | FirstDayOfWeek | Which 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. |
focusedValue | PlainDate | The day it opens on, if nothing is chosen. |
hint | string | — |
id | string | — |
invalid | boolean | — |
isDateUnavailable | (date: PlainDate) => boolean | Days that cannot be chosen even if they fall within the limits. |
legend | ReactNode | Legend below: what the marks mean. |
maxValue | PlainDate | — |
minValue | PlainDate | — |
months | 3 | 2 | 1 | How 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 | — |
range | boolean | Two ends instead of one day: from the 1st to the 30th. |
readOnly | boolean | — |
renderDay | (date: PlainDate, number: string) => ReactNode | Paints 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. |
value | DateRange | 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.
| Variable | Default |
|---|---|
--amset-calendar-size | 2rem |
--amset-calendar-day | min(var(--amset-calendar-size), calc((100vw - 7rem) / 7)) |
--amset-calendar-slot | 2px |
--amset-calendar-padding | var(--amset-space-3) |
--amset-calendar-font | var(--amset-text-sm) |
--amset-calendar-nav | 1.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:
