feat: [console-lite] - market list - a bunch of improvements (#752)

* feat: [console-lite] - market list - a buch of improvements

* feat: [console-lite] - market list - adjust tests, add keyboard navigation

* feat: [console-lite] - market list - adjust tests, add keyboard navigation

* feat: [console-lite] - market list - small fix

* Apply suggestions from code review

Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>

* Update apps/simple-trading-app/src/app/components/simple-market-list/simple-market-list.tsx

Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>

* feat: [console-lite] - market list - other small fix

Co-authored-by: maciek <maciek@vegaprotocol.io>
Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>
This commit is contained in:
macqbat 2022-07-18 11:28:09 +02:00 committed by GitHub
parent c5016d7bad
commit 6e1d976d08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 262 additions and 89 deletions

View File

@ -83,7 +83,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const steps = [
{
label: 'Select Asset',
label: t('Select Market'),
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
component: (
<MarketSelector

View File

@ -9,7 +9,7 @@ interface Props {
export const DrawerContent = ({ children, className = '' }: Props) => {
const classes = classNames(
'w-full sm:w-full grow-1 p-20 overflow-hidden',
'w-full sm:w-full grow-1 p-12 md:p-20 overflow-hidden',
className
);

View File

@ -59,6 +59,10 @@ export interface SimpleMarkets_markets_tradableInstrument_instrument_product {
export interface SimpleMarkets_markets_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* Metadata for this instrument
*/

View File

@ -1,5 +1,7 @@
import { t } from '@vegaprotocol/react-helpers';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import { IS_MARKET_TRADABLE } from '../../constants';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
export const STATES_FILTER = [
{ value: 'all', text: t('All') },
@ -20,15 +22,30 @@ export const agGridLightVariables = `
--ag-row-hover-color: ${theme.colors.transparent};
--ag-font-size: 15px;
}
.ag-theme-balham .ag-row-hover {
.ag-theme-balham .ag-header-cell{
padding-left: 0;
padding-right: 0;
}
.ag-theme-balham .ag-cell{
padding-left: 0.2rem;
padding-right: 0.2rem;
}
.ag-theme-balham .ag-cell.overflow-visible{
overflow: visible;
}
.ag-theme-balham .ag-row-hover:not(.mobile) {
--ag-row-border-color: ${theme.colors.black[100]};
}
.ag-theme-balham .ag-row-hover .icon-green-hover {
fill: ${theme.colors.darkerGreen};
}
.ag-theme-balham [col-id="status"] .ag-header-cell-label,
.ag-theme-balham [col-id="asset"] .ag-header-cell-label,
.ag-theme-balham [col-id="change"] .ag-header-cell-label{
justify-content: center;
}
.ag-theme-balham .ag-header-row .ag-header-cell:first-child{
.ag-theme-balham .ag-header-row .ag-header-cell:first-child,
.ag-theme-balham .ag-row.mobile .ag-cell:first-child{
padding-left: 0;
}
.ag-theme-balham .ag-ltr .ag-header-cell::after, .ag-theme-balham .ag-ltr .ag-header-group-cell::after {
@ -40,32 +57,43 @@ export const agGridLightVariables = `
.ag-theme-balham .ag-header{
border-bottom-width: 0;
}
.ag-theme-balham .ag-has-focus .ag-row.ag-row-focus{
border: 1px solid #0091ea;
}
.ag-theme-balham .ag-has-focus .ag-row.ag-row-focus .ag-cell-focus {
outline: none;
border-width: 0;
}
.ag-theme-balham .ag-header-label-icon .ag-icon{
font-family: unset;
font-size: 20px;
font-weight: 600;
position: relative;
height: 20px;
line-height: 20px;
-moz-osx-font-smoothing: unset;
}
.ag-theme-balham .ag-icon::before{
font-size: 10px;
line-height: 12px;
position: absolute;
transform: rotate(45deg);
top: -6px;
right: -14px;
content: "◾";
background: -webkit-linear-gradient(135deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, rgba(0,0,0,0.54) 52%, rgba(0,0,0,0.54) 100%);
display: inline-block;
font-family: Arial;
font-size: 20px;
line-height: 20px;
height: 20px;
content: "⬥";
background: linear-gradient(0deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.54) 60%, rgba(0,0,0,0.54) 100%);
background: -moz-linear-gradient(-90deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, rgba(0,0,0,0.54) 66%, rgba(0,0,0,0.54) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.ag-theme-balham .ag-icon-desc::before{
background: -webkit-linear-gradient(135deg, #000 0%, #000 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, rgba(0,0,0,0.54) 52%, rgba(0,0,0,0.54) 100%);
background: linear-gradient(0deg, #000 0%, #000 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.54) 60%, rgba(0,0,0,0.54) 100%);
background: -moz-linear-gradient(-90deg, #000 0%, #000 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, rgba(0,0,0,0.54) 66%, rgba(0,0,0,0.54) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.ag-theme-balham .ag-icon-asc::before{
background: -webkit-linear-gradient(135deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, #000 52%, #000 100%);
background: linear-gradient(0deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, #000 60%, #000 100%);
background: -moz-linear-gradient(-90deg, rgba(0,0,0,0.54) 0%, rgba(0,0,0,0.54) 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, #000 66%, #000 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
@ -76,16 +104,36 @@ export const agGridDarkVariables = `
--ag-background-color: ${theme.colors.lite.black};
--ag-row-border-color: ${theme.colors.transparent};
--ag-row-hover-color: ${theme.colors.transparent};
--ag-odd-row-background-color: ${theme.colors.transparent};
--ag-header-background-color: ${theme.colors.transparent};
--ag-font-size: 15px;
}
.ag-theme-balham-dark .ag-row-hover {
.ag-theme-balham-dark .ag-header-cell{
padding-left: 0;
padding-right: 0;
}
.ag-theme-balham-dark .ag-cell{
padding-left: 0.2rem;
padding-right: 0.2rem;
}
.ag-theme-balham-dark .ag-cell.overflow-visible{
overflow: visible;
}
.ag-theme-balham-dark .ag-row-hover:not(.mobile){
--ag-row-border-color: ${theme.colors.white[100]};
}
.ag-theme-balham-dark .ag-row-hover .icon-green-hover {
fill: ${theme.colors.lightGreen};
}
.ag-theme-balham-dark [col-id="status"] .ag-header-cell-label,
.ag-theme-balham-dark [col-id="asset"] .ag-header-cell-label,
.ag-theme-balham-dark [col-id="change"] .ag-header-cell-label{
justify-content: center;
}
.ag-theme-balham-dark .ag-header-row .ag-header-cell:first-child,
.ag-theme-balham-dark .ag-row.mobile .ag-cell:first-child{
padding-left: 0;
}
.ag-theme-balham-dark .ag-header-row .ag-header-cell:first-child{
padding-left: 0;
}
@ -95,34 +143,50 @@ export const agGridDarkVariables = `
.ag-theme-balham-dark .ag-header{
border-bottom-width: 0;
}
.ag-theme-balham-dark .ag-has-focus .ag-row.ag-row-focus{
border: 1px solid #0091ea;
}
.ag-theme-balham-dark .ag-has-focus .ag-row.ag-row-focus .ag-cell-focus {
outline: none;
border-width: 0;
}
.ag-theme-balham-dark .ag-header-label-icon .ag-icon{
font-family: unset;
font-size: 20px;
font-weight: 600;
position: relative;
height: 20px;
line-height: 20px;
-moz-osx-font-smoothing: unset;
}
.ag-theme-balham-dark .ag-icon::before{
font-size: 10px;
line-height: 12px;
position: absolute;
transform: rotate(45deg);
top: -6px;
right: -14px;
content: "◾";
background: -webkit-linear-gradient(135deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, rgba(245, 245, 245, 0.64) 52%, rgba(245, 245, 245, 0.64) 100%);
display: inline-block;
font-family: Arial;
font-size: 20px;
line-height: 20px;
height: 20px;
content: "⬥";
background: linear-gradient(0deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, rgba(245, 245, 245, 0.64) 60%, rgba(245, 245, 245, 0.64) 100%);
background: -moz-linear-gradient(-90deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, rgba(245, 245, 245, 0.64) 66%, rgba(245, 245, 245, 0.64) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-position: center;
-webkit-font-smoothing: antialiased;
}
.ag-theme-balham-dark .ag-icon-desc::before{
background: -webkit-linear-gradient(135deg, #fff 0%, #fff 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, rgba(245, 245, 245, 0.64) 52%, rgba(245, 245, 245, 0.64) 100%);
background: linear-gradient(0deg, #fff 0%, #fff 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, rgba(245, 245, 245, 0.64) 60%, rgba(245, 245, 245, 0.64) 100%);
background: -moz-linear-gradient(-90deg, #fff 0%, #fff 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, rgba(245, 245, 245, 0.64) 66%, rgba(245, 245, 245, 0.64) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.ag-theme-balham-dark .ag-icon-asc::before{
background: -webkit-linear-gradient(135deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 40%, rgba(0,0,0,0) 40%, rgba(0,0,0,0) 52%, #fff 52%, #fff 100%);
background: linear-gradient(0deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 49%, rgba(0,0,0,0) 49%, rgba(0,0,0,0) 60%, #fff 60%, #fff 100%);
background: -moz-linear-gradient(-90deg, rgba(245, 245, 245, 0.64) 0%, rgba(245, 245, 245, 0.64) 54%, rgba(0,0,0,0) 54%, rgba(0,0,0,0) 66%, #fff 66%, #fff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
`;
export const ROW_CLASS_RULES = {
'cursor-pointer': ({ data }: { data: SimpleMarkets_markets }) =>
IS_MARKET_TRADABLE(data || {}),
};

View File

@ -30,6 +30,7 @@ export const MARKETS_QUERY = gql`
}
tradableInstrument {
instrument {
code
metadata {
tags
}

View File

@ -13,7 +13,7 @@ describe('SimpleMarketExpires', () => {
'settlement:20220525T1200',
];
render(<SimpleMarketExpires tags={tags} />);
expect(screen.getByText('expires 25 May 2022 12:00')).toBeInTheDocument();
expect(screen.getByText('May 25')).toBeInTheDocument();
});
it('settlement-date:date', () => {
@ -23,9 +23,7 @@ describe('SimpleMarketExpires', () => {
'settlement-date:2022-04-25T1200',
];
render(<SimpleMarketExpires tags={tags} />);
expect(
screen.getByText('expires 25 April 2022 12:00')
).toBeInTheDocument();
expect(screen.getByText('April 25')).toBeInTheDocument();
});
it('last one proper tag should matter', () => {
@ -35,9 +33,7 @@ describe('SimpleMarketExpires', () => {
'settlement-expiry-date:2022-03-25T12:00:00',
];
render(<SimpleMarketExpires tags={tags} />);
expect(
screen.getByText('expires 25 March 2022 12:00')
).toBeInTheDocument();
expect(screen.getByText('March 25')).toBeInTheDocument();
});
it('when no proper tag nor date should be null', () => {

View File

@ -1,7 +1,6 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import { format, isValid, parseISO } from 'date-fns';
import { DATE_FORMAT } from '../../constants';
import { EXPIRE_DATE_FORMAT } from '../../constants';
const SimpleMarketExpires = ({
tags,
@ -23,9 +22,9 @@ const SimpleMarketExpires = ({
return agg;
}, null);
return dateFound ? (
<div className="py-2">{`${t('expires')} ${format(
<div className="p-2 text-ui-small border-1 border-pink text-pink inline-block">{`${format(
dateFound as Date,
DATE_FORMAT
EXPIRE_DATE_FORMAT
)}`}</div>
) : null;
}

View File

@ -9,7 +9,10 @@ import { useNavigate, useParams } from 'react-router-dom';
import { subDays } from 'date-fns';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import {
useDataProvider,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/react-helpers';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ThemeContext } from '@vegaprotocol/react-helpers';
@ -21,6 +24,8 @@ import * as constants from './constants';
import SimpleMarketToolbar from './simple-market-toolbar';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
import { IS_MARKET_TRADABLE } from '../../constants';
export type SimpleMarketsType = SimpleMarkets_markets & {
percentChange?: number | '-';
};
@ -32,6 +37,7 @@ export type RouterParams = Partial<{
}>;
const SimpleMarketList = () => {
const { isMobile } = useScreenDimensions();
const navigate = useNavigate();
const params = useParams<RouterParams>();
const theme = useContext(ThemeContext);
@ -76,16 +82,40 @@ const SimpleMarketList = () => {
return () => window.removeEventListener('resize', handleOnGridReady);
}, [handleOnGridReady]);
const onClick = useCallback(
(marketId) => {
navigate(`/trading/${marketId}`);
const { columnDefs, defaultColDef } = useColumnDefinitions({ isMobile });
const getRowId = useCallback(({ data }) => data.id, []);
const handleRowClicked = useCallback(
({ data }: { data: SimpleMarketsType }) => {
if (IS_MARKET_TRADABLE(data)) {
navigate(`/trading/${data.id}`);
}
},
[navigate]
);
const { columnDefs, defaultColDef } = useColumnDefinitions({ onClick });
const onTabToNextCell = useCallback((params) => {
const {
api,
previousCellPosition: { rowIndex },
} = params;
const rowCount = api.getDisplayedRowCount();
if (rowCount <= rowIndex + 1) {
return null;
}
return { ...params.previousCellPosition, rowIndex: rowIndex + 1 };
}, []);
const getRowId = useCallback(({ data }) => data.id, []);
const onCellKeyDown = useCallback(
(params) => {
const { event: { key = '' } = {}, data } = params;
if (key === 'Enter') {
handleRowClicked({ data });
}
},
[handleRowClicked]
);
return (
<div className="h-full grid grid-rows-[min-content,1fr]">
@ -103,11 +133,17 @@ const SimpleMarketList = () => {
: constants.agGridLightVariables
}
onGridReady={handleOnGridReady}
onRowClicked={handleRowClicked}
rowClass={isMobile ? 'mobile' : ''}
rowClassRules={constants.ROW_CLASS_RULES}
ref={gridRef}
overlayNoRowsTemplate={t('No data to display')}
suppressContextMenu
getRowId={getRowId}
suppressMovableColumns
suppressRowTransform
onCellKeyDown={onCellKeyDown}
tabToNextCell={onTabToNextCell}
/>
</AsyncRenderer>
</div>

View File

@ -68,7 +68,7 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
/>
</MockedProvider>
);
expect(screen.getByText('-50.000%')).toBeInTheDocument();
expect(screen.getByText('-50.000%')).toHaveClass('text-vega-pink');
expect(screen.getByText('50.000%')).toBeInTheDocument();
expect(screen.getByText('50.000%')).toHaveClass('text-vega-pink');
});
});

View File

@ -15,6 +15,8 @@ interface Props {
setValue: (arg: unknown) => void;
}
const EMPTY_VALUE = ' - ';
const getChange = (
candles: (SimpleMarkets_markets_candles | null)[] | null,
lastClose?: string
@ -34,17 +36,27 @@ const getChange = (
return Number(((last - first) / first) * 100).toFixed(3) + '%';
}
}
return ' - ';
return EMPTY_VALUE;
};
const getClassColor = (change: number | string) => {
if (parseFloat(change as string) > 0) {
return 'text-darkerGreen dark:text-lightGreen';
return 'text-darkerGreen dark:text-lightGreen percent-change-up';
}
if (parseFloat(change as string) < 0) {
return 'text-vega-pink';
return 'text-vega-pink percent-change-down';
}
return 'text-black-10';
if (change === EMPTY_VALUE) {
return 'text-black-10';
}
return 'text-black-10 percent-change-unchanged';
};
const displayValue = (value: string) => {
if (parseFloat(value) < 0) {
return value.replace('-', '');
}
return value;
};
const SimpleMarketPercentChangeWrapper = (props: Props) => {
@ -74,7 +86,9 @@ const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
}, [setValue, change]);
return (
<div className={classNames('flex text-center', colorClasses)}>{change}</div>
<div className={classNames('flex text-center before:block', colorClasses)}>
{displayValue(change)}
</div>
);
};

View File

@ -1,22 +1,28 @@
import React from 'react';
import classNames from 'classnames';
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
import SimpleMarketExpires from './simple-market-expires';
interface Props {
market: MarketNames_markets;
isMobile?: boolean;
}
const MarketNameRenderer = ({ market }: Props) => {
const MarketNameRenderer = ({ market, isMobile }: Props) => {
return (
<div className="flex h-full items-center grid grid-rows-2 grid-flow-col gap-x-8 gap-y-0 grid-cols-[min-content,1fr,1fr]">
<div className="w-60 row-span-2 bg-pink rounded-full w-44 h-44 bg-gradient-to-br from-white-60 to--white-80 opacity-30" />
<div className="col-span-2 uppercase justify-start text-black dark:text-white text-market self-end">
{market.name}{' '}
<div className="flex h-full items-center grid grid-rows-2 grid-flow-col gap-x-4 md:gap-x-8 gap-y-0 grid-cols-[min-content,1fr,1fr] md:pl-8">
<div
className={classNames(
'row-span-2 bg-pink rounded-full bg-gradient-to-br from-white-60 to--white-80 opacity-30 w-20 h-20 md:w-44 md:h-44'
)}
/>
<div className="col-span-2 uppercase justify-start text-black dark:text-white text-ui-small md:text-market self-end">
{isMobile ? market.tradableInstrument.instrument.code : market.name}{' '}
<SimpleMarketExpires
tags={market.tradableInstrument.instrument.metadata.tags}
/>
</div>
<div className="col-span-2 text-ui-small text-deemphasise dark:text-midGrey self-start leading-3">
<div className="col-span-2 text-ui-tiny md:text-ui-small text-deemphasise dark:text-midGrey self-start leading-3">
{market.tradableInstrument.instrument.product.quoteName}
</div>
</div>

View File

@ -67,7 +67,7 @@ const SimpleMarketToolbar = () => {
);
return (
<div className="w-max mb-32 font-alpha">
<div className="w-full max-w-full mb-32 font-alpha">
<ul
ref={slideContRef}
className="grid grid-flow-col auto-cols-min gap-8 relative pb-4 mb-16"
@ -162,7 +162,7 @@ const SimpleMarketToolbar = () => {
</div>
{activeNumber > 0 && (
<ul
className="grid grid-flow-col auto-cols-min md:gap-16 gap-12 pb-4 md:ml-16"
className="md:gap-16 gap-12 pb-4 md:ml-16 flex flex-wrap"
data-testid="market-assets-menu"
aria-label={t('Asset on the market')}
>

View File

@ -1 +1,11 @@
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
export const DATE_FORMAT = 'dd MMMM yyyy HH:mm';
export const EXPIRE_DATE_FORMAT = 'MMMM dd';
export const TRADABLE_STATES = {
Active: true,
};
export const IS_MARKET_TRADABLE = (market: SimpleMarkets_markets) =>
Boolean((market.data?.market.state ?? '') in TRADABLE_STATES && market?.id);

View File

@ -1,48 +1,62 @@
import React, { useMemo } from 'react';
import classNames from 'classnames';
import { t } from '@vegaprotocol/react-helpers';
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
import MarketNameRenderer from '../components/simple-market-list/simple-market-renderer';
import SimpleMarketPercentChange from '../components/simple-market-list/simple-market-percent-change';
import { Button } from '@vegaprotocol/ui-toolkit';
import { Icon } from '@vegaprotocol/ui-toolkit';
import type { ValueSetterParams } from 'ag-grid-community';
import type { SimpleMarketsType } from '../components/simple-market-list/simple-market-list';
import { IconNames } from '@blueprintjs/icons';
import { IS_MARKET_TRADABLE } from '../constants';
interface Props {
onClick: (marketId: string) => void;
isMobile: boolean;
}
const useColumnDefinitions = ({ onClick }: Props) => {
const useColumnDefinitions = ({ isMobile }: Props) => {
const columnDefs = useMemo(() => {
return [
{
colId: 'market',
headerName: t('Markets'),
headerClass: 'uppercase',
minWidth: 300,
minWidth: isMobile ? 160 : 350,
field: 'name',
cellClass: 'overflow-visible',
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
<MarketNameRenderer market={data} />
<MarketNameRenderer market={data} isMobile={isMobile} />
),
},
{
colId: 'asset',
headerName: t('Settlement asset'),
headerName: t(isMobile ? 'Asset' : 'Settlement asset'),
headerClass: 'uppercase',
minWidth: 100,
minWidth: isMobile ? 50 : 80,
cellClass: 'uppercase flex h-full items-center',
field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
<div className="flex h-full items-center justify-center">
{data.tradableInstrument.instrument.product.settlementAsset.symbol}
<div
className="grid h-full items-center text-center"
title={
data.tradableInstrument.instrument.product.settlementAsset.symbol
}
>
<div className="truncate min-w-0">
{
data.tradableInstrument.instrument.product.settlementAsset
.symbol
}
</div>
</div>
),
},
{
colId: 'change',
headerName: t('24h change'),
headerName: t(isMobile ? '24h' : '24h change'),
headerClass: 'uppercase',
field: 'percentChange',
minWidth: 100,
minWidth: isMobile ? 80 : 100,
valueSetter: (params: ValueSetterParams): boolean => {
const { oldValue, newValue, api, data } = params;
if (oldValue !== newValue) {
@ -84,7 +98,7 @@ const useColumnDefinitions = ({ onClick }: Props) => {
minWidth: 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
<div className="uppercase flex h-full items-center justify-center">
<div className="border text-center px-8">
<div className="border text-center px-2 md:px-8 leading-4 md:leading-6">
{data.data?.market.state}
</div>
</div>
@ -95,22 +109,23 @@ const useColumnDefinitions = ({ onClick }: Props) => {
headerName: '',
headerClass: 'uppercase',
sortable: false,
minWidth: 100,
width: isMobile ? 35 : 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
<div className="h-full flex h-full items-center justify-end">
<Button
onClick={() => onClick(data.id)}
variant="inline-link"
appendIconName="arrow-top-right"
className="uppercase no-underline hover:no-underline"
>
{t('Trade')}
</Button>
<div className="uppercase text-center pr-8">
{!isMobile && t('Trade')}
<Icon
name={IconNames.ARROW_TOP_RIGHT}
className={classNames('fill-current ml-5', {
'icon-green-hover': IS_MARKET_TRADABLE(data),
})}
/>
</div>
</div>
),
},
];
}, [onClick]);
}, [isMobile]);
const defaultColDef = useMemo(() => {
return {

View File

@ -25,6 +25,10 @@ export interface MarketNames_markets_tradableInstrument_instrument_product {
export interface MarketNames_markets_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* Metadata for this instrument
*/

View File

@ -34,6 +34,7 @@ export const MARKET_NAMES_QUERY = gql`
name
tradableInstrument {
instrument {
code
metadata {
tags
}
@ -51,7 +52,7 @@ export const MARKET_NAMES_QUERY = gql`
interface Props {
market: DealTicketQuery_market;
setMarket: (marketId: string) => void;
ItemRenderer?: React.FC<{ market: MarketNames_markets }>;
ItemRenderer?: React.FC<{ market: MarketNames_markets; isMobile?: boolean }>;
}
function escapeRegExp(str: string) {
@ -143,21 +144,14 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
const handleInputKeyDown = useCallback(
(event: React.KeyboardEvent) => {
if (event.key === 'ArrowDown') {
(contRef.current?.children[0] as HTMLDivElement).focus();
(contRef.current?.children[0] as HTMLDivElement)?.focus();
}
},
[contRef]
);
const handleOnBlur = useCallback(() => {
console.log('lookup, showPane', lookup, showPane);
if (!lookup && !showPane) {
console.log(
'2 lookup, showPane, market.name',
lookup,
showPane,
market.name
);
setLookup(market.name);
}
}, [market, lookup, showPane, setLookup]);

View File

@ -28,6 +28,8 @@ module.exports = {
...theme.fontSize,
capMenu: ['15px', { lineHeight: '24px', letterSpacing: '-0.01em' }],
market: ['15px', { lineHeight: '24px' }],
'ui-small': ['12px', { lineHeight: '14px' }],
'ui-tiny': ['10px', { lineHeight: '18px' }],
},
boxShadow: {
...theme.boxShadow,

View File

@ -1,4 +1,5 @@
const plugin = require('tailwindcss/plugin');
const theme = require('./theme-lite');
const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
addUtilities({
@ -11,6 +12,33 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
'.shadow-input': {
boxShadow: 'none',
},
'.percent-change-up::before': {
content: ' ',
display: 'block',
borderLeft: '4px solid transparent',
borderRight: '4px solid transparent',
borderBottom: '4px solid',
marginBottom: '11px',
marginRight: '5px',
},
'.percent-change-down::before': {
content: ' ',
display: 'block',
borderLeft: '4px solid transparent',
borderRight: '4px solid transparent',
borderTop: '4px solid',
marginTop: '11px',
marginRight: '5px',
},
'.percent-change-unchanged::before': {
content: ' ',
width: '4px',
height: '4px',
borderRadius: '50%',
backgroundColor: theme.colors.black[10],
marginTop: '10px',
marginRight: '5px',
},
});
});