Skip to content

Commit

Permalink
feat: multi RPC editor (#25219)
Browse files Browse the repository at this point in the history
## **Description**

Initial UI for a multi rpc editor in the network form.



https://github.com/MetaMask/metamask-extension/assets/3500406/1b38f697-56e6-4594-8c74-6fd341c01796


[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25219?quickstart=1)

## **Related issues**


## **Manual testing steps**

- build with yarn; ENABLE_NETWORK_UI_REDESIGN=1 yarn start
- Settings -> networks
- Should see multi rpc dropdown on ethereum network


## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
bergeron authored Jun 18, 2024
1 parent 7b33133 commit 906f7d3
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 11 deletions.
6 changes: 6 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions ui/pages/settings/networks-tab/index.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
@use "design-system";

.networks-tab {
&__rpc-header {
cursor: default;
}

&__rpc-dropdown {
cursor: pointer;
}

&__rpc-item {
position: relative;
}

&__rpc-item:hover {
cursor: pointer;
background-color: var(--color-background-default-hover);
}

&__rpc-item--selected,
&__rpc-item--selected:hover {
background-color: var(--color-primary-muted);
}

&__rpc-selected-pill {
width: 4px;
height: calc(100% - 8px);
position: absolute;
top: 4px;
left: 4px;
}

&__rpc-popover {
z-index: 1;
}

&__imageclose {
cursor: pointer;
color: var(--color-icon-default);
Expand Down
27 changes: 16 additions & 11 deletions ui/pages/settings/networks-tab/networks-form/networks-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
getMatchedChain,
getMatchedSymbols,
} from '../../../../helpers/utils/network-helper';
import { RpcUrlEditor } from './rpc-url-editor';

/**
* Attempts to convert the given chainId to a decimal string, for display
Expand Down Expand Up @@ -760,17 +761,21 @@ const NetworksForm = ({
disabled={viewOnly}
dataTestId="network-form-network-name"
/>
<FormField
error={errors.rpcUrl?.msg || ''}
onChange={(value) => {
setIsEditing(true);
setRpcUrl(value);
}}
titleText={t('rpcUrl')}
value={displayRpcUrl}
disabled={viewOnly}
dataTestId="network-form-rpc-url"
/>
{window.metamaskFeatureFlags?.networkMenuRedesign ? (
<RpcUrlEditor currentRpcUrl={displayRpcUrl} />
) : (
<FormField
error={errors.rpcUrl?.msg || ''}
onChange={(value) => {
setIsEditing(true);
setRpcUrl(value);
}}
titleText={t('rpcUrl')}
value={displayRpcUrl}
disabled={viewOnly}
dataTestId="network-form-rpc-url"
/>
)}
<FormField
warning={warnings.chainId?.msg || ''}
error={errors.chainId?.msg || ''}
Expand Down
144 changes: 144 additions & 0 deletions ui/pages/settings/networks-tab/networks-form/rpc-url-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import React, { useRef, useState } from 'react';
import classnames from 'classnames';
import {
Box,
ButtonIcon,
ButtonIconSize,
Icon,
IconName,
IconSize,
Popover,
PopoverPosition,
Text,
} from '../../../../components/component-library';
import {
AlignItems,
BackgroundColor,
BorderColor,
BorderRadius,
Display,
IconColor,
JustifyContent,
TextColor,
TextVariant,
} from '../../../../helpers/constants/design-system';
import { useI18nContext } from '../../../../hooks/useI18nContext';

export const RpcUrlEditor = ({ currentRpcUrl }: { currentRpcUrl: string }) => {
// TODO: real endpoints
const dummyRpcUrls = [
currentRpcUrl,
'https://dummy.mainnet.public.blastapi.io',
'https://dummy.io/v3/blockchain/node/dummy',
];

const t = useI18nContext();
const rpcDropdown = useRef(null);
const [isOpen, setIsOpen] = useState(false);
const [currentRpcEndpoint, setCurrentRpcEndpoint] = useState(currentRpcUrl);

return (
<>
<Text
className="networks-tab__rpc-header"
marginTop={1}
marginBottom={1}
variant={TextVariant.bodySmBold}
>
{t('defaultRpcUrl')}
</Text>
<Box
onClick={() => setIsOpen(!isOpen)}
className="networks-tab__rpc-dropdown"
display={Display.Flex}
justifyContent={JustifyContent.spaceBetween}
borderRadius={BorderRadius.MD}
borderColor={BorderColor.borderDefault}
borderWidth={1}
padding={2}
ref={rpcDropdown}
>
<Text variant={TextVariant.bodySm}>{currentRpcEndpoint}</Text>
<ButtonIcon
iconName={isOpen ? IconName.ArrowUp : IconName.ArrowDown}
ariaLabel={t('defaultRpcUrl')}
size={ButtonIconSize.Sm}
/>
</Box>
<Popover
paddingTop={2}
paddingBottom={2}
paddingLeft={0}
paddingRight={0}
className="networks-tab__rpc-popover"
referenceElement={rpcDropdown.current}
position={PopoverPosition.Bottom}
isOpen={isOpen}
>
{dummyRpcUrls.map((rpcEndpoint) => (
<Box
padding={4}
display={Display.Flex}
justifyContent={JustifyContent.spaceBetween}
key={rpcEndpoint}
onClick={() => setCurrentRpcEndpoint(rpcEndpoint)}
className={classnames('networks-tab__rpc-item', {
'networks-tab__rpc-item--selected':
rpcEndpoint === currentRpcEndpoint,
})}
>
{rpcEndpoint === currentRpcEndpoint && (
<Box
className="networks-tab__rpc-selected-pill"
borderRadius={BorderRadius.pill}
backgroundColor={BackgroundColor.primaryDefault}
/>
)}
<Text
as="button"
color={TextColor.textDefault}
variant={TextVariant.bodySmMedium}
backgroundColor={BackgroundColor.transparent}
>
{rpcEndpoint}
</Text>
<ButtonIcon
marginLeft={5}
ariaLabel={t('delete')}
size={ButtonIconSize.Sm}
iconName={IconName.Trash}
color={IconColor.errorDefault}
// eslint-disable-next-line no-alert
onClick={() => alert('TODO: delete confirmation modal')}
/>
</Box>
))}
<Box
// eslint-disable-next-line no-alert
onClick={() => alert('TODO: add RPC modal')}
padding={4}
display={Display.Flex}
alignItems={AlignItems.center}
className="networks-tab__rpc-item"
>
<Icon
color={IconColor.primaryDefault}
name={IconName.Add}
size={IconSize.Sm}
marginRight={2}
/>
<Text
as="button"
backgroundColor={BackgroundColor.transparent}
color={TextColor.primaryDefault}
variant={TextVariant.bodySmMedium}
>
{t('addRpcUrl')}
</Text>
</Box>
</Popover>
</>
);
};

export default RpcUrlEditor;

0 comments on commit 906f7d3

Please sign in to comment.