diff --git a/.eslintrc.json b/.eslintrc.json index 6d15a4044..88d9bd572 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -51,7 +51,8 @@ "ul": ["list"], "ol": ["list"] } - ] + ], + "no-console": ["error", { "allow": ["warn", "error"] }] } }, { diff --git a/apps/governance/src/components/nav/nav.tsx b/apps/governance/src/components/nav/nav.tsx index 32c774632..64e95e7d1 100644 --- a/apps/governance/src/components/nav/nav.tsx +++ b/apps/governance/src/components/nav/nav.tsx @@ -18,10 +18,7 @@ import { VegaWallet } from '../vega-wallet'; import { useLocation, useMatch } from 'react-router-dom'; import { useEffect } from 'react'; import { useTelemetryDialog } from '../telemetry-dialog/telemetry-dialog'; -import { - ProtocolUpgradeCountdown, - ProtocolUpgradeCountdownMode, -} from '@vegaprotocol/proposals'; +import { ProtocolUpgradeCountdown } from '@vegaprotocol/proposals'; export const SettingsLink = () => { const { open, isOpen, close } = useTelemetryDialog(); @@ -68,9 +65,7 @@ export const Nav = ({ theme }: Pick) => { actions={ <> - + } > diff --git a/apps/governance/src/lib/download-json.ts b/apps/governance/src/lib/download-json.ts index 6bb43312f..888ac098a 100644 --- a/apps/governance/src/lib/download-json.ts +++ b/apps/governance/src/lib/download-json.ts @@ -20,6 +20,6 @@ export const downloadJson = (jsonString: string, proposalTitle: string) => { window.URL.revokeObjectURL(url); document.body.removeChild(a); } catch (error) { - console.log(error); + console.error(error); } }; diff --git a/apps/governance/src/routes/rewards/home/rewards-page.tsx b/apps/governance/src/routes/rewards/home/rewards-page.tsx index 195716be4..7c161decb 100644 --- a/apps/governance/src/routes/rewards/home/rewards-page.tsx +++ b/apps/governance/src/routes/rewards/home/rewards-page.tsx @@ -61,8 +61,6 @@ export const RewardsPage = () => { error: paramsError, } = useNetworkParams([NetworkParams.reward_staking_delegation_payoutDelay]); - console.log('params', params); - const payoutDuration = useMemo(() => { if (!params) { return 0; diff --git a/apps/trading-e2e/src/integration/capsule.cy.ts b/apps/trading-e2e/src/integration/capsule.cy.ts index 948389480..56790448e 100644 --- a/apps/trading-e2e/src/integration/capsule.cy.ts +++ b/apps/trading-e2e/src/integration/capsule.cy.ts @@ -535,6 +535,7 @@ function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) { // unexpected latency const minBefore = subSeconds(new Date(), 5); const maxAfter = addSeconds(new Date(), 5); + // eslint-disable-next-line no-console console.log(maxAfter); const date = new Date($dateTime.toString()); expect(isAfter(date, minBefore) && isBefore(date, maxAfter)).to.equal( diff --git a/apps/trading-e2e/src/integration/home-node-network.cy.ts b/apps/trading-e2e/src/integration/home-node-network.cy.ts index cc12b5dc4..02ba53d7f 100644 --- a/apps/trading-e2e/src/integration/home-node-network.cy.ts +++ b/apps/trading-e2e/src/integration/home-node-network.cy.ts @@ -68,22 +68,4 @@ describe('home', { tags: '@regression' }, () => { cy.getByTestId('connect').click(); }); }); - - describe('Network switcher', () => { - before(() => { - cy.mockTradingPage(); - cy.mockSubscription(); - cy.visit('/'); - }); - - it('switch to fairground network and check status & incidents link', () => { - // 0006-NETW-002 - // 0006-NETW-003 - cy.getByTestId('navigation') - .find('[data-testid="network-switcher"]') - .should('have.text', 'Custom') - .click(); - cy.getByTestId('network-item').contains('Fairground testnet'); - }); - }); }); diff --git a/apps/trading-e2e/src/integration/markets-proposed.cy.ts b/apps/trading-e2e/src/integration/markets-proposed.cy.ts index 0d51d505a..bac1b6e32 100644 --- a/apps/trading-e2e/src/integration/markets-proposed.cy.ts +++ b/apps/trading-e2e/src/integration/markets-proposed.cy.ts @@ -84,7 +84,7 @@ describe('markets proposed table', { tags: '@smoke' }, () => { .find('button') .click(); - const dropdownContent = '[data-testid="market-actions-content"]'; + const dropdownContent = '[data-testid="proposal-actions-content"]'; const dropdownContentItem = '[role="menuitem"]'; // 6001-MARK-059 @@ -100,7 +100,7 @@ describe('markets proposed table', { tags: '@smoke' }, () => { 'VEGA_TOKEN_URL' )}/proposals/e9ec6d5c46a7e7bcabf9ba7a893fa5a5eeeec08b731f06f7a6eb7bf0e605b829` ); - cy.getByTestId('market-actions-content').click(); + cy.getByTestId('proposal-actions-content').click(); }); // 6001-MARK-060 diff --git a/apps/trading-e2e/src/integration/navbar.cy.ts b/apps/trading-e2e/src/integration/navbar.cy.ts deleted file mode 100644 index 262478610..000000000 --- a/apps/trading-e2e/src/integration/navbar.cy.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { mockConnectWallet } from '@vegaprotocol/cypress'; - -describe('Navbar', { tags: '@smoke' }, () => { - beforeEach(() => { - cy.clearAllLocalStorage(); - cy.mockTradingPage(); - cy.mockSubscription(); - cy.visit('/'); - cy.wait('@Markets'); - cy.wait('@MarketsData'); - }); - - const pages = [ - { name: 'Markets', link: '#/markets/all' }, - { name: 'Trading', link: '#/markets' }, - { name: 'Portfolio', link: '#/portfolio' }, - ]; - - describe('desktop view', () => { - pages.forEach(({ name, link }) => { - it(`${name} should be correctly rendered`, () => { - cy.get('nav') - .find(`a[data-testid=${name}]:visible`) - .then((element) => { - cy.wrap(element).click(); - cy.location('hash').should('contain', link); - }); - }); - }); - - it('Resources dropdown should be correctly rendered', () => { - const resourceSelector = 'ul li:contains(Resources)'; - ['Docs', 'Give Feedback'].forEach((text, index) => { - cy.get('nav').find(resourceSelector).contains('Resources').click(); - cy.get('nav') - .find(resourceSelector) - .find('.navigation-content li') - .eq(index) - .find('a') - .then((element) => { - expect(element.attr('target')).to.eq('_blank'); - expect(element.attr('href')).to.not.be.empty; - expect(element.text()).to.eq(text); - }); - }); - }); - - it('Disclaimer should be presented after choosing from menu', () => { - cy.get('nav') - .find('ul li:contains(Resources)') - .contains('Resources') - .click(); - cy.getByTestId('Disclaimer').eq(0).click(); - cy.location('hash').should('equal', '#/disclaimer'); - cy.get('p').contains( - 'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets.' - ); - }); - }); - - describe('mobile view', () => { - const viewportHeight = Cypress.config('viewportHeight'); - const viewportWidth = Cypress.config('viewportWidth'); - before(() => { - // a little hack to keep the viewport size between tests (cypress bug) - Cypress.config({ - viewportWidth: 560, - viewportHeight: 890, - }); - cy.viewport(560, 890); - }); - - describe('wallet drawer', () => { - it('wallet drawer should be correctly rendered', () => { - mockConnectWallet(); - cy.connectVegaWallet(true); - cy.getByTestId('connect-vega-wallet-mobile').click(); - cy.getByTestId('wallets-drawer').should('be.visible'); - cy.getByTestId('wallets-drawer').within((el) => { - cy.wrap(el).get('button').contains('Disconnect').click(); - }); - cy.getByTestId('wallets-drawer').should('not.be.visible'); - }); - }); - - describe('menu drawer', () => { - pages.forEach(({ name, link }) => { - it(`${name} should be correctly rendered`, () => { - cy.getByTestId('button-menu-drawer').click(); - cy.getByTestId('menu-drawer').should('be.visible'); - cy.getByTestId('menu-drawer').within((el) => { - cy.wrap(el).getByTestId(name).click(); - cy.location('hash').should('contain', link); - }); - }); - }); - - it('Menu drawer should not be visible until opened', () => { - cy.getByTestId('menu-drawer').should('not.be.visible'); - cy.getByTestId('button-menu-drawer').click(); - cy.getByTestId('menu-drawer').should('be.visible'); - cy.getByTestId('button-menu-drawer').click(); - cy.getByTestId('menu-drawer').should('not.be.visible'); - }); - }); - after(() => { - // a little hack to keep the viewport size between tests (cypress bug) - Cypress.config({ - viewportWidth, - viewportHeight, - }); - }); - }); -}); diff --git a/apps/trading-e2e/src/integration/trading-chart.cy.ts b/apps/trading-e2e/src/integration/trading-chart.cy.ts index f4b4026d1..38bdce7f4 100644 --- a/apps/trading-e2e/src/integration/trading-chart.cy.ts +++ b/apps/trading-e2e/src/integration/trading-chart.cy.ts @@ -171,6 +171,7 @@ describe( .invoke('text') .then((text) => { const actualDate = text.slice(0, -67); + // eslint-disable-next-line no-console console.log(actualDate); const actualOhlc = text.slice(-67); assert.isTrue(expectedDateRegex.test(actualDate)); diff --git a/apps/trading-e2e/src/integration/trading-positions.cy.ts b/apps/trading-e2e/src/integration/trading-positions.cy.ts index 3e73a8850..bd7cdb318 100644 --- a/apps/trading-e2e/src/integration/trading-positions.cy.ts +++ b/apps/trading-e2e/src/integration/trading-positions.cy.ts @@ -7,7 +7,7 @@ const closePosition = 'close-position'; const dialogCloseX = 'dialog-close'; const dialogContent = 'dialog-content'; const dropDownMenu = 'dropdown-menu'; -const marketActionsContent = 'market-actions-content'; +const marketActionsContent = 'position-actions-content'; const positions = 'Positions'; const tabPositions = 'tab-positions'; const toastContent = 'toast-content'; diff --git a/apps/trading/client-pages/market/trade-panels.tsx b/apps/trading/client-pages/market/trade-panels.tsx index 037618fb1..65b4b2a53 100644 --- a/apps/trading/client-pages/market/trade-panels.tsx +++ b/apps/trading/client-pages/market/trade-panels.tsx @@ -88,9 +88,12 @@ export const TradePanels = ({
{Object.keys(TradingViews).map((key) => { const isActive = view === key; - const className = classNames('p-4 min-w-[100px] capitalize', { - 'bg-vega-clight-500 dark:bg-vega-cdark-500': isActive, - }); + const className = classNames( + 'py-2 px-4 min-w-[100px] capitalize text-sm', + { + 'bg-vega-clight-500 dark:bg-vega-cdark-500': isActive, + } + ); return ( - ); - const onSelectItem = useCallback( - (pubkey: string) => { - setDrawerOpen(false); - selectPubKey(pubkey); - }, - [selectPubKey] - ); - return ( -
- -
-
- -
-
- {(pubKeys || []).map((pk) => ( - - ))} -
-
- - -
-
-
-
- ); -}; +import classNames from 'classnames'; export const VegaWalletConnectButton = () => { const [dropdownOpen, setDropdownOpen] = useState(false); @@ -166,96 +44,101 @@ export const VegaWalletConnectButton = () => { if (isConnected && pubKeys) { return ( - <> -
- { + if (fetchPubKeys) { + fetchPubKeys(); + } + setDropdownOpen(!dropdownOpen); + }} + > + + + } + > + setDropdownOpen(false)} + sideOffset={12} + side="bottom" + align="end" + onEscapeKeyDown={() => setDropdownOpen(false)} + > +
+ { + selectPubKey(value); + }} + > + {pubKeys.map((pk) => ( + + ))} + + + {!isReadOnly && ( + { - if (fetchPubKeys) { - fetchPubKeys(); - } - setDropdownOpen(!dropdownOpen); + setView({ type: ViewType.Transfer }); + setDropdownOpen(false); }} > - {activeKey && ( - {activeKey.name} - )} - {': '} - {truncateByChars(pubKey)} - - } - > - setDropdownOpen(false)} - sideOffset={17} - side="bottom" - align="end" - onEscapeKeyDown={() => setDropdownOpen(false)} - > -
- { - selectPubKey(value); - }} - > - {pubKeys.map((pk) => ( - - ))} - - - {!isReadOnly && ( - { - setView({ type: ViewType.Transfer }); - setDropdownOpen(false); - }} - > - {t('Transfer')} - - )} - - {t('Disconnect')} - -
-
- -
- - + {t('Transfer')} + + )} + + {t('Disconnect')} + +
+ + ); } return ( - <> - - - + ); }; -const KeypairItem = ({ pk }: { pk: PubKey }) => { +const KeypairItem = ({ pk, active }: { pk: PubKey; active: boolean }) => { const [copied, setCopied] = useCopyTimeout(); return ( - -
- - - {pk.name}:{' '} - {truncateByChars(pk.publicKey)} - + +
+ + {pk.name} + {' | '} + {truncateByChars(pk.publicKey)} setCopied(true)}> @@ -270,46 +153,7 @@ const KeypairItem = ({ pk }: { pk: PubKey }) => { {copied && {t('Copied')}}
- - - ); -}; - -const KeypairListItem = ({ - pk, - isActive, - onSelectItem, -}: { - pk: PubKey; - isActive: boolean; - onSelectItem: (pk: string) => void; -}) => { - const [copied, setCopied] = useCopyTimeout(); - - return ( -
- - - {isActive && } - - - {truncateByChars(pk.publicKey)}{' '} - setCopied(true)}> - - - {copied && {t('Copied')}} - -
+ +
); }; diff --git a/apps/trading/components/vega-wallet/index.ts b/apps/trading/components/vega-wallet/index.ts new file mode 100644 index 000000000..41c7fe1ae --- /dev/null +++ b/apps/trading/components/vega-wallet/index.ts @@ -0,0 +1 @@ +export { VegaWalletMenu } from './vega-wallet-menu'; diff --git a/apps/trading/components/vega-wallet/vega-wallet-menu.tsx b/apps/trading/components/vega-wallet/vega-wallet-menu.tsx new file mode 100644 index 000000000..8e3f9d75c --- /dev/null +++ b/apps/trading/components/vega-wallet/vega-wallet-menu.tsx @@ -0,0 +1,106 @@ +import { t } from '@vegaprotocol/i18n'; +import { useCopyTimeout } from '@vegaprotocol/react-helpers'; +import { + TradingButton as Button, + VegaIcon, + VegaIconNames, +} from '@vegaprotocol/ui-toolkit'; +import { truncateByChars } from '@vegaprotocol/utils'; +import { useVegaWallet, type PubKey } from '@vegaprotocol/wallet'; +import { useCallback, useMemo } from 'react'; +import CopyToClipboard from 'react-copy-to-clipboard'; +import { ViewType, useSidebar } from '../sidebar'; + +export const VegaWalletMenu = ({ + setMenu, +}: { + setMenu: (open: 'nav' | 'wallet' | null) => void; +}) => { + const { pubKey, pubKeys, selectPubKey, disconnect } = useVegaWallet(); + const setView = useSidebar((store) => store.setView); + + const activeKey = useMemo(() => { + return pubKeys?.find((pk) => pk.publicKey === pubKey); + }, [pubKey, pubKeys]); + + const onSelectItem = useCallback( + (pubkey: string) => { + selectPubKey(pubkey); + }, + [selectPubKey] + ); + + return ( +
+
+ {(pubKeys || []).map((pk) => ( + + ))} +
+ +
+ + +
+
+ ); +}; + +const KeypairListItem = ({ + pk, + isActive, + onSelectItem, +}: { + pk: PubKey; + isActive: boolean; + onSelectItem: (pk: string) => void; +}) => { + const [copied, setCopied] = useCopyTimeout(); + + return ( +
+ + + {isActive && } + + + {truncateByChars(pk.publicKey)}{' '} + setCopied(true)}> + + + {copied && {t('Copied')}} + +
+ ); +}; diff --git a/apps/trading/pages/_app.page.tsx b/apps/trading/pages/_app.page.tsx index e0c42fd12..231f30006 100644 --- a/apps/trading/pages/_app.page.tsx +++ b/apps/trading/pages/_app.page.tsx @@ -16,6 +16,7 @@ import { } from '@vegaprotocol/web3'; import { envTriggerMapping, + Networks, NodeSwitcherDialog, useEnvironment, useInitializeEnv, @@ -25,7 +26,13 @@ import './styles.css'; import { usePageTitleStore } from '../stores'; import DialogsContainer from './dialogs-container'; import ToastsManager from './toasts-manager'; -import { HashRouter, useLocation, useSearchParams } from 'react-router-dom'; +import { + HashRouter, + useLocation, + Route, + Routes, + useSearchParams, +} from 'react-router-dom'; import { Connectors } from '../lib/vega-connectors'; import { AppLoader, DynamicLoader } from '../components/app-loader'; import { useDataProvider } from '@vegaprotocol/data-provider'; @@ -39,6 +46,8 @@ import { ProtocolUpgradeProposalNotification, } from '@vegaprotocol/proposals'; import { ViewingBanner } from '../components/viewing-banner'; +import { NavHeader } from '../components/navbar/nav-header'; +import { Routes as AppRoutes } from './client-router'; const DEFAULT_TITLE = t('Welcome to Vega trading!'); @@ -74,6 +83,7 @@ const InitializeHandlers = () => { function AppBody({ Component }: AppProps) { const location = useLocation(); + const { VEGA_ENV } = useEnvironment(); const gridClasses = classNames( 'h-full relative z-0 grid', 'grid-rows-[repeat(3,min-content),minmax(0,1fr)]' @@ -87,7 +97,16 @@ function AppBody({ Component }: AppProps) { <div className={gridClasses}> <AnnouncementBanner /> - <Navbar theme="system" /> + <Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'}> + <Routes> + <Route + path={AppRoutes.MARKETS} + // render nothing for markets/all, otherwise markets/:marketId will match with markets/all + element={null} + /> + <Route path={AppRoutes.MARKET} element={<NavHeader />} /> + </Routes> + </Navbar> <div data-testid="banners"> <ProtocolUpgradeProposalNotification mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING} diff --git a/libs/cypress/src/lib/capsule/logging.ts b/libs/cypress/src/lib/capsule/logging.ts index 67ebe79a4..bd2396abe 100644 --- a/libs/cypress/src/lib/capsule/logging.ts +++ b/libs/cypress/src/lib/capsule/logging.ts @@ -1,5 +1,6 @@ export function createLog(name: string) { return (message: string) => { + // eslint-disable-next-line no-console console.log(`[${name}]: ${message}`); }; } diff --git a/libs/cypress/src/lib/capsule/propose-market.ts b/libs/cypress/src/lib/capsule/propose-market.ts index 1ad7c0c9f..09a7a54cb 100644 --- a/libs/cypress/src/lib/capsule/propose-market.ts +++ b/libs/cypress/src/lib/capsule/propose-market.ts @@ -160,7 +160,7 @@ export function waitForProposal(id: string): Promise<{ id: string }> { resolve(res.proposal); } } catch (err) { - console.log(err); + console.error(err); } tick++; diff --git a/libs/cypress/src/lib/commands/import-node-wallets.ts b/libs/cypress/src/lib/commands/import-node-wallets.ts index 35fd03b02..3d51696e3 100644 --- a/libs/cypress/src/lib/commands/import-node-wallets.ts +++ b/libs/cypress/src/lib/commands/import-node-wallets.ts @@ -15,6 +15,7 @@ export const addImportNodeWallets = () => { .its('stdout') .then((result) => { const obj = JSON.parse(result); + // eslint-disable-next-line no-console console.log(obj); cy.writeFile( './src/fixtures/wallet/node0RecoveryPhrase', diff --git a/libs/cypress/src/lib/commands/validators-self-delegate.ts b/libs/cypress/src/lib/commands/validators-self-delegate.ts index 07f689dac..a31f22b8d 100644 --- a/libs/cypress/src/lib/commands/validators-self-delegate.ts +++ b/libs/cypress/src/lib/commands/validators-self-delegate.ts @@ -30,6 +30,7 @@ export const addValidatorsSelfDelegate = () => { .its('stdout') .then((result) => { const obj = JSON.parse(result); + // eslint-disable-next-line no-console console.log(obj); cy.writeFile( './src/fixtures/wallet/node0RecoveryPhrase', diff --git a/libs/cypress/src/lib/commands/vega-wallet-top-up-rewards-pool.ts b/libs/cypress/src/lib/commands/vega-wallet-top-up-rewards-pool.ts index 2942120c4..5436e3962 100644 --- a/libs/cypress/src/lib/commands/vega-wallet-top-up-rewards-pool.ts +++ b/libs/cypress/src/lib/commands/vega-wallet-top-up-rewards-pool.ts @@ -30,8 +30,10 @@ export function addVegaWalletTopUpRewardsPool() { transferStartEpoch = Number(epochText.replace('Epoch', '')) + 5; transferEndEpoch = transferStartEpoch + 100; + /* eslint-disable no-console */ console.log(transferStartEpoch); console.log(transferEndEpoch); + /* eslint-enable */ }); }) .then(() => { diff --git a/libs/cypress/src/lib/eip1193-bridge.ts b/libs/cypress/src/lib/eip1193-bridge.ts index 621867f63..d0e18750d 100644 --- a/libs/cypress/src/lib/eip1193-bridge.ts +++ b/libs/cypress/src/lib/eip1193-bridge.ts @@ -9,12 +9,14 @@ export class CustomizedBridge extends Eip1193Bridge { // eslint-disable-next-line @typescript-eslint/no-explicit-any async sendAsync(...args: any) { + // eslint-disable-next-line no-console console.debug('sendAsync called', ...args); return this.send(...args); } // eslint-disable-next-line @typescript-eslint/no-explicit-any override async send(...args: any) { + // eslint-disable-next-line no-console console.debug('send called', ...args); const isCallbackForm = typeof args[0] === 'object' && typeof args[1] === 'function'; @@ -89,6 +91,7 @@ export class CustomizedBridge extends Eip1193Bridge { // All other transactions the base class works for result = await super.send(method, params); } + // eslint-disable-next-line no-console console.debug('result received', method, params, result); if (isCallbackForm) { callback(null, { result }); @@ -96,6 +99,7 @@ export class CustomizedBridge extends Eip1193Bridge { return result; } } catch (error) { + // eslint-disable-next-line no-console console.log(error); if (isCallbackForm) { callback(error, null); diff --git a/libs/fills/src/lib/fill-actions-dropdown.tsx b/libs/fills/src/lib/fill-actions-dropdown.tsx index 97c7b4d5e..0d1b16e8c 100644 --- a/libs/fills/src/lib/fill-actions-dropdown.tsx +++ b/libs/fills/src/lib/fill-actions-dropdown.tsx @@ -1,6 +1,6 @@ import { ActionsDropdown, - DropdownMenuCopyItem, + TradingDropdownCopyItem, } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/i18n'; @@ -14,10 +14,13 @@ export const FillActionsDropdown = ({ sellOrderId: string; }) => { return ( - <ActionsDropdown data-testid="market-actions-content"> - <DropdownMenuCopyItem value={tradeId} text={t('Copy trade ID')} /> - <DropdownMenuCopyItem value={buyOrderId} text={t('Copy buy order ID')} /> - <DropdownMenuCopyItem + <ActionsDropdown data-testid="fill-actions-content"> + <TradingDropdownCopyItem value={tradeId} text={t('Copy trade ID')} /> + <TradingDropdownCopyItem + value={buyOrderId} + text={t('Copy buy order ID')} + /> + <TradingDropdownCopyItem value={sellOrderId} text={t('Copy sell order ID')} /> diff --git a/libs/logger/src/lib/local-logger.spec.ts b/libs/logger/src/lib/local-logger.spec.ts index 02769629d..8932c8580 100644 --- a/libs/logger/src/lib/local-logger.spec.ts +++ b/libs/logger/src/lib/local-logger.spec.ts @@ -48,6 +48,7 @@ describe('LocalLogger', () => { const consoleMethod = methodToConsoleMethod[i]; jest.spyOn(console, consoleMethod).mockImplementation(); logger[method]('test', 'test2'); + // eslint-disable-next-line no-console expect(console[consoleMethod]).toHaveBeenCalledWith( `trading:${methodToLevel[i]}: `, 'test', @@ -100,10 +101,14 @@ describe('LocalLogger', () => { const logger = localLoggerFactory({ logLevel: 'info' }); jest.spyOn(console, 'debug').mockImplementation(); logger.debug('test', 'test1'); + + // eslint-disable-next-line no-console expect(console.debug).not.toHaveBeenCalled(); logger.setLogLevel('debug'); logger.debug('test', 'test1'); + + // eslint-disable-next-line no-console expect(console.debug).toHaveBeenCalledWith( 'trading:debug: ', 'test', diff --git a/libs/logger/src/lib/local-logger.ts b/libs/logger/src/lib/local-logger.ts index 6d9447792..6086d843b 100644 --- a/libs/logger/src/lib/local-logger.ts +++ b/libs/logger/src/lib/local-logger.ts @@ -99,6 +99,7 @@ export class LocalLogger { this.numberLogLevel <= LocalLogger.levelLogMap[level] // && //!global.__LOGGER_SILENT_MODE__ ) { + // eslint-disable-next-line no-console console[logMethod].apply(console, [ `${this._application}:${level}: `, ...args, diff --git a/libs/markets/src/lib/components/markets-container/market-table-actions.tsx b/libs/markets/src/lib/components/markets-container/market-table-actions.tsx index 295ffc851..21c8df2da 100644 --- a/libs/markets/src/lib/components/markets-container/market-table-actions.tsx +++ b/libs/markets/src/lib/components/markets-container/market-table-actions.tsx @@ -1,7 +1,7 @@ import { t } from '@vegaprotocol/i18n'; import { - DropdownMenuItem, - DropdownMenuCopyItem, + TradingDropdownItem, + TradingDropdownCopyItem, Link, VegaIcon, VegaIconNames, @@ -22,8 +22,8 @@ export const MarketActionsDropdown = ({ return ( <ActionsDropdown data-testid="market-actions-content"> - <DropdownMenuCopyItem value={marketId} text={t('Copy Market ID')} /> - <DropdownMenuItem> + <TradingDropdownCopyItem value={marketId} text={t('Copy Market ID')} /> + <TradingDropdownItem> <Link href={linkCreator(EXPLORER_MARKET.replace(':id', marketId))} target="_blank" @@ -33,15 +33,15 @@ export const MarketActionsDropdown = ({ {t('View on Explorer')} </span> </Link> - </DropdownMenuItem> - <DropdownMenuItem + </TradingDropdownItem> + <TradingDropdownItem onClick={(e) => { open(assetId, e.target as HTMLElement); }} > <VegaIcon name={VegaIconNames.INFO} size={16} /> {t('View settlement asset details')} - </DropdownMenuItem> + </TradingDropdownItem> </ActionsDropdown> ); }; diff --git a/libs/markets/src/lib/components/markets-container/markets-container.tsx b/libs/markets/src/lib/components/markets-container/markets-container.tsx index f4e140dde..3f68d90d5 100644 --- a/libs/markets/src/lib/components/markets-container/markets-container.tsx +++ b/libs/markets/src/lib/components/markets-container/markets-container.tsx @@ -50,6 +50,7 @@ export const MarketsContainer = ({ 'tradableInstrument.instrument.code', 'tradableInstrument.instrument.product.settlementAsset', 'tradableInstrument.instrument.product.settlementAsset.symbol', + 'market-actions', ].includes(colId) ) { return; diff --git a/libs/markets/src/lib/markets-provider.ts b/libs/markets/src/lib/markets-provider.ts index 70cd3b76c..5fe37a720 100644 --- a/libs/markets/src/lib/markets-provider.ts +++ b/libs/markets/src/lib/markets-provider.ts @@ -83,7 +83,6 @@ export const marketProvider = makeDerivedDataProvider< ); export const useMarket = (marketId?: string) => { - console.log(marketId); const variables = useMemo(() => ({ marketId: marketId || '' }), [marketId]); return useDataProvider({ dataProvider: marketProvider, diff --git a/libs/orders/src/lib/components/order-actions-dropdown/order-actions-dropdown.tsx b/libs/orders/src/lib/components/order-actions-dropdown/order-actions-dropdown.tsx index 52301a011..a2d1c917d 100644 --- a/libs/orders/src/lib/components/order-actions-dropdown/order-actions-dropdown.tsx +++ b/libs/orders/src/lib/components/order-actions-dropdown/order-actions-dropdown.tsx @@ -1,13 +1,13 @@ import { ActionsDropdown, - DropdownMenuCopyItem, + TradingDropdownCopyItem, } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/i18n'; export const OrderActionsDropdown = ({ id }: { id: string }) => { return ( - <ActionsDropdown data-testid="market-actions-content"> - <DropdownMenuCopyItem value={id} text={t('Copy order ID')} /> + <ActionsDropdown data-testid="order-actions-content"> + <TradingDropdownCopyItem value={id} text={t('Copy order ID')} /> </ActionsDropdown> ); }; diff --git a/libs/positions/src/lib/position-actions-dropdown.tsx b/libs/positions/src/lib/position-actions-dropdown.tsx index f9740d5c9..8448a6824 100644 --- a/libs/positions/src/lib/position-actions-dropdown.tsx +++ b/libs/positions/src/lib/position-actions-dropdown.tsx @@ -1,7 +1,7 @@ import { t } from '@vegaprotocol/i18n'; import { ActionsDropdown, - DropdownMenuItem, + TradingDropdownItem, VegaIcon, VegaIconNames, } from '@vegaprotocol/ui-toolkit'; @@ -11,15 +11,15 @@ export const PositionActionsDropdown = ({ assetId }: { assetId: string }) => { const open = useAssetDetailsDialogStore((store) => store.open); return ( - <ActionsDropdown data-testid="market-actions-content"> - <DropdownMenuItem + <ActionsDropdown data-testid="position-actions-content"> + <TradingDropdownItem onClick={(e) => { open(assetId, e.target as HTMLElement); }} > <VegaIcon name={VegaIconNames.INFO} size={16} /> {t('View settlement asset details')} - </DropdownMenuItem> + </TradingDropdownItem> </ActionsDropdown> ); }; diff --git a/libs/proposals/src/components/proposal-actions-dropdown.tsx b/libs/proposals/src/components/proposal-actions-dropdown.tsx index 43a1ed4b2..369ec044c 100644 --- a/libs/proposals/src/components/proposal-actions-dropdown.tsx +++ b/libs/proposals/src/components/proposal-actions-dropdown.tsx @@ -1,5 +1,5 @@ import { - DropdownMenuItem, + TradingDropdownItem, VegaIcon, VegaIconNames, Link, @@ -12,8 +12,8 @@ export const ProposalActionsDropdown = ({ id }: { id: string }) => { const linkCreator = useLinks(DApp.Token); return ( - <ActionsDropdown data-testid="market-actions-content"> - <DropdownMenuItem> + <ActionsDropdown data-testid="proposal-actions-content"> + <TradingDropdownItem> <Link href={linkCreator(TOKEN_PROPOSAL.replace(':id', id))} target="_blank" @@ -21,7 +21,7 @@ export const ProposalActionsDropdown = ({ id }: { id: string }) => { <VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} /> {t('View proposal')} </Link> - </DropdownMenuItem> + </TradingDropdownItem> </ActionsDropdown> ); }; diff --git a/libs/proposals/src/components/protocol-upgrade-countdown.tsx b/libs/proposals/src/components/protocol-upgrade-countdown.tsx index 2d8ab4071..e531d6b43 100644 --- a/libs/proposals/src/components/protocol-upgrade-countdown.tsx +++ b/libs/proposals/src/components/protocol-upgrade-countdown.tsx @@ -1,20 +1,25 @@ import { t } from '@vegaprotocol/i18n'; import { useNextProtocolUpgradeProposal, useTimeToUpgrade } from '../lib'; import { convertToCountdownString } from '@vegaprotocol/utils'; -import { IconNames } from '@blueprintjs/icons'; import classNames from 'classnames'; -import { Icon, NavigationContext } from '@vegaprotocol/ui-toolkit'; +import { + NavigationContext, + VegaIcon, + VegaIconNames, +} from '@vegaprotocol/ui-toolkit'; import { useProtocolUpgradeProposalLink } from '@vegaprotocol/environment'; import { useContext } from 'react'; + export enum ProtocolUpgradeCountdownMode { IN_BLOCKS, IN_ESTIMATED_TIME_REMAINING, } + type ProtocolUpgradeCountdownProps = { mode?: ProtocolUpgradeCountdownMode; }; export const ProtocolUpgradeCountdown = ({ - mode = ProtocolUpgradeCountdownMode.IN_BLOCKS, + mode = ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING, }: ProtocolUpgradeCountdownProps) => { const { theme } = useContext(NavigationContext); const { data, lastBlockHeight } = useNextProtocolUpgradeProposal(); @@ -75,20 +80,17 @@ export const ProtocolUpgradeCountdown = ({ <div data-testid="protocol-upgrade-counter" className={classNames( - 'flex flex-nowrap items-center text-xs py-2 px-4', + 'flex flex-nowrap gap-1 items-center text-xs py-1 px-2 lg:px-4 h-8', 'border rounded', 'border-vega-orange-500 dark:border-vega-orange-500', 'bg-vega-orange-300 dark:bg-vega-orange-700', + 'text-default', { '!bg-transparent !border-black': theme === 'yellow', } )} > - <Icon - name={IconNames.WARNING_SIGN} - size={3} - className={classNames('mr-2', emphasis)} - />{' '} + <VegaIcon name={VegaIconNames.EXCLAIMATION_MARK} size={12} />{' '} <span className="flex gap-1 flex-nowrap whitespace-nowrap"> <span>{t('Network upgrade in')} </span> {countdown} diff --git a/libs/tailwindcss-config/src/theme.js b/libs/tailwindcss-config/src/theme.js index eed6e0c80..7234d3c59 100644 --- a/libs/tailwindcss-config/src/theme.js +++ b/libs/tailwindcss-config/src/theme.js @@ -152,7 +152,7 @@ module.exports = { 200: '#7C7E83', 300: '#626469', 400: '#44464B', - 500: '#323339', // surface-container-highest + 500: '#323339', // surface-container-highest, outline-surface-default 600: '#292B30', 700: '#202227', 800: '#17191E', // surface-container diff --git a/libs/ui-toolkit/src/components/dropdown-menu/actions-dropdown.tsx b/libs/ui-toolkit/src/components/dropdown-menu/actions-dropdown.tsx deleted file mode 100644 index bd63862b6..000000000 --- a/libs/ui-toolkit/src/components/dropdown-menu/actions-dropdown.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { VegaIcon, VegaIconNames } from '../icon'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuTrigger, -} from './dropdown-menu'; - -export const ActionsDropdownTrigger = () => { - return ( - <DropdownMenuTrigger - className='hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 [&[aria-expanded="true"]]:bg-vega-light-200 dark:[&[aria-expanded="true"]]:bg-vega-dark-200 p-0.5 rounded-full' - data-testid="dropdown-menu" - > - <VegaIcon name={VegaIconNames.KEBAB} /> - </DropdownMenuTrigger> - ); -}; - -type ActionMenuContentProps = React.ComponentProps<typeof DropdownMenuContent>; -export const ActionsDropdown = (props: ActionMenuContentProps) => { - return ( - <DropdownMenu trigger={<ActionsDropdownTrigger />}> - <DropdownMenuContent {...props}></DropdownMenuContent> - </DropdownMenu> - ); -}; diff --git a/libs/ui-toolkit/src/components/dropdown-menu/dropdown-menu.stories.tsx b/libs/ui-toolkit/src/components/dropdown-menu/dropdown-menu.stories.tsx index 66aef069e..e2c1c7f48 100644 --- a/libs/ui-toolkit/src/components/dropdown-menu/dropdown-menu.stories.tsx +++ b/libs/ui-toolkit/src/components/dropdown-menu/dropdown-menu.stories.tsx @@ -26,7 +26,6 @@ export const CheckboxItems = () => { { label: 'Moving average', state: useState(false) }, { label: 'Price monitoring bands', state: useState(false) }, ]; - console.log(checkboxItems); return ( <DropdownMenu @@ -68,6 +67,7 @@ export const RadioItems = () => { } > <DropdownMenuContent> + {/* eslint-disable no-console */} <DropdownMenuItem onSelect={() => console.log('minimize')}> Minimize window </DropdownMenuItem> @@ -77,6 +77,7 @@ export const RadioItems = () => { <DropdownMenuItem onSelect={() => console.log('smaller')}> Smaller </DropdownMenuItem> + {/* eslint-enable */} <DropdownMenuSeparator /> <DropdownMenuRadioGroup value={selected} onValueChange={setSelected}> {files.map((file) => ( diff --git a/libs/ui-toolkit/src/components/dropdown-menu/index.ts b/libs/ui-toolkit/src/components/dropdown-menu/index.ts index cc428e45d..2759d3ce6 100644 --- a/libs/ui-toolkit/src/components/dropdown-menu/index.ts +++ b/libs/ui-toolkit/src/components/dropdown-menu/index.ts @@ -1,2 +1 @@ export * from './dropdown-menu'; -export * from './actions-dropdown'; diff --git a/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-exclaimation-mark.tsx b/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-exclaimation-mark.tsx new file mode 100644 index 000000000..e0d6db2f9 --- /dev/null +++ b/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-exclaimation-mark.tsx @@ -0,0 +1,7 @@ +export const IconExclaimationMark = ({ size = 16 }: { size: number }) => { + return ( + <svg width={size} height={size} viewBox="0 0 16 16"> + <path d="M8 0.879997L7.57 1.63L0.130005 14.5H15.87L8 0.879997ZM8.75 12H7.25V10.5H8.75V12ZM7.25 9.5V6H8.75V9.5H7.25Z" /> + </svg> + ); +}; diff --git a/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon-record.ts b/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon-record.ts index e84a59600..951f4b69a 100644 --- a/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon-record.ts +++ b/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon-record.ts @@ -11,6 +11,7 @@ import { IconCopy } from './svg-icons/icon-copy'; import { IconCross } from './svg-icons/icon-cross'; import { IconDeposit } from './svg-icons/icon-deposit'; import { IconEdit } from './svg-icons/icon-edit'; +import { IconExclaimationMark } from './svg-icons/icon-exclaimation-mark'; import { IconForum } from './svg-icons/icon-forum'; import { IconGlobe } from './svg-icons/icon-globe'; import { IconInfo } from './svg-icons/icon-info'; @@ -46,6 +47,7 @@ export enum VegaIconNames { CROSS = 'cross', DEPOSIT = 'deposit', EDIT = 'edit', + EXCLAIMATION_MARK = 'exclaimation-mark', FORUM = 'forum', GLOBE = 'globe', INFO = 'info', @@ -85,6 +87,7 @@ export const VegaIconNameMap: Record< cross: IconCross, deposit: IconDeposit, edit: IconEdit, + 'exclaimation-mark': IconExclaimationMark, forum: IconForum, globe: IconGlobe, info: IconInfo, diff --git a/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon.tsx b/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon.tsx index 8b788ec81..cc48b741f 100644 --- a/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon.tsx +++ b/libs/ui-toolkit/src/components/icon/vega-icons/vega-icon.tsx @@ -16,7 +16,7 @@ export const VegaIcon = ({ size = 16, name }: VegaIconProps) => { ); const Element = VegaIconNameMap[name]; return ( - <span className={effectiveClassName}> + <span className={effectiveClassName} data-testid={`icon-${name}`}> <Element size={size} /> </span> ); diff --git a/libs/ui-toolkit/src/components/index.ts b/libs/ui-toolkit/src/components/index.ts index 082e4c5a5..38e0c8b64 100644 --- a/libs/ui-toolkit/src/components/index.ts +++ b/libs/ui-toolkit/src/components/index.ts @@ -49,6 +49,7 @@ export * from './toast'; export * from './toggle'; export * from './tooltip'; export * from './trading-button'; +export * from './trading-dropdown'; export * from './traffic-light'; export * from './vega-icons'; export * from './vega-logo'; diff --git a/libs/ui-toolkit/src/components/nav-dropdown/dropdown-menu.stories.tsx b/libs/ui-toolkit/src/components/nav-dropdown/dropdown-menu.stories.tsx index 6d2ecf4d1..f20cd7b18 100644 --- a/libs/ui-toolkit/src/components/nav-dropdown/dropdown-menu.stories.tsx +++ b/libs/ui-toolkit/src/components/nav-dropdown/dropdown-menu.stories.tsx @@ -19,6 +19,7 @@ export const RadioItems = () => { <span>Open</span> </NavDropdownMenuTrigger> <NavDropdownMenuContent> + {/* eslint-disable no-console */} <NavDropdownMenuItem onSelect={() => console.log('minimize')}> Minimize window </NavDropdownMenuItem> @@ -28,6 +29,7 @@ export const RadioItems = () => { <NavDropdownMenuItem onSelect={() => console.log('smaller')}> Smaller </NavDropdownMenuItem> + {/* eslint-enable */} </NavDropdownMenuContent> </NavDropdownMenu> </div> diff --git a/libs/ui-toolkit/src/components/select/select.stories.tsx b/libs/ui-toolkit/src/components/select/select.stories.tsx index f21265104..6a323e99a 100644 --- a/libs/ui-toolkit/src/components/select/select.stories.tsx +++ b/libs/ui-toolkit/src/components/select/select.stories.tsx @@ -46,6 +46,7 @@ RichDefaultSelect.args = { name: 'rich', placeholder: 'Select an option', onValueChange: (v: string) => { + // eslint-disable-next-line no-console console.log(v); }, children: ( diff --git a/libs/ui-toolkit/src/components/trading-button/trading-button.tsx b/libs/ui-toolkit/src/components/trading-button/trading-button.tsx index 65c4f0ca8..3c9e902d0 100644 --- a/libs/ui-toolkit/src/components/trading-button/trading-button.tsx +++ b/libs/ui-toolkit/src/components/trading-button/trading-button.tsx @@ -8,7 +8,7 @@ import type { import { Intent } from '../../utils/intent'; type TradingButtonProps = { - size: 'large' | 'medium' | 'small'; + size?: 'large' | 'medium' | 'small'; intent?: Intent; children?: ReactNode; icon?: ReactNode; @@ -24,7 +24,7 @@ const getClassName = ( className?: string ) => classNames( - 'flex items-center justify-center rounded', + 'flex gap-2 items-center justify-center rounded', // size { 'h-12': !subLabel && size === 'large', diff --git a/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx b/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx new file mode 100644 index 000000000..474ed8526 --- /dev/null +++ b/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx @@ -0,0 +1,31 @@ +import { VegaIcon, VegaIconNames } from '../icon'; +import { + TradingDropdown, + TradingDropdownContent, + TradingDropdownTrigger, +} from './trading-dropdown'; + +export const ActionsDropdownTrigger = () => { + return ( + <TradingDropdownTrigger + className='hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 [&[aria-expanded="true"]]:bg-vega-light-200 dark:[&[aria-expanded="true"]]:bg-vega-dark-200 p-0.5 rounded-full' + data-testid="dropdown-menu" + > + <button type="button"> + <VegaIcon name={VegaIconNames.KEBAB} /> + </button> + </TradingDropdownTrigger> + ); +}; + +type ActionMenuContentProps = React.ComponentProps< + typeof TradingDropdownContent +>; + +export const ActionsDropdown = (props: ActionMenuContentProps) => { + return ( + <TradingDropdown trigger={<ActionsDropdownTrigger />}> + <TradingDropdownContent {...props} side="bottom" align="end" /> + </TradingDropdown> + ); +}; diff --git a/libs/ui-toolkit/src/components/trading-dropdown/index.ts b/libs/ui-toolkit/src/components/trading-dropdown/index.ts new file mode 100644 index 000000000..bea80fad8 --- /dev/null +++ b/libs/ui-toolkit/src/components/trading-dropdown/index.ts @@ -0,0 +1,2 @@ +export * from './trading-dropdown'; +export * from './actions-dropdown'; diff --git a/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.spec.tsx b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.spec.tsx new file mode 100644 index 000000000..19ee22d5e --- /dev/null +++ b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.spec.tsx @@ -0,0 +1,38 @@ +import { + TradingDropdown, + TradingDropdownContent, + TradingDropdownTrigger, +} from './trading-dropdown'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +describe('DropdownMenu', () => { + const text = 'Dropdown menu content'; + + // Upgrade from @radix-ui/react-dropdown-menu 0.1.6 to 2.0.2 renders + // dropdowns inline (rather than portals). Currently not using a portal + // will break the UI due to z-index issues + it('renders using a portal', async () => { + render( + <div className="test-wrapper"> + <TradingDropdown + trigger={ + <TradingDropdownTrigger> + <button>Trigger</button> + </TradingDropdownTrigger> + } + > + <TradingDropdownContent> + <p>{text}</p> + </TradingDropdownContent> + </TradingDropdown> + </div> + ); + + userEvent.click(screen.getByText(/trigger/i)); + const contentElement = await screen.findByText(text); + expect(contentElement).toBeInTheDocument(); + // if content is within .test-wrapper then its not been rendered in a portal + expect(contentElement.closest('.test-wrapper')).toBe(null); + }); +}); diff --git a/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx new file mode 100644 index 000000000..8d35d3590 --- /dev/null +++ b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx @@ -0,0 +1,209 @@ +import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; +import classNames from 'classnames'; +import type { ComponentProps, ReactNode } from 'react'; +import { forwardRef } from 'react'; +import { VegaIcon, VegaIconNames } from '../icon'; +import { useCopyTimeout } from '@vegaprotocol/react-helpers'; +import CopyToClipboard from 'react-copy-to-clipboard'; +import { t } from '@vegaprotocol/i18n'; + +const itemClass = classNames( + 'relative flex gap-2 items-center rounded-sm p-2 text-sm', + 'cursor-default hover:cursor-pointer', + 'hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400', + 'focus:bg-vega-clight-400 dark:focus:bg-vega-cdark-400', + 'select-none', + 'whitespace-nowrap' +); + +type TradingDropdownProps = DropdownMenuPrimitive.DropdownMenuProps & { + trigger: ReactNode; +}; + +/** + * Contains all the parts of a dropdown menu. + */ +export const TradingDropdown = ({ + children, + trigger, + ...props +}: TradingDropdownProps) => { + return ( + <DropdownMenuPrimitive.Root {...props}> + {trigger} + <DropdownMenuPrimitive.Portal>{children}</DropdownMenuPrimitive.Portal> + </DropdownMenuPrimitive.Root> + ); +}; +/** + * The button that toggles the dropdown menu. + * By default, the {@link TradingDropdownContent} will position itself against the trigger. + */ +export const TradingDropdownTrigger = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.Trigger>, + DropdownMenuPrimitive.DropdownMenuTriggerProps +>(({ className, children, ...props }, forwardedRef) => { + return ( + <DropdownMenuPrimitive.Trigger + asChild={true} + ref={forwardedRef} + className={className} + {...props} + > + {children} + </DropdownMenuPrimitive.Trigger> + ); +}); +TradingDropdownTrigger.displayName = 'DropdownMenuTrigger'; + +/** + * Used to group multiple {@link TradingDropdownRadioItem}s. + */ +export const TradingDropdownRadioGroup = DropdownMenuPrimitive.RadioGroup; + +/** + * The component that pops out when the dropdown menu is open. + */ +export const TradingDropdownContent = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.Content>, + React.ComponentProps<typeof DropdownMenuPrimitive.Content> +>( + ( + { className, align = 'start', side, sideOffset = 10, ...contentProps }, + forwardedRef + ) => ( + <DropdownMenuPrimitive.Content + ref={forwardedRef} + className={classNames( + 'min-w-[290px] bg-vega-clight-700 dark:bg-vega-cdark-700', + 'border border-vega-clight-500 dark:border-vega-cdark-500', + 'p-2 rounded z-20 text-default' + )} + align={align} + sideOffset={sideOffset} + side={side} + {...contentProps} + /> + ) +); +TradingDropdownContent.displayName = 'DropdownMenuContent'; + +/** + * The component that contains the dropdown menu items. + */ +export const TradingDropdownItem = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.Item>, + React.ComponentProps<typeof DropdownMenuPrimitive.Item> +>(({ className, ...itemProps }, forwardedRef) => ( + <DropdownMenuPrimitive.Item + {...itemProps} + ref={forwardedRef} + className={classNames(itemClass, className)} + /> +)); +TradingDropdownItem.displayName = 'DropdownMenuItem'; + +/** + * An item that can be controlled and rendered like a checkbox. + */ +export const TradingDropdownCheckboxItem = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, + React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> +>(({ className, ...checkboxItemProps }, forwardedRef) => ( + <DropdownMenuPrimitive.CheckboxItem + {...checkboxItemProps} + ref={forwardedRef} + className={classNames(itemClass, 'justify-between', className)} + /> +)); +TradingDropdownCheckboxItem.displayName = 'DropdownMenuCheckboxItem'; + +/** + * An item that can be controlled and rendered like a radio. + */ +export const TradingDropdownRadioItem = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, + React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & { + inset?: boolean; + } +>(({ className, inset = false, ...radioItemProps }, forwardedRef) => ( + <DropdownMenuPrimitive.RadioItem + {...radioItemProps} + ref={forwardedRef} + className={classNames(itemClass, 'justify-between', className)} + /> +)); +TradingDropdownRadioItem.displayName = 'DropdownMenuRadioItem'; + +/** + * Renders when the parent {@link TradingDropdownCheckboxItem} or {@link TradingDropdownRadioItem} is checked. + * You can style this element directly, or you can use it as a wrapper to put an icon into, or both. + */ +export const TradingDropdownItemIndicator = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.ItemIndicator>, + React.ComponentProps<typeof DropdownMenuPrimitive.ItemIndicator> +>(({ ...itemIndicatorProps }, forwardedRef) => ( + <DropdownMenuPrimitive.ItemIndicator + {...itemIndicatorProps} + ref={forwardedRef} + className="flex-end text-vega-green" + > + <VegaIcon name={VegaIconNames.TICK} /> + </DropdownMenuPrimitive.ItemIndicator> +)); +TradingDropdownItemIndicator.displayName = 'DropdownMenuItemIndicator'; + +/** + * Used to visually separate items in the dropdown menu. + */ +export const TradingDropdownSeparator = forwardRef< + React.ElementRef<typeof DropdownMenuPrimitive.Separator>, + React.ComponentProps<typeof DropdownMenuPrimitive.Separator> +>(({ className, ...separatorProps }, forwardedRef) => ( + <DropdownMenuPrimitive.Separator + {...separatorProps} + ref={forwardedRef} + className={classNames( + 'h-px my-1 mx-2 bg-vega-clight-500 dark:bg-vega-cdark-500', + className + )} + /> +)); +TradingDropdownSeparator.displayName = 'DropdownMenuSeparator'; + +/** + * Portal to ensure menu portions are rendered outwith where they appear in the + * DOM. + */ +export const TradingDropdownPortal = ( + portalProps: ComponentProps<typeof DropdownMenuPrimitive.Portal> +) => <DropdownMenuPrimitive.Portal {...portalProps} />; + +/** + * Wraps a regular DropdownMenuItem with copy to clip board functionality + */ +export const TradingDropdownCopyItem = ({ + value, + text, +}: { + value: string; + text: string; +}) => { + const [copied, setCopied] = useCopyTimeout(); + + return ( + <CopyToClipboard text={value} onCopy={() => setCopied(true)}> + <TradingDropdownItem + onClick={(e) => { + e.preventDefault(); + }} + > + <VegaIcon name={VegaIconNames.COPY} size={16} /> + {text} + {copied && ( + <span className="text-xs text-neutral-500">{t('Copied')}</span> + )} + </TradingDropdownItem> + </CopyToClipboard> + ); +}; diff --git a/libs/web3/src/lib/eip-1193-custom-bridge.ts b/libs/web3/src/lib/eip-1193-custom-bridge.ts index d69b666ce..94aa433a6 100644 --- a/libs/web3/src/lib/eip-1193-custom-bridge.ts +++ b/libs/web3/src/lib/eip-1193-custom-bridge.ts @@ -4,12 +4,14 @@ import { ethers } from 'ethers'; export class Eip1193CustomBridge extends Eip1193Bridge { // eslint-disable-next-line @typescript-eslint/no-explicit-any async sendAsync(...args: any) { + // eslint-disable-next-line no-console console.debug('sendAsync called', ...args); return this.send(...args); } // eslint-disable-next-line @typescript-eslint/no-explicit-any override async send(...args: any) { + // eslint-disable-next-line no-console console.debug('send called', ...args); const isCallbackForm = typeof args[0] === 'object' && typeof args[1] === 'function'; @@ -68,6 +70,7 @@ export class Eip1193CustomBridge extends Eip1193Bridge { // All other transactions the base class works for result = await super.send(method, params); } + // eslint-disable-next-line no-console console.debug('result received', method, params, result); if (isCallbackForm) { callback(null, { result }); diff --git a/libs/web3/src/lib/web3-connect-dialog.tsx b/libs/web3/src/lib/web3-connect-dialog.tsx index 6ba540ce3..bee86e392 100644 --- a/libs/web3/src/lib/web3-connect-dialog.tsx +++ b/libs/web3/src/lib/web3-connect-dialog.tsx @@ -89,7 +89,7 @@ const ConnectButton = ({ setEagerConnector(info.name); onClick?.(); } catch (err) { - console.log('could not connect to the wallet', info.name, err); + console.warn('could not connect to the wallet', info.name, err); // NOOP - cancelled wallet connector } }} diff --git a/libs/web3/src/lib/web3-connectors.ts b/libs/web3/src/lib/web3-connectors.ts index 2a3cff027..1d9bb2616 100644 --- a/libs/web3/src/lib/web3-connectors.ts +++ b/libs/web3/src/lib/web3-connectors.ts @@ -26,7 +26,7 @@ export const initializeCoinbaseConnector = (providerUrl: string) => url: providerUrl, }, onError: (error) => { - console.log('ERR_COINBASE_WALLET', error); + console.warn('ERR_COINBASE_WALLET', error); useWeb3ConnectStore.setState({ error }); }, }) @@ -82,7 +82,7 @@ export const initializeWalletConnector = ( }, }, onError: (error) => { - console.log('ERR_WALLET_CONNECT', error.message); + console.warn('ERR_WALLET_CONNECT', error.message); useWeb3ConnectStore.setState({ error }); }, }) @@ -98,7 +98,7 @@ export const initializeMetaMaskConnector = () => mustBeMetaMask: false, }, onError: (error) => { - console.log('ERR_META_MASK', error.message); + console.warn('ERR_META_MASK', error.message); useWeb3ConnectStore.setState({ error }); }, }) diff --git a/libs/withdraws/src/lib/withdrawals-table.tsx b/libs/withdraws/src/lib/withdrawals-table.tsx index 189bedb7d..f5bbc2de2 100644 --- a/libs/withdraws/src/lib/withdrawals-table.tsx +++ b/libs/withdraws/src/lib/withdrawals-table.tsx @@ -12,7 +12,7 @@ import { t } from '@vegaprotocol/i18n'; import { ActionsDropdown, ButtonLink, - DropdownMenuItem, + TradingDropdownItem, VegaIcon, VegaIconNames, } from '@vegaprotocol/ui-toolkit'; @@ -175,7 +175,7 @@ export const CompleteCell = ({ data, complete }: CompleteCellProps) => { </ButtonLink> <ActionsDropdown> - <DropdownMenuItem + <TradingDropdownItem key={'withdrawal-approval'} data-testid="withdrawal-approval" onClick={() => { @@ -186,7 +186,7 @@ export const CompleteCell = ({ data, complete }: CompleteCellProps) => { > <VegaIcon name={VegaIconNames.BREAKDOWN} size={16} /> {t('View withdrawal details')} - </DropdownMenuItem> + </TradingDropdownItem> </ActionsDropdown> </div> );