Calendar
An element for creating interactive calendar.
Showcase
import { Calendar, CalendarButton, CalendarCell, CalendarGrid, CalendarHeader, CalendarTitle} from '@klnjs/react-calendar'import classes from './calendar.module.css'
export default () => ( <Calendar aria-label="Event date" locale="en-GB" className={classes.calendar} > <CalendarHeader className={classes.header}> <CalendarButton action="dec" className={classes.button} /> <CalendarTitle className={classes.title} /> <CalendarButton action="inc" className={classes.button} /> </CalendarHeader> <CalendarGrid className={classes.grid}> {({ type, date }) => ( <CalendarCell key={`${type}-${date.toString()}`} type={type} date={date} className={classes.cell} /> )} </CalendarGrid> </Calendar>)
.calendar { display: inline-flex; flex-direction: column; gap: 8px; font-size: 14px; position: relative; background: var(--sl-color-black); background-clip: padding-box; border-radius: 0.5rem; border: 1px solid var(--sl-color-hairline-light); padding: 8px;}
.title { margin: 0; padding: 0; font-size: 18px;}
.grid { display: grid; grid-template-columns: repeat(7, 1fr); row-gap: 2px;}
.header { display: flex; align-items: center; justify-content: space-between; gap: 4px; height: 32px;}
.button { display: inline-flex; width: 32px; height: 32px; outline: 0; cursor: pointer; border: none; border-radius: 0.5rem; background: none; line-height: 24px; align-items: center; justify-content: center; color: var(--sl-color-text);}
.button:hover,.button:focus-visible { color: var(--sl-color-white);}
.button:disabled { pointer-events: none;}
.cell { width: 32px; height: 28px; display: flex; font: inherit; align-items: center; justify-content: center; user-select: none; padding: 0; outline: 0; border: 1px solid transparent; border-radius: 0.5rem; background: none;}
.cell[data-cell='week'] { font-size: 10px; font-weight: bold; color: var(--sl-color-accent-high);}
.cell[data-cell='day'] { cursor: pointer;}
.cell[data-cell='day']:not([data-selected]):not([data-range-between]):hover { color: var(--sl-color-white);}
.cell[data-cell='day'][data-today] { font-weight: bold;}
.cell[data-cell='day'][data-weekend] { color: var(--sl-color-orange);}
.cell[data-cell='day'][data-overflow] { visibility: hidden;}
.cell[data-cell='day'][data-focused]:focus-visible { border: 1px solid var(--sl-color-white); color: var(--sl-color-white);}
.cell[data-cell='day'][data-selected] { color: var(--sl-color-text-invert); background: var(--sl-color-accent-high);}
.cell[data-cell='day'][data-disabled] { opacity: 0.4; pointer-events: none;}
.cell[data-cell='day'][data-range-start]:not([data-range-end]) { border-start-end-radius: 0; border-end-end-radius: 0;}
.cell[data-cell='day'][data-range-end]:not([data-range-start]) { border-start-start-radius: 0; border-end-start-radius: 0;}
.cell[data-cell='day'][data-range-between] { background-color: rgba(var(--sl-color-accent-high), 0.2); border-radius: 0;}
.cell[data-cell='day'][data-week-start] { border-start-start-radius: 0.5rem; border-end-start-radius: 0.5rem;}
.cell[data-cell='day'][data-week-end] { border-start-end-radius: 0.5rem; border-end-end-radius: 0.5rem;}
Features
-
Controlled or uncontrolled.
-
Multiple selection modes - one, many and range.
-
Keyboard navigation and screen reader support.
-
Supports calendar systems used around the world.
-
Localisation, formatting and right-to-left support.
Installation
The calendar component relies on a temporal polyfill for handling date operations. Ensure the polyfill is included in your project dependencies.
bun install @klnjs/react-calendar temporal-polyfill
Definitions
Components
Calendar
Contains all the parts of a calendar. As the calendar does not have html semantics for providing a label, it is recommended to provide an aria-label
to ensure good accessibility.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
autoFocus | boolean | false |
calendar | LocaleCalendar | - |
defaultValue | CalendarSelectValue | - |
disabled | boolean | false |
locale | string | en |
max | PlainDate | - |
min | PlainDate | - |
pagination | CalendarPagination | visible |
readOnly | boolean | false |
select | CalendarSelect | one |
value | CalendarSelectValue | - |
visibleDuration | CalendarVisibleDuration | { months: 1 } |
onChange | (value: CalendarSelectValue) => void | - |
Header
Used to group calendar header components.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Title
Display a localised title representing the current visible range of the calendar.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Button
Facilitates navigation in the calendar, to ensure keyboard accessibility the active day will be moved to the best matching day within the visible range.
Use the action
to either increment or decrement the visible range. When unit
is set to months, it will use root properties pagination
and visibleDuration
to determine the distance.
The button will be disabled when the action would cause the visible range to land outside of the root properties min
and max
.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
action | 'inc' | 'dec' | - |
unit | 'months' | 'years' | months |
Group
Used to group grid components when working with multiple months.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Grid
Given the dynamic length of the visible range in the calendar, this utility component provides means to render the cells relevant to the visible range using a render function as child.
The properties week
and weekdays
can be used to enable week day and week number headers, when both properties are enabled blank cells can occur in the grid. To differentiate between the different cell types, the render function provides a type
property.
Set overflow: 'align'
to expand overflow at the end of a month, to match the longest possible month. This can prevent misalignment when working with multiple months.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
week | boolean | false |
weekdays | boolean | false |
overflow | 'auto' | 'align' | auto |
children | (cell: CalendarGridCellItem ) => ReactNode | - |
Cell
Used to render individual cells in the grid, it should be used in conjunction with the grid utility component. Cell will render a different native element based on the type
prop.
Cell provides accessibility like localised labeling and keyboard navigation. For sighted users, it provides data-*
attributes enabling styling of the different cell types and states.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
type | CalendarCellType | - |
date | PlainDate | - |
Data attribute | Present when |
---|---|
data-cell | CalendarCellType |
data-today | cell is today |
data-tommorow | cell is tommorow |
data-yesterday | cell is yesterday |
data-weekend | cell is weekend |
data-focused | cell is focused |
data-overflow | cell is outside month |
data-disabled | cell is disabled |
data-selected | cell is selected |
data-week-end | cell is last day of week |
data-week-start | cell is first day of week |
data-range-end | cell is last day of range |
data-range-start | cell is first day of range |
data-range-between | cell is inside range |