[ENG-809] Enter key submits dialog (#1279)

* enter key submit dialog

* code test

* input focus fix + dialog closes only if form is valid

* Update CreateDialog.tsx
This commit is contained in:
ameer2468
2023-08-31 16:22:24 +03:00
committed by GitHub
parent 9d99da9fc3
commit 8d16652c42
5 changed files with 83 additions and 59 deletions

View File

@@ -44,6 +44,7 @@ export default function FeedbackDialog(props: UseDialogProps) {
return (
<Dialog
invertButtonFocus
title="Feedback"
dialog={useDialog(props)}
form={form}

View File

@@ -2,7 +2,6 @@ import { useQueryClient } from '@tanstack/react-query';
import { Check, Trash, X } from 'phosphor-react';
import { useJobProgress, useLibraryMutation, useLibraryQuery } from '@sd/client';
import { Button, PopoverClose, Tooltip, toast } from '@sd/ui';
import { showAlertDialog } from '~/components/AlertDialog';
import IsRunningJob from './IsRunningJob';
import JobGroup from './JobGroup';
import { useState } from 'react';

View File

@@ -1,5 +1,6 @@
import { Pencil, Plus, Trash } from 'phosphor-react';
import { useNavigate } from 'react-router';
import { Link } from 'react-router-dom';
import { ContextMenu as CM, dialogManager } from '@sd/ui';
import CreateDialog from '~/app/$libraryId/settings/library/tags/CreateDialog';
import DeleteDialog from '~/app/$libraryId/settings/library/tags/DeleteDialog';
@@ -26,21 +27,22 @@ export default ({ children, tagId }: Props) => {
onClick={() => navigate(`settings/library/tags/${tagId}`)}
/>
<CM.Separator />
<CM.Item
onClick={() => {
navigate(`settings/library/tags/${tagId}`);
dialogManager.create((dp) => (
<DeleteDialog
{...dp}
tagId={tagId}
onSuccess={() => navigate(`settings/library/tags`)}
/>
));
}}
icon={Trash}
label="Delete"
variant="danger"
/>
<Link to={`settings/library/tags/${tagId}`}>
<CM.Item
onClick={() => {
dialogManager.create((dp) => (
<DeleteDialog
{...dp}
tagId={tagId}
onSuccess={() => navigate(`settings/library/tags`)}
/>
));
}}
icon={Trash}
label="Delete"
variant="danger"
/>
</Link>
</CM.Root>
);
};

View File

@@ -38,6 +38,7 @@ export default (props: UseDialogProps & { objects?: Object[] }) => {
return (
<Dialog
invertButtonFocus
form={form}
onSubmit={onSubmit}
dialog={useDialog(props)}

View File

@@ -124,6 +124,7 @@ export interface DialogProps<S extends FieldValues>
submitDisabled?: boolean;
transformOrigin?: string;
buttonsSideContent?: ReactNode;
invertButtonFocus?: boolean; //this reverses the focus order of submit/cancel buttons
}
export function Dialog<S extends FieldValues>({
@@ -131,6 +132,7 @@ export function Dialog<S extends FieldValues>({
dialog,
onSubmit,
onCancelled = true,
invertButtonFocus,
...props
}: DialogProps<S>) {
const stateSnap = useSnapshot(dialog.state);
@@ -148,6 +150,43 @@ export function Dialog<S extends FieldValues>({
const setOpen = (v: boolean) => (dialog.state.open = v);
const cancelButton = (
<RDialog.Close asChild>
<Button
size="sm"
variant="gray"
onClick={typeof onCancelled === 'function' ? onCancelled : undefined}
>
Cancel
</Button>
</RDialog.Close>
);
const closeButton = (
<RDialog.Close asChild>
<Button
disabled={props.loading}
size="sm"
variant="gray"
onClick={typeof onCancelled === 'function' ? onCancelled : undefined}
>
{props.closeLabel || 'Close'}
</Button>
</RDialog.Close>
);
const submitButton = (
<Button
type="submit"
size="sm"
disabled={form.formState.isSubmitting || props.submitDisabled}
variant={props.ctaDanger ? 'colored' : 'accent'}
className={clsx(props.ctaDanger && 'border-red-500 bg-red-500')}
>
{props.ctaLabel}
</Button>
);
return (
<RDialog.Root open={stateSnap.open} onOpenChange={setOpen}>
{props.trigger && <RDialog.Trigger asChild>{props.trigger}</RDialog.Trigger>}
@@ -171,7 +210,9 @@ export function Dialog<S extends FieldValues>({
e?.preventDefault();
await onSubmit?.(e);
dialog.onSubmit?.();
setOpen(false);
if (form.formState.isValid) {
setOpen(false);
}
}}
className="!pointer-events-auto my-8 min-w-[300px] max-w-[400px] rounded-md border border-app-line bg-app-box text-ink shadow-app-shade"
>
@@ -188,56 +229,36 @@ export function Dialog<S extends FieldValues>({
{props.children}
</div>
<div className="flex flex-row justify-end space-x-2 border-t border-app-line bg-app-selected p-3">
<div
className={clsx(
'flex justify-end space-x-2 border-t border-app-line bg-app-selected p-3'
)}
>
{form.formState.isSubmitting && <Loader />}
{props.buttonsSideContent && (
<div>{props.buttonsSideContent}</div>
)}
<div className="grow" />
{onCancelled && (
<RDialog.Close asChild>
<Button
disabled={props.loading}
size="sm"
variant="gray"
onClick={
typeof onCancelled === 'function'
? onCancelled
: undefined
}
>
{props.closeLabel || 'Close'}
</Button>
</RDialog.Close>
)}
{props.cancelBtn && (
<RDialog.Close asChild>
<Button
size="sm"
variant="gray"
onClick={
typeof onCancelled === 'function'
? onCancelled
: undefined
}
>
Cancel
</Button>
</RDialog.Close>
)}
<Button
type="submit"
size="sm"
disabled={
form.formState.isSubmitting || props.submitDisabled
}
variant={props.ctaDanger ? 'colored' : 'accent'}
<div
className={clsx(
props.ctaDanger && 'border-red-500 bg-red-500'
invertButtonFocus ? 'flex-row-reverse' : ' flex-row',
'flex gap-2'
)}
>
{props.ctaLabel}
</Button>
{invertButtonFocus ? (
<>
{submitButton}
{props.cancelBtn && cancelButton}
{onCancelled && closeButton}
</>
) : (
<>
{onCancelled && closeButton}
{props.cancelBtn && cancelButton}
{submitButton}
</>
)}
</div>
</div>
</Form>
<Remover id={dialog.id} />