Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
917c452116 | ||
|
|
166c9b6fb9 |
@@ -1,8 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { createClient } from './lib/apollo-client';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
|
||||
import {
|
||||
VegaConnectDialog,
|
||||
@@ -18,8 +16,7 @@ import LocalContext from './context/local-context';
|
||||
import useLocalValues from './hooks/use-local-values';
|
||||
|
||||
function App() {
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
const localValues = useLocalValues(theme, toggleTheme);
|
||||
const localValues = useLocalValues();
|
||||
const {
|
||||
vegaWalletDialog,
|
||||
menu: { setMenuOpen },
|
||||
@@ -32,29 +29,27 @@ function App() {
|
||||
|
||||
return (
|
||||
<EnvironmentProvider>
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<VegaWalletProvider>
|
||||
<LocalContext.Provider value={localValues}>
|
||||
<AppLoader>
|
||||
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
|
||||
<Header />
|
||||
<Main />
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
dialogOpen={vegaWalletDialog.connect}
|
||||
setDialogOpen={vegaWalletDialog.setConnect}
|
||||
/>
|
||||
<VegaManageDialog
|
||||
dialogOpen={vegaWalletDialog.manage}
|
||||
setDialogOpen={vegaWalletDialog.setManage}
|
||||
/>
|
||||
</div>
|
||||
</AppLoader>
|
||||
</LocalContext.Provider>
|
||||
</VegaWalletProvider>
|
||||
</NetworkLoader>
|
||||
</ThemeContext.Provider>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<VegaWalletProvider>
|
||||
<LocalContext.Provider value={localValues}>
|
||||
<AppLoader>
|
||||
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
|
||||
<Header />
|
||||
<Main />
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
dialogOpen={vegaWalletDialog.connect}
|
||||
setDialogOpen={vegaWalletDialog.setConnect}
|
||||
/>
|
||||
<VegaManageDialog
|
||||
dialogOpen={vegaWalletDialog.manage}
|
||||
setDialogOpen={vegaWalletDialog.setManage}
|
||||
/>
|
||||
</div>
|
||||
</AppLoader>
|
||||
</LocalContext.Provider>
|
||||
</VegaWalletProvider>
|
||||
</NetworkLoader>
|
||||
</EnvironmentProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import React, { forwardRef, useCallback, useMemo, useRef } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import { ThemeContext, useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { useScreenDimensions, useTheme } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
GridOptions,
|
||||
GetRowIdParams,
|
||||
@@ -43,7 +37,7 @@ const ConsoleLiteGrid = <T extends { id?: string }>(
|
||||
) => {
|
||||
const { isMobile, screenSize } = useScreenDimensions();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const theme = useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
(
|
||||
(ref as React.RefObject<AgGridReact>) || gridRef
|
||||
|
||||
@@ -16,8 +16,6 @@ interface MenuState {
|
||||
export interface LocalValues {
|
||||
vegaWalletDialog: VegaWalletDialogState;
|
||||
menu: MenuState;
|
||||
theme: 'light' | 'dark';
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
const LocalContext = createContext<LocalValues>({} as LocalValues);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import type { LocalValues } from '../context/local-context';
|
||||
|
||||
const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
|
||||
const useLocalValues = () => {
|
||||
const [connect, setConnect] = useState<boolean>(false);
|
||||
const [manage, setManage] = useState<boolean>(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
@@ -9,10 +9,8 @@ const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
|
||||
() => ({
|
||||
vegaWalletDialog: { connect, manage, setConnect, setManage },
|
||||
menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) },
|
||||
theme,
|
||||
toggleTheme,
|
||||
}),
|
||||
[connect, manage, theme, toggleTheme, menuOpen]
|
||||
[connect, manage, menuOpen]
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useState, useEffect } from 'react';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { BrowserTracing } from '@sentry/tracing';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
EnvironmentProvider,
|
||||
NetworkLoader,
|
||||
@@ -18,7 +17,6 @@ import { ENV } from './config/env';
|
||||
|
||||
function App() {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
const location = useLocation();
|
||||
@@ -37,31 +35,24 @@ function App() {
|
||||
}, [VEGA_ENV]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<TendermintWebsocketProvider>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<div
|
||||
className={`${
|
||||
menuOpen && 'h-[100vh] overflow-hidden'
|
||||
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
|
||||
>
|
||||
<div className="grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-neutral-700 dark:border-neutral-300 lg:border-l lg:border-r mx-auto">
|
||||
<Header
|
||||
theme={theme}
|
||||
toggleTheme={toggleTheme}
|
||||
menuOpen={menuOpen}
|
||||
setMenuOpen={setMenuOpen}
|
||||
/>
|
||||
<Nav menuOpen={menuOpen} />
|
||||
<Main />
|
||||
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-sm md:text-md md:flex md:col-span-2 p-4 gap-4 border-t border-neutral-700 dark:border-neutral-300">
|
||||
<NetworkInfo />
|
||||
</footer>
|
||||
</div>
|
||||
<TendermintWebsocketProvider>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<div
|
||||
className={`${
|
||||
menuOpen && 'h-[100vh] overflow-hidden'
|
||||
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
|
||||
>
|
||||
<div className="grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-neutral-700 dark:border-neutral-300 lg:border-l lg:border-r mx-auto">
|
||||
<Header menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
|
||||
<Nav menuOpen={menuOpen} />
|
||||
<Main />
|
||||
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-sm md:text-md md:flex md:col-span-2 p-4 gap-4 border-t border-neutral-700 dark:border-neutral-300">
|
||||
<NetworkInfo />
|
||||
</footer>
|
||||
</div>
|
||||
</NetworkLoader>
|
||||
</TendermintWebsocketProvider>
|
||||
</ThemeContext.Provider>
|
||||
</div>
|
||||
</NetworkLoader>
|
||||
</TendermintWebsocketProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,18 +8,11 @@ import type { Dispatch, SetStateAction } from 'react';
|
||||
import { NetworkSwitcher } from '@vegaprotocol/environment';
|
||||
|
||||
interface ThemeToggleProps {
|
||||
theme: 'light' | 'dark';
|
||||
toggleTheme: () => void;
|
||||
menuOpen: boolean;
|
||||
setMenuOpen: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const Header = ({
|
||||
theme,
|
||||
toggleTheme,
|
||||
menuOpen,
|
||||
setMenuOpen,
|
||||
}: ThemeToggleProps) => {
|
||||
export const Header = ({ menuOpen, setMenuOpen }: ThemeToggleProps) => {
|
||||
const headerClasses = classnames(
|
||||
'md:col-span-2',
|
||||
'grid grid-rows-2 md:grid-rows-1 grid-cols-[1fr_auto] md:grid-cols-[auto_1fr_auto] items-center',
|
||||
@@ -48,7 +41,7 @@ export const Header = ({
|
||||
<Icon name={menuOpen ? 'cross' : 'menu'} />
|
||||
</button>
|
||||
<Search />
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />
|
||||
<ThemeSwitcher className="-my-4" />
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
+7
-13
@@ -1,24 +1,18 @@
|
||||
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
|
||||
import { Header } from './components/header';
|
||||
import { StatsManager } from '@vegaprotocol/network-stats';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { createClient } from './lib/apollo-client';
|
||||
|
||||
function App() {
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<div className="w-screen min-h-screen grid pb-24 bg-white text-neutral-900 dark:bg-black dark:text-neutral-100">
|
||||
<div className="layout-grid w-screen justify-self-center">
|
||||
<Header theme={theme} toggleTheme={toggleTheme} />
|
||||
<StatsManager className="max-w-3xl px-24" />
|
||||
</div>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<div className="w-screen min-h-screen grid pb-24 bg-white text-neutral-900 dark:bg-black dark:text-neutral-100">
|
||||
<div className="layout-grid w-screen justify-self-center">
|
||||
<Header />
|
||||
<StatsManager className="max-w-3xl px-24" />
|
||||
</div>
|
||||
</NetworkLoader>
|
||||
</ThemeContext.Provider>
|
||||
</div>
|
||||
</NetworkLoader>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import { VegaLogo, ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import { VegaBackgroundVideo } from '../videos';
|
||||
|
||||
interface ThemeToggleProps {
|
||||
theme: 'light' | 'dark';
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
export const Header = ({ theme, toggleTheme }: ThemeToggleProps) => {
|
||||
export const Header = () => {
|
||||
return (
|
||||
<header className="relative overflow-hidden py-8 mb-40 md:mb-64">
|
||||
<VegaBackgroundVideo />
|
||||
|
||||
<div className="relative flex justify-center px-8 dark:bg-black bg-white">
|
||||
<div className="w-full max-w-3xl p-20 flex items-center justify-between">
|
||||
<VegaLogo />
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
|
||||
<ThemeSwitcher />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -8,12 +8,7 @@ import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
|
||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import { Vega } from '../icons/vega';
|
||||
|
||||
interface NavbarProps {
|
||||
theme: 'light' | 'dark';
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
|
||||
export const Navbar = () => {
|
||||
const { marketId, update } = useGlobalStore((store) => ({
|
||||
marketId: store.marketId,
|
||||
update: store.update,
|
||||
@@ -43,7 +38,7 @@ export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
|
||||
))}
|
||||
</nav>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
|
||||
<ThemeSwitcher />
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={(open) => update({ connectDialog: open })}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AppProps } from 'next/app';
|
||||
import Head from 'next/head';
|
||||
import { Navbar } from '../components/navbar';
|
||||
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { VegaConnectDialog, VegaWalletProvider } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
EnvironmentProvider,
|
||||
@@ -29,7 +29,6 @@ function AppBody({ Component, pageProps }: AppProps) {
|
||||
update: store.update,
|
||||
}));
|
||||
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const networkName = envTriggerMapping[VEGA_ENV];
|
||||
@@ -41,13 +40,13 @@ function AppBody({ Component, pageProps }: AppProps) {
|
||||
}, [pageTitle, networkName]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
||||
<AppLoader>
|
||||
<Navbar theme={theme} toggleTheme={toggleTheme} />
|
||||
<Navbar />
|
||||
<main data-testid={pageProps.page}>
|
||||
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
|
||||
<Component {...pageProps} />
|
||||
@@ -67,7 +66,7 @@ function AppBody({ Component, pageProps }: AppProps) {
|
||||
<RiskNoticeDialog />
|
||||
</AppLoader>
|
||||
</div>
|
||||
</ThemeContext.Provider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
} from 'pennant';
|
||||
import { VegaDataSource } from './data-source';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useContext, useMemo, useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useTheme } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
@@ -46,7 +46,7 @@ export const CandlesChartContainer = ({
|
||||
}: CandlesChartContainerProps) => {
|
||||
const client = useApolloClient();
|
||||
const { keypair } = useVegaWallet();
|
||||
const theme = useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
|
||||
const [interval, setInterval] = useState<Interval>(Interval.I15M);
|
||||
const [chartType, setChartType] = useState<ChartType>(ChartType.CANDLE);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import './styles.css';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useThemeWatcher } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
@@ -15,36 +14,12 @@ export const parameters = {
|
||||
};
|
||||
|
||||
export const decorators = [
|
||||
(Story, context) => {
|
||||
// storybook-addon-themes doesnt seem to provide the current selected
|
||||
// theme in context, we need to provid it in JS as some components
|
||||
// rely on it for rendering
|
||||
const [theme, setTheme] = useState(context.parameters.themes.default);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new MutationObserver((mutationList) => {
|
||||
if (mutationList.length) {
|
||||
const body = mutationList[0].target;
|
||||
if (body.classList.contains('dark')) {
|
||||
setTheme('dark');
|
||||
} else {
|
||||
setTheme('light');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, { attributes: true });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
(Story) => {
|
||||
useThemeWatcher();
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%', height: 500 }}>
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<Story />
|
||||
</ThemeContext.Provider>
|
||||
<Story />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -4,18 +4,11 @@ import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
useDataProvider,
|
||||
addDecimal,
|
||||
ThemeContext,
|
||||
getNumberFormat,
|
||||
useTheme,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import dataProvider from './market-depth-provider';
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useContext,
|
||||
} from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import type { MarketData } from '@vegaprotocol/market-list';
|
||||
import type {
|
||||
@@ -36,7 +29,7 @@ const formatMidPrice = (midPrice: string, decimalPlaces: number) =>
|
||||
type DepthData = Pick<DepthChartProps, 'data' | 'midPrice'>;
|
||||
|
||||
export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
const variables = useMemo(() => ({ marketId }), [marketId]);
|
||||
const [depthData, setDepthData] = useState<DepthData | null>(null);
|
||||
const dataRef = useRef<DepthData | null>(null);
|
||||
|
||||
@@ -8,11 +8,10 @@ import {
|
||||
useState,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useContext,
|
||||
} from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { formatNumber, t, ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { formatNumber, t, useTheme } from '@vegaprotocol/react-helpers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { OrderbookRow } from './orderbook-row';
|
||||
import { createRow, getPriceLevel } from './orderbook-data';
|
||||
@@ -107,7 +106,7 @@ export const Orderbook = ({
|
||||
resolution,
|
||||
onResolutionChange,
|
||||
}: OrderbookProps) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
const scrollElement = useRef<HTMLDivElement>(null);
|
||||
// scroll offset for which rendered rows are selected, will change after user will scroll to margin of rendered data
|
||||
const [scrollOffset, setScrollOffset] = useState(0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import './styles.scss';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTheme } from '@vegaprotocol/react-helpers';
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
backgrounds: { disable: true },
|
||||
@@ -16,18 +16,18 @@ export const parameters = {
|
||||
export const decorators = [
|
||||
(Story, context) => {
|
||||
// storybook-addon-themes doesnt seem to provide the current selected
|
||||
// theme in context, we need to provid it in JS as some components
|
||||
// theme in context, we need to provide it in JS as some components
|
||||
// rely on it for rendering
|
||||
const [theme, setTheme] = useState(context.parameters.themes.default);
|
||||
const { toggle } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new MutationObserver((mutationList) => {
|
||||
if (mutationList.length) {
|
||||
const body = mutationList[0].target;
|
||||
if (body.classList.contains('dark')) {
|
||||
setTheme('dark');
|
||||
toggle('dark');
|
||||
} else {
|
||||
setTheme('light');
|
||||
toggle('light');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -37,13 +37,11 @@ export const decorators = [
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
}, [toggle]);
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%', height: 500 }}>
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<Story />
|
||||
</ThemeContext.Provider>
|
||||
<Story />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -5,4 +5,5 @@ export * from './use-network-params';
|
||||
export * from './use-outside-click';
|
||||
export * from './use-resize';
|
||||
export * from './use-screen-dimensions';
|
||||
export * from './use-theme-switcher';
|
||||
export * from './use-theme';
|
||||
export * from './use-theme-watcher';
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { LocalStorage } from '../lib/storage';
|
||||
|
||||
const darkTheme = 'dark';
|
||||
const lightTheme = 'light';
|
||||
type themeVariant = typeof darkTheme | typeof lightTheme;
|
||||
|
||||
const darkThemeCssClass = darkTheme;
|
||||
|
||||
const getCurrentTheme = () => {
|
||||
const theme = LocalStorage.getItem('theme');
|
||||
if (
|
||||
theme === darkTheme ||
|
||||
(!theme &&
|
||||
typeof window !== 'undefined' &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
return darkTheme;
|
||||
}
|
||||
return lightTheme;
|
||||
};
|
||||
|
||||
const toggleTheme = () => {
|
||||
const theme = document.documentElement.classList.contains(darkThemeCssClass)
|
||||
? lightTheme
|
||||
: darkTheme;
|
||||
LocalStorage.setItem('theme', theme);
|
||||
return theme;
|
||||
};
|
||||
|
||||
export function useThemeSwitcher(): [themeVariant, () => void] {
|
||||
const [theme, setTheme] = useState<themeVariant>(lightTheme);
|
||||
useEffect(() => setTheme(getCurrentTheme()), []);
|
||||
useEffect(() => {
|
||||
if (theme === darkTheme) {
|
||||
document.documentElement.classList.add(darkThemeCssClass);
|
||||
} else {
|
||||
document.documentElement.classList.remove(darkThemeCssClass);
|
||||
}
|
||||
}, [theme]);
|
||||
return [theme, () => setTheme(toggleTheme)];
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useTheme } from './use-theme';
|
||||
|
||||
export const useThemeWatcher = () => {
|
||||
// storybook-addon-themes doesnt seem to provide the current selected
|
||||
// theme in context, we need to provide it in JS as some components
|
||||
// rely on it for rendering
|
||||
const { toggle } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new MutationObserver((mutationList) => {
|
||||
if (mutationList.length) {
|
||||
const body = mutationList[0].target as HTMLElement;
|
||||
if (body.classList.contains('dark')) {
|
||||
toggle('dark');
|
||||
} else {
|
||||
toggle('light');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, { attributes: true });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [toggle]);
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import { useEffect } from 'react';
|
||||
import create from 'zustand';
|
||||
import { LocalStorage } from '../lib/storage';
|
||||
|
||||
type ThemeVariant = typeof darkTheme | typeof lightTheme;
|
||||
|
||||
const darkTheme = 'dark';
|
||||
const lightTheme = 'light';
|
||||
const storageKey = 'theme';
|
||||
|
||||
const getCurrentTheme = () => {
|
||||
const theme = LocalStorage.getItem(storageKey);
|
||||
if (
|
||||
theme === darkTheme ||
|
||||
(!theme &&
|
||||
typeof window !== 'undefined' &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
return darkTheme;
|
||||
}
|
||||
return lightTheme;
|
||||
};
|
||||
|
||||
const applyClass = (theme: ThemeVariant) => {
|
||||
if (theme === darkTheme) {
|
||||
document.documentElement.classList.add(darkTheme);
|
||||
} else {
|
||||
document.documentElement.classList.remove(darkTheme);
|
||||
}
|
||||
};
|
||||
|
||||
interface ThemeStore {
|
||||
theme: ThemeVariant;
|
||||
toggle: (theme?: ThemeVariant) => void;
|
||||
}
|
||||
|
||||
export const useThemeStore = create<ThemeStore>((set) => ({
|
||||
theme: lightTheme,
|
||||
toggle: (theme) => {
|
||||
set((curr) => {
|
||||
let newTheme: ThemeVariant;
|
||||
if (theme) {
|
||||
newTheme = theme;
|
||||
} else {
|
||||
newTheme = curr.theme === lightTheme ? darkTheme : lightTheme;
|
||||
}
|
||||
LocalStorage.setItem(storageKey, newTheme);
|
||||
applyClass(newTheme);
|
||||
return { theme: newTheme };
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
export function useTheme() {
|
||||
const { theme, toggle } = useThemeStore();
|
||||
|
||||
useEffect(() => {
|
||||
const storedTheme = getCurrentTheme();
|
||||
toggle(storedTheme);
|
||||
}, [toggle]);
|
||||
|
||||
return { theme, toggle };
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from './hooks';
|
||||
export * from './lib/assets';
|
||||
export * from './lib/context';
|
||||
export * from './lib/determine-id';
|
||||
export * from './lib/format';
|
||||
export * from './lib/generic-data-provider';
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export const ThemeContext = React.createContext<'light' | 'dark'>('dark');
|
||||
@@ -1 +0,0 @@
|
||||
export * from './context';
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { ReactNode, FunctionComponent } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useTheme } from '@vegaprotocol/react-helpers';
|
||||
import 'ag-grid-community/dist/styles/ag-grid.css';
|
||||
|
||||
interface GridProps {
|
||||
@@ -33,7 +32,7 @@ export const AgGridThemed = ({
|
||||
gridRef?: React.ForwardedRef<AgGridReact>;
|
||||
customThemeParams?: string;
|
||||
}) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
const defaultProps = { rowHeight: 22, headerHeight: 22 };
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import 'ag-grid-community/dist/styles/ag-grid.css';
|
||||
import { useTheme } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const AgGridLightTheme = React.lazy(() =>
|
||||
import('./ag-grid-light').then((module) => ({
|
||||
@@ -23,7 +23,7 @@ export const AgGridThemed = React.forwardRef<
|
||||
className?: string;
|
||||
}
|
||||
>(({ style, className, ...props }, ref) => {
|
||||
const theme = React.useContext(ThemeContext);
|
||||
const { theme } = useTheme();
|
||||
return (
|
||||
<div
|
||||
className={`${className ?? ''} ${
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import { useTheme } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { SunIcon, MoonIcon } from './icons';
|
||||
|
||||
export const ThemeSwitcher = ({
|
||||
theme,
|
||||
onToggle,
|
||||
className,
|
||||
}: {
|
||||
theme: 'light' | 'dark';
|
||||
onToggle: () => void;
|
||||
className?: string;
|
||||
}) => {
|
||||
export const ThemeSwitcher = ({ className }: { className?: string }) => {
|
||||
const { theme, toggle } = useTheme();
|
||||
const classes = 'text-neutral-800 dark:text-neutral-300';
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onToggle()}
|
||||
onClick={() => toggle()}
|
||||
className={className}
|
||||
data-testid="theme-switcher"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user