feat: adjust padding and add same scroll element for all sidebar children
This commit is contained in:
@@ -23,7 +23,8 @@ export const LayoutWithSidebar = () => {
|
||||
<Outlet />
|
||||
</section>
|
||||
<div
|
||||
className={classNames('col-start-1 lg:col-start-2', {
|
||||
// min-h-0 is needed as this element is part of a grid, we want the content to be scrollable, without it it will push the grid element taller
|
||||
className={classNames('col-start-1 lg:col-start-2 min-h-0', {
|
||||
hidden: !sidebarOpen,
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
|
||||
import { DepositContainer } from '@vegaprotocol/deposits';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { MarketInfoAccordionContainer } from '@vegaprotocol/markets';
|
||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { TinyScroll, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { NodeHealthContainer } from '../node-health';
|
||||
import { Settings } from '../settings';
|
||||
import { Tooltip } from '../../components/tooltip';
|
||||
@@ -186,7 +186,11 @@ export const SidebarContent = () => {
|
||||
|
||||
if (view.type === ViewType.Info) {
|
||||
if (params.marketId) {
|
||||
return <MarketInfoAccordionContainer marketId={params.marketId} />;
|
||||
return (
|
||||
<ContentWrapper>
|
||||
<MarketInfoAccordionContainer marketId={params.marketId} />
|
||||
</ContentWrapper>
|
||||
);
|
||||
} else {
|
||||
return <CloseSidebar />;
|
||||
}
|
||||
@@ -235,14 +239,14 @@ const ContentWrapper = ({
|
||||
title?: string;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
<TinyScroll
|
||||
className="h-full overflow-auto py-4 pl-3 pr-4"
|
||||
// panes have p-1, since sidebar is on the right make pl less to account for additional pane space
|
||||
className="py-4 pl-3 pr-4"
|
||||
data-testid="sidebar-content"
|
||||
>
|
||||
{title && <h2 className="mb-4">{title}</h2>}
|
||||
{children}
|
||||
</div>
|
||||
</TinyScroll>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ function AppBody({ Component }: AppProps) {
|
||||
'grid-rows-[repeat(3,min-content),minmax(0,1fr)]'
|
||||
);
|
||||
return (
|
||||
<div className="font-alpha h-full bg-white dark:bg-vega-cdark-900 text-default">
|
||||
<div className="font-alpha h-full bg-white dark:bg-vega-cdark-900 text-default overflow-hidden">
|
||||
<Head>
|
||||
{/* Cannot use meta tags in _document.page.tsx see https://nextjs.org/docs/messages/no-document-viewport-meta */}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
Intent,
|
||||
Notification,
|
||||
Tooltip,
|
||||
TinyScroll,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import {
|
||||
@@ -268,229 +267,224 @@ export const DealTicket = ({
|
||||
if (!order || !normalizedOrder) return null;
|
||||
|
||||
return (
|
||||
<TinyScroll className="h-full overflow-auto">
|
||||
<form
|
||||
onSubmit={isReadOnly ? undefined : handleSubmit(onSubmit)}
|
||||
noValidate
|
||||
>
|
||||
<Controller
|
||||
name="type"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateType(
|
||||
marketData.marketTradingMode,
|
||||
marketData.trigger
|
||||
),
|
||||
}}
|
||||
render={() => (
|
||||
<TypeSelector
|
||||
value={order.type}
|
||||
onSelect={(type) => {
|
||||
if (type === OrderType.TYPE_NETWORK) return;
|
||||
update({
|
||||
type,
|
||||
// when changing type also update the TIF to what was last used of new type
|
||||
timeInForce: lastTIF[type] || order.timeInForce,
|
||||
postOnly:
|
||||
type === OrderType.TYPE_MARKET ? false : order.postOnly,
|
||||
reduceOnly:
|
||||
type === OrderType.TYPE_LIMIT &&
|
||||
![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(lastTIF[type] || order.timeInForce)
|
||||
? false
|
||||
: order.postOnly,
|
||||
expiresAt: undefined,
|
||||
});
|
||||
clearErrors(['expiresAt', 'price']);
|
||||
}}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
errorMessage={errors.type?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="side"
|
||||
control={control}
|
||||
render={() => (
|
||||
<SideSelector
|
||||
value={order.side}
|
||||
onSelect={(side) => {
|
||||
update({ side });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<DealTicketAmount
|
||||
control={control}
|
||||
orderType={order.type}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
sizeError={errors.size?.message}
|
||||
priceError={errors.price?.message}
|
||||
update={update}
|
||||
size={order.size}
|
||||
price={order.price}
|
||||
/>
|
||||
<Controller
|
||||
name="timeInForce"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateTimeInForce(
|
||||
marketData.marketTradingMode,
|
||||
marketData.trigger
|
||||
),
|
||||
}}
|
||||
render={() => (
|
||||
<TimeInForceSelector
|
||||
value={order.timeInForce}
|
||||
orderType={order.type}
|
||||
onSelect={(timeInForce) => {
|
||||
// Reset post only and reduce only when changing TIF
|
||||
update({
|
||||
timeInForce,
|
||||
postOnly: [
|
||||
<form onSubmit={isReadOnly ? undefined : handleSubmit(onSubmit)} noValidate>
|
||||
<Controller
|
||||
name="type"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateType(
|
||||
marketData.marketTradingMode,
|
||||
marketData.trigger
|
||||
),
|
||||
}}
|
||||
render={() => (
|
||||
<TypeSelector
|
||||
value={order.type}
|
||||
onSelect={(type) => {
|
||||
if (type === OrderType.TYPE_NETWORK) return;
|
||||
update({
|
||||
type,
|
||||
// when changing type also update the TIF to what was last used of new type
|
||||
timeInForce: lastTIF[type] || order.timeInForce,
|
||||
postOnly:
|
||||
type === OrderType.TYPE_MARKET ? false : order.postOnly,
|
||||
reduceOnly:
|
||||
type === OrderType.TYPE_LIMIT &&
|
||||
![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
].includes(lastTIF[type] || order.timeInForce)
|
||||
? false
|
||||
: order.postOnly,
|
||||
reduceOnly: ![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
? false
|
||||
: order.reduceOnly,
|
||||
});
|
||||
// Set TIF value for the given order type, so that when switching
|
||||
// types we know the last used TIF for the given order type
|
||||
setLastTIF((curr) => ({
|
||||
...curr,
|
||||
[order.type]: timeInForce,
|
||||
expiresAt: undefined,
|
||||
}));
|
||||
clearErrors('expiresAt');
|
||||
expiresAt: undefined,
|
||||
});
|
||||
clearErrors(['expiresAt', 'price']);
|
||||
}}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
errorMessage={errors.type?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="side"
|
||||
control={control}
|
||||
render={() => (
|
||||
<SideSelector
|
||||
value={order.side}
|
||||
onSelect={(side) => {
|
||||
update({ side });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<DealTicketAmount
|
||||
control={control}
|
||||
orderType={order.type}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
sizeError={errors.size?.message}
|
||||
priceError={errors.price?.message}
|
||||
update={update}
|
||||
size={order.size}
|
||||
price={order.price}
|
||||
/>
|
||||
<Controller
|
||||
name="timeInForce"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateTimeInForce(
|
||||
marketData.marketTradingMode,
|
||||
marketData.trigger
|
||||
),
|
||||
}}
|
||||
render={() => (
|
||||
<TimeInForceSelector
|
||||
value={order.timeInForce}
|
||||
orderType={order.type}
|
||||
onSelect={(timeInForce) => {
|
||||
// Reset post only and reduce only when changing TIF
|
||||
update({
|
||||
timeInForce,
|
||||
postOnly: [
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
? false
|
||||
: order.postOnly,
|
||||
reduceOnly: ![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
? false
|
||||
: order.reduceOnly,
|
||||
});
|
||||
// Set TIF value for the given order type, so that when switching
|
||||
// types we know the last used TIF for the given order type
|
||||
setLastTIF((curr) => ({
|
||||
...curr,
|
||||
[order.type]: timeInForce,
|
||||
expiresAt: undefined,
|
||||
}));
|
||||
clearErrors('expiresAt');
|
||||
}}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
errorMessage={errors.timeInForce?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{order.type === Schema.OrderType.TYPE_LIMIT &&
|
||||
order.timeInForce === Schema.OrderTimeInForce.TIME_IN_FORCE_GTT && (
|
||||
<Controller
|
||||
name="expiresAt"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateExpiration,
|
||||
}}
|
||||
render={() => (
|
||||
<ExpirySelector
|
||||
value={order.expiresAt}
|
||||
onSelect={(expiresAt) =>
|
||||
update({
|
||||
expiresAt: expiresAt || undefined,
|
||||
})
|
||||
}
|
||||
errorMessage={errors.expiresAt?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<div className="flex gap-2 pb-2 justify-between">
|
||||
<Controller
|
||||
name="postOnly"
|
||||
control={control}
|
||||
render={() => (
|
||||
<Checkbox
|
||||
name="post-only"
|
||||
checked={order.postOnly}
|
||||
disabled={disablePostOnlyCheckbox}
|
||||
onCheckedChange={() => {
|
||||
update({ postOnly: !order.postOnly, reduceOnly: false });
|
||||
}}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
errorMessage={errors.timeInForce?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{order.type === Schema.OrderType.TYPE_LIMIT &&
|
||||
order.timeInForce === Schema.OrderTimeInForce.TIME_IN_FORCE_GTT && (
|
||||
<Controller
|
||||
name="expiresAt"
|
||||
control={control}
|
||||
rules={{
|
||||
validate: validateExpiration,
|
||||
}}
|
||||
render={() => (
|
||||
<ExpirySelector
|
||||
value={order.expiresAt}
|
||||
onSelect={(expiresAt) =>
|
||||
update({
|
||||
expiresAt: expiresAt || undefined,
|
||||
})
|
||||
label={
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{disablePostOnlyCheckbox
|
||||
? t(
|
||||
'"Post only" can not be used on "Fill or Kill" or "Immediate or Cancel" orders.'
|
||||
)
|
||||
: t(
|
||||
'"Post only" will ensure the order is not filled immediately but is placed on the order book as a passive order. When the order is processed it is either stopped (if it would not be filled immediately), or placed in the order book as a passive order until the price taker matches with it.'
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
errorMessage={errors.expiresAt?.message}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<span className="text-xs">{t('Post only')}</span>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<div className="flex gap-2 pb-2 justify-between">
|
||||
<Controller
|
||||
name="postOnly"
|
||||
control={control}
|
||||
render={() => (
|
||||
<Checkbox
|
||||
name="post-only"
|
||||
checked={order.postOnly}
|
||||
disabled={disablePostOnlyCheckbox}
|
||||
onCheckedChange={() => {
|
||||
update({ postOnly: !order.postOnly, reduceOnly: false });
|
||||
}}
|
||||
label={
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{disablePostOnlyCheckbox
|
||||
? t(
|
||||
'"Post only" can not be used on "Fill or Kill" or "Immediate or Cancel" orders.'
|
||||
)
|
||||
: t(
|
||||
'"Post only" will ensure the order is not filled immediately but is placed on the order book as a passive order. When the order is processed it is either stopped (if it would not be filled immediately), or placed in the order book as a passive order until the price taker matches with it.'
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<span className="text-xs">{t('Post only')}</span>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="reduceOnly"
|
||||
control={control}
|
||||
render={() => (
|
||||
<Checkbox
|
||||
name="reduce-only"
|
||||
checked={order.reduceOnly}
|
||||
disabled={disableReduceOnlyCheckbox}
|
||||
onCheckedChange={() => {
|
||||
update({ postOnly: false, reduceOnly: !order.reduceOnly });
|
||||
}}
|
||||
label={
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{disableReduceOnlyCheckbox
|
||||
? t(
|
||||
'"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".'
|
||||
)
|
||||
: t(
|
||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.'
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<span className="text-xs">{t('Reduce only')}</span>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<SummaryMessage
|
||||
errorMessage={errors.summary?.message}
|
||||
asset={asset}
|
||||
marketTradingMode={marketData.marketTradingMode}
|
||||
balance={balance}
|
||||
margin={
|
||||
positionEstimate?.estimatePosition?.margin.bestCase.initialLevel ||
|
||||
'0'
|
||||
}
|
||||
isReadOnly={isReadOnly}
|
||||
pubKey={pubKey}
|
||||
onClickCollateral={onClickCollateral}
|
||||
onDeposit={onDeposit}
|
||||
/>
|
||||
<DealTicketButton side={order.side} />
|
||||
<DealTicketFeeDetails
|
||||
onMarketClick={onMarketClick}
|
||||
feeEstimate={feeEstimate}
|
||||
notionalSize={notionalSize}
|
||||
assetSymbol={assetSymbol}
|
||||
marginAccountBalance={marginAccountBalance}
|
||||
generalAccountBalance={generalAccountBalance}
|
||||
positionEstimate={positionEstimate?.estimatePosition}
|
||||
market={market}
|
||||
<Controller
|
||||
name="reduceOnly"
|
||||
control={control}
|
||||
render={() => (
|
||||
<Checkbox
|
||||
name="reduce-only"
|
||||
checked={order.reduceOnly}
|
||||
disabled={disableReduceOnlyCheckbox}
|
||||
onCheckedChange={() => {
|
||||
update({ postOnly: false, reduceOnly: !order.reduceOnly });
|
||||
}}
|
||||
label={
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{disableReduceOnlyCheckbox
|
||||
? t(
|
||||
'"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".'
|
||||
)
|
||||
: t(
|
||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.'
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<span className="text-xs">{t('Reduce only')}</span>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</TinyScroll>
|
||||
</div>
|
||||
<SummaryMessage
|
||||
errorMessage={errors.summary?.message}
|
||||
asset={asset}
|
||||
marketTradingMode={marketData.marketTradingMode}
|
||||
balance={balance}
|
||||
margin={
|
||||
positionEstimate?.estimatePosition?.margin.bestCase.initialLevel ||
|
||||
'0'
|
||||
}
|
||||
isReadOnly={isReadOnly}
|
||||
pubKey={pubKey}
|
||||
onClickCollateral={onClickCollateral}
|
||||
onDeposit={onDeposit}
|
||||
/>
|
||||
<DealTicketButton side={order.side} />
|
||||
<DealTicketFeeDetails
|
||||
onMarketClick={onMarketClick}
|
||||
feeEstimate={feeEstimate}
|
||||
notionalSize={notionalSize}
|
||||
assetSymbol={assetSymbol}
|
||||
marginAccountBalance={marginAccountBalance}
|
||||
generalAccountBalance={generalAccountBalance}
|
||||
positionEstimate={positionEstimate?.estimatePosition}
|
||||
market={market}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -61,11 +61,7 @@ export const MarketInfoAccordionContainer = ({
|
||||
return (
|
||||
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
||||
{data ? (
|
||||
<TinyScroll className="h-full overflow-auto">
|
||||
<div className="p-4">
|
||||
<MarketInfoAccordion market={data} onSelect={onSelect} />
|
||||
</div>
|
||||
</TinyScroll>
|
||||
<MarketInfoAccordion market={data} onSelect={onSelect} />
|
||||
) : (
|
||||
<Splash>
|
||||
<p>{t('Could not load market')}</p>
|
||||
|
||||
Reference in New Issue
Block a user