mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-02-23 01:46:41 -05:00
[ENG-1070] Dialog form button submit disabled if form is not valid (#1292)
* Feedback dialog cleanup, disable submit button of dialog if form not valid * ts * Update FeedbackDialog.tsx
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import clsx from 'clsx';
|
||||
import { useState } from 'react';
|
||||
import { useZodForm } from '@sd/client';
|
||||
import { Dialog, TextArea, UseDialogProps, toast, useDialog, z } from '@sd/ui';
|
||||
import { Dialog, TextAreaField, UseDialogProps, toast, useDialog, z } from '@sd/ui';
|
||||
|
||||
const schema = z.object({
|
||||
feedback: z.string().min(1),
|
||||
feedback: z.string().min(1, { message: 'Feedback is required' }),
|
||||
emoji: z.string().emoji().max(2).optional()
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@ const EMOJIS = ['🤩', '😀', '🙁', '😭'];
|
||||
const FEEDBACK_URL = 'https://spacedrive.com/api/feedback';
|
||||
|
||||
export default function FeedbackDialog(props: UseDialogProps) {
|
||||
const form = useZodForm({ schema });
|
||||
const form = useZodForm({ schema, mode: 'onBlur' });
|
||||
const [emojiSelected, setEmojiSelected] = useState<string | undefined>(undefined);
|
||||
|
||||
const emojiSelectHandler = (index: number) => {
|
||||
@@ -36,8 +36,6 @@ export default function FeedbackDialog(props: UseDialogProps) {
|
||||
}
|
||||
});
|
||||
|
||||
const watchForm = form.watch();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
invertButtonFocus
|
||||
@@ -45,11 +43,10 @@ export default function FeedbackDialog(props: UseDialogProps) {
|
||||
dialog={useDialog(props)}
|
||||
form={form}
|
||||
onSubmit={formSubmit}
|
||||
submitDisabled={form.formState.isSubmitting || !watchForm.feedback}
|
||||
ctaLabel="Submit"
|
||||
closeLabel="Cancel"
|
||||
buttonsSideContent={
|
||||
<div className="flex w-full items-center justify-center gap-1">
|
||||
<div className="flex items-center justify-center w-full gap-1">
|
||||
{EMOJIS.map((emoji, i) => (
|
||||
<div
|
||||
onClick={() => emojiSelectHandler(i)}
|
||||
@@ -65,10 +62,10 @@ export default function FeedbackDialog(props: UseDialogProps) {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<TextArea
|
||||
<TextAreaField
|
||||
{...form.register('feedback')}
|
||||
placeholder="Your feedback..."
|
||||
className="w-full"
|
||||
{...form.register('feedback')}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -75,7 +75,10 @@ export const AddLocationDialog = ({
|
||||
[listIndexerRules.data]
|
||||
);
|
||||
|
||||
const form = useZodForm({ schema, defaultValues: { path, method, indexerRulesIds } });
|
||||
const form = useZodForm({
|
||||
schema,
|
||||
defaultValues: { path, method, indexerRulesIds }
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Update form values when default value changes and the user hasn't made any changes
|
||||
@@ -213,7 +216,7 @@ export const AddLocationDialog = ({
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<ErrorMessage name={REMOTE_ERROR_FORM_FIELD} variant="large" className="mb-4 mt-2" />
|
||||
<ErrorMessage name={REMOTE_ERROR_FORM_FIELD} variant="large" className="mt-2 mb-4" />
|
||||
|
||||
<InputField
|
||||
size="md"
|
||||
|
||||
@@ -12,7 +12,8 @@ export default (props: UseDialogProps & { objects?: Object[] }) => {
|
||||
|
||||
const form = useZodForm({
|
||||
schema: schema,
|
||||
defaultValues: { color: '#A717D9' }
|
||||
defaultValues: { color: '#A717D9' },
|
||||
mode: 'onBlur'
|
||||
});
|
||||
|
||||
const createTag = useLibraryMutation('tags.create');
|
||||
|
||||
@@ -179,7 +179,9 @@ export function Dialog<S extends FieldValues>({
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
disabled={form.formState.isSubmitting || props.submitDisabled}
|
||||
disabled={
|
||||
form.formState.isSubmitting || props.submitDisabled || !form.formState.isValid
|
||||
}
|
||||
variant={props.ctaDanger ? 'colored' : 'accent'}
|
||||
className={clsx(props.ctaDanger && 'border-red-500 bg-red-500')}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { VariantProps, cva } from 'class-variance-authority';
|
||||
import clsx from 'clsx';
|
||||
import { Eye, EyeSlash, Icon, IconProps, MagnifyingGlass } from 'phosphor-react';
|
||||
import { PropsWithChildren, createElement, forwardRef, isValidElement, useState } from 'react';
|
||||
import { createElement, forwardRef, isValidElement, useState } from 'react';
|
||||
import { Button } from './Button';
|
||||
|
||||
export interface InputBaseProps extends VariantProps<typeof inputStyles> {
|
||||
|
||||
18
packages/ui/src/forms/TextAreaField.tsx
Normal file
18
packages/ui/src/forms/TextAreaField.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { forwardRef } from 'react';
|
||||
import * as Root from '../Input';
|
||||
import { useFormField } from './FormField';
|
||||
import { FormField, UseFormFieldProps } from './FormField';
|
||||
|
||||
export interface TextAreaFieldProps extends UseFormFieldProps, Root.TextareaProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const TextAreaField = forwardRef<HTMLTextAreaElement, TextAreaFieldProps>((props, ref) => {
|
||||
const { formFieldProps, childProps } = useFormField(props);
|
||||
|
||||
return (
|
||||
<FormField {...formFieldProps}>
|
||||
<Root.TextArea {...childProps} ref={ref} error={formFieldProps.error !== undefined} />
|
||||
</FormField>
|
||||
);
|
||||
});
|
||||
@@ -4,4 +4,5 @@ export * from './CheckBoxField';
|
||||
export * from './InputField';
|
||||
export * from './SwitchField';
|
||||
export * from './SelectField';
|
||||
export * from './TextAreaField';
|
||||
export * as RadioGroupField from './RadioGroupField';
|
||||
|
||||
Reference in New Issue
Block a user