Compare commits

...
20 changed files with 428 additions and 372 deletions
@@ -137,6 +137,8 @@ const ClosedMarketsDataGrid = ({
headerName: t('Market'),
field: 'code',
cellRenderer: 'MarketCodeCell',
width: 150,
resizable: true,
},
{
headerName: t('Status'),
@@ -280,6 +282,7 @@ const ClosedMarketsDataGrid = ({
return (
<AgGrid
rowData={rowData}
defaultColDef={COL_DEFS.default}
columnDefs={colDefs}
getRowId={({ data }) => data.id}
overlayNoRowsTemplate={error ? error.message : t('No markets')}
@@ -17,6 +17,7 @@ const defaultColDef = {
filter: true,
resizable: true,
filterParams: { buttons: ['reset'] },
minWidth: 120,
};
const components = {
@@ -53,6 +53,7 @@ export const MarketsPage = () => {
size="extra-small"
data-testid="propose-new-market"
href={externalLink}
target="_blank"
>
{t('Propose a new market')}
</TradingAnchorButton>
@@ -29,6 +29,7 @@ export const useColumnDefs = () => {
{
headerName: t('Market'),
field: 'tradableInstrument.instrument.code',
pinned: true,
cellRenderer: ({
value,
data,
+5 -2
View File
@@ -67,6 +67,7 @@ const defaultColDef = {
sortable: true,
tooltipComponent: TooltipCellComponent,
comparator: accountValuesComparator,
minWidth: 150,
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
@@ -139,6 +140,8 @@ export const AccountTable = ({
{
headerName: t('Asset'),
field: 'asset.symbol',
pinned: true,
minWidth: 75,
headerTooltip: t(
'Asset is the collateral that is deposited into the Vega protocol.'
),
@@ -253,8 +256,8 @@ export const AccountTable = ({
colId: 'accounts-actions',
field: 'asset.id',
...COL_DEFS.actions,
minWidth: showDepositButton ? 105 : COL_DEFS.actions.minWidth,
maxWidth: showDepositButton ? 105 : COL_DEFS.actions.maxWidth,
minWidth: showDepositButton ? 110 : COL_DEFS.actions.minWidth,
maxWidth: showDepositButton ? 110 : COL_DEFS.actions.maxWidth,
cellRenderer: ({
value: assetId,
node,
+6 -3
View File
@@ -23,7 +23,9 @@ import { AccountType } from '@vegaprotocol/types';
const defaultColDef = {
resizable: true,
sortable: true,
minWidth: 100,
};
interface BreakdownTableProps extends AgGridReactProps {
data: AccountFields[] | null;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
@@ -32,12 +34,13 @@ interface BreakdownTableProps extends AgGridReactProps {
const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
({ data }, ref) => {
const t = useT();
const coldefs = useMemo(() => {
const colDefs = useMemo(() => {
const defs: ColDef[] = [
{
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
minWidth: 200,
width: 90,
pinned: true,
sort: 'desc',
cellRenderer: ({
value,
@@ -141,7 +144,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
components={{ PriceCell, ProgressBarCell }}
tooltipShowDelay={500}
defaultColDef={defaultColDef}
columnDefs={coldefs}
columnDefs={colDefs}
domLayout="autoHeight"
/>
);
@@ -9,4 +9,7 @@ export const COL_DEFS = {
type: 'rightAligned',
pinned: 'right' as const,
},
default: {
minWidth: 100,
},
};
+9 -3
View File
@@ -6,7 +6,7 @@ import {
isNumeric,
} from '@vegaprotocol/utils';
import { type ColDef } from 'ag-grid-community';
import { AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
import {
type VegaICellRendererParams,
type VegaValueFormatterParams,
@@ -21,7 +21,7 @@ export const DepositsTable = (
) => {
const columnDefs = useMemo<ColDef[]>(
() => [
{ headerName: 'Asset', field: 'asset.symbol' },
{ headerName: 'Asset', field: 'asset.symbol', pinned: true },
{
headerName: 'Amount',
field: 'amount',
@@ -74,5 +74,11 @@ export const DepositsTable = (
],
[]
);
return <AgGrid columnDefs={columnDefs} {...props} />;
return (
<AgGrid
columnDefs={columnDefs}
defaultColDef={COL_DEFS.default}
{...props}
/>
);
};
+2
View File
@@ -48,6 +48,7 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
},
{
headerName: t('Size'),
@@ -143,6 +144,7 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
<AgGrid
ref={ref}
columnDefs={columnDefs}
defaultColDef={COL_DEFS.default}
overlayNoRowsTemplate={t('No fills')}
getRowId={({ data }) => data?.id}
tooltipShowDelay={0}
@@ -39,6 +39,7 @@ const defaultColDef = {
resizable: true,
sortable: true,
filterParams: { buttons: ['reset'] },
minWidth: 100,
};
export type OrderListTableProps = TypedDataAgGrid<Order> & {
@@ -82,6 +83,9 @@ export const OrderListTable = memo<
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
width: 130,
resizable: true,
},
{
headerName: t('Filled'),
@@ -40,6 +40,7 @@ const defaultColDef = {
resizable: true,
sortable: true,
filterParams: { buttons: ['reset'] },
minWidth: 100,
};
export type StopOrdersTableProps = TypedDataAgGrid<StopOrder> & {
@@ -61,6 +62,7 @@ export const StopOrdersTable = memo(
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
},
{
headerName: t('Trigger'),
+326 -343
View File
@@ -71,6 +71,7 @@ const defaultColDef = {
filterParams: { buttons: ['reset'] },
tooltipComponent: TooltipCellComponent,
resizable: true,
minWidth: 110,
};
export const PositionsTable = ({
@@ -83,6 +84,330 @@ export const PositionsTable = ({
...props
}: Props) => {
const t = useT();
const colDefs = useMemo<ColDef[]>(() => {
const columnDefs: (ColDef | null)[] = [
multipleKeys
? {
headerName: t('Vega key'),
field: 'partyId',
valueGetter: ({ data }: VegaValueGetterParams<Position>) =>
(data?.partyId &&
pubKeys &&
pubKeys.find((key) => key.publicKey === data.partyId)?.name) ||
data?.partyId,
}
: null,
{
headerName: t('Market'),
field: 'marketCode',
resizable: true,
onCellClicked: ({ data }) => {
if (!onMarketClick) return;
onMarketClick(data.marketId);
},
pinned: true,
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Position, 'marketCode'>) => {
if (!data || !value) return '-';
return (
<StackedCell
primary={value}
secondary={
<>
{data?.assetSymbol}
<MarketProductPill productType={data.productType} />
</>
}
/>
);
},
},
{
headerName: t('Size / Notional'),
field: 'openVolume',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellClassRules: signedNumberCssClassRules,
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: { data: Position }) => {
return data?.openVolume === undefined
? undefined
: toBigNum(data?.openVolume, data.positionDecimalPlaces).toNumber();
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'openVolume'>): string => {
if (!data?.openVolume) return '-';
const vol = volumePrefix(
addDecimalsFormatNumber(data.openVolume, data.positionDecimalPlaces)
);
return vol;
},
cellRenderer: OpenVolumeCell,
},
{
headerName: t('Entry / Mark'),
field: 'markPrice',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellRenderer: ({
data,
}: VegaICellRendererParams<Position, 'markPrice'>) => {
if (
!data?.averageEntryPrice ||
!data?.markPrice ||
!data?.marketDecimalPlaces
) {
return <>-</>;
}
if (
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
) {
return <>-</>;
}
const entry = addDecimalsFormatNumber(
data.averageEntryPrice,
data.marketDecimalPlaces
);
const mark = addDecimalsFormatNumber(
data.markPrice,
data.marketDecimalPlaces
);
return (
<StackedCell
primary={entry}
secondary={
<PriceFlashCell
value={Number(data.markPrice)}
valueFormatted={mark}
/>
}
/>
);
},
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data ||
!data.markPrice ||
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
? undefined
: toBigNum(data.markPrice, data.marketDecimalPlaces).toNumber();
},
},
{
headerName: t('Margin / Leverage'),
colId: 'margin',
type: 'rightAligned',
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data
? undefined
: toBigNum(
data.marginAccountBalance,
data.assetDecimals
).toNumber();
},
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (
!data ||
!data.marginAccountBalance ||
!data.marketDecimalPlaces
) {
return null;
}
const margin = addDecimalsFormatNumberQuantum(
data.marginAccountBalance,
data.assetDecimals,
data.quantum
);
const lev = data?.currentLeverage ? data.currentLeverage : 1;
const leverage = formatNumber(Math.max(1, lev), 1);
return <StackedCell primary={margin} secondary={leverage + 'x'} />;
},
},
{
colId: 'liquidationPrice',
headerName: 'Liquidation',
headerTooltip: t('Worst case liquidation price'),
cellClass: 'font-mono text-right',
type: 'rightAligned',
// Cannot be sortable as data is fetched within the cell
sortable: false,
filter: false,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (!data) {
return '-';
}
return (
<div className="flex h-[45px] items-center">
<LiquidationPrice
className="block text-right grow"
marketId={data.marketId}
openVolume={data.openVolume}
collateralAvailable={data.totalBalance}
decimalPlaces={data.marketDecimalPlaces}
/>
</div>
);
},
},
{
headerName: t('Realised PNL'),
field: 'realisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: realisedPNLValueGetter,
cellRenderer: (
args: VegaICellRendererParams<Position, 'realisedPNL'>
) => {
const LOSS_SOCIALIZATION_LINK = DocsLinks?.LOSS_SOCIALIZATION ?? '';
if (!args.data || args.value === undefined) {
return null;
}
const losses = parseInt(args.data?.lossSocializationAmount ?? '0');
if (losses <= 0) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return (
<Tooltip description={args.valueFormatted} align="end">
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
}
const lossesFormatted = addDecimalsFormatNumber(
args.data.lossSocializationAmount,
args.data.assetDecimals
);
return (
<Tooltip
align="end"
description={
<>
<p className="mb-2">
{t('Realised PNL: {{value}}', {
nsSeparator: '*',
replace: { value: args.value },
})}
</p>
<p className="mb-2">
{t('Lifetime loss socialisation deductions: {{losses}}', {
nsSeparator: '*',
replace: {
losses: lossesFormatted,
},
})}
</p>
<p className="mb-2">
{t(
`You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.`,
{ assetSymbol: args.data.assetSymbol }
)}
</p>
{LOSS_SOCIALIZATION_LINK && (
<ExternalLink href={LOSS_SOCIALIZATION_LINK}>
{t('Read more about loss socialisation')}
</ExternalLink>
)}
</>
}
>
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'realisedPNL'>) => {
return !data
? ''
: addDecimalsFormatNumberQuantum(
data.realisedPNL,
data.assetDecimals,
data.quantum
);
},
headerTooltip: t(
'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.'
),
},
{
headerName: t('Unrealised PNL'),
field: 'unrealisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: unrealisedPNLValueGetter,
// @ts-ignore no type overlap but function can be identical
tooltipValueGetter: unrealisedPNLValueGetter,
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
!data
? ''
: addDecimalsFormatNumberQuantum(
data.unrealisedPNL,
data.assetDecimals,
data.quantum
),
headerTooltip: t(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
),
},
onClose && !isReadOnly
? {
...COL_DEFS.actions,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
return (
<div className="flex items-center justify-end gap-2">
{data?.openVolume &&
data?.openVolume !== '0' &&
data.partyId === pubKey ? (
<ButtonLink
data-testid="close-position"
onClick={() => data && onClose(data)}
title={t('Close position')}
>
<VegaIcon name={VegaIconNames.CROSS} size={16} />
</ButtonLink>
) : null}
{data?.assetId && (
<PositionActionsDropdown assetId={data?.assetId} />
)}
</div>
);
},
minWidth: 55,
maxWidth: 55,
}
: null,
];
return columnDefs.filter<ColDef>(
(colDef: ColDef | null): colDef is ColDef => colDef !== null
);
}, [isReadOnly, multipleKeys, onClose, onMarketClick, pubKey, pubKeys, t]);
return (
<AgGrid
overlayNoRowsTemplate={t('No positions')}
@@ -95,349 +420,7 @@ export const PositionsTable = ({
MarketNameCell,
}}
rowHeight={45}
columnDefs={useMemo<ColDef[]>(() => {
const columnDefs: (ColDef | null)[] = [
multipleKeys
? {
headerName: t('Vega key'),
field: 'partyId',
valueGetter: ({ data }: VegaValueGetterParams<Position>) =>
(data?.partyId &&
pubKeys &&
pubKeys.find((key) => key.publicKey === data.partyId)
?.name) ||
data?.partyId,
}
: null,
{
headerName: t('Market'),
field: 'marketCode',
onCellClicked: ({ data }) => {
if (!onMarketClick) return;
onMarketClick(data.marketId);
},
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Position, 'marketCode'>) => {
if (!data || !value) return '-';
return (
<StackedCell
primary={value}
secondary={
<>
{data?.assetSymbol}
<MarketProductPill productType={data.productType} />
</>
}
/>
);
},
},
{
headerName: t('Size / Notional'),
field: 'openVolume',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellClassRules: signedNumberCssClassRules,
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: { data: Position }) => {
return data?.openVolume === undefined
? undefined
: toBigNum(
data?.openVolume,
data.positionDecimalPlaces
).toNumber();
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'openVolume'>): string => {
if (!data?.openVolume) return '-';
const vol = volumePrefix(
addDecimalsFormatNumber(
data.openVolume,
data.positionDecimalPlaces
)
);
return vol;
},
cellRenderer: OpenVolumeCell,
},
{
headerName: t('Entry / Mark'),
field: 'markPrice',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellRenderer: ({
data,
}: VegaICellRendererParams<Position, 'markPrice'>) => {
if (
!data?.averageEntryPrice ||
!data?.markPrice ||
!data?.marketDecimalPlaces
) {
return <>-</>;
}
if (
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
) {
return <>-</>;
}
const entry = addDecimalsFormatNumber(
data.averageEntryPrice,
data.marketDecimalPlaces
);
const mark = addDecimalsFormatNumber(
data.markPrice,
data.marketDecimalPlaces
);
return (
<StackedCell
primary={entry}
secondary={
<PriceFlashCell
value={Number(data.markPrice)}
valueFormatted={mark}
/>
}
/>
);
},
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data ||
!data.markPrice ||
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
? undefined
: toBigNum(data.markPrice, data.marketDecimalPlaces).toNumber();
},
},
{
headerName: t('Margin / Leverage'),
colId: 'margin',
type: 'rightAligned',
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data
? undefined
: toBigNum(
data.marginAccountBalance,
data.assetDecimals
).toNumber();
},
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (
!data ||
!data.marginAccountBalance ||
!data.marketDecimalPlaces
) {
return null;
}
const margin = addDecimalsFormatNumberQuantum(
data.marginAccountBalance,
data.assetDecimals,
data.quantum
);
const lev = data?.currentLeverage ? data.currentLeverage : 1;
const leverage = formatNumber(Math.max(1, lev), 1);
return (
<StackedCell primary={margin} secondary={leverage + 'x'} />
);
},
},
{
colId: 'liquidationPrice',
headerName: 'Liquidation',
headerTooltip: t('Worst case liquidation price'),
cellClass: 'font-mono text-right',
type: 'rightAligned',
// Cannot be sortable as data is fetched within the cell
sortable: false,
filter: false,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (!data) {
return '-';
}
return (
<div className="flex h-[45px] items-center">
<LiquidationPrice
className="block text-right grow"
marketId={data.marketId}
openVolume={data.openVolume}
collateralAvailable={data.totalBalance}
decimalPlaces={data.marketDecimalPlaces}
/>
</div>
);
},
},
{
headerName: t('Realised PNL'),
field: 'realisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: realisedPNLValueGetter,
cellRenderer: (
args: VegaICellRendererParams<Position, 'realisedPNL'>
) => {
const LOSS_SOCIALIZATION_LINK =
DocsLinks?.LOSS_SOCIALIZATION ?? '';
if (!args.data || args.value === undefined) {
return null;
}
const losses = parseInt(
args.data?.lossSocializationAmount ?? '0'
);
if (losses <= 0) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return (
<Tooltip description={args.valueFormatted} align="end">
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
}
const lossesFormatted = addDecimalsFormatNumber(
args.data.lossSocializationAmount,
args.data.assetDecimals
);
return (
<Tooltip
align="end"
description={
<>
<p className="mb-2">
{t('Realised PNL: {{value}}', {
nsSeparator: '*',
replace: { value: args.value },
})}
</p>
<p className="mb-2">
{t(
'Lifetime loss socialisation deductions: {{losses}}',
{
nsSeparator: '*',
replace: {
losses: lossesFormatted,
},
}
)}
</p>
<p className="mb-2">
{t(
`You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.`,
{ assetSymbol: args.data.assetSymbol }
)}
</p>
{LOSS_SOCIALIZATION_LINK && (
<ExternalLink href={LOSS_SOCIALIZATION_LINK}>
{t('Read more about loss socialisation')}
</ExternalLink>
)}
</>
}
>
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'realisedPNL'>) => {
return !data
? ''
: addDecimalsFormatNumberQuantum(
data.realisedPNL,
data.assetDecimals,
data.quantum
);
},
headerTooltip: t(
'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.'
),
},
{
headerName: t('Unrealised PNL'),
field: 'unrealisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: unrealisedPNLValueGetter,
// @ts-ignore no type overlap but function can be identical
tooltipValueGetter: unrealisedPNLValueGetter,
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
!data
? ''
: addDecimalsFormatNumberQuantum(
data.unrealisedPNL,
data.assetDecimals,
data.quantum
),
headerTooltip: t(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
),
},
onClose && !isReadOnly
? {
...COL_DEFS.actions,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
return (
<div className="flex items-center justify-end gap-2">
{data?.openVolume &&
data?.openVolume !== '0' &&
data.partyId === pubKey ? (
<ButtonLink
data-testid="close-position"
onClick={() => data && onClose(data)}
title={t('Close position')}
>
<VegaIcon name={VegaIconNames.CROSS} size={16} />
</ButtonLink>
) : null}
{data?.assetId && (
<PositionActionsDropdown assetId={data?.assetId} />
)}
</div>
);
},
minWidth: 55,
maxWidth: 55,
}
: null,
];
return columnDefs.filter<ColDef>(
(colDef: ColDef | null): colDef is ColDef => colDef !== null
);
}, [
isReadOnly,
multipleKeys,
onClose,
onMarketClick,
pubKey,
pubKeys,
t,
])}
columnDefs={colDefs}
{...props}
/>
);
@@ -29,6 +29,7 @@ export const useColumnDefs = () => {
colId: 'market',
headerName: t('Market'),
field: 'terms.change.instrument.code',
pinned: true,
cellStyle: { lineHeight: '14px' },
cellRenderer: ({
value,
@@ -85,19 +85,21 @@ export function Dialog({
<VegaIcon name={VegaIconNames.CROSS} size={24} />
</DialogPrimitives.Close>
)}
<div className="flex gap-4 max-w-full">
{icon && <div className="fill-current">{icon}</div>}
<div data-testid="dialog-content" className="flex-1 max-w-full">
{title && (
<h1
className="text-xl uppercase mb-4 pr-2"
data-testid="dialog-title"
>
{title}
</h1>
)}
<div>{children}</div>
</div>
<div data-testid="dialog-content" className="flex-1 max-w-full">
{title && (
<span
className="text-xl uppercase flex gap-4"
data-testid="dialog-title"
>
{icon && (
<span className="fill-current flex items-center">
{icon}
</span>
)}
{title}
</span>
)}
<div>{children}</div>
</div>
</div>
</div>
@@ -5,15 +5,16 @@ import { ToastPosition, useToastsConfiguration, useToasts } from './use-toasts';
import { useCallback } from 'react';
import { Intent } from '../../utils/intent';
import { useT } from '../../use-t';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
export const ToastPositionSetter = () => {
const t = useT();
const setPostion = useToastsConfiguration((store) => store.setPosition);
const setPosition = useToastsConfiguration((store) => store.setPosition);
const position = useToastsConfiguration((store) => store.position);
const setToast = useToasts((store) => store.setToast);
const handleChange = useCallback(
(position: ToastPosition) => {
setPostion(position);
setPosition(position);
setToast({
id: 'test-toast',
intent: Intent.Primary,
@@ -21,11 +22,49 @@ export const ToastPositionSetter = () => {
onClose: () => useToasts.getState().remove('test-toast'),
});
},
[setToast, setPostion, t]
[setToast, setPosition, t]
);
const buttonCssClasses =
'flex items-center px-1 py-1 relative rounded bg-vega-clight-400 dark:bg-vega-cdark-400';
const activeIcon = 'fill-vega-clight-900 dark:fill-vega-cdark-900';
const { screenSize } = useScreenDimensions();
const isMobileScreen = screenSize === 'xs';
if (isMobileScreen) {
return (
<div className="flex justify-between">
<div className={classNames('grid grid-cols-1 grid-rows-2 gap-1')}>
<button
className={buttonCssClasses}
onClick={() => handleChange(ToastPosition.TopCenter)}
>
<Icon
className={classNames(
position === ToastPosition.TopCenter && activeIcon
)}
size={3}
name={IconNames.ARROW_UP}
/>
</button>
<button
className={buttonCssClasses}
onClick={() => handleChange(ToastPosition.BottomCenter)}
>
<Icon
className={classNames(
position === ToastPosition.BottomCenter && activeIcon
)}
size={3}
name={IconNames.ARROW_DOWN}
/>
</button>
</div>
</div>
);
}
return (
<div className="flex justify-between">
<div className={classNames('grid grid-cols-3 grid-rows-2 gap-1')}>
@@ -92,7 +92,7 @@ export const ToastsContainer = ({
className={classNames(
'absolute right-0 top-[-38px] z-20 w-full',
'transition-opacity',
'opacity-0 hover:!opacity-100 group-hover:opacity-50',
'sm:opacity-0 sm:hover:!opacity-100 sm:group-hover:opacity-50',
{
hidden: validToasts.length === 0,
}
@@ -34,7 +34,7 @@ export class ViewConnector implements VegaConnector {
});
return Promise.resolve([
{
name: 'View only pubkey',
name: 'View only',
publicKey: this.pubkey,
},
]);
+3 -1
View File
@@ -15,6 +15,7 @@ import {
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import {
COL_DEFS,
type TypedDataAgGrid,
type VegaICellRendererParams,
type VegaValueFormatterParams,
@@ -46,7 +47,7 @@ export const WithdrawalsTable = ({
const columnDefs = useMemo<ColDef[]>(
() => [
{ headerName: t('Asset'), field: 'asset.symbol' },
{ headerName: t('Asset'), field: 'asset.symbol', pinned: true },
{
headerName: t('Amount'),
field: 'amount',
@@ -135,6 +136,7 @@ export const WithdrawalsTable = ({
<AgGrid
overlayNoRowsTemplate={t('No withdrawals')}
columnDefs={columnDefs}
defaultColDef={COL_DEFS.default}
components={{
RecipientCell,
StatusCell,
+1 -1
View File
@@ -38,7 +38,7 @@
"@radix-ui/react-slider": "^1.1.0",
"@radix-ui/react-switch": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
"@sentry/nextjs": "^6.19.3",
"@sentry/react": "^6.19.2",
"@sentry/tracing": "^6.19.2",
+1 -1
View File
@@ -4864,7 +4864,7 @@
"@radix-ui/react-separator" "1.0.3"
"@radix-ui/react-toggle-group" "1.0.4"
"@radix-ui/react-tooltip@^1.0.3":
"@radix-ui/react-tooltip@^1.0.7":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz#8f55070f852e7e7450cc1d9210b793d2e5a7686e"
integrity sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==