Skip to content

Commit

Permalink
feat(calendar): implement custom cell content rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
1amageek committed Nov 23, 2024
1 parent 930d4af commit 9fc7840
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 54 deletions.
6 changes: 4 additions & 2 deletions packages/components/calendar/src/calendar-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface CalendarCellProps extends CalendarCellBaseProps, AriaCalendarCe
slots?: CalendarReturnType;
classNames?: SlotsToClasses<CalendarSlots>;
currentMonth: CalendarDate;
cellContent?: (date: CalendarDate) => React.ReactNode;
cellContent?: ((date: CalendarDate) => React.ReactNode) | React.ReactNode;
}

export const CalendarCell = ({
Expand Down Expand Up @@ -95,7 +95,9 @@ export const CalendarCell = ({
return (
<td {...cellProps} className={slots?.cell({class: classNames?.cell})} data-slot="cell">
<CalendarCellProvider value={cellContextValue}>
{cellContent ? cellContent(date) : <CalendarCellContentDefault date={date} />}
{typeof cellContent === "function"
? cellContent(date)
: cellContent ?? <CalendarCellContentDefault date={date} />}
</CalendarCellProvider>
</td>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/components/calendar/src/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface Props<T extends DateValue>
/**
* The calendar cell render function
*/
children?: (date: CalendarDate) => React.ReactNode;
children?: ((date: CalendarDate) => React.ReactNode) | React.ReactNode;
}

function Calendar<T extends DateValue>(props: Props<T>, ref: ForwardedRef<HTMLDivElement>) {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/calendar/src/range-calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface Props<T extends DateValue>
/**
* The calendar cell render function
*/
children?: (date: CalendarDate) => React.ReactNode;
children?: ((date: CalendarDate) => React.ReactNode) | React.ReactNode;
}

function RangeCalendar<T extends DateValue>(props: Props<T>, ref: ForwardedRef<HTMLDivElement>) {
Expand Down
4 changes: 2 additions & 2 deletions packages/components/calendar/src/use-calendar-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ interface Props extends NextUIBaseProps {
* @param cellState The state of the calendar cell
* @returns ReactNode
*/
cellContent?: (date: CalendarDate) => React.ReactNode;
cellContent?: ((date: CalendarDate) => React.ReactNode) | React.ReactNode;
/**
* This function helps to reduce the bundle size by providing a custom calendar system.
*
Expand Down Expand Up @@ -183,7 +183,7 @@ export type ContextType<T extends CalendarState | RangeCalendarState> = {
setIsHeaderExpanded?: (isExpanded: boolean) => void;
classNames?: SlotsToClasses<CalendarSlots>;
disableAnimation?: boolean;
cellContent?: (date: CalendarDate) => React.ReactNode;
cellContent?: ((date: CalendarDate) => React.ReactNode) | React.ReactNode;
};

export function useCalendarBase(originalProps: UseCalendarBasePropsComplete) {
Expand Down
61 changes: 37 additions & 24 deletions packages/components/calendar/stories/calendar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ import {
isWeekend,
startOfWeek,
startOfMonth,
getDayOfWeek,
} from "@internationalized/date";
import {I18nProvider, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/theme";

import {Calendar, CalendarProps, DateValue} from "../src";
import {
Calendar,
CalendarProps,
DateValue,
CalendarCellContent,
CalendarCellButton,
CalendarCellBody,
} from "../src";

export default {
title: "Components/Calendar",
Expand Down Expand Up @@ -258,29 +266,40 @@ const CalendarWidthTemplate = (args: CalendarProps) => {
};

const CustomCellTemplate = (args: CalendarProps) => {
const {locale} = useLocale();

return (
<div className="flex gap-4">
<div className="flex flex-col items-center gap-4">
<Calendar
{...args}
calendarWidth={300}
classNames={{
gridHeaderCell: "w-12",
cell: "h-12",
cellButton: "w-12 h-full rounded-xl",
}}
/>
<Calendar {...args}>
<CalendarCellContent>
<CalendarCellButton />
<CalendarCellBody>
<div className="flex flex-col w-full gap-0.5 justify-center items-center p-0.5">
<span className="bg-red-600 h-1 w-full rounded-full" />
<span className="bg-green-600 h-1 w-full rounded-full" />
<span className="bg-yellow-600 h-1 w-full rounded-full" />
</div>
</CalendarCellBody>
</CalendarCellContent>
</Calendar>
</div>
<div className="flex flex-col items-center gap-4">
<Calendar
{...args}
calendarWidth="30em"
classNames={{
gridHeaderCell: "w-16",
cell: "w-16",
cellButton: "w-16 h-full rounded-xl",
<Calendar {...args}>
{(date) => {
const dayOfWeek = getDayOfWeek(date, locale);
const style =
dayOfWeek === 0 ? "text-red-500" : dayOfWeek === 6 ? "text-blue-500" : "inherit";

return (
<CalendarCellContent>
<CalendarCellButton>
<span className={style}>{date.day}</span>
</CalendarCellButton>
</CalendarCellContent>
);
}}
/>
</Calendar>
</div>
</div>
);
Expand Down Expand Up @@ -409,11 +428,5 @@ export const CustomCellContent = {
render: CustomCellTemplate,
args: {
...defaultProps,
renderCellContent: (date) => (
<div className="flex flex-col gap-0">
{date.day}
<span className="text-tiny text-default-500 text-center"></span>
</div>
),
},
};
60 changes: 36 additions & 24 deletions packages/components/calendar/stories/range-calendar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@ import {
startOfWeek,
endOfMonth,
endOfWeek,
getDayOfWeek,
} from "@internationalized/date";
import {I18nProvider, useLocale} from "@react-aria/i18n";
import {Button, ButtonGroup} from "@nextui-org/button";
import {Radio, RadioGroup} from "@nextui-org/radio";
import {cn} from "@nextui-org/theme";

import {RangeCalendar, RangeCalendarProps} from "../src";
import {
RangeCalendar,
RangeCalendarProps,
CalendarCellContent,
CalendarCellButton,
CalendarCellBody,
} from "../src";

export default {
title: "Components/RangeCalendar",
Expand Down Expand Up @@ -289,29 +296,40 @@ const PresetsTemplate = (args: RangeCalendarProps) => {
};

const CustomCellTemplate = (args: RangeCalendarProps) => {
const {locale} = useLocale();

return (
<div className="flex gap-4">
<div className="flex flex-col items-center gap-4">
<RangeCalendar
{...args}
calendarWidth={300}
classNames={{
gridHeaderCell: "w-12",
cell: "h-12",
cellButton: "w-12 h-full rounded-xl",
}}
/>
<RangeCalendar {...args}>
<CalendarCellContent>
<CalendarCellButton />
<CalendarCellBody>
<div className="flex flex-col w-full gap-0.5 justify-center items-center p-0.5">
<span className="bg-red-600 h-1 w-full rounded-full" />
<span className="bg-green-600 h-1 w-full rounded-full" />
<span className="bg-yellow-600 h-1 w-full rounded-full" />
</div>
</CalendarCellBody>
</CalendarCellContent>
</RangeCalendar>
</div>
<div className="flex flex-col items-center gap-4">
<RangeCalendar
{...args}
calendarWidth="30em"
classNames={{
gridHeaderCell: "w-16",
cell: "w-16",
cellButton: "w-16 h-full rounded-xl",
<RangeCalendar {...args}>
{(date) => {
const dayOfWeek = getDayOfWeek(date, locale);
const style =
dayOfWeek === 0 ? "text-red-500" : dayOfWeek === 6 ? "text-blue-500" : "inherit";

return (
<CalendarCellContent>
<CalendarCellButton>
<span className={style}>{date.day}</span>
</CalendarCellButton>
</CalendarCellContent>
);
}}
/>
</RangeCalendar>
</div>
</div>
);
Expand Down Expand Up @@ -442,11 +460,5 @@ export const CustomCellContent = {
render: CustomCellTemplate,
args: {
...defaultProps,
renderCellContent: (date) => (
<div className="flex flex-col gap-0">
{date.day}
<span className="text-tiny text-default-500 text-center"></span>
</div>
),
},
};

0 comments on commit 9fc7840

Please sign in to comment.