chore(trading): split bottom panel into two parts (#3205)

This commit is contained in:
Maciek 2023-03-17 10:50:43 +01:00 committed by GitHub
parent 300019f108
commit 84795b2d6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 323 additions and 187 deletions

View File

@ -10,7 +10,7 @@ export const Footer = () => {
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false); const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
const { screenSize } = useScreenDimensions(); const { screenSize } = useScreenDimensions();
const showFullFeedbackLabel = useMemo( const showFullFeedbackLabel = useMemo(
() => ['lg', 'xl'].includes(screenSize), () => ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
[screenSize] [screenSize]
); );

View File

@ -216,6 +216,60 @@ describe('Market trading page', () => {
}); });
}); });
}); });
describe('market bottom panel', { tags: '@smoke' }, () => {
it('on xxl screen should be splitted out into two tables', () => {
cy.getByTestId('tab-positions').should(
'have.attr',
'data-state',
'active'
);
cy.getByTestId('tab-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-accounts').should(
'have.attr',
'data-state',
'inactive'
);
cy.viewport(1801, 1000);
cy.getByTestId('tab-positions').should(
'have.attr',
'data-state',
'active'
);
cy.getByTestId('tab-orders').should('have.attr', 'data-state', 'active');
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'inactive');
cy.getByTestId('tab-accounts').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('Fills').click();
cy.getByTestId('Collateral').click();
cy.getByTestId('tab-positions').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-orders').should(
'have.attr',
'data-state',
'inactive'
);
cy.getByTestId('tab-fills').should('have.attr', 'data-state', 'active');
cy.getByTestId('tab-accounts').should(
'have.attr',
'data-state',
'active'
);
});
});
}); });
describe('market states not accepting orders', { tags: '@smoke' }, function () { describe('market states not accepting orders', { tags: '@smoke' }, function () {

View File

@ -1,9 +1,9 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo } from 'react';
import debounce from 'lodash/debounce';
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils'; import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { import {
useDataProvider, useDataProvider,
useScreenDimensions,
useThrottledDataProvider, useThrottledDataProvider,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
@ -61,7 +61,8 @@ export const MarketPage = () => {
const { marketId } = useParams(); const { marketId } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const { w } = useWindowSize(); const { screenSize } = useScreenDimensions();
const largeScreen = ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize);
const update = useGlobalStore((store) => store.update); const update = useGlobalStore((store) => store.update);
const lastMarketId = useGlobalStore((store) => store.marketId); const lastMarketId = useGlobalStore((store) => store.marketId);
@ -87,7 +88,7 @@ export const MarketPage = () => {
}, [update, lastMarketId, data?.id]); }, [update, lastMarketId, data?.id]);
const tradeView = useMemo(() => { const tradeView = useMemo(() => {
if (w > 960) { if (largeScreen) {
return ( return (
<TradeGrid <TradeGrid
market={data} market={data}
@ -105,7 +106,7 @@ export const MarketPage = () => {
onClickCollateral={() => navigate('/portfolio')} onClickCollateral={() => navigate('/portfolio')}
/> />
); );
}, [w, data, onSelect, navigate]); }, [largeScreen, data, onSelect, navigate]);
if (!data && marketId) { if (!data && marketId) {
return ( return (
<Splash> <Splash>
@ -140,37 +141,3 @@ export const MarketPage = () => {
</AsyncRenderer> </AsyncRenderer>
); );
}; };
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState(() => {
if (typeof window !== 'undefined') {
return {
w: window.innerWidth,
h: window.innerHeight,
};
}
// Something sensible for server rendered page
return {
w: 1200,
h: 900,
};
});
useEffect(() => {
const handleResize = debounce(({ target }) => {
setWindowSize({
w: target.innerWidth,
h: target.innerHeight,
});
}, 300);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return windowSize;
};

View File

@ -8,7 +8,7 @@ import { TradesContainer } from '@vegaprotocol/trades';
import { LayoutPriority } from 'allotment'; import { LayoutPriority } from 'allotment';
import classNames from 'classnames'; import classNames from 'classnames';
import AutoSizer from 'react-virtualized-auto-sizer'; import AutoSizer from 'react-virtualized-auto-sizer';
import { memo, useState } from 'react'; import { memo, useCallback, useState } from 'react';
import type { ReactNode, ComponentProps } from 'react'; import type { ReactNode, ComponentProps } from 'react';
import { DepthChartContainer } from '@vegaprotocol/market-depth'; import { DepthChartContainer } from '@vegaprotocol/market-depth';
import { CandlesChartContainer } from '@vegaprotocol/candles-chart'; import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
@ -29,6 +29,7 @@ import { LiquidityContainer } from '../liquidity/liquidity';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Links, Routes } from '../../pages/client-router'; import { Links, Routes } from '../../pages/client-router';
import type { PinnedAsset } from '@vegaprotocol/accounts'; import type { PinnedAsset } from '@vegaprotocol/accounts';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
type MarketDependantView = type MarketDependantView =
| typeof CandlesChartContainer | typeof CandlesChartContainer
@ -69,129 +70,204 @@ interface TradeGridProps {
pinnedAsset?: PinnedAsset; pinnedAsset?: PinnedAsset;
} }
const MainGrid = ({ interface BottomPanelProps {
marketId,
onSelect,
pinnedAsset,
}: {
marketId: string; marketId: string;
onSelect?: (marketId: string) => void;
pinnedAsset?: PinnedAsset; pinnedAsset?: PinnedAsset;
}) => { }
const navigate = useNavigate();
const onMarketClick = (marketId: string) => { const MarketBottomPanel = memo(
navigate(Links[Routes.MARKET](marketId), { ({ marketId, pinnedAsset }: BottomPanelProps) => {
replace: true, const { screenSize } = useScreenDimensions();
}); const navigate = useNavigate();
}; const onMarketClick = useCallback(
return ( (marketId: string) => {
<ResizableGrid vertical> navigate(Links[Routes.MARKET](marketId), {
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}> replace: true,
<ResizableGrid proportionalLayout={false} minSize={200}> });
<ResizableGridPanel },
priority={LayoutPriority.High} [navigate]
minSize={200} );
preferredSize="50%"
> return 'xxxl' === screenSize ? (
<TradeGridChild> <ResizableGrid proportionalLayout minSize={200}>
<Tabs> <ResizableGridPanel
<Tab id="chart" name={t('Chart')}> priority={LayoutPriority.Low}
<TradingViews.Candles marketId={marketId} /> preferredSize="50%"
</Tab> minSize={50}
<Tab id="depth" name={t('Depth')}> >
<TradingViews.Depth marketId={marketId} /> <TradeGridChild>
</Tab> <Tabs>
<Tab id="liquidity" name={t('Liquidity')}> <Tab id="orders" name={t('Orders')}>
<TradingViews.Liquidity marketId={marketId} /> <VegaWalletContainer>
</Tab> <TradingViews.Orders
</Tabs>
</TradeGridChild>
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={330}
minSize={300}
>
<TradeGridChild>
<Tabs>
<Tab id="ticket" name={t('Ticket')}>
<TradingViews.Ticket
marketId={marketId} marketId={marketId}
onClickCollateral={() => navigate('/portfolio')} onMarketClick={onMarketClick}
/> />
</Tab> </VegaWalletContainer>
<Tab id="info" name={t('Info')}> </Tab>
<TradingViews.Info <Tab id="fills" name={t('Fills')}>
<VegaWalletContainer>
<TradingViews.Fills
marketId={marketId} marketId={marketId}
onSelect={(id: string) => { onMarketClick={onMarketClick}
onSelect?.(id);
}}
/> />
</Tab> </VegaWalletContainer>
</Tabs> </Tab>
</TradeGridChild> </Tabs>
</ResizableGridPanel> </TradeGridChild>
<ResizableGridPanel </ResizableGridPanel>
priority={LayoutPriority.Low} <ResizableGridPanel
preferredSize={430} priority={LayoutPriority.Low}
minSize={200} preferredSize="50%"
> minSize={50}
<TradeGridChild> >
<Tabs> <TradeGridChild>
<Tab id="orderbook" name={t('Orderbook')}> <Tabs>
<TradingViews.Orderbook marketId={marketId} /> <Tab id="positions" name={t('Positions')}>
</Tab> <VegaWalletContainer>
<Tab id="trades" name={t('Trades')}> <TradingViews.Positions
<TradingViews.Trades marketId={marketId} /> onMarketClick={onMarketClick}
</Tab> noBottomPlaceholder
</Tabs> />
</TradeGridChild> </VegaWalletContainer>
</ResizableGridPanel> </Tab>
</ResizableGrid> <Tab id="accounts" name={t('Collateral')}>
</ResizableGridPanel> <VegaWalletContainer>
<ResizableGridPanel <TradingViews.Collateral
priority={LayoutPriority.Low} pinnedAsset={pinnedAsset}
preferredSize="25%" noBottomPlaceholder
minSize={50} hideButtons
> />
<TradeGridChild> </VegaWalletContainer>
<Tabs> </Tab>
<Tab id="positions" name={t('Positions')}> </Tabs>
<VegaWalletContainer> </TradeGridChild>
<TradingViews.Positions onMarketClick={onMarketClick} /> </ResizableGridPanel>
</VegaWalletContainer> </ResizableGrid>
</Tab> ) : (
<Tab id="orders" name={t('Orders')}> <TradeGridChild>
<VegaWalletContainer> <Tabs>
<TradingViews.Orders <Tab id="positions" name={t('Positions')}>
marketId={marketId} <VegaWalletContainer>
onMarketClick={onMarketClick} <TradingViews.Positions onMarketClick={onMarketClick} />
/> </VegaWalletContainer>
</VegaWalletContainer> </Tab>
</Tab> <Tab id="orders" name={t('Orders')}>
<Tab id="fills" name={t('Fills')}> <VegaWalletContainer>
<VegaWalletContainer> <TradingViews.Orders
<TradingViews.Fills marketId={marketId}
marketId={marketId} onMarketClick={onMarketClick}
onMarketClick={onMarketClick} />
/> </VegaWalletContainer>
</VegaWalletContainer> </Tab>
</Tab> <Tab id="fills" name={t('Fills')}>
<Tab id="accounts" name={t('Collateral')}> <VegaWalletContainer>
<VegaWalletContainer> <TradingViews.Fills
<TradingViews.Collateral marketId={marketId}
pinnedAsset={pinnedAsset} onMarketClick={onMarketClick}
hideButtons />
/> </VegaWalletContainer>
</VegaWalletContainer> </Tab>
</Tab> <Tab id="accounts" name={t('Collateral')}>
</Tabs> <VegaWalletContainer>
</TradeGridChild> <TradingViews.Collateral pinnedAsset={pinnedAsset} hideButtons />
</ResizableGridPanel> </VegaWalletContainer>
</ResizableGrid> </Tab>
); </Tabs>
}; </TradeGridChild>
const MainGridWrapped = memo(MainGrid); );
}
);
MarketBottomPanel.displayName = 'MarketBottomPanel';
const MainGrid = memo(
({
marketId,
onSelect,
pinnedAsset,
}: {
marketId: string;
onSelect?: (marketId: string) => void;
pinnedAsset?: PinnedAsset;
}) => {
const navigate = useNavigate();
return (
<ResizableGrid vertical>
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
<ResizableGrid proportionalLayout={false} minSize={200}>
<ResizableGridPanel
priority={LayoutPriority.High}
minSize={200}
preferredSize="50%"
>
<TradeGridChild>
<Tabs>
<Tab id="chart" name={t('Chart')}>
<TradingViews.Candles marketId={marketId} />
</Tab>
<Tab id="depth" name={t('Depth')}>
<TradingViews.Depth marketId={marketId} />
</Tab>
<Tab id="liquidity" name={t('Liquidity')}>
<TradingViews.Liquidity marketId={marketId} />
</Tab>
</Tabs>
</TradeGridChild>
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={330}
minSize={300}
>
<TradeGridChild>
<Tabs>
<Tab id="ticket" name={t('Ticket')}>
<TradingViews.Ticket
marketId={marketId}
onClickCollateral={() => navigate('/portfolio')}
/>
</Tab>
<Tab id="info" name={t('Info')}>
<TradingViews.Info
marketId={marketId}
onSelect={(id: string) => {
onSelect?.(id);
}}
/>
</Tab>
</Tabs>
</TradeGridChild>
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={430}
minSize={200}
>
<TradeGridChild>
<Tabs>
<Tab id="orderbook" name={t('Orderbook')}>
<TradingViews.Orderbook marketId={marketId} />
</Tab>
<Tab id="trades" name={t('Trades')}>
<TradingViews.Trades marketId={marketId} />
</Tab>
</Tabs>
</TradeGridChild>
</ResizableGridPanel>
</ResizableGrid>
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize="25%"
minSize={50}
>
<MarketBottomPanel marketId={marketId} pinnedAsset={pinnedAsset} />
</ResizableGridPanel>
</ResizableGrid>
);
}
);
MainGrid.displayName = 'MainGrid';
export const TradeGrid = ({ export const TradeGrid = ({
market, market,
@ -201,7 +277,7 @@ export const TradeGrid = ({
return ( return (
<div className="h-full grid grid-rows-[min-content_1fr]"> <div className="h-full grid grid-rows-[min-content_1fr]">
<TradeMarketHeader market={market} onSelect={onSelect} /> <TradeMarketHeader market={market} onSelect={onSelect} />
<MainGridWrapped <MainGrid
marketId={market?.id || ''} marketId={market?.id || ''}
onSelect={onSelect} onSelect={onSelect}
pinnedAsset={pinnedAsset} pinnedAsset={pinnedAsset}

View File

@ -12,9 +12,11 @@ import { useDepositDialog } from '@vegaprotocol/deposits';
export const AccountsContainer = ({ export const AccountsContainer = ({
pinnedAsset, pinnedAsset,
hideButtons, hideButtons,
noBottomPlaceholder,
}: { }: {
pinnedAsset?: PinnedAsset; pinnedAsset?: PinnedAsset;
hideButtons?: boolean; hideButtons?: boolean;
noBottomPlaceholder?: boolean;
}) => { }) => {
const { pubKey, isReadOnly } = useVegaWallet(); const { pubKey, isReadOnly } = useVegaWallet();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore(); const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
@ -46,6 +48,7 @@ export const AccountsContainer = ({
onClickDeposit={openDepositDialog} onClickDeposit={openDepositDialog}
isReadOnly={isReadOnly} isReadOnly={isReadOnly}
pinnedAsset={pinnedAsset} pinnedAsset={pinnedAsset}
noBottomPlaceholder={noBottomPlaceholder}
/> />
{!isReadOnly && !hideButtons && ( {!isReadOnly && !hideButtons && (
<div className="flex gap-2 justify-end p-2 px-[11px] absolute lg:fixed bottom-0 right-3 dark:bg-black/75 bg-white/75 rounded"> <div className="flex gap-2 justify-end p-2 px-[11px] absolute lg:fixed bottom-0 right-3 dark:bg-black/75 bg-white/75 rounded">

View File

@ -19,6 +19,7 @@ interface AccountManagerProps {
onClickDeposit?: (assetId?: string) => void; onClickDeposit?: (assetId?: string) => void;
isReadOnly: boolean; isReadOnly: boolean;
pinnedAsset?: PinnedAsset; pinnedAsset?: PinnedAsset;
noBottomPlaceholder?: boolean;
} }
export const AccountManager = ({ export const AccountManager = ({
@ -28,6 +29,7 @@ export const AccountManager = ({
partyId, partyId,
isReadOnly, isReadOnly,
pinnedAsset, pinnedAsset,
noBottomPlaceholder,
}: AccountManagerProps) => { }: AccountManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]); const variables = useMemo(() => ({ partyId }), [partyId]);
@ -45,6 +47,7 @@ export const AccountManager = ({
const bottomPlaceholderProps = useBottomPlaceholder<AccountFields>({ const bottomPlaceholderProps = useBottomPlaceholder<AccountFields>({
gridRef, gridRef,
setId, setId,
disabled: noBottomPlaceholder,
}); });
const getRowHeight = useCallback( const getRowHeight = useCallback(

View File

@ -68,10 +68,11 @@ export const PositionsManager = ({
const bottomPlaceholderProps = useBottomPlaceholder<Position>({ const bottomPlaceholderProps = useBottomPlaceholder<Position>({
gridRef, gridRef,
setId, setId,
disabled: noBottomPlaceholder,
}); });
useEffect(() => { useEffect(() => {
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0); setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
}, [data]); }, [data?.length]);
const onFilterChanged = useCallback((event: FilterChangedEvent) => { const onFilterChanged = useCallback((event: FilterChangedEvent) => {
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0); setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
}, []); }, []);
@ -86,7 +87,7 @@ export const PositionsManager = ({
suppressNoRowsOverlay suppressNoRowsOverlay
isReadOnly={isReadOnly} isReadOnly={isReadOnly}
onFilterChanged={onFilterChanged} onFilterChanged={onFilterChanged}
{...(noBottomPlaceholder ? null : bottomPlaceholderProps)} {...bottomPlaceholderProps}
/> />
<div className="pointer-events-none absolute inset-0"> <div className="pointer-events-none absolute inset-0">
<AsyncRenderer <AsyncRenderer

View File

@ -116,6 +116,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
value value
) )
} }
minWidth={190}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Notional')} headerName={t('Notional')}
@ -141,6 +142,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
data.marketDecimalPlaces data.marketDecimalPlaces
); );
}} }}
minWidth={80}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Open volume')} headerName={t('Open volume')}
@ -174,6 +176,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
); );
}} }}
cellRenderer={OpenVolumeCell} cellRenderer={OpenVolumeCell}
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Mark price')} headerName={t('Mark price')}
@ -213,8 +216,13 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
data.marketDecimalPlaces data.marketDecimalPlaces
); );
}} }}
minWidth={100}
/>
<AgGridColumn
headerName={t('Settlement asset')}
field="assetSymbol"
minWidth={100}
/> />
<AgGridColumn headerName={t('Settlement asset')} field="assetSymbol" />
<AgGridColumn <AgGridColumn
headerName={t('Entry price')} headerName={t('Entry price')}
field="averageEntryPrice" field="averageEntryPrice"
@ -248,6 +256,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
data.marketDecimalPlaces data.marketDecimalPlaces
); );
}} }}
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Leverage')} headerName={t('Leverage')}
@ -264,6 +273,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
}: VegaValueFormatterParams<Position, 'currentLeverage'>) => }: VegaValueFormatterParams<Position, 'currentLeverage'>) =>
value === undefined ? undefined : formatNumber(value.toString(), 1) value === undefined ? undefined : formatNumber(value.toString(), 1)
} }
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Margin allocated')} headerName={t('Margin allocated')}
@ -295,6 +305,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
data.decimals data.decimals
); );
}} }}
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Realised PNL')} headerName={t('Realised PNL')}
@ -321,6 +332,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.' 'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.'
)} )}
cellRenderer={PNLCell} cellRenderer={PNLCell}
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Unrealised PNL')} headerName={t('Unrealised PNL')}
@ -347,6 +359,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.' 'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
)} )}
cellRenderer={PNLCell} cellRenderer={PNLCell}
minWidth={100}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Updated')} headerName={t('Updated')}
@ -361,6 +374,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
} }
return getDateTimeFormat().format(new Date(value)); return getDateTimeFormat().format(new Date(value));
}} }}
minWidth={150}
/> />
{onClose && !props.isReadOnly ? ( {onClose && !props.isReadOnly ? (
<AgGridColumn <AgGridColumn
@ -375,6 +389,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
</ButtonLink> </ButtonLink>
) : null ) : null
} }
minWidth={80}
/> />
) : null} ) : null}
</AgGrid> </AgGrid>

View File

@ -11,11 +11,13 @@ const isFullWidthRow = (params: IsFullWidthRowParams) =>
interface Props<T> { interface Props<T> {
gridRef: RefObject<AgGridReact>; gridRef: RefObject<AgGridReact>;
setId?: (data: T) => T; setId?: (data: T) => T;
disabled?: boolean;
} }
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
export const useBottomPlaceholder = <T extends {}>({ export const useBottomPlaceholder = <T extends {}>({
gridRef, gridRef,
setId, setId,
disabled,
}: Props<T>) => { }: Props<T>) => {
const onBodyScrollEnd = useCallback(() => { const onBodyScrollEnd = useCallback(() => {
const rowCont = gridRef.current?.api.getModel().getRowCount() ?? 0; const rowCont = gridRef.current?.api.getModel().getRowCount() ?? 0;
@ -58,14 +60,17 @@ export const useBottomPlaceholder = <T extends {}>({
}, [gridRef, onBodyScrollEnd]); }, [gridRef, onBodyScrollEnd]);
return useMemo( return useMemo(
() => ({ () =>
onBodyScrollEnd, !disabled
rowClassRules: NO_HOVER_CSS_RULE, ? {
isFullWidthRow, onBodyScrollEnd,
fullWidthCellRenderer, rowClassRules: NO_HOVER_CSS_RULE,
onSortChanged: onRowsChanged, isFullWidthRow,
onFilterChange: onRowsChanged, fullWidthCellRenderer,
}), onSortChanged: onRowsChanged,
[onBodyScrollEnd, onRowsChanged] onFilterChange: onRowsChanged,
}
: {},
[onBodyScrollEnd, onRowsChanged, disabled]
); );
}; };

View File

@ -1,10 +1,19 @@
import { useRef, useEffect, useState } from 'react'; import { useRef, useEffect, useState } from 'react';
const SERVER_SIDE_DIMENSIONS = {
width: 1200,
height: 900,
};
export const useResize = () => { export const useResize = () => {
const [windowSize, setWindowSize] = useState({ const [windowSize, setWindowSize] = useState(
width: window.innerWidth, typeof window !== undefined
height: window.innerHeight, ? {
}); width: window.innerWidth,
height: window.innerHeight,
}
: { ...SERVER_SIDE_DIMENSIONS }
);
const timeout = useRef(0); const timeout = useRef(0);

View File

@ -1,29 +1,31 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
// @ts-ignore avoid adding declaration file
import { theme } from '@vegaprotocol/tailwindcss-config'; import { theme } from '@vegaprotocol/tailwindcss-config';
import { useResize } from './use-resize'; import { useResize } from './use-resize';
type Screen = keyof typeof theme.screens; export type Screen = keyof typeof theme.screens;
interface Props { interface Props {
isMobile: boolean; isMobile: boolean;
screenSize: Screen; screenSize: Screen;
width: number;
} }
export const useScreenDimensions = (): Props => { export const useScreenDimensions = (): Props => {
const { width } = useResize(); const { width } = useResize();
const isMobile = width < parseInt(theme.screens.md);
const screenSize = Object.entries(theme.screens).reduce(
(agg: Screen, entry) => {
if (width > parseInt(entry[1])) {
agg = entry[0] as Screen;
}
return agg;
},
'xs'
);
return useMemo( return useMemo(
() => ({ () => ({
width, isMobile,
isMobile: width < parseInt(theme.screens.md), screenSize,
screenSize: Object.entries(theme.screens).reduce((agg: Screen, entry) => {
if (width > parseInt(entry[1])) {
agg = entry[0] as Screen;
}
return agg;
}, 'xs'),
}), }),
[width] [isMobile, screenSize]
); );
}; };

View File

@ -6,6 +6,7 @@ module.exports = {
lg: '960px', lg: '960px',
xl: '1280px', xl: '1280px',
xxl: '1536px', xxl: '1536px',
xxxl: '1800px',
}, },
colors: { colors: {
transparent: 'transparent', transparent: 'transparent',