Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "ldOmsuDgyS+Dz5o+bZtxtgb4Ss5XVJQ0fYpJtbHFtz8=",
"shasum": "ZfrR4llZ3X3UXNIvRClCXQoQ7qSZKdgO3PgVq6L1Gxk=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
Dropdown,
Option,
Checkbox,
Container,
Footer,
} from '@metamask/snaps-sdk/jsx';

/**
Expand Down Expand Up @@ -46,54 +48,72 @@ export type InteractiveFormState = {
'example-selector': string;
};

export const InteractiveForm: SnapComponent = () => {
export const InteractiveForm: SnapComponent<{ disabled?: boolean }> = ({
disabled,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just add a few disabled elements instead of a prop to disable everything?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we want to show each component's disabled state, it would duplicate a lot to introduce each component in its disabled state too 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is neat that we can test the submit button being disabled too, would be kinda hard without a disabled state

}) => {
return (
<Box>
<Heading>Interactive UI Example Snap</Heading>
<Form name="example-form">
<Field label="Example Input">
<Input name="example-input" placeholder="Enter something..." />
</Field>
<Field label="Example Dropdown">
<Dropdown name="example-dropdown">
<Option value="option1">Option 1</Option>
<Option value="option2">Option 2</Option>
<Option value="option3">Option 3</Option>
</Dropdown>
</Field>
<Field label="Example RadioGroup">
<RadioGroup name="example-radiogroup">
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
<Radio value="option3">Option 3</Radio>
</RadioGroup>
</Field>
<Field label="Example Checkbox">
<Checkbox name="example-checkbox" label="Checkbox" />
</Field>
<Field label="Example Selector">
<Selector
name="example-selector"
title="Choose an option"
value="option1"
>
<SelectorOption value="option1">
<Card title="Option 1" value="option1" />
</SelectorOption>
<SelectorOption value="option2">
<Card title="Option 2" value="option2" />
</SelectorOption>
<SelectorOption value="option3">
<Card title="Option 3" value="option3" />
</SelectorOption>
</Selector>
</Field>
<Box center>
<Button type="submit" name="submit">
Submit
</Button>
</Box>
</Form>
</Box>
<Container>
<Box>
<Heading>Interactive UI Example Snap</Heading>
<Form name="example-form">
<Field label="Example Input">
<Input
name="example-input"
placeholder="Enter something..."
disabled={disabled}
/>
</Field>
<Field label="Example Dropdown">
<Dropdown name="example-dropdown" disabled={disabled}>
<Option value="option1">Option 1</Option>
<Option value="option2">Option 2</Option>
<Option value="option3">Option 3</Option>
</Dropdown>
</Field>
<Field label="Example RadioGroup">
<RadioGroup name="example-radiogroup" disabled={disabled}>
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
<Radio value="option3">Option 3</Radio>
</RadioGroup>
</Field>
<Field label="Example Checkbox">
<Checkbox
name="example-checkbox"
label="Checkbox"
disabled={disabled}
/>
</Field>
<Field label="Example Selector">
<Selector
name="example-selector"
title="Choose an option"
value="option1"
disabled={disabled}
>
<SelectorOption value="option1">
<Card title="Option 1" value="option1" />
</SelectorOption>
<SelectorOption value="option2">
<Card title="Option 2" value="option2" />
</SelectorOption>
<SelectorOption value="option3">
<Card title="Option 3" value="option3" />
</SelectorOption>
</Selector>
</Field>
</Form>
</Box>
<Footer>
<Button
type="submit"
name="submit"
form="example-form"
disabled={disabled}
>
Submit
</Button>
</Footer>
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type { SnapComponent } from '@metamask/snaps-sdk/jsx';
import { Heading, Button, Box, Text, Copyable } from '@metamask/snaps-sdk/jsx';
import {
Heading,
Button,
Box,
Text,
Copyable,
Container,
Footer,
} from '@metamask/snaps-sdk/jsx';

import type { InteractiveFormState } from './InteractiveForm';

Expand All @@ -9,17 +17,20 @@ type ResultProps = {

export const Result: SnapComponent<ResultProps> = ({ values }) => {
return (
<Box>
<Heading>Interactive UI Example Snap</Heading>
<Text>You submitted the following values:</Text>
<Container>
<Box>
{Object.values(values).map((value) => (
<Copyable value={value?.toString() ?? ''} />
))}
<Heading>Interactive UI Example Snap</Heading>
<Text>You submitted the following values:</Text>
<Box>
{Object.values(values).map((value) => (
<Copyable value={value?.toString() ?? ''} />
))}
</Box>
</Box>
<Box center>
<Footer>
<Button name="back">Back</Button>
</Box>
</Box>
<Button name="ok">OK</Button>
</Footer>
</Container>
);
};
14 changes: 7 additions & 7 deletions packages/examples/packages/interactive-ui/src/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from '@jest/globals';
import { assertIsConfirmationDialog, installSnap } from '@metamask/snaps-jest';
import { assertIsCustomDialog, installSnap } from '@metamask/snaps-jest';

import {
Insight,
Expand Down Expand Up @@ -52,7 +52,7 @@ describe('onRpcRequest', () => {
await formScreen.clickElement('submit');

const resultScreen = await response.getInterface();
assertIsConfirmationDialog(resultScreen);
assertIsCustomDialog(resultScreen);

expect(resultScreen).toRender(
<Result
Expand All @@ -65,9 +65,9 @@ describe('onRpcRequest', () => {
}}
/>,
);
await resultScreen.ok();
await resultScreen.clickElement('ok');

expect(await response).toRespondWith(true);
expect(await response).toRespondWith(null);
});

it('lets users input nothing', async () => {
Expand All @@ -84,7 +84,7 @@ describe('onRpcRequest', () => {
await formScreen.clickElement('submit');

const resultScreen = await response.getInterface();
assertIsConfirmationDialog(resultScreen);
assertIsCustomDialog(resultScreen);

expect(resultScreen).toRender(
<Result
Expand All @@ -97,9 +97,9 @@ describe('onRpcRequest', () => {
}}
/>,
);
await resultScreen.ok();
await resultScreen.clickElement('ok');

expect(await response).toRespondWith(true);
expect(await response).toRespondWith(null);
});
});
});
Expand Down
24 changes: 21 additions & 3 deletions packages/examples/packages/interactive-ui/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ import { decodeData } from './utils';
export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
switch (request.method) {
case 'dialog': {
const params = request.params as { disabled: boolean };
const disabled = params?.disabled;
const interfaceId = await snap.request({
method: 'snap_createInterface',
params: {
ui: <InteractiveForm disabled={disabled} />,
context: { disabled },
},
});
return await snap.request({
method: 'snap_dialog',
params: {
type: 'confirmation',
content: <InteractiveForm />,
id: interfaceId,
},
});
}
Expand Down Expand Up @@ -139,7 +147,17 @@ export const onUserInput: OnUserInputHandler = async ({
method: 'snap_updateInterface',
params: {
id,
ui: <InteractiveForm />,
ui: <InteractiveForm disabled={context?.disabled as boolean} />,
},
});
break;

case 'ok':
await snap.request({
method: 'snap_resolveInterface',
params: {
id,
value: null,
},
});
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import { getSnapId } from '../../../utils';
export const InteractiveUI: FunctionComponent = () => {
const [invokeSnap, { isLoading, data, error }] = useInvokeMutation();

const handleClick = (method: string) => () => {
const handleClick = (method: string, disabled: boolean) => () => {
invokeSnap({
snapId: getSnapId(INTERACTIVE_UI_SNAP_ID, INTERACTIVE_UI_SNAP_PORT),
method,
params: {
disabled,
},
}).catch(logError);
};
return (
Expand All @@ -33,16 +36,17 @@ export const InteractiveUI: FunctionComponent = () => {
variant="primary"
id="createDialogButton"
disabled={isLoading}
onClick={handleClick('dialog')}
onClick={handleClick('dialog', false)}
>
Create Dialog
</Button>
<Button
variant="primary"
id="getInterfaceStateButton"
onClick={handleClick('getState')}
id="createDisabledDialogButton"
disabled={isLoading}
onClick={handleClick('dialog', true)}
>
Get interface state
Create Disabled Dialog
</Button>
</ButtonGroup>
<Result>
Expand Down
Loading