huridocs/uwazi

View on GitHub
app/react/V2/Components/UI/Sidepanel.tsx

Summary

Maintainability
A
0 mins
Test Coverage
D
66%
/* eslint-disable react/no-multi-comp */
import React from 'react';
import { Transition } from '@headlessui/react';
import { useParams } from 'react-router-dom';
import { XMarkIcon } from '@heroicons/react/20/solid';
import { availableLanguages } from 'shared/languagesList';
import { Translate } from 'app/I18N';

interface SidePanelProps {
  children: JSX.Element | React.ReactNode;
  closeSidepanelFunction: () => any;
  isOpen?: boolean;
  title?: string | React.ReactNode;
  withOverlay?: boolean;
  size?: 'small' | 'medium' | 'large';
}

const sidepanelHeader = (closeSidepanelFunction: () => any, title?: React.ReactNode) => (
  <div className="flex p-4 mb-2 text-gray-500">
    <h1 className="text-base font-bold grow">{title}</h1>
    <button
      type="button"
      className="justify-end"
      data-testid="close-sidepanel"
      onClick={closeSidepanelFunction}
    >
      <span className="sr-only">
        <Translate>Close</Translate>
      </span>
      <XMarkIcon className="w-6" />
    </button>
  </div>
);

// eslint-disable-next-line max-statements
const Sidepanel = ({
  children,
  closeSidepanelFunction,
  isOpen = false,
  title,
  withOverlay,
  size = 'medium',
}: SidePanelProps) => {
  const { lang: languageKey } = useParams();

  let transitionRight = '-translate-x-[500px]';
  let transitionLeft = '-translate-x-[-500px]';
  let width = 'md:w-[500px]';

  switch (size) {
    case 'small':
      transitionRight = '-translate-x-[300px]';
      transitionLeft = '-translate-x-[-300px]';
      width = 'md:w-[300px]';
      break;

    case 'large':
      transitionRight = 'md:-translate-x-[768px] lg:-translate-x-1/2';
      transitionLeft = 'md:-translate-x-[-768px] lg:-translate-x-[-50%]';
      width = 'md:w-[768px] lg:w-1/2';
      break;

    default:
      break;
  }

  const isRigthToLeft = availableLanguages.find(language => language.key === languageKey)?.rtl;
  const transition = isRigthToLeft ? transitionRight : transitionLeft;
  const contentClasses = 'flex flex-col h-full overflow-y-auto';

  if (withOverlay) {
    return (
      <Transition show={isOpen} className="fixed top-0 left-0 z-10 flex w-full h-full max-h-full">
        <Transition.Child
          className="w-full transition-opacity duration-200 ease-in bg-gray-900 md:flex-grow"
          enterFrom="opacity-0"
          enterTo="opacity-50"
          leaveTo="opacity-0"
          onClick={closeSidepanelFunction}
        />
        <Transition.Child
          as="aside"
          className={`w-full h-full top-0 right-0 fixed bg-white border-l-2 transition duration-200 ease-in transform ${width}`}
          enterFrom={transition}
          enterTo="translate-x-0"
          leaveTo={transition}
        >
          <div className={contentClasses}>
            {sidepanelHeader(closeSidepanelFunction, title)}
            {children}
          </div>
        </Transition.Child>
      </Transition>
    );
  }

  return (
    <Transition
      show={isOpen}
      as="aside"
      className={`fixed top-0 right-0 z-10 w-full h-full bg-white border-l-2 shadow-lg transition duration-200 ease-in transform ${width}`}
      enterFrom={transition}
      enterTo="translate-x-0"
      leaveTo={transition}
    >
      <div className={contentClasses}>
        {sidepanelHeader(closeSidepanelFunction, title)}
        {children}
      </div>
    </Transition>
  );
};

Sidepanel.Body = ({
  children,
  className = '',
}: {
  children: React.ReactNode;
  className?: String;
}) => <div className={`flex-grow p-4 ${className}`}>{children}</div>;

Sidepanel.Footer = ({
  children,
  className = '',
}: {
  children: React.ReactNode;
  className?: String;
}) => <div className={`bottom-0 left-0 w-full bg-white z-1 ${className}`}>{children}</div>;

export type { SidePanelProps };
export { Sidepanel };