feat(11-02): auto-scroll to first errored field on validation failure
- BackendSelectionStep: add onInvalidSubmit scrolling to remote-name input - BackendSelectionStep: pass onInvalidSubmit to form onSubmit and handleCardClick - RemoteConfigStep: add FieldErrors import from react-hook-form - RemoteConfigStep: add onInvalidSubmit scrolling to first errored field by key - RemoteConfigStep: pass onInvalidSubmit to form onSubmit
This commit is contained in:
@@ -50,9 +50,14 @@ export function BackendSelectionStep() {
|
|||||||
dispatch({ type: 'SET_STEP', payload: 1 });
|
dispatch({ type: 'SET_STEP', payload: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onInvalidSubmit() {
|
||||||
|
// Only one validatable field in this step: remote-name
|
||||||
|
document.getElementById('remote-name')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
|
||||||
function handleCardClick(backendType: BackendType) {
|
function handleCardClick(backendType: BackendType) {
|
||||||
pendingBackend.current = backendType;
|
pendingBackend.current = backendType;
|
||||||
void handleSubmit(onValidSubmit)();
|
void handleSubmit(onValidSubmit, onInvalidSubmit)();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -62,7 +67,7 @@ export function BackendSelectionStep() {
|
|||||||
Name your remote and pick the cloud storage provider you want to connect to.
|
Name your remote and pick the cloud storage provider you want to connect to.
|
||||||
Your choice determines which credentials are required in the next step.
|
Your choice determines which credentials are required in the next step.
|
||||||
</p>
|
</p>
|
||||||
<form onSubmit={handleSubmit(onValidSubmit)}>
|
<form onSubmit={handleSubmit(onValidSubmit, onInvalidSubmit)}>
|
||||||
<TextFieldMD3
|
<TextFieldMD3
|
||||||
id="remote-name"
|
id="remote-name"
|
||||||
label="Remote name"
|
label="Remote name"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { BACKEND_SCHEMAS } from '../../schemas';
|
|||||||
import { FieldRenderer } from '../ui/FieldRenderer';
|
import { FieldRenderer } from '../ui/FieldRenderer';
|
||||||
import { AzureAuthToggle } from './AzureAuthToggle';
|
import { AzureAuthToggle } from './AzureAuthToggle';
|
||||||
import { SftpAuthToggle } from './SftpAuthToggle';
|
import { SftpAuthToggle } from './SftpAuthToggle';
|
||||||
import type { FieldError } from 'react-hook-form';
|
import type { FieldError, FieldErrors } from 'react-hook-form';
|
||||||
import { MD3_BTN_FILLED, MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
|
import { MD3_BTN_FILLED, MD3_BTN_OUTLINED } from '../../styles/md3-buttons';
|
||||||
|
|
||||||
export function RemoteConfigStep() {
|
export function RemoteConfigStep() {
|
||||||
@@ -43,6 +43,13 @@ export function RemoteConfigStep() {
|
|||||||
dispatch({ type: 'SET_STEP', payload: 2 });
|
dispatch({ type: 'SET_STEP', payload: 2 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function onInvalidSubmit(errors: FieldErrors) {
|
||||||
|
const firstKey = Object.keys(errors)[0];
|
||||||
|
if (firstKey) {
|
||||||
|
document.getElementById(firstKey)?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const backendLabel: Record<NonNullable<typeof backendType>, string> = {
|
const backendLabel: Record<NonNullable<typeof backendType>, string> = {
|
||||||
azureblob: 'Azure Blob Storage',
|
azureblob: 'Azure Blob Storage',
|
||||||
s3: 'Amazon S3',
|
s3: 'Amazon S3',
|
||||||
@@ -60,7 +67,7 @@ export function RemoteConfigStep() {
|
|||||||
Enter the credentials for your selected backend. These values are written directly into the
|
Enter the credentials for your selected backend. These values are written directly into the
|
||||||
generated rclone.conf and are never sent to any server.
|
generated rclone.conf and are never sent to any server.
|
||||||
</p>
|
</p>
|
||||||
<form onSubmit={handleSubmit(onNext)}>
|
<form onSubmit={handleSubmit(onNext, onInvalidSubmit)}>
|
||||||
{backendType === 'azureblob' ? (
|
{backendType === 'azureblob' ? (
|
||||||
<>
|
<>
|
||||||
{/* Account field via FieldRenderer */}
|
{/* Account field via FieldRenderer */}
|
||||||
|
|||||||
Reference in New Issue
Block a user