Full keyboard nav: Arrows, Home/End, PageUp/PageDown, Enter/Space
Surface-aware (pixel / linear) — follows the nearest PxlKitSurfaceProvider
Status
stable
Category
forms
Since
v1.9.0
API
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
Prop
Type
Default
Description
value
Date | null
—
The picked day, null for none; leave unset for an uncontrolled grid.
defaultValue
Date | null
—
Initial day while uncontrolled.
onChange
(date: Date) => void
—
Called with the day picked, at its start.
minDate
Date
—
First day that can be picked.
maxDate
Date
—
Last day that can be picked.
disabledDates
Date[] | ((d: Date) => boolean)
—
Days that cannot be picked: a list, or a test of each day.
renderDay
(d: Date) => React.ReactNode
—
Draws a day's cell content in place of its number.
month
Date
—
The month on show (any day of it); leave unset to start on the picked day's, else today's.
onMonthChange
(m: Date) => void
—
Called with the first day of the month shown next (the navigation buttons, or focus leaving the month).
surface
'pixel' | 'linear'
—
Surface override; defaults to the nearest provider.
rangePreview
{ from?: Date; to?: Date; hover?: Date }
—
A range to highlight: from from to to, or to hover while to is not picked.
data-testid
string
—
Optional hook for tests.
ref points to <div>.
Accessibility
WCAG target: 2.1 AA
grid
role=grid with columnheader weekday cells and gridcell day buttons; aria-selected marks the chosen day, aria-current="date" marks today, and aria-disabled marks out-of-bounds or disabled dates. Moves skip disabled days and stop at min/max. One enabled day is in the tab order. Week start, month and weekday names follow PxlKitLocaleProvider.
Keyboard
Key
Action
When
ArrowLeft
Move focus to previous day
—
ArrowRight
Move focus to next day
—
ArrowUp
Move focus to previous week
—
ArrowDown
Move focus to next week
—
Home
Move focus to start of week
—
End
Move focus to end of week
—
PageUp
Move focus to the same day of the previous month (its last day when shorter)
—
PageDown
Move focus to the same day of the next month (its last day when shorter)
—
Shift+PageUp
Move focus to the same day of the previous year
—
Shift+PageDown
Move focus to the same day of the next year
—
Enter
Select the focused day
—
Space
Select the focused day
—
Usage
import { useState } from 'react';
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
export function Default() {
const [value, setValue] = useState<Date | null>(null)
return <PixelCalendarGrid value={value} onChange={setValue} />
}
Examples
Default
Shows the current month and marks today, by the clock of whatever renders it: a server render can differ from the browser's (a page built on another day, another time zone) and fail to hydrate. For a stable server render pass month (and value or defaultValue), or render a current-month calendar in the browser only: next/dynamic with ssr: false (Next.js), ClientOnly (Nuxt), @defer (Angular).
import { useState } from 'react';
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
export function Default() {
const [value, setValue] = useState<Date | null>(null)
return <PixelCalendarGrid value={value} onChange={setValue} />
}
With Selected Date
import { useState } from 'react';
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
export function WithSelectedDate() {
const [value, setValue] = useState<Date | null>(new Date())
return <PixelCalendarGrid value={value} onChange={setValue} />
}
With Min/Max Bounds
import { useState } from 'react';
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
export function WithMinMax() {
const today = new Date()
const min = new Date(today.getFullYear(), today.getMonth(), 1)
const max = new Date(today.getFullYear(), today.getMonth() + 1, 0)
const [value, setValue] = useState<Date | null>(null)
return (
<PixelCalendarGrid
value={value}
onChange={setValue}
minDate={min}
maxDate={max}
/>
)
}
import { PixelCalendarGrid } from '@pxlkit/ui-kit';
export function RangePreview() {
const from = new Date()
const to = new Date(from.getFullYear(), from.getMonth(), from.getDate() + 5)
return <PixelCalendarGrid rangePreview={{ from, to }} />
}