feat(#927) design update (#1201)

* feat: create new buttons

* feat: update anchor and button link styles

* feat: add icon support

* feat: fix full width with icon

* feat: convert invalid button props to use new props

* feat: tidy up explorer

* feat: more tidy up for token and trading

* feat: move styles to css file using @apply

* chore: remove css with @apply as its not working in apps

* fix: deposit form button

* feat: use default tailwind config, start on forms

* feat: fixup trade grid styles

* feat: form styles

* feat: styles for order book and tables

* feat: make key management use dropdown

* feat: update various components

* feat: tidy up wallet section

* feat: token tidy up

* feat: token governance styles

* Feat/927: Dialog styling

* feat: token styles

* feat: add font familys

* feat: change token borders to be softer

* feat: console-lite changes to support new theme

* Feat/927: Centered key-value-table.tsx spacing

* Feat/927: Tweak to Explorer site border colours to be inline with trading

* Feat/927: Tweak to Explorer header

* Feat/927: Theme switcher icon colours

* Feat/927: Fix for Explorer block data styling

* feat: fix tests, add status footer and change logos

* feat: render both theme icons to avoid hydration error

* chore: run migrations for project

* fix: tailwindconfig build to work with new next version

* feat: use document page for next as per documentation

* chore: update build targets to use development mode when serving

* fix: console-lite default text colors

* chore: fix tooltip text break, change submit button

* feat: adjust console-lite styles to work with tabs

* feat: add bespoke dialog for console-lite market-selector

* Feat/927: Theme switcher now has prop for fixed bg colour

* Feat/927: Font size and border radius tweak for toggles

* Feat/927: Cleaned up trade-grid.tsx spacing

* feat: responsive styles for market header and nav

* feat: update designs for market popover

* fix: nav active state

* chore: allow classname to be passed to button

* Feat/927: Fix Token width on desktop (was overflowing)

* Feat/927: Fix token header h1 from wrapping

* Feat/927: Tweak for claim-flow.tsx

* fix: connect button test

* Feat/927: Proposals list styling polish

* Feat/927: key-value-table.tsx spacing tweak

* feat: add copy button to kp dropdown

* Feat/927: Removing old theme params and uses

* Feat/927: Removing old theme params and uses, documenting the now used otb sizes

* feat: use key val table in asset dialog

* feat: align tooltip styles

* fix: orderbook grid alignment

* chore: linting

* fix: dialog sizing in medium mode, node switcher styles

* chore: remove unused color classes

* feat: update radio and checkbox designs

* feat: updates to storybook

* feat: update design system stories

* chore: stories update

* chore: rename resize panels and tidy

* feat: fix checkbox tick

* fix: add poyfills for jest in trading test setup

* chore: fix checkbox tests

* chore: fix tests

* chore: fix tests again

* chore: revert token wallet name test

* fix: tooltip tests on console-lite

* fix: wallet dropdown test

Co-authored-by: sam-keen <samuel.kleinmann@gmail.com>
This commit is contained in:
Matthew Russell 2022-08-30 21:35:46 -07:00 committed by GitHub
parent 688d15ef75
commit c259622848
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
382 changed files with 5289 additions and 6216 deletions

3
.gitignore vendored
View File

@ -43,3 +43,6 @@ Thumbs.db
.local.env .local.env
.env.local .env.local
cypress.env.json cypress.env.json
# Next.js
.next

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/console-lite-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/console-lite-e2e/src", "sourceRoot": "apps/console-lite-e2e/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {

View File

@ -127,7 +127,7 @@ describe('market selector', () => {
.children() .children()
.find('[role="button"]') .find('[role="button"]')
.should('have.length', 3); .should('have.length', 3);
cy.get('div[role="dialog"]').should('have.class', 'w-full'); cy.get('div[role="dialog"]').should('have.class', 'w-screen');
cy.getByTestId('dialog-close').click(); cy.getByTestId('dialog-close').click();
cy.get('input[placeholder="Search"]').should( cy.get('input[placeholder="Search"]').should(
'have.value', 'have.value',

View File

@ -255,17 +255,19 @@ describe('Market trade', () => {
connectVegaWallet(); connectVegaWallet();
cy.get('#step-3-control').click(); cy.get('#step-3-control').click();
// Start from the bottom tooltip to ensure the tooltip above
// can be interacted with
cy.getByTestId('review-trade').get('div.cursor-help').eq(1).realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The notional size represents the position size'
);
cy.getByTestId('review-trade') cy.getByTestId('review-trade')
.get('#contracts_tooltip_trigger') .get('#contracts_tooltip_trigger')
.realTouch(); .realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains( cy.get('[data-radix-popper-content-wrapper]').contains(
'The number of contracts determines' 'The number of contracts determines'
); );
cy.getByTestId('review-trade').get('div.cursor-help').eq(1).realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The notional size represents the position size'
);
} }
}); });
}); });

View File

@ -1,4 +1,5 @@
module.exports = { /* eslint-disable */
export default {
displayName: 'console-lite', displayName: 'console-lite',
preset: '../../jest.preset.js', preset: '../../jest.preset.js',
transform: { transform: {

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/console-lite", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/console-lite/src", "sourceRoot": "apps/console-lite/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {
@ -43,7 +43,7 @@
"serve": { "serve": {
"executor": "./tools/executors/webpack:serve", "executor": "./tools/executors/webpack:serve",
"options": { "options": {
"buildTarget": "console-lite:build", "buildTarget": "console-lite:build:development",
"hmr": true, "hmr": true,
"port": 4001 "port": 4001
}, },
@ -65,12 +65,12 @@
"executor": "@nrwl/jest:jest", "executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/console-lite"], "outputs": ["coverage/apps/console-lite"],
"options": { "options": {
"jestConfig": "apps/console-lite/jest.config.js", "jestConfig": "apps/console-lite/jest.config.ts",
"passWithNoTests": true "passWithNoTests": true
} }
}, },
"build-netlify": { "build-netlify": {
"builder": "@nrwl/workspace:run-commands", "executor": "@nrwl/workspace:run-commands",
"options": { "options": {
"commands": [ "commands": [
"cp apps/console-lite/netlify.toml netlify.toml", "cp apps/console-lite/netlify.toml netlify.toml",

View File

@ -19,7 +19,7 @@ import useLocalValues from './hooks/use-local-values';
function App() { function App() {
const [theme, toggleTheme] = useThemeSwitcher(); const [theme, toggleTheme] = useThemeSwitcher();
const localValues = useLocalValues(toggleTheme); const localValues = useLocalValues(theme, toggleTheme);
const { const {
vegaWalletDialog, vegaWalletDialog,
menu: { setMenuOpen }, menu: { setMenuOpen },
@ -37,7 +37,7 @@ function App() {
<VegaWalletProvider> <VegaWalletProvider>
<LocalContext.Provider value={localValues}> <LocalContext.Provider value={localValues}>
<AppLoader> <AppLoader>
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]"> <div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header /> <Header />
<Main /> <Main />
<VegaConnectDialog <VegaConnectDialog

View File

@ -54,7 +54,7 @@ export const DealTicketContainer = () => {
{(data) => { {(data) => {
const balance = ( const balance = (
<DealTicketBalance <DealTicketBalance
className="mb-16" className="mb-4"
settlementAsset={ settlementAsset={
data.market.tradableInstrument.instrument.product?.settlementAsset data.market.tradableInstrument.instrument.product?.settlementAsset
} }
@ -76,7 +76,7 @@ export const DealTicketContainer = () => {
); );
return ( return (
<section className="flex"> <section className="flex p-4 md:p-6">
<section className="w-full md:w-1/2 md:min-w-[500px]"> <section className="w-full md:w-1/2 md:min-w-[500px]">
{keypair ? container : <ConnectWallet />} {keypair ? container : <ConnectWallet />}
</section> </section>

View File

@ -34,7 +34,7 @@ interface ValueTooltipProps {
} }
const ValueTooltipRow = ({ value, description, id }: ValueTooltipProps) => ( const ValueTooltipRow = ({ value, description, id }: ValueTooltipProps) => (
<dd className="flex gap-x-5 items-center"> <dd className="flex gap-x-2 items-center">
{value} {value}
<Tooltip align="center" description={description}> <Tooltip align="center" description={description}>
<div className="cursor-help" id={id || ''} tabIndex={-1}> <div className="cursor-help" id={id || ''} tabIndex={-1}>
@ -59,7 +59,7 @@ export const DealTicketEstimates = ({
}: DealTicketEstimatesProps) => ( }: DealTicketEstimatesProps) => (
<dl className="text-black dark:text-white"> <dl className="text-black dark:text-white">
{size && ( {size && (
<div className="flex justify-between mb-8"> <div className="flex justify-between mb-2">
<DataTitle>{t('Contracts')}</DataTitle> <DataTitle>{t('Contracts')}</DataTitle>
<ValueTooltipRow <ValueTooltipRow
value={size} value={size}
@ -69,13 +69,13 @@ export const DealTicketEstimates = ({
</div> </div>
)} )}
{price && ( {price && (
<div className="flex justify-between mb-8"> <div className="flex justify-between mb-2">
<DataTitle>{t('Est. Price')}</DataTitle> <DataTitle>{t('Est. Price')}</DataTitle>
<dd>{price}</dd> <dd>{price}</dd>
</div> </div>
)} )}
{notionalSize && ( {notionalSize && (
<div className="flex justify-between mb-8"> <div className="flex justify-between mb-2">
<DataTitle quoteName={quoteName}>{t('Est. Position Size')}</DataTitle> <DataTitle quoteName={quoteName}>{t('Est. Position Size')}</DataTitle>
<ValueTooltipRow <ValueTooltipRow
value={notionalSize} value={notionalSize}
@ -84,7 +84,7 @@ export const DealTicketEstimates = ({
</div> </div>
)} )}
{fees && ( {fees && (
<div className="flex justify-between mb-8"> <div className="flex justify-between mb-2">
<DataTitle quoteName={quoteName}>{t('Est. Fees')}</DataTitle> <DataTitle quoteName={quoteName}>{t('Est. Fees')}</DataTitle>
<ValueTooltipRow <ValueTooltipRow
value={fees} value={fees}

View File

@ -5,7 +5,6 @@ import {
SliderThumb, SliderThumb,
SliderTrack, SliderTrack,
SliderRange, SliderRange,
Button,
Input, Input,
FormGroup, FormGroup,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
@ -108,12 +107,12 @@ export const DealTicketSize = ({
<p>Not enough balance to trade</p> <p>Not enough balance to trade</p>
) : ( ) : (
<div> <div>
<div className="flex justify-between text-black dark:text-white mb-8"> <div className="flex justify-between text-black dark:text-white mb-2">
<span data-testid="min-label">{min}</span> <span data-testid="min-label">{min}</span>
<span data-testid="max-label">{max}</span> <span data-testid="max-label">{max}</span>
</div> </div>
<SliderRoot <SliderRoot
className="mb-8" className="mb-2"
value={[value]} value={[value]}
onValueChange={onValueChange} onValueChange={onValueChange}
step={step} step={step}
@ -128,35 +127,34 @@ export const DealTicketSize = ({
<div <div
data-testid="percentage-selector" data-testid="percentage-selector"
className="flex w-full justify-between text-black dark:text-white mb-32" className="flex w-full justify-between text-black dark:text-white mb-6"
> >
{sizeRatios.map((size, index) => { {sizeRatios.map((size, index) => {
const proportionalSize = size ? (size / 100) * max : min; const proportionalSize = size ? (size / 100) * max : min;
return ( return (
<Button <button
variant="inline-link" className="no-underline hover:underline text-blue"
className="no-underline !text-blue"
onClick={() => onButtonValueChange(proportionalSize)} onClick={() => onButtonValueChange(proportionalSize)}
type="button"
key={index} key={index}
> >
{getSizeLabel(size)} {getSizeLabel(size)}
</Button> </button>
); );
})} })}
</div> </div>
<dl className="text-black dark:text-white"> <dl className="text-black dark:text-white">
<div className="flex items-center justify-between mb-8"> <div className="flex items-center justify-between mb-4">
<dt>{t('Contracts')}</dt> <dt>{t('Contracts')}</dt>
<dd className="flex justify-end w-full"> <dd className="flex justify-end w-full">
<FormGroup <FormGroup
className="mb-0 flex items-center" hideLabel={true}
labelClassName="mr-8 sr-only"
label="Enter Size" label="Enter Size"
labelFor="trade-size-input" labelFor="trade-size-input"
> >
{isInputVisible ? ( {isInputVisible ? (
<> <div className="flex items-center">
<Input <Input
id="input-order-size-market" id="input-order-size-market"
type="number" type="number"
@ -168,22 +166,22 @@ export const DealTicketSize = ({
onKeyDown={onInputEnter} onKeyDown={onInputEnter}
onChange={onInputValueChange} onChange={onInputValueChange}
/> />
<Button <button
variant="inline-link" className="no-underline hover:underline text-blue ml-2"
className="no-underline !text-blue" type="button"
onClick={toggleInput} onClick={toggleInput}
> >
{t('set')} {t('set')}
</Button> </button>
</> </div>
) : ( ) : (
<Button <button
variant="inline-link" className="no-underline hover:underline text-blue"
className="no-underline !text-blue"
onClick={toggleInput} onClick={toggleInput}
type="button"
> >
{value} {value}
</Button> </button>
)} )}
</FormGroup> </FormGroup>
</dd> </dd>

View File

@ -213,9 +213,11 @@ export const DealTicketSteps = ({
component: ( component: (
<div className="mb-8"> <div className="mb-8">
{invalidText && ( {invalidText && (
<InputError className="mb-8" data-testid="dealticket-error-message"> <div className="mb-2">
{invalidText} <InputError data-testid="dealticket-error-message">
</InputError> {invalidText}
</InputError>
</div>
)} )}
<ReviewTrade <ReviewTrade
market={market} market={market}
@ -246,7 +248,7 @@ export const DealTicketSteps = ({
]; ];
return ( return (
<form onSubmit={handleSubmit(onSubmit)} className="px-4 py-8"> <form onSubmit={handleSubmit(onSubmit)} className="px-2 py-4">
<Stepper steps={steps} /> <Stepper steps={steps} />
</form> </form>
); );

View File

@ -67,7 +67,7 @@ export default ({
<div className="mb-8 text-black dark:text-white" data-testid="review-trade"> <div className="mb-8 text-black dark:text-white" data-testid="review-trade">
<KeyValueTable> <KeyValueTable>
<KeyValueTableRow noBorder> <KeyValueTableRow noBorder>
<div className="flex flex-none gap-x-5 items-center"> <div className="flex flex-none gap-x-2 items-center">
<div <div
className={classNames( className={classNames(
{ {
@ -75,7 +75,7 @@ export default ({
'sellButton dark:sellButtonDark': 'sellButton dark:sellButtonDark':
order.side === Side.SIDE_SELL, order.side === Side.SIDE_SELL,
}, },
'px-8 py-4 inline text-ui-small' 'px-2 py-1 inline text-ui-small'
)} )}
> >
{SIDE_NAMES[order.side]} {SIDE_NAMES[order.side]}
@ -107,17 +107,17 @@ export default ({
notionalSize={notionalSize} notionalSize={notionalSize}
/> />
<Button <div className="mt-12 max-w-sm">
className="w-full !py-8 mt-64 max-w-sm" <Button
boxShadow={false} fill={true}
variant="secondary" type="submit"
type="submit" disabled={transactionStatus === 'pending' || isDisabled}
disabled={transactionStatus === 'pending' || isDisabled} data-testid="place-order"
data-testid="place-order" rightIcon="arrow-top-right"
appendIconName="arrow-top-right" >
> {transactionStatus === 'pending' ? t('Pending...') : t('Submit')}
{transactionStatus === 'pending' ? t('Pending...') : t('Submit')} </Button>
</Button> </div>
</div> </div>
); );
}; };

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { FormGroup, Button } from '@vegaprotocol/ui-toolkit'; import { FormGroup } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { Side } from '@vegaprotocol/types'; import { Side } from '@vegaprotocol/types';
@ -19,36 +19,36 @@ export default ({ value, onSelect }: SideSelectorProps) => {
<FormGroup <FormGroup
label={t('Direction')} label={t('Direction')}
labelFor="order-side-toggle" labelFor="order-side-toggle"
labelClassName="sr-only" hideLabel={true}
> >
<fieldset <fieldset
className="w-full grid md:grid-cols-2 gap-20" className="w-full grid md:grid-cols-2 gap-4"
id="order-side-toggle" id="order-side-toggle"
> >
<Button <button
variant="inline-link"
aria-label={t('Open long position')} aria-label={t('Open long position')}
type="button"
className={classNames( className={classNames(
'py-8', 'px-8 py-2',
'buyButton hover:buyButton dark:buyButtonDark dark:hover:buyButtonDark', 'buyButton hover:buyButton dark:buyButtonDark dark:hover:buyButtonDark',
{ selected: value === Side.SIDE_BUY } { selected: value === Side.SIDE_BUY }
)} )}
onClick={() => onSelect(Side.SIDE_BUY)} onClick={() => onSelect(Side.SIDE_BUY)}
> >
{t('Long')} {t('Long')}
</Button> </button>
<Button <button
variant="inline-link"
aria-label={t('Open short position')} aria-label={t('Open short position')}
type="button"
className={classNames( className={classNames(
'py-8', 'px-8 py-2',
'sellButton hover:sellButton dark:sellButtonDark dark:hover:sellButtonDark', 'sellButton hover:sellButton dark:sellButtonDark dark:hover:sellButtonDark',
{ selected: value === Side.SIDE_SELL } { selected: value === Side.SIDE_SELL }
)} )}
onClick={() => onSelect(Side.SIDE_SELL)} onClick={() => onSelect(Side.SIDE_SELL)}
> >
{t('Short')} {t('Short')}
</Button> </button>
<div className="md:col-span-2 text-black dark:text-white text-ui-small"> <div className="md:col-span-2 text-black dark:text-white text-ui-small">
{t( {t(
'Trading derivatives allows you to make a profit or loss regardless of whether the market you are trading goes up or down. If you open a "long" position, you will make a profit if the price of your chosen market goes up, and you will make a profit for "short" positions when the price goes down.' 'Trading derivatives allows you to make a profit or loss regardless of whether the market you are trading goes up or down. If you open a "long" position, you will make a profit if the price of your chosen market goes up, and you will make a profit for "short" positions when the price goes down.'

View File

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

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Button, Icon } from '@vegaprotocol/ui-toolkit'; import { ButtonLink, Icon } from '@vegaprotocol/ui-toolkit';
import { IconNames } from '@blueprintjs/icons'; import { IconNames } from '@blueprintjs/icons';
import type { IconName } from '@vegaprotocol/ui-toolkit'; import type { IconName } from '@vegaprotocol/ui-toolkit';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
@ -37,13 +37,10 @@ export const DrawerToggle = ({
} Sidebar Navigation Menu`; } Sidebar Navigation Menu`;
return ( return (
<Button <span className={classes}>
aria-label={ariaLabel} <ButtonLink aria-label={ariaLabel} onClick={onToggle}>
variant="inline-link" <Icon name={iconName as IconName} />
className={classes} </ButtonLink>
onClick={onToggle} </span>
>
<Icon name={iconName as IconName} />
</Button>
); );
}; };

View File

@ -22,8 +22,9 @@ export const NavigationDrawer = ({
const width = 'w-full md:w-auto md:min-w-[15%] shrink-0'; const width = 'w-full md:w-auto md:min-w-[15%] shrink-0';
const position = 'absolute inset-0 h-full z-10 md:static'; const position = 'absolute inset-0 h-full z-10 md:static';
const background = 'bg-black/50 dark:bg-white/50'; const background = 'bg-black/50 dark:bg-white/50';
const border = 'border-r border-neutral-300 dark:border-neutral-700';
const flex = 'flex justify-end overflow-hidden'; const flex = 'flex justify-end overflow-hidden';
const joinedClasses = [flex, width, position, background].join(' '); const joinedClasses = [flex, width, position, background, border].join(' ');
const outerStyles = classNames(joinedClasses, { const outerStyles = classNames(joinedClasses, {
visible: isMenuOpen, visible: isMenuOpen,

View File

@ -7,23 +7,25 @@ import LocalContext from '../../context/local-context';
const Header = () => { const Header = () => {
const { const {
vegaWalletDialog: { setConnect, setManage }, vegaWalletDialog: { setConnect, setManage },
theme,
toggleTheme, toggleTheme,
} = useContext(LocalContext); } = useContext(LocalContext);
return ( return (
<div <div
className="flex items-stretch pr-16 py-16 bg-black text-white-60" className="flex items-stretch pr-6 py-6 bg-black text-neutral-400 border-b border-neutral-300 dark:border-neutral-700"
data-testid="header" data-testid="header"
> >
<Logo /> <Logo />
<div className="flex items-center gap-4 ml-auto mr-8 relative z-10"> <div className="flex items-center gap-2 ml-auto relative z-10">
<VegaWalletConnectButton <VegaWalletConnectButton
setConnectDialog={setConnect} setConnectDialog={setConnect}
setManageDialog={setManage} setManageDialog={setManage}
/> />
<ThemeSwitcher <ThemeSwitcher
theme={theme}
onToggle={toggleTheme} onToggle={toggleTheme}
className="-my-4" className="-my-4"
sunClassName="text-white" fixedBg="dark"
/> />
</div> </div>
</div> </div>

View File

@ -6,11 +6,11 @@ import { VLogo } from '@vegaprotocol/ui-toolkit';
const Logo = () => { const Logo = () => {
return ( return (
<NavLink <NavLink
className="mx-20 text-white" className="mx-6 text-white"
aria-label={t('Go to home page')} aria-label={t('Go to home page')}
to="/" to="/"
> >
<VLogo /> <VLogo className="mx-6 my-2" />
</NavLink> </NavLink>
); );
}; };

View File

@ -29,7 +29,7 @@ export const Main = () => {
variant={DRAWER_TOGGLE_VARIANTS.CLOSE} variant={DRAWER_TOGGLE_VARIANTS.CLOSE}
className="p-16" className="p-16"
/> />
<Nav className="hidden md:block my-20 h-full" /> <Nav className="hidden md:block my-6 h-full" />
</NavigationDrawer> </NavigationDrawer>
<DrawerContent> <DrawerContent>
<AppRouter /> <AppRouter />

View File

@ -9,7 +9,7 @@ interface NavItemProps {
export const NavItem = ({ iconName, label }: NavItemProps) => { export const NavItem = ({ iconName, label }: NavItemProps) => {
return ( return (
<div className="flex flex-col md:flex-row items-center justify-start cursor-pointer relative"> <div className="flex flex-col md:flex-row items-center justify-start cursor-pointer relative">
<Icon name={iconName} className="mr-8" /> <Icon name={iconName} className="mr-2" />
<span className="text-lg">{label}</span> <span className="text-lg">{label}</span>
</div> </div>
); );

View File

@ -19,7 +19,7 @@ export const Nav = ({ className, tabs = false }: NavProps) => {
key={r.name} key={r.name}
to={r.path} to={r.path}
className={({ isActive }) => className={({ isActive }) =>
`text-h5 block md:mb-40 px-40 md:text-black md:dark:text-white ${ `text-base block md:mb-10 px-12 md:text-black md:dark:text-white ${
isActive && 'text-white md:text-blue md:dark:text-blue' isActive && 'text-white md:text-blue md:dark:text-blue'
}` }`
} }

View File

@ -8,7 +8,7 @@ interface TabBarProps {
export const TabBar = ({ className }: TabBarProps) => ( export const TabBar = ({ className }: TabBarProps) => (
<div role="group" aria-label="Tab Bar Navigation Menu" className={className}> <div role="group" aria-label="Tab Bar Navigation Menu" className={className}>
<div role="presentation" className="py-[42px]" /> <div role="presentation" className="py-[42px]" />
<div className="md:hidden fixed bottom-0 left-0 right-0 bg-black py-16"> <div className="md:hidden fixed bottom-0 left-0 right-0 bg-black py-4 border-t border-neutral-300 dark:border-neutral-700">
<Nav tabs className="flex justify-evenly items-center" /> <Nav tabs className="flex justify-evenly items-center" />
</div> </div>
</div> </div>

View File

@ -3,6 +3,7 @@ import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import { IS_MARKET_TRADABLE } from '../../constants'; import { IS_MARKET_TRADABLE } from '../../constants';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets'; import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import colors from 'tailwindcss/colors';
export const STATES_FILTER = [ export const STATES_FILTER = [
{ value: 'all', text: t('All') }, { value: 'all', text: t('All') },
@ -36,7 +37,7 @@ export const agGridLightVariables = `
overflow: visible; overflow: visible;
} }
.ag-theme-balham .ag-row-hover:not(.mobile) { .ag-theme-balham .ag-row-hover:not(.mobile) {
--ag-row-border-color: ${theme.colors.black[100]}; --ag-row-border-color: ${colors.black};
} }
.ag-theme-balham .ag-row-hover .icon-green-hover { .ag-theme-balham .ag-row-hover .icon-green-hover {
fill: ${theme.colors.darkerGreen}; fill: ${theme.colors.darkerGreen};
@ -123,7 +124,7 @@ export const agGridDarkVariables = `
overflow: visible; overflow: visible;
} }
.ag-theme-balham-dark .ag-row-hover:not(.mobile){ .ag-theme-balham-dark .ag-row-hover:not(.mobile){
--ag-row-border-color: ${theme.colors.white[100]}; --ag-row-border-color: ${colors.white};
} }
.ag-theme-balham-dark .ag-row-hover .icon-green-hover { .ag-theme-balham-dark .ag-row-hover .icon-green-hover {
fill: ${theme.colors.lightGreen}; fill: ${theme.colors.lightGreen};

View File

@ -22,7 +22,7 @@ const SimpleMarketExpires = ({
return agg; return agg;
}, null); }, null);
return dateFound ? ( return dateFound ? (
<div className="p-2 text-ui-small border-1 border-pink text-pink inline-block">{`${format( <div className="p-2 text-ui-small border border-pink text-pink inline-block">{`${format(
dateFound as Date, dateFound as Date,
EXPIRE_DATE_FORMAT EXPIRE_DATE_FORMAT
)}`}</div> )}`}</div>

View File

@ -130,7 +130,7 @@ const SimpleMarketList = () => {
); );
return ( return (
<div className="h-full grid grid-rows-[min-content,1fr]"> <div className="h-full p-4 md:p-6 grid grid-rows-[min-content,1fr]">
<SimpleMarketToolbar data={data || []} /> <SimpleMarketToolbar data={data || []} />
<AsyncRenderer loading={loading} error={error} data={localData}> <AsyncRenderer loading={loading} error={error} data={localData}>
<AgGrid <AgGrid

View File

@ -10,10 +10,10 @@ interface Props {
const MarketNameRenderer = ({ market, isMobile }: Props) => { const MarketNameRenderer = ({ market, isMobile }: Props) => {
return ( return (
<div className="flex h-full items-center grid grid-rows-2 grid-flow-col gap-x-4 md:gap-x-8 gap-y-0 grid-cols-[min-content,1fr,1fr] md:pl-8"> <div className="flex h-full items-center grid grid-rows-2 grid-flow-col gap-x-2 md:gap-x-4 gap-y-0 grid-cols-[min-content,1fr,1fr] md:pl-4">
<div <div
className={classNames( className={classNames(
'row-span-2 bg-pink rounded-full bg-gradient-to-br from-white-60 to--white-80 opacity-30 w-20 h-20 md:w-44 md:h-44' 'row-span-2 bg-pink rounded-full bg-gradient-to-br from-white/40 to-white/80 opacity-30 w-6 h-6 md:w-10 md:h-10'
)} )}
/> />
<div className="col-span-2 uppercase justify-start text-black dark:text-white text-ui-small md:text-market self-end"> <div className="col-span-2 uppercase justify-start text-black dark:text-white text-ui-small md:text-market self-end">

View File

@ -75,14 +75,14 @@ const SimpleMarketToolbar = ({ data }: Props) => {
); );
return ( return (
<div className="w-full max-w-full mb-32 font-alpha"> <div className="w-full max-w-full mb-4 font-alpha">
<ul <ul
ref={slideContRef} ref={slideContRef}
className="grid grid-flow-col auto-cols-min gap-8 relative pb-4 mb-16" className="grid grid-flow-col auto-cols-min gap-4 relative pb-2 mb-2"
data-testid="market-products-menu" data-testid="market-products-menu"
aria-label={t('Product type')} aria-label={t('Product type')}
> >
<li key="all-markets" className="md:mr-16 whitespace-nowrap"> <li key="all-markets" className="md:mr-2 whitespace-nowrap">
<Link <Link
to={`/markets${ to={`/markets${
params.state && params.state !== MarketState.STATE_ACTIVE params.state && params.state !== MarketState.STATE_ACTIVE
@ -90,7 +90,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
: '' : ''
}`} }`}
aria-label={t('All markets')} aria-label={t('All markets')}
className={classNames('text-h5 pl-0 text-pink hover:opacity-75', { className={classNames('pl-0 text-pink hover:opacity-75', {
active: !activeNumber, active: !activeNumber,
})} })}
> >
@ -98,13 +98,13 @@ const SimpleMarketToolbar = ({ data }: Props) => {
</Link> </Link>
</li> </li>
{products.map((product, i) => ( {products.map((product, i) => (
<li key={product} className="mx-16 whitespace-nowrap"> <li key={product} className="mx-2 whitespace-nowrap">
<Link <Link
to={`/markets/${ to={`/markets/${
params.state || MarketState.STATE_ACTIVE params.state || MarketState.STATE_ACTIVE
}/${product}`} }/${product}`}
className={classNames( className={classNames(
'text-h5 hover:opacity-75 text-black dark:text-white', 'hover:opacity-75 text-black dark:text-white',
{ {
active: activeNumber - 1 === i, active: activeNumber - 1 === i,
} }
@ -116,16 +116,16 @@ const SimpleMarketToolbar = ({ data }: Props) => {
</li> </li>
))} ))}
<li <li
className="absolute bottom-0 h-2 transition-left duration-300 dark:bg-white bg-black" className="absolute bottom-0 h-[2px] transition-left duration-300 dark:bg-white bg-black"
key="slider" key="slider"
style={sliderStyles} style={sliderStyles}
/> />
</ul> </ul>
<div className="grid gap-8 pb-4 mt-8 md:grid-cols-[min-content,min-content,1fr]"> <div className="grid gap-8 pb-4 mt-6 md:grid-cols-[min-content,min-content,1fr]">
<div className="pb-8"> <div className="pb-8">
<DropdownMenu onOpenChange={(open) => setOpen(open)}> <DropdownMenu onOpenChange={(open) => setOpen(open)}>
<DropdownMenuTrigger <DropdownMenuTrigger
className="mr-16 w-auto text-capMenu text-black dark:text-white" className="mr-2 w-auto text-capMenu text-black dark:text-white"
data-testid="state-trigger" data-testid="state-trigger"
> >
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border"> <div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
@ -137,12 +137,11 @@ const SimpleMarketToolbar = ({ data }: Props) => {
<Icon <Icon
name={IconNames.ARROW_DOWN} name={IconNames.ARROW_DOWN}
className={classNames( className={classNames(
'fill-current ml-8 transition-transform', 'fill-current ml-2 transition-transform',
{ {
'rotate-180': isOpen, 'rotate-180': isOpen,
} }
)} )}
size={16}
/> />
</div> </div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
@ -151,17 +150,16 @@ const SimpleMarketToolbar = ({ data }: Props) => {
<DropdownMenuCheckboxItem <DropdownMenuCheckboxItem
className="uppercase text-ui dark:text-white" className="uppercase text-ui dark:text-white"
key={value} key={value}
inset
checked={ checked={
value === params.state || value === params.state ||
(!params.state && value === MarketState.STATE_ACTIVE) (!params.state && value === MarketState.STATE_ACTIVE)
} }
onCheckedChange={() => onStateChange(value)} onCheckedChange={() => onStateChange(value)}
> >
{text}
<DropdownMenuItemIndicator> <DropdownMenuItemIndicator>
<Icon name="tick" /> <Icon name="tick" />
</DropdownMenuItemIndicator> </DropdownMenuItemIndicator>
{text}
</DropdownMenuCheckboxItem> </DropdownMenuCheckboxItem>
))} ))}
</DropdownMenuContent> </DropdownMenuContent>
@ -172,14 +170,14 @@ const SimpleMarketToolbar = ({ data }: Props) => {
</div> </div>
{activeNumber > 0 && ( {activeNumber > 0 && (
<ul <ul
className="md:gap-16 gap-12 pb-4 md:ml-16 flex flex-wrap" className="md:gap-6 gap-4 pb-4 md:ml-2 flex flex-wrap"
data-testid="market-assets-menu" data-testid="market-assets-menu"
aria-label={t('Asset on the market')} aria-label={t('Asset on the market')}
> >
<li key="all"> <li key="all">
<Link <Link
to={`/markets/${params.state}/${params.product}`} to={`/markets/${params.state}/${params.product}`}
className={classNames('uppercase pl-0 md:pl-4 text-capMenu', { className={classNames('uppercase pl-0 md:pl-2 text-capMenu', {
'text-deemphasise dark:text-midGrey': 'text-deemphasise dark:text-midGrey':
params.asset && params.asset !== 'all', params.asset && params.asset !== 'all',
'active text-black dark:text-white': 'active text-black dark:text-white':

View File

@ -25,13 +25,13 @@ export const Counter = ({ label, isActive, className }: CounterProps) => {
const unselected: TStyleMap = { const unselected: TStyleMap = {
border: 'border', border: 'border',
size: 'w-[30px] md:w-40', size: 'w-[30px] md:w-10',
margin: 'mt-[5px] md:ml-[10px] md:mt-0', margin: 'mt-[5px] md:ml-[10px] md:mt-0',
}; };
const selected: TStyleMap = { const selected: TStyleMap = {
colours: 'text-xl text-white', colours: 'text-xl text-white',
size: 'w-40 md:w-[60px]', size: 'w-10 md:w-[60px]',
}; };
const classes = classNames( const classes = classNames(

View File

@ -58,13 +58,13 @@ export const Stepper = ({ steps }: StepperProps) => {
key={`${index}-${step.label}`} key={`${index}-${step.label}`}
aria-label={t(`Step ${index + 1}`)} aria-label={t(`Step ${index + 1}`)}
> >
<div className="flex relative md:pt-16"> <div className="flex relative md:pt-6">
{!isFirstStep ? ( {!isFirstStep ? (
<div <div
aria-hidden aria-hidden
className="flex-auto absolute top-[20px] -left-1/2 right-1/2 md:-top-1/2 md:bottom-1/2 md:left-[29.5px] md:right-auto" className="flex-auto absolute top-[20px] -left-1/2 right-1/2 md:-top-1/2 md:bottom-1/2 md:left-[29.5px] md:right-auto"
> >
<span className="h-full block border-t-1 border-black dark:border-white w-full md:border-l-1 md:border-t-0" /> <span className="h-full block border-t border-black dark:border-white w-full md:border-l md:border-t-0" />
</div> </div>
) : undefined} ) : undefined}
<button <button
@ -79,7 +79,7 @@ export const Stepper = ({ steps }: StepperProps) => {
> >
<div className="flex-1 flex flex-col md:flex-row items-center w-full text-center"> <div className="flex-1 flex flex-col md:flex-row items-center w-full text-center">
<Counter <Counter
className="md:mr-16" className="md:mr-4"
isActive={isActive} isActive={isActive}
label={(index + 1).toString()} label={(index + 1).toString()}
/> />
@ -87,8 +87,8 @@ export const Stepper = ({ steps }: StepperProps) => {
className={classNames( className={classNames(
'md:mt-0 font-alpha uppercase text-black dark:text-white', 'md:mt-0 font-alpha uppercase text-black dark:text-white',
{ {
'mt-8 text-md md:text-2xl': isActive, 'mt-2 text-md md:text-2xl': isActive,
'mt-16 text-sm md:text-lg ml-8': !isActive, 'mt-4 text-sm md:text-lg md:ml-8': !isActive,
} }
)} )}
> >
@ -134,22 +134,22 @@ export const Stepper = ({ steps }: StepperProps) => {
id={`step-${activeStep}-panel`} id={`step-${activeStep}-panel`}
aria-labelledby={`step-${activeStep}-control`} aria-labelledby={`step-${activeStep}-control`}
role="tabpanel" role="tabpanel"
className="md:hidden mt-32" // md:hidden as fallback className="md:hidden mt-10" // md:hidden as fallback
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */ /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
tabIndex={0} tabIndex={0}
> >
{steps[activeStep].component} {steps[activeStep].component}
{!isLastStep && ( {!isLastStep && (
<Button <div className="mt-10 md:sr-only">
className="w-full !py-8 mt-64 md:sr-only" <Button
boxShadow={false} fill={true}
variant="secondary" onClick={handleNext}
onClick={handleNext} disabled={steps[activeStep].disabled}
disabled={steps[activeStep].disabled} data-testid="next-button"
data-testid="next-button" >
> {t('Next')}
{t('Next')} </Button>
</Button> </div>
)} )}
</div> </div>
)} )}

View File

@ -10,19 +10,17 @@ const ConnectWallet = () => {
} = useContext(LocalContext); } = useContext(LocalContext);
return ( return (
<section <section
className="p-32 bg-white-normal dark:bg-offBlack" className="p-8 bg-white-normal dark:bg-offBlack"
data-testid="trading-connect-wallet" data-testid="trading-connect-wallet"
> >
<h3 className="mb-16 text-2xl text-offBlack dark:text-white"> <h3 className="mb-4 text-2xl text-offBlack dark:text-white">
{t('Please connect your Vega wallet to make a trade')} {t('Please connect your Vega wallet to make a trade')}
</h3> </h3>
<Button <div className="mb-4">
variant="primary" <Button variant="primary" onClick={() => setConnect(true)} size="lg">
onClick={() => setConnect(true)} {t('Connect Vega wallet')}
className="h-[50px] mb-16" </Button>
> </div>
{t('Connect Vega wallet')}
</Button>
<h4 className="text-lg text-offBlack dark:text-white"> <h4 className="text-lg text-offBlack dark:text-white">
{t("Don't have a wallet?")} {t("Don't have a wallet?")}
</h4> </h4>

View File

@ -16,6 +16,7 @@ interface MenuState {
export interface LocalValues { export interface LocalValues {
vegaWalletDialog: VegaWalletDialogState; vegaWalletDialog: VegaWalletDialogState;
menu: MenuState; menu: MenuState;
theme: 'light' | 'dark';
toggleTheme: () => void; toggleTheme: () => void;
} }

View File

@ -112,7 +112,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
width: isMobile ? 35 : 100, width: isMobile ? 35 : 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => ( cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
<div className="h-full flex h-full items-center justify-end"> <div className="h-full flex h-full items-center justify-end">
<div className="uppercase text-center pr-8"> <div className="uppercase text-center pr-2">
{!isMobile && t('Trade')} {!isMobile && t('Trade')}
<Icon <Icon
name={IconNames.ARROW_TOP_RIGHT} name={IconNames.ARROW_TOP_RIGHT}

View File

@ -1,7 +1,7 @@
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import type { LocalValues } from '../context/local-context'; import type { LocalValues } from '../context/local-context';
const useLocalValues = (toggleTheme: () => void) => { const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
const [connect, setConnect] = useState<boolean>(false); const [connect, setConnect] = useState<boolean>(false);
const [manage, setManage] = useState<boolean>(false); const [manage, setManage] = useState<boolean>(false);
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
@ -9,9 +9,10 @@ const useLocalValues = (toggleTheme: () => void) => {
() => ({ () => ({
vegaWalletDialog: { connect, manage, setConnect, setManage }, vegaWalletDialog: { connect, manage, setConnect, setManage },
menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) }, menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) },
theme,
toggleTheme, toggleTheme,
}), }),
[connect, manage, toggleTheme, menuOpen] [connect, manage, theme, toggleTheme, menuOpen]
); );
}; };

View File

@ -16,7 +16,8 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.js", "**/*.test.js",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.test.jsx" "**/*.test.jsx",
"jest.config.ts"
], ],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
} }

View File

@ -17,6 +17,7 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.jsx", "**/*.test.jsx",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.d.ts" "**/*.d.ts",
"jest.config.ts"
] ]
} }

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/explorer-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/explorer-e2e/src", "sourceRoot": "apps/explorer-e2e/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {

View File

@ -1,9 +1,9 @@
# App configuration variables # App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n06.testnet.vega.xyz/tm NX_TENDERMINT_URL=https://tm.n06.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n06.testnet.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -1,4 +1,5 @@
module.exports = { /* eslint-disable */
export default {
displayName: 'explorer', displayName: 'explorer',
preset: '../../jest.preset.js', preset: '../../jest.preset.js',
transform: { transform: {

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/explorer", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/explorer/src", "sourceRoot": "apps/explorer/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {
@ -41,7 +41,7 @@
"executor": "./tools/executors/webpack:serve", "executor": "./tools/executors/webpack:serve",
"options": { "options": {
"port": 3000, "port": 3000,
"buildTarget": "explorer:build", "buildTarget": "explorer:build:development",
"hmr": true "hmr": true
}, },
"configurations": { "configurations": {
@ -62,12 +62,12 @@
"executor": "@nrwl/jest:jest", "executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/explorer"], "outputs": ["coverage/apps/explorer"],
"options": { "options": {
"jestConfig": "apps/explorer/jest.config.js", "jestConfig": "apps/explorer/jest.config.ts",
"passWithNoTests": true "passWithNoTests": true
} }
}, },
"build-netlify": { "build-netlify": {
"builder": "@nrwl/workspace:run-commands", "executor": "@nrwl/workspace:run-commands",
"options": { "options": {
"commands": [ "commands": [
"cp apps/explorer/netlify.toml netlify.toml", "cp apps/explorer/netlify.toml netlify.toml",

View File

@ -45,15 +45,16 @@ function App() {
menuOpen && 'h-[100vh] overflow-hidden' menuOpen && 'h-[100vh] overflow-hidden'
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`} } antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
> >
<div className="min-h-[100vh] max-w-[1300px] grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-black dark:border-white lg:border-l-1 lg:border-r-1 mx-auto"> <div className="min-h-[100vh] max-w-[1300px] grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-neutral-700 dark:border-neutral-300 lg:border-l lg:border-r mx-auto">
<Header <Header
theme={theme}
toggleTheme={toggleTheme} toggleTheme={toggleTheme}
menuOpen={menuOpen} menuOpen={menuOpen}
setMenuOpen={setMenuOpen} setMenuOpen={setMenuOpen}
/> />
<Nav menuOpen={menuOpen} /> <Nav menuOpen={menuOpen} />
<Main /> <Main />
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] md:flex md:col-span-2 p-16 gap-12 border-t-1"> <footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-sm md:text-md md:flex md:col-span-2 p-4 gap-4 border-t border-neutral-700 dark:border-neutral-300">
<NetworkInfo /> <NetworkInfo />
</footer> </footer>
</div> </div>

View File

@ -22,7 +22,7 @@ export const BlockData = ({ block, className }: BlockProps) => {
<TableRow data-testid="block-row" modifier="background"> <TableRow data-testid="block-row" modifier="background">
<TableCell <TableCell
data-testid="block-height" data-testid="block-height"
className="pl-4 py-2 font-mono" className="p-0.5 font-mono"
aria-label={t('Block height')} aria-label={t('Block height')}
> >
<Link <Link
@ -34,7 +34,7 @@ export const BlockData = ({ block, className }: BlockProps) => {
</TableCell> </TableCell>
<TableCell <TableCell
data-testid="num-txs" data-testid="num-txs"
className="px-8 text-center" className="text-center"
aria-label={t('Number of transactions')} aria-label={t('Number of transactions')}
> >
{block.num_txs === '1' {block.num_txs === '1'
@ -43,7 +43,7 @@ export const BlockData = ({ block, className }: BlockProps) => {
</TableCell> </TableCell>
<TableCell <TableCell
data-testid="validator-link" data-testid="validator-link"
className="px-8 text-center font-mono" className="text-center font-mono"
aria-label={t('Validator')} aria-label={t('Validator')}
> >
<Link to={`/${Routes.VALIDATORS}`}> <Link to={`/${Routes.VALIDATORS}`}>
@ -52,7 +52,7 @@ export const BlockData = ({ block, className }: BlockProps) => {
</TableCell> </TableCell>
<TableCell <TableCell
data-testid="block-time" data-testid="block-time"
className="text-center pr-28 text-neutral-300 w-[170px]" className="text-center pr-6 w-[170px]"
aria-label={t('Block genesis')} aria-label={t('Block genesis')}
> >
<Tooltip <Tooltip

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useTendermintWebsocket } from '../../hooks/use-tendermint-websocket'; import { useTendermintWebsocket } from '../../hooks/use-tendermint-websocket';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { Button } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
interface BlocksRefetchProps { interface BlocksRefetchProps {
refetch: () => void; refetch: () => void;
@ -26,17 +26,11 @@ export const BlocksRefetch = ({ refetch }: BlocksRefetchProps) => {
}; };
return ( return (
<> <div className="mb-4">
<span data-testid="new-blocks">{blocksToLoad} new blocks -</span> <span data-testid="new-blocks">{blocksToLoad} new blocks - </span>
<ButtonLink onClick={refresh} data-testid="refresh">
<Button
onClick={refresh}
variant="inline-link"
className="mb-28"
data-testid="refresh"
>
{t('refresh to see latest')} {t('refresh to see latest')}
</Button> </ButtonLink>
</> </div>
); );
}; };

View File

@ -1,26 +1,35 @@
import type { Dispatch, SetStateAction } from 'react'; import classnames from 'classnames';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { ThemeSwitcher, Icon } from '@vegaprotocol/ui-toolkit'; import { ThemeSwitcher, Icon } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { Search } from '../search'; import { Search } from '../search';
import { Routes } from '../../routes/route-names'; import { Routes } from '../../routes/route-names';
import type { Dispatch, SetStateAction } from 'react';
interface ThemeToggleProps { interface ThemeToggleProps {
theme: 'light' | 'dark';
toggleTheme: () => void; toggleTheme: () => void;
menuOpen: boolean; menuOpen: boolean;
setMenuOpen: Dispatch<SetStateAction<boolean>>; setMenuOpen: Dispatch<SetStateAction<boolean>>;
} }
export const Header = ({ export const Header = ({
theme,
toggleTheme, toggleTheme,
menuOpen, menuOpen,
setMenuOpen, setMenuOpen,
}: ThemeToggleProps) => { }: ThemeToggleProps) => {
const headerClasses = classnames(
'md:col-span-2',
'grid grid-rows-2 md:grid-rows-1 grid-cols-[1fr_auto] md:grid-cols-[auto_1fr_auto] items-center',
'p-4 gap-2 md:gap-4',
'border-b border-neutral-700 dark:border-neutral-300'
);
return ( return (
<header className="grid grid-rows-2 grid-cols-[1fr_auto] md:flex md:col-span-2 p-16 gap-12 border-b-1"> <header className={headerClasses}>
<Link to={Routes.HOME}> <Link to={Routes.HOME}>
<h1 <h1
className="text-h3 font-alpha uppercase calt mb-2" className="text-3xl font-alpha uppercase calt mb-0"
data-testid="explorer-header" data-testid="explorer-header"
> >
{t('Vega Explorer')} {t('Vega Explorer')}
@ -31,10 +40,10 @@ export const Header = ({
className="md:hidden" className="md:hidden"
onClick={() => setMenuOpen(!menuOpen)} onClick={() => setMenuOpen(!menuOpen)}
> >
<Icon name={menuOpen ? 'cross' : 'menu'} size={20} /> <Icon name={menuOpen ? 'cross' : 'menu'} />
</button> </button>
<Search /> <Search />
<ThemeSwitcher onToggle={toggleTheme} /> <ThemeSwitcher theme={theme} onToggle={toggleTheme} />
</header> </header>
); );
}; };

View File

@ -25,13 +25,10 @@ export const JumpTo = ({
}: JumpToProps) => { }: JumpToProps) => {
return ( return (
<form onSubmit={submitHandler}> <form onSubmit={submitHandler}>
<label <label htmlFor={inputId} className="block uppercase font-bold mb-2">
htmlFor={inputId}
className="block uppercase text-h5 font-bold mb-4"
>
{label} {label}
</label> </label>
<div className="flex"> <div className="flex gap-2">
<Input <Input
data-testid={inputId} data-testid={inputId}
id={inputId} id={inputId}
@ -42,12 +39,7 @@ export const JumpTo = ({
min={inputMin} min={inputMin}
max={inputMax} max={inputMax}
/> />
<Button <Button data-testid="go-submit" size="sm" type="submit">
data-testid="go-submit"
variant="secondary"
boxShadow={false}
type="submit"
>
{t('Go')} {t('Go')}
</Button> </Button>
</div> </div>

View File

@ -2,7 +2,7 @@ import { AppRouter } from '../../routes';
export const Main = () => { export const Main = () => {
return ( return (
<main className="p-20 overflow-hidden"> <main className="p-4 overflow-hidden">
<AppRouter /> <AppRouter />
</main> </main>
); );

View File

@ -12,7 +12,7 @@ export const Nav = ({ menuOpen }: NavProps) => {
<div <div
className={classnames( className={classnames(
'absolute top-0 z-50 md:static', 'absolute top-0 z-50 md:static',
'w-full p-20 md:border-r-1', 'w-full p-4 md:border-r border-neutral-700 dark:border-neutral-300',
'bg-white dark:bg-black', 'bg-white dark:bg-black',
'transition-[right]', 'transition-[right]',
{ {
@ -27,8 +27,8 @@ export const Nav = ({ menuOpen }: NavProps) => {
to={r.path} to={r.path}
className={({ isActive }) => className={({ isActive }) =>
classnames( classnames(
'block mb-8 px-8', 'block mb-2 px-2',
'text-h5 hover:bg-vega-pink dark:hover:bg-vega-yellow hover:text-white dark:hover:text-black', 'text-lg hover:bg-vega-pink dark:hover:bg-vega-yellow hover:text-white dark:hover:text-black',
{ {
'bg-vega-pink text-white dark:bg-vega-yellow dark:text-black': 'bg-vega-pink text-white dark:bg-vega-yellow dark:text-black':
isActive, isActive,

View File

@ -14,10 +14,9 @@ export const RouteTitle = ({
}: RouteTitleProps) => { }: RouteTitleProps) => {
const classes = classnames( const classes = classnames(
'font-alpha', 'font-alpha',
'text-h3', 'text-2xl',
'uppercase', 'uppercase',
'mt-12', 'mb-8',
'mb-28',
className className
); );
return ( return (

View File

@ -53,14 +53,12 @@ export const Search = () => {
return ( return (
<form <form
onSubmit={handleSubmit(onSubmit)} onSubmit={handleSubmit(onSubmit)}
className="flex-1 flex self-center md:ml-16 md:mr-12 md:justify-end" className="w-full md:max-w-[620px] justify-self-end"
> >
<FormGroup <label htmlFor="search" className="sr-only">
label={t('Search by block number or transaction hash')} {t('Search by block number or transaction hash')}
className="relative w-full md:w-2/3 mb-0" </label>
labelClassName="sr-only" <div className="flex items-stretch gap-2">
labelFor="search"
>
<Input <Input
{...register('search')} {...register('search')}
id="search" id="search"
@ -70,23 +68,16 @@ export const Search = () => {
placeholder={t('Enter block number or transaction hash')} placeholder={t('Enter block number or transaction hash')}
/> />
{error?.message && ( {error?.message && (
<InputError <div className="absolute top-[100%] flex-1 w-full">
data-testid="search-error" <InputError data-testid="search-error" intent="danger">
intent="danger" {error.message}
className="absolute top-[100%] flex-1 w-full" </InputError>
> </div>
{error.message}
</InputError>
)} )}
</FormGroup> <Button type="submit" size="sm" data-testid="search-button">
<Button {t('Search')}
type="submit" </Button>
boxShadow={false} </div>
variant="secondary"
data-testid="search-button"
>
{t('Search')}
</Button>
</form> </form>
); );
}; };

View File

@ -11,7 +11,7 @@ export const StatusMessage = ({
className, className,
...props ...props
}: StatusMessageProps) => { }: StatusMessageProps) => {
const classes = classnames('font-alpha text-h4 mb-28', className); const classes = classnames('font-alpha text-2xl mb-28', className);
return ( return (
<h3 className={classes} {...props}> <h3 className={classes} {...props}>
{children} {children}

View File

@ -13,10 +13,9 @@ export const SubHeading = ({
}: SubHeadingProps) => { }: SubHeadingProps) => {
const classes = classnames( const classes = classnames(
'font-alpha', 'font-alpha',
'text-h4', 'text-2xl',
'uppercase', 'uppercase',
'mt-12', 'mt-8 mb-2',
'mb-12',
'truncate', 'truncate',
className className
); );

View File

@ -2,7 +2,7 @@ import type { ThHTMLAttributes } from 'react';
import React from 'react'; import React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
interface TableProps extends ThHTMLAttributes<HTMLTableElement> { interface TableProps {
children: React.ReactNode; children: React.ReactNode;
className?: string; className?: string;
} }
@ -73,8 +73,9 @@ export const TableRow = ({
...props ...props
}: TableRowProps) => { }: TableRowProps) => {
const cellClasses = classnames(className, { const cellClasses = classnames(className, {
'border-b border-black-40 dark:border-white-40': modifier === 'bordered', 'border-b border-neutral-600 dark:border-neutral-400':
'border-b-4 bg-black-25 border-b-white dark:bg-white-25 dark:border-b-black': modifier === 'bordered',
'border-b-2 bg-neutral-300 border-white dark:bg-neutral-700 dark:border-black':
modifier === 'background', modifier === 'background',
}); });
return ( return (
@ -91,7 +92,7 @@ export const TableCell = ({
...props ...props
}: TableCellProps) => { }: TableCellProps) => {
const cellClasses = classnames(className, { const cellClasses = classnames(className, {
'py-4': modifier === 'bordered', 'py-1': modifier === 'bordered',
}); });
return ( return (
<td className={cellClasses} {...props}> <td className={cellClasses} {...props}>

View File

@ -76,6 +76,6 @@ describe('Table cell', () => {
</TableWithTbody> </TableWithTbody>
); );
expect(screen.getByTestId('modifier-class-test')).toHaveClass('py-4'); expect(screen.getByTestId('modifier-class-test')).toHaveClass('py-1');
}); });
}); });

View File

@ -27,7 +27,7 @@ export const TxsInfiniteListItem = ({
return ( return (
<div <div
data-testid="transaction-row" data-testid="transaction-row"
className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full border-t border-black-60 dark:border-white-25 py-8 txs-infinite-list-item" className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full border-t border-neutral-600 dark:border-neutral-800 py-8 txs-infinite-list-item"
> >
<div className="whitespace-nowrap overflow-scroll" data-testid="tx-hash"> <div className="whitespace-nowrap overflow-scroll" data-testid="tx-hash">
<TruncatedLink <TruncatedLink

View File

@ -72,9 +72,9 @@ export const TxsInfiniteList = ({
return ( return (
<div className={className} data-testid="transactions-list"> <div className={className} data-testid="transactions-list">
<div className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full mb-8"> <div className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full mb-8">
<div className="text-h5 font-bold">Txn hash</div> <div className="text-lg font-bold">Txn hash</div>
<div className="text-h5 font-bold">Party</div> <div className="text-lg font-bold">Party</div>
<div className="text-h5 font-bold pl-2">Type</div> <div className="text-lg font-bold pl-2">Type</div>
</div> </div>
<div data-testid="infinite-scroll-wrapper"> <div data-testid="infinite-scroll-wrapper">
<InfiniteLoader <InfiniteLoader

View File

@ -113,7 +113,7 @@ const Blocks = () => {
blocks={blocksData} blocks={blocksData}
loadMoreBlocks={loadBlocks} loadMoreBlocks={loadBlocks}
error={blocksError} error={blocksError}
className="mb-28" className="mb-4"
/> />
<JumpToBlock /> <JumpToBlock />
</section> </section>

View File

@ -31,16 +31,16 @@ const Block = () => {
<RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle> <RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle>
<RenderFetched error={error} loading={loading}> <RenderFetched error={error} loading={loading}>
<> <>
<div className="grid grid-cols-2 gap-16 mb-24"> <div className="grid grid-cols-2 gap-2 mb-8">
<Link <Link
data-testid="previous-block" data-testid="previous-block"
to={`/${Routes.BLOCKS}/${Number(block) - 1}`} to={`/${Routes.BLOCKS}/${Number(block) - 1}`}
> >
<Button <Button
data-testid="previous-block-button" data-testid="previous-block-button"
className="w-full" fill={true}
size="sm"
disabled={Number(block) === 1} disabled={Number(block) === 1}
variant="secondary"
> >
Previous Previous
</Button> </Button>
@ -49,14 +49,14 @@ const Block = () => {
data-testid="next-block" data-testid="next-block"
to={`/${Routes.BLOCKS}/${Number(block) + 1}`} to={`/${Routes.BLOCKS}/${Number(block) + 1}`}
> >
<Button className="w-full" variant="secondary"> <Button size="sm" fill={true}>
Next Next
</Button> </Button>
</Link> </Link>
</div> </div>
{blockData && ( {blockData && (
<> <>
<TableWithTbody className="mb-28"> <TableWithTbody className="mb-8">
<TableRow modifier="bordered"> <TableRow modifier="bordered">
<TableHeader scope="row">Mined by</TableHeader> <TableHeader scope="row">Mined by</TableHeader>
<TableCell modifier="bordered"> <TableCell modifier="bordered">

View File

@ -1,7 +1,7 @@
import { StatsManager } from '@vegaprotocol/network-stats'; import { StatsManager } from '@vegaprotocol/network-stats';
const Home = () => { const Home = () => {
const classnames = 'mt-12 grid grid-cols-1 lg:grid-cols-2 lg:gap-16'; const classnames = 'mt-4 grid grid-cols-1 lg:grid-cols-2 lg:gap-4';
return ( return (
<section> <section>
<StatsManager className={classnames} /> <StatsManager className={classnames} />

View File

@ -41,7 +41,7 @@ const Tx = () => {
/> />
</RenderFetched> </RenderFetched>
<h2 className="text-h4 uppercase mb-16">{t('Transaction content')}</h2> <h2 className="text-2xl uppercase mb-4">{t('Transaction content')}</h2>
<RenderFetched error={ceTxError} loading={ceTxLoading}> <RenderFetched error={ceTxError} loading={ceTxLoading}>
<TxContent data={ceTxData} /> <TxContent data={ceTxData} />
</RenderFetched> </RenderFetched>

View File

@ -1,5 +1,5 @@
import { Routes } from '../../route-names'; import { Routes } from '../../route-names';
import { Button, CopyWithTooltip } from '@vegaprotocol/ui-toolkit'; import { ButtonLink, CopyWithTooltip } from '@vegaprotocol/ui-toolkit';
import { import {
TableWithTbody, TableWithTbody,
TableCell, TableCell,
@ -61,12 +61,9 @@ export const TxDetails = ({ txData, pubKey, className }: TxDetailsProps) => {
startChars={txDetailsTruncateLength} startChars={txDetailsTruncateLength}
endChars={txDetailsTruncateLength} endChars={txDetailsTruncateLength}
/> />
<CopyWithTooltip text=""> <CopyWithTooltip text={txData.tx}>
<Button <ButtonLink
variant="inline-link"
prependIconName="duplicate"
title={t('Copy tx to clipboard')} title={t('Copy tx to clipboard')}
onClick={() => navigator.clipboard.writeText(txData.tx)}
data-testid="copy-tx-to-clipboard" data-testid="copy-tx-to-clipboard"
/> />
</CopyWithTooltip> </CopyWithTooltip>

View File

@ -10,6 +10,8 @@ module.exports = {
...createGlobPatternsForDependencies(__dirname), ...createGlobPatternsForDependencies(__dirname),
], ],
darkMode: 'class', darkMode: 'class',
theme, theme: {
extend: theme,
},
plugins: [vegaCustomClasses], plugins: [vegaCustomClasses],
}; };

View File

@ -16,7 +16,8 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.js", "**/*.test.js",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.test.jsx" "**/*.test.jsx",
"jest.config.ts"
], ],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
} }

View File

@ -14,7 +14,8 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.jsx", "**/*.test.jsx",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.d.ts" "**/*.d.ts",
"jest.config.ts"
], ],
"files": [ "files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts", "../../node_modules/@nrwl/react/typings/cssmodule.d.ts",

View File

@ -1,6 +1,6 @@
{ {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application", "projectType": "application",
"root": "apps/static",
"sourceRoot": "apps/static/src", "sourceRoot": "apps/static/src",
"tags": [], "tags": [],
"targets": { "targets": {
@ -46,9 +46,8 @@
} }
} }
}, },
"build-netlify": { "build-netlify": {
"builder": "@nrwl/workspace:run-commands", "executor": "@nrwl/workspace:run-commands",
"options": { "options": {
"commands": [ "commands": [
"cp apps/static/netlify.toml netlify.toml", "cp apps/static/netlify.toml netlify.toml",

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/stats-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/stats-e2e/src", "sourceRoot": "apps/stats-e2e/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {

View File

@ -1,4 +1,5 @@
module.exports = { /* eslint-disable */
export default {
displayName: 'stats', displayName: 'stats',
preset: '../../jest.preset.js', preset: '../../jest.preset.js',
transform: { transform: {

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/stats", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/stats/src", "sourceRoot": "apps/stats/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {
@ -40,7 +40,7 @@
"executor": "./tools/executors/webpack:serve", "executor": "./tools/executors/webpack:serve",
"options": { "options": {
"port": 3010, "port": 3010,
"buildTarget": "stats:build", "buildTarget": "stats:build:development",
"hmr": true "hmr": true
}, },
"configurations": { "configurations": {
@ -61,7 +61,7 @@
"executor": "@nrwl/jest:jest", "executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/stats"], "outputs": ["coverage/apps/stats"],
"options": { "options": {
"jestConfig": "apps/stats/jest.config.js", "jestConfig": "apps/stats/jest.config.ts",
"passWithNoTests": true "passWithNoTests": true
} }
} }

View File

@ -11,9 +11,9 @@ function App() {
return ( return (
<ThemeContext.Provider value={theme}> <ThemeContext.Provider value={theme}>
<NetworkLoader createClient={createClient}> <NetworkLoader createClient={createClient}>
<div className="w-screen min-h-screen grid pb-24 bg-white text-black-95 dark:bg-black dark:text-white-80"> <div className="w-screen min-h-screen grid pb-24 bg-white text-neutral-900 dark:bg-black dark:text-neutral-100">
<div className="layout-grid w-screen justify-self-center"> <div className="layout-grid w-screen justify-self-center">
<Header toggleTheme={toggleTheme} /> <Header theme={theme} toggleTheme={toggleTheme} />
<StatsManager className="max-w-3xl px-24" /> <StatsManager className="max-w-3xl px-24" />
</div> </div>
</div> </div>

View File

@ -2,10 +2,11 @@ import { VegaLogo, ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { VegaBackgroundVideo } from '../videos'; import { VegaBackgroundVideo } from '../videos';
interface ThemeToggleProps { interface ThemeToggleProps {
theme: 'light' | 'dark';
toggleTheme: () => void; toggleTheme: () => void;
} }
export const Header = ({ toggleTheme }: ThemeToggleProps) => { export const Header = ({ theme, toggleTheme }: ThemeToggleProps) => {
return ( return (
<header className="relative overflow-hidden py-8 mb-40 md:mb-64"> <header className="relative overflow-hidden py-8 mb-40 md:mb-64">
<VegaBackgroundVideo /> <VegaBackgroundVideo />
@ -13,7 +14,7 @@ export const Header = ({ toggleTheme }: ThemeToggleProps) => {
<div className="relative flex justify-center px-8 dark:bg-black bg-white"> <div className="relative flex justify-center px-8 dark:bg-black bg-white">
<div className="w-full max-w-3xl p-20 flex items-center justify-between"> <div className="w-full max-w-3xl p-20 flex items-center justify-between">
<VegaLogo /> <VegaLogo />
<ThemeSwitcher onToggle={toggleTheme} /> <ThemeSwitcher theme={theme} onToggle={toggleTheme} />
</div> </div>
</div> </div>
</header> </header>

View File

@ -16,7 +16,8 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.js", "**/*.test.js",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.test.jsx" "**/*.test.jsx",
"jest.config.ts"
], ],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
} }

View File

@ -14,7 +14,8 @@
"**/*.spec.js", "**/*.spec.js",
"**/*.test.jsx", "**/*.test.jsx",
"**/*.spec.jsx", "**/*.spec.jsx",
"**/*.d.ts" "**/*.d.ts",
"jest.config.ts"
], ],
"files": [ "files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts", "../../node_modules/@nrwl/react/typings/cssmodule.d.ts",

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/token-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/token-e2e/src", "sourceRoot": "apps/token-e2e/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {

View File

@ -1,3 +1,5 @@
import { truncateByChars } from '@vegaprotocol/react-helpers';
const walletContainer = '[data-testid="vega-wallet"]'; const walletContainer = '[data-testid="vega-wallet"]';
const walletHeader = '[data-testid="wallet-header"] h1'; const walletHeader = '[data-testid="wallet-header"] h1';
const connectButton = '[data-testid="connect-vega"]'; const connectButton = '[data-testid="connect-vega"]';
@ -19,9 +21,6 @@ const vegaUnstaked = '[data-testid="vega-wallet-balance-unstaked"] .text-right';
const governanceBtn = '[href="/governance"]'; const governanceBtn = '[href="/governance"]';
const stakingBtn = '[href="/staking"]'; const stakingBtn = '[href="/staking"]';
const manageLink = '[data-testid="manage-vega-wallet"]'; const manageLink = '[data-testid="manage-vega-wallet"]';
const dialogWalletName = `[data-testid="key-${Cypress.env(
'vegaWalletPublicKey'
)}"] h2`;
const dialogVegaKey = '[data-testid="vega-public-key-full"]'; const dialogVegaKey = '[data-testid="vega-public-key-full"]';
const dialogDisconnectBtn = '[data-testid="disconnect"]'; const dialogDisconnectBtn = '[data-testid="disconnect"]';
const copyPublicKeyBtn = '[data-testid="copy-vega-public-key"]'; const copyPublicKeyBtn = '[data-testid="copy-vega-public-key"]';
@ -239,19 +238,16 @@ context('Vega Wallet - verify elements on widget', function () {
}); });
}); });
it('should have wallet name visible', function () { it('should have vega wallet public key and name visible', function () {
cy.get(dialog).within(() => {
cy.get(dialogWalletName)
.should('be.visible')
.and('have.text', `${Cypress.env('vegaWalletName')} key 1`);
});
});
it('should have vega wallet public key visible', function () {
cy.get(dialog).within(() => { cy.get(dialog).within(() => {
cy.get(dialogVegaKey) cy.get(dialogVegaKey)
.should('be.visible') .should('be.visible')
.and('have.text', `${Cypress.env('vegaWalletPublicKey')}`); .and(
'have.text',
`${Cypress.env('vegaWalletName')} key 1 ${truncateByChars(
Cypress.env('vegaWalletPublicKey')
)}`
);
}); });
}); });

View File

@ -1,4 +1,5 @@
module.exports = { /* eslint-disable */
export default {
displayName: 'token', displayName: 'token',
preset: '../../jest.preset.js', preset: '../../jest.preset.js',
transform: { transform: {

View File

@ -1,5 +1,5 @@
{ {
"root": "apps/token", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/token/src", "sourceRoot": "apps/token/src",
"projectType": "application", "projectType": "application",
"targets": { "targets": {
@ -41,7 +41,7 @@
"executor": "./tools/executors/webpack:serve", "executor": "./tools/executors/webpack:serve",
"options": { "options": {
"port": 4210, "port": 4210,
"buildTarget": "token:build", "buildTarget": "token:build:development",
"hmr": true "hmr": true
}, },
"configurations": { "configurations": {
@ -62,12 +62,12 @@
"executor": "@nrwl/jest:jest", "executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/token"], "outputs": ["coverage/apps/token"],
"options": { "options": {
"jestConfig": "apps/token/jest.config.js", "jestConfig": "apps/token/jest.config.ts",
"passWithNoTests": true "passWithNoTests": true
} }
}, },
"build-netlify": { "build-netlify": {
"builder": "@nrwl/workspace:run-commands", "executor": "@nrwl/workspace:run-commands",
"options": { "options": {
"commands": [ "commands": [
"cp apps/token/netlify.toml netlify.toml", "cp apps/token/netlify.toml netlify.toml",

View File

@ -3,7 +3,6 @@ import './i18n';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { BrowserRouter as Router } from 'react-router-dom'; import { BrowserRouter as Router } from 'react-router-dom';
import { AppLoader } from './app-loader'; import { AppLoader } from './app-loader';
import { AppBanner } from './components/app-banner';
import { NetworkInfo } from '@vegaprotocol/network-info'; import { NetworkInfo } from '@vegaprotocol/network-info';
import { BalanceManager } from './components/balance-manager'; import { BalanceManager } from './components/balance-manager';
import { EthWallet } from './components/eth-wallet'; import { EthWallet } from './components/eth-wallet';
@ -40,7 +39,7 @@ const AppContainer = () => {
return ( return (
<Router> <Router>
<AppStateProvider> <AppStateProvider>
<div className="grid min-h-full text-white-80"> <div className="grid min-h-full text-white">
<AsyncRenderer loading={loading} data={config} error={error}> <AsyncRenderer loading={loading} data={config} error={error}>
{Connectors && ( {Connectors && (
<Web3Provider connectors={Connectors}> <Web3Provider connectors={Connectors}>
@ -50,12 +49,11 @@ const AppContainer = () => {
<AppLoader> <AppLoader>
<BalanceManager> <BalanceManager>
<> <>
<div className="app max-w-[1300px] mx-auto my-0 grid grid-rows-[min-content_1fr_min-content] min-h-full lg:border-l-1 lg:border-r-1 lg:border-white font-sans text-body lg:text-body-large"> <div className="app w-full max-w-[1300px] mx-auto grid grid-rows-[1fr_min-content] min-h-full border-neutral-700 lg:border-l lg:border-r lg:text-body-large">
<AppBanner />
<TemplateSidebar sidebar={sideBar}> <TemplateSidebar sidebar={sideBar}>
<AppRouter /> <AppRouter />
</TemplateSidebar> </TemplateSidebar>
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] md:flex md:col-span-2 p-16 gap-12 border-t-1"> <footer className="p-4 border-t border-neutral-700">
<NetworkInfo /> <NetworkInfo />
</footer> </footer>
</div> </div>

View File

@ -25,9 +25,9 @@ export const AddLockedTokenAddress = () => {
image={vegaVesting} image={vegaVesting}
/> />
</p> </p>
<div className="flex my-12 gap-12"> <div className="flex my-2 gap-4">
<hr className="flex-1 mt-8" /> <hr className="flex-1 mt-4" />
{t('Or')} <hr className="flex-1 mt-8" /> {t('Or')} <hr className="flex-1 mt-4" />
</div> </div>
</> </>
) : null} ) : null}

View File

@ -1,4 +1,4 @@
import { Button } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAddAssetToWallet } from '../../hooks/use-add-asset-to-wallet'; import { useAddAssetToWallet } from '../../hooks/use-add-asset-to-wallet';
@ -24,11 +24,7 @@ export const AddTokenButtonLink = ({
if (!addSupported) { if (!addSupported) {
return null; return null;
} }
return ( return <ButtonLink onClick={add}>{t('addTokenToWallet')}</ButtonLink>;
<Button variant="inline-link" className="add-token-button" onClick={add}>
{t('addTokenToWallet')}
</Button>
);
}; };
export const AddTokenButton = ({ export const AddTokenButton = ({
@ -56,13 +52,13 @@ export const AddTokenButton = ({
return null; return null;
} }
return ( return (
<Button variant="inline-link" className="add-token-button" onClick={add}> <ButtonLink onClick={add}>
<img <img
className={className} className={className}
style={{ width: size, height: size }} style={{ width: size, height: size }}
alt="token-logo" alt="token-logo"
src={image} src={image}
/> />
</Button> </ButtonLink>
); );
}; };

View File

@ -1,22 +0,0 @@
import { useAppState } from '../../contexts/app-state/app-state-context';
import { Error } from '../icons';
export const AppBanner = () => {
const {
appState: { bannerMessage },
} = useAppState();
// Return empty div so that grid placement remains correct
if (!bannerMessage) return <div />;
return (
<div className="row-start-1 bg-white p-8 text-black" role="alert">
<p>
<span className="inline-block relative top-[1px] text-danger text-ui mr-[5px]">
<Error />
</span>
{bannerMessage}
</p>
</div>
);
};

View File

@ -1 +0,0 @@
export * from './app-banner';

View File

@ -10,11 +10,11 @@ export const BulletHeader = ({ tag, children, style }: BulletHeaderProps) => {
return React.createElement( return React.createElement(
tag, tag,
{ {
className: 'mt-24 py-8 border-t border-white uppercase text-white', className: 'mb-2 uppercase',
style, style,
}, },
<> <>
<span className="inline-block w-[12px] h-[12px] mr-12 bg-white" /> <span className="inline-block w-4 h-4 mr-4 bg-white" />
{children} {children}
</> </>
); );

View File

@ -59,17 +59,17 @@ export function EpochCountdown({
return ( return (
<div data-testid="epoch-countdown" className="epoch-countdown"> <div data-testid="epoch-countdown" className="epoch-countdown">
<div className="flex items-end"> <div className="flex items-end">
<h3 className="flex-1 font-normal mb-4"> <h3 className="flex-1">
{t('Epoch')} {id} {t('Epoch')} {id}
</h3> </h3>
<p className="text-ui-small mb-4"> <p className="text-sm m-0">
{endsIn {endsIn
? t('Next epoch in {{endText}}', { endText: endsIn }) ? t('Next epoch in {{endText}}', { endText: endsIn })
: t('Awaiting next epoch')} : t('Awaiting next epoch')}
</p> </p>
</div> </div>
<ProgressBar value={progress} /> <ProgressBar value={progress} />
<div className="flex mt-4 text-ui-small"> <div className="flex text-sm">
<p>{format(startDate, DATE_FORMAT_DETAILED)}</p> <p>{format(startDate, DATE_FORMAT_DETAILED)}</p>
<div className="flex-1 text-center"> <div className="flex-1 text-center">
<img <img

View File

@ -2,7 +2,7 @@ import { useWeb3React } from '@web3-react/core';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { getButtonClasses, Button } from '@vegaprotocol/ui-toolkit'; import { Button } from '@vegaprotocol/ui-toolkit';
import { import {
AppStateActionType, AppStateActionType,
@ -24,9 +24,7 @@ import {
WalletCardRow, WalletCardRow,
} from '../wallet-card'; } from '../wallet-card';
import { Loader } from '@vegaprotocol/ui-toolkit'; import { Loader } from '@vegaprotocol/ui-toolkit';
import { theme } from '@vegaprotocol/tailwindcss-config'; import colors from 'tailwindcss/colors';
const Colors = theme.colors;
const removeLeadingAddressSymbol = (key: string) => { const removeLeadingAddressSymbol = (key: string) => {
if (key && key.length > 2 && key.slice(0, 2) === '0x') { if (key && key.length > 2 && key.slice(0, 2) === '0x') {
@ -69,18 +67,12 @@ const AssociatedAmounts = ({
total={associationAmounts.total} total={associationAmounts.total}
leftLabel={t('associated')} leftLabel={t('associated')}
rightLabel={t('notAssociated')} rightLabel={t('notAssociated')}
leftColor={Colors.white.DEFAULT} leftColor={colors.white}
rightColor={Colors.black.DEFAULT} rightColor={colors.black}
light={false}
/> />
{vestingAssociationByVegaKey.length ? ( {vestingAssociationByVegaKey.length ? (
<div> <div className="pt-2 border-t border-dashed">
<hr style={{ borderStyle: 'dashed' }} /> <WalletCardRow label="Associated with Vega keys" />
<WalletCardRow
label="Associated with Vega keys"
bold={true}
dark={true}
/>
{vestingAssociationByVegaKey.map(([key, amount], i) => { {vestingAssociationByVegaKey.map(([key, amount], i) => {
return ( return (
<div data-testid="eth-wallet-associated-balances" key={i}> <div data-testid="eth-wallet-associated-balances" key={i}>
@ -88,7 +80,6 @@ const AssociatedAmounts = ({
key={key} key={key}
label={removeLeadingAddressSymbol(key)} label={removeLeadingAddressSymbol(key)}
value={amount} value={amount}
dark={true}
/> />
</div> </div>
); );
@ -138,7 +129,6 @@ const ConnectedKey = () => {
name="VEGA" name="VEGA"
symbol="In vesting contract" symbol="In vesting contract"
balance={totalInVestingContract} balance={totalInVestingContract}
dark={true}
/> />
<LockedProgress <LockedProgress
locked={totalLockedBalance} locked={totalLockedBalance}
@ -146,7 +136,6 @@ const ConnectedKey = () => {
total={totalVestedBalance.plus(totalLockedBalance)} total={totalVestedBalance.plus(totalLockedBalance)}
leftLabel={t('Locked')} leftLabel={t('Locked')}
rightLabel={t('Unlocked')} rightLabel={t('Unlocked')}
light={false}
/> />
</section> </section>
)} )}
@ -165,7 +154,6 @@ const ConnectedKey = () => {
name="VEGA" name="VEGA"
symbol="In Wallet" symbol="In Wallet"
balance={walletWithAssociations} balance={walletWithAssociations}
dark={true}
/> />
{!Object.keys( {!Object.keys(
appState.associationBreakdown.stakingAssociations appState.associationBreakdown.stakingAssociations
@ -177,17 +165,15 @@ const ConnectedKey = () => {
)} )}
</section> </section>
<WalletCardActions> <WalletCardActions>
<Link <Link className="flex-1" to={`${Routes.STAKING}/associate`}>
className={getButtonClasses('flex-1 mr-4', 'secondary')} <Button size="sm" fill={true}>
to={`${Routes.STAKING}/associate`} {t('associate')}
> </Button>
{t('associate')}
</Link> </Link>
<Link <Link className="flex-1" to={`${Routes.STAKING}/disassociate`}>
className={getButtonClasses('flex-1 ml-4', 'secondary')} <Button size="sm" fill={true}>
to={`${Routes.STAKING}/disassociate`} {t('disassociate')}
> </Button>
{t('disassociate')}
</Link> </Link>
</WalletCardActions> </WalletCardActions>
</> </>
@ -201,12 +187,12 @@ export const EthWallet = () => {
const pendingTxs = usePendingTransactions(); const pendingTxs = usePendingTransactions();
return ( return (
<WalletCard dark={true}> <WalletCard>
<section data-testid="ethereum-wallet"> <section data-testid="ethereum-wallet">
<WalletCardHeader> <WalletCardHeader>
<h1 className="m-0 text-h3 uppercase">{t('ethereumKey')}</h1> <h1 className="m-0 uppercase">{t('ethereumKey')}</h1>
{account && ( {account && (
<div className="place-self-end font-mono px-4 pb-2"> <div className="place-self-end font-mono">
<div <div
className="font-mono" className="font-mono"
data-testid="ethereum-account-truncated" data-testid="ethereum-account-truncated"
@ -238,8 +224,7 @@ export const EthWallet = () => {
<ConnectedKey /> <ConnectedKey />
) : ( ) : (
<Button <Button
variant={'secondary'} fill={true}
className="w-full"
onClick={() => onClick={() =>
appDispatch({ appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY, type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
@ -252,15 +237,15 @@ export const EthWallet = () => {
</Button> </Button>
)} )}
{account && ( {account && (
<WalletCardActions> <div className="flex justify-end">
<button <button
className="mt-4 underline" className="underline"
onClick={() => connector.deactivate()} onClick={() => connector.deactivate()}
data-testid="disconnect-from-eth-wallet-button" data-testid="disconnect-from-eth-wallet-button"
> >
{t('disconnect')} {t('disconnect')}
</button> </button>
</WalletCardActions> </div>
)} )}
</WalletCardContent> </WalletCardContent>
</section> </section>

View File

@ -3,9 +3,14 @@ import classNames from 'classnames';
interface HeadingProps { interface HeadingProps {
title?: string; title?: string;
centerContent?: boolean; centerContent?: boolean;
marginBottom?: boolean;
} }
export const Heading = ({ title, centerContent = true }: HeadingProps) => { export const Heading = ({
title,
centerContent = true,
marginBottom = true,
}: HeadingProps) => {
if (!title) return null; if (!title) return null;
return ( return (
@ -14,7 +19,9 @@ export const Heading = ({ title, centerContent = true }: HeadingProps) => {
'mx-auto': centerContent, 'mx-auto': centerContent,
})} })}
> >
<h1 className="font-alpha calt">{title}</h1> <h1 className={classNames('font-alpha calt', { 'mb-0': !marginBottom })}>
{title}
</h1>
</header> </header>
); );
}; };

View File

@ -6,18 +6,12 @@ import classnames from 'classnames';
const Colors = theme.colors; const Colors = theme.colors;
const ProgressContents = ({ const ProgressContents = ({ children }: { children: React.ReactNode }) => (
light,
children,
}: {
light: boolean;
children: React.ReactNode;
}) => (
<div <div
className={classnames('flex justify-between py-2 font-mono mb-2', { className={classnames(
'gap-0 px-0 text-black': light, 'flex justify-between font-mono mb-2',
'gap-y-0 gap-x-4': !light, 'gap-y-0 gap-x-4'
})} )}
> >
{children} {children}
</div> </div>
@ -36,9 +30,9 @@ const ProgressIndicator = ({
style={{ style={{
backgroundColor: bgColor, backgroundColor: bgColor,
}} }}
className={classnames('inline-block w-12 h-12 border', { className={classnames('inline-block w-4 h-4 border', {
'mr-8': side === 'left', 'mr-2': side === 'left',
'ml-8': side === 'right', 'ml-2': side === 'right',
'border-black': light, 'border-black': light,
'border-white': !light, 'border-white': !light,
})} })}
@ -53,7 +47,7 @@ const ProgressBar = ({
bgColor: string; bgColor: string;
}) => ( }) => (
<div <div
className="h-16" className="h-4"
style={{ style={{
flex: isNaN(percentage.toNumber()) ? 0 : percentage.toNumber(), flex: isNaN(percentage.toNumber()) ? 0 : percentage.toNumber(),
backgroundColor: bgColor, backgroundColor: bgColor,
@ -69,7 +63,6 @@ export interface LockedProgressProps {
rightLabel: string; rightLabel: string;
leftColor?: string; leftColor?: string;
rightColor?: string; rightColor?: string;
light?: boolean;
decimals?: number; decimals?: number;
} }
@ -81,7 +74,6 @@ export const LockedProgress = ({
rightLabel, rightLabel,
leftColor = Colors.vega.pink, leftColor = Colors.vega.pink,
rightColor = Colors.vega.green, rightColor = Colors.vega.green,
light = false,
decimals = 2, decimals = 2,
}: LockedProgressProps) => { }: LockedProgressProps) => {
const lockedPercentage = React.useMemo(() => { const lockedPercentage = React.useMemo(() => {
@ -93,18 +85,12 @@ export const LockedProgress = ({
}, [total, unlocked]); }, [total, unlocked]);
return ( return (
<div className="mb-8"> <div className="mb-4">
<div <div className="flex border border-white mb-2" data-testid="progress-bar">
className={classnames('flex border', {
'border-black': light,
'border-white': !light,
})}
data-testid="progress-bar"
>
<ProgressBar percentage={lockedPercentage} bgColor={leftColor} /> <ProgressBar percentage={lockedPercentage} bgColor={leftColor} />
<ProgressBar percentage={unlockedPercentage} bgColor={rightColor} /> <ProgressBar percentage={unlockedPercentage} bgColor={rightColor} />
</div> </div>
<ProgressContents light={light}> <ProgressContents>
<span> <span>
<ProgressIndicator bgColor={leftColor} side={'left'} light={false} /> <ProgressIndicator bgColor={leftColor} side={'left'} light={false} />
{leftLabel} {leftLabel}
@ -118,8 +104,7 @@ export const LockedProgress = ({
/> />
</span> </span>
</ProgressContents> </ProgressContents>
<ProgressContents>
<ProgressContents light={light}>
<span data-testid="currency-locked"> <span data-testid="currency-locked">
{formatNumber(locked, decimals)} {formatNumber(locked, decimals)}
</span> </span>

View File

@ -99,10 +99,10 @@ export const Nav = () => {
return ( return (
<div <div
className={`px-16 py-8 ${ className={`px-4 py-2 ${
inverted inverted
? 'bg-clouds bg-no-repeat bg-cover bg-vega-yellow' ? 'bg-clouds bg-no-repeat bg-cover bg-vega-yellow'
: 'border-b-white border-b-1' : 'border-neutral-700 border-b'
}`} }`}
> >
{isDesktop && <NavHeader fairground={inverted} />} {isDesktop && <NavHeader fairground={inverted} />}
@ -124,7 +124,7 @@ const NavHeader = ({ fairground }: { fairground: boolean }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="flex items-center gap-8"> <div className="flex items-center gap-4">
<Link to="/"> <Link to="/">
{fairground ? ( {fairground ? (
<Fish /> <Fish />
@ -132,26 +132,24 @@ const NavHeader = ({ fairground }: { fairground: boolean }) => {
<img alt="Vega" src={vegaWhite} height={30} width={30} /> <img alt="Vega" src={vegaWhite} height={30} width={30} />
)} )}
</Link> </Link>
<div className="h-[30px] inline-flex items-center lg:h-40 uppercase"> <h1
<h1 data-testid="header-title"
data-testid="header-title" className={`uppercase md:text-2xl sm:text-lg font-alpha uppercase calt my-0 ${
className={`text-h4 sm:text-h3 font-alpha uppercase calt mb-2 ${ fairground ? 'text-black' : 'text-white'
fairground ? 'text-black' : 'text-white' }`}
}`} >
> {fairground ? t('fairgroundTitle') : t('title')}
{fairground ? t('fairgroundTitle') : t('title')} </h1>
</h1>
</div>
</div> </div>
); );
}; };
const DrawerSection = ({ children }: { children: React.ReactNode }) => ( const DrawerSection = ({ children }: { children: React.ReactNode }) => (
<div className="p-12">{children}</div> <div className="px-4 my-4">{children}</div>
); );
const IconLine = ({ inverted }: { inverted: boolean }) => ( const IconLine = ({ inverted }: { inverted: boolean }) => (
<span className={`block w-28 h-4 ${inverted ? 'bg-black' : 'bg-white'}`} /> <span className={`block w-6 h-[2px] ${inverted ? 'bg-black' : 'bg-white'}`} />
); );
const NavDrawer = ({ inverted }: { inverted: boolean }) => { const NavDrawer = ({ inverted }: { inverted: boolean }) => {
@ -162,7 +160,7 @@ const NavDrawer = ({ inverted }: { inverted: boolean }) => {
// Positions the modal in the center of screen // Positions the modal in the center of screen
'fixed w-[80vw] max-w-[420px] top-0 right-0', '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', 'flex flex-col flex-nowrap justify-between h-full bg-banner overflow-y-scroll border-l border-white',
'bg-black text-white-95' 'bg-black text-neutral-200'
); );
return ( return (
<> <>
@ -173,7 +171,7 @@ const NavDrawer = ({ inverted }: { inverted: boolean }) => {
isOpen: true, isOpen: true,
}) })
} }
className="flex flex-col flex-nowrap gap-4" className="flex flex-col flex-nowrap gap-1"
> >
<IconLine inverted={inverted} /> <IconLine inverted={inverted} />
<IconLine inverted={inverted} /> <IconLine inverted={inverted} />
@ -230,7 +228,7 @@ const NavLinks = ({
{ route: Routes.GOVERNANCE, text: t('Governance') }, { route: Routes.GOVERNANCE, text: t('Governance') },
]; ];
const navClasses = classNames('flex', { const navClasses = classNames('flex', {
'flex-row gap-8 mt-8 uppercase': isDesktop, 'flex-row gap-2 mt-4 uppercase': isDesktop,
'flex-col': !isDesktop, 'flex-col': !isDesktop,
}); });
@ -243,19 +241,16 @@ const NavLinks = ({
to={route} to={route}
key={route} key={route}
className={({ isActive }) => className={({ isActive }) =>
classNames( classNames({
'no-underline hover:no-underline focus-visible:outline-none focus-visible:border-none focus-visible:shadow-inset-white', 'bg-vega-yellow text-black': !isInverted && isActive,
{ 'bg-transparent text-white hover:text-vega-yellow':
'bg-vega-yellow text-black': !isInverted && isActive, !isInverted && !isActive,
'bg-transparent text-white hover:text-vega-yellow': 'bg-black text-white': isInverted && isActive,
!isInverted && !isActive, 'bg-transparent text-black hover:text-white':
'bg-black text-white': isInverted && isActive, isInverted && !isActive,
'bg-transparent text-black hover:text-white': 'py-1 px-2': isDesktop,
isInverted && !isActive, 'border-t border-white p-4': !isDesktop,
'py-2 px-12': isDesktop, })
'border-t border-white p-20': !isDesktop,
}
)
} }
> >
{text} {text}

View File

@ -9,12 +9,12 @@ export interface TemplateSidebarProps {
export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) { export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
return ( return (
<div className="row-start-2 border-b border-white lg:grid lg:grid-rows-[auto_minmax(600px,_1fr)] lg:grid-cols-[850px_450px]"> <div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[min-content_1fr] lg:grid-cols-[1fr_450px]">
<Nav /> <Nav />
<main className="col-start-1 p-20">{children}</main> <main className="col-start-1 p-4">{children}</main>
<aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-20 bg-banner bg-contain border-l border-white"> <aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700">
{sidebar.map((Component, i) => ( {sidebar.map((Component, i) => (
<section className="mb-20 last:mb-0" key={i}> <section className="mb-4 last:mb-0" key={i}>
{Component} {Component}
</section> </section>
))} ))}

View File

@ -5,6 +5,7 @@ import {
Intent, Intent,
FormGroup, FormGroup,
Lozenge, Lozenge,
ButtonLink,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import React from 'react'; import React from 'react';
@ -60,14 +61,14 @@ export const AmountInput = ({
/> />
</div> </div>
{maximum && ( {maximum && (
<Button <div className="flex flex-col justify-center p-8 h-28 my-0 mx-8">
variant="inline-link" <ButtonLink
onClick={() => setAmount(maximum.toString())} onClick={() => setAmount(maximum.toString())}
data-testid="token-amount-use-maximum" data-testid="token-amount-use-maximum"
className="flex flex-col justify-center p-8 h-28 my-0 mx-8" >
> {t('Use maximum')}
{t('Use maximum')} </ButtonLink>
</Button> </div>
)} )}
</div> </div>
); );
@ -158,7 +159,7 @@ export const TokenInput = ({
approveContent = ( approveContent = (
<Button <Button
data-testid="token-input-approve-button" data-testid="token-input-approve-button"
className="token-input__submit w-full" fill={true}
onClick={approve} onClick={approve}
> >
{approveText} {approveText}
@ -176,9 +177,9 @@ export const TokenInput = ({
return ( return (
<> <>
<FormGroup <FormGroup
labelClassName="sr-only"
label={t('Input Amount')} label={t('Input Amount')}
labelFor={inputName} labelFor={inputName}
hideLabel={true}
> >
<AmountInput <AmountInput
amount={amount} amount={amount}
@ -190,7 +191,7 @@ export const TokenInput = ({
{approveContent ? <div className="mb-24">{approveContent}</div> : null} {approveContent ? <div className="mb-24">{approveContent}</div> : null}
<Button <Button
data-testid="token-input-submit-button" data-testid="token-input-submit-button"
className="w-full" fill={true}
disabled={isDisabled} disabled={isDisabled}
onClick={perform} onClick={perform}
> >

View File

@ -13,7 +13,7 @@ import type { TxData } from '../../stores/transactions';
import { useTransactionStore } from '../../stores/transactions'; import { useTransactionStore } from '../../stores/transactions';
const TransactionModalTh = ({ children }: { children: React.ReactNode }) => ( const TransactionModalTh = ({ children }: { children: React.ReactNode }) => (
<th className="border-b border-black-25 text-black-60 text-left font-normal"> <th className="border-b border-neutral-600 text-neutral-600 text-left font-normal">
{children} {children}
</th> </th>
); );

View File

@ -6,9 +6,9 @@ export const DownloadWalletPrompt = () => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
<h3 className="mt-12 mb-4">{t('getWallet')}</h3> <h3 className="mt-4 mb-2">{t('getWallet')}</h3>
<p className="mb-4"> <p>
<Link className="text-deemphasise" href={Links.WALLET_PAGE}> <Link className="text-neutral-500" href={Links.WALLET_PAGE}>
{t('getWalletLink')} {t('getWalletLink')}
</Link> </Link>
</p> </p>

View File

@ -24,7 +24,7 @@ import { DownloadWalletPrompt } from './download-wallet-prompt';
import { usePollForDelegations } from './hooks'; import { usePollForDelegations } from './hooks';
import type { VegaKeyExtended } from '@vegaprotocol/wallet'; import type { VegaKeyExtended } from '@vegaprotocol/wallet';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { Button } from '@vegaprotocol/ui-toolkit'; import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
export const VegaWallet = () => { export const VegaWallet = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -38,14 +38,14 @@ export const VegaWallet = () => {
return ( return (
<section className="vega-wallet" data-testid="vega-wallet"> <section className="vega-wallet" data-testid="vega-wallet">
<WalletCard dark={true}> <WalletCard>
<WalletCardHeader dark={true}> <WalletCardHeader dark={true}>
<h1 className="col-start-1 m-0">{t('vegaWallet')}</h1> <h1 className="col-start-1 m-0">{t('vegaWallet')}</h1>
{keypair && ( {keypair && (
<> <>
<div <div
data-testid="wallet-name" data-testid="wallet-name"
className="sm:row-start-2 sm:col-start-1 sm:col-span-2 text-h6 mb-12" className="sm:row-start-2 sm:col-start-1 sm:col-span-2 text-base mb-4"
> >
{keypair.name} {keypair.name}
</div> </div>
@ -77,8 +77,7 @@ const VegaWalletNotConnected = () => {
isOpen: true, isOpen: true,
}) })
} }
variant="secondary" fill={true}
className="w-full"
data-testid="connect-vega" data-testid="connect-vega"
> >
{t('connectVegaWalletToUseAssociated')} {t('connectVegaWalletToUseAssociated')}
@ -100,12 +99,10 @@ const VegaWalletAssetList = ({ accounts }: VegaWalletAssetsListProps) => {
return ( return (
<> <>
<WalletCardHeader> <WalletCardHeader>
<BulletHeader style={{ border: 'none' }} tag="h2"> <BulletHeader tag="h2">{t('assets')}</BulletHeader>
{t('assets')}
</BulletHeader>
</WalletCardHeader> </WalletCardHeader>
{accounts.map((a, i) => ( {accounts.map((a, i) => (
<WalletCardAsset key={i} {...a} dark={true} /> <WalletCardAsset key={i} {...a} />
))} ))}
</> </>
); );
@ -133,11 +130,9 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
}, [currentStakeAvailable, delegations]); }, [currentStakeAvailable, delegations]);
const footer = ( const footer = (
<WalletCardActions> <div className="flex justify-end">
<Button <ButtonLink
data-testid="manage-vega-wallet" data-testid="manage-vega-wallet"
variant="inline-link"
className="mt-4"
onClick={() => onClick={() =>
appDispatch({ appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY, type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY,
@ -146,8 +141,8 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
} }
> >
Manage Manage
</Button> </ButtonLink>
</WalletCardActions> </div>
); );
return vegaKeys.length ? ( return vegaKeys.length ? (
@ -159,13 +154,12 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
subheading={t('Associated')} subheading={t('Associated')}
symbol="VEGA" symbol="VEGA"
balance={currentStakeAvailable} balance={currentStakeAvailable}
dark={true}
/> />
<div data-testid="vega-wallet-balance-unstaked"> <div data-testid="vega-wallet-balance-unstaked">
<WalletCardRow label={t('unstaked')} value={unstaked} dark={true} /> <WalletCardRow label={t('unstaked')} value={unstaked} />
</div> </div>
{delegatedNodes.length ? ( {delegatedNodes.length ? (
<WalletCardRow label={t('stakedValidators')} dark={true} bold={true} /> <WalletCardRow label={t('stakedValidators')} />
) : null} ) : null}
{delegatedNodes.map((d) => ( {delegatedNodes.map((d) => (
<div key={d.nodeId} data-testid="vega-wallet-balance-staked-validators"> <div key={d.nodeId} data-testid="vega-wallet-balance-staked-validators">
@ -177,7 +171,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
}`} }`}
link={`${Routes.STAKING}/${d.nodeId}`} link={`${Routes.STAKING}/${d.nodeId}`}
value={d.currentEpochStake} value={d.currentEpochStake}
dark={true}
/> />
</div> </div>
)} )}
@ -189,20 +182,19 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
)})`} )})`}
link={`${Routes.STAKING}/${d.nodeId}`} link={`${Routes.STAKING}/${d.nodeId}`}
value={d.nextEpochStake} value={d.nextEpochStake}
dark={true}
/> />
</div> </div>
)} )}
</div> </div>
))} ))}
<WalletCardActions> <WalletCardActions>
<Link className="flex-1 pr-8" to={Routes.GOVERNANCE}> <Link className="flex-1" to={Routes.GOVERNANCE}>
<Button variant={'secondary'} className="w-full"> <Button size="sm" fill={true}>
{t('governance')} {t('governance')}
</Button> </Button>
</Link> </Link>
<Link className="flex-1 pl-8" to={Routes.STAKING}> <Link className="flex-1" to={Routes.STAKING}>
<Button variant={'secondary'} className="w-full"> <Button size="sm" fill={true}>
{t('staking')} {t('staking')}
</Button> </Button>
</Link> </Link>

View File

@ -1,4 +1,3 @@
import classNames from 'classnames';
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -8,19 +7,14 @@ import { useNumberParts } from '@vegaprotocol/react-helpers';
interface WalletCardProps { interface WalletCardProps {
children: React.ReactNode; children: React.ReactNode;
dark?: boolean;
} }
export const WalletCard = ({ dark, children }: WalletCardProps) => { export const WalletCard = ({ children }: WalletCardProps) => {
const className = classNames( return (
'text-ui border border-white', <div className="text-sm border border-neutral-700 p-4 bg-black text-white">
'pt-4 pl-8 pr-12 pb-12', {children}
{ </div>
'bg-black text-white': dark,
'bg-white text-black': !dark,
}
); );
return <div className={className}>{children}</div>;
}; };
interface WalletCardHeaderProps { interface WalletCardHeaderProps {
@ -31,7 +25,7 @@ interface WalletCardHeaderProps {
export const WalletCardHeader = ({ children }: WalletCardHeaderProps) => { export const WalletCardHeader = ({ children }: WalletCardHeaderProps) => {
return ( return (
<div <div
className="grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-4" className="grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-2 mb-2"
data-testid="wallet-header" data-testid="wallet-header"
> >
{children} {children}
@ -44,23 +38,19 @@ interface WalletCardContentProps {
} }
export const WalletCardContent = ({ children }: WalletCardContentProps) => { export const WalletCardContent = ({ children }: WalletCardContentProps) => {
return <div className="mt-8">{children}</div>; return <div>{children}</div>;
}; };
export const WalletCardRow = ({ export const WalletCardRow = ({
label, label,
link, link,
value, value,
dark = false,
decimals = 18, decimals = 18,
bold = false,
}: { }: {
label: string; label: string;
link?: string; link?: string;
decimals?: number; decimals?: number;
value?: BigNumber | null; value?: BigNumber | null;
dark?: boolean;
bold?: boolean;
}) => { }) => {
const ref = React.useRef<HTMLDivElement | null>(null); const ref = React.useRef<HTMLDivElement | null>(null);
useAnimateValue(ref, value); useAnimateValue(ref, value);
@ -68,9 +58,7 @@ export const WalletCardRow = ({
return ( return (
<div <div
className={`flex justify-between gap-y-0 gap-x-4 text-ui my-4 p-2 ${ className="flex justify-between gap-y-0 gap-x-2 text-sm mb-2"
dark ? 'text-white-60' : 'text-black'
} ${bold && 'font-bold'}`}
ref={ref} ref={ref}
> >
{link ? ( {link ? (
@ -78,10 +66,7 @@ export const WalletCardRow = ({
{label} {label}
</Link> </Link>
) : ( ) : (
<span <span className="max-w-[200px]" data-test-id="associated-key">
className={`max-w-[200px] ${dark ? 'text-white' : 'text-black'}`}
data-test-id="associated-key"
>
{label} {label}
</span> </span>
)} )}
@ -90,12 +75,8 @@ export const WalletCardRow = ({
className="font-mono flex-1 text-right" className="font-mono flex-1 text-right"
data-test-id="associated-amount" data-test-id="associated-amount"
> >
<span className={dark ? 'text-white' : 'text-black'}> <span>{integers}.</span>
{integers}. <span>{decimalsPlaces}</span>
</span>
<span className={dark ? 'text-white-60' : 'text-black-60'}>
{decimalsPlaces}
</span>
</span> </span>
)} )}
</div> </div>
@ -107,7 +88,7 @@ export const WalletCardActions = ({
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return <div className="flex justify-end gap-2 py-2">{children}</div>; return <div className="flex justify-end gap-2 mb-4">{children}</div>;
}; };
export interface WalletCardAssetProps { export interface WalletCardAssetProps {
@ -117,7 +98,6 @@ export interface WalletCardAssetProps {
balance: BigNumber; balance: BigNumber;
decimals: number; decimals: number;
border?: boolean; border?: boolean;
dark?: boolean;
subheading?: string; subheading?: string;
} }
@ -128,48 +108,32 @@ export const WalletCardAsset = ({
balance, balance,
decimals, decimals,
border, border,
dark,
subheading, subheading,
}: WalletCardAssetProps) => { }: WalletCardAssetProps) => {
const [integers, decimalsPlaces] = useNumberParts(balance, decimals); const [integers, decimalsPlaces] = useNumberParts(balance, decimals);
return ( return (
<div className="flex flex-nowrap mt-8 mb-16"> <div className="flex flex-nowrap mt-2 mb-4">
<img <img
alt="Vega" alt="Vega"
src={image} src={image}
className={`inline-block h-[30px] rounded-[50%] border ${ className={`inline-block w-6 h-6 mt-2 rounded-full border ${
border ? 'border-white' : 'border-black' border ? 'border-white' : 'border-black'
}`} }`}
/> />
<div> <div>
<div <div
className="flex font-medium align-center" className="flex align-center text-base"
data-testid="currency-title" data-testid="currency-title"
> >
<h1 <div className="mb-0 px-2 uppercase">{name}</div>
className={`text-h5 mb-0 px-8 uppercase leading-none ${ <div className="mb-0 uppercase text-neutral-400">
dark ? 'text-white' : 'text-black'
}`}
>
{name}
</h1>
<h2
className={`text-h5 mb-0 uppercase leading-none ${
dark ? 'text-white-60' : 'text-black-60'
}`}
>
{subheading || symbol} {subheading || symbol}
</h2> </div>
</div> </div>
<div <div className="px-2 basis-full font-mono" data-testid="currency-value">
className="px-8 text-h5 basis-full font-mono"
data-testid="currency-value"
>
<span>{integers}.</span> <span>{integers}.</span>
<span className={dark ? 'text-white-60' : 'text-black-60'}> <span className="text-neutral-400">{decimalsPlaces}</span>
{decimalsPlaces}
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { usePrevious } from './use-previous'; import { usePrevious } from './use-previous';
import type { BigNumber } from '../lib/bignumber'; import type { BigNumber } from '../lib/bignumber';
import { theme as tailwindcss } from '@vegaprotocol/tailwindcss-config'; import { theme } from '@vegaprotocol/tailwindcss-config';
const Colors = tailwindcss.colors; import colors from 'tailwindcss/colors';
const customColors = theme.colors;
const FLASH_DURATION = 1200; // Duration of flash animation in milliseconds const FLASH_DURATION = 1200; // Duration of flash animation in milliseconds
@ -29,15 +30,15 @@ export function useAnimateValue(
) { ) {
elRef.current?.animate( elRef.current?.animate(
[ [
{ backgroundColor: Colors.vega.red, color: Colors.white.DEFAULT }, { backgroundColor: customColors.vega.red, color: colors.white },
{ {
backgroundColor: Colors.vega.red, backgroundColor: customColors.vega.red,
color: Colors.white.DEFAULT, color: colors.white,
offset: 0.8, offset: 0.8,
}, },
{ {
backgroundColor: Colors.white[60], backgroundColor: colors.neutral[500],
color: Colors.white.DEFAULT, color: colors.white,
}, },
], ],
FLASH_DURATION FLASH_DURATION
@ -52,17 +53,17 @@ export function useAnimateValue(
elRef.current?.animate( elRef.current?.animate(
[ [
{ {
backgroundColor: Colors.vega.green, backgroundColor: customColors.vega.green,
color: Colors.white.DEFAULT, color: colors.white,
}, },
{ {
backgroundColor: Colors.vega.green, backgroundColor: customColors.vega.green,
color: Colors.white.DEFAULT, color: colors.white,
offset: 0.8, offset: 0.8,
}, },
{ {
backgroundColor: Colors.white[60], backgroundColor: colors.neutral[500],
color: Colors.white.DEFAULT, color: colors.white,
}, },
], ],
FLASH_DURATION FLASH_DURATION

View File

@ -4,6 +4,6 @@ import { formatNumber as format } from '@vegaprotocol/react-helpers';
export const formatNumber = (value: BigNumber, decimals?: number) => { export const formatNumber = (value: BigNumber, decimals?: number) => {
return format( return format(
value, value,
typeof decimals === 'undefined' ? Math.max(value.dp(), 2) : decimals typeof decimals === 'undefined' ? Math.max(value.dp() || 0, 2) : decimals
); );
}; };

View File

@ -120,7 +120,7 @@ export const ClaimFlow = ({
return ( return (
<> <>
<section> <section>
<div className="lg:grid lg:gap-24 lg:grid-cols-[1fr_1fr] lg:grid-rows-[min-content_min-content]"> <div className="lg:grid lg:gap-6 lg:grid-cols-[1fr_1fr] lg:grid-rows-[min-content_min-content]">
<div> <div>
<p> <p>
<Trans <Trans

View File

@ -76,7 +76,7 @@ export const ClaimForm = ({
} }
return ( return (
<Button type="submit" onClick={handleOnClick} className="fill"> <Button type="submit" onClick={handleOnClick}>
{countryCheck === CountryCheck.Pending {countryCheck === CountryCheck.Pending
? t('verifyingCountryPrompt') ? t('verifyingCountryPrompt')
: t('Continue')} : t('Continue')}

View File

@ -40,7 +40,7 @@ export const ClaimStep2 = ({
return ( return (
<div data-testid="claim-step-2"> <div data-testid="claim-step-2">
<Button type="submit" onClick={onSubmit} className="fill"> <Button type="submit" onClick={onSubmit}>
{t('Claim {amount} Vega', { amount: formatNumber(amount) })} {t('Claim {amount} Vega', { amount: formatNumber(amount) })}
</Button> </Button>
</div> </div>

View File

@ -57,7 +57,7 @@ export const Complete = ({
</p> </p>
)} )}
<RouteLink to={Routes.VESTING}> <RouteLink to={Routes.VESTING}>
<Button className="fill">{t('Check your vesting VEGA tokens')}</Button> <Button>{t('Check your vesting VEGA tokens')}</Button>
</RouteLink> </RouteLink>
</Callout> </Callout>
); );

View File

@ -77,7 +77,7 @@ export const TargetedClaim = ({
onSubmit={claimTargeted} onSubmit={claimTargeted}
/> />
) : ( ) : (
<p className="text-white-60">{t('selectCountryPrompt')}</p> <p>{t('selectCountryPrompt')}</p>
)} )}
</div> </div>
); );

View File

@ -99,7 +99,7 @@ export const UntargetedClaim = ({
onSubmit={commitClaim} onSubmit={commitClaim}
/> />
) : ( ) : (
<p className="text-white-60">{t('selectCountryPrompt')}</p> <p>{t('selectCountryPrompt')}</p>
)} )}
<BulletHeader tag="h2"> <BulletHeader tag="h2">
{t('Step')} 3. {t('Claim tokens')} {t('Step')} 3. {t('Claim tokens')}
@ -112,7 +112,7 @@ export const UntargetedClaim = ({
onSubmit={commitReveal} onSubmit={commitReveal}
/> />
) : ( ) : (
<p className="text-white-60">{t('claimNotReady')}</p> <p>{t('claimNotReady')}</p>
)} )}
</div> </div>
); );

View File

@ -16,7 +16,7 @@ export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {
const terms = proposal.terms; const terms = proposal.terms;
return ( return (
<KeyValueTable data-testid="proposal-change-table" muted={true}> <KeyValueTable data-testid="proposal-change-table">
<KeyValueTableRow> <KeyValueTableRow>
{t('id')} {t('id')}
{proposal.id} {proposal.id}

Some files were not shown because too many files have changed in this diff Show More