framer-motion#AnimatePresence TypeScript Examples

The following examples show how to use framer-motion#AnimatePresence. 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: motion.tsx    From notebook with MIT License 6 votes vote down vote up
AnimatePage = ({ children }) => {
  return (
    <AnimatePresence initial={true} exitBeforeEnter>
      <MotionBox
        as="main"
        animate="enter"
        exit="exit"
        flexGrow={1}
        initial="initial"
        variants={{
          initial: { opacity: 0, y: -200 },
          enter: { opacity: 1, y: 0 },
          exit: { opacity: 0, y: 250 }
        }}
      >
        {children}
      </MotionBox>
    </AnimatePresence>
  );
}
Example #2
Source File: Demo.tsx    From postel with MIT License 6 votes vote down vote up
DemoCaret = React.forwardRef((props: DemoCaretProps, ref: any) => {
  const motionProps = props.animated && {
    initial: { scale: 1, opacity: 0 },
    animate: { scale: 1, opacity: 1 },
    exit: { scale: 0.8, opacity: 0 },
    transition: {
      ease: "easeInOut",
      duration: 0.1,
    },
  };

  return (
    <AnimatePresence>
      {!props.isTransitioningOut && (
        <div
          ref={ref}
          style={{
            filter: "drop-shadow(rgba(50, 50, 0, 0.5) -1px 16px 6px)",
          }}
        >
          <motion.div
            {...motionProps}
            style={{
              height: 10,
              width: 10,
              background: props.caretColor,
              clipPath: "polygon(100% 0, 0% 100%, 100% 100%)",
            }}
          ></motion.div>
        </div>
      )}
    </AnimatePresence>
  );
})
Example #3
Source File: _app.tsx    From samuelkraft-next with MIT License 6 votes vote down vote up
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
  const router = useRouter()

  useEffect(() => {
    const handleRouteChange = (url: string) => {
      gtag.pageview(url)
    }
    router.events.on('routeChangeComplete', handleRouteChange)
    return () => {
      router.events.off('routeChangeComplete', handleRouteChange)
    }
  }, [router.events])
  return (
    <ThemeProvider defaultTheme="system">
      <SEO />
      <Head>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <AnimatePresence initial={false}>
        <Component {...pageProps} key={router.route} />
      </AnimatePresence>
    </ThemeProvider>
  )
}
Example #4
Source File: Loading.tsx    From rcvr-app with GNU Affero General Public License v3.0 6 votes vote down vote up
Loading: React.FC<Props> = ({ show = false }) => {
  const transition = {
    ease: 'easeInOut',
    yoyo: Infinity,
    duration: 0.6,
  }

  return (
    <AnimatePresence>
      {show && (
        <Overlay
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          css={{ pointerEvents: show ? 'initial' : 'none' }}
        >
          {[0, 1, 2].map((i) => (
            <motion.div
              key={i}
              animate={{ y: -40 }}
              initial={{ y: 40 }}
              transition={{ ...transition, delay: i * 0.15 }}
            >
              <Dot />
            </motion.div>
          ))}
        </Overlay>
      )}
    </AnimatePresence>
  )
}
Example #5
Source File: Modal.tsx    From Meshtastic with GNU General Public License v3.0 6 votes vote down vote up
Modal = ({ open, onClose, children }: ModalProps): JSX.Element => {
  return (
    <AnimatePresence initial={false} exitBeforeEnter={true}>
      <Dialog
        as="div"
        className="fixed inset-0 z-10 overflow-y-auto"
        open={open}
        onClose={onClose}
      >
        <div className="min-h-screen px-0.5 text-center md:px-4">
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          >
            <Dialog.Overlay className="fixed inset-0 backdrop-blur-md" />
          </motion.div>

          <span
            className="inline-block h-screen align-middle"
            aria-hidden="true"
          >
            &#8203;
          </span>
          <div className="inline-block w-full transform text-left align-middle transition-all 2xl:max-w-7xl">
            <div className="group relative">
              <div className="animate-tilt absolute -inset-0.5 rotate-2 rounded-lg bg-accent shadow-md transition duration-1000 group-hover:opacity-100 group-hover:duration-200"></div>
              <div className="relative flex flex-col overflow-hidden rounded-2xl bg-base shadow-md md:aspect-[2/1] md:flex-row md:bg-primary">
                {children}
              </div>
            </div>
          </div>
        </div>
      </Dialog>
    </AnimatePresence>
  );
}
Example #6
Source File: back-button.tsx    From bitpay-browser-extension with MIT License 6 votes vote down vote up
BackButton: React.FC<{ show: boolean; onClick: () => void }> = ({ show, onClick }) => (
  <AnimatePresence>
    {show && (
      <motion.button
        key="BackButton"
        initial={{ opacity: 0, x: -20 }}
        animate={{ opacity: 1, x: 0, y: -1, transition: { duration: 0.1 } }}
        exit={{ opacity: 0, x: FrameDimensions.width * -3 }}
        className="back-button"
        type="button"
        onClick={onClick}
      >
        <img alt="go back" src="../assets/icons/go-back-icon.svg" />
        <span className="back-button--text">Back</span>
      </motion.button>
    )}
  </AnimatePresence>
)
Example #7
Source File: note-modal.tsx    From notebook with MIT License 6 votes vote down vote up
NoteModal: React.SFC<NoteFormProps> = ({
  isOpen,
  onClose,
  selectedNote
}) => {
  return (
    <AnimatePresence>
      <motion.div layoutId={selectedNote?.id}>
        <Modal
          isOpen={isOpen}
          onClose={onClose}
          scrollBehavior={"inside"}
          isCentered
          motionPreset="slideInBottom"
        >
          <ModalOverlay />
          <ModalContent>
            <motion.div>
              <ModalHeader isTruncated paddingRight="10">
                {selectedNote?.title}
              </ModalHeader>
            </motion.div>
            <ModalCloseButton />
            <motion.div>
              <ModalBody pb={6}>{selectedNote?.body}</ModalBody>
            </motion.div>
          </ModalContent>
        </Modal>
      </motion.div>
    </AnimatePresence>
  );
}
Example #8
Source File: Main.tsx    From Intro_to_React with GNU General Public License v2.0 6 votes vote down vote up
Main = () => {
  return (
    <main>
      <AnimatePresence>
        <Switch>
          <Route path="/:mission_id" component={Detail} />
          <Route path="/" component={SpaceX} />
        </Switch>
      </AnimatePresence>
    </main>
  )
}
Example #9
Source File: History.tsx    From useDApp with MIT License 6 votes vote down vote up
TransactionsList = () => {
  const { transactions } = useTransactions()
  return (
    <TableWrapper title="Transactions history">
      <AnimatePresence initial={false}>
        {transactions.map((transaction) => (
          <ListElement
            transaction={transaction.transaction}
            title={transaction.transactionName}
            icon={TransactionIcon(transaction)}
            key={transaction.transaction.hash}
            date={transaction.submittedAt}
          />
        ))}
      </AnimatePresence>
    </TableWrapper>
  )
}
Example #10
Source File: index.tsx    From gatsby-markdown-typescript-personal-website with MIT License 6 votes vote down vote up
Layout: React.FC<Props> = ({ children }) => {
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `);

  return (
    <>
      <GlobalStyles />
      <AnimatePresence exitBeforeEnter>
        <Styled.Layout>
          <Header siteTitle={data.site.siteMetadata.title} />
          <motion.div
            initial={{ y: 30, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ delay: 0.2 }}
          >
            {children}
            <Newsletter />
            <Footer />
          </motion.div>
        </Styled.Layout>
      </AnimatePresence>
    </>
  );
}
Example #11
Source File: IconGridItem.tsx    From phosphor-home with MIT License 5 votes vote down vote up
IconGridItem: React.FC<IconGridItemProps> = (props) => {
  const { index, originOffset, entry } = props;
  const { name, Icon } = entry;
  const [open, setOpen] = useRecoilState(iconPreviewOpenAtom);
  const isOpen = open === name;
  const isNew = entry.tags.includes("*new*");
  const isUpdated = entry.tags.includes("*updated*");
  const delayRef = useRef<number>(0);
  const offset = useRef({ top: 0, left: 0 });
  const ref = useRef<any>();

  const handleOpen = () => setOpen(isOpen ? false : name);

  // The measurement for all elements happens in the layoutEffect cycle
  // This ensures that when we calculate distance in the effect cycle
  // all elements have already been measured
  useLayoutEffect(() => {
    const element = ref.current;
    if (!element) return;

    offset.current = {
      top: element.offsetTop,
      left: element.offsetLeft,
    };

    if (index === originIndex) {
      originOffset.current = offset.current;
    }
  }, [index, originOffset]);

  useEffect(() => {
    const dx = Math.abs(offset.current.left - originOffset.current.left);
    const dy = Math.abs(offset.current.top - originOffset.current.top);
    const d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
    delayRef.current = d * delayPerPixel;
  }, [originOffset]);

  return (
    <>
      <motion.div
        className="grid-item"
        key={name}
        ref={ref}
        tabIndex={0}
        style={{
          order: index,
          backgroundColor: isOpen ? "rgba(163, 159, 171, 0.1)" : undefined,
        }}
        custom={delayRef}
        transition={transition}
        variants={itemVariants}
        onKeyPress={(e) => e.key === "Enter" && handleOpen()}
        onClick={handleOpen}
      >
        <Icon />
        <p>
          {name}
          {isNew && <span className="badge new">•</span>}
          {isUpdated && <span className="badge updated">•</span>}
        </p>
      </motion.div>
      <AnimatePresence initial={false}>
        {isOpen && <DetailsPanel {...props} />}
      </AnimatePresence>
    </>
  );
}
Example #12
Source File: FileBrowser.tsx    From meshtastic-web with GNU General Public License v3.0 5 votes vote down vote up
FileBrowser = (): JSX.Element => {
  const connectionParams = useAppSelector(
    (state) => state.app.connectionParams,
  );
  const appState = useAppSelector((state) => state.app);
  const meshtasticState = useAppSelector((state) => state.meshtastic);

  const { data } = useSWR<Files>(
    `${connectionParams.HTTP.tls ? 'https' : 'http'}://${
      connectionParams.HTTP.address
    }${
      meshtasticState.radio.hardware.firmwareVersion.includes('1.2')
        ? '/json/spiffs/browse/static'
        : '/json/fs/browse/static'
    }`,
    fetcher,
  );

  return (
    <div className="flex h-full p-4">
      <Card
        title="File Browser"
        actions={<Button icon={<FiFilePlus />}>Upload File</Button>}
        className="flex-grow flex-col"
      >
        <div className="h-full px-4">
          <AnimatePresence>
            {(!data || data?.data.files.length === 0) && (
              <div className="flex h-full w-full">
                <m.img
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  className="m-auto h-64 w-64 text-green-500"
                  src={appState.darkMode ? '/Files_Dark.svg' : '/Files.svg'}
                />
              </div>
            )}
          </AnimatePresence>
          {data?.data.files.map((file) => (
            <div
              key={file.name}
              className="flex h-10 w-full border-b border-gray-400 px-4 font-medium dark:border-gray-600 dark:text-white"
            >
              <div className="my-auto  w-1/3">
                <a
                  target="_blank"
                  rel="noopener noreferrer"
                  href={`${connectionParams.HTTP.tls ? 'https' : 'http'}://${
                    connectionParams.HTTP.address
                  }/${file.name.replace('static/', '')}`}
                >
                  {file.name.replace('static/', '').replace('.gz', '')}
                </a>
              </div>
              <div className="my-auto  w-1/3"></div>
            </div>
          ))}
        </div>
      </Card>
    </div>
  );
}
Example #13
Source File: TransactionForm.tsx    From useDApp with MIT License 5 votes vote down vote up
StatusAnimation = ({ transaction }: StatusAnimationProps) => {
  const [showTransactionStatus, setShowTransactionStatus] = useState(false)
  const [timer, setTimer] = useState(
    setTimeout(() => {
      void 0
    }, 1)
  )

  useEffect(() => {
    setShowTransactionStatus(true)
    clearTimeout(timer)

    if (transaction.status != 'Mining') setTimer(setTimeout(() => setShowTransactionStatus(false), 5000))
  }, [transaction])

  return (
    <AnimationWrapper>
      <AnimatePresence initial={false} exitBeforeEnter>
        {showTransactionStatus && transactionErrored(transaction) && (
          <StatusBlock
            color={Colors.Red['400']}
            text={transaction?.errorMessage || ''}
            icon={<ExclamationIcon />}
            key={transaction?.chainId + transaction.status}
          />
        )}
        {showTransactionStatus && transaction.status === 'Mining' && (
          <StatusBlock
            color="black"
            text="Transaction is being mined"
            icon={<SpinnerIcon />}
            key={transaction?.chainId + transaction.status}
          />
        )}
        {showTransactionStatus && transaction.status === 'Success' && (
          <StatusBlock
            color="green"
            text="Transaction successful"
            icon={<CheckIcon />}
            key={transaction?.chainId + transaction.status}
          />
        )}
      </AnimatePresence>
    </AnimationWrapper>
  )
}
Example #14
Source File: Modal.tsx    From chroma-react with MIT License 5 votes vote down vote up
Modal = React.forwardRef<HTMLDivElement, ModalProps>(
  (
    {
      allowPinchZoom,
      isFullScreen,
      isOpen,
      onDismiss,
      disableDismissOnClickOutside,
      size = 0,
      overlayClassName,
      ...rootProps
    },
    ref
  ) => {
    const ownRef = React.useRef(null);

    // If a ref is forwarded, use it; otherwise, use ourselves as the ref
    const thisRef = ref || ownRef;

    return (
      <AnimatePresence>
        {isOpen ? (
          <Overlay
            overlayClassName={overlayClassName}
            allowPinchZoom={allowPinchZoom}
            isOpen={isOpen}
            onDismiss={onDismiss}
            disableDismissOnClickOutside={disableDismissOnClickOutside}
          >
            {isFullScreen ? (
              <FullScreenContent
                ref={thisRef}
                size={size}
                onDismiss={onDismiss}
                {...rootProps}
              />
            ) : (
              <Content
                ref={thisRef}
                size={size}
                onDismiss={onDismiss}
                {...rootProps}
              />
            )}
          </Overlay>
        ) : null}
      </AnimatePresence>
    );
  }
)
Example #15
Source File: ToastNotification.tsx    From website with MIT License 5 votes vote down vote up
ToastNotification: React.FC<ToastNotificationProps> = ({
  children,
  type,
  onDidDismiss,
}) => {
  const [show, setShow] = useState(true);
  const [didDismiss, setDidDismiss] = useState(false);
  const backgroundColorClass = getBackgroundColorClass(type);
  useEffect(() => {
    let timeoutDismiss = null;
    let timeoutHide = null;
    if (show) {
      timeoutHide = setTimeout(() => {
        setShow(false);
      }, showTime);
    } else {
      if (!didDismiss)
        timeoutDismiss = setTimeout(() => {
          setDidDismiss(true);
          onDidDismiss();
        }, delayByAnimation);
    }
    return () => {
      clearTimeout(timeoutHide);
      clearTimeout(timeoutDismiss);
    };
  }, [show, onDidDismiss, didDismiss]);

  return (
    <AnimatePresence>
      {show && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className={`fixed top-12 max-w-md w-11/12 rounded-lg overflow-hidden mx-auto inset-x-0 flex justify-center items-center 
                     ${backgroundColorClass} text-primary text-sm font-bold px-4 py-3 mt-2`}
          role="alert"
          onClick={() => setShow(false)}
        >
          <ToastNotificationIcon type={type} />
          {children}
        </motion.div>
      )}
    </AnimatePresence>
  );
}
Example #16
Source File: AllActions.tsx    From nosgestesclimat-site with MIT License 5 votes vote down vote up
List = ({
	actions,
	rules,
	bilans,
	actionChoices,
	focusedAction,
	focusAction,
}) => (
	<ul
		css={`
			display: flex;
			justify-content: center;
			align-items: center;
			flex-wrap: wrap;
			list-style-type: none;
			padding-left: 0;
		`}
	>
		<AnimatePresence>
			{actions.map((evaluation) => {
				const cardComponent = (
					<motion.li
						key={evaluation.dottedName}
						layoutId={evaluation.dottedName}
						animate={{ scale: 1 }}
						initial={{ scale: 0.8 }}
						exit={{ scale: 0.2 }}
						transition={{ duration: 1 }}
						css={`
							width: 11rem;
							height: 16rem;
							margin: 0.4rem;

							@media (min-width: 800px) {
								width: 12rem;
							}
						`}
					>
						<ActionListCard
							focusAction={focusAction}
							focused={focusedAction === evaluation.dottedName}
							key={evaluation.dottedName}
							rule={rules[evaluation.dottedName]}
							evaluation={evaluation}
							total={bilans.length ? bilans[0].nodeValue : null}
						/>
					</motion.li>
				)
				if (focusedAction === evaluation.dottedName) {
					const convId = 'conv'
					return (
						<>
							<motion.li
								key={convId}
								layoutId={convId}
								animate={{ scale: 1 }}
								initial={{ scale: 0.8 }}
								exit={{ scale: 0.2 }}
								transition={{ duration: 0.5 }}
								css={`
									margin-top: 1.6rem 1rem 1rem;
									width: 100%;
									height: auto;
								`}
							>
								<ActionConversation
									key={focusedAction}
									dottedName={focusedAction}
								/>
								<ScrollToElement delay={1000} center />
							</motion.li>
							{cardComponent}
						</>
					)
				}
				return cardComponent
			})}
		</AnimatePresence>
	</ul>
)
Example #17
Source File: ModalBase.tsx    From rcvr-app with GNU Affero General Public License v3.0 5 votes vote down vote up
ModalBase: React.FC<ModalBaseProps & Props> = ({
  open,
  onClose,
  children,
  maxWidth,
  loading,
  title,
  ...rest
}) => {
  const ref = React.useRef()
  const close = React.useCallback(() => {
    if (loading) return
    onClose()
  }, [loading, onClose])
  useClickAway(ref, close)

  React.useEffect(() => {
    if (open) document.body.classList.add('no-scroll')
    if (!open) document.body.classList.remove('no-scroll')
  }, [open])

  return (
    <AnimatePresence>
      {open && (
        <Overlay
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.2 }}
          css={{ pointerEvents: open ? 'initial' : 'none' }}
        >
          <ModalBox
            ref={ref}
            {...rest}
            css={{ maxWidth }}
            initial={{ scale: 1.1 }}
            animate={{ scale: 1 }}
            exit={{ scale: 0.9 }}
          >
            <Loading show={loading} />
            <CloseButton onClose={close} />
            <Box height={4} />
            {title && (
              <Box px={10}>
                <Text variant="h3" textAlign="center">
                  {title}
                </Text>
                <Box height={6} />
              </Box>
            )}
            {children}
          </ModalBox>
        </Overlay>
      )}
    </AnimatePresence>
  )
}
Example #18
Source File: payment.tsx    From bitpay-browser-extension with MIT License 5 votes vote down vote up
Payment: React.FC<RouteComponentProps & {
  user?: BitpayUser;
  setEmail: Dispatch<SetStateAction<string>>;
  purchasedGiftCards: GiftCard[];
  setPurchasedGiftCards: Dispatch<SetStateAction<GiftCard[]>>;
  supportedMerchant?: Merchant;
  initiallyCollapsed: boolean;
}> = ({
  location,
  history,
  user,
  setEmail,
  purchasedGiftCards,
  setPurchasedGiftCards,
  supportedMerchant,
  initiallyCollapsed
}) => {
  const ref = useRef<HTMLDivElement>(null);
  const emailRef = useRef<HTMLInputElement>(null);

  const { amount, invoiceParams, cardConfig, isFirstPage } = location.state as {
    amount: number;
    invoiceParams: GiftCardInvoiceParams;
    cardConfig: CardConfig;
    isFirstPage: boolean;
  };

  const [email, setReceiptEmail] = useState(invoiceParams.email || '');
  const card: UnsoldGiftCard = {
    amount,
    currency: invoiceParams.currency,
    name: cardConfig.name,
    discounts: cardConfig.discounts
  };
  const shouldShowLineItems = !!(
    (cardConfig.discounts && cardConfig.discounts.length) ||
    (cardConfig.activationFees && cardConfig.activationFees.length)
  );
  const onEmailChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
    emailRef.current?.validity.valid ? setReceiptEmail(event.target.value) : setReceiptEmail('');
  };
  useEffect(() => {
    if (initiallyCollapsed && isFirstPage) return;
    resizeToFitPage(ref, 71, 100);
  }, [ref, initiallyCollapsed, isFirstPage]);
  return (
    <div className="payment">
      <div ref={ref}>
        <AnimatePresence initial={false}>
          <CardHeader cardConfig={cardConfig} card={card} />
          {shouldShowLineItems && <LineItems cardConfig={cardConfig} card={card} />}
        </AnimatePresence>
        {!invoiceParams.email && !user && (
          <div className="settings-group">
            <div className="settings-group__label">Email</div>
            <div className="settings-group__input">
              <input type="email" placeholder="[email protected]" autoFocus onChange={onEmailChange} ref={emailRef} />
            </div>
            <div className="settings-group__caption">Email used for purchase receipts and communication</div>
          </div>
        )}
        <PayWithBitpay
          invoiceParams={{ ...invoiceParams, amount, email }}
          cardConfig={cardConfig}
          history={history}
          user={user}
          setEmail={setEmail}
          purchasedGiftCards={purchasedGiftCards}
          setPurchasedGiftCards={setPurchasedGiftCards}
          supportedMerchant={supportedMerchant}
        />
      </div>
    </div>
  );
}
Example #19
Source File: themechanger.tsx    From samuelkraft-next with MIT License 5 votes vote down vote up
ThemeChanger = (): JSX.Element => {
  const [mounted, setMounted] = useState(false)
  const [active, setActive] = useState(false)
  const [hovered, setHovered] = useState('')
  const { setTheme, theme } = useTheme()

  // When mounted on client, now we can show the UI
  useEffect(() => setMounted(true), [])

  if (!mounted) return <div className={styles.wrapper} /> // skeleton on server

  return (
    <AnimateSharedLayout>
      <div className={styles.wrapper}>
        <motion.div layout className={styles.menu}>
          <AnimatePresence initial={false}>
            {active && (
              <motion.div
                layout
                initial={{ borderRadius: 26, opacity: 0, scale: 0.9 }}
                exit={{ opacity: 0, scale: 0.9 }}
                animate={{ opacity: 1, scale: 1 }}
                className={styles.bg}
              />
            )}
            {variants.map(variant => {
              const selected = theme === variant
              const isHovered = hovered === variant
              return (
                <Fragment key={variant}>
                  {(selected || active) && (
                    <motion.button
                      onHoverStart={() => setHovered(variant)}
                      layout
                      animate={{ opacity: 1, scale: 1 }}
                      exit={{ opacity: 0, scale: 0.85 }}
                      initial={{ opacity: 0, scale: 0.85 }}
                      type="button"
                      title={variant}
                      key={variant}
                      className={styles.button}
                      onClick={() => {
                        if (!active) {
                          return setActive(true)
                        }
                        setActive(false)
                        return setTheme(variant)
                      }}
                    >
                      {((!active && selected) || isHovered) && (
                        <motion.span layoutId="buttonBackground" className={styles.buttonBackground} />
                      )}
                      <span className={styles.buttonLabel}>{getIcon(variant)}</span>
                    </motion.button>
                  )}
                </Fragment>
              )
            })}
          </AnimatePresence>
        </motion.div>
      </div>
    </AnimateSharedLayout>
  )
}
Example #20
Source File: index.tsx    From frontend-boilerplate with MIT License 5 votes vote down vote up
export default function Home() {
  const [isOpen, setOpen] = useState<boolean>(false);
  const toggleModal = () => setOpen(!isOpen);
  return (
    <DefaultLayout title={'Index'}>
      <Layout.Container center>
        <div className={'pt-12 md:pt-20 text-center'}>
          <h1 className={'font-bold text-white text-3xl md:text-5xl mb-8'}>
            React, Next.js & TailwindCSS
          </h1>
          <h2 className={'text-lg text-on-naked-50'}>
            Don't waste time structuring or setting up interfaces on your next
            project!
          </h2>
        </div>
        <Button.Group className="flex mt-12 space-y-5 sm:space-y-0 sm:space-x-5">
          <Button.Primary
            title={`Open modal`}
            size="xl"
            className="!px-6"
            onClick={() => toggleModal()}
          />
        </Button.Group>
      </Layout.Container>
      <AnimatePresence>
        {isOpen && (
          <Modal.Default open={isOpen} onClose={() => toggleModal()}>
            <Modal.Title onClose={() => toggleModal()}>Title</Modal.Title>
            <Modal.Body>
              <h1 className="text-[17px] font-semibold text-on-naked-100">
                Did you know that..?
              </h1>
              {[...Array(30)].map(() => (
                <h3 className="mt-1 text-base text-on-naked-800">
                  There is a technical name for the "fear of long words."
                </h3>
              ))}
            </Modal.Body>
            <Modal.Footer>
              <h4 className="text-sm text-center xs:text-left">
                This is my cute little footer!
              </h4>
              <div
                className="flex items-center justify-center px-5 py-3 mt-4 mb-5 font-semibold text-white rounded-full xs:hidden bg-types-200"
                onClick={() => toggleModal()}
              >
                Close
              </div>
            </Modal.Footer>
          </Modal.Default>
        )}
      </AnimatePresence>
    </DefaultLayout>
  );
}
Example #21
Source File: LastCheckins.tsx    From rcvr-app with GNU Affero General Public License v3.0 4 votes vote down vote up
LastCheckins: React.FC<Props> = ({ checkins, onCheckout }) => {
  const [checkin] = checkins

  const { t } = useLocaleObject(LastCheckinsLocales)
  const area = useArea(checkins[0].areaId).data
  const checkedOut = !!checkin.leftAt
  const idRef = React.useRef<string>(uuidv4())
  const [showProxyCheckin, setShowProxyCheckin] = React.useState(false)
  const [isLoading, setLoading] = React.useState(false)
  const [showEditData, setShowEditData] = React.useState(false)

  const queryClient = useQueryClient()

  const mutation = useMutation(checkinAction)

  const handleEditGuest = (guest, _opts) => {
    setLoading(true)
    updateCurrentGuest(queryClient, guest).then((_checkin) => {
      setLoading(false)
      setShowEditData(false)
    })
  }

  const proxyCheckin = React.useCallback(
    async (guest: Guest) => {
      const id = idRef.current

      try {
        setLoading(true)

        const ticket = {
          ...checkin,
          id,
          publicKey: area.publicKey,
          encryptedData: null,
          proxyCheckin: true,
          enteredAt: new Date(),
        }

        await mutation.mutateAsync({ ticket, guest })

        idRef.current = uuidv4() // add a new one for the next
        await queryClient.invalidateQueries('checkins')
        setShowProxyCheckin(false)
        setLoading(false)
      } catch (error) {
        console.error(error)
      }
    },
    [checkin, setShowProxyCheckin, area, queryClient, mutation]
  )

  return (
    <Container>
      <Box height={16} />
      <Circle animated delay={0.5} color={checkedOut ? 'pink' : 'green'}>
        {checkedOut ? (
          <Thumb delay={0.8} />
        ) : (
          <Check delay={0.8} css={{ position: 'relative', top: 2 }} />
        )}
      </Circle>
      <Box height={4} />
      <Text variant="h2">
        {checkedOut ? t('header_checkedOut') : t('header')}
      </Text>
      <Box height={1} />
      <Text variant="h4" data-wfd-location={checkin.business}>
        {checkin.business}
      </Text>
      {checkins.length > 1 && (
        <>
          <Box height={1} />
          <Text variant="h4">
            {checkins.length} {t('people')}
          </Text>
        </>
      )}
      <Box height={4} />
      <CheckinDates from={checkin.enteredAt} to={checkin.leftAt} />
      {!checkedOut && checkin.cwaLinkEnabled && checkin.cwaSeed && (
        <>
          <Box height={4} />
          <ButtonLink
            href={generateCwaLink(checkin)}
            name="cwaCheckinUrl"
            target="_blank"
          >
            <CwaLink>
              <CwaLogo width="24" height="24" />
              {t('CWALinkText')}
            </CwaLink>
          </ButtonLink>
          <Box height={4} />
        </>
      )}
      <Box height={2} />
      {checkins
        .map(({ guest }) => guest)
        .filter((guest) => guest != null)
        .map((guest, index) => (
          <GuestDetails key={index}>
            {index > 0 && <Box height={2} />}
            <Text variant="label" as="label">
              {t('name')}{' '}
              <Text variant="regular" as="span">
                {guest.name}
              </Text>
            </Text>
            <Box height={1} />
            <Text variant="label" as="label">
              {t('address')}{' '}
              <Text variant="regular" as="span">
                {guest.address}, {guest.postalCode}&nbsp;{guest.city}
              </Text>
            </Text>
            <Box height={1} />
            <Text variant="label" as="label">
              {t('telephone')}{' '}
              <Text variant="regular" as="span">
                {guest.phone}
              </Text>
            </Text>
            <Box height={1} />
          </GuestDetails>
        ))}
      <AnimatePresence>
        {!checkin.leftAt && (
          <motion.div
            css={{ width: '100%' }}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          >
            <Box height={8} />
            <Button
              css={{ width: '100%' }}
              left={<ArrowsRight color="pink" />}
              right={<ArrowsLeft color="pink" />}
              onClick={() => onCheckout(checkins)}
              dataAttributes={{ 'wfd-action': 'check-out' }}
            >
              {t('checkOutButtonText')}
            </Button>
            <Box height={4} />
            <Button
              css={{ width: '100%' }}
              onClick={() => setShowEditData(!showEditData)}
            >
              {t('changeYourDataButtonText')}
            </Button>
            <Box height={4} />
            {showEditData && (
              <Onboarding
                area={area}
                onSubmit={handleEditGuest}
                hideRememberMe={true}
                prefilledGuest={checkin.guest}
                submitButtonValue={t('onboardingButtonText')}
              />
            )}
            <Loading show={isLoading} />
            <Box height={8} />
            {showProxyCheckin ? (
              <>
                <Box height={4} />
                <Text variant="h3">{t('checkInMorePeopleHeadline')}</Text>
                <Box height={2} />
                <Onboarding
                  area={area}
                  prefilledGuest={{
                    address: checkin.guest?.address,
                    postalCode: checkin.guest?.postalCode,
                    city: checkin.guest?.city,
                    phone: checkin.guest?.phone,
                  }}
                  hideRememberMe={true}
                  onSubmit={proxyCheckin}
                  onAbort={() => setShowProxyCheckin(false)}
                />
              </>
            ) : (
              <Button
                css={{ width: '100%', marginTop: '10px' }}
                onClick={() => setShowProxyCheckin(true)}
              >
                {t('addPersonButtonText')}
              </Button>
            )}
          </motion.div>
        )}
      </AnimatePresence>
      <AnimatePresence>
        {!checkin.leftAt && area?.menuLink && (
          <motion.div
            css={{ width: '100%' }}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          >
            <Box height={4} />
            <a href={area.menuLink} target="_blank" rel="noopener noreferrer">
              <Button as="div" css={{ width: '100%' }}>
                {area.menuAlias || t('additionalInfoLinkText')}
              </Button>
            </a>
          </motion.div>
        )}
      </AnimatePresence>
    </Container>
  )
}
Example #22
Source File: QRExpandedState.tsx    From rainbow-button with MIT License 4 votes vote down vote up
QRExpandedState = ({
  enabled,
  value,
  setIsQRCodeOpen,
}: {
  enabled: boolean;
  value: string;
  setIsQRCodeOpen: Dispatch<SetStateAction<boolean>>;
}) => {
  return (
    <AnimatePresence>
      {enabled && (
        <>
          <UniqueTokenExpandedStateContent key={value}>
            <motion.div
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              initial={{ opacity: 0 }}
              transition={easingConfig}
            >
              <ExpandedStateBackground
                onClick={() => setIsQRCodeOpen(false)}
                opacity={0.8}
              />
            </motion.div>
            <ExpandedState
              animate={{ scale: 1, y: 0 }}
              as={motion.div}
              exit={{ scale: 0.8, y: '100vh' }}
              initial={{ scale: 0.8, y: '100vh' }}
              qr
              style={{ pointerEvents: 'auto' }}
              transition={springConfig}
            >
              <Column
                onClick={() => setIsQRCodeOpen(false)}
                style={{ height: '100%', justifyContent: 'center' }}
              >
                <TitleText>
                  <span aria-labelledby="emoji" role="img">
                    ?
                  </span>{' '}
                  Scan to connect to Rainbow
                </TitleText>
                <Container onClick={(proxy) => proxy.stopPropagation()}>
                  <QRCode logoSize={100} size={380} value={value} />
                </Container>
                <DownloadContainer>
                  <TitleText subtitle>
                    <span aria-labelledby="emoji" role="img">
                      ?
                    </span>{' '}
                    Don’t have the app yet?{' '}
                    <span aria-labelledby="emoji" role="img">
                      ?
                    </span>
                  </TitleText>
                  <div style={{ display: 'flex', flexDirection: 'row' }}>
                    <DownloadButton
                      href="https://apps.apple.com/us/app/rainbow-ethereum-wallet/id1457119021"
                      onClick={(proxy) => proxy.stopPropagation()}
                      target="_blank"
                    >
                      <div style={{ marginRight: 6 }}>
                        <LogoAppStore />
                      </div>
                      App Store
                    </DownloadButton>
                  </div>
                </DownloadContainer>
              </Column>
            </ExpandedState>
          </UniqueTokenExpandedStateContent>
          <XButtonWrapper onClick={() => setIsQRCodeOpen(false)}>
            <motion.div
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0, scale: 0 }}
              initial={{ opacity: 0, scale: 0 }}
              transition={easingConfig}
            >
              <XButton />
            </motion.div>
          </XButtonWrapper>
        </>
      )}
    </AnimatePresence>
  );
}
Example #23
Source File: Notifications.tsx    From realayers with Apache License 2.0 4 votes vote down vote up
Notifications: FC<NotificationsProps> = ({
  children,
  limit,
  timeout,
  showClose,
  preventFlooding
}) => {
  const [notifications, setNotifications] = useState<any[]>([]);

  const clearNotification = useCallback(
    (id: number) => setNotifications(notifications.filter(n => n.id !== id)),
    [notifications]
  );

  const clearAllNotifications = useCallback(() => setNotifications([]), []);

  const notify = useCallback(
    (title: string, options: NotificationOptions = {}) => {
      // If we are flooded with the same message over and over,
      // dont add more of the same type. Mainly used for error use cases.
      if (preventFlooding) {
        const has = notifications.find(n => n.title === title);

        if (has) {
          return false;
        }
      }

      const id = nextId++;

      const obj = {
        title,
        id,
        variant: 'default',
        timeout,
        showClose,
        ...options
      };

      const sorted = [obj, ...notifications];

      // Clear old notifications if we hit limit
      if (sorted.length >= limit) {
        sorted.pop();
      }

      // Update the container instance
      setNotifications(sorted);

      return id;
    },
    [limit, notifications, preventFlooding, showClose, timeout]
  );

  const notifyError = useCallback(
    (title: string, options: NotificationOptions = {}) =>
      notify(title, { ...options, variant: 'error' }),
    [notify]
  );

  const notifyWarning = useCallback(
    (title: string, options: NotificationOptions = {}) =>
      notify(title, { ...options, variant: 'warning' }),
    [notify]
  );

  const notifySuccess = useCallback(
    (title: string, options: NotificationOptions = {}) =>
      notify(title, { ...options, variant: 'success' }),
    [notify]
  );

  const values = useMemo(
    () => ({
      notify,
      notifyError,
      notifyWarning,
      notifySuccess,
      clearNotification,
      clearAllNotifications
    }),
    [
      clearNotification,
      clearAllNotifications,
      notify,
      notifyError,
      notifySuccess,
      notifyWarning
    ]
  );

  return (
    <Fragment>
      <NotificationsContext.Provider value={values}>
        {children}
      </NotificationsContext.Provider>
      <div className={css.container}>
        <div className={css.positions}>
          <AnimatePresence>
            {!!notifications.length && (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
              >
                {notifications.map(n => (
                  <Notification {...n} key={n.id} onClose={clearNotification} />
                ))}
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      </div>
    </Fragment>
  );
}
Example #24
Source File: project-card.tsx    From portfolio with MIT License 4 votes vote down vote up
ProjectCard: React.FC<ProjectCardProps> = ({
  title,
  description,
  logo,
  blurHash,
  link,
  technologies
}) => {
  const textColor = useColorModeValue("gray.500", "gray.200");
  const [isOpen, setIsOpen] = React.useState(false);
  const toggleOpen = () => setIsOpen(!isOpen);

  return (
    <motion.div layout onClick={toggleOpen}>
      <HStack
        p={4}
        bg={useColorModeValue("white", "gray.800")}
        rounded="xl"
        borderWidth="1px"
        borderColor={useColorModeValue("gray.100", "gray.700")}
        w="100%"
        h="100%"
        textAlign="left"
        align="start"
        spacing={4}
        cursor="pointer"
        _hover={{ shadow: "lg" }}
      >
        <LazyImage
          src={logo}
          blurHash={blurHash}
          size="sm"
          width={33}
          height={33}
          layout="fixed"
          rounded="md"
        />
        <VStack align="start" justify="flex-start">
          <VStack spacing={0} align="start">
            <motion.div layout>
              <HStack>
                <Text
                  as={Link}
                  href={link}
                  fontWeight="bold"
                  fontSize="md"
                  noOfLines={1}
                  onClick={e => e.stopPropagation()}
                  isExternal
                >
                  {title}
                </Text>
                <HStack spacing="1">
                  {technologies.map(tech => (
                    <Tag size="sm" colorScheme={getTagColor(tech)}>
                      {tech}
                    </Tag>
                  ))}
                </HStack>
              </HStack>
            </motion.div>
            <AnimatePresence>
              <motion.div
                layout
                initial={{ opacity: 1 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 1 }}
              >
                {!isOpen && (
                  <Text fontSize="sm" color={textColor} noOfLines={{ base: 2 }}>
                    {description}
                  </Text>
                )}
              </motion.div>
            </AnimatePresence>

            <AnimatePresence>
              <motion.div
                layout
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                variants={{ exit: { transition: { staggerChildren: 0.1 } } }}
              >
                {isOpen && (
                  <Text
                    fontSize="sm"
                    color={textColor}
                    // noOfLines={{ base: isOpen ? 5 : 2 }}
                  >
                    {description}
                  </Text>
                )}
              </motion.div>
            </AnimatePresence>
          </VStack>
        </VStack>
      </HStack>
    </motion.div>
  );
}
Example #25
Source File: navbar.tsx    From next-mdx with MIT License 4 votes vote down vote up
export function Navbar() {
  const [showMenu, setShowMenu] = React.useState(false)
  const [colorMode, setColorMode] = useColorMode()

  return (
    <header
      borderBottomWidth="1px"
      position="relative|sticky"
      top="0"
      zIndex="1000"
      sx={{
        ":after": {
          content: '""',
          position: "absolute",
          top: 0,
          left: 0,
          w: "full",
          h: "100%",
          zIndex: 10,
          bg: "background",
          opacity: "0.85",
          backdropFilter: "saturate(100%) blur(10px)",
        },
      }}
    >
      <div
        variant="container"
        display="flex"
        alignItems="center"
        h="14"
        position="relative"
        zIndex="1000"
      >
        <button
          display="block|block|block|none"
          mr="2"
          onClick={() => setShowMenu(!showMenu)}
          color="text"
        >
          <Icon name="menu-alt" size="6" />
        </button>
        <Link href="/" passHref>
          <a
            display="none|flex"
            textDecoration="none"
            color="text"
            alignItems="center"
            fontSize="md|||xl"
            fontWeight="semibold"
            mr="0|0|0|10"
          >
            <Icon name="logo" size="6" mr="2" />
            {site.name}
          </a>
        </Link>
        <div
          display="none|none|none|inline-grid"
          col={`repeat(${site.links.length}, minmax(0,auto))`}
          gap="8"
        >
          {site.links.map((link, index) => (
            <NavbarLink
              key={index}
              href={link.url}
              external={link.external}
              activePathNames={link.activePathNames}
            >
              {link.title}
            </NavbarLink>
          ))}
        </div>
        <div display="flex" ml="0|auto" flex="1|none">
          <DocSearch ml="4" mr="4" flex="1" />
          <a
            href={`https://github.com/${site.social.github}`}
            target="_blank"
            rel="noreferrer"
            variant="button.navbar"
            ml="auto|0"
          >
            <Icon name="github" />
          </a>
          <button
            variant="button.navbar"
            onClick={() =>
              setColorMode(colorMode === "dark" ? "light" : "dark")
            }
          >
            <Icon name={colorMode === "dark" ? "sun" : "moon"} size="5" />
            <VisuallyHidden>Toggle color mode</VisuallyHidden>
          </button>
        </div>
      </div>
      <AnimatePresence>
        {showMenu ? (
          <motion.div
            initial={{
              opacity: 0,
              x: -50,
            }}
            animate={{
              opacity: 1,
              x: 0,
            }}
            exit={{
              opacity: 0,
              x: -50,
            }}
            transition={{
              ease: "easeInOut",
            }}
            sx={{
              px: 6,
              top: "18|18",
              position: "absolute",
              w: "full",
            }}
          >
            <div
              boxShadow="xl"
              borderWidth="1"
              rounded="lg"
              bg="background"
              w="full"
              h="85vh"
              overflow="scroll"
            >
              <div
                display="grid"
                row={`repeat(${site.links.length}, minmax(0,auto))`}
                gap="2|2|2|8"
                zIndex="100"
                position="relative"
                py="4|4|4|0"
              >
                {site.links.map((link) => (
                  <NavbarLink
                    key={link.url}
                    href={link.url}
                    external={link.external}
                    activePathNames={link.activePathNames}
                    fontWeight="medium"
                    fontSize="xl"
                    py="0"
                  >
                    {link.title}
                  </NavbarLink>
                ))}
              </div>
              <div p="6" borderTopWidth="1">
                <SidebarNav
                  items={docs.links}
                  onLinkClick={() => setShowMenu(false)}
                />
              </div>
            </div>
          </motion.div>
        ) : null}
      </AnimatePresence>
    </header>
  )
}
Example #26
Source File: index.tsx    From color-copy-paste with MIT License 4 votes vote down vote up
IndexPage = () => {
  const controls = useAnimation()
  const controlSlider = useAnimation()
  const controlColor = useAnimation()
  const [color, setColor] = React.useState("#DDDDDD")
  const [colors, setColors] = React.useState([])
  const canvasRef = React.useRef(null)
  const sliderRef = React.useRef(null)

  const renderCanvas = () => {
    try {
      const canvas = canvasRef.current
      var context = canvas.getContext("2d")
      canvas.width = 1080
      canvas.height = 152
      context.drawImage(sliderRef.current, 0, 0, 1080, 152)
    } catch (e) {
      console.log(e)
    }
  }

  React.useEffect(() => {
    controls.start({ x: 720 }, { damping: 300 })
    controlSlider.start({ x: -800 }, { damping: 300 })
    setTimeout(() => renderCanvas(), 500)
    setTimeout(() => renderCanvas(), 1500)
  }, [])

  return (
    <>
      <SEO title="Color Copy Paste" />
      <div
        style={{
          margin: `0 auto`,
          maxWidth: 960,
          padding: `0 1.0875rem 1.45rem`,
        }}
      >
        <div className="header">
          <div className="header-column">
            <div className="header-wrap">
              <img src={Logo} style={{ marginBottom: 16 }} />
              <h1 style={{ display: "none" }}>Color Copy Paste</h1>
              <a
                className="github-button"
                href="https://github.com/sonnylazuardi/color-copy-paste"
                data-size="large"
                data-show-count="true"
                aria-label="Star sonnylazuardi/color-copy-paste on GitHub"
              >
                Star
              </a>
            </div>
          </div>
          <div className="header-column column-two">
            <div className="header-wrap">
              <div className="header-label">
                Copy & paste colour directly from your camera to:
              </div>
              <a
                href="https://www.figma.com/community/plugin/845733021314534317/Camera-Color-Copy-Paste"
                className="button-web button-blue"
              >
                <img className="button-icon" src={IconFigma} />
                Figma Plugin
              </a>
              <a
                href="color-copy-paste.sketchplugin.zip"
                className="button-web button-yellow"
              >
                <img className="button-icon" src={IconSketch} />
                Sketch Plugin
              </a>
              <Link to="app" className="button-web button-yellow">
                <img className="button-icon" src={IconBrowser} />
                Web Browser
              </Link>
            </div>
          </div>
        </div>
        <img
          src={BgSlider}
          ref={sliderRef}
          style={{ width: 1080, height: 152, display: "none" }}
          onLoad={() => renderCanvas()}
        />
        <canvas ref={canvasRef} style={{ display: "none" }}></canvas>
        <img src={BgStatic} className="content-static" />
        <motion.div
          className="content-default"
          onMouseMove={e => {
            function getElementOffset(element) {
              var de = document.documentElement
              var box = element.getBoundingClientRect()
              var left = box.left + window.pageXOffset - de.clientLeft
              return left
            }

            const relativeX = e.pageX - getElementOffset(e.target)
            if (relativeX > 70 && relativeX < 790) {
              controls.start(
                {
                  x: relativeX,
                },
                { damping: 300 }
              )
              controlSlider.start(
                {
                  x: relativeX * -1 - 180,
                },
                { damping: 300 }
              )
              const canvas = canvasRef.current
              var context = canvas.getContext("2d")
              var pixel = context.getImageData(relativeX + 224, 68, 1, 1).data
              controlColor.start({
                backgroundColor: `rgb(${pixel[0]},${pixel[1]},${pixel[2]})`,
              })
              setColor(rgbToHex(pixel[0], pixel[1], pixel[2]))
            }
          }}
          onClick={() => {
            setColors([...colors, color])
          }}
        >
          <div style={{ height: 500, overflow: "hidden" }}>
            <img src={BgDesk} style={{ width: "100%" }} draggable={false} />
          </div>
          <motion.div
            drag="x"
            dragConstraints={{
              left: -100,
              right: 200,
            }}
            animate={controls}
            className="control-hand"
            style={{
              backgroundImage: `url(${Hand})`,
            }}
          >
            <div className="phone-screen">
              <motion.div
                animate={controlSlider}
                className="control-slider"
                style={{
                  backgroundImage: `url(${BgSlider})`,
                }}
              />
            </div>
            <div className="bubble">
              <motion.div animate={controlColor} className="control-color" />
              {color.toUpperCase()}
            </div>
          </motion.div>
          <div className="pallete">
            {colors.length > 0 ? (
              <AnimatePresence>
                 
                <div className="grid-demo">
                  {colors.map((item: any, i: number) => {
                    return (
                      <motion.div
                        key={i}
                        className="color-demo"
                        initial={{ scale: 0 }}
                        animate={{ scale: 1 }}
                        exit={{ scale: 0 }}
                        style={{ backgroundColor: item }}
                        onClick={() => {
                          copyTextToClipboard(item)
                        }}
                      ></motion.div>
                    )
                  })}
                </div>
              </AnimatePresence>
            ) : (
              <div className="empty">
                <img src={IconClick} style={{ marginBottom: 8 }} />
                Click to capture colour
              </div>
            )}
          </div>
        </motion.div>
      </div>
      <div className="section">
        <div
          style={{
            margin: `0 auto`,
            maxWidth: 960,
            padding: `0 1.0875rem 1.45rem`,
          }}
        >
          <div className="row">
            <div className="column">
              <div className="box">
                <h3>How can I copy color?</h3>
                <p>
                  Tap and hold the capture button located in the bottom of your
                  screen. Release to paste it to web browser or plugin.
                </p>
              </div>
            </div>
            <div className="column">
              <div className="box">
                <h3>Where is my color saved?</h3>
                <p>
                  It is saved inside the local storage of the plugin or web
                  browser.
                </p>
              </div>
            </div>
            <div className="column">
              <div className="box">
                <h3>How does my phone connect?</h3>
                <p>
                  The app uses socket to connect phone to your computer. It will
                  generate unique id when showing QR Code.
                </p>
              </div>
            </div>
            <div className="column">
              <div className="box">
                <h3>Can I save to color style?</h3>
                <p>
                  Currently not yet, but you can click on the color to change
                  the object's color and copy the hex code
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          marginTop: 80,
          padding: 16,
        }}
      >
        <blockquote className="twitter-tweet" data-theme="dark">
          <a href="https://twitter.com/sonnylazuardi/status/1263895972456697856">
            @sonnylazuardi
          </a>
        </blockquote>
      </div>

      <div className="section-dark">
        <div
          style={{
            margin: `0 auto`,
            maxWidth: 960,
            padding: `0 1.0875rem 1.45rem`,
          }}
        >
          <h2>What others are saying</h2>
          <div className="row">
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar1})` }}
                />

                <div className="card-comment">
                  Well this just might be the coolest plugin I've ever reviewed.
                  :) Great job on this.
                </div>
                <div className="card-name">Josh, Figma Review</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar2})` }}
                />

                <div className="card-comment">
                  Get the inspiration from nature, so... going out door to pick
                  colour
                </div>
                <div className="card-name">Clu, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar7})` }}
                />

                <div className="card-comment">
                  Yeah nooo! This is some crazy stuff right here @sonnylazuardi
                  More reasons why we love the @figmadesign community ?
                </div>
                <div className="card-name">Uche, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar4})` }}
                />

                <div className="card-comment">
                  So cool, moving 3D real world elements into 2D interface or
                  digital world, the boundary is becoming blur.
                </div>
                <div className="card-name">Mi Yuhao, AI UX Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar5})` }}
                />

                <div className="card-comment">This is neat!</div>
                <div className="card-name">Ernest Ojeh, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar6})` }}
                />

                <div className="card-comment">Gokil sekali</div>
                <div className="card-name">Dimas, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar3})` }}
                />

                <div className="card-comment">So goood mas!</div>
                <div className="card-name">Afnizar, UX Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar8})` }}
                />

                <div className="card-comment">
                  @sonnylazuardi built a @figmadesign plugin through a @framer
                  prototype ?
                </div>
                <div className="card-name">
                  Addison, Frontend Dev & Designer
                </div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar9})` }}
                />

                <div className="card-comment">
                  Marvellous plugin as always! Easy to use yet useful. Hats off!
                </div>
                <div className="card-name">Tyas, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar10})` }}
                />

                <div className="card-comment">
                  That’s pretty insane. Great work!
                </div>
                <div className="card-name">
                  Andy Ngo, Designer & Frontend Dev
                </div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar11})` }}
                />

                <div className="card-comment">Sorcery ?‍♂️</div>
                <div className="card-name">Arif Eka, UI Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar12})` }}
                />

                <div className="card-comment">You’re on a roll ?</div>
                <div className="card-name">Gaddafi Rusli, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar14})` }}
                />

                <div className="card-comment">
                  This is amazing! Looking forward to the plugin ?
                </div>
                <div className="card-name">Soliudeen, Product Designer</div>
              </div>
            </div>
            <div className="column">
              <div className="card">
                <div
                  className="card-avatar"
                  style={{ backgroundImage: `url(${avatar13})` }}
                />

                <div className="card-comment">?</div>
                <div className="card-name">Jacky Lee, Product Designer</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div className="section-footer">
        <div className="footer-caption">
          This project was built for fun and to explore what’s possible with
          design plugin. If you like this app, give me a{" "}
          <a href="https://twitter.com/sonnylazuardi">follow on twitter</a>, an
          upvote in{" "}
          <a href="https://www.producthunt.com/posts/color-copy-paste">
            Product Hunt
          </a>{" "}
          or star on{" "}
          <a href="https://github.com/sonnylazuardi/color-copy-paste">github</a>
          . We built this to give back ? to the design community.
        </div>
        <div className="producthunt-wrap">
          <a
            href="https://www.producthunt.com/posts/color-copy-paste?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-color-copy-paste"
            target="_blank"
          >
            <img
              src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=205039&theme=dark&period=daily"
              alt="Color Copy Paste - Copy colors from your phone & paste on web, figma, or sketch | Product Hunt Embed"
              style={{ width: 250, height: 54 }}
              width="250px"
              height="54px"
            />
          </a>
        </div>
        <div className="footer">
          Built by{" "}
          <a href="https://twitter.com/sonnylazuardi">@sonnylazuardi</a> in
          Singapore. Illustrated by{" "}
          <a href="https://dribbble.com/alzea">Alzea Arafat</a>
        </div>
      </div>
    </>
  )
}
Example #27
Source File: carousel.tsx    From notebook with MIT License 4 votes vote down vote up
Carousel: React.SFC<CarouselProps> = ({
  onOpen,
  onClose,
  isOpen,
  repoId
}) => {
  const [[page, direction], setPage] = React.useState([0, 0]);
  const [imageIndex, setImageIndex] = React.useState<number>(0);

  const paginate = (newDirection: number) => {
    setPage([page + newDirection, newDirection]);
  };

  React.useEffect(() => {
    setImageIndex(repoId);
  }, [repoId]);

  const nextImage = (newDirection: number) => {
    paginate(newDirection);
    setImageIndex(imageIndex + 1 < coverImages.length ? imageIndex + 1 : 0);
  };

  const prevImage = (newDirection: number) => {
    paginate(newDirection);
    setImageIndex(
      0 === imageIndex ? coverImages.length - 1 : imageIndex - 1
    );
  };

  return (
    <Modal isCentered onClose={onClose} size={"6xl"} isOpen={isOpen}>
      <ModalOverlay />
      <ModalContent>
        <ModalBody padding="0">
          <div className="carousel-container">
            <AnimatePresence initial={false} custom={direction}>
              <motion.img
                key={page}
                src={coverImages[imageIndex]}
                custom={direction}
                variants={variants}
                initial="enter"
                animate="center"
                exit="exit"
                transition={{
                  x: { type: "spring", stiffness: 300, damping: 30 },
                  opacity: { duration: 0.2 }
                }}
                drag="x"
                dragConstraints={{ left: 0, right: 0 }}
                dragElastic={1}
                onDragEnd={(e, { offset, velocity }) => {
                  const swipe = swipePower(offset.x, velocity.x);

                  if (swipe < -swipeConfidenceThreshold) {
                    paginate(1);
                  } else if (swipe > swipeConfidenceThreshold) {
                    paginate(-1);
                  }
                }}
              />
            </AnimatePresence>
            <div className="next" onClick={() => nextImage(1)}>
              <IconButton
                aria-label="left image"
                icon={<ChevronLeftIcon />}
                cursor="pointer"
                as={ChevronRightIcon}
                size="md"
                colorScheme="teal"
                borderRadius="full"
              />
            </div>

            <div className="prev" onClick={() => prevImage(-1)}>
              <IconButton
                aria-label="right image"
                icon={<ChevronRightIcon />}
                cursor="pointer"
                as={ChevronLeftIcon}
                size="md"
                colorScheme="teal"
                borderRadius="full"
              />
            </div>
          </div>
        </ModalBody>
      </ModalContent>
    </Modal>
  );
}
Example #28
Source File: Snackbar.tsx    From chroma-react with MIT License 4 votes vote down vote up
Snackbar: React.FC<SnackbarProps> = React.forwardRef<
  HTMLDivElement,
  SnackbarProps
>(
  (
    {
      className,
      duration = 6000,
      icon: Icon,
      isOpen = false,
      allowDismiss = false,
      onClose,
      role = 'status',
      statusType = 'info',
      title,
      children,
      ...rootProps
    },
    ref
  ) => {
    const classes = useStyles({});

    const shouldReduceMotion = useReducedMotion();

    const [snackbarTimeout, setSnackbarTimeout] = React.useState<number | null>(
      duration
    );

    // Event handlers
    const onMouseEnter = () => setSnackbarTimeout(null);
    const onMouseLeave = () => setSnackbarTimeout(duration);
    const closeSnackbar = React.useCallback(() => {
      onClose && onClose();
    }, [onClose]);

    // Use a ref to close our Snackbar after the timeout
    const callbackRef = React.useRef<() => void | null>();

    React.useEffect(() => {
      if (!callbackRef.current) {
        callbackRef.current = closeSnackbar;
      }
    }, [closeSnackbar]);

    React.useEffect(() => {
      // Ignore setting up a timer for the Snackbar
      // if one is not isOpen.
      if (!isOpen) {
        return;
      }

      const tick = () => {
        if (callbackRef.current) {
          callbackRef.current();
        }
      };

      if (snackbarTimeout) {
        const id = setTimeout(tick, snackbarTimeout);
        return () => clearTimeout(id);
      }
    }, [snackbarTimeout, isOpen]);

    return (
      <AnimatePresence initial={false}>
        {isOpen ? (
          <motion.div
            ref={ref}
            className={clsx(
              classes.root,
              {
                [classes.infoModifier]: statusType === 'info',
                [classes.errorModifier]: statusType === 'error',
                [classes.warningModifier]: statusType === 'warning',
                [classes.successModifier]: statusType === 'success',
              },
              className
            )}
            aria-live={role === 'alert' ? 'assertive' : 'polite'}
            role={role}
            onMouseEnter={onMouseEnter}
            onMouseLeave={onMouseLeave}
            positionTransition
            initial={
              shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: -40 }
            }
            animate={
              shouldReduceMotion
                ? { opacity: 1 }
                : {
                    opacity: 1,
                    y: 0,
                  }
            }
            exit={
              shouldReduceMotion
                ? { opacity: 0 }
                : {
                    opacity: 0,
                    y: 60,
                    transition: { duration: 0.25, ease: 'easeIn' },
                  }
            }
            {...rootProps}
          >
            {!!Icon && <Icon role="img" aria-hidden className={classes.icon} />}
            {children ? (
              children
            ) : (
              <Text className={classes.title}>{title}</Text>
            )}
            {allowDismiss && (
              <>
                <IconButton
                  className={classes.closeButton}
                  aria-label="Close Notification"
                  size={0}
                  paddingTop={0}
                  paddingBottom={0}
                  paddingRight={0}
                  icon={X}
                  onClick={closeSnackbar}
                />
              </>
            )}
          </motion.div>
        ) : null}
      </AnimatePresence>
    );
  }
)
Example #29
Source File: Logs.tsx    From meshtastic-web with GNU General Public License v3.0 4 votes vote down vote up
Logs = (): JSX.Element => {
  const dispatch = useAppDispatch();

  const meshtasticState = useAppSelector((state) => state.meshtastic);
  const appState = useAppSelector((state) => state.app);

  type lookupType = { [key: number]: string };

  const emitterLookup: lookupType = {
    [Types.Emitter.sendText]: 'text-rose-500',
    [Types.Emitter.sendPacket]: 'text-pink-500',
    [Types.Emitter.sendRaw]: 'text-fuchsia-500',
    [Types.Emitter.setConfig]: 'text-purple-500',
    [Types.Emitter.confirmSetConfig]: 'text-violet-500',
    [Types.Emitter.setOwner]: 'text-indigo-500',
    [Types.Emitter.setChannel]: 'text-blue-500',
    [Types.Emitter.confirmSetChannel]: 'text-sky-500',
    [Types.Emitter.deleteChannel]: 'text-cyan-500',
    [Types.Emitter.getChannel]: 'text-teal-500',
    [Types.Emitter.getAllChannels]: 'text-emerald-500',
    [Types.Emitter.getConfig]: 'text-green-500',
    [Types.Emitter.getOwner]: 'text-lime-500',
    [Types.Emitter.configure]: 'text-yellow-500',
    [Types.Emitter.handleFromRadio]: 'text-amber-500',
    [Types.Emitter.handleMeshPacket]: 'text-orange-500',
    [Types.Emitter.connect]: 'text-red-500',
    [Types.Emitter.ping]: 'text-stone-500',
    [Types.Emitter.readFromRadio]: 'text-zinc-500',
    [Types.Emitter.writeToRadio]: 'text-gray-500',
    [Types.Emitter.setDebugMode]: 'text-slate-500',
  };

  const levelLookup: lookupType = {
    [Protobuf.LogRecord_Level.UNSET]: 'text-green-500',
    [Protobuf.LogRecord_Level.CRITICAL]: 'text-purple-500',
    [Protobuf.LogRecord_Level.ERROR]: 'text-red-500',
    [Protobuf.LogRecord_Level.WARNING]: 'text-orange-500',
    [Protobuf.LogRecord_Level.INFO]: 'text-blue-500',
    [Protobuf.LogRecord_Level.DEBUG]: 'text-neutral-500',
    [Protobuf.LogRecord_Level.TRACE]: 'text-slate-500',
  };

  return (
    <div className="flex h-full flex-col gap-4 p-4">
      <Card
        title="Device Logs"
        actions={
          <IconButton
            icon={<FiTrash />}
            onClick={(): void => {
              dispatch(clearLogs());
            }}
          />
        }
        className="flex-grow overflow-y-auto"
      >
        <table className="table-cell flex-grow">
          <tbody
            className="
          block h-full flex-col overflow-y-auto font-mono text-xs dark:text-gray-400"
          >
            <AnimatePresence>
              {meshtasticState.logs.length === 0 && (
                <div className="flex h-full w-full">
                  <m.img
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    className="m-auto h-64 w-64 text-green-500"
                    src={
                      appState.darkMode
                        ? '/View_Code_Dark.svg'
                        : '/View_Code.svg'
                    }
                  />
                </div>
              )}

              {meshtasticState.logs.map((log, index) => (
                <m.tr
                  key={index}
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  transition={{ duration: 0.3 }}
                  className="group hover:bg-gray-300 dark:hover:bg-secondaryDark"
                >
                  <m.td
                    className="w-6 cursor-pointer"
                    whileHover={{ scale: 1.01 }}
                    whileTap={{ scale: 0.99 }}
                  >
                    <div className="m-auto pl-2 text-white group-hover:text-black dark:text-primaryDark dark:group-hover:text-gray-400">
                      <FiArrowRight />
                    </div>
                  </m.td>
                  <Wrapper>
                    {log.date
                      .toLocaleString(undefined, {
                        year: 'numeric',
                        month: '2-digit',
                        day: '2-digit',

                        hour: '2-digit',
                        minute: '2-digit',
                        second: '2-digit',
                      })
                      .replaceAll('/', '-')
                      .replace(',', '')}
                  </Wrapper>
                  <Wrapper>
                    <div className={emitterLookup[log.emitter]}>
                      [{Types.EmitterScope[log.scope]}.
                      {Types.Emitter[log.emitter]}]
                    </div>
                  </Wrapper>
                  <Wrapper className={levelLookup[log.level]}>
                    [{Protobuf.LogRecord_Level[log.level]}]{/* </div> */}
                  </Wrapper>
                  <td
                    className={`m-auto ${
                      log.packet ? '' : 'dark:text-secondaryDark'
                    }`}
                  >
                    <FiPaperclip />
                  </td>
                  <td className="w-full truncate pl-1">{log.message}</td>
                </m.tr>
                // </ContextMenu>
              ))}
            </AnimatePresence>
          </tbody>
        </table>
      </Card>
    </div>
  );
}