feat(trading): update layout on mobile

This commit is contained in:
Madalina Raicu 2024-02-01 16:11:04 +00:00
parent 18a3786c98
commit f5406941e7
No known key found for this signature in database
GPG Key ID: 688B7B31149C1DCD
3 changed files with 149 additions and 81 deletions

View File

@ -3,7 +3,6 @@ import { type Market } from '@vegaprotocol/markets';
// TODO: handle oracle banner
// import { OracleBanner } from '@vegaprotocol/markets';
import { useState } from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import classNames from 'classnames';
import {
Popover,
@ -23,10 +22,12 @@ interface TradePanelsProps {
}
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
const [view, setView] = useState<TradingView>('chart');
const viewCfg = TradingViews[view];
const [view1, setView1] = useState<TradingView>('chart');
const viewCfg1 = TradingViews[view1];
const [view2, setView2] = useState<TradingView>('positions');
const viewCfg2 = TradingViews[view2];
const renderView = () => {
const renderView = (view: TradingView) => {
const Component = TradingViews[view].component;
if (!Component) {
@ -44,7 +45,8 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
);
};
const renderMenu = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderMenu = (viewCfg: any) => {
if ('menu' in viewCfg || 'settings' in viewCfg) {
return (
<div className="flex items-center justify-end gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
@ -69,56 +71,86 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
};
return (
<div className="h-full grid grid-rows-[min-content_min-content_1fr_min-content]">
<div className="h-full flex flex-col lg:grid grid-rows-[min-content_min-content_1fr_min-content]">
<div>
<MarketBanner market={market} />
</div>
<div>{renderMenu()}</div>
<div className="h-full relative">
<AutoSizer>
{({ width, height }) => (
<div style={{ width, height }} className="overflow-auto">
{renderView()}
</div>
)}
</AutoSizer>
</div>
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
{Object.keys(TradingViews)
// filter to control available views for the current market
// eg only perps should get the funding views
.filter((_key) => {
const key = _key as TradingView;
const perpOnlyViews = ['funding', 'fundingPayments'];
<div className="flex flex-col w-full overflow-hidden">
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
{['chart', 'orderbook', 'trades', 'liquidity', 'fundingPayments']
// filter to control available views for the current market
// e.g. only perpetuals should get the funding views
.filter((_key) => {
const key = _key as TradingView;
const perpOnlyViews = ['funding', 'fundingPayments'];
if (
market?.tradableInstrument.instrument.product.__typename ===
'Perpetual'
) {
return true;
}
if (perpOnlyViews.includes(key)) {
return false;
}
if (
market?.tradableInstrument.instrument.product.__typename ===
'Perpetual'
) {
return true;
}
if (perpOnlyViews.includes(key)) {
return false;
}
return true;
})
.map((_key) => {
const key = _key as TradingView;
const isActive = view === key;
return (
<ViewButton
key={key}
view={key}
isActive={isActive}
onClick={() => {
setView(key);
}}
/>
);
})}
})
.map((_key) => {
const key = _key as TradingView;
const isActive = view1 === key;
return (
<ViewButton
key={key}
view={key}
isActive={isActive}
onClick={() => {
setView1(key);
}}
/>
);
})}
</div>
<div className="h-[376px] sm:h-[460px] lg:h-full relative">
<div>{renderMenu(viewCfg1)}</div>
<div className="overflow-auto h-full">{renderView(view1)}</div>
</div>
</div>
{
<div className="flex flex-col w-full grow">
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
{[
'positions',
'activeOrders',
'closedOrders',
'rejectedOrders',
'orders',
'stopOrders',
'collateral',
'fills',
].map((_key) => {
const key = _key as TradingView;
const isActive = view2 === key;
return (
<ViewButton
key={key}
view={key}
isActive={isActive}
onClick={() => {
setView2(key);
}}
/>
);
})}
</div>
<div className="relative grow">
<div className="flex flex-col">{renderMenu(viewCfg2)}</div>
<div className="overflow-auto h-full">{renderView(view2)}</div>
</div>
</div>
}
</div>
);
};
@ -157,7 +189,7 @@ const useViewLabel = (view: TradingView) => {
depth: t('Depth'),
liquidity: t('Liquidity'),
funding: t('Funding'),
fundingPayments: t('Funding Payments'),
fundingPayments: t('Funding'),
orderbook: t('Orderbook'),
trades: t('Trades'),
positions: t('Positions'),

View File

@ -27,10 +27,13 @@ export const LayoutWithSidebar = ({
<div className={gridClasses}>
<div className="col-span-full">{header}</div>
<main
className={classNames('col-start-1 col-end-1 overflow-y-auto', {
'lg:col-end-3': !sidebarOpen,
'hidden lg:block lg:col-end-2': sidebarOpen,
})}
className={classNames(
'col-start-1 col-end-1 overflow-y-auto grow lg:grow-0',
{
'lg:col-end-3': !sidebarOpen,
'hidden lg:block lg:col-end-2': sidebarOpen,
}
)}
>
<Outlet />
</main>

View File

@ -14,7 +14,8 @@ export const NavHeader = () => {
const t = useT();
const { marketId } = useParams();
const { data } = useMarket(marketId);
const [open, setOpen] = useState(false);
const [openMarket, setOpenMarket] = useState(false);
const [openPrice, setOpenPrice] = useState(false);
// Ensure that markets are kept cached so opening the list
// shows all markets instantly
@ -23,32 +24,64 @@ export const NavHeader = () => {
if (!marketId) return null;
return (
<FullScreenPopover
open={open}
onOpenChange={(x) => {
setOpen(x);
}}
trigger={
<h1 className="flex gap-1 sm:gap-2 md:gap-4 items-center text-default text-lg whitespace-nowrap xl:pr-4 xl:border-r border-default">
{data ? data.tradableInstrument.instrument.code : t('Select market')}
<span
className={classNames(
'transition-transform ease-in-out duration-300',
{
'rotate-180': open,
}
)}
>
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
</span>
</h1>
}
>
<MarketSelector
currentMarketId={marketId}
onSelect={() => setOpen(false)}
/>
</FullScreenPopover>
<div className="flex items-center gap-2">
<FullScreenPopover
open={openMarket}
onOpenChange={(x) => {
setOpenMarket(x);
}}
trigger={
<h1 className="flex gap-1 sm:gap-2 md:gap-4 items-center text-default text-sm md:text-lg whitespace-nowrap xl:pr-4 xl:border-r border-default">
{data
? data.tradableInstrument.instrument.code
: t('Select market')}
<span
className={classNames(
'transition-transform ease-in-out duration-300',
{
'rotate-180': openMarket,
}
)}
>
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={12} />
</span>
</h1>
}
>
<MarketSelector
currentMarketId={marketId}
onSelect={() => setOpenMarket(false)}
/>
</FullScreenPopover>
{/* // TODO MOBILE - price popover with market header content */}
<FullScreenPopover
open={openPrice}
onOpenChange={(x) => {
setOpenPrice(x);
}}
trigger={
<h1 className="flex gap-1 sm:gap-2 md:gap-4 items-center text-default text-xs md:text-md whitespace-nowrap xl:pr-4 xl:border-r border-default">
44,500
<span
className={classNames(
'transition-transform ease-in-out duration-300',
{
'rotate-180': openPrice,
}
)}
>
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={12} />
</span>
</h1>
}
>
<MarketSelector
currentMarketId={marketId}
onSelect={() => setOpenMarket(false)}
/>
{/* <MarketHeader /> */}
</FullScreenPopover>
</div>
);
};