Calendar

Calendar displays a month grid for choosing dates.

npm install @plocks/dates

Basics

Bind value and onChange to local state to capture the selected day while highlightToday keeps the current date visually distinct.

Loading demo…

import { useState } from 'react'; import { Block, Text } from '@plocks/ui'; import { Calendar } from '@plocks/dates'; const formatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }); export function Demo() { const [selectedDate, setSelectedDate] = useState<Date | null>(new Date()); return ( <Block fullWidth> <Calendar value={selectedDate} onChange={(date) => setSelectedDate(date as Date | null)} highlightToday /> <Text size="sm" c="secondary"> Selected date: {selectedDate ? formatter.format(selectedDate) : 'none'} </Text> </Block> ); }

Date constraints

Set minDate and maxDate to keep navigation inside the current month while still allowing the calendar to show surrounding weeks.

Loading demo…

import { useMemo, useState } from 'react'; import { Block, Text } from '@plocks/ui'; import { Calendar } from '@plocks/dates'; const monthFormatter = new Intl.DateTimeFormat('en-US', { month: 'long', year: 'numeric' }); const dateFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }); export function Demo() { const [selectedDate, setSelectedDate] = useState<Date | null>(new Date()); const { minDate, maxDate, monthLabel } = useMemo(() => { const today = new Date(); const start = new Date(today.getFullYear(), today.getMonth(), 1); const end = new Date(today.getFullYear(), today.getMonth() + 1, 0); return { minDate: start, maxDate: end, monthLabel: monthFormatter.format(start) }; }, []); return ( <Block fullWidth> <Calendar value={selectedDate} onChange={(date) => setSelectedDate(date as Date | null)} minDate={minDate} maxDate={maxDate} highlightToday /> <Text size="sm" c="secondary"> Selected date: {selectedDate ? dateFormatter.format(selectedDate) : 'none'} </Text> <Text size="xs" c="secondary"> Only dates in {monthLabel} are enabled. </Text> </Block> ); }

Multiple selection

Switch type="multiple" to let teammates flag several event days at once; the component returns an array you can format for summaries or badges.

Loading demo…

import { useMemo, useState } from 'react'; import { Block, Text } from '@plocks/ui'; import { Calendar } from '@plocks/dates'; const formatter = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric' }); export function Demo() { const [selectedDates, setSelectedDates] = useState<Date[]>([]); const summary = useMemo(() => { if (selectedDates.length === 0) return 'No dates picked yet.'; if (selectedDates.length === 1) { return `1 date picked: ${formatter.format(selectedDates[0])}`; } return `${selectedDates.length} dates picked: ${selectedDates.map((date) => formatter.format(date)).join(', ')}`; }, [selectedDates]); return ( <Block fullWidth> <Calendar type="multiple" value={selectedDates} onChange={(dates) => setSelectedDates(dates as Date[])} highlightToday /> <Text size="sm" c="secondary"> {summary} </Text> </Block> ); }

Range selection

Use type="range" to capture a start and end date for bookings or sprints; the component returns a tuple you can translate into summaries or validation.

Loading demo…

import { useMemo, useState } from 'react'; import { Block, Text } from '@plocks/ui'; import { Calendar } from '@plocks/dates'; const formatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }); export function Demo() { const [selectedRange, setSelectedRange] = useState<[Date | null, Date | null]>([null, null]); const summary = useMemo(() => { const [start, end] = selectedRange; if (!start) { return 'No dates selected yet.'; } if (!end) { return `Start date chosen: ${formatter.format(start)} — pick an end date.`; } return `${formatter.format(start)} → ${formatter.format(end)}`; }, [selectedRange]); return ( <Block fullWidth> <Calendar type="range" value={selectedRange} onChange={(range) => setSelectedRange(range as [Date | null, Date | null])} highlightToday /> <Text size="sm" c="secondary"> {summary} </Text> </Block> ); }
Scan to open this page on your phoneplocks.dev/dates/Calendar