From ffb4258e9157556366e08917884dc9347905f534 Mon Sep 17 00:00:00 2001 From: William Robertson Date: Thu, 27 Jul 2023 16:47:19 -0400 Subject: [PATCH] [wallet-ext] build new "Protect Account" UI screen and add some form primitives (#13160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR adds the new "Protect Account" screen used when clicking "Create a new account" button and as the second step of the "Import Passphrase" and "Import Private Key" flows. As part of this, I attempted to create some new form primitives to make building forms more manageable (all of the existing components aren't quite up to spec, use Formik, and aren't fully accessible). I ended up following an approach similar to https://www.brendonovich.dev/blog/the-ultimate-form-abstraction which gave some creds to @Jordan-Mysten 😆 As a rough outline, we have generic, non-form-library-specific input controls like `TextArea`, `Input`, `PasswordInput`, `Checkbox` which are used to create `react-hook-form` specific controls such as `TextField`, `TextAreaField`, `CheckboxField`, and so forth. We also have some helper components like `Form` and `FormField` to help abstract away some specific form details such as error states when using react-hook-form. I considered using the Radix form primitives, but I didn't really see the immediate value 🤷🏼 Additional note #1: Some of these pages are used in different flows and have different submission logic depending on the usage context. I think I might need to brainstorm on the best way to handle that and tackle it in a follow-up PR Additional note #2: the auto-lock input is still a WIP on the design side, so I have a TODO to add that once it's ready. Checkbox in Figma - https://www.figma.com/file/T06obgYVOUD2JDGXM8QEDX?node-id=341%3A378&main-component=1&fuid=1209977329759347633 Input in Figma - https://www.figma.com/file/T06obgYVOUD2JDGXM8QEDX/01-Components-%3A-Shared?node-id=19%3A312&mode=dev image ## Test Plan - Manual testing (error states, successful submission, accessibility, focus/disabled/hover states, etc.) - CI --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [ ] protocol change - [ ] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes --- apps/wallet/package.json | 1 + .../accounts/ImportPrivateKeyForm.tsx | 34 ++--- .../accounts/ProtectAccountForm.tsx | 94 +++++++++++++ apps/wallet/src/ui/app/index.tsx | 6 +- .../ui/app/pages/accounts/AddAccountPage.tsx | 2 +- .../pages/accounts/CreateNewAccountPage.tsx | 6 - .../app/pages/accounts/ProtectAccountPage.tsx | 34 +++++ .../src/ui/app/shared/forms/CheckboxField.tsx | 33 +++++ apps/wallet/src/ui/app/shared/forms/Form.tsx | 25 ++++ .../src/ui/app/shared/forms/FormField.tsx | 26 ++++ .../src/ui/app/shared/forms/FormLabel.tsx | 24 ++++ .../src/ui/app/shared/forms/TextAreaField.tsx | 19 +++ .../src/ui/app/shared/forms/TextField.tsx | 24 ++++ .../ui/app/shared/forms/controls/Checkbox.tsx | 35 +++++ .../ui/app/shared/forms/controls/Input.tsx | 15 ++ .../shared/forms/controls/PasswordInput.tsx | 35 +++++ .../ui/app/shared/forms/controls/TextArea.tsx | 15 ++ pnpm-lock.yaml | 128 +++++------------- 18 files changed, 427 insertions(+), 129 deletions(-) create mode 100644 apps/wallet/src/ui/app/components/accounts/ProtectAccountForm.tsx delete mode 100644 apps/wallet/src/ui/app/pages/accounts/CreateNewAccountPage.tsx create mode 100644 apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/CheckboxField.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/Form.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/FormField.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/FormLabel.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/TextAreaField.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/TextField.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/controls/Checkbox.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/controls/Input.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/controls/PasswordInput.tsx create mode 100644 apps/wallet/src/ui/app/shared/forms/controls/TextArea.tsx diff --git a/apps/wallet/package.json b/apps/wallet/package.json index 6a78d5b9a3b86..dea2c6ac3d3be 100644 --- a/apps/wallet/package.json +++ b/apps/wallet/package.json @@ -121,6 +121,7 @@ "@mysten/sui.js": "workspace:*", "@mysten/wallet-standard": "workspace:*", "@noble/hashes": "^1.3.1", + "@radix-ui/react-checkbox": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", "@scure/bip32": "^1.3.1", "@scure/bip39": "^1.2.1", diff --git a/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx b/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx index 73d0c07afd599..2da561b16a4c3 100644 --- a/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx +++ b/apps/wallet/src/ui/app/components/accounts/ImportPrivateKeyForm.tsx @@ -6,9 +6,9 @@ import { useForm, type SubmitHandler } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import * as Yup from 'yup'; import { privateKeyValidation } from '../../helpers/validation/privateKeyValidation'; +import { Form } from '../../shared/forms/Form'; +import { TextAreaField } from '../../shared/forms/TextAreaField'; import { Button } from '_app/shared/ButtonUI'; -import Alert from '_src/ui/app/components/alert'; -import { Text } from '_src/ui/app/shared/text'; const formSchema = Yup.object({ privateKey: privateKeyValidation, @@ -21,33 +21,19 @@ type ImportPrivateKeyFormProps = { }; export function ImportPrivateKeyForm({ onSubmit }: ImportPrivateKeyFormProps) { - const { - register, - handleSubmit, - formState: { isSubmitting, isValid, touchedFields, errors }, - } = useForm({ + const form = useForm({ mode: 'onTouched', resolver: yupResolver(formSchema), }); + const { + register, + formState: { isSubmitting, isValid }, + } = form; const navigate = useNavigate(); return ( -
-