# Calendar
**📖 Live documentation:** https://cds.coinbase.com/components/other/Calendar/
Calendar is a flexible, accessible date grid component for selecting dates, supporting keyboard navigation, disabled/highlighted dates, and custom rendering.
## Import
```tsx
import { Calendar } from '@coinbase/cds-web/dates/Calendar'
```
## Examples
Calendar is a date grid for selecting dates and powers the picker in [DatePicker](/components/other/DatePicker). Control the visible month with `selectedDate` or `seedDate`, and use `onPressDate` to handle selection. It supports keyboard navigation, disabled and highlighted dates, and custom styling via `classNames` and `styles`.
### Basics
#### Basic usage
```tsx live
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
return ;
};
```
### Disabled dates
```tsx live
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
// Disable today and tomorrow
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
return (
);
};
```
### Highlighted dates
```tsx live
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
// Highlight the 10th, 15th, and 20th of the current month
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const highlightedDates = [
new Date(year, month, 10),
new Date(year, month, 15),
new Date(year, month, 20),
];
return (
);
};
```
### Styling
#### Slot styling
Use the `classNames` and `styles` props to target specific elements: `root`, `header`, `monthLabel`, `navArrows` (container), `navArrow` (each button), `dayHeader`, `content` (day header + date grid), `calendarGrid` (date cells container), and `dayCell`.
```tsx live
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
const highlightedDates = useMemo(() => {
const d = new Date();
d.setDate(d.getDate() - 1);
return [d];
}, []);
const disabledDates = useMemo(() => {
const d = new Date();
d.setDate(d.getDate() - 2);
return [d];
}, []);
return (
<>
>
);
};
```
### Accessibility
Use `nextArrowAccessibilityLabel` and `previousArrowAccessibilityLabel` so screen reader users can navigate months. When using `disabledDates`, `minDate`, or `maxDate`, provide `disabledDateError` so users understand why a date cannot be selected.
```tsx live
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
const nextMonth = useMemo(() => {
const d = new Date();
d.setMonth(d.getMonth() + 1);
return d;
}, []);
return (
);
};
```
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `alignContent` | `ResponsiveProp
` | No | `-` | - |
| `alignItems` | `ResponsiveProp` | No | `-` | - |
| `alignSelf` | `ResponsiveProp` | No | `-` | - |
| `as` | `div` | No | `-` | The underlying element or component the polymorphic component will render. Changing as also changes the inherited native props (e.g. href for as=a) and the expected ref type. |
| `aspectRatio` | `ResponsiveProp` | No | `-` | - |
| `background` | `ResponsiveProp` | No | `-` | - |
| `borderBottomLeftRadius` | `ResponsiveProp` | No | `-` | - |
| `borderBottomRightRadius` | `ResponsiveProp` | No | `-` | - |
| `borderBottomWidth` | `ResponsiveProp` | No | `-` | - |
| `borderColor` | `ResponsiveProp` | No | `-` | - |
| `borderEndWidth` | `ResponsiveProp` | No | `-` | - |
| `borderRadius` | `ResponsiveProp` | No | `-` | - |
| `borderStartWidth` | `ResponsiveProp` | No | `-` | - |
| `borderTopLeftRadius` | `ResponsiveProp` | No | `-` | - |
| `borderTopRightRadius` | `ResponsiveProp` | No | `-` | - |
| `borderTopWidth` | `ResponsiveProp` | No | `-` | - |
| `borderWidth` | `ResponsiveProp` | No | `-` | - |
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
| `bottom` | `ResponsiveProp>` | No | `-` | - |
| `classNames` | `{ readonly root?: string; readonly header?: string \| undefined; readonly title?: string \| undefined; readonly navigation?: string \| undefined; readonly content?: string \| undefined; readonly day?: string \| undefined; } \| undefined` | No | `-` | - |
| `color` | `ResponsiveProp` | No | `-` | - |
| `columnGap` | `ResponsiveProp` | No | `-` | - |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `disabled` | `boolean` | No | `-` | Disables user interaction. |
| `disabledDateError` | `string` | No | `'Date unavailable'` | Tooltip content shown when hovering or focusing a disabled date, including dates before the minDate or after the maxDate. |
| `disabledDates` | `(Date \| [Date, Date])[]` | No | `-` | Array of disabled dates, and date tuples for date ranges. Make sure to set disabledDateError as well. A number is created for every individual date within a tuple range, so do not abuse this with massive ranges. |
| `display` | `ResponsiveProp` | No | `-` | - |
| `elevation` | `ResponsiveProp` | No | `-` | - |
| `flexBasis` | `ResponsiveProp>` | No | `-` | - |
| `flexDirection` | `ResponsiveProp` | No | `-` | - |
| `flexGrow` | `ResponsiveProp` | No | `-` | - |
| `flexShrink` | `ResponsiveProp` | No | `-` | - |
| `flexWrap` | `ResponsiveProp` | No | `-` | - |
| `font` | `ResponsiveProp` | No | `-` | - |
| `fontFamily` | `ResponsiveProp` | No | `-` | - |
| `fontSize` | `ResponsiveProp` | No | `-` | - |
| `fontWeight` | `ResponsiveProp` | No | `-` | - |
| `gap` | `ResponsiveProp` | No | `-` | - |
| `grid` | `ResponsiveProp` | No | `-` | - |
| `gridArea` | `ResponsiveProp` | No | `-` | - |
| `gridAutoColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridAutoFlow` | `ResponsiveProp` | No | `-` | - |
| `gridAutoRows` | `ResponsiveProp>` | No | `-` | - |
| `gridColumn` | `ResponsiveProp` | No | `-` | - |
| `gridColumnEnd` | `ResponsiveProp` | No | `-` | - |
| `gridColumnStart` | `ResponsiveProp` | No | `-` | - |
| `gridRow` | `ResponsiveProp` | No | `-` | - |
| `gridRowEnd` | `ResponsiveProp` | No | `-` | - |
| `gridRowStart` | `ResponsiveProp` | No | `-` | - |
| `gridTemplate` | `ResponsiveProp` | No | `-` | - |
| `gridTemplateAreas` | `ResponsiveProp` | No | `-` | - |
| `gridTemplateColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridTemplateRows` | `ResponsiveProp>` | No | `-` | - |
| `height` | `ResponsiveProp>` | No | `-` | - |
| `hideControls` | `boolean` | No | `-` | Hides the Calendar next and previous month arrows, but does not prevent navigating to the next or previous months via keyboard. This probably only makes sense to be used when minDate and maxDate are set to the first and last days of the same month. |
| `highlightedDateAccessibilityHint` | `string` | No | `'Highlighted'` | Accessibility hint announced for highlighted dates. Applied to all highlighted dates. |
| `highlightedDates` | `(Date \| [Date, Date])[]` | No | `-` | Array of highlighted dates, and date tuples for date ranges. A number is created for every individual date within a tuple range, so do not abuse this with massive ranges. |
| `justifyContent` | `ResponsiveProp` | No | `-` | - |
| `key` | `Key \| null` | No | `-` | - |
| `left` | `ResponsiveProp>` | No | `-` | - |
| `lineHeight` | `ResponsiveProp` | No | `-` | - |
| `margin` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginBottom` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginEnd` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginStart` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginTop` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginX` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginY` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `maxDate` | `Date` | No | `-` | Maximum date allowed to be selected, inclusive. Dates after the maxDate are disabled. All navigation to months after the maxDate is disabled. |
| `maxHeight` | `ResponsiveProp>` | No | `-` | - |
| `maxWidth` | `ResponsiveProp>` | No | `-` | - |
| `minDate` | `Date` | No | `-` | Minimum date allowed to be selected, inclusive. Dates before the minDate are disabled. All navigation to months before the minDate is disabled. |
| `minHeight` | `ResponsiveProp>` | No | `-` | - |
| `minWidth` | `ResponsiveProp>` | No | `-` | - |
| `nextArrowAccessibilityLabel` | `string` | No | `'Go to next month'` | Accessibility label describing the Calendar next month arrow. |
| `onChange` | `FormEventHandler` | No | `-` | - |
| `onPressDate` | `((date: Date) => void)` | No | `-` | Callback function fired when pressing a Calendar date. |
| `opacity` | `ResponsiveProp` | No | `-` | - |
| `overflow` | `ResponsiveProp` | No | `-` | - |
| `padding` | `ResponsiveProp` | No | `-` | - |
| `paddingBottom` | `ResponsiveProp` | No | `-` | - |
| `paddingEnd` | `ResponsiveProp` | No | `-` | - |
| `paddingStart` | `ResponsiveProp` | No | `-` | - |
| `paddingTop` | `ResponsiveProp` | No | `-` | - |
| `paddingX` | `ResponsiveProp` | No | `-` | - |
| `paddingY` | `ResponsiveProp` | No | `-` | - |
| `pin` | `PinningDirection` | No | `-` | Direction in which to absolutely pin the box. |
| `position` | `ResponsiveProp` | No | `-` | - |
| `previousArrowAccessibilityLabel` | `string` | No | `'Go to previous month'` | Accessibility label describing the Calendar previous month arrow. |
| `ref` | `((instance: HTMLElement \| null) => void) \| RefObject \| null` | No | `-` | - |
| `right` | `ResponsiveProp>` | No | `-` | - |
| `rowGap` | `ResponsiveProp` | No | `-` | - |
| `seedDate` | `Date` | No | `-` | Date used to generate the Calendar month when there is no value for the selectedDate prop, defaults to today. |
| `selectedDate` | `Date \| null` | No | `-` | Currently selected Calendar date. Date used to generate the Calendar month. Will be rendered with active styles. |
| `style` | `CSSProperties` | No | `-` | - |
| `styles` | `{ readonly root?: CSSProperties; readonly header?: CSSProperties \| undefined; readonly title?: CSSProperties \| undefined; readonly navigation?: CSSProperties \| undefined; readonly content?: CSSProperties \| undefined; readonly day?: CSSProperties \| undefined; } \| undefined` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `textAlign` | `ResponsiveProp` | No | `-` | - |
| `textDecoration` | `ResponsiveProp` | No | `-` | - |
| `textTransform` | `ResponsiveProp` | No | `-` | - |
| `top` | `ResponsiveProp>` | No | `-` | - |
| `transform` | `ResponsiveProp` | No | `-` | - |
| `userSelect` | `ResponsiveProp` | No | `-` | - |
| `visibility` | `ResponsiveProp` | No | `-` | - |
| `width` | `ResponsiveProp>` | No | `-` | - |
| `zIndex` | `ResponsiveProp` | No | `-` | - |
## Styles
| Selector | Static class name | Description |
| --- | --- | --- |
| `root` | `cds-Calendar` | Root element |
| `header` | `cds-Calendar-header` | Header section |
| `title` | `cds-Calendar-title` | Month and year title text element |
| `navigation` | `cds-Calendar-navigation` | Navigation controls element |
| `content` | `cds-Calendar-content` | Main content area |
| `day` | `cds-Calendar-day` | Individual date cell in a calendar grid |