diff --git a/apps/token-e2e/src/integration/flow/governance-flow.cy.js b/apps/token-e2e/src/integration/flow/governance-flow.cy.js index 53e4cfa90..9f1c4261a 100644 --- a/apps/token-e2e/src/integration/flow/governance-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/governance-flow.cy.js @@ -52,7 +52,6 @@ context( function () { before('connect wallets and set approval limit', function () { cy.visit('/'); - cy.verify_page_header('The $VEGA token'); cy.get_network_parameters().then((network_parameters) => { cy.wrap( network_parameters['spam.protection.proposal.min.tokens'] / @@ -132,7 +131,7 @@ context( cy.wait_for_spinner(); cy.connectVegaWallet(); cy.ethereum_wallet_connect(); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); }); @@ -207,7 +206,7 @@ context( let arrayOfProposals = []; - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); cy.get(proposalDetailsTitle) .each((proposalTitleElement) => { @@ -223,16 +222,16 @@ context( it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () { cy.ensure_specified_unstaked_tokens_are_associated('2'); - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', '2'); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.wait_for_spinner(); cy.click_on_validator_from_list(0); cy.staking_validator_page_add_stake('2'); cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2'); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); cy.enter_unique_freeform_proposal_body('50', generateProposalTitle()); @@ -320,14 +319,14 @@ context( cy.ensure_specified_unstaked_tokens_are_associated( tokensRequiredToAchieveResult ); - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.get('@submittedProposal').within(() => cy.get(viewProposalButton).click() ); cy.get_proposal_information_from_table('Participation met') .contains('👍') .should('be.visible'); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); cy.get('@submittedProposal').within(() => cy.get(voteStatus).should('have.text', 'Participation met') @@ -378,7 +377,7 @@ context( cy.wait_for_proposal_submitted(); cy.wait_for_proposal_sync(); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); cy.get_submitted_proposal_from_proposal_list(proposalTitle).within( () => cy.get(viewProposalButton).click() @@ -523,7 +522,7 @@ context( cy.ensure_specified_unstaked_tokens_are_associated( tokensRequiredToAchieveResult ); - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.get('@submittedProposal').within(() => cy.get(viewProposalButton).click() ); @@ -611,7 +610,7 @@ context( cy.contains('Proposal rejected', proposalTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); cy.wait_for_proposal_sync(); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); cy.get(rejectProposalsLink).click().wait_for_spinner(); cy.get('@rawProposal').then((rawProposal) => { @@ -808,7 +807,7 @@ context( cy.get(newProposalSubmitButton).should('be.visible').click(); cy.wait_for_proposal_submitted(); cy.wait_for_proposal_sync(); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); } @@ -820,7 +819,7 @@ context( cy.wait_for_proposal_submitted(); cy.wait_for_proposal_sync(); cy.get(proposalDetailsTitle).invoke('text').as('proposalTitle'); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); } diff --git a/apps/token-e2e/src/integration/flow/governance-forms-flow.cy.js b/apps/token-e2e/src/integration/flow/governance-forms-flow.cy.js index a4699ac12..656d8ac47 100644 --- a/apps/token-e2e/src/integration/flow/governance-forms-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/governance-forms-flow.cy.js @@ -41,7 +41,6 @@ context( function () { before('connect wallets and set approval limit', function () { cy.visit('/'); - cy.verify_page_header('The $VEGA token'); cy.vega_wallet_set_specified_approval_amount('1000'); }); @@ -50,7 +49,7 @@ context( cy.wait_for_spinner(); cy.connectVegaWallet(); cy.ethereum_wallet_connect(); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); }); @@ -74,7 +73,7 @@ context( }); it('Unable to submit network parameter with missing/invalid fields', function () { - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(inputError).should('have.length', 3); @@ -99,7 +98,7 @@ context( }); it('Unable to submit network parameter proposal with vote deadline above enactment deadline', function () { - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); cy.get(newProposalTitle).type('Test update network parameter proposal'); cy.get(newProposalDescription).type('invalid deadlines'); diff --git a/apps/token-e2e/src/integration/flow/staking-flow.cy.js b/apps/token-e2e/src/integration/flow/staking-flow.cy.js index c63b54627..05c5c2c8d 100644 --- a/apps/token-e2e/src/integration/flow/staking-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/staking-flow.cy.js @@ -33,7 +33,6 @@ context( // 2001-STKE-002, 2001-STKE-032 before('visit staking tab and connect vega wallet', function () { cy.visit('/'); - cy.verify_page_header('The $VEGA token'); cy.vega_wallet_set_specified_approval_amount('1000'); }); @@ -46,7 +45,7 @@ context( cy.connectVegaWallet(); cy.ethereum_wallet_connect(); cy.vega_wallet_teardown(); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.wait_for_spinner(); } ); @@ -95,7 +94,7 @@ context( .contains(2.0, epochTimeout) .should('be.visible'); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%'); }); @@ -142,14 +141,14 @@ context( .contains(2.0, epochTimeout) .should('be.visible'); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%'); }); it('Able to stake against a validator - using vega from both wallet and vesting contract', function () { cy.staking_page_associate_tokens('3', { type: 'contract' }); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.staking_page_associate_tokens('4', { type: 'wallet' }); cy.get(vegaWalletUnstakedBalance, txTimeout).should( @@ -202,7 +201,7 @@ context( .contains(6.0, epochTimeout) .should('be.visible'); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '6.00', '100%'); }); @@ -232,7 +231,7 @@ context( .parent() .should('contain', 2.0, txTimeout); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.click_on_validator_from_list(1); @@ -253,7 +252,7 @@ context( .eq(1) .should('contain', 1.0, txTimeout); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.wait_for_spinner(); cy.get(`[row-id="${0}"]`).within(() => { @@ -310,7 +309,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); // 2001-STKE-040 cy.click_on_validator_from_list(0); @@ -343,7 +342,7 @@ context( cy.get(totalStake, epochTimeout).should('contain.text', '2'); cy.get(stakeShare, epochTimeout).should('have.text', '100%'); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%'); }); @@ -370,7 +369,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.click_on_validator_from_list('0'); @@ -399,7 +398,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%'); }); @@ -429,7 +428,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.click_on_validator_from_list(0); @@ -470,7 +469,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.click_on_validator_from_list(0); @@ -536,7 +535,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%'); }); @@ -590,7 +589,7 @@ context( txTimeout ); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%'); }); @@ -637,7 +636,7 @@ context( .should('contain', 2.0, txTimeout) .and('contain', partValidatorId); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%'); }); diff --git a/apps/token-e2e/src/integration/flow/token-association-flow.cy.js b/apps/token-e2e/src/integration/flow/token-association-flow.cy.js index 01b4e2fe3..4cdc1f7a1 100644 --- a/apps/token-e2e/src/integration/flow/token-association-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/token-association-flow.cy.js @@ -7,11 +7,11 @@ const vegaWalletUnstakedBalance = '[data-testid="vega-wallet-balance-unstaked"]'; const txTimeout = Cypress.env('txTimeout'); const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort'); -const ethWalletAssociateButton = '[href="/staking/associate"]'; +const ethWalletAssociateButton = '[href="/validators/associate"]'; const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]'; const tokenAmountInputBox = '[data-testid="token-amount-input"]'; const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; -const ethWalletDissociateButton = '[href="/staking/disassociate"]'; +const ethWalletDissociateButton = '[href="/validators/disassociate"]'; const vestingContractSection = '[data-testid="vega-in-vesting-contract"]'; const vegaInWalletSection = '[data-testid="vega-in-wallet"]'; const connectedVegaKey = '[data-testid="connected-vega-key"]'; @@ -27,7 +27,6 @@ context( function () { before('visit staking tab and connect vega wallet', function () { cy.visit('/'); - cy.verify_page_header('The $VEGA token'); cy.vega_wallet_set_specified_approval_amount('1000'); }); @@ -40,7 +39,7 @@ context( cy.connectVegaWallet(); cy.ethereum_wallet_connect(); cy.vega_wallet_teardown(); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.wait_for_spinner(); } ); @@ -257,7 +256,7 @@ context( cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52); }); - cy.navigate_to('staking'); + cy.navigate_to('validators'); cy.staking_page_disassociate_tokens('9', { type: 'wallet' }); cy.get(vegaInWalletSection).within(() => { diff --git a/apps/token-e2e/src/integration/flow/withdrawal-flow.cy.js b/apps/token-e2e/src/integration/flow/withdrawal-flow.cy.js index 86a917307..b98fc5d0e 100644 --- a/apps/token-e2e/src/integration/flow/withdrawal-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/withdrawal-flow.cy.js @@ -33,7 +33,7 @@ context( beforeEach('Navigate to withdrawal page', function () { cy.reload(); cy.visit('/'); - cy.navigate_to('withdrawals'); + cy.navigate_to('withdraw'); cy.wait_for_spinner(); cy.connectVegaWallet(); cy.ethereum_wallet_connect(); diff --git a/apps/token-e2e/src/integration/view/governance.cy.js b/apps/token-e2e/src/integration/view/governance.cy.js index 0b09cd58e..cc91b4905 100644 --- a/apps/token-e2e/src/integration/view/governance.cy.js +++ b/apps/token-e2e/src/integration/view/governance.cy.js @@ -9,12 +9,12 @@ context( { tags: '@smoke' }, function () { before('navigate to governance page', function () { - cy.visit('/').navigate_to('governance'); + cy.visit('/').navigate_to('proposals'); }); describe('with no network change proposals', function () { it('should have governance tab highlighted', function () { - cy.verify_tab_highlighted('governance'); + cy.verify_tab_highlighted('proposals'); }); it('should have GOVERNANCE header visible', function () { @@ -49,7 +49,7 @@ context( .should('be.visible') .and('have.text', 'New proposal') .and('have.attr', 'href') - .and('equal', '/governance/propose'); + .and('equal', '/proposals/propose'); }); // Skipping this test for now, the new proposal button no longer takes a user directly @@ -60,7 +60,7 @@ context( cy.get(connectToVegaWalletButton) .should('be.visible') .and('have.text', 'Connect Vega wallet'); - cy.navigate_to('governance'); + cy.navigate_to('proposals'); cy.wait_for_spinner(); }); }); diff --git a/apps/token-e2e/src/integration/view/home.cy.js b/apps/token-e2e/src/integration/view/home.cy.js index 1759f1f75..c9d5a0983 100644 --- a/apps/token-e2e/src/integration/view/home.cy.js +++ b/apps/token-e2e/src/integration/view/home.cy.js @@ -1,10 +1,10 @@ const navSection = 'nav'; -const navHome = '[href="/"]'; -const navVesting = '[href="/vesting"]'; -const navStaking = '[href="/staking"]'; +const navVesting = '[href="/token/tranches"]'; +const navToken = '[href="/token"]'; +const navStaking = '[href="/validators"]'; const navRewards = '[href="/rewards"]'; -const navWithdraw = '[href="/withdrawals"]'; -const navGovernance = '[href="/governance"]'; +const navWithdraw = '[href="/token/withdraw"]'; +const navGovernance = '[href="/proposals"]'; const tokenDetailsTable = '.token-details'; const address = '[data-testid="token-address"]'; @@ -25,7 +25,7 @@ const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress'); context('Home Page - verify elements on page', { tags: '@smoke' }, function () { before('visit token home page', function () { - cy.visit('/'); + cy.visit('/token'); }); describe('with wallets disconnected', function () { @@ -34,9 +34,9 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () { }); describe('Navigation tabs', function () { - it('should have HOME tab', function () { + it('should have TOKEN tab', function () { cy.get(navSection).within(() => { - cy.get(navHome).should('be.visible'); + cy.get(navToken).should('be.visible'); }); }); it('should have VESTING tab', function () { @@ -106,14 +106,14 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () { cy.get(tranchesLink) .should('be.visible') .and('have.attr', 'href') - .and('equal', '/tranches'); + .and('equal', '/token/tranches'); }); it('should have REDEEM button', function () { cy.get(redeemBtn) .should('be.visible') .parent() .should('have.attr', 'href') - .and('equal', '/vesting'); + .and('equal', '/token/redeem'); }); it('should have GET VEGA WALLET link', function () { cy.get(getVegaWalletLink) @@ -125,21 +125,21 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () { cy.get(associateVegaLink) .should('be.visible') .and('have.attr', 'href') - .and('equal', '/staking/associate'); + .and('equal', '/validators/associate'); }); it('should have STAKING button', function () { cy.get(stakingBtn) .should('be.visible') .parent() .should('have.attr', 'href') - .and('equal', '/staking'); + .and('equal', '/validators'); }); it('should have GOVERNANCE button', function () { cy.get(governanceBtn) .should('be.visible') .parent() .should('have.attr', 'href') - .and('equal', '/governance'); + .and('equal', '/proposals'); }); }); }); diff --git a/apps/token-e2e/src/integration/view/staking.cy.js b/apps/token-e2e/src/integration/view/staking.cy.js index 8a7d95f64..fb4dd125c 100644 --- a/apps/token-e2e/src/integration/view/staking.cy.js +++ b/apps/token-e2e/src/integration/view/staking.cy.js @@ -15,13 +15,13 @@ const stakeNumberRegex = /^\d*\.?\d*$/; context('Staking Page - verify elements on page', function () { before('navigate to staking page', function () { - cy.visit('/').navigate_to('staking'); + cy.visit('/').navigate_to('validators'); }); describe('with wallets disconnected', { tags: '@smoke' }, function () { describe('description section', function () { it('Should have staking tab highlighted', function () { - cy.verify_tab_highlighted('staking'); + cy.verify_tab_highlighted('validators'); }); it('Should have STAKING ON VEGA header visible', function () { diff --git a/apps/token-e2e/src/integration/view/vesting.cy.js b/apps/token-e2e/src/integration/view/vesting.cy.js index 30bebd176..93910b134 100644 --- a/apps/token-e2e/src/integration/view/vesting.cy.js +++ b/apps/token-e2e/src/integration/view/vesting.cy.js @@ -5,11 +5,10 @@ context( 'Vesting Page - verify elements on page', { tags: '@smoke' }, function () { - before('navigate to vesting page', function () { - cy.visit('/').navigate_to('vesting'); - }); - describe('with wallets disconnected', function () { + before('navigate to vesting page', function () { + cy.visit('/').navigate_to('vesting'); + }); it('should have vesting tab highlighted', function () { cy.verify_tab_highlighted('vesting'); }); @@ -32,15 +31,16 @@ context( describe('with eth wallet connected', function () { before('connect eth wallet', function () { cy.ethereum_wallet_connect(); + cy.visit('/'); }); // 1005-VEST-001 // 1005-VEST-002 it('Able to view tranches', function () { - cy.get('[href="/tranches"]') - .should('have.text', 'all tranches') + cy.get('[href="/token/tranches"]') + .should('have.text', 'Supply & Vesting') .click(); - cy.url().should('include', '/tranches'); + cy.url().should('include', '/token/tranches'); cy.get('h1').should('contain.text', 'Vesting tranches'); }); }); diff --git a/apps/token-e2e/src/integration/view/wallet-eth.cy.js b/apps/token-e2e/src/integration/view/wallet-eth.cy.js index 2b2e4658b..ea7edd0d3 100644 --- a/apps/token-e2e/src/integration/view/wallet-eth.cy.js +++ b/apps/token-e2e/src/integration/view/wallet-eth.cy.js @@ -2,8 +2,8 @@ const walletContainer = '[data-testid="ethereum-wallet"]'; const walletHeader = '[data-testid="wallet-header"] h1'; const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]'; const connectorList = '[data-testid="web3-connector-list"]'; -const associate = '[href="/staking/associate"]'; -const disassociate = '[href="/staking/disassociate"]'; +const associate = '[href="/validators/associate"]'; +const disassociate = '[href="/validators/disassociate"]'; const disconnect = '[data-testid="disconnect-from-eth-wallet-button"]'; const accountNo = '[data-testid="ethereum-account-truncated"]'; const currencyTitle = '[data-testid="currency-title"]'; diff --git a/apps/token-e2e/src/integration/view/wallet-vega.cy.js b/apps/token-e2e/src/integration/view/wallet-vega.cy.js index 27f589e9f..59ac74cc0 100644 --- a/apps/token-e2e/src/integration/view/wallet-vega.cy.js +++ b/apps/token-e2e/src/integration/view/wallet-vega.cy.js @@ -18,8 +18,8 @@ const walletName = '[data-testid="wallet-name"]'; const currencyTitle = '[data-testid="currency-title"]'; const currencyValue = '[data-testid="currency-value"]'; const vegaUnstaked = '[data-testid="vega-wallet-balance-unstaked"] .text-right'; -const governanceBtn = '[href="/governance"]'; -const stakingBtn = '[href="/staking"]'; +const governanceBtn = '[href="/proposals"]'; +const stakingBtn = '[href="/validators"]'; const manageLink = '[data-testid="manage-vega-wallet"]'; const dialogVegaKey = '[data-testid="vega-public-key-full"]'; const dialogDisconnectBtn = '[data-testid="disconnect"]'; diff --git a/apps/token-e2e/src/integration/view/withdraw.cy.js b/apps/token-e2e/src/integration/view/withdraw.cy.js index f817a24c6..1b9d5d32e 100644 --- a/apps/token-e2e/src/integration/view/withdraw.cy.js +++ b/apps/token-e2e/src/integration/view/withdraw.cy.js @@ -5,12 +5,12 @@ context( { tags: '@smoke' }, function () { before('navigate to withdrawals page', function () { - cy.visit('/').navigate_to('withdrawals'); + cy.visit('/').navigate_to('withdraw'); }); describe('with wallets disconnected', function () { it('should have withdraw tab highlighted', function () { - cy.verify_tab_highlighted('withdrawals'); + cy.verify_tab_highlighted('withdraw'); }); it('should have WITHDRAW header visible', function () { diff --git a/apps/token-e2e/src/support/common.functions.js b/apps/token-e2e/src/support/common.functions.js index 4266ef186..da0c1ef62 100644 --- a/apps/token-e2e/src/support/common.functions.js +++ b/apps/token-e2e/src/support/common.functions.js @@ -8,13 +8,13 @@ Cypress.Commands.add( const navigation = { section: 'nav', - home: '[href="/"]', - vesting: '[href="/vesting"]', - staking: '[href="/staking"]', + vesting: '[href="/token/redeem"]', + validators: '[href="/validators"]', rewards: '[href="/rewards"]', - withdrawals: '[href="/withdrawals"]', - governance: '[href="/governance"]', + withdraw: '[href="/token/withdraw"]', + proposals: '[href="/proposals"]', pageSpinner: '[data-testid="splash-loader"]', + token: '[href="/token"]', }; Cypress.Commands.add('navigate_to', (page) => { diff --git a/apps/token-e2e/src/support/governance.functions.js b/apps/token-e2e/src/support/governance.functions.js index 72162dc43..0060a2e3f 100644 --- a/apps/token-e2e/src/support/governance.functions.js +++ b/apps/token-e2e/src/support/governance.functions.js @@ -172,9 +172,9 @@ Cypress.Commands.add('get_sort_order_of_supplied_array', (suppliedArray) => { }); Cypress.Commands.add('go_to_make_new_proposal', (proposalType) => { - cy.navigate_to_page_if_not_already_loaded('governance'); + cy.navigate_to_page_if_not_already_loaded('proposals'); cy.get(newProposalButton).should('be.visible').click(); - cy.url().should('include', '/governance/propose'); + cy.url().should('include', '/proposals/propose'); cy.wait_for_spinner(); cy.get('li').contains(proposalType).click(); }); diff --git a/apps/token-e2e/src/support/staking.functions.js b/apps/token-e2e/src/support/staking.functions.js index 9d41b6e74..c1197fd16 100644 --- a/apps/token-e2e/src/support/staking.functions.js +++ b/apps/token-e2e/src/support/staking.functions.js @@ -3,8 +3,8 @@ const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; const tokenInputApprove = '[data-testid="token-input-approve-button"]'; const addStakeRadioButton = '[data-testid="add-stake-radio"]'; const removeStakeRadioButton = '[data-testid="remove-stake-radio"]'; -const ethWalletAssociateButton = '[href="/staking/associate"]'; -const ethWalletDissociateButton = '[href="/staking/disassociate"]'; +const ethWalletAssociateButton = '[href="/validators/associate"]'; +const ethWalletDissociateButton = '[href="/validators/disassociate"]'; const vegaWalletUnstakedBalance = '[data-testid="vega-wallet-balance-unstaked"]'; const vegaWalletAssociatedBalance = '[data-testid="currency-value"]'; diff --git a/apps/token/src/app.tsx b/apps/token/src/app.tsx index 579942f93..ab1bdf15a 100644 --- a/apps/token/src/app.tsx +++ b/apps/token/src/app.tsx @@ -88,7 +88,7 @@ const Web3Container = ({ <> -
+
diff --git a/apps/token/src/components/eth-wallet/eth-wallet.tsx b/apps/token/src/components/eth-wallet/eth-wallet.tsx index 1c52b14cc..79da2f651 100644 --- a/apps/token/src/components/eth-wallet/eth-wallet.tsx +++ b/apps/token/src/components/eth-wallet/eth-wallet.tsx @@ -164,12 +164,12 @@ const ConnectedKey = () => { )} - + - + diff --git a/apps/token/src/components/nav/nav-draw.tsx b/apps/token/src/components/nav/nav-draw.tsx new file mode 100644 index 000000000..7fdbbe6bc --- /dev/null +++ b/apps/token/src/components/nav/nav-draw.tsx @@ -0,0 +1,124 @@ +import classNames from 'classnames'; +import { NavLink } from 'react-router-dom'; +import { + AppStateActionType, + useAppState, +} from '../../contexts/app-state/app-state-context'; +import * as Dialog from '@radix-ui/react-dialog'; +import { EthWallet } from '../eth-wallet'; +import { VegaWallet } from '../vega-wallet'; + +interface Route { + name: string; + path: string; +} + +const DrawerSection = ({ children }: { children: React.ReactNode }) => ( +
{children}
+); + +const IconLine = ({ inverted }: { inverted: boolean }) => ( + +); + +const DrawerNavLinks = ({ + isInverted, + routes, +}: { + isInverted?: boolean; + routes: Route[]; +}) => { + const { appDispatch } = useAppState(); + const linkProps = { + end: true, + onClick: () => + appDispatch({ type: AppStateActionType.SET_DRAWER, isOpen: false }), + }; + const navClasses = classNames('flex flex-col'); + + return ( + + ); +}; + +export const NavDrawer = ({ + inverted, + routes, +}: { + inverted: boolean; + routes: Route[]; +}) => { + const { appState, appDispatch } = useAppState(); + + const drawerContentClasses = classNames( + 'drawer-content', // needed for css animation + // Positions the modal in the center of screen + 'fixed w-[80vw] max-w-[420px] top-0 right-0', + 'flex flex-col flex-nowrap justify-between h-full bg-banner overflow-y-scroll border-l border-white', + 'bg-black text-neutral-200' + ); + return ( + <> + + + + appDispatch({ + type: AppStateActionType.SET_DRAWER, + isOpen, + }) + } + > + + + +
+ + + + + + +
+ +
+
+
+ + ); +}; diff --git a/apps/token/src/components/nav/nav.tsx b/apps/token/src/components/nav/nav.tsx index af047ea3f..245e119f0 100644 --- a/apps/token/src/components/nav/nav.tsx +++ b/apps/token/src/components/nav/nav.tsx @@ -1,91 +1,22 @@ -import './nav.css'; - import classNames from 'classnames'; -import debounce from 'lodash/debounce'; -import React from 'react'; -import * as Dialog from '@radix-ui/react-dialog'; -import { useTranslation } from 'react-i18next'; -import { Link, NavLink } from 'react-router-dom'; -import vegaWhite from '../../images/vega_white.png'; - -import { Flags } from '../../config'; -import { - AppStateActionType, - useAppState, -} from '../../contexts/app-state/app-state-context'; +import { NavLink, Link } from 'react-router-dom'; +import { NetworkSwitcher } from '@vegaprotocol/environment'; +import type { HTMLAttributeAnchorTarget } from 'react'; +import { useEffect, useState } from 'react'; import Routes from '../../routes/routes'; -import { EthWallet } from '../eth-wallet'; -import { VegaWallet } from '../vega-wallet'; +import { useTranslation } from 'react-i18next'; +import vegaWhite from '../../images/vega_white.png'; +import debounce from 'lodash/debounce'; +import { NavDrawer } from './nav-draw'; +import { + getNavLinkClassNames, + Nav as ToolkitNav, +} from '@vegaprotocol/ui-toolkit'; -const Fish = () => ( - - - - - - - - - - - - - - - - - - - - -); +const useDebouncedResize = () => { + const [windowWidth, setWindowWidth] = useState(window.innerWidth); -export const Nav = () => { - const [windowWidth, setWindowWidth] = React.useState(window.innerWidth); - const isDesktop = windowWidth > 959; - const inverted = Flags.FAIRGROUND; - - React.useEffect(() => { + useEffect(() => { const handleResizeDebounced = debounce(() => { setWindowWidth(window.innerWidth); }, 300); @@ -96,167 +27,116 @@ export const Nav = () => { window.removeEventListener('resize', handleResizeDebounced); }; }, []); - - return ( -
- {isDesktop && } -
- {!isDesktop && } -
- {isDesktop ? ( - - ) : ( - - )} -
-
-
- ); -}; - -const NavHeader = ({ fairground }: { fairground: boolean }) => { - const { t } = useTranslation(); - - return ( -
- - {fairground ? ( - - ) : ( - Vega - )} - -

- {fairground ? t('fairgroundTitle') : t('title')} -

-
- ); -}; - -const DrawerSection = ({ children }: { children: React.ReactNode }) => ( -
{children}
-); - -const IconLine = ({ inverted }: { inverted: boolean }) => ( - -); - -const NavDrawer = ({ inverted }: { inverted: boolean }) => { - const { appState, appDispatch } = useAppState(); - - const drawerContentClasses = classNames( - 'drawer-content', // needed for css animation - // Positions the modal in the center of screen - 'fixed w-[80vw] max-w-[420px] top-0 right-0', - 'flex flex-col flex-nowrap justify-between h-full bg-banner overflow-y-scroll border-l border-white', - 'bg-black text-neutral-200' - ); - return ( - <> - - - - appDispatch({ - type: AppStateActionType.SET_DRAWER, - isOpen, - }) - } - > - - - -
- - - - - - -
- -
-
-
- - ); -}; - -const NavLinks = ({ - isDesktop, - isInverted, -}: { - isDesktop: boolean; - isInverted?: boolean; -}) => { - const { appDispatch } = useAppState(); - const { t } = useTranslation(); - const linkProps = { - onClick: () => - appDispatch({ type: AppStateActionType.SET_DRAWER, isOpen: false }), + return { + windowWidth, }; +}; + +type NavbarTheme = 'inherit' | 'dark' | 'yellow'; +interface NavbarProps { + navbarTheme?: NavbarTheme; +} + +export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => { + const { windowWidth } = useDebouncedResize(); + const isDesktop = windowWidth > 995; + + const { t } = useTranslation(); + const isYellow = navbarTheme === 'yellow'; const routes = [ - { route: Routes.HOME, text: t('Home') }, - { route: Routes.VESTING, text: t('Vesting') }, - { route: Routes.STAKING, text: t('Staking') }, - { route: Routes.REWARDS, text: t('Rewards') }, - { route: Routes.WITHDRAWALS, text: t('Withdraw') }, - { route: Routes.GOVERNANCE, text: t('Governance') }, + { + name: t('Proposals'), + path: Routes.PROPOSALS, + }, + { + name: t('Validators'), + path: Routes.VALIDATORS, + }, + { + name: t('Rewards'), + path: Routes.REWARDS, + }, + { + name: t('Token'), + path: Routes.TOKEN, + }, + { + name: t('Redeem'), + path: Routes.REDEEM, + }, + { + name: t('Withdraw'), + path: Routes.WITHDRAWALS, + }, + { + name: t('Supply & Vesting'), + path: Routes.TRANCHES, + }, ]; - const navClasses = classNames('flex', { - 'flex-row gap-2 mt-4 uppercase': isDesktop, - 'flex-col': !isDesktop, - }); return ( - + + Vega + + } + title={t('Governance')} + titleContent={} + > + {isDesktop ? ( + + ) : ( + + )} + + ); +}; + +interface AppNavLinkProps { + name: string; + path: string; + navbarTheme: NavbarTheme; + testId?: string; + alignRight?: boolean; + target?: HTMLAttributeAnchorTarget; +} + +const AppNavLink = ({ + name, + path, + navbarTheme, + alignRight, + target, + testId = name, +}: AppNavLinkProps) => { + const borderClasses = classNames('absolute h-1 w-full bottom-[-1px] left-0', { + 'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow', + 'bg-black': navbarTheme === 'yellow', + }); + return ( + + {({ isActive }) => { + return ( + <> + {name} + {isActive && } + + ); + }} + ); }; diff --git a/apps/token/src/components/page-templates/template-sidebar.tsx b/apps/token/src/components/page-templates/template-sidebar.tsx index bbc87ec0e..bf4fd8cab 100644 --- a/apps/token/src/components/page-templates/template-sidebar.tsx +++ b/apps/token/src/components/page-templates/template-sidebar.tsx @@ -1,3 +1,4 @@ +import { Networks, useEnvironment } from '@vegaprotocol/environment'; import React from 'react'; import { Nav } from '../nav'; @@ -8,17 +9,20 @@ export interface TemplateSidebarProps { } export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) { + const { VEGA_ENV } = useEnvironment(); return ( -
-
+ <> +
@@ -186,7 +186,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => { label={`${d.name || truncateMiddle(d.nodeId)} (${t( 'nextEpoch' )})`} - link={`${Routes.STAKING}/${d.nodeId}`} + link={`${Routes.VALIDATORS}/${d.nodeId}`} value={d.nextEpochStake} />
@@ -194,12 +194,12 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => { ))} - + - + diff --git a/apps/token/src/i18n/translations/dev.json b/apps/token/src/i18n/translations/dev.json index d0b50a817..822447cc5 100644 --- a/apps/token/src/i18n/translations/dev.json +++ b/apps/token/src/i18n/translations/dev.json @@ -472,7 +472,7 @@ "transaction": "Transaction", "associated": "Associated", "notAssociated": "Not Associated", - "title": "VEGA TOKEN", + "title": "Governance", "Use the Ethereum wallet you want to send your tokens to. You'll also need enough Ethereum to pay gas.": "Connect to the Ethereum wallet that holds your $VEGA tokens to see what can be redeemed from vesting tranches. To redeem tokens you will need some ETH to pay gas fees.\n", "Connect to see your stake": "Connect to see your stake", "Staked on Vega validator": "Associated to Vega key", @@ -715,5 +715,8 @@ "SpamProtectionMin": "Spam protection minimum", "ListAsset": "List Asset", "ListAssetDescription": "This asset needs to be listed on the collateral bridge before it can be used.", - "ListAssetAction": "List asset" + "ListAssetAction": "List asset", + "Proposals": "Proposals", + "Validators": "Validators", + "Redeem": "Redeem" } diff --git a/apps/token/src/routes/claim/complete.tsx b/apps/token/src/routes/claim/complete.tsx index ca659b610..90089c960 100644 --- a/apps/token/src/routes/claim/complete.tsx +++ b/apps/token/src/routes/claim/complete.tsx @@ -56,7 +56,7 @@ export const Complete = ({

)} - + diff --git a/apps/token/src/routes/governance/components/proposals-list-item/proposals-list-item-details.tsx b/apps/token/src/routes/governance/components/proposals-list-item/proposals-list-item-details.tsx index 565ca897b..2c73f1f15 100644 --- a/apps/token/src/routes/governance/components/proposals-list-item/proposals-list-item-details.tsx +++ b/apps/token/src/routes/governance/components/proposals-list-item/proposals-list-item-details.tsx @@ -196,7 +196,7 @@ export const ProposalsListItemDetails = ({ )} {proposal.id && (
- + diff --git a/apps/token/src/routes/governance/components/proposals-list/proposals-list.tsx b/apps/token/src/routes/governance/components/proposals-list/proposals-list.tsx index 75b6c741f..8596af153 100644 --- a/apps/token/src/routes/governance/components/proposals-list/proposals-list.tsx +++ b/apps/token/src/routes/governance/components/proposals-list/proposals-list.tsx @@ -54,7 +54,7 @@ export const ProposalsList = ({ proposals }: ProposalsListProps) => { @@ -127,7 +127,7 @@ const Home = ({ name }: RouteChildProps) => { )}

- + diff --git a/apps/token/src/routes/redemption/index.tsx b/apps/token/src/routes/redemption/index.tsx index 8ddb97f3e..dd8da68ea 100644 --- a/apps/token/src/routes/redemption/index.tsx +++ b/apps/token/src/routes/redemption/index.tsx @@ -10,7 +10,7 @@ import Routes from '../routes'; const RedemptionIndex = ({ name }: RouteChildProps) => { useDocumentTitle(name); const { t } = useTranslation(); - const tranche = useMatch(`${Routes.VESTING}/:id`); + const tranche = useMatch(`${Routes.REDEEM}/:id`); return ( <> diff --git a/apps/token/src/routes/redemption/tranche/index.tsx b/apps/token/src/routes/redemption/tranche/index.tsx index 197310641..d643ba9f4 100644 --- a/apps/token/src/routes/redemption/tranche/index.tsx +++ b/apps/token/src/routes/redemption/tranche/index.tsx @@ -121,13 +121,13 @@ export const RedeemFromTranche = () => { stakingLink: ( ), governanceLink: ( ), }} diff --git a/apps/token/src/routes/router-config.tsx b/apps/token/src/routes/router-config.tsx index 5c97bd5f7..c8cfba4a7 100644 --- a/apps/token/src/routes/router-config.tsx +++ b/apps/token/src/routes/router-config.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Outlet } from 'react-router-dom'; +import { Navigate, Outlet } from 'react-router-dom'; import Home from './home'; import NotFound from './not-found'; import NotPermitted from './not-permitted'; @@ -193,61 +193,32 @@ const LazyWithdrawals = React.lazy( ) ); -const routerConfig = [ +const redirects = [ { path: Routes.HOME, - // Not lazy as loaded when a user first hits the site - element: , - }, - { - path: Routes.TRANCHES, - element: , - children: [ - { index: true, element: }, - { path: ':trancheId', element: }, - ], - }, - { - path: Routes.CLAIM, - element: , + element: , }, { path: Routes.STAKING, - element: , - children: [ - { path: 'associate', element: }, - { path: 'disassociate', element: }, - { path: ':node', element: }, - { - index: true, - element: , - }, - ], + element: , }, { - path: Routes.REWARDS, - element: , + path: '/tranches', + element: , }, { - path: Routes.WITHDRAWALS, - element: , + path: '/withdrawals', + element: , }, { - path: Routes.VESTING, - element: , - children: [ - { - index: true, - element: , - }, - { - path: ':id', - element: , - }, - ], + path: '/vesting', + element: , }, +]; + +const routerConfig = [ { - path: Routes.GOVERNANCE, + path: Routes.PROPOSALS, element: , children: [ { index: true, element: }, @@ -281,6 +252,63 @@ const routerConfig = [ { path: 'rejected', element: }, ], }, + { + path: Routes.VALIDATORS, + element: , + children: [ + { path: 'associate', element: }, + { path: 'disassociate', element: }, + { path: ':node', element: }, + { + index: true, + element: , + }, + ], + }, + { + path: Routes.REWARDS, + element: , + }, + { + path: Routes.TOKEN, + // Not lazy as loaded when a user first hits the site + children: [ + { + element: , + index: true, + }, + { + path: Routes.TRANCHES, + element: , + children: [ + { index: true, element: }, + { path: ':trancheId', element: }, + ], + }, + { + path: Routes.WITHDRAWALS, + element: , + }, + { + path: Routes.REDEEM, + element: , + children: [ + { + index: true, + element: , + }, + { + path: ':id', + element: , + }, + ], + }, + ], + }, + { + path: Routes.CLAIM, + element: , + }, { path: Routes.NOT_PERMITTED, // Not lazy as loaded when a user first hits the site @@ -295,6 +323,7 @@ const routerConfig = [ // Not lazy as loaded when a user first hits the site element: , }, + ...redirects, ]; export default routerConfig; diff --git a/apps/token/src/routes/routes.ts b/apps/token/src/routes/routes.ts index d79a9d1bb..b3e230dde 100644 --- a/apps/token/src/routes/routes.ts +++ b/apps/token/src/routes/routes.ts @@ -1,13 +1,16 @@ export default { HOME: '/', - TRANCHES: '/tranches', CLAIM: '/claim', - STAKING: '/staking', + VALIDATORS: '/validators', REWARDS: '/rewards', - WITHDRAWALS: '/withdrawals', - GOVERNANCE: '/governance', - VESTING: '/vesting', + PROPOSALS: '/proposals', NOT_PERMITTED: '/not-permitted', NOT_FOUND: '/not-found', CONTRACTS: '/contracts', + STAKING: '/staking', + TOKEN: '/token', + REDEEM: '/token/redeem', + WITHDRAWALS: '/token/withdraw', + TRANCHES: '/token/tranches', + ASSOCIATE: '/token/associate', }; diff --git a/apps/token/src/routes/staking/associate/associate-transaction.tsx b/apps/token/src/routes/staking/associate/associate-transaction.tsx index cf72cb51d..d6bd7d62f 100644 --- a/apps/token/src/routes/staking/associate/associate-transaction.tsx +++ b/apps/token/src/routes/staking/associate/associate-transaction.tsx @@ -93,7 +93,7 @@ export const AssociateTransaction = ({ vegaKey: truncateMiddle(vegaKey), })} completeFooter={ - + } diff --git a/apps/token/src/routes/staking/disassociate/components/disassociate-transaction/disassociate-transaction.tsx b/apps/token/src/routes/staking/disassociate/components/disassociate-transaction/disassociate-transaction.tsx index 97939943d..7b681ed6f 100644 --- a/apps/token/src/routes/staking/disassociate/components/disassociate-transaction/disassociate-transaction.tsx +++ b/apps/token/src/routes/staking/disassociate/components/disassociate-transaction/disassociate-transaction.tsx @@ -39,7 +39,7 @@ export const DisassociateTransaction = ({ }) } completeFooter={ - + } diff --git a/apps/token/src/routes/staking/home/staking-intro.tsx b/apps/token/src/routes/staking/home/staking-intro.tsx index 84b851bf5..ee0808f68 100644 --- a/apps/token/src/routes/staking/home/staking-intro.tsx +++ b/apps/token/src/routes/staking/home/staking-intro.tsx @@ -8,6 +8,7 @@ import { } from '@vegaprotocol/ui-toolkit'; import { createDocsLinks, ExternalLinks } from '@vegaprotocol/react-helpers'; import { useEnvironment } from '@vegaprotocol/environment'; +import Routes from '../../../routes/routes'; export const StakingIntro = () => { const { t } = useTranslation(); @@ -24,7 +25,7 @@ export const StakingIntro = () => {

  • {t('stakingDescription1')}{' '} diff --git a/apps/token/src/routes/staking/index.tsx b/apps/token/src/routes/staking/index.tsx index 69ef0159d..63955152d 100644 --- a/apps/token/src/routes/staking/index.tsx +++ b/apps/token/src/routes/staking/index.tsx @@ -9,8 +9,8 @@ import type { RouteChildProps } from '..'; const StakingRouter = ({ name }: RouteChildProps) => { useDocumentTitle(name); const { t } = useTranslation(); - const associate = useMatch('/staking/associate'); - const disassociate = useMatch('/staking/disassociate'); + const associate = useMatch('/validators/associate'); + const disassociate = useMatch('/validators/disassociate'); const title = React.useMemo(() => { if (associate) { diff --git a/apps/token/src/routes/staking/node/stake-success.tsx b/apps/token/src/routes/staking/node/stake-success.tsx index bc8ebe721..03f0c0fed 100644 --- a/apps/token/src/routes/staking/node/stake-success.tsx +++ b/apps/token/src/routes/staking/node/stake-success.tsx @@ -44,7 +44,7 @@ export const StakeSuccess = ({

    {message}

    - + {t('backToStaking')}

    diff --git a/apps/token/src/routes/tranches/vesting-chart.tsx b/apps/token/src/routes/tranches/vesting-chart.tsx index 3610226bd..c52e9172f 100644 --- a/apps/token/src/routes/tranches/vesting-chart.tsx +++ b/apps/token/src/routes/tranches/vesting-chart.tsx @@ -88,7 +88,7 @@ export const VestingChart = () => { stroke={colors.white} strokeWidth={2} label={{ - position: 'right', + position: 'left', value: currentDate, fill: colors.white, }} diff --git a/apps/trading/components/navbar/navbar.tsx b/apps/trading/components/navbar/navbar.tsx index 950d2cbb7..182993404 100644 --- a/apps/trading/components/navbar/navbar.tsx +++ b/apps/trading/components/navbar/navbar.tsx @@ -7,8 +7,12 @@ import { VegaWalletConnectButton } from '../vega-wallet-connect-button'; import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit'; import { Vega } from '../icons/vega'; import type { HTMLAttributeAnchorTarget } from 'react'; -import testnetBg from '../../assets/green-cloud.png'; import { Routes } from '../../pages/client-router'; +import { + getNavLinkClassNames, + getActiveNavLinkClassNames, + Nav, +} from '@vegaprotocol/ui-toolkit'; type NavbarTheme = 'inherit' | 'dark' | 'yellow'; interface NavbarProps { @@ -27,61 +31,40 @@ export const Navbar = ({ marketId: store.marketId, })); const tradingPath = marketId ? `/markets/${marketId}` : '/markets'; - - const themeWrapperClasses = classNames({ - dark: navbarTheme === 'dark', - }); - - const isYellow = navbarTheme === 'yellow'; - const navbarClasses = classNames( - 'flex items-stretch border-b px-4 border-default', - { - 'dark:bg-black dark:text-white': !isYellow, - 'bg-vega-yellow text-black bg-right-top bg-no-repeat bg-contain': - isYellow, - } - ); - return ( -
    -
    -
    - - - - -
    - -
    - - -
    +
    + ); }; @@ -124,28 +107,3 @@ const AppNavLink = ({ ); }; - -function getNavLinkClassNames( - navbarTheme: string, - alignRight = false -): (props: { isActive?: boolean }) => string | undefined { - return ({ isActive = false }) => { - return getActiveNavLinkClassNames(isActive, navbarTheme, alignRight); - }; -} - -const getActiveNavLinkClassNames = ( - isActive: boolean, - navbarTheme: string, - alignRight = false -): string | undefined => { - return classNames('mx-2 py-3 self-end relative', { - 'cursor-default': isActive, - 'text-black dark:text-white': isActive && navbarTheme !== 'yellow', - 'text-neutral-500 dark:text-neutral-400 hover:text-black dark:hover:text-neutral-300': - !isActive && navbarTheme !== 'yellow', - 'ml-auto': alignRight, - 'text-black': isActive && navbarTheme === 'yellow', - 'text-black/60 hover:text-black': !isActive && navbarTheme === 'yellow', - }); -}; diff --git a/libs/ui-toolkit/src/components/index.ts b/libs/ui-toolkit/src/components/index.ts index 03df3010c..1141027c6 100644 --- a/libs/ui-toolkit/src/components/index.ts +++ b/libs/ui-toolkit/src/components/index.ts @@ -18,6 +18,7 @@ export * from './key-value-table'; export * from './link'; export * from './loader'; export * from './lozenge'; +export * from './nav'; export * from './popover'; export * from './price-change'; export * from './progress-bar'; diff --git a/libs/ui-toolkit/src/components/nav/index.ts b/libs/ui-toolkit/src/components/nav/index.ts new file mode 100644 index 000000000..38d674589 --- /dev/null +++ b/libs/ui-toolkit/src/components/nav/index.ts @@ -0,0 +1 @@ +export * from './nav'; diff --git a/libs/ui-toolkit/src/components/nav/nav.spec.tsx b/libs/ui-toolkit/src/components/nav/nav.spec.tsx new file mode 100644 index 000000000..453120980 --- /dev/null +++ b/libs/ui-toolkit/src/components/nav/nav.spec.tsx @@ -0,0 +1,19 @@ +import { render } from '@testing-library/react'; + +import { Nav } from './nav'; + +describe('Nav', () => { + it('should render title, title content, icon and children', () => { + const { baseElement } = render( + + ); + expect(baseElement).toBeTruthy(); + }); +}); diff --git a/libs/ui-toolkit/src/components/nav/nav.stories.tsx b/libs/ui-toolkit/src/components/nav/nav.stories.tsx new file mode 100644 index 000000000..68d32b160 --- /dev/null +++ b/libs/ui-toolkit/src/components/nav/nav.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, Story } from '@storybook/react'; +import { ButtonLink } from '../button'; + +import { VegaLogo } from '../vega-logo'; +import { Nav } from './nav'; + +export default { + component: Nav, + title: 'Nav', +} as Meta; + +const Template: Story = ({ icon, title, titleContent }) => ( +
    + +
    +); + +const props = { + icon: , + title: 'Title', + titleContent:
    Content next to title
    , +}; + +export const Default = Template.bind({}); +Default.args = { + ...props, +}; diff --git a/libs/ui-toolkit/src/components/nav/nav.tsx b/libs/ui-toolkit/src/components/nav/nav.tsx new file mode 100644 index 000000000..c4dec8f75 --- /dev/null +++ b/libs/ui-toolkit/src/components/nav/nav.tsx @@ -0,0 +1,79 @@ +import classNames from 'classnames'; +import type { ReactNode } from 'react'; + +export function getNavLinkClassNames( + navbarTheme: string, + alignRight = false +): (props: { isActive?: boolean }) => string | undefined { + return ({ isActive = false }) => { + return getActiveNavLinkClassNames(isActive, navbarTheme, alignRight); + }; +} + +export const getActiveNavLinkClassNames = ( + isActive: boolean, + navbarTheme: string, + alignRight = false +): string | undefined => { + return classNames('mx-2 py-3 self-end relative', { + 'cursor-default': isActive, + 'text-black dark:text-white': isActive && navbarTheme !== 'yellow', + 'text-neutral-500 dark:text-neutral-400 hover:text-black dark:hover:text-neutral-300': + !isActive && navbarTheme !== 'yellow', + 'ml-auto': alignRight, + 'text-black': isActive && navbarTheme === 'yellow', + 'text-black/60 hover:text-black': !isActive && navbarTheme === 'yellow', + }); +}; + +type NavbarTheme = 'inherit' | 'dark' | 'yellow'; + +interface NavbarProps { + navbarTheme?: NavbarTheme; + icon: ReactNode; + titleContent: ReactNode; + children: ReactNode; + title: string; +} + +export const Nav = ({ + navbarTheme = 'inherit', + children, + icon, + titleContent, + title, +}: NavbarProps) => { + const themeWrapperClasses = classNames('w-full', { + dark: navbarTheme === 'dark', + }); + + const isYellow = navbarTheme === 'yellow'; + const navbarClasses = classNames( + 'flex items-stretch border-b px-4 border-default', + { + 'dark:bg-black dark:text-white': !isYellow, + 'bg-vega-yellow text-black bg-right-top bg-no-repeat bg-contain': + isYellow, + } + ); + + return ( +
    +
    +
    + {icon} +

    + {title} +

    + {titleContent} +
    + {children} +
    +
    + ); +};