Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure darkmode with props #28

Merged
merged 5 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eighty-papayas-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@marceloterreiro/flash-calendar": patch
---

- Add an optional `calendarColorScheme` prop that enables overriding the color scheme used by Flash Calendar.
34 changes: 33 additions & 1 deletion apps/docs/docs/fundamentals/tips-and-tricks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ export function ImperativeScrolling() {

## Setting Border Radius to `Calendar.Item.Day`

To apply a border radius to the `Calendar.Item.Day` component, it's necessary to specify the radius for all four corners. Here's an example of how to achieve this:
To apply a border radius to the `Calendar.Item.Day` component, it's necessary to
specify the radius for all four corners. Here's an example of how to achieve
this:

```tsx
itemDay: {
Expand All @@ -123,3 +125,33 @@ itemDay: {
}),
}
```

## Avoiding dark mode

If your app doesn't support dynamic themes, you can override Flash Calendar's
color scheme by passing a `calendarColorScheme` prop:

```tsx
export const LightModeOnly = () => {
const { calendarActiveDateRanges, onCalendarDayPress } = useDateRange({
startId: "2024-02-04",
endId: "2024-02-09",
});

return (
<Calendar
calendarActiveDateRanges={calendarActiveDateRanges}
calendarColorScheme="light"
calendarMonthId={toDateId(startOfThisMonth)}
onCalendarDayPress={onCalendarDayPress}
/>
);
};
```

When set, Flash Calendar's theming system will use this scheme instead of the
user system's theme.

**Note**: you should avoid using this prop. Instead, your app should
support dynamic themes that react to the user's system preferences. The prop is
provided as an escape hatch for apps that doesn't support dynamic themes yet.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { memo, useEffect } from "react";
import { Text } from "react-native";
import { uppercaseFirstLetter } from "@/helpers/strings";

import { useRenderCount } from "./useRenderCount";
import { PerfTestCalendarItemDayWithContainer } from "./PerfTestCalendarItemDay";
import { useRenderCount } from "./useRenderCount";

const BasePerfTestCalendar = memo(
({
Expand Down
22 changes: 22 additions & 0 deletions packages/flash-calendar/src/components/Calendar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,25 @@ export const DateRangePicker = (args: typeof KichenSink.args) => {
/>
);
};

export const ControlledColorScheme: StoryObj<typeof Calendar> = {
args: {
calendarColorScheme: "dark",
},
};

export const LightModeOnly = () => {
const { calendarActiveDateRanges, onCalendarDayPress } = useDateRange({
startId: "2024-02-04",
endId: "2024-02-09",
});

return (
<Calendar
calendarActiveDateRanges={calendarActiveDateRanges}
calendarColorScheme="light"
calendarMonthId={toDateId(startOfThisMonth)}
onCalendarDayPress={onCalendarDayPress}
/>
);
};
25 changes: 23 additions & 2 deletions packages/flash-calendar/src/components/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { memo, useEffect } from "react";
import type { ColorSchemeName } from "react-native";

import type {
CalendarItemDayContainerProps,
Expand All @@ -22,6 +23,7 @@ import type { BaseTheme } from "@/helpers/tokens";
import type { UseCalendarParams } from "@/hooks/useCalendar";
import { useCalendar } from "@/hooks/useCalendar";
import { activeDateRangesEmitter } from "@/hooks/useOptimizedDayMetadata";
import { CalendarThemeProvider } from "@/components/CalendarThemeProvider";

export interface CalendarTheme {
rowMonth?: CalendarRowMonthProps["theme"];
Expand Down Expand Up @@ -66,6 +68,16 @@ export interface CalendarProps extends UseCalendarParams {
* @defaultValue 20
*/
calendarMonthHeaderHeight?: number;
/**
* When set, Flash Calendar will use this color scheme instead of the system's
* value (`light|dark`). This is useful if your app doesn't support dark-mode,
* for example.
*
* We don't advise using this prop - ideally, your app should reflect the
* user's preferences.
* @defaultValue undefined
*/
calendarColorScheme?: ColorSchemeName;
/** Theme to customize the calendar component. */
theme?: CalendarTheme;
}
Expand Down Expand Up @@ -150,7 +162,12 @@ const BaseCalendar = memo(
BaseCalendar.displayName = "BaseCalendar";

export const Calendar = memo(
({ calendarActiveDateRanges, calendarMonthId, ...props }: CalendarProps) => {
({
calendarActiveDateRanges,
calendarMonthId,
calendarColorScheme,
...props
}: CalendarProps) => {
useEffect(() => {
activeDateRangesEmitter.emit(
"onSetActiveDateRanges",
Expand All @@ -168,7 +185,11 @@ export const Calendar = memo(
*/
}, [calendarActiveDateRanges, calendarMonthId]);

return <BaseCalendar {...props} calendarMonthId={calendarMonthId} />;
return (
<CalendarThemeProvider colorScheme={calendarColorScheme}>
<BaseCalendar {...props} calendarMonthId={calendarMonthId} />
</CalendarThemeProvider>
);
}
);

Expand Down
13 changes: 8 additions & 5 deletions packages/flash-calendar/src/components/CalendarList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export const CalendarList = memo(
calendarAdditionalHeight = 0,

// Other props
calendarColorScheme,
theme,
onEndReached,
...props
Expand All @@ -137,20 +138,21 @@ export const CalendarList = memo(

const calendarProps = useMemo(
(): CalendarMonthEnhanced["calendarProps"] => ({
calendarColorScheme,
calendarActiveDateRanges,
calendarDayHeight,
calendarDisabledDateIds,
calendarFirstDayOfWeek,
getCalendarDayFormat,
getCalendarWeekDayFormat,
calendarFormatLocale,
calendarMaxDateId,
calendarMinDateId,
calendarFormatLocale,
calendarMonthHeaderHeight,
calendarRowHorizontalSpacing,
getCalendarMonthFormat,
calendarRowVerticalSpacing,
calendarWeekHeaderHeight,
calendarDisabledDateIds,
getCalendarDayFormat,
getCalendarMonthFormat,
getCalendarWeekDayFormat,
onCalendarDayPress,
theme,
}),
Expand All @@ -169,6 +171,7 @@ export const CalendarList = memo(
calendarRowVerticalSpacing,
calendarWeekHeaderHeight,
calendarDisabledDateIds,
calendarColorScheme,
onCalendarDayPress,
theme,
]
Expand Down
43 changes: 43 additions & 0 deletions packages/flash-calendar/src/components/CalendarThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { ReactNode } from "react";
import { createContext, useContext, useMemo } from "react";
import type { ColorSchemeName } from "react-native";

export interface CalendarThemeContextType {
colorScheme?: ColorSchemeName;
}

const CalendarThemeContext = createContext<CalendarThemeContextType>({
colorScheme: undefined,
});

export const CalendarThemeProvider = ({
children,
colorScheme,
}: {
children: ReactNode;
/**
* When set, Flash Calendar will use this color scheme instead of the system's
* value (`light|dark`). This is useful if your app doesn't support dark-mode,
* for example.
*
* We don't advise using this prop - ideally, your app should reflect the
* user's preferences.
*/
colorScheme?: ColorSchemeName;
}) => {
const calendarThemeContextValue = useMemo<CalendarThemeContextType>(
() => ({ colorScheme }),
[colorScheme]
);

return (
<CalendarThemeContext.Provider value={calendarThemeContextValue}>
{children}
</CalendarThemeContext.Provider>
);
};

export const useCalendarTheme = () => {
const context = useContext(CalendarThemeContext);
return context;
};
7 changes: 6 additions & 1 deletion packages/flash-calendar/src/hooks/useTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import { useColorScheme } from "react-native";

import type { BaseTheme } from "@/helpers/tokens";
import { darkTheme, lightTheme } from "@/helpers/tokens";
import { useCalendarTheme } from "@/components/CalendarThemeProvider";

export const useTheme = (): BaseTheme => {
const appearance = useColorScheme();
return appearance === "dark" ? darkTheme : lightTheme;
const { colorScheme } = useCalendarTheme();

const theme = colorScheme ?? appearance;

return theme === "dark" ? darkTheme : lightTheme;
};
Loading