All files / src/contexts/ExternalLinkWarning ExternalLinkWarningModal.tsx

0% Statements 0/16
0% Branches 0/2
0% Functions 0/4
0% Lines 0/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121                                                                                                                                                                                                                                                 
import { ExternalLinkIcon } from "@chakra-ui/icons";
import {
  Button,
  Checkbox,
  Modal,
  ModalBody,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  Text,
  Tooltip,
} from "@chakra-ui/react";
import {
  ChangeEventHandler,
  FunctionComponent,
  MouseEventHandler,
  useState,
} from "react";
import {
  ExternalLinkPromptOptions,
  PREFERS_WARN_ON_EXTERNAL_LINK_CLICK,
} from "./constants";
import { ExternalLink } from "../../components/ExternalLink";
 
export interface ExternalLinkWarningModalProps
  extends ExternalLinkPromptOptions {
  isOpen: boolean;
  onClose: () => void;
  setShouldWarn: (shouldWarn: boolean) => void;
}
 
export const ExternalLinkWarningModal: FunctionComponent<
  ExternalLinkWarningModalProps
> = ({ href, isOpen, onClick, onClose, setShouldWarn }) => {
  // Track a final state for showing warnings that will only be updated if a user chooses to proceed
  const [finalShouldWarn, setFinalShouldWarn] = useState(true);
 
  // Update intermediate state when preference checkmark is updated
  const onPreferenceUpdated: ChangeEventHandler<HTMLInputElement> = (e) => {
    const shouldWarn = !e.target.checked;
    setFinalShouldWarn(shouldWarn);
  };
 
  const onCancel = () => {
    // If user cancelled the navigation, reset final warning state
    setFinalShouldWarn(true);
    onClose();
  };
 
  const onProceed: MouseEventHandler<HTMLAnchorElement> = (e) => {
    // If a user decided to not show warnings in the future, update localStorage & state to reflect their decision
    if (!finalShouldWarn) {
      setShouldWarn(finalShouldWarn);
 
      try {
        localStorage.setItem(
          PREFERS_WARN_ON_EXTERNAL_LINK_CLICK,
          JSON.stringify(finalShouldWarn)
        );
      } catch {}
    }
 
    onClick?.(e);
    onClose();
  };
 
  return (
    <Modal closeOnOverlayClick={false} isOpen={isOpen} onClose={onClose}>
      <ModalOverlay>
        <ModalContent color="textPrimary">
          <ModalHeader>Confirm</ModalHeader>
          <ModalBody>
            <Text fontSize="lg" mb={2}>
              This link is taking you to an external site
            </Text>
            <Text
              bg="bgPrimary"
              borderRadius="sm"
              color="blue.500"
              fontSize="sm"
              mb={4}
              p={1}
            >
              {href}
            </Text>
            <Checkbox onChange={onPreferenceUpdated}>
              Do not show this warning again.
            </Checkbox>
          </ModalBody>
          <ModalFooter>
            <Button onClick={onCancel} variant="ghost">
              Cancel
            </Button>
 
            <Tooltip hasArrow label={href} placement="top">
              <ExternalLink
                hasIcon={false}
                hasWarning={false}
                href={href}
                noFollow
                onClick={onProceed}
              >
                <Button
                  colorScheme="brand"
                  ml={4}
                  rightIcon={<ExternalLinkIcon />}
                  tabIndex={0}
                  variant="ghost"
                >
                  Proceed
                </Button>
              </ExternalLink>
            </Tooltip>
          </ModalFooter>
        </ModalContent>
      </ModalOverlay>
    </Modal>
  );
};