Skip to content

Confirmation modal dialog

Delete project confirmation

tsx
import React from 'react';
import Button from '@semcore/button';
import { Flex } from '@semcore/flex-box';
import Modal from '@semcore/modal';
import { Text, List } from '@semcore/typography';
import Input from '@semcore/input';
import Tooltip from '@semcore/tooltip';
import '@semcore/utils/lib/themes/default.css';
import { useForm, SubmitHandler } from 'react-hook-form';

const warningBlockStyles = {
  background: 'var(--intergalactic-bg-secondary-critical)',
  border: '1px solid var(--intergalactic-border-critical)',
  borderRadius: 'var(--intergalactic-surface-rounded)',
  marginBottom: '24px',
  padding: '16px',
};

type FormValues = {
  project: string;
};

const fieldName: keyof FormValues = 'project';

const Demo = () => {
  const { register, trigger, handleSubmit, reset, resetField, getValues, formState } =
    useForm<FormValues>({
      mode: 'onBlur',
      defaultValues: { project: '' },
    });

  const [visible, setVisible] = React.useState(false);
  const handleOpen = React.useCallback(() => setVisible(true), []);
  const handleClose = React.useCallback(() => {
    setVisible(false);
    reset({ project: '' }, { keepIsSubmitted: false, keepTouched: false });
  }, []);

  const { errors, isSubmitted } = formState;
  const [focusedFieldName, setFocusedFieldName] = React.useState('');
  const onSubmit: SubmitHandler<FormValues> = handleClose;

  const hasError = () => {
    const error = errors[fieldName];

    if (error && error.type === 'projectRequired' && !isSubmitted) {
      return false;
    }

    return Boolean(error);
  };

  const showErrorTooltip = (): boolean => {
    const isActive = focusedFieldName === fieldName;
    return hasError() && isActive;
  };

  const { onChange, ...restField } = register(fieldName, {
    validate: {
      projectRequired: (v) => {
        return Boolean(v) || 'Please enter the correct project name';
      },
      projectName: (v) => {
        if (!v) {
          return true;
        }

        return /^test$/i.test(v) || 'Please enter the correct project name';
      },
    },
    onBlur: () => setFocusedFieldName(''),
  });

  const field = {
    onChange: (_v: string, e: React.SyntheticEvent) => {
      // important: keep call order, otherwise validation breaks
      onChange(e);
      hasError() && trigger();
    },
    ...restField,
  };

  return (
    <>
      <Button onClick={handleOpen}>Open confirmation modal</Button>
      <Modal visible={visible} onClose={handleClose} w={536}>
        <Modal.Title mb={4}>Delete project?</Modal.Title>
        <Text size={300} mb={4} tag='p'>
          This will <Text tag='strong'>delete</Text> the following campaigns set up for{' '}
          <Text tag='strong'>test.com</Text> with all their data:
        </Text>
        <List size={300} mb={4}>
          <List.Item>Position Tracking</List.Item>
          <List.Item>Social Media Poster</List.Item>
          <List.Item>Backlink Audit</List.Item>
          <List.Item>Content Analyzer</List.Item>
        </List>

        <form noValidate onSubmit={handleSubmit(onSubmit)}>
          <Flex style={warningBlockStyles} direction='column'>
            <Text size={300} mb={2} tag='label' htmlFor={fieldName}>
              Confirm deletion by typing the project name{' '}
              <Text tag='strong' color='red-500'>
                Test
              </Text>
            </Text>

            <Tooltip
              placement='right'
              interaction={'none'}
              theme='warning'
              animationsDisabled={true}
            >
              <Tooltip.Popper visible={showErrorTooltip()} id='form-project-error'>
                {errors[fieldName]?.message}
              </Tooltip.Popper>

              <Input state={hasError() ? 'invalid' : 'normal'} controlsLength={1} mb={2} size='l'>
                <Tooltip.Trigger
                  tag={Input.Value}
                  {...field}
                  id={fieldName}
                  placeholder={'Enter project name'}
                  w={'100%'}
                  onFocus={() => setFocusedFieldName(fieldName)}
                  aria-invalid={hasError()}
                  aria-describedby={showErrorTooltip() ? 'form-project-error' : undefined}
                />
              </Input>
            </Tooltip>
          </Flex>

          <Flex direction={'row'}>
            <Button use='primary' theme='danger' size='l' type='submit'>
              Delete
            </Button>

            <Button size='l' ml={2} onClick={handleClose} type='button'>
              Cancel
            </Button>
          </Flex>
        </form>
      </Modal>
    </>
  );
};

export default Demo;

Last updated:

Released under the MIT License.

Released under the MIT License.