import React from "react"; import { ChakraProvider, Box, css as resolveCSS, extendTheme, useColorMode, useTheme, } from "@chakra-ui/react"; import { mode } from "@chakra-ui/theme-tools"; import { ApolloProvider } from "@apollo/client"; import { BrowserRouter } from "react-router-dom"; import { css, Global } from "@emotion/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import apolloClient from "./apolloClient"; const reactQueryClient = new QueryClient(); let theme = extendTheme({ styles: { global: (props) => ({ body: { background: mode("gray.50", "gray.800")(props), color: mode("green.800", "green.50")(props), transition: "all 0.25s", }, }), }, }); // Capture the global styles function from our theme, but remove it from the // theme's `styles.global` key. We don't actually want to apply these styles // globally, because they conflict with the app's other styles when embedded in // e.g. the item page! We'll apply them more carefully in `ScopedCSSReset`. // // NOTE: We get this from `theme`, instead of just declaring the function // separately, because `extendTheme` returns a wrapped version of our function // that also returns some of Chakra's own default global styles. const globalStyles = theme.styles.global; theme.styles.global = {}; export default function AppProvider({ children }) { return ( {children} ); } /** * ScopedCSSReset applies a copy of Chakra UI's CSS reset, but only to its * children (or, well, any element with the chakra-css-reset class). It also * applies to .chakra-portal elements mounted by components. * * We also apply some base styles, like the default text color. * * NOTE: We use the `:where` CSS selector, instead of the .chakra-css-reset * selector directly, to avoid specificity conflicts. e.g. the selector * `.chakra-css-reset h1` is considered MORE specific than `.my-h1`, whereas * the selector `:where(.chakra-css-reset) h1` is lower specificity. */ function ScopedCSSReset({ children }) { // Get the current theme and color mode. // // NOTE: The theme object returned by `useTheme` has some extensions that are // necessary for the code below, but aren't present in the theme config // returned by `extendTheme`! That's why we use this here instead of `theme`. const liveTheme = useTheme(); const colorMode = useColorMode(); // Resolve the theme's global styles into CSS objects for Emotion. const globalStylesCSS = resolveCSS( globalStyles({ theme: liveTheme, colorMode }), )(liveTheme); // Prepend our special scope selector to the global styles. const scopedGlobalStylesCSS = {}; for (let [selector, rules] of Object.entries(globalStylesCSS)) { // The `body` selector is where typography etc rules go, but `body` isn't // actually *inside* our scoped element! Instead, ignore the `body` part, // and just apply it to the scoping element itself. if (selector.trim() === "body") { selector = ""; } const scopedSelector = ":where(.chakra-css-reset, .chakra-portal) " + selector; scopedGlobalStylesCSS[scopedSelector] = rules; } return ( <> {children} ); }