+
Selected date: {value?.toDateString() ?? 'Not set'}
+
setValue(data.date)} />
+
+ } onClick={() => setValue(addMonths(value ?? new Date(), -1))}>
+ Previous
+
+ } onClick={() => setValue(addMonths(value ?? new Date(), 1))}>
+ Next
+
+ } onClick={() => setValue(null)}>
+ Clear selection
+
+
+
+ );
+};
+
+CalendarControlledSelection.parameters = {
+ docs: {
+ description: {
+ story:
+ 'Use null for an empty controlled selection. External value changes navigate to the new date unless displayedDate is also controlled. Clearing selection preserves the displayed month.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarCustomCells.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarCustomCells.stories.tsx
new file mode 100644
index 0000000000000..dc7a347a3d98f
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarCustomCells.stories.tsx
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import { Button, makeStyles, tokens } from '@fluentui/react-components';
+import type { JSXElement } from '@fluentui/react-components';
+import { CalendarRegular } from '@fluentui/react-icons';
+import { Calendar } from '@fluentui/react-calendar-preview';
+
+const useStyles = makeStyles({
+ root: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: tokens.spacingVerticalM },
+ appointment: { color: tokens.colorBrandForeground1, fontWeight: tokens.fontWeightSemibold },
+});
+
+export const CalendarCustomCells = (): JSXElement => {
+ const styles = useStyles();
+ const appointmentRef = React.useRef(null);
+
+ return (
+
+
+ date.getDate() === 15
+ ? {
+ ref: appointmentRef,
+ title: 'Monthly appointment',
+ dayLabel: { className: styles.appointment },
+ }
+ : {},
+ }}
+ monthPicker={{
+ yearPicker: {
+ renderYear: year => {year},
+ },
+ }}
+ />
+ } onClick={() => appointmentRef.current?.focus()}>
+ Focus appointment
+
+
+ );
+};
+
+CalendarCustomCells.parameters = {
+ docs: {
+ description: {
+ story:
+ 'getDayCellProps customizes each visible day, including refs and child slots, without replacing the grid. ' +
+ 'CalendarYear.renderYear customizes year content. Cell click and keyboard handlers run first; preventDefault cancels the built-in action.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDateBoundaries.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDateBoundaries.stories.tsx
new file mode 100644
index 0000000000000..7ffe752d4f14b
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDateBoundaries.stories.tsx
@@ -0,0 +1,54 @@
+import * as React from 'react';
+import { Checkbox } from '@fluentui/react-components';
+import type { JSXElement } from '@fluentui/react-components';
+import { addMonths, addYears, addDays, Calendar } from '@fluentui/react-calendar-preview';
+import type { CalendarProps } from '@fluentui/react-calendar-preview';
+
+export const CalendarDateBoundaries = (): JSXElement => {
+ const today = new Date();
+ const minDate = addMonths(today, -1);
+ const maxDate = addYears(today, 1);
+ const restrictedDates = [addDays(today, -2), addDays(today, -8), addDays(today, 2), addDays(today, 8)];
+
+ const [selectedDate, setSelectedDate] = React.useState(null);
+ const [allFocusable, setAllFocusable] = React.useState(false);
+
+ const onSelectDate: NonNullable = React.useCallback((_event, data) => {
+ setSelectedDate(data.date);
+ }, []);
+
+ return (
+ <>
+ Selected date: {selectedDate?.toDateString() || 'Not set'}
+
+ Date boundary: {minDate.toDateString()}-{maxDate.toDateString()}
+
+ Disabled dates: {restrictedDates.map(d => d.toDateString()).join(', ')}
+ setAllFocusable(data.checked === true)}
+ />
+
+ >
+ );
+};
+
+CalendarDateBoundaries.parameters = {
+ docs: {
+ description: {
+ story:
+ 'A Calendar can be modified to set a minDate and maxDate in order to restrict ' +
+ 'the dates that can be selected.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDefault.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDefault.stories.tsx
new file mode 100644
index 0000000000000..fde4a24fa0fb8
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDefault.stories.tsx
@@ -0,0 +1,6 @@
+import * as React from 'react';
+import type { JSXElement } from '@fluentui/react-components';
+import { Calendar } from '@fluentui/react-calendar-preview';
+import type { CalendarProps } from '@fluentui/react-calendar-preview';
+
+export const Default = (props: CalendarProps): JSXElement => ;
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDescription.md b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDescription.md
new file mode 100644
index 0000000000000..4094f6eba752c
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarDescription.md
@@ -0,0 +1 @@
+The calendar control lets people select and view a single date or a range of dates in their calendar. It’s made up of 3 separate views: the month view, year view, and decade view.
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarFocusAndDismissal.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarFocusAndDismissal.stories.tsx
new file mode 100644
index 0000000000000..499f3e597bfcb
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarFocusAndDismissal.stories.tsx
@@ -0,0 +1,48 @@
+import * as React from 'react';
+import { Button, Popover, PopoverSurface, PopoverTrigger } from '@fluentui/react-components';
+import type { JSXElement } from '@fluentui/react-components';
+import { CalendarRegular } from '@fluentui/react-icons';
+import { Calendar } from '@fluentui/react-calendar-preview';
+import type { CalendarDayHandle } from '@fluentui/react-calendar-preview';
+
+export const CalendarFocusAndDismissal = (): JSXElement => {
+ const [open, setOpen] = React.useState(false);
+ const [value, setValue] = React.useState(null);
+ const dayRef = React.useRef(null);
+
+ React.useEffect(() => {
+ if (open) {
+ dayRef.current?.focus();
+ }
+ }, [open]);
+
+ return (
+ setOpen(data.open)} trapFocus>
+
+ }>{value?.toDateString() ?? 'Select date'}
+
+
+ {
+ setValue(data.date);
+ setOpen(false);
+ }}
+ onDismiss={() => setOpen(false)}
+ />
+
+
+ );
+};
+
+CalendarFocusAndDismissal.parameters = {
+ docs: {
+ description: {
+ story:
+ 'Use the day picker handle for initial focus. Calendar reports Escape and close-button dismissal; ' +
+ 'the surrounding Popover owns positioning, light dismissal, the focus trap, and return focus.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarLocalizedFormatting.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarLocalizedFormatting.stories.tsx
new file mode 100644
index 0000000000000..1143e20089d36
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarLocalizedFormatting.stories.tsx
@@ -0,0 +1,42 @@
+import * as React from 'react';
+import type { JSXElement } from '@fluentui/react-components';
+import { Calendar, createCalendarDateTimeFormatter } from '@fluentui/react-calendar-preview';
+import type { CalendarFormatters } from '@fluentui/react-calendar-preview';
+
+const formatters: CalendarFormatters = {
+ dateTime: createCalendarDateTimeFormatter('de-DE'),
+ previousMonthLabel: data => `Vorheriger Monat ${data.formattedDate}`,
+ nextMonthLabel: data => `Folgender Monat ${data.formattedDate}`,
+ previousYearLabel: data => `Vorheriges Jahr ${data.formattedDate}`,
+ nextYearLabel: data => `Folgendes Jahr ${data.formattedDate}`,
+ previousYearRangeLabel: data => `Vorherige Jahre ${data.formattedRange}`,
+ nextYearRangeLabel: data => `Weitere Jahre ${data.formattedRange}`,
+ monthPickerHeaderLabel: data => `${data.formattedDate}, Jahr wechseln`,
+ yearPickerHeaderLabel: data => `${data.formattedDate}, Monat wechseln`,
+ yearRangePickerHeaderLabel: data => `${data.formattedRange}, Jahr wechseln`,
+ weekNumberLabel: data => `Kalenderwoche ${data.weekNumber}`,
+ selectedDateLabel: data => `Auswahl: ${data.formattedDate}`,
+ todayDateLabel: data => `Heute: ${data.formattedDate}`,
+ dayMarkedLabel: data => `${data.formattedDate}, markiert`,
+};
+
+export const CalendarLocalizedFormatting = (): JSXElement => (
+
+);
+
+CalendarLocalizedFormatting.parameters = {
+ docs: {
+ description: {
+ story:
+ 'A fully localized Calendar uses createCalendarDateTimeFormatter for dates, all label formatters for accessibility, ' +
+ 'and slot props for button text. Week layout and week-number rules are configured separately.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMarkedDays.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMarkedDays.stories.tsx
new file mode 100644
index 0000000000000..b4ee3b97265e2
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMarkedDays.stories.tsx
@@ -0,0 +1,37 @@
+import * as React from 'react';
+import type { JSXElement } from '@fluentui/react-components';
+import { Calendar, addDays } from '@fluentui/react-calendar-preview';
+import type { CalendarDayProps, CalendarProps } from '@fluentui/react-calendar-preview';
+
+const dayPicker: Partial = {
+ getMarkedDays: (startingDate, _) => [addDays(startingDate, 3), addDays(startingDate, 4)],
+};
+
+export const CalendarMarkedDays = (): JSXElement => {
+ const [selectedDate, setSelectedDate] = React.useState(new Date());
+ const onSelectDate: NonNullable = React.useCallback((_event, data) => {
+ setSelectedDate(data.date);
+ }, []);
+
+ return (
+ <>
+ Selected date: {selectedDate?.toDateString() || 'Not set'}
+
+ >
+ );
+};
+
+CalendarMarkedDays.parameters = {
+ docs: {
+ description: {
+ story:
+ 'A Calendar allows you to pass a callback that returns an array of dates that should be ' +
+ 'marked. This callback provides a starting date and an ending date.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthOnly.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthOnly.stories.tsx
new file mode 100644
index 0000000000000..72a515118ceda
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthOnly.stories.tsx
@@ -0,0 +1,43 @@
+import * as React from 'react';
+import type { JSXElement } from '@fluentui/react-components';
+import { Calendar } from '@fluentui/react-calendar-preview';
+import type { CalendarProps } from '@fluentui/react-calendar-preview';
+
+export const CalendarMonthOnly = (): JSXElement => {
+ const [selectedDateRange, setSelectedDateRange] = React.useState();
+ const [selectedDate, setSelectedDate] = React.useState(null);
+
+ const onSelectDate: NonNullable = React.useCallback((_event, data) => {
+ setSelectedDate(data.date);
+ setSelectedDateRange(data.selectedDateRange);
+ }, []);
+
+ let dateRangeString = 'Not set';
+ if (selectedDateRange) {
+ const rangeStart = selectedDateRange[0];
+ const rangeEnd = selectedDateRange[selectedDateRange.length - 1];
+ dateRangeString = rangeStart.toDateString() + '-' + rangeEnd.toDateString();
+ }
+
+ return (
+ <>
+ Selected date: {selectedDate?.toDateString() || 'Not set'}
+ Selected range: {dateRangeString}
+
+ >
+ );
+};
+
+CalendarMonthOnly.parameters = {
+ docs: {
+ description: {
+ story: 'A Calendar allows you to only show the month and year picker, leaving the day picker hidden.',
+ },
+ },
+};
diff --git a/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthSelection.stories.tsx b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthSelection.stories.tsx
new file mode 100644
index 0000000000000..2373f4344f6c9
--- /dev/null
+++ b/packages/react-components/react-calendar-preview/stories/src/Calendar/CalendarMonthSelection.stories.tsx
@@ -0,0 +1,75 @@
+import * as React from 'react';
+import type { JSXElement } from '@fluentui/react-components';
+import { Calendar, addDays, getDateRange } from '@fluentui/react-calendar-preview';
+import type { CalendarProps } from '@fluentui/react-calendar-preview';
+import { Button, makeStyles } from '@fluentui/react-components';
+
+const useStyles = makeStyles({
+ wrapper: { height: '360px' },
+});
+const dateRangeType = 'month';
+const firstDayOfWeek = 'sunday';
+
+export const CalendarMonthSelection = (): JSXElement => {
+ const styles = useStyles();
+ const [selectedDate, setSelectedDate] = React.useState(null);
+ const selectedDateRange = selectedDate ? getDateRange(selectedDate, dateRangeType, firstDayOfWeek) : undefined;
+
+ const onSelectDate: NonNullable