@headlessui/react#Transition TypeScript Examples

The following examples show how to use @headlessui/react#Transition. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From interbtc-ui with Apache License 2.0 6 votes vote down vote up
CloseButton = React.forwardRef<Ref, InterlayButtonBaseProps>(
  ({ onClick }, ref): JSX.Element => {
    return (
      <Transition.Child
        as={React.Fragment}
        enter={clsx('ease-in-out', 'duration-300')}
        enterFrom='opacity-0'
        enterTo='opacity-100'
        leave={clsx('ease-in-out', 'duration-300')}
        leaveFrom='opacity-100'
        leaveTo='opacity-0'
      >
        <div className={clsx('absolute', 'top-0', 'right-0', '-mr-12', 'pt-2')}>
          <InterlayButtonBase
            ref={ref}
            className={clsx(
              'ml-1',
              'justify-center',
              'h-10',
              'w-10',
              'rounded-full',
              'focus:outline-none',
              'focus:ring-2',
              'focus:ring-inset',
              'focus:ring-white'
            )}
            onClick={onClick}
          >
            <span className='sr-only'>Close sidebar</span>
            <XIcon className={clsx('h-6', 'w-6', 'text-white')} aria-hidden='true' />
          </InterlayButtonBase>
        </div>
      </Transition.Child>
    );
  }
)
Example #2
Source File: ContentSwitch.tsx    From yet-another-generic-startpage with MIT License 6 votes vote down vote up
SwitchTransition = styled(Transition)`
  position: absolute;
  width: 100%;

  &.transition {
    transition: transform 0.7s ease-in-out;
  }
  &.display {
    transform: translateX(0);
  }
  &.hideLeft {
    transform: translateX(-150vw);
  }
  &.hideRight {
    transform: translateX(150vw);
  }
`
Example #3
Source File: stake-actions.tsx    From arkadiko with GNU General Public License v3.0 6 votes vote down vote up
StakeActions: React.FC<StakeActionsProps> = ({ children }) => {
  return (
    <Menu as="div" className="relative flex items-center justify-end">
      {({ open }) => (
        <>
          <Menu.Button className="inline-flex items-center justify-center w-8 h-8 text-gray-400 bg-white rounded-full hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
            <span className="sr-only">Open options</span>
            <StyledIcon as="DotsVerticalIcon" size={5} />
          </Menu.Button>
          <Transition
            show={open}
            as={Fragment}
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="transform opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="transform opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <Menu.Items
              static
              className="absolute top-0 z-10 w-48 mx-3 mt-1 origin-top-right bg-white divide-y divide-gray-200 rounded-md shadow-lg dark:bg-zinc-800 dark:divide-zinc-600 right-7 ring-1 ring-black ring-opacity-5 focus:outline-none"
            >
              <div className="px-1 py-1">{children}</div>
            </Menu.Items>
          </Transition>
        </>
      )}
    </Menu>
  );
}
Example #4
Source File: Modal.tsx    From pali-wallet with MIT License 5 votes vote down vote up
Modal = ({
  children,
  className = '',
  onClose,
  show = true,
}: IModal) => (
  <Transition appear show={show} as={Fragment}>
    <Dialog
      as="div"
      className={`fixed z-10 inset-0 overflow-y-auto ${className}`}
      onClose={onClose ?? (() => {})}
    >
      <div
        onClick={() => console.log('inside onClick')}
        className="fixed z-0 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out"
      />

      <div className="px-4 min-h-screen text-center">
        <Transition.Child
          as={Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-in duration-200"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <Dialog.Overlay className="fixed inset-0" />
        </Transition.Child>

        <span className="inline-block align-middle h-screen" aria-hidden="true">
          &#8203;
        </span>

        <Transition.Child
          as={Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0 scale-95"
          enterTo="opacity-100 scale-100"
          leave="ease-in duration-200"
          leaveFrom="opacity-100 scale-100"
          leaveTo="opacity-0 scale-95"
        >
          {children}
        </Transition.Child>
      </div>
    </Dialog>
  </Transition>
)
Example #5
Source File: index.tsx    From interbtc-ui with Apache License 2.0 5 votes vote down vote up
Sidebar = ({ className, children }: Props): JSX.Element => {
  const [sidebarOpen, setSidebarOpen] = React.useState(false);

  const handleClose = () => {
    setSidebarOpen(false);
  };
  const handleOpen = () => {
    setSidebarOpen(true);
  };

  return (
    <div className={clsx('h-screen', 'flex', 'overflow-hidden', className)}>
      <Transition.Root show={sidebarOpen} as={React.Fragment}>
        <Dialog
          as='div'
          static
          className={clsx('fixed', 'inset-0', 'flex', 'z-40', ON_SMALL_SCREEN_CLASS_NAME)}
          open={sidebarOpen}
          onClose={setSidebarOpen}
        >
          <Transition.Child
            as={React.Fragment}
            enter={clsx('transition-opacity', 'ease-linear', 'duration-300')}
            enterFrom='opacity-0'
            enterTo='opacity-100'
            leave={clsx('transition-opacity', 'ease-linear', 'duration-300')}
            leaveFrom='opacity-100'
            leaveTo='opacity-0'
          >
            <Dialog.Overlay className={clsx('fixed', 'inset-0', 'bg-interlayHaiti-400', 'bg-opacity-75')} />
          </Transition.Child>
          <Transition.Child
            as={React.Fragment}
            enter={clsx('transition', 'ease-in-out', 'duration-300', 'transform')}
            enterFrom='-translate-x-full'
            enterTo='translate-x-0'
            leave={clsx('transition', 'ease-in-out', 'duration-300', 'transform')}
            leaveFrom='translate-x-0'
            leaveTo='-translate-x-full'
          >
            <SidebarContent onSmallScreen onClose={handleClose} />
          </Transition.Child>
          <div className={clsx('flex-shrink-0', 'w-14')} />
        </Dialog>
      </Transition.Root>
      <div className={clsx('hidden', 'md:flex', 'md:flex-shrink-0')}>
        <div className={clsx('flex', 'flex-col', 'w-64')}>
          <SidebarContent onClose={handleClose} />
        </div>
      </div>
      <div className={clsx('flex', 'flex-col', 'w-0', 'flex-1', 'overflow-hidden')}>
        <div className={clsx(ON_SMALL_SCREEN_CLASS_NAME, 'pl-1', 'pt-1', 'sm:pl-3', 'sm:pt-3')}>
          <OpenButton onClick={handleOpen} />
        </div>
        <main className={clsx('flex-1', 'relative', 'z-0', 'overflow-y-auto', 'focus:outline-none')}>{children}</main>
      </div>
    </div>
  );
}
Example #6
Source File: VariantSelectButton.tsx    From Meshtastic with GNU General Public License v3.0 5 votes vote down vote up
VariantSelectButton = ({
  options,
}: VariantSelectButtonProps): JSX.Element => {
  const [selected, setSelected] = useState(options[options.length - 1]);

  return (
    <Listbox value={selected} onChange={setSelected}>
      {({ open }) => (
        <>
          <div className="relative select-none">
            <Listbox.Button as={Fragment}>
              <motion.button
                whileHover={{ backgroundColor: 'var(--tertiary)' }}
                whileTap={{ scale: 0.99 }}
                className="relative -mt-5 ml-2 flex w-fit gap-1 rounded-lg bg-secondary p-2 py-2 pl-3 pr-10 text-lg font-medium leading-6 shadow-md md:mt-2"
              >
                <span className="block truncate">{selected.name}</span>
                <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
                  <HiSelector
                    className="h-5 w-5 text-gray-400"
                    aria-hidden="true"
                  />
                </span>
              </motion.button>
            </Listbox.Button>

            <Transition
              show={open}
              as={Fragment}
              leave="transition ease-in duration-100"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <Listbox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-primary py-1 shadow-md ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                {options.map((variant, index) => (
                  <Listbox.Option
                    key={index}
                    className={({ active }) =>
                      `relative cursor-default select-none py-2 pl-3 pr-9 ${
                        active ? 'bg-secondary' : ''
                      }`
                    }
                    value={variant}
                  >
                    {({ selected, active }) => (
                      <>
                        <span
                          className={`block truncate ${
                            selected ? 'font-semibold' : 'font-normal'
                          }`}
                        >
                          {variant.name}
                        </span>

                        {selected ? (
                          <span
                            className={`absolute inset-y-0 right-0 flex items-center pr-4 ${
                              active ? '' : 'text-primaryInv'
                            }`}
                          >
                            <FiCheck className="h-5 w-5" aria-hidden="true" />
                          </span>
                        ) : null}
                      </>
                    )}
                  </Listbox.Option>
                ))}
              </Listbox.Options>
            </Transition>
          </div>
        </>
      )}
    </Listbox>
  );
}
Example #7
Source File: ModalBase.tsx    From contracts-ui with GNU General Public License v3.0 5 votes vote down vote up
ModalBase = ({ isOpen, setIsOpen, title, children }: ModalProps) => {
  function closeModal() {
    setIsOpen(false);
  }
  return (
    <>
      <Transition appear show={isOpen} as={Fragment}>
        <Dialog as="div" className="fixed inset-0 z-99 overflow-y-auto " onClose={closeModal}>
          <div className="min-h-screen px-4 text-center">
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0"
              enterTo="opacity-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <Dialog.Overlay className="fixed inset-0 bg-black dark:opacity-70 opacity-10" />
            </Transition.Child>

            {/* This element is to trick the browser into centering the modal contents. */}
            <span className="inline-block h-screen align-middle" aria-hidden="true">
              &#8203;
            </span>
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0 scale-95"
              enterTo="opacity-100 scale-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100 scale-100"
              leaveTo="opacity-0 scale-95"
            >
              <div className="inline-block w-full max-w-lg  my-8 overflow-hidden text-left align-middle transition-all transform opacity-100 dark:bg-gray-900 bg-white shadow-xl rounded-xl">
                <div className="flex justify-between border-b dark:border-gray-800 border-gray-200">
                  <Dialog.Title
                    as="h3"
                    className="text-lg font-bold leading-6 p-6 dark:text-gray-300 text-gray-600"
                  >
                    {title}
                  </Dialog.Title>
                  <XIcon
                    className="w-4 h-4 mx-6 mt-7 text-gray-500 cursor-pointer"
                    aria-hidden="true"
                    onClick={closeModal}
                  />
                </div>
                <div className="px-6">{children}</div>
              </div>
            </Transition.Child>
          </div>
        </Dialog>
      </Transition>
    </>
  );
}
Example #8
Source File: Nav.tsx    From supabase-ui-web with Apache License 2.0 5 votes vote down vote up
function Nav({ contents, show, setShow }: any) {
  return (
    <>
      <Transition
        show={show}
        enter="transition-opacity duration-75"
        enterFrom="opacity-0"
        enterTo="opacity-100"
        leave="transition-opacity duration-150"
        leaveFrom="opacity-100"
        leaveTo="opacity-0"
      >
        <div
          onClick={setShow}
          className="z-30 fixed inset-0 bg-gray-600 bg-opacity-75"
          aria-hidden="true"
        ></div>
      </Transition>
      <Transition
        show={show}
        enter="transform transition ease-in-out duration-500 sm:duration-700"
        enterFrom="-translate-x-full"
        enterTo="translate-x-0"
        leave="transform transition ease-in-out duration-500 sm:duration-700"
        leaveFrom="translate-x-0"
        leaveTo="-translate-x-full"
      >
        <div className="fixed inset-0 flex z-40 md:hidden" role="dialog" aria-modal="true">
          {/* // capture close clicks */}
          <div className="absolute h-full w-full" onClick={setShow}></div>
          {/* content of mobile menu */}
          <div className="relative flex-1 flex flex-col max-w-xs w-full bg-white dark:bg-gray-800">
            {contents}
          </div>

          <div className="flex-shrink-0 w-14">
            {/* <!-- Force sidebar to shrink to fit close icon --> */}
          </div>
        </div>
      </Transition>
    </>
  )
}
Example #9
Source File: Accordion.tsx    From ui with MIT License 5 votes vote down vote up
export function Item({ children, className, label, id }: ItemProps) {
  const { defaultActiveId, icon, iconPosition, onChange } =
    useContext(AccordionContext)

  let panelClasses = [AccordionStyles['sbui-accordion-item__panel']]

  let buttonClasses = [AccordionStyles['sbui-accordion-item__button']]
  if (className) {
    buttonClasses.push(className)
  }

  const isDefaultActive = id ? defaultActiveId?.includes(id) : false

  const handleOnChange = useCallback(
    (open: boolean) => () => {
      if (onChange) {
        onChange({ id, label, open })
      }
    },
    [onChange, id, label]
  )

  return (
    <Disclosure defaultOpen={isDefaultActive}>
      {({ open }) => (
        <>
          <Disclosure.Button
            className={
              open
                ? `${buttonClasses.join(' ')} sbui-accordion-item__button--open`
                : buttonClasses.join(' ')
            }
          >
            {iconPosition === 'left' && icon}
            <Typography.Text>{label}</Typography.Text>
            {iconPosition === 'right' && icon}
          </Disclosure.Button>
          <Transition
            show={open}
            enter={AccordionStyles[`sbui-accordion-item__panel--enter`]}
            enterFrom={AccordionStyles[`sbui-accordion-item__panel--enterFrom`]}
            enterTo={AccordionStyles[`sbui-accordion-item__panel--enterTo`]}
            leave={AccordionStyles[`sbui-accordion-item__panel--leave`]}
            leaveFrom={AccordionStyles[`sbui-accordion-item__panel--leaveFrom`]}
            leaveTo={AccordionStyles[`sbui-accordion-item__panel--leaveTo`]}
            afterEnter={handleOnChange(open)}
            afterLeave={handleOnChange(open)}
          >
            <Disclosure.Panel className={panelClasses.join(' ')} static>
              {children}
            </Disclosure.Panel>
          </Transition>
        </>
      )}
    </Disclosure>
  )
}
Example #10
Source File: DropdownMenu.tsx    From sdk with ISC License 5 votes vote down vote up
export default function DropdownMenu({title, selectedItem, setSelectedItem, items}: DropdownMenuProps) {
    return(
        <div className={"flex items-center justify-center"}>
            <div className={"w-60 max-w-xs"}>
                <Listbox value={selectedItem} onChange={setSelectedItem} as={"div"} className={"space-y-1"}>
                    {({open}) => (
                        <>
                            <Listbox.Label className={"block text-sm font-medium"}>{title}</Listbox.Label>
                            <div className={"relative"}>
                                <span className={"inline-block w-full rounded-md"}>
                                    <Listbox.Button
                                        className={classNames(
                                            "cursor-default relative w-full",
                                            "py-2 pl-3 pr-10 text-center",
                                            "rounded-md shadow-md",
                                            "sm:text-sm",
                                            "focus:outline-none focus-visible:ring-2",
                                            "focus-visible:ring-opacity-75 focus-visible:ring-white",
                                            "focus-visible:ring-offset-2 focus-visible:border-indigo-500"
                                        )}
                                    >
                                        <span className={"block truncate text-lg"}>{selectedItem?.label || ""}</span>
                                        <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                                            <SelectorIcon className="w-5 h-5 text-gray-400" aria-hidden="true"/>
                                        </span>
                                    </Listbox.Button>
                                </span>
                                <Transition
                                    // as={Fragment}
                                    show={open}
                                    unmount={false}
                                    enter="transition duration-100 ease-in"
                                    enterFrom="transform opacity-0"
                                    enterTo="transform opacity-100"
                                    leave="transition duration-75 ease-out"
                                    leaveFrom="transform opacity-100"
                                    leaveTo="transform opacity-0"
                                    className={"absolute mt-1 w-full rounded-md dark:bg-gray-600"}
                                >
                                    <Listbox.Options static className={"z-10 overflow-auto max-h-60 sm:text-sm"}>
                                        {items.map((item) => {
                                            const selected = item.key === selectedItem.key;
                                            return(<Listbox.Option
                                                    key={item.key}
                                                    value={item}
                                                    disabled={item.disabled || selected}
                                                >
                                                    {({ active }) => (
                                                        <div className={classNames(
                                                            "cursor-default select-none relative",
                                                            active ? "bg-blue-500" : ""
                                                        )}>
                                                            <span
                                                                className={classNames(
                                                                    selected ? "font-semibold" : "font-normal",
                                                                    "block truncate"
                                                                )}
                                                            >
                                                                {item.label}
                                                            </span>
                                                        </div>
                                                    )}
                                                </Listbox.Option>
                                            )})}
                                    </Listbox.Options>
                                </Transition>
                            </div>
                        </>
                    )}
                </Listbox>
            </div>
        </div>
    )
}
Example #11
Source File: ProfileDropDown.tsx    From platform with MIT License 5 votes vote down vote up
export default function ProfileDropDown(props) {
  const { signOut, avatarUrl } = props;
  return (
    <Menu as="div" className="relative inline-block text-left">
      {({ open }) => (
        <>
          <div>
            <Menu.Button className="inline-flex justify-center w-full rounded-lg border-2 border-teal-500 shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-teal-500">
              {avatarUrl ? (
                <img
                  className="rounded-md h-8 w-8"
                  src={avatarUrl}
                  alt="Avatar"
                />
              ) : (
                <span className="inline-block relative h-8 w-8 rounded-lg">
                  <svg
                    className="h-full w-full text-gray-300 rounded-lg"
                    fill="currentColor"
                    viewBox="0 0 24 24"
                  >
                    <path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
                  </svg>
                </span>
              )}
            </Menu.Button>
          </div>

          <Transition
            show={open}
            as={Fragment}
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="transform opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="transform opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <Menu.Items
              static
              className="origin-top-right absolute right-0 mt-2 w-32 sm:w-44 rounded-md shadow-lg bg-white border border-teal-500 ring-black ring-opacity-100 divide-y divide-gray-100 focus:outline-none"
            >
              <div className="py-1">
                <Menu.Item>
                  {({ active }) => (
                    <Link
                      to="/app/profile"
                      className={classNames(
                        active ? "bg-gray-100 text-gray-900" : "text-gray-700",
                        "block px-4 py-1 sm:py-2 text-xs sm:text-sm"
                      )}
                    >
                      Profile
                    </Link>
                  )}
                </Menu.Item>
              </div>
              <div className="py-1">
                <Menu.Item>
                  {({ active }) => (
                    <div
                      onClick={signOut}
                      className={classNames(
                        active ? "bg-gray-100 text-gray-900" : "text-gray-700",
                        "block px-4 py-1 sm:py-2 text-xs sm:text-sm cursor-pointer"
                      )}
                    >
                      Logout
                    </div>
                  )}
                </Menu.Item>
              </div>
            </Menu.Items>
          </Transition>
        </>
      )}
    </Menu>
  );
}
Example #12
Source File: Modal.tsx    From projectboard with MIT License 5 votes vote down vote up
function Modal({ title, isOpen, center, size, className, onDismiss, children, modalStyles }: Props) {
  const ref = useRef<HTMLDivElement>(null) as RefObject<HTMLDivElement>;
  const outerRef = useRef(null);

  const wrapperClasses = classnames(
    'fixed flex flex-col items-center inset-0 z-50',
    {
      'justify-center': center,
    }
  );
  const modalClasses = classnames(
    'flex flex-col items-center transform bg-white modal shadow-large-modal rounded-xl overflow-hidden',
    {
      'mt-20 mb-2 ': !center,
    },
    sizeClasses[size],
    className
  );
  const handleClick = useCallback((e) => {
    if (!onDismiss) return;
    const markdownDropdown = document.getElementById('block-menu-container');
    const insideMarkdown = markdownDropdown?.contains(e.target);
    if (ref.current && !ref.current.contains(e.target) && !insideMarkdown) {
      onDismiss();
    }
  }, [onDismiss]);

  useLockBodyScroll();

  let modal = (
    <div ref={outerRef}
      onClick={handleClick}
    >
      <Transition
        show={isOpen}
        enter="transition ease-out duration-100"
        enterFrom="transform opacity-0 scale-95"
        enterTo="transform opacity-100 scale-100"
        leave="transition easy-in duration-75"
        leaveFrom="transform opacity-100 scale-100"
        leaveTo="transform opacity-0 scale-95"
        className={wrapperClasses}
      >
        <div ref={ref}
          className={modalClasses}
          style={modalStyles}
        >
          {title && <div className='flex items-center justify-between w-full pl-8 pr-4 border-b border-gray-200'>
            <div className='text-sm font-semibold text-gray-700'>{title}</div>
            <div className='p-4'
              onClick={onDismiss}
            ><CloseIcon className='w-4 text-gray-500 hover:text-gray-700' /></div>
          </div>}
          {children}
        </div>
      </Transition>
    </div>
  );

  return ReactDOM.createPortal(
    modal,
    document.getElementById('root-modal') as Element
  );
}
Example #13
Source File: modal.tsx    From website with Apache License 2.0 5 votes vote down vote up
export function Modal({isOpen, ...props}: Props) {
	const close = () => {
		props.setIsOpen(false);
	};

	return (
		<Transition appear as={Fragment} show={isOpen}>
			<Dialog
				as="div"
				className="overflow-y-auto fixed inset-0 z-10"
				initialFocus={props.focusRef}
				onClose={close}
			>
				<div className="px-4 min-h-screen text-center">
					<Transition.Child
						as={Fragment}
						enter="ease-out duration-300"
						enterFrom="opacity-0"
						enterTo="opacity-100"
						leave="ease-in duration-200"
						leaveFrom="opacity-100"
						leaveTo="opacity-0"
					>
						<Dialog.Overlay className="fixed inset-0 bg-black/30 dark:bg-black/80 backdrop-blur-md" />
					</Transition.Child>

					<span
						className="inline-block h-screen align-middle"
						aria-hidden="true"
					>
						&#8203;
					</span>

					<Transition.Child
						as={Fragment}
						enter="ease-out duration-300"
						enterFrom="opacity-0 scale-95"
						enterTo="opacity-100 scale-100"
						leave="ease-in duration-200"
						leaveFrom="opacity-100 scale-100"
						leaveTo="opacity-0 scale-95"
					>
						<div className="inline-block overflow-hidden relative z-10 p-6 my-8 w-full max-w-xl text-left align-middle bg-white dark:bg-gray-800 rounded-2xl shadow-xl transition-all">
							<div className="relative">
								<Dialog.Title as="h3" className="text-lg font-medium leading-6">
									{props.title}
								</Dialog.Title>

								<div className="absolute top-0 right-0 text-xl">
									<button
										type="button"
										className="leading-none"
										onClick={close}
									>
										&times;
									</button>
								</div>
							</div>

							{props.description && (
								<div className="mt-2">
									<p className="text-sm text-gray-100">{props.description}</p>
								</div>
							)}

							<div className="mt-4">{props.children}</div>
						</div>
					</Transition.Child>
				</div>
			</Dialog>
		</Transition>
	);
}
Example #14
Source File: BlogNav.tsx    From vignette-web with MIT License 5 votes vote down vote up
// en: `ENG`,
// ja: `日本`,
// ko: `한국`,
// 'zh-CN': `中国`,
// 'zh-TW': `中国`,
// fil: `FIL`,
// fr: `FR`,
// id: `IDN`,
// de: `DE`,
// it: `IT`,
// nl: `NL`,
function MyListbox({ router }: { router: NextRouter }) {
  const [selectedLocale, setSelectedLocale] = useState(router.locale)

  return (
    <div>
      <Listbox
        value={selectedLocale}
        onChange={(selected) => {
          setSelectedLocale(selected)
          setCookies(`NEXT_LOCALE`, selected)
          router.push(router.asPath, undefined, {
            locale: selected,
          })
        }}
      >
        <Listbox.Button className="relative flex w-full cursor-default items-center rounded-lg bg-transparent pl-1 text-left text-sm font-semibold outline-none  sm:font-normal">
          <ReactCountryFlag
            countryCode={locales[selectedLocale as string].flag}
            svg
          />
          <span className="mx-1">
            {locales[selectedLocale as string].shortName}
          </span>
          <BiChevronDown />
        </Listbox.Button>
        <Transition
          as={Fragment}
          leave="transition ease-in duration-100"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <Listbox.Options className="w-18 absolute z-100 mt-1 max-h-96 overflow-auto rounded-md border bg-white text-black shadow-lg focus:outline-none dark:border-neutral-700 dark:bg-[#181a1b] dark:text-white">
            {Object.keys(locales).map((key) => (
              /* Use the `active` state to conditionally style the active option. */
              /* Use the `selected` state to conditionally style the selected option. */
              <Listbox.Option key={key} value={key} as={Fragment}>
                {({ active, selected }) => (
                  <li
                    className={`flex cursor-default items-center px-2 py-1 sm:px-1 lg:py-0  ${
                      active
                        ? `bg-gray-100 dark:bg-neutral-700 `
                        : `bg-white  dark:bg-[#181a1b]`
                    }`}
                  >
                    <ReactCountryFlag countryCode={locales[key].flag} svg />
                    <span className="mx-1 text-sm text-black dark:text-white">
                      {locales[key].name}
                    </span>
                    {selected && (
                      <AiOutlineCheck className="fill-black dark:fill-white" />
                    )}
                  </li>
                )}
              </Listbox.Option>
            ))}
          </Listbox.Options>
        </Transition>
      </Listbox>
    </div>
  )
}
Example #15
Source File: select.tsx    From website with Apache License 2.0 5 votes vote down vote up
export function Select<T>(props: {
	items: Array<Value<T>>;
	selected: Value<T>;
	setSelected: (value: Value<T>) => unknown;
}) {
	const {selected, setSelected} = props;

	return (
		<div className="w-24">
			<Listbox value={selected} onChange={setSelected}>
				<div className="relative mt-1">
					<Listbox.Button className="relative py-2 pr-10 pl-3 w-full text-left bg-black hover:bg-gray-800 rounded-lg focus-visible:border-indigo-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 shadow-md cursor-default sm:text-sm">
						<span className="block truncate">{selected.name}</span>
						<span className="flex absolute inset-y-0 right-0 items-center pr-2 pointer-events-none">
							<HiChevronDown
								className="w-4 h-4 text-gray-400"
								aria-hidden="true"
							/>
						</span>
					</Listbox.Button>

					<Transition
						as={Fragment}
						leave="transition ease-in duration-100"
						leaveFrom="opacity-100"
						leaveTo="opacity-0"
					>
						<Listbox.Options className="overflow-auto absolute py-1 mt-1 w-full max-h-60 text-base bg-white rounded-md focus:outline-none ring-1 ring-black/5 shadow-lg sm:text-sm">
							{props.items.map(item => (
								<Listbox.Option
									key={item.name}
									className={({active}) =>
										`${active ? 'text-amber-900 bg-amber-100' : 'text-gray-900'}
                          cursor-default select-none relative py-2 pl-10 pr-4`
									}
									value={item}
								>
									{({selected, active}) => (
										<>
											<span
												className={`${
													selected ? 'font-medium' : 'font-normal'
												} block truncate`}
											>
												{item.name}
											</span>
											{selected && (
												<span
													className={`${
														active ? 'text-amber-600' : 'text-amber-600'
													}
                                absolute inset-y-0 left-0 flex items-center pl-3`}
												>
													<HiCheck className="w-5 h-5" aria-hidden="true" />
												</span>
											)}
										</>
									)}
								</Listbox.Option>
							))}
						</Listbox.Options>
					</Transition>
				</div>
			</Listbox>
		</div>
	);
}
Example #16
Source File: Nav.tsx    From vignette-web with MIT License 5 votes vote down vote up
// en: `ENG`,
// ja: `日本`,
// ko: `한국`,
// 'zh-CN': `中国`,
// 'zh-TW': `中国`,
// fil: `FIL`,
// fr: `FR`,
// id: `IDN`,
// de: `DE`,
// it: `IT`,
// nl: `NL`,
function MyListbox({ router }: { router: NextRouter }) {
  const [selectedLocale, setSelectedLocale] = useState(router.locale)

  return (
    <div>
      <Listbox
        value={selectedLocale}
        onChange={(selected) => {
          setSelectedLocale(selected)
          setCookies(`NEXT_LOCALE`, selected)
          router.push(router.asPath, undefined, {
            locale: selected,
          })
        }}
      >
        <Listbox.Button className="relative flex w-full cursor-default items-center rounded-lg bg-transparent pl-1 text-left text-sm font-semibold outline-none  sm:font-normal">
          <ReactCountryFlag
            countryCode={locales[selectedLocale as string].flag}
            svg
          />
          <span className="mx-1">
            {locales[selectedLocale as string].shortName}
          </span>
          <BiChevronDown />
        </Listbox.Button>
        <Transition
          as={Fragment}
          leave="transition ease-in duration-100"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <Listbox.Options className="w-18 absolute z-100 mt-1 max-h-96 overflow-auto rounded-md border bg-white text-black shadow-lg focus:outline-none dark:border-neutral-700 dark:bg-[#181a1b] dark:text-white">
            {Object.keys(locales).map((key) => (
              /* Use the `active` state to conditionally style the active option. */
              /* Use the `selected` state to conditionally style the selected option. */
              <Listbox.Option key={key} value={key} as={Fragment}>
                {({ active, selected }) => (
                  <li
                    className={`flex cursor-default items-center px-2 py-1 sm:px-1 lg:py-0  ${
                      active
                        ? `bg-gray-100 dark:bg-neutral-700 `
                        : `bg-white  dark:bg-[#181a1b]`
                    }`}
                  >
                    <ReactCountryFlag countryCode={locales[key].flag} svg />
                    <span className="mx-1 text-sm text-black dark:text-white">
                      {locales[key].name}
                    </span>
                    {selected && (
                      <AiOutlineCheck className="fill-black dark:fill-white" />
                    )}
                  </li>
                )}
              </Listbox.Option>
            ))}
          </Listbox.Options>
        </Transition>
      </Listbox>
    </div>
  )
}
Example #17
Source File: token-price-select.tsx    From arkadiko with GNU General Public License v3.0 5 votes vote down vote up
export function TokenPriceSelect({ tokenPrices, selected, setSelected }: Props) {
  return (
    <Listbox value={selected} onChange={setSelected}>
      {({ open }) => (
        <>
          <Listbox.Label className="block text-sm font-medium text-gray-700 sr-only">Token price</Listbox.Label>
          <div className="relative mt-1">
            <Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-white border border-gray-300 rounded-md shadow-sm cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
              <span className="block truncate">{selected.name}</span>
              <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                <SelectorIcon className="w-5 h-5 text-gray-400" aria-hidden="true" />
              </span>
            </Listbox.Button>

            <Transition
              show={open}
              as={Fragment}
              leave="transition ease-in duration-100"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <Listbox.Options className="absolute z-10 w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                {tokenPrices.map((token:any) => (
                  <Listbox.Option
                    key={token.id}
                    className={({ active }) =>
                      classNames(
                        active ? 'text-white bg-indigo-600' : 'text-gray-900',
                        'cursor-default select-none relative py-2 pl-3 pr-9'
                      )
                    }
                    value={token}
                  >
                    {({ selected, active }) => (
                      <>
                        <span className={classNames(selected ? 'font-semibold' : 'font-normal', 'block truncate')}>
                          {token.name}
                        </span>

                        {selected ? (
                          <span
                            className={classNames(
                              active ? 'text-white' : 'text-indigo-600',
                              'absolute inset-y-0 right-0 flex items-center pr-4'
                            )}
                          >
                            <CheckIcon className="w-5 h-5" aria-hidden="true" />
                          </span>
                        ) : null}
                      </>
                    )}
                  </Listbox.Option>
                ))}
              </Listbox.Options>
            </Transition>
          </div>
        </>
      )}
    </Listbox>
  )
}
Example #18
Source File: Modal.tsx    From ui with MIT License 4 votes vote down vote up
Modal = ({
  children,
  customFooter = undefined,
  closable,
  description,
  hideFooter = false,
  alignFooter = 'left',
  layout = 'horizontal',
  loading = false,
  cancelText = 'Cancel',
  onConfirm = () => {},
  onCancel = () => {},
  confirmText = 'Confirm',
  showIcon = false,
  title,
  footerBackground,
  icon,
  variant = 'success',
  visible = false,
  size = 'large',
  style,
  overlayStyle,
  contentStyle,
  className = '',
  overlayClassName,
  triggerElement,
}: Props) => {
  const [open, setOpen] = React.useState(visible ? visible : false)

  useEffect(() => {
    setOpen(visible)
  }, [visible])

  function stopPropagation(e: React.MouseEvent) {
    e.stopPropagation()
  }

  let footerClasses = [ModalStyles['sbui-modal-footer']]
  if (footerBackground) {
    footerClasses.push(ModalStyles['sbui-modal-footer--with-bg'])
  }

  let modalClasses = [
    ModalStyles[`sbui-modal`],
    ModalStyles[`sbui-modal--${size}`],
  ]
  if (className) modalClasses.push(className)

  let overlayClasses = [ModalStyles['sbui-modal-overlay']]
  if (overlayClassName) overlayClasses.push(overlayClassName)

  const footerContent = customFooter ? (
    customFooter
  ) : (
    <Space
      style={{
        width: '100%',
        justifyContent:
          layout === 'vertical'
            ? 'center'
            : alignFooter === 'right'
            ? 'flex-end'
            : 'flex-start',
      }}
    >
      <Button type="outline" onClick={onCancel} disabled={loading}>
        {cancelText}
      </Button>
      <Button
        onClick={onConfirm}
        loading={loading}
        danger={variant === 'danger'}
      >
        {confirmText}
      </Button>
    </Space>
  )

  function handleOpenChange(open: boolean) {
    if (visible !== undefined && !open) {
      // controlled component behaviour
      onCancel()
    } else {
      // un-controlled component behaviour
      setOpen(open)
    }
  }

  return (
    <Dialog.Root open={open} onOpenChange={handleOpenChange}>
      {triggerElement && (
        <Dialog.Trigger className={ModalStyles[`sbui-modal__trigger`]}>
          {triggerElement}
        </Dialog.Trigger>
      )}
      <Transition show={open}>
        <Dialog.Overlay>
          <Transition.Child
            enter={ModalStyles[`sbui-modal-overlay--enter`]}
            enterFrom={ModalStyles[`sbui-modal-overlay--enterFrom`]}
            enterTo={ModalStyles[`sbui-modal-overlay--enterTo`]}
            leave={ModalStyles[`sbui-modal-overlay--leave`]}
            leaveFrom={ModalStyles[`sbui-modal-overlay--leaveFrom`]}
            leaveTo={ModalStyles[`sbui-modal-overlay--leaveTo`]}
          >
            <div className={ModalStyles['sbui-modal-overlay-container']}>
              <div
                className={overlayClasses.join(' ')}
                style={overlayStyle}
              ></div>
            </div>
          </Transition.Child>
        </Dialog.Overlay>
        <Dialog.Content forceMount style={{ width: '100vw' }}>
          <div
            className={ModalStyles['sbui-modal-container'] + ' ' + className}
            onClick={() => (onCancel ? onCancel() : null)}
          >
            <div className={ModalStyles['sbui-modal-flex-container']}>
              <Transition.Child
                enter={ModalStyles[`sbui-modal--enter`]}
                enterFrom={ModalStyles[`sbui-modal--enterFrom`]}
                enterTo={ModalStyles[`sbui-modal--enterTo`]}
                leave={ModalStyles[`sbui-modal--leave`]}
                leaveFrom={ModalStyles[`sbui-modal--leaveFrom`]}
                leaveTo={ModalStyles[`sbui-modal--leaveTo`]}
                className="fixed inset-0 overflow-y-auto"
              >
                <div
                  className={modalClasses.join(' ')}
                  role="dialog"
                  aria-modal="true"
                  aria-labelledby="modal-headline"
                  onClick={stopPropagation}
                  style={style}
                >
                  <div
                    className={ModalStyles['sbui-modal-content']}
                    style={contentStyle}
                  >
                    <Space
                      size={5}
                      style={{
                        alignItems:
                          layout === 'vertical' ? 'center' : 'flex-start',
                      }}
                      direction={layout}
                    >
                      {icon ? icon : null}
                      <Space
                        size={4}
                        direction="vertical"
                        style={{
                          alignItems: 'flex-start',
                          textAlign: layout === 'vertical' ? 'center' : null,
                          width: '100%',
                        }}
                      >
                        <span style={{ width: 'inherit' }}>
                          {title && (
                            <Typography.Title
                              style={{
                                marginBottom: '.1rem',
                                marginTop: '0',
                              }}
                              level={4}
                            >
                              {title}
                            </Typography.Title>
                          )}
                          {description && (
                            <Typography.Text>{description}</Typography.Text>
                          )}
                        </span>

                        {children}
                        {!footerBackground && !hideFooter && footerContent}
                      </Space>
                    </Space>
                  </div>
                  {!hideFooter && footerBackground && (
                    <div className={footerClasses.join(' ')}>
                      {footerContent}
                    </div>
                  )}
                  {closable && (
                    <div className={ModalStyles['sbui-modal-close-container']}>
                      <Button
                        onClick={onCancel}
                        type="text"
                        shadow={false}
                        icon={<IconX size="medium" />}
                      />
                    </div>
                  )}
                </div>
              </Transition.Child>
            </div>
          </div>
        </Dialog.Content>
      </Transition>
    </Dialog.Root>
  )
}
Example #19
Source File: ProfileMenu.tsx    From projectboard with MIT License 4 votes vote down vote up
ProfileMenu = ({ isOpen, className, onDismiss }: Props) => {
    let classes = classnames(
        'select-none w-53 shadow-modal z-50 flex flex-col py-1 bg-white font-normal rounded text-gray-800',
        className
    );
    const ref = useRef(null);
    let ready = false;

    const { projectData } = useSelector((state: RootState) => state.currentProject);

    const { logout } = useAuth0();

    useClickOutside(ref, () => {
        if (ready && isOpen && onDismiss) {
            onDismiss();
        }
    });

    useEffect(() => {
        // eslint-disable-next-line react-hooks/exhaustive-deps
        setTimeout(() => (ready = true), 300);
    });

    return (
        <div ref={ref}>
            <Transition
                show={isOpen}
                enter="transition ease-out duration-100"
                enterFrom="transform opacity-0 scale-95"
                enterTo="transform opacity-100 scale-100"
                leave="transition easy-in duration-75"
                leaveFrom="transform opacity-100 scale-100"
                leaveTo="transform opacity-0 scale-95"
                className={classes}
                style={{ left: '-140px' }}
            >
                <Link to="/projects" className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer">
                    All Projects
                </Link>
                <div className="w-full px-3 my-1 border-b border-gray-200"></div>
                <Link
                    to="/edit-profile"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
                >
                    Edit Profile
                </Link>
                <Link
                    to="/edit-project"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
                >
                    Edit Project
                </Link>
                {projectData.access === 'admin' && (
                    <>
                        <div className="w-full px-3 my-1 border-b border-gray-200"></div>
                        <Link
                            to={`/projects/${projectData.project._id}/members`}
                            className="flex items-center h-8 px-3 hover:bg-gray-100 "
                        >
                            Manage Members
                        </Link>
                    </>
                )}
                <div className="w-full px-3 my-1 border-b border-gray-200"></div>
                <a
                    rel="noreferrer"
                    href="https://hashnode.com/@vishwajeetraj11"
                    target="_blank"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 "
                >
                    Join me on Hashnode
                </a>
                <a
                    rel="noreferrer"
                    href="https://vishwajeetraj11.hashnode.dev/introducing-product-board-a-project-management-platform"
                    target="_blank"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 "
                >
                    Introducing Project Board
                </a>
                <a
                    rel="noreferrer"
                    href="https://github.com/vishwajeetraj11/productboard"
                    target="_blank"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 "
                >
                    Github
                </a>
                <a
                    rel="noreferrer"
                    href="https://www.buymeacoffee.com/vishwajeetraj11"
                    target="_blank"
                    className="flex items-center h-8 px-3 hover:bg-gray-100 "
                >
                    Buy Me a Coffee
                </a>
                <div className="w-full px-3 my-1 border-b border-gray-200"></div>
                <div
                    className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
                    onClick={() =>
                        logout({
                            returnTo: window.location.origin
                        })
                    }
                >
                    Logout
                </div>
            </Transition>
        </div>
    );
}
Example #20
Source File: about.tsx    From vignette-web with MIT License 4 votes vote down vote up
OpenSource: NextPage<pageProps> = ({
  contributors,
  commits,
  netReceived,
  pullRequests,
  openIssues,
  totalPaid,
  balance,
}) => {
  const { t } = useTranslation(`about`)
  const [isOpen, setIsOpen] = useState(false)

  return (
    <>
      <SEO title={t(`page-title`)} />
      <Nav />
      <Container className="pt-8 lg:pt-16" id="content">
        <div className="z-20 mx-auto px-2 pb-8 lg:max-w-7xl ">
          <h1 className="lg:text-0xl bg-gradient-to-br from-[#005BEA] to-[#00C6FB] bg-clip-text text-4xl font-bold text-transparent xxs:text-5xl lg:text-9xl">
            {t(`title1`)} <br />
            {t(`title2`)}
          </h1>
          <p className="my-4 mb-8 mt-8 text-lg sm:px-2 sm:text-xl lg:mb-20 lg:text-2xl">
            {t(`hero-p`)}
          </p>
          <Container offset={10} noMargin fadeIn>
            <div className="mx-auto flex flex-wrap gap-8 pb-16 text-center">
              <div className="mx-auto text-xl">
                <div className="mb-1 text-6xl font-bold">{commits}</div>
                {t(`commits`)}
                <BiGitPullRequest
                  className="mx-auto mt-2 fill-pinkRed"
                  size={40}
                />
              </div>
              <div className="mx-auto text-xl">
                <div className="mb-1 text-6xl font-bold">{pullRequests}</div>
                {t(`pull-requests`)}
                <BiGitPullRequest
                  className="mx-auto mt-2 fill-pinkRed"
                  size={40}
                />
              </div>
              <div className="mx-auto text-xl">
                <div className="mb-1 text-6xl font-bold">{openIssues}</div>
                {t(`open-issues`)}
                <BiGitPullRequest
                  className="mx-auto mt-2 fill-pinkRed"
                  size={40}
                />
              </div>
            </div>
            <div className="w-full text-center">
              <a
                href="https://github.com/vignetteapp"
                className="button mx-auto "
              >
                {t(`visit-github-button`)}
              </a>
            </div>
          </Container>
        </div>
        <Container fadeIn noMargin className="mt-32 text-center ">
          <Image src={repoIcon} alt="" quality={100} width={72} height={72} />

          <h2 className="mt-8 text-2xl font-bold lg:text-3xl">
            {t(`section1-title`)}
          </h2>
          <div className=" mx-auto  mt-6 flex max-w-6xl flex-wrap justify-center gap-4 px-0 lg:p-8 ">
            {contributors.map((user) => (
              <Link
                passHref
                key={user.login}
                href={`https://github.com/${user.login}`}
              >
                <a className="p-4">
                  <div className="mx-auto">
                    <Image
                      width={64}
                      height={64}
                      className="rounded-full"
                      src={user.profile}
                      alt=""
                    />
                  </div>
                </a>
              </Link>
            ))}
          </div>

          <p className="mx-auto mt-8 text-xs leading-snug  text-gray-700 dark:text-gray-300 sm:max-w-md sm:text-sm">
            {t(`section1-p`)}
          </p>

          <p className="mt-4 text-xs text-gray-800 dark:text-gray-200  ">
            {t(`updates-daily-text`)}
          </p>
        </Container>
        <Container>
          <div className="mt-14 text-center lg:mt-28">
            <div className="inline-flex overflow-hidden rounded-2xl drop-shadow-xl">
              <Image
                alt=""
                src={VignettePadding}
                width={64}
                height={64}
                quality={100}
              />
            </div>

            <h2 className="mt-3 text-2xl font-semibold">
              {t(`section2-title`)}
            </h2>
            <p className="mx-auto mt-2 max-w-md">{t(`section2-p`)}</p>
          </div>
          <div className="mx-auto mt-10 flex flex-wrap justify-center gap-4 lg:max-w-5xl ">
            {teamMembers.map((m: Member) => (
              <a
                href={m.url}
                key={m.name}
                className=" my-2 mx-2 text-center lg:mx-8"
              >
                <div className="inline-flex overflow-hidden rounded-full ">
                  <Image
                    alt=""
                    className=""
                    src={m.avatar}
                    width={64}
                    height={64}
                  />
                </div>
                <h4 className=" my-1 font-medium capitalize">{m.name}</h4>
                <p className="max-w-[9em] text-xs">{m.role}</p>
              </a>
            ))}
          </div>
        </Container>
        <Container className="mt-12 text-center">
          <Image src={donationImage} width={400} height={400} alt="" />
          <h1 className="text-3xl font-bold"> {t(`section3-title`)}</h1>
          <p className="mx-auto mt-2 mb-2 max-w-[34em]">{t(`section3-p`)}</p>
          <button
            onClick={() => setIsOpen(true)}
            className="font-semibold text-pinkRed hover:underline"
          >
            {t(`gives-back-button`)}
          </button>
          <Transition appear show={isOpen} as={Fragment}>
            <Dialog
              as="div"
              className="fixed inset-0 z-10 overflow-y-auto"
              onClose={() => setIsOpen(false)}
            >
              <div className="min-h-screen px-4 text-center">
                <Transition.Child
                  as={Fragment}
                  enter="ease-out duration-300"
                  enterFrom="opacity-0"
                  enterTo="opacity-100"
                  leave="ease-in duration-200"
                  leaveFrom="opacity-100"
                  leaveTo="opacity-0"
                >
                  <Dialog.Overlay className="fixed inset-0" />
                </Transition.Child>
                <Dialog.Overlay className="fixed inset-0 bg-black/20 backdrop-blur-sm dark:bg-neutral-900/80 " />
                {/* This element is to trick the browser into centering the modal contents. */}
                <span
                  className="inline-block h-screen align-middle"
                  aria-hidden="true"
                >
                  &#8203;
                </span>
                <Transition.Child
                  as={Fragment}
                  enter="ease-out duration-300"
                  enterFrom="opacity-0 scale-95"
                  enterTo="opacity-100 scale-100"
                  leave="ease-in duration-200"
                  leaveFrom="opacity-100 scale-100"
                  leaveTo="opacity-0 scale-95"
                >
                  <div className="prose-md prose my-8 inline-block w-full max-w-2xl transform overflow-hidden rounded-2xl bg-white px-6 py-4 text-left align-middle shadow-xl transition-all dark:prose-invert dark:bg-black">
                    <Dialog.Title
                      as="h3"
                      className="text-lg font-medium leading-6 "
                    >
                      {t(`gives-back-button`)}
                    </Dialog.Title>
                    <div className="mt-2">
                      <ReactMarkdown>{t(`gives-back-p`)}</ReactMarkdown>
                    </div>

                    <div className="mt-6">
                      <button
                        type="button"
                        className="button-small inline-flex justify-center border border-transparent bg-pinkRed px-4 py-2 text-sm font-medium text-white hover:bg-[#ff2277] focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 dark:bg-pinkRed"
                        onClick={() => setIsOpen(false)}
                      >
                        {t(`got-it-button`)}
                      </button>
                    </div>
                  </div>
                </Transition.Child>
              </div>
            </Dialog>
          </Transition>
          <div className="mx-auto my-10 flex w-full max-w-5xl flex-wrap justify-center gap-6 text-lg lg:gap-20 lg:text-xl ">
            <div className="w-40 md:w-52">
              <h3 className="mb-1 text-3xl font-bold lg:text-5xl">
                ${netReceived}
              </h3>
              {t(`earned`)}
            </div>

            <div className="w-40 md:w-52">
              <h3 className="mb-1 text-3xl font-bold lg:text-5xl">
                ${balance}
              </h3>
              {t(`balance`)}
            </div>

            <div className="w-52">
              <h3 className="mb-1 text-3xl font-bold lg:text-5xl">
                ${totalPaid}
              </h3>
              {t(`paid`)}
            </div>
          </div>
          <a className="button">{t(`support-us-button`)}</a>
        </Container>
      </Container>

      <Footer />
    </>
  )
}
Example #21
Source File: index.tsx    From ledokku with MIT License 4 votes vote down vote up
Database = () => {
  const { id: databaseId } = useParams<{ id: string }>();
  const toast = useToast();
  const [isUnlinkModalOpen, setIsUnlinkModalOpen] = useState(false);
  const [isLinkModalOpen, setIsLinkModalOpen] = useState(false);
  const [arrayOfUnlinkLogs, setArrayOfUnlinkLogs] = useState<RealTimeLog[]>([]);
  const [arrayOfLinkLogs, setArrayOfLinkLogs] = useState<RealTimeLog[]>([]);
  const [appAboutToUnlink, setAppAboutToUnlink] = useState<string>();
  const [isTerminalVisible, setIsTerminalVisible] = useState(false);
  const [processStatus, setProcessStatus] = useState<
    'running' | 'notStarted' | 'finished'
  >('notStarted');
  const [unlinkLoading, setUnlinkLoading] = useState(false);
  const [linkLoading, setLinkLoading] = useState(false);

  const [selectedApp, setSelectedApp] = useState({
    value: { name: '', id: '' },
    label: 'Please select an app',
  });
  const [
    linkDatabaseMutation,
    {
      data: databaseLinkData,
      loading: databaseLinkLoading,
      error: databaseLinkError,
    },
  ] = useLinkDatabaseMutation();

  const { data: appsData } = useAppsQuery();

  const { data, loading, refetch /* error */ } = useDatabaseByIdQuery({
    variables: {
      databaseId,
    },
    ssr: false,
    skip: !databaseId,
  });

  const [unlinkDatabaseMutation] = useUnlinkDatabaseMutation();

  useUnlinkDatabaseLogsSubscription({
    onSubscriptionData: (data) => {
      const logsExist = data.subscriptionData.data?.unlinkDatabaseLogs;
      if (logsExist) {
        setArrayOfUnlinkLogs((currentLogs) => {
          return [...currentLogs, logsExist];
        });
        if (
          logsExist.type === 'end:success' ||
          logsExist.type === 'end:failure'
        ) {
          setProcessStatus('finished');
        }
      }
    },
  });

  useLinkDatabaseLogsSubscription({
    onSubscriptionData: (data) => {
      const logsExist = data.subscriptionData.data?.linkDatabaseLogs;
      if (logsExist) {
        setArrayOfLinkLogs((currentLogs) => {
          return [...currentLogs, logsExist];
        });
        if (
          logsExist.type === 'end:success' ||
          logsExist.type === 'end:failure'
        ) {
          setProcessStatus('finished');
        }
      }
    },
  });

  if (!data || !appsData) {
    return null;
  }

  // // TODO display error

  if (loading) {
    // TODO nice loading
    return <p>Loading...</p>;
  }

  const { database } = data;
  const { apps } = appsData;

  const handleUnlink = async (databaseId: string, appId: string) => {
    try {
      await unlinkDatabaseMutation({
        variables: {
          input: {
            databaseId,
            appId,
          },
        },
      });
      setIsTerminalVisible(true);
      setUnlinkLoading(true);
    } catch (e) {
      toast.error(e.message);
    }
  };

  if (!database) {
    // TODO nice 404
    return <p>Database not found.</p>;
  }

  const linkedApps = database.apps;
  const linkedIds = linkedApps?.map((db) => db.id);
  const notLinkedApps = apps.filter((db) => {
    return linkedIds?.indexOf(db.id) === -1;
  });

  const appOptions = notLinkedApps.map((app) => {
    return {
      value: { name: app.name, id: app.id },
      label: app.name,
    };
  });

  const handleConnect = async (databaseId: string, appId: string) => {
    try {
      await linkDatabaseMutation({
        variables: {
          input: {
            databaseId,
            appId,
          },
        },
      });
      setSelectedApp({
        value: { name: '', id: '' },
        label: 'Please select an app',
      });
      setIsTerminalVisible(true);
      setLinkLoading(true);
    } catch (e) {
      toast.error(e.message);
    }
  };

  return (
    <div>
      <HeaderContainer>
        <Header />
        <DatabaseHeaderInfo database={database} />
        <DatabaseHeaderTabNav database={database} />
      </HeaderContainer>

      <Container maxW="5xl" mt={10}>
        <div className="grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-4 mt-10">
          <div>
            <Heading as="h2" size="md" py={5}>
              Database info
            </Heading>
            <div className="bg-gray-100 shadow overflow-hidden rounded-lg border-b border-gray-200">
              <Table mt="4" mb="4" variant="simple">
                <Tbody mt="10">
                  <Tr py="4">
                    <Td className="font-semibold" py="3" px="4">
                      Database name
                    </Td>
                    <Td py="3" px="4">
                      {database.name}
                    </Td>
                  </Tr>
                  <Tr>
                    <Td className="font-semibold" py="7" px="4">
                      id
                    </Td>
                    <Td w="1/3" py="3" px="4">
                      {database.id}
                    </Td>
                  </Tr>
                  <Tr>
                    <Td className="font-semibold" py="3" px="4">
                      Type
                    </Td>
                    <Td py="3" px="4">
                      {database.type}
                    </Td>
                  </Tr>
                </Tbody>
              </Table>
            </div>
          </div>

          <div className="w-full">
            <h1 className="font-bold text-lg font-bold py-5">Apps</h1>
            {apps.length === 0 ? (
              <>
                <div className="mt-3 mb-4">
                  <h2 className="text-gray-400">
                    Currently you haven't created apps, to do so proceed with
                    the app creation flow
                  </h2>
                </div>
                <Link to="/create-app">
                  <Button width="large" color={'grey'}>
                    Create app
                  </Button>
                </Link>
              </>
            ) : (
              <>
                {notLinkedApps.length !== 0 ? (
                  <div>
                    <Listbox
                      as="div"
                      value={selectedApp}
                      //@ts-ignore
                      onChange={setSelectedApp}
                    >
                      {({ open }) => (
                        <div className="relative w-80">
                          <Listbox.Button className="cursor-default relative w-full rounded-md border border-gray-300 bg-white pl-3 pr-10 py-2 text-left focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition ease-in-out duration-150 sm:text-sm sm:leading-5">
                            <span className="block truncate">
                              {selectedApp.label}
                            </span>
                            <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                              <svg
                                className="h-5 w-5 text-gray-400"
                                viewBox="0 0 20 20"
                                fill="none"
                                stroke="currentColor"
                              >
                                <path
                                  d="M7 7l3-3 3 3m0 6l-3 3-3-3"
                                  strokeWidth="1.5"
                                  strokeLinecap="round"
                                  strokeLinejoin="round"
                                />
                              </svg>
                            </span>
                          </Listbox.Button>
                          {open && (
                            <Transition
                              show={open}
                              enter="transition ease-out duration-100"
                              enterFrom="transform opacity-0 scale-95"
                              enterTo="transform opacity-100 scale-100"
                              leave="transition ease-in duration-75"
                              leaveFrom="transform opacity-100 scale-100"
                              leaveTo="transform opacity-0 scale-95"
                              className="absolute mt-1 w-full rounded-md bg-white shadow-lg z-10"
                            >
                              <Listbox.Options
                                static
                                className="max-h-60 rounded-md py-1 text-base leading-6 shadow-ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm sm:leading-5"
                              >
                                {appOptions.map(
                                  (app) =>
                                    app.value.id !== selectedApp.value.id && (
                                      <Listbox.Option
                                        key={appOptions.indexOf(app)}
                                        value={app as any}
                                      >
                                        {({ active }) => (
                                          <div
                                            className={cx(
                                              'cursor-default select-none relative py-2 px-4',
                                              {
                                                'bg-gray-200': active,
                                                'bg-white text-black': !active,
                                              }
                                            )}
                                          >
                                            {app.label}
                                          </div>
                                        )}
                                      </Listbox.Option>
                                    )
                                )}
                              </Listbox.Options>
                            </Transition>
                          )}
                        </div>
                      )}
                    </Listbox>

                    {databaseLinkError && (
                      <p className="text-red-500 text-sm font-semibold">
                        {databaseLinkError.graphQLErrors[0].message}
                      </p>
                    )}
                    <Button
                      color="grey"
                      width="large"
                      className="mt-2"
                      isLoading={
                        databaseLinkLoading &&
                        !databaseLinkData &&
                        !databaseLinkError
                      }
                      disabled={!selectedApp.value.id}
                      onClick={() => setIsLinkModalOpen(true)}
                    >
                      Link app
                    </Button>
                    {isLinkModalOpen && (
                      <Modal>
                        <ModalTitle>Link app</ModalTitle>
                        <ModalDescription>
                          {isTerminalVisible ? (
                            <>
                              <p className="mb-2 ">
                                Linking <b>{selectedApp.value.name}</b> with{' '}
                                <b>{database.name}</b>!
                              </p>
                              <p className="text-gray-500 mb-2">
                                Linking process usually takes a couple of
                                minutes. Breathe in, breathe out, logs are about
                                to appear below:
                              </p>
                              <Terminal className={'w-6/6'}>
                                {arrayOfLinkLogs.map((log) => (
                                  <p
                                    key={arrayOfLinkLogs.indexOf(log)}
                                    className="text-s leading-5"
                                  >
                                    {log.message}
                                  </p>
                                ))}
                              </Terminal>
                            </>
                          ) : (
                            <p>
                              Are you sure, you want to link{' '}
                              <b>{selectedApp.value.name}</b> to{' '}
                              <b>{database.name}</b>?
                            </p>
                          )}
                        </ModalDescription>
                        <ModalButton
                          ctaFn={() => {
                            setProcessStatus('running');
                            handleConnect(databaseId, selectedApp.value.id);
                          }}
                          ctaText={'Link'}
                          otherButtonText={'Cancel'}
                          isCtaLoading={isTerminalVisible ? false : linkLoading}
                          isCtaDisabled={isTerminalVisible}
                          isOtherButtonDisabled={processStatus === 'running'}
                          closeModal={() => {
                            setIsLinkModalOpen(false);
                            refetch({ databaseId });
                            setLinkLoading(false);
                            setIsTerminalVisible(false);
                            setProcessStatus('notStarted');
                          }}
                        />
                      </Modal>
                    )}
                  </div>
                ) : (
                  <>
                    <p className="mt-3 mb-3 mr-8 text-cool-gray-400">
                      All your apps are already linked to this database! If you
                      want to create more apps proceed with create app flow.
                    </p>
                    <div className="ml-80">
                      <Link to="/create-app">
                        <Button
                          color={'grey'}
                          variant="outline"
                          className="text-sm mr-3"
                        >
                          Create app
                        </Button>
                      </Link>
                    </div>
                  </>
                )}

                {!loading && database && database.apps && (
                  <>
                    <h2 className="mb-1 mt-3 font-semibold">
                      {database.apps.length > 0 && 'Linked apps'}
                    </h2>
                    {database.apps.map((app) => (
                      <div
                        key={database.apps?.indexOf(app)}
                        className="flex flex-row justify-start"
                      >
                        <Link to={`/app/${app.id}`} className="py-2 block">
                          <div className="w-64 flex items-center py-3 px-2 shadow hover:shadow-md transition-shadow duration-100 ease-in-out rounded bg-white">
                            {app.name}
                          </div>
                        </Link>
                        <Button
                          width="normal"
                          className="mt-4 ml-2 h-10"
                          color="red"
                          onClick={() => {
                            setIsUnlinkModalOpen(true);
                            setAppAboutToUnlink(app.name);
                          }}
                        >
                          Unlink
                        </Button>

                        {isUnlinkModalOpen && (
                          <Modal>
                            <ModalTitle>Unlink app</ModalTitle>
                            <ModalDescription>
                              {isTerminalVisible ? (
                                <>
                                  <p className="mb-2 ">
                                    Unlinking <b>{database.name}</b> from{' '}
                                    <b>{appAboutToUnlink}</b>!
                                  </p>
                                  <p className="text-gray-500 mb-2">
                                    Unlinking process usually takes a couple of
                                    minutes. Breathe in, breathe out, logs are
                                    about to appear below:
                                  </p>
                                  <Terminal className={'w-6/6'}>
                                    {arrayOfUnlinkLogs.map((log) => (
                                      <p
                                        key={arrayOfUnlinkLogs.indexOf(log)}
                                        className="text-s leading-5"
                                      >
                                        {log.message}
                                      </p>
                                    ))}
                                  </Terminal>
                                </>
                              ) : (
                                <p>
                                  Are you sure, you want to unlink{' '}
                                  <b>{database.name}</b> from{' '}
                                  <b>{appAboutToUnlink}</b>?
                                </p>
                              )}
                            </ModalDescription>
                            <ModalButton
                              ctaFn={() => {
                                setProcessStatus('running');
                                handleUnlink(database.id, app.id);
                              }}
                              ctaText={'Unlink'}
                              otherButtonText={'Cancel'}
                              isCtaLoading={
                                isTerminalVisible ? false : unlinkLoading
                              }
                              isOtherButtonDisabled={
                                processStatus === 'running'
                              }
                              isCtaDisabled={isTerminalVisible}
                              closeModal={() => {
                                setIsUnlinkModalOpen(false);
                                refetch({ databaseId });
                                setUnlinkLoading(false);
                                setIsTerminalVisible(false);
                                setAppAboutToUnlink('');
                                setProcessStatus('notStarted');
                              }}
                            />
                          </Modal>
                        )}
                      </div>
                    ))}
                  </>
                )}
              </>
            )}
          </div>
        </div>
      </Container>
    </div>
  );
}
Example #22
Source File: Listbox.tsx    From ui with MIT License 4 votes vote down vote up
function Listbox({
  children,
  className,
  descriptionText,
  error,
  icon,
  id,
  label,
  labelOptional,
  layout,
  onChange,
  value,
  style,
  size = 'medium',
  defaultValue,
  borderless = false,
}: Props) {
  const [selected, setSelected] = useState(defaultValue || undefined)
  const [selectedNode, setSelectedNode] = useState<any>({})

  useEffect(() => {
    if (value) {
      setSelected(value)
    }
  }, [value])

  useEffect(() => {
    const data: any = children
    const content: any = flatten(data)

    function findNode(value: any) {
      return content.find((node: any) => node.props.value == value)
    }

    /*
     * value prop overrides everything
     */
    if (value) {
      setSelected(value)
      const node: any = findNode(value)
      setSelectedNode(node?.props ? node.props : undefined)
      return
    }

    /*
     * if no value prop, then use selected state
     */
    if (selected) {
      const node: any = findNode(selected)
      setSelectedNode(node?.props ? node.props : undefined)
    } else {
      /*
       * if no selected value (including a `defaultvalue`), then use first child
       */
      setSelectedNode(content[0].props)
    }
  }, [children, selected, value])

  function handleOnChange(e: any) {
    if (onChange) onChange(e)
    setSelected(e)
  }

  let selectClasses = [SelectStyles['sbui-listbox']]
  if (error) selectClasses.push(SelectStyles['sbui-listbox--error'])
  if (icon) selectClasses.push(SelectStyles['sbui-listbox--with-icon'])
  if (size) selectClasses.push(SelectStyles[`sbui-listbox--${size}`])
  if (borderless) selectClasses.push(SelectStyles['sbui-listbox--borderless'])

  return (
    <FormLayout
      label={label}
      labelOptional={labelOptional}
      layout={layout}
      id={id}
      error={error}
      descriptionText={descriptionText}
      className={className}
      style={style}
      size={size}
    >
      <div className={SelectStyles['sbui-listbox-container']}>
        <HeadlessListbox value={selected} onChange={handleOnChange}>
          {({ open }) => {
            return (
              <div className="relative">
                <HeadlessListbox.Button className={selectClasses.join(' ')}>
                  {icon && <InputIconContainer icon={icon} />}
                  <span className={SelectStyles['sbui-listbox-addonbefore']}>
                    {selectedNode?.addOnBefore && <selectedNode.addOnBefore />}
                    <span className={SelectStyles['sbui-listbox-label']}>
                      {selectedNode?.label}
                    </span>
                  </span>
                  <span
                    className={SelectStyles['sbui-listbox-chevron-container']}
                  >
                    <svg
                      className={SelectStyles['sbui-listbox-chevron']}
                      xmlns="http://www.w3.org/2000/svg"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                      aria-hidden="true"
                    >
                      <path
                        fillRule="evenodd"
                        d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
                        clipRule="evenodd"
                      />
                    </svg>
                  </span>
                  {error && (
                    <div
                      className={SelectStyles['sbui-listbox-actions-container']}
                    >
                      {error && <InputErrorIcon size={size} />}
                    </div>
                  )}
                </HeadlessListbox.Button>
                <Transition
                  show={open}
                  as={Fragment}
                  leave={SelectStyles['sbui-listbox-transition--leave']}
                  leaveFrom={
                    SelectStyles['sbui-listbox-transition--leave-from']
                  }
                  leaveTo={SelectStyles['sbui-listbox-transition--leave-to']}
                >
                  <HeadlessListbox.Options
                    static
                    className={SelectStyles['sbui-listbox-option-container']}
                  >
                    {children}
                  </HeadlessListbox.Options>
                </Transition>
              </div>
            )
          }}
        </HeadlessListbox>
      </div>
    </FormLayout>
  )
}
Example #23
Source File: ConnectedSites.tsx    From pali-wallet with MIT License 4 votes vote down vote up
ConnectedSites = (): any => {
  const { navigate } = useUtils();

  const { activeAccount } = useStore();

  const [selected, setSelected] = useState<string>('');

  const disconnectSite = (id: any) => {
    browser.runtime.sendMessage({
      type: 'RESET_CONNECTION_INFO',
      target: 'background',
      id,
      url: selected,
    });

    setSelected('');
  };

  return (
    <Layout title="CONNECTED SITES">
      <p className="m-4 max-w-xs text-white text-xs md:max-w-md">
        {`${activeAccount?.label} is not connected to any sites. To connect to a SYS platform site, find the connect button on their site.`}
      </p>

      <div className="flex flex-col items-center justify-center w-full">
        {/* {activeAccount?.connectedTo &&
          activeAccount.connectedTo.map((url: string) => (
            <ul
              key={url}
              className="scrollbar-styled px-4 py-2 w-full h-80 overflow-auto"
            >
              <li className="flex items-center justify-between my-2 py-3 w-full text-xs border-b border-dashed border-gray-500">
                <p>{formatUrl(url, 25)}</p>
                <IconButton onClick={() => setSelected(url)}>
                  <Icon name="edit" wrapperClassname="w-4" />
                </IconButton>
              </li>
            </ul>
          ))} */}

        {selected && (
          <Transition appear show={selected !== ''} as={Fragment}>
            <Dialog
              as="div"
              className="fixed z-10 inset-0 text-center overflow-y-auto"
              onClose={() => setSelected('')}
            >
              <div className="fixed z-0 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out" />

              <div className="px-4 min-h-screen">
                <Transition.Child
                  as={Fragment}
                  enter="ease-out duration-300"
                  enterFrom="opacity-0"
                  enterTo="opacity-100"
                  leave="ease-in duration-200"
                  leaveFrom="opacity-100"
                  leaveTo="opacity-0"
                >
                  <Dialog.Overlay className="fixed inset-0" />
                </Transition.Child>

                <span
                  className="inline-block align-middle h-screen"
                  aria-hidden="true"
                >
                  &#8203;
                </span>
                <Transition.Child
                  as={Fragment}
                  enter="ease-out duration-300"
                  enterFrom="opacity-0 scale-95"
                  enterTo="opacity-100 scale-100"
                  leave="ease-in duration-200"
                  leaveFrom="opacity-100 scale-100"
                  leaveTo="opacity-0 scale-95"
                >
                  <div className="inline-block align-middle my-8 py-6 w-full max-w-2xl text-left font-poppins bg-bkg-2 rounded-2xl shadow-xl overflow-hidden transform transition-all">
                    <Dialog.Title
                      as="h3"
                      className="pb-3 text-center text-brand-white text-lg font-medium leading-6 border-b border-dashed border-brand-white"
                    >
                      Edit connection
                    </Dialog.Title>
                    <div className="my-4">
                      <p className="m-3 text-brand-white text-sm">
                        Delete connected site:
                      </p>

                      <div className="flex items-center justify-between m-3 text-brand-white">
                        <p>{formatUrl(selected, 20)}</p>

                        <IconButton
                          onClick={() => disconnectSite(activeAccount?.id)}
                        >
                          <Icon name="delete" />
                        </IconButton>
                      </div>

                      <div className="p-4 bg-bkg-1">
                        <p className="mb-3 text-brand-white">Permissions</p>

                        <div className="flex items-center justify-between">
                          <p className="text-brand-white text-xs">
                            {activeAccount?.label}
                          </p>

                          <p className="text-brand-white text-xs">
                            {ellipsis(activeAccount?.address)}
                          </p>
                        </div>

                        <p className="mt-4 pt-3 text-brand-white border-t border-dashed border-brand-white opacity-60 cursor-not-allowed">
                          <input type="checkbox" />

                          <span className="mb-1 ml-3">
                            View the addresses of your permitted accounts
                          </span>
                        </p>
                      </div>
                    </div>

                    <div className="mt-4 text-center">
                      <button
                        type="button"
                        className="transparent inline-flex justify-center px-12 py-2 hover:text-bkg-4 text-brand-white text-sm font-medium hover:bg-white bg-repeat border border-white rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-royalblue focus-visible:ring-offset-2"
                        onClick={() => setSelected('')}
                      >
                        Close
                      </button>
                    </div>
                  </div>
                </Transition.Child>
              </div>
            </Dialog>
          </Transition>
        )}

        <div className="absolute bottom-12 md:static">
          <SecondaryButton type="button" onClick={() => navigate('/home')}>
            Close
          </SecondaryButton>
        </div>
      </div>
    </Layout>
  );
}
Example #24
Source File: SidePanel.tsx    From ui with MIT License 4 votes vote down vote up
SidePanel = ({
  className,
  children,
  title,
  description,
  visible,
  wide = false,
  loading,
  align = 'right',
  alignFooter = 'right',
  hideFooter = false,
  customFooter = undefined,
  onConfirm,
  onCancel,
  confirmText = 'Confirm',
  cancelText = 'Cancel',
  triggerElement,
}: Props) => {
  const [open, setOpen] = React.useState(visible ? visible : false)

  useEffect(() => {
    setOpen(visible)
  }, [visible])

  function stopPropagation(e: React.MouseEvent) {
    e.stopPropagation()
  }

  const sidePanelClasses = [SlidePanelStyles['sbui-sidepanel']]

  const left = align === 'left'

  const containerClasses = [SlidePanelStyles['sbui-sidepanel-container']]
  if (left) {
    containerClasses.push(SlidePanelStyles['sbui-sidepanel--left'])
  } else {
    containerClasses.push(SlidePanelStyles['sbui-sidepanel--right'])
  }
  if (className) containerClasses.push(className)

  let footerClasses = [SlidePanelStyles['sbui-sidepanel-footer-container']]
  if (!customFooter) {
    footerClasses.push(SlidePanelStyles['sbui-sidepanel-footer'])
  }

  const footerContent = customFooter ? (
    <div className={footerClasses.join(' ')}>{customFooter}</div>
  ) : (
    <div className={footerClasses.join(' ')}>
      <Space
        style={{
          width: '100%',
          justifyContent: alignFooter === 'right' ? 'flex-end' : 'flex-start',
        }}
      >
        <Button
          disabled={loading}
          type="outline"
          onClick={() => (onCancel ? onCancel() : null)}
        >
          {cancelText}
        </Button>
        <Button
          loading={loading}
          onClick={() => (onConfirm ? onConfirm() : null)}
        >
          {confirmText}
        </Button>
      </Space>
    </div>
  )

  function handleOpenChange(open: boolean) {
    if (visible !== undefined && !open) {
      // controlled component behaviour
      onCancel()
    } else {
      // un-controlled component behaviour
      setOpen(open)
    }
  }

  return (
    <Dialog.Root open={open} onOpenChange={handleOpenChange}>
      {triggerElement && (
        <Dialog.Trigger className={SlidePanelStyles[`sbui-sidepanel__trigger`]}>
          {triggerElement}
        </Dialog.Trigger>
      )}
      <Transition show={open}>
        <Dialog.Overlay forceMount>
          <Transition.Child
            enter={SlidePanelStyles[`sbui-sidepanel-overlay--enter`]}
            enterFrom={SlidePanelStyles[`sbui-sidepanel-overlay--enterFrom`]}
            enterTo={SlidePanelStyles[`sbui-sidepanel-overlay--enterTo`]}
            leave={SlidePanelStyles[`sbui-sidepanel-overlay--leave`]}
            leaveFrom={SlidePanelStyles[`sbui-sidepanel-overlay--leaveFrom`]}
            leaveTo={SlidePanelStyles[`sbui-sidepanel-overlay--leaveTo`]}
          >
            <div
              className={SlidePanelStyles['sbui-sidepanel-overlay-container']}
            >
              <div className={SlidePanelStyles['sbui-sidepanel-overlay']}></div>
            </div>
          </Transition.Child>
        </Dialog.Overlay>

        <Dialog.Content forceMount style={{ width: '100vw' }}>
          <div className={containerClasses.join(' ')}>
            <Transition.Child
              enter={SlidePanelStyles[`sbui-sidepanel--enter`]}
              enterFrom={
                left
                  ? SlidePanelStyles[`sbui-sidepanel--enterFrom--left`]
                  : SlidePanelStyles[`sbui-sidepanel--enterFrom`]
              }
              enterTo={SlidePanelStyles[`sbui-sidepanel--enterTo`]}
              leave={SlidePanelStyles[`sbui-sidepanel--leave`]}
              leaveFrom={SlidePanelStyles[`sbui-sidepanel--leaveFrom`]}
              leaveTo={
                left
                  ? SlidePanelStyles[`sbui-sidepanel--leaveTo--left`]
                  : SlidePanelStyles[`sbui-sidepanel--leaveTo`]
              }
            >
              <div
                className={
                  wide
                    ? SlidePanelStyles['sbui-sidepanel--wide']
                    : SlidePanelStyles['sbui-sidepanel--medium']
                }
              >
                <div
                  className={sidePanelClasses.join(' ')}
                  onClick={stopPropagation}
                >
                  <Space
                    size={6}
                    direction="vertical"
                    style={{
                      minHeight: '0',
                      flex: '1 1 0%',
                      overflowY: 'scroll',
                    }}
                  >
                    <header
                      className={SlidePanelStyles['sbui-sidepanel-header']}
                    >
                      <Space
                        size={3}
                        direction="row"
                        style={{
                          alignItems: 'center',
                          justifyContent: 'space-between',
                        }}
                      >
                        {title && (
                          <Typography.Title className="m-0" level={4}>
                            {title}
                          </Typography.Title>
                        )}
                        <div
                          className={
                            SlidePanelStyles['sbui-sidepanel-close-container']
                          }
                        >
                          <Button
                            aria-label="Close panel"
                            onClick={onCancel}
                            type="text"
                            shadow={false}
                            style={{ padding: 0 }}
                            icon={<IconX size="xlarge" strokeWidth={2} />}
                          />
                        </div>
                      </Space>
                      <div>
                        {description && (
                          <Typography.Text type="secondary">
                            {description}
                          </Typography.Text>
                        )}
                      </div>
                    </header>
                    <div className={SlidePanelStyles['sbui-sidepanel-content']}>
                      {children}
                    </div>
                  </Space>
                  {!hideFooter && footerContent}
                </div>
              </div>
            </Transition.Child>
          </div>
        </Dialog.Content>
      </Transition>
    </Dialog.Root>
  )
}
Example #25
Source File: BlogNav.tsx    From vignette-web with MIT License 4 votes vote down vote up
Nav: React.FC = () => {
  const { t } = useTranslation([`nav`, `common`])
  const [isOpen, setIsOpen] = useState<boolean>(false)
  const toggleMenu = () => (isOpen ? setIsOpen(false) : setIsOpen(true))
  const [mounted, setMounted] = useState(false)
  const { resolvedTheme, setTheme } = useTheme()

  const router = useRouter()

  // A flag to know when the page has mounted so the theme can be accessed
  useEffect(() => setMounted(true), [])

  return (
    <>
      {` `}
      <a
        href="#content"
        className="text-md absolute -top-7 z-50 ml-3 -translate-y-12 transform rounded-md border border-gray-300 bg-white px-3 py-2 tracking-tight outline-none transition-transform duration-100 focus:translate-y-12 dark:border-neutral-700 dark:bg-black lg:ml-8"
      >
        Skip to content
      </a>
      {` `}
      <div className="relative z-30 mx-auto flex w-full max-w-7xl items-center justify-between bg-transparent py-6 px-4  sm:px-8 lg:px-4 ">
        <div className="flex items-center">
          <Link href="/blog" passHref>
            <a className="text-lg font-bold lg:text-xl">
              {t(`blog:nav-title`)}
            </a>
          </Link>
        </div>

        <div className=" mx-4 ml-auto hidden items-center gap-4 sm:flex ">
          <MyListbox router={router} />
          <button
            className="outline-none"
            onClick={() =>
              setTheme(resolvedTheme === `dark` ? `light` : `dark`)
            }
          >
            {mounted ? (
              resolvedTheme == `dark` ? (
                <BsSunFill size={18} />
              ) : (
                <BsMoonFill size={18} />
              )
            ) : (
              <div className="w-[18px]" />
            )}
          </button>
          <Link href="https://github.com/vignetteapp" passHref>
            <a className="outline-none">
              <AiFillGithub size={24} />
            </a>
          </Link>
          <Link href="https://twitter.com/vignette_org" passHref>
            <a className="outline-none">
              <AiOutlineTwitter size={24} />
            </a>
          </Link>

          <button className="rounded-full bg-pinkRed px-8 py-1 font-semibold text-white ">
            {t(`download`)}
          </button>
        </div>
        <div className="flex items-center lg:hidden">
          <button className="" onClick={toggleMenu}>
            <GiHamburgerMenu size="28" className="fill-neutral-100" />
          </button>
          <Transition appear show={isOpen} as={Fragment}>
            <Dialog
              open={isOpen}
              onClose={() => setIsOpen(false)}
              className="fixed inset-0 z-50 lg:hidden"
            >
              <Transition.Child
                as={Fragment}
                enter="ease-out duration-100"
                enterFrom="opacity-0"
                enterTo="opacity-100"
                leave="ease-in duration-75"
                leaveFrom="opacity-100"
                leaveTo="opacity-0"
              >
                <Dialog.Overlay className="fixed inset-0 bg-black/20 backdrop-blur-sm dark:bg-neutral-900/80 " />
              </Transition.Child>
              <Transition.Child
                as={Fragment}
                enter="ease-out duration-100"
                enterFrom="opacity-0 scale-95"
                enterTo="opacity-100 scale-100"
                leave="ease-in duration-75"
                leaveFrom="opacity-100 scale-100"
                leaveTo="opacity-0 scale-95"
              >
                <div className="dark:highlight-white/5 fixed top-4 right-4 w-full max-w-xs rounded-lg bg-white p-6 text-base font-semibold text-gray-900 shadow-lg dark:bg-neutral-900 dark:text-gray-300">
                  <button
                    onClick={() => setIsOpen(false)}
                    className="absolute top-5 right-5 flex h-8 w-8 items-center justify-center text-gray-500 hover:text-gray-600 dark:text-gray-200 dark:hover:text-gray-100"
                  >
                    <span className="sr-only">Close navigation</span>
                    <svg
                      viewBox="0 0 10 10"
                      className="h-2.5 w-2.5 overflow-visible"
                      aria-hidden="true"
                    >
                      <path
                        d="M0 0L10 10M10 0L0 10"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="2"
                        strokeLinecap="round"
                      ></path>
                    </svg>
                  </button>
                  <ul className="space-y-6">
                    <li>
                      <Link href="/">
                        <a>{t(`nav:home`)}</a>
                      </Link>
                    </li>
                    <li>
                      <Link href="/features">
                        <a>{t(`nav:features`)}</a>
                      </Link>
                    </li>
                    <li>
                      <Link href="/about">
                        <a>{t(`nav:about`)}</a>
                      </Link>
                    </li>
                    <li>
                      <Link href="/blog">
                        <a>{t(`nav:blog`)}</a>
                      </Link>
                    </li>
                    <li>
                      <Link href="/contact">
                        <a>{t(`nav:contact`)}</a>
                      </Link>
                    </li>
                    <li>
                      <MyListbox router={router} />
                    </li>
                  </ul>
                  <div className="mt-6 border-t border-gray-200 pt-6 dark:border-gray-200/10">
                    <button
                      aria-label="Toggle Dark Mode"
                      type="button"
                      className="general-ring-state flex w-full items-center justify-center rounded-full bg-gray-200 py-3 dark:bg-neutral-700"
                      onClick={() =>
                        setTheme(resolvedTheme === `dark` ? `light` : `dark`)
                      }
                    >
                      {mounted && (
                        <>
                          <div>
                            {resolvedTheme === `dark` ? (
                              <BsSunFill size={18} />
                            ) : (
                              <BsMoonFill size={18} />
                            )}
                          </div>
                          {resolvedTheme === `dark` ? (
                            <p className="ml-3 font-semibold">
                              {t(`common:switch-theme-light`)}
                            </p>
                          ) : (
                            <p className="ml-3 font-semibold">
                              {t(`common:switch-theme-dark`)}
                            </p>
                          )}
                        </>
                      )}
                    </button>
                  </div>
                </div>
              </Transition.Child>
            </Dialog>
          </Transition>
        </div>
      </div>
    </>
  )
}
Example #26
Source File: Currency.tsx    From pali-wallet with MIT License 4 votes vote down vote up
CurrencyView = () => {
  const controller = getController();
  const { navigate, handleRefresh } = useUtils();
  const { getFiatAmount } = usePrice();
  const { activeAccount } = useStore();

  if (!activeAccount) throw new Error('No account');

  const { accounts, activeAccountId, coins, fiat, activeNetwork, networks } =
    useStore();

  const { asset } = fiat;

  const [selectedCoin, setSelectedCoin] = useState(String(asset));
  const [checkValueCoin, setCheckValueCoin] = useState('usd');
  const [confirmed, setConfirmed] = useState(false);
  const [fiatAmountValue, setFiatAmountValue] = useState('');

  const convertCurrency = (value: number, toCoin: string) =>
    value * coins[toCoin];

  const convertToCrypto = (value: number, fromCoin: string) =>
    value / coins[fromCoin];

  const isUnlocked =
    controller.wallet.isUnlocked() && activeAccount.address !== '';

  const isSyscoinChain = Boolean(networks.syscoin[activeNetwork.chainId]);

  const balance = isSyscoinChain
    ? activeAccount.balances.syscoin
    : activeAccount.balances.ethereum;

  const [conversorValues, setConversorValues] = useState({
    crypto: balance,
    fiat: convertCurrency(balance, checkValueCoin),
  });

  const handleConvert = (value: number, toCoin: string) => {
    setConversorValues({
      crypto: value,
      fiat: convertCurrency(value, toCoin),
    });
  };

  const handleReverseConvert = (value: number, fromCoin: string) => {
    setConversorValues({
      crypto: convertToCrypto(value, fromCoin),
      fiat: value,
    });
  };

  const handleConfirmCurrencyChange = () => {
    setConfirmed(true);
  };

  const fiatCurrency = asset ? String(asset).toUpperCase() : 'USD';

  const getFiatAmountValue = async () => {
    const value = await getFiatAmount(balance || 0, 4, String(selectedCoin));

    setFiatAmountValue(value);
  };

  useEffect(() => {
    if (isUnlocked && accounts && accounts[activeAccountId]) {
      handleRefresh(true);
    }
  }, [isUnlocked, activeAccountId]);

  useEffect(() => {
    if (selectedCoin) {
      controller.utils.setFiat(
        selectedCoin,
        isSyscoinChain ? 'syscoin' : 'ethereum'
      );

      getFiatAmountValue();
    }
  }, [selectedCoin]);

  useEffect(() => {
    getFiatAmountValue();
  }, [selectedCoin, getFiatAmountValue]);

  return (
    <Layout title="FIAT CURRENCY" id="fiat-currency-title">
      <DefaultModal
        show={confirmed}
        onClose={() => navigate('/home')}
        title="Fiat currency set successfully"
        description={`Now you will see the values in your wallet in SYS and ${
          selectedCoin.toUpperCase() || 'USD'
        }`}
      />

      <p className="mx-4 my-3 max-w-xs text-left text-white text-sm md:max-w-full">
        You can choose and set your preferred currency to see in your wallet.
      </p>

      <div className="flex flex-col items-center justify-center">
        <Menu as="div" className="relative inline-block text-left">
          <Menu.Button
            disabled={!fiat || !coins}
            className="inline-flex justify-center py-2 w-80 text-white text-sm font-medium bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full"
          >
            <p className="ml-2">
              {selectedCoin ? selectedCoin.toUpperCase() : fiatCurrency}
            </p>

            <Icon
              name="select-down"
              className="text-brand-royalblue"
              wrapperClassname="w-8 absolute right-28 bottom-3"
            />
          </Menu.Button>

          <Transition
            as={Fragment}
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="transform opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="transform opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            {fiat && coins && (
              <Menu.Items className="scrollbar-styled absolute z-10 mt-2 py-3 w-full h-44 text-brand-white font-poppins bg-bkg-4 border border-fields-input-border rounded-xl shadow-2xl overflow-auto origin-top-right">
                {Object.entries(coins).map(([key]) => (
                  <Menu.Item key={key}>
                    <button
                      key={key}
                      onClick={() => setSelectedCoin(key)}
                      className="group flex gap-x-1 items-center justify-start px-4 py-2 w-full hover:text-brand-royalbluemedium text-brand-white font-poppins text-sm border-0 border-b border-dashed border-brand-royalblue border-transparent border-opacity-30 transition-all duration-300"
                    >
                      {getSymbolFromCurrency(key.toUpperCase())}

                      <p>{key.toUpperCase()}</p>
                    </button>
                  </Menu.Item>
                ))}
              </Menu.Items>
            )}
          </Transition>
        </Menu>

        <div className="flex flex-col items-center justify-center text-center">
          {activeNetwork.chainId === 5700 ? (
            <div className="flex gap-x-0.5 items-center justify-center mt-8">
              <p className="font-rubik text-5xl font-medium">
                {formatNumber(Number(balance) || 0)}{' '}
              </p>

              <p className="font-poppins md:mt-4">TSYS</p>
            </div>
          ) : (
            <>
              <div className="flex gap-x-0.5 items-center justify-center mt-8">
                <p className="font-rubik text-5xl font-medium">
                  {formatNumber(balance || 0)}{' '}
                </p>

                <p className="font-poppins md:mt-4">
                  {activeNetwork.currency
                    ? activeNetwork.currency.toUpperCase()
                    : ''}
                </p>
              </div>

              <p>{fiatAmountValue ?? 0}</p>
            </>
          )}
        </div>

        <div className="mt-6 md:mt-8">
          <SecondaryButton type="button" onClick={handleConfirmCurrencyChange}>
            Save
          </SecondaryButton>
        </div>
      </div>

      <div className="fixed bottom-0 left-0 flex flex-col gap-y-3 items-center justify-center w-full max-w-2xl h-44 bg-bkg-4 md:bottom-8 md:left-auto">
        <p className="mb-2 text-left text-white text-sm">
          Check your balance in different currencies
        </p>

        <div className="standard relative text-brand-royalblue text-sm font-medium">
          <Input
            type="number"
            onChange={(event) =>
              handleConvert(Number(event.target.value), checkValueCoin)
            }
            maxLength={20}
            value={Number(conversorValues.crypto)}
            className="flex items-center justify-between px-4 py-2 w-80 bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full outline-none"
          />

          <div className="absolute bottom-1.5 right-4 flex gap-x-3 items-center justify-center">
            <p
              className="cursor-pointer"
              onClick={() => handleConvert(Number(balance), checkValueCoin)}
            >
              MAX
            </p>

            <div className="flex gap-x-3 items-center justify-center border-l border-dashed border-gray-700">
              <Icon
                name="dolar"
                wrapperClassname="w-2 ml-4 mb-1.5"
                className="text-brand-royalblue"
              />

              <p>SYS</p>
            </div>
          </div>
        </div>

        <div className="standard relative text-brand-royalblue text-sm font-medium">
          <Input
            type="number"
            maxLength={20}
            onChange={(event) => {
              handleReverseConvert(Number(event.target.value), checkValueCoin);
            }}
            value={Number(conversorValues.fiat)}
            className="flex items-center justify-between px-4 py-2 w-80 bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full outline-none"
          />
          <div className="absolute bottom-2 right-2 flex gap-x-3 items-center justify-center">
            <Menu as="div" className="relative inline-block text-left">
              <Menu.Button
                disabled={!fiat || !coins}
                className="flex gap-x-1 justify-center mr-5 text-brand-royalblue text-sm font-medium bg-fields-input-primary rounded-full"
              >
                {getSymbolFromCurrency(checkValueCoin.toUpperCase())}
                {checkValueCoin.toUpperCase()}

                <Icon
                  name="select-down"
                  className="text-brand-royalblue"
                  wrapperClassname="w-8 absolute -right-1 bottom-1"
                />
              </Menu.Button>

              <Transition
                as={Fragment}
                enter="transition ease-out duration-100"
                enterFrom="transform opacity-0 scale-95"
                enterTo="transform opacity-100 scale-100"
                leave="transition ease-in duration-75"
                leaveFrom="transform opacity-100 scale-100"
                leaveTo="transform opacity-0 scale-95"
              >
                {fiat && coins && (
                  <Menu.Items className="scrollbar-styled absolute z-10 bottom-10 right-0 mt-2 py-3 w-44 h-56 text-brand-white font-poppins bg-bkg-4 border border-fields-input-border rounded-xl shadow-2xl overflow-auto origin-bottom-right">
                    {Object.entries(coins).map(([key]) => (
                      <Menu.Item key={key}>
                        <button
                          key={key}
                          onClick={() => {
                            setCheckValueCoin(key);
                            handleConvert(conversorValues.crypto, key);
                          }}
                          className="group flex gap-x-1 items-center justify-start px-4 py-2 w-full hover:text-brand-royalbluemedium text-brand-white font-poppins text-sm border-0 border-b border-dashed border-brand-royalblue border-transparent border-opacity-30 transition-all duration-300"
                        >
                          {getSymbolFromCurrency(key.toUpperCase())}

                          <p>{key.toUpperCase()}</p>
                        </button>
                      </Menu.Item>
                    ))}
                  </Menu.Items>
                )}
              </Transition>
            </Menu>
          </div>
        </div>
      </div>
    </Layout>
  );
}
Example #27
Source File: Navbar.tsx    From ultimate-saas-ts with MIT License 4 votes vote down vote up
Component = () => {
  const { data: session, status } = useSession();
  const router = useRouter();

  return (
    <Disclosure as="nav" className="bg-white">
      {({ open }) => (
        <>
          <div className="px-2 mx-auto max-w-7xl sm:px-6 lg:px-8">
            <div className="relative flex justify-between h-16">
              <div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
                <Disclosure.Button className="inline-flex items-center justify-center p-2 text-gray-400 rounded-md hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
                  <span className="sr-only">Open main menu</span>
                  {open ? (
                    <XIcon className="block w-6 h-6" aria-hidden="true" />
                  ) : (
                    <MenuIcon className="block w-6 h-6" aria-hidden="true" />
                  )}
                </Disclosure.Button>
              </div>
              <div className="flex items-center justify-center flex-1 sm:items-stretch sm:justify-start">
                <div className="flex items-center flex-shrink-0">
                  <img
                    className="block w-auto h-8 lg:hidden"
                    src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"
                    alt="Workflow"
                  />
                  <img
                    className="hidden w-auto h-8 lg:block"
                    src="https://tailwindui.com/img/logos/workflow-logo-indigo-600-mark-gray-800-text.svg"
                    alt="Workflow"
                  />
                </div>
                <div className="hidden sm:ml-6 sm:flex sm:space-x-8">
                  <Link href="/">
                    <a
                      className={classNames(
                        'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
                        {
                          'border-indigo-500 text-gray-900':
                            router.pathname === '/',
                          '': router.pathname !== '/',
                        }
                      )}
                    >
                      Pricings
                    </a>
                  </Link>

                  <Link href="/account">
                    <a
                      className={classNames(
                        'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
                        {
                          'border-indigo-500 text-gray-900':
                            router.pathname === '/account',
                          '': router.pathname !== '/account',
                        }
                      )}
                    >
                      Account
                    </a>
                  </Link>
                </div>
              </div>
              <div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
                {/* Profile dropdown */}
                {status === 'authenticated' ? (
                  <Menu as="div" className="relative ml-3">
                    <div>
                      <Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                        <span className="sr-only">Open user menu</span>
                        <img
                          className="w-8 h-8 rounded-full"
                          src={
                            session?.user?.image ||
                            'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
                          }
                          alt=""
                        />
                      </Menu.Button>
                    </div>
                    <Transition
                      as={Fragment}
                      enter="transition ease-out duration-200"
                      enterFrom="transform opacity-0 scale-95"
                      enterTo="transform opacity-100 scale-100"
                      leave="transition ease-in duration-75"
                      leaveFrom="transform opacity-100 scale-100"
                      leaveTo="transform opacity-0 scale-95"
                    >
                      <Menu.Items className="absolute right-0 w-48 py-1 mt-2 origin-top-right bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
                        <Menu.Item>
                          {({ active }) => (
                            <Link href="/account">
                              <a
                                className={classNames(
                                  active ? 'bg-gray-100' : '',
                                  'block px-4 py-2 text-sm text-gray-700'
                                )}
                              >
                                Account
                              </a>
                            </Link>
                          )}
                        </Menu.Item>
                        <Menu.Item>
                          {({ active }) => (
                            <a
                              onClick={() => signOut()}
                              className={classNames(
                                active ? 'bg-gray-100' : '',
                                'block px-4 py-2 text-sm text-gray-700'
                              )}
                            >
                              Sign out
                            </a>
                          )}
                        </Menu.Item>
                      </Menu.Items>
                    </Transition>
                  </Menu>
                ) : (
                  <Link href="/api/auth/signin">
                    <a>Sign in</a>
                  </Link>
                )}
              </div>
            </div>
          </div>

          <Disclosure.Panel className="sm:hidden">
            <div className="pt-2 pb-4 space-y-1">
              {/* Current: "bg-indigo-50 border-indigo-500 text-indigo-700", Default: "border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700" */}

              <Link href="/">
                <a className="block py-2 pl-3 pr-4 text-base font-medium text-indigo-700 border-l-4 border-indigo-500 bg-indigo-50">
                  Pricings
                </a>
              </Link>
              <Link href="/account">
                <a className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700">
                  Account
                </a>
              </Link>
            </div>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}
Example #28
Source File: SendEth.tsx    From pali-wallet with MIT License 4 votes vote down vote up
SendEth = () => {
  const controller = getController();

  const { alert, navigate } = useUtils();
  const { activeAccount } = useStore();
  const [selectedAsset, setSelectedAsset] = useState<any | null>(null);
  const [recommendedGasPrice, setRecommendedGasPrice] = useState(0);
  const [recommendedGasLimit, setRecommendedGasLimit] = useState(0);
  const [feeValue, setFeeValue] = useState(0);
  const [editGas, setEditGas] = useState(false);
  const [form] = Form.useForm();

  const { convertGasFee } = feeUtils();

  const getRecomendedFees = useCallback(async () => {
    const gasPrice =
      await controller.wallet.account.eth.tx.getRecommendedGasPrice(false);
    const gasLimit = await controller.wallet.account.eth.tx.getGasLimit();

    setRecommendedGasPrice(gasPrice);
    setRecommendedGasLimit(gasLimit);
    setFeeValue(gasPrice);

    form.setFieldsValue({ baseFee: recommendedGasPrice, gasLimit, gasPrice });
  }, [controller.wallet.account]);

  useEffect(() => {
    getRecomendedFees();
  }, [getRecomendedFees]);

  const hasAccountAssets = activeAccount && activeAccount.assets.length > 0;

  const handleSelectedAsset = (item: string) => {
    if (activeAccount?.assets) {
      const getAsset = activeAccount?.assets.find(
        (asset: any) => asset.contract_address === item
      );

      if (getAsset) {
        setSelectedAsset(getAsset);

        return;
      }

      setSelectedAsset(null);
    }
  };

  const nextStep = ({ receiver, amount, gasPrice, gasLimit }: any) => {
    try {
      navigate('/send/confirm', {
        state: {
          tx: {
            sender: activeAccount.address,
            senderXprv: activeAccount.xprv,
            receivingAddress: receiver,
            amount,
            gasPrice,
            gasLimit,
            fee: Number(convertGasFee(String(feeValue))),
            token: null,
            // token: {
            //   decimals: 18,
            //   contractAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
            // },
          },
        },
      });
    } catch (error) {
      alert.removeAll();
      alert.error('An internal error has occurred.');
    }
  };

  return (
    <>
      {editGas ? (
        <EditGasFee
          setGasFee={setRecommendedGasPrice}
          setEdit={setEditGas}
          form={form}
          setFee={setFeeValue}
        />
      ) : (
        <div className="mt-4">
          <p className="flex flex-col items-center justify-center text-center font-rubik">
            <span className="text-brand-royalblue font-poppins font-thin">
              Balance
            </span>

            {selectedAsset
              ? getAssetBalance(selectedAsset, activeAccount)
              : activeAccount.balances.ethereum}
          </p>

          <Form
            form={form}
            id="send-form"
            labelCol={{ span: 8 }}
            wrapperCol={{ span: 8 }}
            initialValues={{
              baseFee: recommendedGasPrice,
              gasLimit: recommendedGasLimit,
              gasPrice: recommendedGasPrice,
            }}
            onFinish={nextStep}
            autoComplete="off"
            className="standard flex flex-col gap-3 items-center justify-center mt-4 text-center md:w-full"
          >
            <Form.Item
              name="receiver"
              className="md:w-full md:max-w-md"
              hasFeedback
              rules={[
                {
                  required: true,
                  message: '',
                },
                () => ({
                  validator(_, value) {
                    if (!value || isValidEthereumAddress(value)) {
                      return Promise.resolve();
                    }

                    return Promise.reject();
                  },
                }),
              ]}
            >
              <Input type="text" placeholder="Receiver" className="large" />
            </Form.Item>

            <div className="flex items-center justify-center md:w-full md:max-w-md">
              {hasAccountAssets && (
                <Form.Item
                  name="asset"
                  className=""
                  rules={[
                    {
                      required: false,
                      message: '',
                    },
                  ]}
                >
                  <Menu>
                    <div className="relative inline-block text-left">
                      <Menu.Button
                        disabled={!hasAccountAssets}
                        className="inline-flex justify-center mt-3 py-3 w-20 text-white text-sm font-medium bg-fields-input-primary hover:bg-opacity-30 border border-fields-input-border focus:border-fields-input-borderfocus rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"
                      >
                        {selectedAsset?.symbol
                          ? formatUrl(String(selectedAsset?.symbol), 2)
                          : 'ETH'}
                        <ChevronDoubleDownIcon
                          className="text-violet-200 hover:text-violet-100 -mr-1 ml-2 w-5 h-5"
                          aria-hidden="true"
                        />
                      </Menu.Button>

                      <Transition
                        as={Fragment}
                        enter="transition ease-out duration-100"
                        enterFrom="transform opacity-0 scale-95"
                        enterTo="transform opacity-100 scale-100"
                        leave="transition ease-in duration-75"
                        leaveFrom="transform opacity-100 scale-100"
                        leaveTo="transform opacity-0 scale-95"
                      >
                        {hasAccountAssets && (
                          <Menu.Items className="scrollbar-styled absolute z-10 left-0 mt-2 py-3 w-44 h-56 text-brand-white font-poppins bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-lg shadow-2xl overflow-auto origin-top-right">
                            {activeAccount &&
                              Object.values(activeAccount.assets).map(
                                (item: any) => (
                                  <Menu.Item>
                                    <button
                                      onClick={() =>
                                        handleSelectedAsset(
                                          item.contract_address
                                        )
                                      }
                                      className="group flex items-center justify-between px-2 py-2 w-full hover:text-brand-royalblue text-brand-white font-poppins text-sm border-0 border-transparent transition-all duration-300"
                                    >
                                      <p>{item.symbol}</p>
                                    </button>
                                  </Menu.Item>
                                )
                              )}
                          </Menu.Items>
                        )}
                      </Transition>
                    </div>
                  </Menu>
                </Form.Item>
              )}

              <div className="flex flex-col">
                <div className="flex w-full">
                  <label className="flex-1 mr-4 text-xs" htmlFor="gasPrice">
                    Gas Price
                  </label>
                  <label className="flex-1 mr-6 text-xs" htmlFor="gasLimit">
                    Gas Limit
                  </label>
                </div>

                <div
                  className={`${
                    hasAccountAssets ? 'w-48 ml-4' : 'w-72'
                  } flex gap-x-0.5 items-center justify-center md:w-full`}
                >
                  <Form.Item
                    name="gasPrice"
                    className="flex-1 w-32 text-center bg-fields-input-primary rounded-l-full md:w-full"
                    rules={[
                      {
                        required: false,
                        message: '',
                      },
                    ]}
                  >
                    <Input
                      type="text"
                      placeholder="Gas Price (GWEI)"
                      className="p-3 w-full text-sm bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-l-full outline-none md:w-full"
                    />
                  </Form.Item>

                  <Form.Item
                    name="gasLimit"
                    className="flex-1 w-32 text-center bg-fields-input-primary rounded-r-full"
                    rules={[
                      {
                        required: false,
                        message: '',
                      },
                    ]}
                  >
                    <Input
                      type="text"
                      placeholder="Gas Limit"
                      className="p-3 w-full text-sm bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-r-full outline-none md:w-full"
                    />
                  </Form.Item>
                </div>
              </div>
            </div>

            <Form.Item
              name="amount"
              className="md:w-full md:max-w-md"
              hasFeedback
              rules={[
                {
                  required: true,
                  message: '',
                },
                () => ({
                  validator(_, value) {
                    const balance = selectedAsset
                      ? selectedAsset.balance / 10 ** selectedAsset.decimals
                      : Number(activeAccount?.balances.ethereum);

                    if (value > balance) {
                      return Promise.reject();
                    }

                    return Promise.resolve();
                  },
                }),
              ]}
            >
              <Input className="large" type="number" placeholder="Amount" />
            </Form.Item>

            <div className="flex gap-x-0.5 items-center justify-center mx-2 md:w-full md:max-w-md">
              <Form.Item
                name="edit"
                className="w-12 text-center bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-l-full opacity-70 cursor-pointer"
                rules={[
                  {
                    required: false,
                    message: '',
                  },
                ]}
              >
                <Tooltip content="Click to edit fee">
                  <div onClick={() => setEditGas(true)}>
                    <Icon
                      wrapperClassname="w-6 ml-3 mt-1 h-10"
                      name="edit"
                      className="text-brand-royalbluemedium cursor-pointer"
                    />
                  </div>
                </Tooltip>
              </Form.Item>

              <Form.Item
                name="baseFee"
                className="md:w-full"
                hasFeedback
                rules={[
                  {
                    required: true,
                    message: '',
                  },
                ]}
              >
                <Tooltip content="Recommended network base fee">
                  <Input
                    disabled
                    className="block pl-4 pr-8 py-3 w-60 text-brand-white text-sm bg-fields-input-primary border border-fields-input-border rounded-r-full outline-none opacity-50 cursor-not-allowed md:w-full"
                    id="baseFee-input"
                    type="number"
                    placeholder="Base fee"
                    value={recommendedGasPrice}
                  />
                </Tooltip>
              </Form.Item>
            </div>

            <p className="flex flex-col items-center justify-center p-0 max-w-xs text-center text-brand-royalblue sm:w-full md:my-4">
              <span className="text-xs">Amount + fee</span>

              <span className="mt-0.5 text-brand-white font-rubik text-xs">
                {'≈ '}
              </span>
            </p>

            <SecondaryButton type="submit" id="next-btn">
              Next
            </SecondaryButton>
          </Form>
        </div>
      )}
    </>
  );
}
Example #29
Source File: services.tsx    From eventcatalog with MIT License 4 votes vote down vote up
export default function Page({ services }: PageProps) {
  const [servicesToRender, setServicesToRender] = useState(services);
  const [searchFilter, setSearchFilter] = useState('');

  const getFilteredServices = (): any => {
    let filteredServices = services;

    if (searchFilter) {
      filteredServices = filteredServices.filter((service) => service.name.toLowerCase().includes(searchFilter.toLowerCase()));
    }

    return filteredServices;
  };

  useEffect(() => {
    setServicesToRender(getFilteredServices());
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searchFilter]);

  const debouncedFilter = useCallback(
    debounce((e) => {
      setSearchFilter(e.target.value);
    }, 500),
    [servicesToRender]
  );

  const filtersApplied = !!searchFilter;
  const [showMermaidDiagrams, setShowMermaidDiagrams] = useState(false);
  const { title } = useConfig();

  return (
    <>
      <Head>
        <title>{title} - All Services</title>
      </Head>
      <main className="max-w-7xl mx-auto md:min-h-screen px-4 xl:px-0">
        <div className="relative z-10 flex items-baseline justify-between pt-8 pb-6 border-b border-gray-200">
          <h1 className="text-2xl font-extrabold tracking-tight text-gray-900">Services ({services.length})</h1>

          <div className="flex items-center">
            <Menu as="div" className="relative hidden text-left">
              <div>
                <Menu.Button className="group inline-flex justify-center text-sm font-medium text-gray-700 hover:text-gray-900">
                  Sort
                  <ChevronDownIcon
                    className="flex-shrink-0 -mr-1 ml-1 h-5 w-5 text-gray-400 group-hover:text-gray-500"
                    aria-hidden="true"
                  />
                </Menu.Button>
              </div>

              <Transition
                as={Fragment}
                enter="transition ease-out duration-100"
                enterFrom="transform opacity-0 scale-95"
                enterTo="transform opacity-100 scale-100"
                leave="transition ease-in duration-75"
                leaveFrom="transform opacity-100 scale-100"
                leaveTo="transform opacity-0 scale-95"
              >
                <Menu.Items className="origin-top-right absolute right-0 mt-2 w-40 rounded-md shadow-2xl bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
                  <div className="py-1">
                    {sortOptions.map((option) => (
                      <Menu.Item key={option.name}>
                        {({ active }) => (
                          <a
                            href={option.href}
                            className={classNames(
                              option.current ? 'font-medium text-gray-900' : 'text-gray-500',
                              active ? 'bg-gray-100' : '',
                              'block px-4 py-2 text-sm'
                            )}
                          >
                            {option.name}
                          </a>
                        )}
                      </Menu.Item>
                    ))}
                  </div>
                </Menu.Items>
              </Transition>
            </Menu>
          </div>
        </div>

        <section className="pt-6 pb-24">
          <div className="grid grid-cols-4 gap-x-8 gap-y-10">
            {/* Filters */}
            <form className="hidden lg:block">
              <div className="border-b border-gray-200 pb-6">
                <label htmlFor="service" className="font-bold block text-sm font-medium text-gray-700">
                  Search Services
                </label>
                <div className="mt-1 relative rounded-md shadow-sm">
                  <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                    <SearchIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
                  </div>
                  <input
                    type="text"
                    name="service"
                    id="service"
                    onChange={debouncedFilter}
                    className="focus:ring-gray-500 focus:border-gray-500 block w-full pl-10 sm:text-sm border-gray-300 rounded-md"
                  />
                </div>
              </div>

              <div className="border-b border-gray-200 pb-6">
                <h3 className="-my-3 flow-root">
                  <div className="py-3 bg-white w-full flex items-center justify-between text-sm text-gray-400 hover:text-gray-500">
                    <span className="font-medium text-gray-900">Features</span>
                  </div>
                </h3>
                <div className="pt-6">
                  <div className="space-y-4">
                    <div className="flex items-center">
                      <input
                        id="show-mermaid"
                        type="checkbox"
                        onChange={(e) => setShowMermaidDiagrams(e.target.checked)}
                        defaultChecked={showMermaidDiagrams}
                        className="h-4 w-4 border-gray-300 rounded text-gray-600 focus:ring-gray-500"
                      />
                      <label htmlFor="show-mermaid" className="ml-3 text-sm text-gray-600">
                        Show Mermaid Diagrams
                      </label>
                    </div>
                  </div>
                </div>
              </div>
            </form>

            <div className="col-span-4 lg:col-span-3">
              <div>
                <h2 className="text-gray-500 text-xs font-medium uppercase tracking-wide">
                  {filtersApplied
                    ? `Filtered Services (${servicesToRender.length}/${services.length})`
                    : `All Services (${services.length})`}
                </h2>
                <ServiceGrid services={servicesToRender} showMermaidDiagrams={showMermaidDiagrams} />
                {servicesToRender.length === 0 && (
                  <div className="text-gray-400 flex h-96  justify-center items-center">
                    <div>
                      <SearchIcon className="w-6 h-6 inline-block mr-1" />
                      No services found.
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>
        </section>
      </main>
    </>
  );
}