Feat/526 consolelite design update market list (#635)

* feat: [console-lite] - market list - improve list view

* feat: [console-lite] - market list - add column sorting, improve ag-grid styles

* feat: [console-lite] - market list - remove unnecessary changes

* feat: [console-lite] - market list - fixes for eslint errors

* feat: [console-lite] - market list - remove redundant changes

* feat: [console-lite] - market list - add resize handler and other small improvements

Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
macqbat 2022-06-28 11:57:47 +02:00 committed by GitHub
parent 5c57d0e433
commit 51712f4c20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 425 additions and 99 deletions

View File

@ -47,6 +47,10 @@ export interface SimpleMarkets_markets_tradableInstrument_instrument_product_set
export interface SimpleMarkets_markets_tradableInstrument_instrument_product {
__typename: "Future";
/**
* String representing the quote (e.g. BTCUSD -> USD is quote)
*/
quoteName: string;
/**
* The name of the asset (string)
*/

View File

@ -1,19 +1,5 @@
import { Intent } from '@vegaprotocol/ui-toolkit';
import { MarketState } from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers';
export const MARKET_STATUS: Record<MarketState | '', Intent> = {
[MarketState.Active]: Intent.Success,
[MarketState.Cancelled]: Intent.Primary,
[MarketState.Closed]: Intent.None,
[MarketState.Pending]: Intent.Warning,
[MarketState.Proposed]: Intent.Warning,
[MarketState.Rejected]: Intent.Danger,
[MarketState.Settled]: Intent.Primary,
[MarketState.Suspended]: Intent.Warning,
[MarketState.TradingTerminated]: Intent.Danger,
'': Intent.Primary,
};
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
export const STATES_FILTER = [
{ value: 'all', text: t('All') },
@ -27,3 +13,115 @@ export const STATES_FILTER = [
{ value: 'Suspended', text: t('Suspended') },
{ value: 'TradingTerminated', text: t('TradingTerminated') },
];
export const agGridLightVariables = `
.ag-theme-balham {
--ag-row-border-color: ${theme.colors.transparent};
--ag-row-hover-color: ${theme.colors.transparent};
--ag-font-size: 15px;
}
.ag-theme-balham .ag-row-hover {
--ag-row-border-color: ${theme.colors.black[100]};
}
.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{
padding-left: 0;
}
.ag-theme-balham .ag-ltr .ag-header-cell::after, .ag-theme-balham .ag-ltr .ag-header-group-cell::after {
right: 0;
}
.ag-theme-balham .ag-header-cell::after{
width: 0;
}
.ag-theme-balham .ag-header{
border-bottom-width: 0;
}
.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{
position: relative;
}
.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%);
-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%);
-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%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
`;
export const agGridDarkVariables = `
.ag-theme-balham-dark {
--ag-row-border-color: ${theme.colors.transparent};
--ag-row-hover-color: ${theme.colors.transparent};
--ag-font-size: 15px;
}
.ag-theme-balham-dark .ag-row-hover {
--ag-row-border-color: ${theme.colors.white[100]};
}
.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{
padding-left: 0;
}
.ag-theme-balham-dark .ag-header-cell::after{
width: 0;
}
.ag-theme-balham-dark .ag-header{
border-bottom-width: 0;
}
.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{
position: relative;
}
.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%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-position: center;
}
.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%);
-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%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
`;

View File

@ -36,6 +36,7 @@ export const MARKETS_QUERY = gql`
product {
__typename
... on Future {
quoteName
settlementAsset {
symbol
}

View File

@ -1,6 +1,12 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { render, screen, waitFor } from '@testing-library/react';
import {
render,
screen,
waitFor,
cleanup,
getAllByRole,
} from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { BrowserRouter } from 'react-router-dom';
@ -37,6 +43,7 @@ describe('SimpleMarketList', () => {
afterEach(() => {
jest.clearAllMocks();
cleanup();
});
it('should be properly renderer as empty', async () => {
@ -130,8 +137,12 @@ describe('SimpleMarketList', () => {
await new Promise((resolve) => setTimeout(resolve, 0));
});
await waitFor(() => {
expect(screen.getByTestId('simple-market-list')).toBeInTheDocument();
expect(
document.querySelector('.ag-center-cols-container')
).toBeInTheDocument();
});
expect(screen.getByTestId('simple-market-list').children).toHaveLength(2);
const container = document.querySelector('.ag-center-cols-container');
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
});
});

View File

@ -1,17 +1,29 @@
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from 'react';
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 { t } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, Lozenge, Splash } from '@vegaprotocol/ui-toolkit';
import { Button } from '@vegaprotocol/ui-toolkit';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ThemeContext } from '@vegaprotocol/react-helpers';
import type { MarketState } from '@vegaprotocol/types';
import SimpleMarketPercentChange from './simple-market-percent-change';
import SimpleMarketExpires from './simple-market-expires';
import DataProvider from './data-provider';
import { MARKET_STATUS } from './constants';
import SimpleMarketToolbar from './simple-market-toolbar';
import useMarketsFilterData from '../../hooks/use-markets-filter-data';
import useColumnDefinitions from '../../hooks/use-column-definitions';
import DataProvider from './data-provider';
import * as constants from './constants';
import SimpleMarketToolbar from './simple-market-toolbar';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
export type SimpleMarketsType = SimpleMarkets_markets & {
percentChange?: number | '-';
};
export type RouterParams = Partial<{
product: string;
@ -22,8 +34,9 @@ export type RouterParams = Partial<{
const SimpleMarketList = () => {
const navigate = useNavigate();
const params = useParams<RouterParams>();
const theme = useContext(ThemeContext);
const statusesRef = useRef<Record<string, MarketState | ''>>({});
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(
() => ({
CandleSince: subDays(Date.now(), 1).toJSON(),
@ -40,7 +53,14 @@ const SimpleMarketList = () => {
update,
variables
);
const localData = useMarketsFilterData(data || [], params);
const localData: Array<SimpleMarketsType> = useMarketsFilterData(
data || [],
params
);
const handleOnGridReady = useCallback(() => {
gridRef.current?.api.sizeColumnsToFit();
}, [gridRef]);
useEffect(() => {
const statuses: Record<string, MarketState | ''> = {};
@ -50,6 +70,11 @@ const SimpleMarketList = () => {
statusesRef.current = statuses;
}, [data, statusesRef]);
useEffect(() => {
window.addEventListener('resize', handleOnGridReady);
return () => window.removeEventListener('resize', handleOnGridReady);
}, [handleOnGridReady]);
const onClick = useCallback(
(marketId) => {
navigate(`/trading/${marketId}`);
@ -57,62 +82,34 @@ const SimpleMarketList = () => {
[navigate]
);
const { columnDefs, defaultColDef } = useColumnDefinitions({ onClick });
const getRowId = useCallback(({ data }) => data.id, []);
return (
<>
<div className="h-full grid grid-rows-[min-content,1fr]">
<SimpleMarketToolbar />
<AsyncRenderer loading={loading} error={error} data={localData}>
{localData && localData.length > 0 ? (
<ul
className="list-none relative pt-8 pb-8"
data-testid="simple-market-list"
>
{localData?.map((market) => (
<li
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">
<div className="w-full grid sm:auto-rows-auto">
<div className="font-extrabold py-2">{market.name}</div>
<SimpleMarketExpires
tags={market.tradableInstrument.instrument.metadata.tags}
/>
<div className="py-2">{`${t('settled in')} ${
market.tradableInstrument.instrument.product
.settlementAsset.symbol
}`}</div>
</div>
<div className="w-full grid sm:grid-rows-2">
<div>
<SimpleMarketPercentChange
candles={market.candles}
marketId={market.id}
/>
</div>
<div>
<Lozenge
variant={MARKET_STATUS[market.data?.market.state || '']}
>
{market.data?.market.state}
</Lozenge>
</div>
</div>
</div>
<div className="absolute right-16 top-1/2 -translate-y-1/2">
<Button
onClick={() => onClick(market.id)}
variant="inline-link"
prependIconName="chevron-right"
/>
</div>
</li>
))}
</ul>
) : (
<Splash>{t('No data to display')}</Splash>
)}
<AgGrid
className="mb-32 min-h-[300px]"
defaultColDef={defaultColDef}
columnDefs={columnDefs}
rowData={localData}
rowHeight={60}
customThemeParams={
theme === 'dark'
? constants.agGridDarkVariables
: constants.agGridLightVariables
}
onGridReady={handleOnGridReady}
ref={gridRef}
overlayNoRowsTemplate={t('No data to display')}
suppressContextMenu
getRowId={getRowId}
suppressMovableColumns
/>
</AsyncRenderer>
</>
</div>
);
};

View File

@ -7,11 +7,16 @@ import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarket
describe('SimpleMarketPercentChange should parse proper change', () => {
let candles: (SimpleMarkets_markets_candles | null)[] | null;
const setValue = () => undefined;
it('empty array', () => {
candles = [];
render(
<MockedProvider>
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
<SimpleMarketPercentChange
candles={candles}
marketId={'1'}
setValue={setValue}
/>
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
@ -20,7 +25,11 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
candles = null;
render(
<MockedProvider>
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
<SimpleMarketPercentChange
candles={candles}
marketId={'1'}
setValue={setValue}
/>
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
@ -33,7 +42,11 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
];
render(
<MockedProvider>
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
<SimpleMarketPercentChange
candles={candles}
marketId={'1'}
setValue={setValue}
/>
</MockedProvider>
);
expect(screen.getByText('100.000%')).toBeInTheDocument();
@ -49,7 +62,11 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
];
render(
<MockedProvider>
<SimpleMarketPercentChange candles={candles} marketId={'1'} />
<SimpleMarketPercentChange
candles={candles}
marketId={'1'}
setValue={setValue}
/>
</MockedProvider>
);
expect(screen.getByText('-50.000%')).toBeInTheDocument();

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { InView } from 'react-intersection-observer';
import { useSubscription } from '@apollo/client';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
@ -12,6 +12,7 @@ import { CANDLE_SUB } from './data-provider';
interface Props {
candles: (SimpleMarkets_markets_candles | null)[] | null;
marketId: string;
setValue: (arg: unknown) => void;
}
const getChange = (
@ -51,20 +52,32 @@ const SimpleMarketPercentChangeWrapper = (props: Props) => {
return (
// @ts-ignore falsy wrong type?
<InView onChange={setInView}>
<InView
onChange={setInView}
className="flex h-full items-center justify-center"
>
{inView && <SimpleMarketPercentChange {...props} />}
</InView>
);
};
const SimpleMarketPercentChange = ({ candles, marketId }: Props) => {
const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
const { data: { candles: { close = undefined } = {} } = {} } =
useSubscription<CandleLive, CandleLiveVariables>(CANDLE_SUB, {
variables: { marketId },
});
const change = getChange(candles, close);
const color = getColor(change);
return <p style={{ color }}>{change}</p>;
useEffect(() => {
const value = parseFloat(change);
setValue(isNaN(value) ? '-' : value);
}, [setValue, change]);
return (
<div className="flex text-center" style={{ color }}>
{change}
</div>
);
};
export default SimpleMarketPercentChangeWrapper;

View File

@ -0,0 +1,26 @@
import React from 'react';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import SimpleMarketExpires from './simple-market-expires';
interface Props {
data: SimpleMarkets_markets;
}
const MarketNameRenderer = ({ data }: 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">
{data.name}{' '}
<SimpleMarketExpires
tags={data.tradableInstrument.instrument.metadata.tags}
/>
</div>
<div className="col-span-2 ui-small text-deemphasise dark:text-midGrey self-start leading-3">
{data.tradableInstrument.instrument.product.quoteName}
</div>
</div>
);
};
export default MarketNameRenderer;

View File

@ -67,7 +67,7 @@ const SimpleMarketToolbar = () => {
);
return (
<div className="w-max mb-16 font-alpha">
<div className="w-max 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 sm:gap-12 pb-4 md:ml-16"
className="grid grid-flow-col auto-cols-min md:gap-16 gap-12 pb-4 md:ml-16"
data-testid="market-assets-menu"
aria-label={t('Asset on the market')}
>

View File

@ -0,0 +1,125 @@
import React, { useMemo } from 'react';
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 type { ValueSetterParams } from 'ag-grid-community';
import type { SimpleMarketsType } from '../components/simple-market-list/simple-market-list';
interface Props {
onClick: (marketId: string) => void;
}
const useColumnDefinitions = ({ onClick }: Props) => {
const columnDefs = useMemo(() => {
return [
{
colId: 'market',
headerName: t('Markets'),
headerClass: 'uppercase',
minWidth: 300,
field: 'name',
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
<MarketNameRenderer data={data} />
),
},
{
colId: 'asset',
headerName: t('Settlement asset'),
headerClass: 'uppercase',
minWidth: 100,
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>
),
},
{
colId: 'change',
headerName: t('24h change'),
headerClass: 'uppercase',
field: 'percentChange',
minWidth: 100,
valueSetter: (params: ValueSetterParams): boolean => {
const { oldValue, newValue, api, data } = params;
if (oldValue !== newValue) {
const newdata = { percentChange: newValue, ...data };
api.applyTransaction({ update: [newdata] });
return true;
}
return false;
},
cellRenderer: ({
data,
setValue,
}: {
data: SimpleMarketsType;
setValue: (arg: unknown) => void;
}) => (
<SimpleMarketPercentChange
candles={data.candles}
marketId={data.id}
setValue={setValue}
/>
),
comparator: (valueA: number | '-', valueB: number | '-') => {
if (valueA === valueB) return 0;
if (valueA === '-') {
return -1;
}
if (valueB === '-') {
return 1;
}
return valueA > valueB ? 1 : -1;
},
},
{
colId: 'status',
headerName: t('Status'),
field: 'data.market.state',
headerClass: 'uppercase',
minWidth: 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
<div className="uppercase flex h-full items-center justify-center">
<div className="border text-center px-8">
{data.data?.market.state}
</div>
</div>
),
},
{
colId: 'trade',
headerName: '',
headerClass: 'uppercase',
sortable: false,
minWidth: 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>
),
},
];
}, [onClick]);
const defaultColDef = useMemo(() => {
return {
sortable: true,
unSortIcon: true,
};
}, []);
return { columnDefs, defaultColDef };
};
export default useColumnDefinitions;

View File

@ -12,9 +12,21 @@ module.exports = {
mint: '#00F780',
pink: '#FF077F',
blue: '#2E6DE5',
vega: {
...theme.colors.vega,
'highlight-item': '#000',
'highlight-item-dark': '#fff',
},
'dropdown-bg-dark': theme.colors.black['100'],
},
fontSize: {
...theme.fontSize,
capMenu: ['15px', { lineHeight: '24px', letterSpacing: '-0.01em' }],
market: ['15px', { lineHeight: '24px' }],
},
boxShadow: {
...theme.boxShadow,
'inset-black': '',
'inset-white': '',
},
};

View File

@ -55,6 +55,8 @@ const colours = {
'green-dark': '#008545',
red: '#FF261A',
'red-dark': '#EB001B',
'highlight-item': '#FF077F',
'highlight-item-dark': '#DFFF0B',
},
blue: '#1DA2FB',
coral: '#FF6057',
@ -65,6 +67,8 @@ const colours = {
selected: '#DFFF0B',
success: '#00F780',
'danger-bg': '#9E0025', // for white text
'dropdown-bg': '#FFF',
'dropdown-bg-dark': shadeOfGray(100 - 60),
};
const boxShadowPosition = {

View File

@ -27,9 +27,16 @@ const agGridDarkVariables = `
}
`;
export const AgGrid = (props: { children: ReactNode }) => (
export const AgGrid = ({
children,
customThemeParams,
}: {
children: ReactNode;
customThemeParams?: string;
}) => (
<>
<style>{agGridDarkVariables}</style>
{props.children}
{customThemeParams && <style>{customThemeParams}</style>}
{children}
</>
);

View File

@ -8,6 +8,7 @@ import 'ag-grid-community/dist/styles/ag-grid.css';
interface GridProps {
children: ReactNode;
customThemeParams: string;
}
const AgGridLightTheme = dynamic<GridProps>(
@ -24,11 +25,13 @@ export const AgGridThemed = ({
style,
className,
gridRef,
customThemeParams = '',
...props
}: (AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
className?: string;
gridRef?: React.ForwardedRef<AgGridReact>;
customThemeParams?: string;
}) => {
const theme = useContext(ThemeContext);
const defaultProps = { rowHeight: 20, headerHeight: 22 };
@ -40,11 +43,11 @@ export const AgGridThemed = ({
style={style}
>
{theme === 'dark' ? (
<AgGridDarkTheme>
<AgGridDarkTheme customThemeParams={customThemeParams}>
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
</AgGridDarkTheme>
) : (
<AgGridLightTheme>
<AgGridLightTheme customThemeParams={customThemeParams}>
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
</AgGridLightTheme>
)}

View File

@ -11,6 +11,7 @@ type Props = (AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
className?: string;
gridRef?: React.Ref<AgGridReact>;
customThemeParams?: string;
};
// https://stackoverflow.com/questions/69433673/nextjs-reactdomserver-does-not-yet-support-suspense

View File

@ -27,9 +27,16 @@ const agGridLightVariables = `
}
`;
export const AgGrid = (props: { children: ReactNode }) => (
export const AgGrid = ({
children,
customThemeParams,
}: {
children: ReactNode;
customThemeParams?: string;
}) => (
<>
<style>{agGridLightVariables}</style>
{props.children}
{customThemeParams && <style>{customThemeParams}</style>}
{children}
</>
);

View File

@ -13,7 +13,7 @@ const itemClass = classNames(
'hover:cursor-pointer',
'select-none',
'whitespace-nowrap',
'focus:bg-vega-pink dark:focus:bg-vega-yellow',
'focus:bg-vega-highlight-item dark:focus:bg-vega-highlight-item-dark',
'focus:text-white dark:focus:text-black',
'focus:outline-none'
);
@ -23,7 +23,7 @@ function getItemClasses(inset: boolean, checked?: boolean) {
itemClass,
inset ? 'pl-28' : 'pl-8',
checked
? 'bg-vega-pink dark:bg-vega-yellow text-white dark:text-black'
? 'bg-vega-highlight-item dark:bg-vega-highlight-item-dark text-white dark:text-black'
: 'text-black dark:text-white'
);
}
@ -73,7 +73,7 @@ export const DropdownMenuContent = forwardRef<
{...contentProps}
ref={forwardedRef}
className={classNames(
'inline-block box-border border-1 border-black bg-white dark:bg-black-60',
'inline-block box-border border-1 border-black bg-dropdown-bg dark:bg-dropdown-bg-dark',
className
)}
/>