diff --git a/example/src/App.tsx b/example/src/App.tsx index 54d992f4..7541577f 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,64 +1,25 @@ -import { - DarkTheme, - DefaultTheme, - NavigationContainer -} from "@react-navigation/native"; import * as React from "react"; import { IODSExperimentalContextProvider, - IOStyles, - IOThemeContext, - IOThemeDark, - IOThemeLight, - IOThemes, + IOThemeContextProvider, ToastProvider } from "@pagopa/io-app-design-system"; import { useColorScheme } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import AppNavigator from "./navigation/navigator"; -const IONavigationDarkTheme = { - ...DarkTheme, - colors: { - ...DarkTheme.colors, - background: IOThemeDark["appBackground-primary"], - card: IOThemeDark["appBackground-primary"] - } -}; - -const IONavigationLightTheme = { - ...DefaultTheme, - colors: { - ...DefaultTheme.colors, - background: IOThemeLight["appBackground-primary"], - card: IOThemeLight["appBackground-primary"] - } -}; - export default function App() { const colorScheme = useColorScheme(); return ( - + - - - - - + - + ); } diff --git a/example/src/components/IconViewerBox.tsx b/example/src/components/IconViewerBox.tsx index a0ba6d8b..882f230b 100644 --- a/example/src/components/IconViewerBox.tsx +++ b/example/src/components/IconViewerBox.tsx @@ -1,5 +1,5 @@ -import { IOColors, IOThemeContext } from "@pagopa/io-app-design-system"; -import React, { useContext } from "react"; +import { IOColors, useIOTheme } from "@pagopa/io-app-design-system"; +import React from "react"; import { StyleSheet, Text, View } from "react-native"; export const iconItemGutter = 8; @@ -92,7 +92,7 @@ export const IconViewerBox = ({ size, withDot = false }: IconViewerBoxProps) => { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return ( { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return ( { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return ( <> {orientation === "vertical" ? ( diff --git a/example/src/navigation/navigator.tsx b/example/src/navigation/navigator.tsx index 43bd9cdb..e57f423c 100644 --- a/example/src/navigation/navigator.tsx +++ b/example/src/navigation/navigator.tsx @@ -1,6 +1,19 @@ -import { HeaderSecondLevel, ModalBSHeader } from "@pagopa/io-app-design-system"; +import { + HeaderSecondLevel, + ModalBSHeader, + IOStyles, + IOThemeDark, + IOThemeLight, + useIOThemeContext +} from "@pagopa/io-app-design-system"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import React from "react"; +import { + DarkTheme, + DefaultTheme, + NavigationContainer +} from "@react-navigation/native"; +import { GestureHandlerRootView } from "react-native-gesture-handler"; import { Accordion } from "../pages/Accordion"; import { DSAdvice } from "../pages/Advice"; import { DSAlert } from "../pages/Alert"; @@ -38,357 +51,388 @@ import { Typography } from "../pages/Typography"; import { AppParamsList } from "./params"; import APP_ROUTES from "./routes"; +const IONavigationDarkTheme = { + ...DarkTheme, + colors: { + ...DarkTheme.colors, + background: IOThemeDark["appBackground-primary"], + card: IOThemeDark["appBackground-primary"] + } +}; + +const IONavigationLightTheme = { + ...DefaultTheme, + colors: { + ...DefaultTheme.colors, + background: IOThemeLight["appBackground-primary"], + card: IOThemeLight["appBackground-primary"] + } +}; + const Stack = createNativeStackNavigator(); -const AppNavigator = () => ( - - - - - - - - - - - - - - - - - - - - - +const AppNavigator = () => { + const { themeType } = useIOThemeContext(); + return ( + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - ( - { - navigation.goBack(); - }, - accessibilityLabel: "" + + ( + { + navigation.goBack(); + }, + accessibilityLabel: "" + }} + /> + ) }} /> - ) - }} - /> - ( - ( + + ) + }} /> - ) - }} - /> - - -); + + + + + ); +}; export default AppNavigator; diff --git a/example/src/pages/Icons.tsx b/example/src/pages/Icons.tsx index 122d73d8..90a8d7e3 100644 --- a/example/src/pages/Icons.tsx +++ b/example/src/pages/Icons.tsx @@ -12,14 +12,14 @@ import { IOProductIcons, IOStyles, IOSystemIcons, - IOThemeContext, IOVisualCostants, Icon, IconContained, SVGIconProps, - IOIconsNew + IOIconsNew, + useIOTheme } from "@pagopa/io-app-design-system"; -import React, { useContext } from "react"; +import React from "react"; import { StyleSheet, View } from "react-native"; import { IconViewerBox, iconItemGutter } from "../components/IconViewerBox"; import { Screen } from "../components/Screen"; @@ -80,7 +80,7 @@ const styles = StyleSheet.create({ }); export const Icons = () => { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return ( diff --git a/example/src/pages/Layout.tsx b/example/src/pages/Layout.tsx index a0017bec..d0c632f0 100644 --- a/example/src/pages/Layout.tsx +++ b/example/src/pages/Layout.tsx @@ -8,19 +8,19 @@ import { IOAppMargin, IOColors, IOSpacer, - IOThemeContext, IOVisualCostants, LabelSmall, VDivider, - VSpacer + VSpacer, + useIOTheme } from "@pagopa/io-app-design-system"; -import React, { useContext } from "react"; +import React from "react"; import { StatusBar, View } from "react-native"; import { NoMarginScreen } from "../components/Screen"; import { SpacerViewerBox } from "../components/SpacerViewerBox"; export const Layout = () => { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return ( diff --git a/example/src/pages/ListItem.tsx b/example/src/pages/ListItem.tsx index fbca315a..f9d39bde 100644 --- a/example/src/pages/ListItem.tsx +++ b/example/src/pages/ListItem.tsx @@ -1,7 +1,6 @@ import { Divider, H2, - IOThemeContext, Icon, ListItemAction, ListItemAmount, @@ -16,7 +15,8 @@ import { ListItemTransactionLogo, ListItemTransactionStatusWithBadge, VSpacer, - useIOExperimentalDesign + useIOExperimentalDesign, + useIOTheme } from "@pagopa/io-app-design-system"; import * as React from "react"; import { Alert, View } from "react-native"; @@ -29,89 +29,86 @@ const onButtonPress = () => { export const ListItems = () => { const { isExperimental, setExperimental } = useIOExperimentalDesign(); + const theme = useIOTheme(); return ( - - {theme => ( - -

- ListItemNav -

- - {renderListItemNav()} - -

- ListItemInfoCopy -

- {renderListItemInfoCopy()} - -

- ListItemInfo -

- {renderListItemInfo()} - -

- ListItemHeader -

- {renderListItemHeader()} - -

- ListItemAmount -

- {renderListItemAmount()} - -

- ListItemAction -

- {renderListItemAction()} - -

- ListItemTransaction -

- {renderListItemTransaction()} -

- ListItemRadioWithAmount -

- {renderListItemRadioWithAmount()} - -
- )} -
+ +

+ ListItemNav +

+ + {renderListItemNav()} + +

+ ListItemInfoCopy +

+ {renderListItemInfoCopy()} + +

+ ListItemInfo +

+ {renderListItemInfo()} + +

+ ListItemHeader +

+ {renderListItemHeader()} + +

+ ListItemAmount +

+ {renderListItemAmount()} + +

+ ListItemAction +

+ {renderListItemAction()} + +

+ ListItemTransaction +

+ {renderListItemTransaction()} +

+ ListItemRadioWithAmount +

+ {renderListItemRadioWithAmount()} + +
); }; diff --git a/example/src/pages/MainScreen.tsx b/example/src/pages/MainScreen.tsx index 494cbb91..dbad4c2d 100644 --- a/example/src/pages/MainScreen.tsx +++ b/example/src/pages/MainScreen.tsx @@ -2,14 +2,14 @@ import { SectionList, View } from "react-native"; import * as React from "react"; import { IOStyles, - useIOTheme, Divider, H1, LabelSmall, VSpacer, ListItemNav, useIOExperimentalDesign, - ListItemSwitch + ListItemSwitch, + useIOThemeContext } from "@pagopa/io-app-design-system"; import APP_ROUTES from "../navigation/routes"; import { AppParamsList } from "../navigation/params"; @@ -55,7 +55,7 @@ const DESIGN_SYSTEM_SECTION_DATA = [ ]; const MainScreen = (props: Props) => { - const theme = useIOTheme(); + const { setTheme, themeType, theme } = useIOThemeContext(); const { isExperimental, setExperimental } = useIOExperimentalDesign(); const renderDSNavItem = ({ item: { title, route } @@ -96,6 +96,14 @@ const MainScreen = (props: Props) => { onSwitchValueChange={setExperimental} /> + + setTheme(themeType === "dark" ? "light" : "dark") + } + /> +
`${item.route}-${index}`} diff --git a/example/src/pages/Modules.tsx b/example/src/pages/Modules.tsx index 92ac3235..0b730406 100644 --- a/example/src/pages/Modules.tsx +++ b/example/src/pages/Modules.tsx @@ -1,13 +1,13 @@ import * as React from "react"; import { useIOExperimentalDesign, - IOThemeContext, ListItemSwitch, H2, ModuleIDP, ModuleAttachment, ModulePaymentNotice, - ModuleCheckout + ModuleCheckout, + useIOTheme } from "@pagopa/io-app-design-system"; import { Alert, ImageSourcePropType, View } from "react-native"; import { Screen } from "../components/Screen"; @@ -189,50 +189,47 @@ const renderModuleAttachment = () => ( const Modules = () => { const { isExperimental, setExperimental } = useIOExperimentalDesign(); + const theme = useIOTheme(); return ( - - {theme => ( - - -

- ModuleIDP -

- {renderModuleIDP()} -

- ModulePaymentNotice -

- {renderModulePaymentNotice()} -

- ModuleCheckout -

- {renderModuleCheckout()} -

- ModuleAttachment -

- {renderModuleAttachment()} -
- )} -
+ + +

+ ModuleIDP +

+ {renderModuleIDP()} +

+ ModulePaymentNotice +

+ {renderModulePaymentNotice()} +

+ ModuleCheckout +

+ {renderModuleCheckout()} +

+ ModuleAttachment +

+ {renderModuleAttachment()} +
); }; diff --git a/example/src/pages/Pictograms.tsx b/example/src/pages/Pictograms.tsx index 116031d7..11a90055 100644 --- a/example/src/pages/Pictograms.tsx +++ b/example/src/pages/Pictograms.tsx @@ -6,15 +6,14 @@ import { IOPictogramsBleed, IOPictogramsLegacy, IOPictogramsObject, - IOThemeContext, IOVisualCostants, Pictogram, PictogramBleed, SVGPictogramProps, - hexToRgba + hexToRgba, + useIOTheme } from "@pagopa/io-app-design-system"; import * as React from "react"; -import { useContext } from "react"; import { StyleSheet, View } from "react-native"; import { AssetViewerBox, assetItemGutter } from "../components/AssetViewerBox"; import { ComponentViewerBox } from "../components/ComponentViewerBox"; @@ -73,7 +72,7 @@ const sortedIOPictogramsObject = sortPictogramSet(IOPictogramsObject); const sortedIOPictogramsLegacy = sortPictogramSet(IOPictogramsLegacy); export const Pictograms = () => { - const theme = useContext(IOThemeContext); + const theme = useIOTheme(); return (

{ - const theme = React.useContext(IOThemeContext); + const theme = useIOTheme(); const baseStyle = { backgroundColor: IOColors[theme["divider-default"]], ...(orientation === "vertical" diff --git a/src/components/pictograms/Pictogram.tsx b/src/components/pictograms/Pictogram.tsx index 87c9329e..1c6299ca 100644 --- a/src/components/pictograms/Pictogram.tsx +++ b/src/components/pictograms/Pictogram.tsx @@ -1,11 +1,6 @@ import React, { useMemo } from "react"; import { ColorValue } from "react-native"; -import { - IOColors, - IOThemeDark, - IOThemeLight, - useIOTheme -} from "../../core/IOColors"; +import { IOColors, IOThemeDark, IOThemeLight, useIOTheme } from "../../core"; import PictogramAbacus from "./svg/PictogramAbacus"; import PictogramAccessDenied from "./svg/PictogramAccessDenied"; diff --git a/src/core/IOColors.ts b/src/core/IOColors.ts index 42081d3b..b781ef71 100644 --- a/src/core/IOColors.ts +++ b/src/core/IOColors.ts @@ -1,6 +1,5 @@ import type { ComponentProps } from "react"; -import * as React from "react"; -import { Appearance, ColorValue } from "react-native"; +import { ColorValue } from "react-native"; import type LinearGradient from "react-native-linear-gradient"; // Used by `getGradientColorValues` function /* @@ -400,15 +399,6 @@ export const themeStatusColorsDarkMode: Record< export type themeStatusColorsDarkMode = keyof typeof themeStatusColorsDarkMode; -/* -THEME CONTEXT -*/ -export const IOThemes = { light: IOThemeLight, dark: IOThemeDark }; -export const IOThemeContext: React.Context = React.createContext( - Appearance.getColorScheme() === "dark" ? IOThemes.dark : IOThemes.light -); -export const useIOTheme = () => React.useContext(IOThemeContext); - /* UTILS */ diff --git a/src/core/IOThemeContextProvider.tsx b/src/core/IOThemeContextProvider.tsx new file mode 100644 index 00000000..1cea23e3 --- /dev/null +++ b/src/core/IOThemeContextProvider.tsx @@ -0,0 +1,50 @@ +import { constVoid } from "fp-ts/function"; +import React from "react"; +import { Appearance } from "react-native"; +import { IOTheme, IOThemeDark, IOThemeLight } from "./IOColors"; + +export const IOThemes = { light: IOThemeLight, dark: IOThemeDark }; +type IOThemeType = keyof typeof IOThemes; + +type IOThemeContextType = { + themeType: IOThemeType; + theme: IOTheme; + setTheme: (theme: IOThemeType) => void; +}; + +export const IOThemeContext: React.Context = + React.createContext({ + themeType: Appearance.getColorScheme() === "dark" ? "dark" : "light", + theme: + Appearance.getColorScheme() === "dark" ? IOThemes.dark : IOThemes.light, + setTheme: constVoid + }); + +export const useIOThemeContext = () => React.useContext(IOThemeContext); + +export const useIOTheme = () => useIOThemeContext().theme; + +type IOThemeContextProviderProps = { + theme?: IOThemeType; +}; + +export const IOThemeContextProvider = ({ + children, + theme +}: React.PropsWithChildren) => { + const [currentTheme, setCurrentTheme] = React.useState( + theme ?? "light" + ); + + return ( + + {children} + + ); +}; diff --git a/src/core/index.ts b/src/core/index.ts index 94287494..de156d49 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -6,3 +6,4 @@ export * from "./IOShapes"; export * from "./IOSpacing"; export * from "./IOStyleVariables"; export * from "./IODSExperimentalContextProvider"; +export * from "./IOThemeContextProvider"; diff --git a/stories/utils.tsx b/stories/utils.tsx index f803c5fa..b793be47 100644 --- a/stories/utils.tsx +++ b/stories/utils.tsx @@ -6,8 +6,7 @@ import { View } from "react-native"; import { IOColors, IODSExperimentalContextProvider, - IOThemeContext, - IOThemes, + IOThemeContextProvider, hexToRgba } from "../src/core"; import { EXPERIMENTAL_DS_PARAM_KEY } from "./addons/ExperimentalDsToggle"; @@ -15,14 +14,14 @@ import { EXPERIMENTAL_DS_PARAM_KEY } from "./addons/ExperimentalDsToggle"; export const withTheme: Decorator = (StoryFn, context) => { const themeContext = context.globals.backgrounds && context.globals.backgrounds.value === "black" - ? IOThemes.dark - : IOThemes.light; + ? "dark" + : "light"; // console.log("context", context); return ( - + - + ); };