Feat/359 console lite improve market list toolbar (#575)
* feat: [console-lite] - simple market list toolbar - fixes in unit tests * feat: [console-lite] - simple market list toolbar - fixes in unit tests * feat: [console-lite] - simple market list toolbar - fixes in unit tests * feat: [console-lite] - simple market list toolbar - fixes in unit tests * feat: [console-lite] - improve simple market list toolbar, improve int and unit test * feat: [console-lite] - adjust int test * feat: [console-lite] - add theme-lite, adjust css's to design * feat: [console-lite] - remove redundant class name * feat: [console-lite] - market list toolbar - change the concept - use router links * feat: [console-lite] - market list toolbar - improve some css * feat: [console-lite] - market list toolbar - improve some css, review feedback Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
parent
6386eb1d5b
commit
52b7a2db59
@ -1,11 +1,14 @@
|
||||
describe('market list', () => {
|
||||
describe('simple url', () => {
|
||||
beforeEach(() => cy.visit('/markets'));
|
||||
beforeEach(() => {
|
||||
cy.visit('/markets');
|
||||
});
|
||||
|
||||
it('selects menus', () => {
|
||||
cy.get('.MuiDrawer-root [aria-current]').should('have.text', 'Markets');
|
||||
cy.get('select[name="states"]').should('have.value', 'Active');
|
||||
cy.get('[data-testid="market-assets-menu"] button.font-bold').should(
|
||||
cy.getByTestId('state-trigger').should('have.text', 'Active');
|
||||
cy.get('[aria-label="Future"]').click();
|
||||
cy.get('[data-testid="market-assets-menu"] a.active').should(
|
||||
'have.text',
|
||||
'All'
|
||||
);
|
||||
@ -14,9 +17,12 @@ describe('market list', () => {
|
||||
it('navigation should make possibly shortest url', () => {
|
||||
cy.location('pathname').should('equal', '/markets');
|
||||
|
||||
cy.get('select[name="states"]').select('All');
|
||||
cy.getByTestId('state-trigger').click();
|
||||
cy.get('[role=menuitemcheckbox]').contains('All').click();
|
||||
cy.location('pathname').should('equal', '/markets/all');
|
||||
|
||||
cy.get('[aria-label="Future"]').click();
|
||||
cy.location('pathname').should('eq', '/markets/all/Future');
|
||||
let asset = '';
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.children()
|
||||
@ -25,25 +31,18 @@ describe('market list', () => {
|
||||
asset = children[1].innerText;
|
||||
if (asset) {
|
||||
cy.wrap(children[1]).click();
|
||||
cy.location('pathname').should('equal', `/markets/all/${asset}`);
|
||||
cy.location('pathname').should(
|
||||
'match',
|
||||
new RegExp(`/markets/all/Future/${asset}`, 'i')
|
||||
);
|
||||
cy.get('a').contains('All Markets').click();
|
||||
cy.location('pathname').should('eq', '/markets/all');
|
||||
}
|
||||
}
|
||||
});
|
||||
if (asset) {
|
||||
cy.get('button').contains('Future').click();
|
||||
cy.location('pathname').should('equal', `/markets/all/${asset}/Future`);
|
||||
|
||||
cy.get('button').contains('All Markets').click();
|
||||
cy.location('pathname').should('equal', `/markets/all/${asset}`);
|
||||
}
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.children()
|
||||
.find('button')
|
||||
.contains('All')
|
||||
.click();
|
||||
cy.location('pathname').should('equal', '/markets/all');
|
||||
|
||||
cy.get('select[name="states"]').select('Active');
|
||||
cy.getByTestId('state-trigger').click();
|
||||
cy.get('[role=menuitemcheckbox]').contains('Active').click();
|
||||
cy.location('pathname').should('equal', '/markets');
|
||||
});
|
||||
});
|
||||
@ -51,20 +50,29 @@ describe('market list', () => {
|
||||
describe('url params should select filters', () => {
|
||||
it('suspended status', () => {
|
||||
cy.visit('/markets/Suspended');
|
||||
cy.get('select[name="states"]').should('have.value', 'Suspended');
|
||||
cy.getByTestId('state-trigger').should('have.text', 'Suspended');
|
||||
});
|
||||
|
||||
it('tBTC asset', () => {
|
||||
cy.visit('/markets/Suspended/tBTC');
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.find('button.font-bold')
|
||||
.should('have.text', 'tBTC');
|
||||
it('last asset (if exists)', () => {
|
||||
cy.intercept('POST', '/query').as('Filters');
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Filters').then((filters) => {
|
||||
if (filters?.response?.body.data.markets.length) {
|
||||
const asset =
|
||||
filters.response.body.data.markets[0].tradableInstrument.instrument
|
||||
.product.settlementAsset.symbol;
|
||||
cy.visit(`/markets/Suspended/Future/${asset}`);
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.find('a.active')
|
||||
.should('have.text', asset);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('Future product', () => {
|
||||
cy.visit('/markets/Suspended/tBTC/Future');
|
||||
cy.visit('/markets/Suspended/Future');
|
||||
cy.getByTestId('market-products-menu')
|
||||
.find('button.active')
|
||||
.find('a.active')
|
||||
.should('have.text', 'Future');
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import type { ReactElement } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
|
@ -3,6 +3,7 @@ import { act } from 'react-dom/test-utils';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import SimpleMarketList from './simple-market-list';
|
||||
import { FILTERS_QUERY, MARKETS_QUERY } from './data-provider';
|
||||
@ -54,7 +55,8 @@ describe('SimpleMarketList', () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks, filterMock]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
@ -122,7 +124,8 @@ describe('SimpleMarketList', () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks, filterMock]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ const SimpleMarketList = () => {
|
||||
>
|
||||
{localData?.map((market) => (
|
||||
<li
|
||||
className="w-full relative flex justify-start items-center no-underline box-border text-left pt-8 pb-8 pl-16 pr-16 mb-10"
|
||||
className="w-full relative flex justify-start items-center no-underline box-border text-left py-8 mb-10"
|
||||
key={market.id}
|
||||
>
|
||||
<div className="w-full grid sm:grid-cols-2">
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import SimpleMarketPercentChange from './simple-market-percent-change';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
import type {
|
||||
CandleLive,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { useLocation, useRoutes, BrowserRouter } from 'react-router-dom';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import SimpleMarketToolbar from './simple-market-toolbar';
|
||||
@ -8,14 +8,6 @@ import type { MarketFilters } from './__generated__/MarketFilters';
|
||||
import { FILTERS_QUERY } from './data-provider';
|
||||
import filterData from './mocks/market-filters.json';
|
||||
|
||||
const mockedNavigate = jest.fn();
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useNavigate: () => mockedNavigate,
|
||||
useParams: () => ({}),
|
||||
}));
|
||||
|
||||
describe('SimpleMarketToolbar', () => {
|
||||
const filterMock: MockedResponse<MarketFilters> = {
|
||||
request: {
|
||||
@ -26,58 +18,105 @@ describe('SimpleMarketToolbar', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const WrappedCompForTest = () => {
|
||||
const routes = useRoutes([
|
||||
{
|
||||
path: '/',
|
||||
element: <SimpleMarketToolbar />,
|
||||
},
|
||||
{
|
||||
path: 'markets',
|
||||
children: [
|
||||
{
|
||||
path: `:state`,
|
||||
element: <SimpleMarketToolbar />,
|
||||
children: [
|
||||
{
|
||||
path: `:product`,
|
||||
element: <SimpleMarketToolbar />,
|
||||
children: [
|
||||
{ path: `:asset`, element: <SimpleMarketToolbar /> },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
element: <SimpleMarketToolbar />,
|
||||
},
|
||||
]);
|
||||
const location = useLocation();
|
||||
return (
|
||||
<>
|
||||
{routes}
|
||||
<div data-testid="location-display">{location.pathname}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should be properly rendered', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<SimpleMarketToolbar />
|
||||
</MockedProvider>
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
render(
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<WrappedCompForTest />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('market-assets-menu')).toBeInTheDocument();
|
||||
expect(screen.getByText('Future')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(screen.getByText('Future'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('market-products-menu').children).toHaveLength(
|
||||
3
|
||||
);
|
||||
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
|
||||
});
|
||||
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||
waitFor(() => {
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||
expect(screen.getByRole('menu').children).toHaveLength(10);
|
||||
});
|
||||
expect(screen.getByTestId('market-products-menu').children).toHaveLength(3);
|
||||
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
|
||||
expect(screen.getByRole('combobox').children).toHaveLength(10);
|
||||
});
|
||||
|
||||
it('navigation should work well', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<SimpleMarketToolbar />
|
||||
</MockedProvider>
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('market-assets-menu')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(
|
||||
screen
|
||||
.getByTestId('market-products-menu')
|
||||
.children[1].querySelector('button') as HTMLButtonElement
|
||||
render(
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<WrappedCompForTest />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
expect(mockedNavigate).toHaveBeenCalledWith('/markets/Active/all/Future');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Future')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(screen.getByText('Future'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
||||
'/markets/Active/Future'
|
||||
);
|
||||
});
|
||||
|
||||
fireEvent.click(
|
||||
screen
|
||||
.getByTestId('market-assets-menu')
|
||||
.children[5].querySelector('button') as HTMLButtonElement
|
||||
.children[5].querySelector('a') as HTMLAnchorElement
|
||||
);
|
||||
expect(mockedNavigate).toHaveBeenCalledWith('/markets/Active/tEURO/Future');
|
||||
|
||||
fireEvent.change(screen.getByRole('combobox'), {
|
||||
target: { value: 'Pending' },
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
||||
'/markets/Active/Future/tEURO'
|
||||
);
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||
waitFor(() => {
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Pending'));
|
||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
||||
'/markets/Pending/Future/tEURO'
|
||||
);
|
||||
});
|
||||
expect(mockedNavigate).toHaveBeenCalledWith(
|
||||
'/markets/Pending/tEURO/Future'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,38 +1,41 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useNavigate, useParams, Link } from 'react-router-dom';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
} from '@radix-ui/react-dropdown-menu';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Button, Select } from '@vegaprotocol/ui-toolkit';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import {
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItemIndicator,
|
||||
Icon,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import useMarketFiltersData from '../../hooks/use-markets-filter';
|
||||
import { STATES_FILTER } from './constants';
|
||||
|
||||
const SimpleMarketToolbar = () => {
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const { assets, products, assetsPerProduct } = useMarketFiltersData();
|
||||
const { products, assetsPerProduct } = useMarketFiltersData();
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const [activeNumber, setActiveNumber] = useState(
|
||||
products?.length ? products.indexOf(params.product || '') + 1 : -1
|
||||
);
|
||||
const [activeAsset, setActiveAsset] = useState(params.asset || 'all');
|
||||
const [activeState, setActiveState] = useState(params.state || 'Active');
|
||||
|
||||
const [sliderStyles, setSliderStyles] = useState<Record<string, string>>({});
|
||||
const slideContRef = useRef<HTMLUListElement | null>(null);
|
||||
|
||||
const onStateChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
setActiveState(e.target.value);
|
||||
},
|
||||
[setActiveState]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// handle corner case when there is product
|
||||
// param, but no products yet
|
||||
if (activeNumber < 0 && products?.length) {
|
||||
setActiveNumber(products.indexOf(params.product || '') + 1 || 0);
|
||||
if (products.length) {
|
||||
setActiveNumber(products.indexOf(params.product || '') + 1);
|
||||
} else {
|
||||
setActiveNumber(-1);
|
||||
}
|
||||
}, [activeNumber, setActiveNumber, products, params]);
|
||||
}, [params, products, setActiveNumber]);
|
||||
|
||||
useEffect(() => {
|
||||
const contStyles = (
|
||||
@ -43,7 +46,7 @@ const SimpleMarketToolbar = () => {
|
||||
]?.getBoundingClientRect();
|
||||
const styles: Record<string, string> = selectedStyles
|
||||
? {
|
||||
backgroundColor: activeNumber ? '' : theme.colors.coral,
|
||||
backgroundColor: activeNumber ? '' : theme.colors.pink,
|
||||
width: `${selectedStyles.width}px`,
|
||||
left: `${selectedStyles.left - contStyles.left}px`,
|
||||
}
|
||||
@ -51,42 +54,55 @@ const SimpleMarketToolbar = () => {
|
||||
setSliderStyles(styles);
|
||||
}, [activeNumber, slideContRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeNumber < 0) {
|
||||
return;
|
||||
}
|
||||
const product = activeNumber ? `/${products[activeNumber - 1]}` : '';
|
||||
const asset = activeAsset !== 'all' || product ? `/${activeAsset}` : '';
|
||||
const state = activeState !== 'Active' || asset ? `/${activeState}` : '';
|
||||
navigate(`/markets${state}${asset}${product}`);
|
||||
}, [activeNumber, activeAsset, activeState, products, navigate]);
|
||||
const onStateChange = useCallback(
|
||||
(activeState: string) => {
|
||||
const asset =
|
||||
params.asset && params.asset !== 'all' ? `/${params.asset}` : '';
|
||||
const product = params.product ? `/${params.product}` : '';
|
||||
const state =
|
||||
activeState !== 'Active' || product ? `/${activeState}` : '';
|
||||
navigate(`/markets${state}${product}${asset}`);
|
||||
},
|
||||
[params, navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-max">
|
||||
<div className="w-max mb-16 font-alpha">
|
||||
<ul
|
||||
ref={slideContRef}
|
||||
className="grid grid-flow-col auto-cols-min gap-8 relative pb-4"
|
||||
className="grid grid-flow-col auto-cols-min gap-8 relative pb-4 mb-16"
|
||||
data-testid="market-products-menu"
|
||||
aria-label={t('Product type')}
|
||||
>
|
||||
<li key="all" className="md:mx-16 whitespace-nowrap">
|
||||
<Button
|
||||
variant="inline"
|
||||
onClick={() => setActiveNumber(0)}
|
||||
style={{ color: theme.colors.coral }}
|
||||
className={classNames({ active: !activeNumber })}
|
||||
<li key="all" className="md:mr-16 whitespace-nowrap">
|
||||
<Link
|
||||
to={`/markets${
|
||||
params.state && params.state !== 'Active'
|
||||
? '/' + params.state
|
||||
: ''
|
||||
}`}
|
||||
aria-label={t('All markets')}
|
||||
className={classNames('text-h5 pl-0 text-pink hover:opacity-75', {
|
||||
active: !activeNumber,
|
||||
})}
|
||||
>
|
||||
{t('All Markets')}
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
{products.map((product, i) => (
|
||||
<li key={product} className="mx-16 whitespace-nowrap">
|
||||
<Button
|
||||
variant="inline"
|
||||
onClick={() => setActiveNumber(++i)}
|
||||
className={classNames({ active: activeNumber - 1 === i })}
|
||||
<Link
|
||||
to={`/markets/${params.state || 'Active'}/${product}`}
|
||||
className={classNames(
|
||||
'text-h5 hover:opacity-75 text-black dark:text-white',
|
||||
{
|
||||
active: activeNumber - 1 === i,
|
||||
}
|
||||
)}
|
||||
aria-label={product}
|
||||
>
|
||||
{product}
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
<li
|
||||
@ -96,53 +112,91 @@ const SimpleMarketToolbar = () => {
|
||||
/>
|
||||
</ul>
|
||||
<div className="grid gap-8 pb-4 mt-8 md:grid-cols-[min-content,min-content,1fr]">
|
||||
<div className="md:ml-16">
|
||||
<Select
|
||||
value={activeState}
|
||||
onChange={onStateChange}
|
||||
name="states"
|
||||
className="mr-16 w-auto"
|
||||
>
|
||||
{STATES_FILTER.map((state) => (
|
||||
<option key={state.value} value={state.value}>
|
||||
{state.text}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div className="hidden md:block">|</div>
|
||||
<ul
|
||||
className="grid grid-flow-col auto-cols-min md:gap-8 pb-4"
|
||||
data-testid="market-assets-menu"
|
||||
>
|
||||
<li key="all" className="mx-8">
|
||||
<Button
|
||||
variant="inline"
|
||||
onClick={() => setActiveAsset('all')}
|
||||
className={classNames({
|
||||
'font-bold': activeAsset === 'all',
|
||||
})}
|
||||
<div className="pb-8">
|
||||
<DropdownMenu onOpenChange={(open) => setOpen(open)}>
|
||||
<DropdownMenuTrigger
|
||||
className="mr-16 w-auto text-capMenu text-black dark:text-white"
|
||||
data-testid="state-trigger"
|
||||
>
|
||||
{t('All')}
|
||||
</Button>
|
||||
</li>
|
||||
{(activeNumber
|
||||
? assetsPerProduct[products[activeNumber - 1]]
|
||||
: assets
|
||||
)?.map((asset) => (
|
||||
<li key={asset} className="mx-8">
|
||||
<Button
|
||||
variant="inline"
|
||||
onClick={() => setActiveAsset(asset)}
|
||||
className={classNames({
|
||||
'font-bold': activeAsset === asset,
|
||||
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
|
||||
{STATES_FILTER.find(
|
||||
(state) =>
|
||||
state.value === params.state ||
|
||||
(!params.state && state.value === 'Active')
|
||||
)?.text || params.state}
|
||||
<Icon
|
||||
name={IconNames.ARROW_DOWN}
|
||||
className={classNames(
|
||||
'fill-current ml-8 transition-transform',
|
||||
{
|
||||
'rotate-180': isOpen,
|
||||
}
|
||||
)}
|
||||
size={16}
|
||||
/>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
{STATES_FILTER.map(({ value, text }) => (
|
||||
<DropdownMenuCheckboxItem
|
||||
className="uppercase text-ui dark:text-white"
|
||||
key={value}
|
||||
inset
|
||||
checked={
|
||||
value === params.state ||
|
||||
(!params.state && value === 'Active')
|
||||
}
|
||||
onCheckedChange={() => onStateChange(value)}
|
||||
>
|
||||
<DropdownMenuItemIndicator>
|
||||
<Icon name="tick" />
|
||||
</DropdownMenuItemIndicator>
|
||||
{text}
|
||||
</DropdownMenuCheckboxItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="hidden md:block text-deemphasise dark:text-midGrey">
|
||||
|
|
||||
</div>
|
||||
{activeNumber > 0 && (
|
||||
<ul
|
||||
className="grid grid-flow-col auto-cols-min md:gap-16 sm:gap-12 pb-4 md:ml-16"
|
||||
data-testid="market-assets-menu"
|
||||
aria-label={t('Asset on the market')}
|
||||
>
|
||||
<li key="all">
|
||||
<Link
|
||||
to={`/markets/${params.state}/${params.product}`}
|
||||
className={classNames('uppercase pl-0 md:pl-4 text-capMenu', {
|
||||
'text-deemphasise dark:text-midGrey':
|
||||
params.asset && params.asset !== 'all',
|
||||
'active text-black dark:text-white':
|
||||
!params.asset || params.asset === 'all',
|
||||
})}
|
||||
aria-label={t('All assets')}
|
||||
>
|
||||
{asset}
|
||||
</Button>
|
||||
{t('All')}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{assetsPerProduct[products[activeNumber - 1]]?.map((asset) => (
|
||||
<li key={asset}>
|
||||
<Link
|
||||
to={`/markets/${params.state}/${params.product}/${asset}`}
|
||||
className={classNames('uppercase text-capMenu', {
|
||||
'text-deemphasise dark:text-midGrey':
|
||||
params.asset !== asset,
|
||||
'active text-black dark:text-white': params.asset === asset,
|
||||
})}
|
||||
aria-label={asset}
|
||||
>
|
||||
{asset}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -4,7 +4,6 @@ import { FILTERS_QUERY } from '../components/simple-market-list/data-provider';
|
||||
import type { MarketFilters } from '../components/simple-market-list/__generated__/MarketFilters';
|
||||
|
||||
const useMarketFilters = () => {
|
||||
const [assets, setAssets] = useState<string[]>([]);
|
||||
const [products, setProducts] = useState<string[]>([]);
|
||||
const [assetsPerProduct, setAssetsPerProduct] = useState<
|
||||
Record<string, string[]>
|
||||
@ -14,7 +13,6 @@ const useMarketFilters = () => {
|
||||
});
|
||||
useEffect(() => {
|
||||
const localProducts = new Set<string>();
|
||||
const localAssets = new Set<string>();
|
||||
const localAssetPerProduct: Record<string, Set<string>> = {};
|
||||
data?.markets?.forEach((item) => {
|
||||
const product = item.tradableInstrument.instrument.product.__typename;
|
||||
@ -25,9 +23,7 @@ const useMarketFilters = () => {
|
||||
}
|
||||
localAssetPerProduct[product].add(asset);
|
||||
localProducts.add(product);
|
||||
localAssets.add(asset);
|
||||
});
|
||||
setAssets([...localAssets]);
|
||||
setProducts([...localProducts]);
|
||||
setAssetsPerProduct(
|
||||
Object.entries(localAssetPerProduct).reduce(
|
||||
@ -39,7 +35,7 @@ const useMarketFilters = () => {
|
||||
)
|
||||
);
|
||||
}, [data]);
|
||||
return { assets, products, assetsPerProduct };
|
||||
return { products, assetsPerProduct };
|
||||
};
|
||||
|
||||
export default useMarketFilters;
|
||||
|
@ -26,9 +26,9 @@ export const routerConfig = [
|
||||
element: <SimpleMarketList />,
|
||||
children: [
|
||||
{
|
||||
path: `:asset`,
|
||||
path: `:product`,
|
||||
element: <SimpleMarketList />,
|
||||
children: [{ path: `:product`, element: <SimpleMarketList /> }],
|
||||
children: [{ path: `:asset`, element: <SimpleMarketList /> }],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
const { join } = require('path');
|
||||
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');
|
||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
||||
const theme = require('../../libs/tailwindcss-config/src/theme-lite');
|
||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||
|
||||
module.exports = {
|
||||
|
@ -145,7 +145,6 @@ export const VoteButtons = ({
|
||||
{proposalState === ProposalState.Open ? (
|
||||
<Button
|
||||
variant="inline-link"
|
||||
className="text-yellow"
|
||||
onClick={() => {
|
||||
setChangeVote(true);
|
||||
}}
|
||||
|
@ -1,7 +1,9 @@
|
||||
const theme = require('./theme');
|
||||
const themelite = require('./theme-lite');
|
||||
const vegaCustomClasses = require('./vega-custom-classes');
|
||||
|
||||
module.exports = {
|
||||
theme,
|
||||
themelite,
|
||||
plugins: [vegaCustomClasses],
|
||||
};
|
||||
|
19
libs/tailwindcss-config/src/theme-lite.js
Normal file
19
libs/tailwindcss-config/src/theme-lite.js
Normal file
@ -0,0 +1,19 @@
|
||||
const theme = require('./theme');
|
||||
|
||||
module.exports = {
|
||||
...theme,
|
||||
colors: {
|
||||
...theme.colors,
|
||||
offBlack: '#252525',
|
||||
midGrey: '#828282',
|
||||
borderGrey: '#4f4f4f',
|
||||
lightGrey: '#F2F2F2',
|
||||
yellow: '#DFFF0B',
|
||||
mint: '#00F780',
|
||||
pink: '#FF077F',
|
||||
},
|
||||
fontSize: {
|
||||
...theme.fontSize,
|
||||
capMenu: ['15px', { lineHeight: '24px', letterSpacing: '-0.01em' }],
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user