diff --git a/src/renderer/components/pool/PoolTitle.styles.ts b/src/renderer/components/pool/PoolTitle.styles.ts index 7d3b2b12a..6549a4fb4 100644 --- a/src/renderer/components/pool/PoolTitle.styles.ts +++ b/src/renderer/components/pool/PoolTitle.styles.ts @@ -38,15 +38,6 @@ export const RowItem = styled(A.Col)` align-items: center; ` -export const ButtonActions = styled.div` - display: flex; - align-items: center; - justify-content: center; - > :not(:first-child) { - margin-left: 10px; - } -` - export const TitleContainer = styled.div` display: flex; flex-direction: row; diff --git a/src/renderer/components/pool/PoolTitle.tsx b/src/renderer/components/pool/PoolTitle.tsx index 5c12e6d28..a52aaf405 100644 --- a/src/renderer/components/pool/PoolTitle.tsx +++ b/src/renderer/components/pool/PoolTitle.tsx @@ -1,14 +1,17 @@ import React, { useMemo } from 'react' import * as RD from '@devexperts/remote-data-ts' -import { Asset, AssetAmount, assetToString, formatAssetAmount } from '@xchainjs/xchain-util' +import { Asset, AssetAmount, AssetRuneNative, assetToString, formatAssetAmount } from '@xchainjs/xchain-util' import { Grid } from 'antd' import * as FP from 'fp-ts/lib/function' +import { useIntl } from 'react-intl' +import { useNavigate } from 'react-router-dom' import { Network } from '../../../shared/api/types' +import { Action as ActionButtonAction, ActionButton } from '../../components/uielements/button/ActionButton' import { loadingString } from '../../helpers/stringHelper' +import * as poolsRoutes from '../../routes/pools' import { AssetIcon } from '../uielements/assets/assetIcon' -import { SwapButton, ManageButton } from '../uielements/button' import * as Styled from './PoolTitle.styles' export type Props = { @@ -41,6 +44,9 @@ export const PoolTitle: React.FC = ({ }) => { const isDesktopView = Grid.useBreakpoint()?.md ?? false + const intl = useIntl() + const navigate = useNavigate() + const title = useMemo(() => { const Star = watched ? Styled.StarFilled : Styled.StarOutlined const starClickHandler = watched ? unwatch : watch @@ -68,35 +74,43 @@ export const PoolTitle: React.FC = ({ [priceRD] ) - const buttons = useMemo( - () => ( - - - {isAvailablePool && ( - - )} - - ), - [ - disableAllPoolActions, - disablePoolActions, - walletLocked, - asset, - isDesktopView, - isAvailablePool, - disableTradingPoolAction + const actionButton = useMemo(() => { + const actions: ActionButtonAction[] = [ + { + label: intl.formatMessage({ id: 'common.swap' }), + disabled: !isAvailablePool || disableAllPoolActions || disableTradingPoolAction, + callback: () => { + navigate(poolsRoutes.swap.path({ source: assetToString(AssetRuneNative), target: assetToString(asset) })) + } + }, + { + label: intl.formatMessage({ id: 'common.manage' }), + disabled: disableAllPoolActions || disablePoolActions || walletLocked, + callback: () => { + navigate(poolsRoutes.deposit.path({ asset: assetToString(asset) })) + } + }, + { + label: intl.formatMessage({ id: 'common.savers' }), + disabled: !isAvailablePool || disableAllPoolActions || disableTradingPoolAction, + callback: () => { + navigate(poolsRoutes.savers.path({ asset: assetToString(asset) })) + } + } ] - ) + + return + }, [ + intl, + isAvailablePool, + disableAllPoolActions, + disableTradingPoolAction, + disablePoolActions, + walletLocked, + isDesktopView, + navigate, + asset + ]) return ( @@ -104,7 +118,7 @@ export const PoolTitle: React.FC = ({ {title} {priceStr} - {buttons} + {actionButton} ) } diff --git a/src/renderer/components/uielements/assets/assetIcon/AssetIcon.styles.ts b/src/renderer/components/uielements/assets/assetIcon/AssetIcon.styles.ts index cecb36a9f..f32019663 100644 --- a/src/renderer/components/uielements/assets/assetIcon/AssetIcon.styles.ts +++ b/src/renderer/components/uielements/assets/assetIcon/AssetIcon.styles.ts @@ -77,4 +77,5 @@ export const Icon = styled.img` width: ${({ size, isSynth }) => `${sizes[size] - (isSynth ? 2 : 0) * borders[size]}px`}; height: ${({ size, isSynth }) => `${sizes[size] - (isSynth ? 2 : 0) * borders[size]}px`}; border-radius: 50%; + max-width: auto; // overridden to avoid max-w-100% (default) ` diff --git a/src/renderer/components/uielements/button/ActionButton.stories.tsx b/src/renderer/components/uielements/button/ActionButton.stories.tsx new file mode 100644 index 000000000..10a84cbe3 --- /dev/null +++ b/src/renderer/components/uielements/button/ActionButton.stories.tsx @@ -0,0 +1,75 @@ +import { ComponentMeta, StoryFn } from '@storybook/react' + +import { ActionButton as Component, Props } from './ActionButton' + +const Template: StoryFn = (args) => +export const Default = Template.bind({}) + +const meta: ComponentMeta = { + title: 'Components/button/ActionButton', + argTypes: { + size: { + control: { + type: 'select', + options: ['small', 'medium', 'normal', 'large'] + } + } + }, + args: { + actions: [ + { + label: 'swap', + callback: () => { + console.log('swap') + }, + disabled: false + }, + { + label: 'manage', + callback: () => { + console.log('manage') + }, + disabled: false + }, + { + label: 'savers', + callback: () => { + console.log('savers') + }, + disabled: true + }, + { + label: 'send', + callback: () => { + console.log('send') + }, + disabled: false + }, + { + label: 'deposit', + callback: () => { + console.log('deposit') + }, + disabled: false + }, + { + label: 'upgrade', + callback: () => { + console.log('upgrade') + }, + disabled: true + } + ], + disabled: false, + size: 'normal' + }, + decorators: [ + (Story) => ( +
+ +
+ ) + ] +} + +export default meta diff --git a/src/renderer/components/uielements/button/ActionButton.tsx b/src/renderer/components/uielements/button/ActionButton.tsx new file mode 100644 index 000000000..d12016e7f --- /dev/null +++ b/src/renderer/components/uielements/button/ActionButton.tsx @@ -0,0 +1,66 @@ +import React from 'react' + +import { Popover } from '@headlessui/react' +import { ChevronDownIcon } from '@heroicons/react/24/outline' +import * as A from 'fp-ts/lib/Array' +import * as FP from 'fp-ts/lib/function' +import { useIntl } from 'react-intl' + +import type { Props as ButtonProps } from './FlatButton' +import { TextButton, FlatButton } from './index' + +export type Action = { label: string; callback: FP.Lazy; disabled?: boolean } +export type Props = Omit & { + actions: Action[] + isTextView?: boolean +} + +export const ActionButton: React.FC = (props): JSX.Element => { + const { size, actions, isTextView = true, disabled = false } = props + + const intl = useIntl() + + return ( + + + {({ open }) => ( + + + {intl.formatMessage({ id: 'common.action' })} + + + + )} + + + {({ close }) => ( +
+ {FP.pipe( + actions, + A.mapWithIndex((index, { label, callback, disabled = false }) => ( + ) => { + event.preventDefault() + event.stopPropagation() + callback() + close() + }}> + {label} + + )) + )} +
+ )} +
+
+ ) +} diff --git a/src/renderer/components/uielements/button/ManageButton.stories.tsx b/src/renderer/components/uielements/button/ManageButton.stories.tsx index 7ddebb587..bd1c83bfb 100644 --- a/src/renderer/components/uielements/button/ManageButton.stories.tsx +++ b/src/renderer/components/uielements/button/ManageButton.stories.tsx @@ -12,7 +12,7 @@ const meta: ComponentMeta = { size: { control: { type: 'select', - options: ['small', 'normal', 'large'] + options: ['small', 'medium', 'normal', 'large'] } } }, diff --git a/src/renderer/i18n/de/common.ts b/src/renderer/i18n/de/common.ts index dda6a3bde..bfdf8f4f4 100644 --- a/src/renderer/i18n/de/common.ts +++ b/src/renderer/i18n/de/common.ts @@ -63,6 +63,7 @@ const common: CommonMessages = { 'common.searchAsset': 'Suche Asset', 'common.retry': 'Wiederholen', 'common.reload': 'Neuladen', + 'common.action': 'Aktion', 'common.add': 'Einzahlen', 'common.swap': 'Swap', 'common.savers': 'Savers', diff --git a/src/renderer/i18n/en/common.ts b/src/renderer/i18n/en/common.ts index 2851721dc..27c769fcb 100644 --- a/src/renderer/i18n/en/common.ts +++ b/src/renderer/i18n/en/common.ts @@ -63,6 +63,7 @@ const common: CommonMessages = { 'common.searchAsset': 'Search Asset', 'common.retry': 'Retry', 'common.reload': 'Reload', + 'common.action': 'Action', 'common.add': 'Add', 'common.swap': 'Swap', 'common.savers': 'Savers', diff --git a/src/renderer/i18n/fr/common.ts b/src/renderer/i18n/fr/common.ts index 5a5b40d60..c570134c9 100644 --- a/src/renderer/i18n/fr/common.ts +++ b/src/renderer/i18n/fr/common.ts @@ -63,6 +63,7 @@ const common: CommonMessages = { 'common.searchAsset': 'Rechercher un actif', 'common.retry': 'Réessayer', 'common.reload': 'Recharger', + 'common.action': 'Action - FR', 'common.add': 'Ajouter', 'common.swap': 'Échanger', 'common.savers': 'Savers - FR', diff --git a/src/renderer/i18n/ru/common.ts b/src/renderer/i18n/ru/common.ts index 59be9731c..91e29e9a3 100644 --- a/src/renderer/i18n/ru/common.ts +++ b/src/renderer/i18n/ru/common.ts @@ -63,6 +63,7 @@ const common: CommonMessages = { 'common.searchAsset': 'Поиск актива', 'common.retry': 'Повторить', 'common.reload': 'Обновить', + 'common.action': 'Action - RU', 'common.add': 'Добавить', 'common.swap': 'Обмен', 'common.savers': 'Savers - RU', diff --git a/src/renderer/i18n/types.ts b/src/renderer/i18n/types.ts index 5ee2e6f12..cd5e8ad46 100644 --- a/src/renderer/i18n/types.ts +++ b/src/renderer/i18n/types.ts @@ -62,6 +62,7 @@ export type CommonMessageKey = | 'common.searchAsset' | 'common.retry' | 'common.reload' + | 'common.action' | 'common.add' | 'common.swap' | 'common.savers' diff --git a/src/renderer/views/pools/ActivePools.tsx b/src/renderer/views/pools/ActivePools.tsx index c48170f7d..6b56002ae 100644 --- a/src/renderer/views/pools/ActivePools.tsx +++ b/src/renderer/views/pools/ActivePools.tsx @@ -1,7 +1,14 @@ import React, { useCallback, useMemo, useRef } from 'react' import * as RD from '@devexperts/remote-data-ts' -import { assetToString, baseToAsset, bn, formatAssetAmountCurrency, formatBN } from '@xchainjs/xchain-util' +import { + AssetRuneNative, + assetToString, + baseToAsset, + bn, + formatAssetAmountCurrency, + formatBN +} from '@xchainjs/xchain-util' import { Grid } from 'antd' import { ColumnsType, ColumnType } from 'antd/lib/table' import * as A from 'fp-ts/Array' @@ -13,7 +20,7 @@ import { useNavigate } from 'react-router-dom' import { Network } from '../../../shared/api/types' import { ProtocolLimit, IncentivePendulum } from '../../components/pool' -import { ManageButton, SaversButton, Size as ButtonSize, SwapButton } from '../../components/uielements/button' +import { Action as ActionButtonAction, ActionButton } from '../../components/uielements/button/ActionButton' import { Table } from '../../components/uielements/table' import { useAppContext } from '../../contexts/AppContext' import { useMidgardContext } from '../../contexts/MidgardContext' @@ -79,35 +86,39 @@ export const ActivePools: React.FC = ({ haltedChains, mimir mimirHalt }) - const buttonSize: ButtonSize = isDesktopView ? 'normal' : 'large' + const actions: ActionButtonAction[] = [ + { + label: intl.formatMessage({ id: 'common.swap' }), + disabled: disableAllPoolActions || disableTradingActions, + callback: () => { + console.log('swap', assetToString(asset)) + navigate(poolsRoutes.swap.path({ source: assetToString(AssetRuneNative), target: assetToString(asset) })) + } + }, + { + label: intl.formatMessage({ id: 'common.manage' }), + disabled: disableAllPoolActions || disablePoolActions || walletLocked, + callback: () => { + navigate(poolsRoutes.deposit.path({ asset: assetToString(asset) })) + } + }, + { + label: intl.formatMessage({ id: 'common.savers' }), + disabled: disableAllPoolActions || disableTradingActions, + callback: () => { + navigate(poolsRoutes.savers.path({ asset: assetToString(asset) })) + } + } + ] return ( - - - + ) }, - [haltedChains, mimirHalt, walletLocked, isDesktopView] + [haltedChains, mimirHalt, intl, walletLocked, navigate] ) const btnPoolsColumn = useMemo(