@chakra-ui/react#useDisclosure TypeScript Examples

The following examples show how to use @chakra-ui/react#useDisclosure. 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: ContextMenu.tsx    From wiregui with MIT License 6 votes vote down vote up
ContextMenu: React.FC<Props> = ({ children }) => {
  const { isOpen, onClose: closeMenu, onOpen: openMenu } = useDisclosure();
  const [position, setPosition] = useState<MousePosition>({ x: 0, y: 0 });
  const menuRef = useRef<HTMLDivElement>(null);
  return (
    <ContextMenuContext.Provider
      value={{
        isOpen,
        closeMenu,
        openMenu,
        menuRef,
        position,
        setPosition,
      }}
    >
      {children}
    </ContextMenuContext.Provider>
  );
}
Example #2
Source File: index.tsx    From calories-in with MIT License 6 votes vote down vote up
function MenuOrDrawer({ children, title, ...rest }: Props) {
  const screenSize = useScreenSize()
  const modalDisclosure = useDisclosure()

  if (screenSize < ScreenSize.Medium) {
    return (
      <>
        <Trigger onClick={modalDisclosure.onOpen} {...rest} />
        <Drawer
          isOpen={modalDisclosure.isOpen}
          onClose={modalDisclosure.onClose}
          title={title}
        >
          {children}
        </Drawer>
      </>
    )
  }

  return (
    <Menu title={title} {...rest}>
      {children}
    </Menu>
  )
}
Example #3
Source File: useFoodEvents.ts    From calories-in with MIT License 6 votes vote down vote up
function useFoodEvents({ listRef, selection }: Params) {
  const foodModalDisclosure = useDisclosure()
  const [food, setFood] = useState<Food>()

  function onCreateFood() {
    setFood(undefined)
    foodModalDisclosure.onOpen()
  }

  function onPreviewFood(food: Food) {
    setFood(food)
    foodModalDisclosure.onOpen()
  }

  function onFoodDeleted(food: Food) {
    selection.removeItem(food)
  }

  function onFoodCreatedOrUpdated(newFood: Food, oldFood?: Food) {
    if (!listRef.current) {
      return
    }

    if (!oldFood || (oldFood && newFood.categoryId !== oldFood.categoryId)) {
      listRef.current.scrollToFood(newFood)
    }
  }

  return {
    onCreateFood,
    onPreviewFood,
    onFoodCreatedOrUpdated,
    food,
    foodModalDisclosure,
    onFoodDeleted,
  }
}
Example #4
Source File: MobileNavigationProvider.tsx    From lucide with ISC License 6 votes vote down vote up
export function MobileNavigationProvider({ children }) {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const toggleMobileMenu = () => (isOpen ? onClose() : onOpen());

  return (
    <MobileNavigationContext.Provider value={{ isOpen, onOpen, onClose, toggleMobileMenu }}>
      {children}
    </MobileNavigationContext.Provider>
  );
}
Example #5
Source File: SideBar.tsx    From ke with MIT License 6 votes vote down vote up
SideBar: FC<SidebarProps> = ({ header, children, breadcrumbsRules }) => {
  const { isOpen, onOpen, onClose } = useDisclosure()

  goToResourceEvent.watch(onClose)

  return (
    <>
      <Row>
        <Col xs={12}>
          <SidebarButtonContainer>
            <Button colorScheme="brand" m={2} width={20} onClick={onOpen}>
              <Menu size="1em" />
            </Button>
            <BreadCrumbContainer>{breadcrumbsRules && <Breadcrumbs rules={breadcrumbsRules} />}</BreadCrumbContainer>
          </SidebarButtonContainer>
        </Col>
      </Row>
      <Drawer isOpen={isOpen} placement="left" onClose={onClose}>
        <DrawerOverlay />
        <DrawerContent>
          <DrawerCloseButton />
          <DrawerHeader>{header}</DrawerHeader>
          <DrawerBody>
            <Flex flexDirection="column">{children}</Flex>
          </DrawerBody>
        </DrawerContent>
      </Drawer>
    </>
  )
}
Example #6
Source File: AccountButton.tsx    From rari-dApp with GNU Affero General Public License v3.0 6 votes vote down vote up
AccountButton = memo(() => {
  const {
    isOpen: isSettingsModalOpen,
    onOpen: openSettingsModal,
    onClose: closeSettingsModal,
  } = useDisclosure();

  const authedOpenSettingsModal = useAuthedCallback(openSettingsModal);

  const {
    isOpen: isClaimRGTModalOpen,
    onOpen: openClaimRGTModal,
    onClose: closeClaimRGTModal,
  } = useDisclosure();

  const authedOpenClaimRGTModal = useAuthedCallback(openClaimRGTModal);

  const { hasClaimableRewards } = useClaimable();

  return (
    <>
      <SettingsModal
        isOpen={isSettingsModalOpen}
        onClose={closeSettingsModal}
        openClaimRGTModal={openClaimRGTModal}
      />
      <ClaimRGTModal
        isOpen={isClaimRGTModalOpen}
        onClose={closeClaimRGTModal}
      />
      <Buttons
        openModal={authedOpenSettingsModal}
        openClaimRGTModal={authedOpenClaimRGTModal}
        hasClaimableRewards={hasClaimableRewards}
      />
    </>
  );
})
Example #7
Source File: Pool2Page.tsx    From rari-dApp with GNU Affero General Public License v3.0 6 votes vote down vote up
GeneralInfo = () => {
  const { t } = useTranslation();

  const apr = usePool2APR();
  const isMobile = useIsSmallScreen();

  const {
    isOpen: isDepositModalOpen,
    onOpen: openDepositModal,
    onClose: closeDepositModal,
  } = useDisclosure();

  const authedOpenDepositModal = useAuthedCallback(openDepositModal);

  return (
    <>
      <Pool2Modal isOpen={isDepositModalOpen} onClose={closeDepositModal} />
      <Heading fontSize="20px">{apr ?? "?"}% APR</Heading>
      <Text mt={3} width="70%" textAlign="center">
        {t("Deposit your LP tokens here to earn bonus RGT rewards!")}
      </Text>
      <DashboardBox
        mt={isMobile ? 4 : "auto"}
        width="70%"
        height="45px"
        borderRadius="7px"
        fontSize="xl"
        fontWeight="bold"
        as="button"
        onClick={authedOpenDepositModal}
      >
        <Center expand>{t("Deposit")}</Center>
      </DashboardBox>
    </>
  );
}
Example #8
Source File: home-page.tsx    From notebook with MIT License 6 votes vote down vote up
HomePage: React.SFC<HomePageProps> = ({ notes, setNotes }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const [selectedNote, setSelectedNote] = React.useState<note>();
  const toast = useToast();

  const handleClick = (id: string) => {
    const selectedNote = notes.find((note: note) => note.id === id);
    setSelectedNote(selectedNote);
    onOpen();
  };

  const handleNoteUpdate = (newNote: note) => {
    const newNotesState: note[] = [...notes];
    const index = notes.findIndex((note: note) => note.id === newNote.id);
    newNotesState[index] = newNote;
    setNotes(newNotesState);
    showToast();
  };

  const showToast = () => {
    toast({
      title: "Note updated.",
      status: "success",
      position: "top",
      duration: 2000,
      isClosable: true
    });
  };

  return (
    <>
      <AnimatePage>
        {notes.length ? (
          <NotesList
            notes={notes}
            handleClick={handleClick}
            setNotes={setNotes}
          />
        ) : (
          <HeroSection />
        )}
        {isOpen ? (
          <NoteForm
            isOpen={isOpen}
            onClose={onClose}
            handleNoteUpdate={handleNoteUpdate}
            selectedNote={selectedNote}
          />
        ) : (
          ""
        )}
      </AnimatePage>
    </>
  );
}
Example #9
Source File: AllCoupons.tsx    From fresh-coupons with GNU General Public License v3.0 5 votes vote down vote up
function AllCoupons() {
  const {isOpen, onOpen, onClose} = useDisclosure()
  const btnRef = React.useRef<HTMLButtonElement>(null)

  const courses = useCourses()

  return (
    <>
      <Button ref={btnRef} colorScheme="teal" onClick={onOpen}>
        Open
      </Button>
      <Drawer
        isOpen={isOpen}
        placement="right"
        onClose={onClose}
        size={"4xl"}
        finalFocusRef={btnRef}
      >
        <DrawerOverlay/>
        <DrawerContent>
          <DrawerCloseButton/>
          <DrawerBody>
            <Box my={9}>
              <Center>
                <Heading my={3} className={"course-list-title"} textAlign="center">Premium courses with
                  discount</Heading>
              </Center>
              <Stack spacing="10" py="5">
                {Object.entries(courses.coursesWithCoupon)
                  .sort(([_, course]) => course.courseDetails.language === 'English' ? -1 : 1)
                  .map(([url, course]) => (
                  <CourseCard key={url} course={course}/>
                ))}
              </Stack>
            </Box>
            <Box>
              <Center>
                <Heading my={3} className={"course-list-title"} textAlign="center">More free courses</Heading>
              </Center>
              <Stack spacing="10" py="5">
                {Object.entries(courses.freeCourses).map(([url, course]) => (
                  <CourseCard key={url} course={course}/>
                ))}
              </Stack>
            </Box>
          </DrawerBody>
        </DrawerContent>
      </Drawer>
    </>
  )
}
Example #10
Source File: ManagePiggybankBar.tsx    From coindrop with GNU General Public License v3.0 5 votes vote down vote up
ManagePiggybankBar: FunctionComponent<Props> = ({ editButtonOptions, initialSetupComplete }) => {
    const { isOpen: isEditOpen, onOpen: onEditOpen, onClose: onEditClose } = useDisclosure();
    const [isDashboardLoading, setIsDashboardLoading] = useState(false);
    return (
        <Box>
            {isEditOpen && ( // this conditional is needed to force remount of form so latest values are used
                <AdditionalValidationProvider>
                    <EditPiggybankModal
                        isOpen={isEditOpen}
                        onClose={onEditClose}
                    />
                </AdditionalValidationProvider>
            )}
            <Flex
                justify={["center", null, "space-between"]}
                my={4}
                mx={6}
                wrap="wrap"
            >
                <Box
                    onClick={() => setIsDashboardLoading(true)}
                    mt={2}
                >
                    <LinkButton
                        href="/dashboard"
                        buttonProps={{
                            leftIcon: <ArrowBackIcon />,
                            isLoading: isDashboardLoading,
                            loadingText: "Loading",
                        }}
                    >
                        Dashboard
                    </LinkButton>
                </Box>
                <Box mx={3} mt={2}>
                    <Button
                        id="configure-coindrop-button"
                        leftIcon={editButtonOptions.icon}
                        onClick={onEditOpen}
                        colorScheme={editButtonOptions.color}
                        isDisabled={isEditOpen}
                    >
                        {editButtonOptions.text}
                    </Button>
                </Box>
                <Box
                    align="center"
                    mt={2}
                >
                    <ShareButtonModal
                        buttonColor={initialSetupComplete ? 'green' : undefined}
                    />
                </Box>
            </Flex>
            <hr />
        </Box>
    );
}
Example #11
Source File: index.tsx    From eth-dapps-nextjs-boiletplate with MIT License 5 votes vote down vote up
function Home() {
  const { isOpen, onOpen, onClose } = useDisclosure()

  const title = 'Ethereum dApps Next.js Boiletplate'
  return (
    <Layout>
      <Head>
        <title>{title}</title>
        <meta name="description" content={title} />
        <link rel="icon" href="/favicon.ico" />
        <link rel="manifest" href="/manifest.json" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <a href="https://github.com/limcheekin/eth-dapps-nextjs-boiletplate">{title}</a>
        </h1>

        <p className={styles.description}>
          A simple dApps to demo the integration of MetaMask, WalletConnect and Greeter smart contract.
        </p>

        {
        // Our connect button will only handle opening
        }
        <ConnectButton handleOpenModal={onOpen} />
        {
        // Our Account modal will handle open state & closing
        }
        <AccountModal isOpen={isOpen} onClose={onClose} />
        <Greeter />
      </main>

      <footer className={styles.footer}>
        Powered by{' '}
        <img className={styles.logo} src="/logos/ethereum.png" alt="Ethereum Logo" width="144" height="32" />
        <img className={styles.logo} src="/logos/nextjs.png" alt="NextJS Logo" width="64" height="32" />
        <img className={styles.logo} src="/logos/metamask.png" alt="MetaMask Logo" width="128" height="32" />
        <img className={styles.logo} src="/logos/walletconnect.png" alt="WalletConnect Logo" width="128" height="32" />
        { process.env.NEXT_PUBLIC_GITHUB_RUN_NUMBER && <div className={styles.logo}>b{process.env.NEXT_PUBLIC_GITHUB_RUN_NUMBER}</div> }
      </footer>
    </Layout>
  )
}
Example #12
Source File: Navigation.tsx    From bluebubbles-server with Apache License 2.0 5 votes vote down vote up
Navigation = (): JSX.Element => {
    const { isOpen, onOpen, onClose } = useDisclosure();
    const {
        isOpen: isNotificationsOpen,
        onOpen: onNotificationOpen,
        onClose: onNotificationClose
    } = useDisclosure();

    const notifications: Array<NotificationItem> = useAppSelector(state => state.notificationStore.notifications);
    const unreadCount = notifications.filter(e => !e.read).length;
    const dispatch = useAppDispatch();

    return (
        <Box minH="100vh">
            <Router>
                <SidebarContent onClose={() => onClose} display={{ base: 'none', md: 'block' }} />
                <Drawer
                    autoFocus={false}
                    isOpen={isOpen}
                    placement="left"
                    onClose={onClose}
                    returnFocusOnClose={false}
                    onOverlayClick={onClose}
                    size="full"
                >
                    <DrawerContent>
                        <SidebarContent onClose={onClose} />
                    </DrawerContent>
                </Drawer>
                {/* mobilenav */}
                <MobileNav onOpen={onOpen} onNotificationOpen={onNotificationOpen} unreadCount={unreadCount} />
                <Box ml={{ base: 0, md: 60 }} p="2">
                    <Routes>
                        <Route path="/settings" element={<SettingsLayout />} />
                        <Route path="/logs" element={<LogsLayout />} />
                        <Route path="/contacts" element={<ContactsLayout />} />
                        <Route path="/fcm" element={<FcmLayout />} />
                        <Route path="/devices" element={<DevicesLayout />} />
                        <Route path="/webhooks" element={<ApiLayout />} />
                        <Route path="/guides" element={<GuidesLayout />} />
                        <Route path="/" element={<HomeLayout />} />
                    </Routes>
                </Box>
            </Router>

            <Drawer onClose={() => closeNotification(onNotificationClose, dispatch)} isOpen={isNotificationsOpen} size="lg">
                <DrawerOverlay />
                <DrawerContent>
                    <DrawerHeader>Notifications / Alerts ({unreadCount})</DrawerHeader>
                    <DrawerBody>
                        <Menu>
                            <MenuButton
                                as={Button}
                                rightIcon={<BsChevronDown />}
                                width="12em"mr={5}
                                mb={4}
                            >
                                Manage
                            </MenuButton>
                            <MenuList>
                                <MenuItem icon={<FiTrash />} onClick={() => {
                                    dispatch(clearAlerts());
                                }}>
                                    Clear Alerts
                                </MenuItem>
                                <MenuItem icon={<BsCheckAll />} onClick={() => {
                                    dispatch(readAll());
                                }}>
                                    Mark All as Read
                                </MenuItem>
                            </MenuList>
                        </Menu>
                        <NotificationsTable notifications={notifications} />
                    </DrawerBody>
                </DrawerContent>
            </Drawer>
        </Box>
    );
}
Example #13
Source File: DialogButton.tsx    From wiregui with MIT License 5 votes vote down vote up
export function DialogButton({
  header,
  body,
  onConfirm,
  onCancel,
  launchButtonText,
  title,
  color,
  colorScheme,
  motionPreset = "slideInBottom",
  cancelButtonText = "Cancel",
  confirmButtonText = "Confirm",
}: DialogButtonProps) {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const cancelRef = React.useRef<HTMLButtonElement>(null);

  function onHandleConfirm() {
    if (onConfirm) {
      onConfirm();
    }
    onClose();
  }

  function onHandleCancel() {
    if (onCancel) {
      onCancel();
    }
    onClose();
  }

  return (
    <>
      <Button colorScheme={colorScheme} color={color} title={title} onClick={onOpen} size="sm" ml="4">
        {launchButtonText}
      </Button>
      <AlertDialog
        motionPreset={motionPreset}
        leastDestructiveRef={cancelRef}
        onClose={onClose}
        isOpen={isOpen}
        isCentered
      >
        <AlertDialogOverlay />

        <AlertDialogContent bg="gray.300">
          <AlertDialogHeader>{header}</AlertDialogHeader>
          <AlertDialogCloseButton />
          <AlertDialogBody>{body}</AlertDialogBody>
          <AlertDialogFooter>
            <Button ref={cancelRef} onClick={onHandleCancel}>
              {cancelButtonText}
            </Button>
            <Button colorScheme="orange" ml={3} onClick={onHandleConfirm}>
              {confirmButtonText}
            </Button>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}
Example #14
Source File: Pool2Page.tsx    From rari-dApp with GNU Affero General Public License v3.0 5 votes vote down vote up
YourBalance = () => {
  const { t } = useTranslation();

  const balance = usePool2Balance();
  const earned = usePool2UnclaimedRGT();

  const {
    isOpen: isClaimRGTModalOpen,
    onOpen: openClaimRGTModal,
    onClose: closeClaimRGTModal,
  } = useDisclosure();
  const authedOpenModal = useAuthedCallback(openClaimRGTModal);

  const isMobile = useIsSmallScreen();

  return (
    <Column
      mainAxisAlignment="flex-start"
      crossAxisAlignment="center"
      width="100%"
      height="100%"
      style={
        !balance?.hasDeposited ? { opacity: "0.3", pointerEvents: "none" } : {}
      }
    >
      <ClaimRGTModal
        isOpen={isClaimRGTModalOpen}
        onClose={closeClaimRGTModal}
        defaultMode="pool2"
      />
      <Heading fontSize="20px">{t("Your Balance")}</Heading>
      <Text fontSize="sm" mt={2} width="70%" textAlign="center">
        {balance?.hasDeposited ? balance.SLP!.toFixed(4) : "0.0000"} Staked SLP
      </Text>
      <Text mt={1} fontSize="xs" width="70%" textAlign="center">
        {balance?.hasDeposited ? balance.eth!.toFixed(0) : "0.0000"} ETH{" + "}
        {balance?.hasDeposited ? balance.rgt!.toFixed(0) : "0.0000"} RGT
      </Text>
      <Text mt={2} width="70%" textAlign="center">
        <b>
          {earned ? earned.toFixed(2) : "0.00"} {t("RGT Earned")}
        </b>
      </Text>
      <DashboardBox
        mt={isMobile ? 4 : "auto"}
        width="70%"
        height="45px"
        borderRadius="7px"
        fontSize="xl"
        fontWeight="bold"
        as="button"
        onClick={authedOpenModal}
      >
        <Center expand>{t("Claim RGT")}</Center>
      </DashboardBox>
    </Column>
  );
}
Example #15
Source File: ShareButtonModal.tsx    From coindrop with GNU General Public License v3.0 5 votes vote down vote up
ShareButtonModal: FunctionComponent<Props> = ({ buttonColor }) => {
    const { isOpen, onClose, onOpen } = useDisclosure();
    const { query: { piggybankName: piggybankNameQuery }} = useRouter();
    const piggybankName = Array.isArray(piggybankNameQuery) ? piggybankNameQuery[0] : piggybankNameQuery;
    const publicUrl = `coindrop.to/${piggybankName}`;
    const fullPublicUrl = `https://${publicUrl}`;
    return (
        <>
        <Button
            leftIcon={<ShareIcon />}
            onClick={onOpen}
            colorScheme={buttonColor}
            isDisabled={isOpen}
        >
            Share
        </Button>
        <Modal isOpen={isOpen} onClose={onClose}>
            <ModalOverlay />
            <ModalContent>
                <ModalCloseButton />
                <Heading
                    mt={4}
                    as="h2"
                    size="md"
                    mx={12}
                    textAlign="center"
                >
                    {publicUrl}
                </Heading>
                <ModalBody>
                    <Box mb={4}>
                        <Box>
                            <Heading as="h2" size="lg">
                                Link
                            </Heading>
                        </Box>
                        <Center mt={2}>
                            <CopyLinkShareButton textToCopy={publicUrl} />
                        </Center>
                    </Box>
                    <ShareEmbedButton
                        fullPublicUrl={fullPublicUrl}
                    />
                    <PiggybankQRCode
                        fullPublicUrl={fullPublicUrl}
                        publicUrl={publicUrl}
                    />
                    <TipCards />
                </ModalBody>
                <ModalFooter />
            </ModalContent>
        </Modal>
        </>
    );
}
Example #16
Source File: index.tsx    From calories-in with MIT License 5 votes vote down vote up
function Controls() {
  const dietFormActions = useDietFormActions()
  const exportModalDisclosure = useDisclosure()
  const missingFoodsModalDisclosure = useDisclosure()
  const { onLoadFromFile } = useImportDietForm({ missingFoodsModalDisclosure })
  const foodsListModalDisclosure = useDisclosure()
  const importFoods = useImportFoods({ foodsListModalDisclosure })
  const foodsDrawerDisclosure = useDisclosure()
  const screenSize = useScreenSize()

  useKeyboard()

  function onClear() {
    dietFormActions.setDietForm(getDietForm())
  }

  return (
    <Flex width="100%" alignItems="center">
      <Flex flex={1} mr={2}>
        <UndoRedoButtons />
      </Flex>

      <Flex flexShrink={1} justifyContent="center" flex={4}>
        <Name />
      </Flex>

      <Flex ml={2} justifyContent="flex-end" spacing={3} flex={1}>
        <MenuOrDrawer
          onImport={onLoadFromFile}
          onClear={onClear}
          onViewFoods={foodsDrawerDisclosure.onOpen}
        />

        {screenSize >= ScreenSize.Medium && (
          <Button
            leftIcon={<Trash size={16} />}
            size="md"
            onClick={onClear}
            mr={2}
          >
            Clear
          </Button>
        )}

        <ExportButton onClick={exportModalDisclosure.onOpen} />
      </Flex>

      <MissingFoodsModal
        isOpen={missingFoodsModalDisclosure.isOpen}
        onClose={missingFoodsModalDisclosure.onClose}
        onImport={importFoods.onImport}
      />

      <FoodsListModal
        isOpen={foodsListModalDisclosure.isOpen}
        onClose={foodsListModalDisclosure.onClose}
        foodsToImport={importFoods.foodsToImport}
      />

      <FoodsDrawer
        isOpen={foodsDrawerDisclosure.isOpen}
        onClose={foodsDrawerDisclosure.onClose}
        canSelect={false}
      />

      <ExportModal
        isOpen={exportModalDisclosure.isOpen}
        onClose={exportModalDisclosure.onClose}
      />
    </Flex>
  )
}
Example #17
Source File: PaymentMethodButton.tsx    From coindrop with GNU General Public License v3.0 5 votes vote down vote up
PaymentMethodButton: FunctionComponent<Props> = ({
    paymentMethod,
    paymentMethodValue,
    isPreferred,
    accentColor,
}) => {
    const theme = useTheme();
    const { isOpen, onOpen, onClose } = useDisclosure();
    const paymentMethodDisplayName = paymentMethodNames[paymentMethod];
    const Icon = paymentMethodIcons[paymentMethod];
    if (!paymentMethodDisplayName || !Icon) return null;
    const textColor = useColorModeValue("gray.800", "white");
    const bgColor = useColorModeValue("gray.50", "gray.700");
    const bgColorHover = useColorModeValue("gray.100", "gray.600");
    const bgColorActive = useColorModeValue("gray.200", "gray.500");
    const borderColor = isPreferred
        ? theme.colors[accentColor]['500']
        : useColorModeValue("gray.300", "gray.500");
    const borderColorHover = isPreferred
        ? theme.colors[accentColor]['500']
        : useColorModeValue("gray.300", "gray.500");
    return (
        <>
        <PaymentMethodButtonModal
            isOpen={isOpen}
            onClose={onClose}
            paymentMethod={paymentMethod}
            paymentMethodDisplayName={paymentMethodDisplayName}
            paymentMethodValue={paymentMethodValue}
        />
        <Box
            as="button"
            id={`payment-method-button-${paymentMethod}`}
            onClick={onOpen}
            lineHeight="1.2"
            transition="all 0.2s cubic-bezier(.08,.52,.52,1)"
            borderWidth={isPreferred ? "2px" : "1px"}
            rounded="6px"
            fontSize="18px"
            fontWeight="semibold"
            bg={bgColor}
            borderColor={borderColor}
            p={4}
            m={2}
            shadow="md"
            color={textColor}
            _hover={{
                bg: bgColorHover,
                transform: "scale(0.98)",
                borderColor: borderColorHover,
            }}
            _active={{
                bg: bgColorActive,
                transform: "scale(0.96)",
                borderColor: borderColorHover,
            }}
            _focus={{
                outline: "none",
            }}
        >
            <Flex align="center">
                <Icon boxSize="32px" />
                <Text ml={2}>{paymentMethodDisplayName}</Text>
            </Flex>
            {isPreferred && (
                <Text
                    fontSize="xs"
                    color={textColor}
                >
                    Preferred
                </Text>
            )}
        </Box>
        </>
    );
}
Example #18
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function Form() {
  const horizontalScrollRef = useRef<HTMLDivElement>(null)
  const dietForm = useDietForm()
  const { variantsForms } = dietForm
  const selectedVariantForm = variantsForms[dietForm.selectedVariantFormIndex]

  const scrollManager = useScrollManager({
    selectedVariantForm,
    horizontalScrollRef,
  })

  const foodsDrawerDisclosure = useDisclosure()
  const dietFormEvents = useDietFormEvents({
    scrollManager,
    foodsDrawerDisclosure,
  })

  const {
    elementHeight: headerHeight,
    elementRef: headerRef,
  } = useElementHeight()
  const variantFormEvents = useVariantFormEvents({ scrollManager })

  const screenSize = useScreenSize()

  const aboutModalDisclosure = useDisclosure()

  return (
    <DietFormVersionsStoreProvider
      horizontalScrollRef={horizontalScrollRef}
      form={dietForm}
      onUndo={dietFormEvents.onUndoOrRedo}
      onRedo={dietFormEvents.onUndoOrRedo}
    >
      <Page>
        <PageHeader ref={headerRef}>
          <Box bg="white" py={3}>
            <Controls />
          </Box>
        </PageHeader>

        <PageBody>
          <VariantsList
            onVariantFormCopy={variantFormEvents.onVariantFormCopy}
            onVariantFormSelect={variantFormEvents.onVariantFormSelect}
            ref={horizontalScrollRef}
          />

          <Flex>
            <MealsList
              flex={1}
              headerHeight={headerHeight}
              selectedVariantFormFieldId={selectedVariantForm.fieldId}
              mealsForms={selectedVariantForm.mealsForms}
              selectedVariantFormIndex={dietForm.selectedVariantFormIndex}
              onAddMeal={foodsDrawerDisclosure.onOpen}
            />

            {screenSize >= ScreenSize.Large && (
              <VariantStats
                position="sticky"
                top={`${headerHeight + 24}px`}
                ml={6}
                width="300px"
                bg="white"
                borderRadius={6}
                boxShadow="base"
              />
            )}
          </Flex>

          <Footer mt={10} onAbout={aboutModalDisclosure.onOpen} />

          <FoodsDrawer
            isOpen={foodsDrawerDisclosure.isOpen}
            onClose={foodsDrawerDisclosure.onClose}
            mealName={`Meal ${selectedVariantForm.mealsForms.length + 1}`}
            onSelectedFoods={dietFormEvents.onMealAdded}
          />

          <About
            isOpen={aboutModalDisclosure.isOpen}
            onClose={aboutModalDisclosure.onClose}
          />
        </PageBody>
      </Page>
    </DietFormVersionsStoreProvider>
  )
}
Example #19
Source File: LandingPage.tsx    From coindrop with GNU General Public License v3.0 4 votes vote down vote up
LandingPage: FC<Props> = ({
    headingTextPrimaryPreUnderline,
    headingTextPrimaryUnderline,
    headingTextPrimaryPostUnderline,
    headingTextSecondary,
    headingTextTertiary,
    smartphoneMockupImagePublicPath,
    showSubscriptionPlatforms,
    ShareOptions,
    shareOptionsHeading,
    advertiseOpenSource,
    getStartedText,
    smartphoneMockupImageWidth,
    smartphoneMockupImageHeight,
    createCoindropInputPlaceholder,
    logoSubtitle,
}) => {
    const {
        isOpen: isAuthOpen,
        onOpen: onAuthOpen,
        onClose: onAuthClose,
    } = useDisclosure();
    const router = useRouter();
    const { user } = useUser();
    useEffect(() => {
        if (user) {
            const pendingLoginCreatePiggybankPath = cookies.get('pendingLoginCreatePiggybankPath');
            if (pendingLoginCreatePiggybankPath) {
                router.push('/create');
            } else {
                router.push('/dashboard');
            }
        }
    }, [user]);
    useEffect(() => {
        if (router.query.auth) {
            onAuthOpen();
        } else {
            onAuthClose();
        }
    }, [router.query]);
    return (
        <>
        <AuthModal
            isOpen={isAuthOpen}
        />
        <HeaderFooterContainer>
            <Navbar
                logoSubtitle={logoSubtitle}
            />
        </HeaderFooterContainer>
        <Container
            maxW="100%"
            mx="auto"
            px={4}
            mb={6}
        >
            <Container
                my="3rem"
                maxW="98em" // there is no theme.breakpoints.2xl
            >
                <HeadingTextPrimary
                    textPreUnderline={headingTextPrimaryPreUnderline}
                    textUnderline={headingTextPrimaryUnderline}
                    textPostUnderline={headingTextPrimaryPostUnderline}
                />
                <Text fontSize="lg" textAlign="center" mt={3}>
                    {headingTextSecondary}
                </Text>
                <Text fontSize="lg" textAlign="center" mt={2}>
                    <b>{headingTextTertiary}</b>
                </Text>
                <Center mt={8}>
                    <Image
                        src={smartphoneMockupImagePublicPath}
                        alt="Smartphone mockup"
                        height={smartphoneMockupImageHeight}
                        width={smartphoneMockupImageWidth}
                    />
                </Center>
            </Container>
            <ContentContainer>
                <ContentContainerHeading withThroughline>
                    ➀ Pick a custom URL
                </ContentContainerHeading>
                <Box
                    mt={8}
                >
                    <CreatePiggybankInput
                        createButtonColorScheme="orange"
                        onCancel={null}
                        instanceId="top"
                        buttonText="Check availability"
                        placeholder={createCoindropInputPlaceholder}
                    />
                </Box>
            </ContentContainer>
            <ContentContainer>
                <ContentContainerHeading withThroughline>
                    ➁ Add your payment methods
                </ContentContainerHeading>
                <Flex
                    direction={['column', 'row']}
                    wrap="wrap"
                    maxW="80%"
                    mx="auto"
                >
                    <PaymentMethodContainer title="Digital wallets" paymentMethodCategory="digital-wallet" />
                    <PaymentMethodContainer title="Digital assets" paymentMethodCategory="digital-asset" />
                    {showSubscriptionPlatforms && (
                        <PaymentMethodContainer title="Subscription platforms" paymentMethodCategory="subscription-platform" />
                    )}
                </Flex>
            </ContentContainer>
            <ContentContainer>
                <ContentContainerHeading withThroughline>
                    ➂ {shareOptionsHeading}
                </ContentContainerHeading>
                <ShareOptions />
            </ContentContainer>
            {advertiseOpenSource && (
                <ContentContainer
                    boxProps={{
                        borderRadius: '16px',
                        position: 'relative',
                    }}
                >
                    <ContentContainerHeading>
                        Open-Source
                    </ContentContainerHeading>
                    <Flex align="center" justify="center" mt={4}>
                        <GithubIcon
                            opacity={0.9}
                            boxSize="72px"
                            mr={4}
                        />
                        <Text
                            fontSize="lg"
                        >
                            {'The source code for Coindrop is publicly available on '}
                            <Link isExternal href={githubUrl}>
                                Github
                            </Link>
                        </Text>
                    </Flex>
                </ContentContainer>
            )}
            <ContentContainer>
                <ContentContainerHeading>
                    Get started ?
                </ContentContainerHeading>
                <Text textAlign="center" fontSize="lg">
                    {getStartedText}
                </Text>
                <Box mt={2}>
                    <CreatePiggybankInput
                        createButtonColorScheme="orange"
                        onCancel={null}
                        instanceId="bottom"
                        buttonText="Create"
                        placeholder={createCoindropInputPlaceholder}
                    />
                </Box>
            </ContentContainer>
        </Container>
        <HeaderFooterContainer>
            <Footer />
        </HeaderFooterContainer>
        </>
    );
}
Example #20
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function VariantsList({
  onVariantFormSelect,
  onVariantFormCopy,
  forwardedRef = createRef(),
}: Props) {
  const scrollNodeRef = useRef<HTMLDivElement>(null)
  const screenSize = useScreenSize()
  const isPhone = screenSize <= ScreenSize.Small

  const nameModalDisclosure = useDisclosure()
  const detailsModalDisclosure = useDisclosure()

  const variantFormEvents = useVariantFormEvents({
    onVariantFormSelect,
    onVariantFormCopy,
    nameModalDisclosure,
    detailsModalDisclosure,
  })

  const dietForm = useDietForm()
  const getVariantItemRefById = useGetRefForId<HTMLDivElement>()
  const scrollState = useScrollState()

  return (
    <Flex py={6}>
      <AddVariantButton onClick={variantFormEvents.onAppend} />

      {!isPhone && (
        <VariantsMenuOrDrawer onVariantFormSelect={onVariantFormSelect} />
      )}

      <Droppable
        droppableId="variantsList"
        type="variantsList"
        direction="horizontal"
      >
        {provided => (
          <HFadeScroll
            onScrollStateChange={scrollState.onScrollStateChange}
            ref={mergeRefs([provided.innerRef, scrollNodeRef, forwardedRef])}
          >
            {dietForm.variantsForms.map((variantForm, index) => {
              return (
                <VariantItem
                  canRemove={dietForm.variantsForms.length > 1}
                  mr={2}
                  index={index}
                  onDelete={variantFormEvents.onRemove}
                  onEditName={variantFormEvents.onRename}
                  onClone={variantFormEvents.onCopy}
                  onViewDetails={variantFormEvents.onViewDetails}
                  key={variantForm.fieldId}
                  variantForm={variantForm}
                  isSelected={index === dietForm.selectedVariantFormIndex}
                  onSelect={variantFormEvents.onSelect}
                  ref={getVariantItemRefById(variantForm.fieldId)}
                >
                  {variantForm.name}
                </VariantItem>
              )
            })}

            {provided.placeholder}
          </HFadeScroll>
        )}
      </Droppable>

      {isPhone ? (
        <VariantsMenuOrDrawer onVariantFormSelect={onVariantFormSelect} />
      ) : (
        <ScrollButtons
          scrollNodeRef={scrollNodeRef}
          showsButtons={scrollState.showsScrollButtons}
          canScrollLeft={scrollState.canScrollLeft}
          canScrollRight={scrollState.canScrollRight}
        />
      )}

      <VariantNameModal
        isOpen={nameModalDisclosure.isOpen}
        onClose={nameModalDisclosure.onClose}
        variantFormIndex={variantFormEvents.variantFormIndex}
      />

      {variantFormEvents.variantForm && (
        <VariantsDetailsModal
          isOpen={detailsModalDisclosure.isOpen}
          onClose={detailsModalDisclosure.onClose}
          initialVariantForm={variantFormEvents.variantForm}
        />
      )}
    </Flex>
  )
}
Example #21
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function Content({
  onClose,
  mealName,
  mealForm,
  searchInputRef,
  onSelectedFoods,
  canSelect,
}: Props) {
  const selection = useSelection<Food>()
  const listRef = useRef<FoodsListMethods>(null)
  const foodEvents = useFoodEvents({ listRef, selection })

  const foodsListModalDisclosure = useDisclosure()
  const importFoods = useImportFoods({ foodsListModalDisclosure })
  const [foodsFilter] = useState(loadFoodsFilter)

  function onAdd() {
    onSelectedFoods && onSelectedFoods(selection.selectedItems, mealName)
  }

  return (
    <DrawerContent>
      <DrawerCloseButton />
      <Header mealForm={mealForm} mealName={mealName} canSelect={canSelect} />

      <DrawerBody overflow="hidden">
        <VStack
          width="100%"
          height="100%"
          spacing={canSelect ? 3 : 6}
          alignItems="stretch"
        >
          <Flex>
            <Text textColor="gray.500" size="lg" mr={1}>
              Need more foods?
            </Text>
            <Button
              variant="link"
              colorScheme="teal"
              onClick={foodEvents.onCreateFood}
            >
              Create a new food
            </Button>
          </Flex>

          {canSelect && <SelectedFoodsList selection={selection} />}

          <FoodsFilterStoreProvider initialFilter={foodsFilter}>
            <FoodsList
              ref={listRef}
              searchInputRef={searchInputRef}
              selection={selection}
              flex={1}
              onFoodPreview={foodEvents.onPreviewFood}
              itemUsageType={canSelect ? 'selectOrPreview' : 'previewOnly'}
            />
          </FoodsFilterStoreProvider>
        </VStack>
      </DrawerBody>

      <DrawerFooter justifyContent={canSelect ? 'flex-end' : 'space-between'}>
        {!canSelect && (
          <MenuButtons
            onImport={importFoods.onImport}
            onExport={foodsListModalDisclosure.onOpen}
          />
        )}

        <HStack spacing={3}>
          <Button variant="solid" size="md" onClick={onClose}>
            Close
          </Button>
          {canSelect && (
            <Tooltip
              isActive={!mealForm}
              delay={300}
              label="You can add more later"
            >
              <Button
                isDisabled={selection.selectedItems.length === 0}
                colorScheme="teal"
                onClick={onAdd}
              >
                {mealForm ? 'Add selected foods' : 'Select foods'}
              </Button>
            </Tooltip>
          )}
        </HStack>
      </DrawerFooter>

      <FoodModal
        isOpen={foodEvents.foodModalDisclosure.isOpen}
        onClose={foodEvents.foodModalDisclosure.onClose}
        onFoodCreatedOrUpdated={foodEvents.onFoodCreatedOrUpdated}
        onFoodDeleted={foodEvents.onFoodDeleted}
        food={foodEvents.food}
      />

      <FoodsListModal
        isOpen={foodsListModalDisclosure.isOpen}
        onClose={foodsListModalDisclosure.onClose}
        foodsToImport={importFoods.foodsToImport}
      />
    </DrawerContent>
  )
}
Example #22
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function IngredientItem({
  variantIndex,
  mealIndex,
  index,
  ingredientForm,
  energy,
  protein,
  carbs,
  fat,
  onRemove,
  shouldAddRadiusToLastBottomBorder,
  isLast,
  isDraggingOver,
}: Props) {
  const { foodsById } = useFoods()
  const food = foodsById[ingredientForm.foodId]

  const ingredientEvents = useIngredientsEvents({
    variantIndex,
    mealIndex,
    index,
    onRemove,
    ingredientForm,
    food,
  })

  const notesEvents = useNotesEvents({
    variantIndex,
    mealIndex,
    index,
    ingredientForm,
  })

  const foodModalDisclosure = useDisclosure()
  const editNotesModalDisclosure = useDisclosure()

  const menuOrDrawerItems = getMenuOrDrawerItems({
    onEditNotes: editNotesModalDisclosure.onOpen,
    onRemove: ingredientEvents.onRemoveRequest,
    onViewFoodDetails: foodModalDisclosure.onOpen,
    ingredientForm,
  })

  // console.log('ingredient', variantIndex, mealIndex, index)

  return (
    <Draggable
      key={ingredientForm.fieldId}
      draggableId={ingredientForm.fieldId as string}
      index={index}
    >
      {(provided, { isDragging }) => (
        <PresenceAnimation
          shouldAnimate={ingredientEvents.shouldAnimate}
          onAnimationComplete={ingredientEvents.onAnimationComplete}
          isVisible={ingredientEvents.isVisible}
          isDraggingOver={isDraggingOver}
        >
          <ContextMenuFlex
            ref={provided.innerRef}
            {...provided.draggableProps}
            {...provided.dragHandleProps}
            style={provided.draggableProps.style}
            boxShadow={
              isDragging
                ? 'rgba(0, 0, 0, 0.2) 0px 5px 10px, rgba(0, 0, 0, 0.4) 0px 15px 40px'
                : undefined
            }
            bg={isDragging ? 'gray.50' : undefined}
            alignItems="center"
            position="relative"
            py={3}
            _hover={{ backgroundColor: 'gray.50' }}
            borderBottomRadius={
              !isDragging && isLast && shouldAddRadiusToLastBottomBorder
                ? 10
                : 0
            }
            overflow="hidden"
            menuOrDrawerItems={menuOrDrawerItems}
          >
            {food ? (
              <StatsLayout
                ingredientForm={ingredientForm}
                energy={energy}
                protein={protein}
                carbs={carbs}
                fat={fat}
                onAmountChange={ingredientEvents.onAmountChange}
                onPortionChange={ingredientEvents.onPortionChange}
                menuElement={<MenuOrDrawer>{menuOrDrawerItems}</MenuOrDrawer>}
                food={food}
                notes={ingredientForm.notes}
              >
                {ingredientForm.notes && (
                  <Notes
                    ingredientForm={ingredientForm}
                    notesEvents={notesEvents}
                  />
                )}
              </StatsLayout>
            ) : (
              <MissingStatsLayout
                onRemoveRequest={ingredientEvents.onRemoveRequest}
              />
            )}
          </ContextMenuFlex>

          {food && (
            <FoodModal
              isOpen={foodModalDisclosure.isOpen}
              onClose={foodModalDisclosure.onClose}
              onFoodCreatedOrUpdated={ingredientEvents.onFoodUpdated}
              food={food}
            />
          )}

          {food && (
            <EditNotesModal
              isOpen={editNotesModalDisclosure.isOpen}
              onClose={editNotesModalDisclosure.onClose}
              notes={ingredientForm.notes}
              onEditNotes={notesEvents.onEditNotes}
              fieldId={ingredientForm.fieldId}
              ownerName={food.name}
            />
          )}
        </PresenceAnimation>
      )}
    </Draggable>
  )
}
Example #23
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function MealItem({
  mealForm,
  index,
  onRemove,
  getMealNameInputRefById,
  variantIndex,
  selectedVariantFormFieldId,
  onFirstAppear,
  isDragging,
  ...rest
}: Props) {
  const foodsDrawerDisclosure = useDisclosure()
  const mealFormEvents = useMealFormEvents({
    mealForm,
    variantIndex,
    index,
    onFirstAppear,
    onRemove,
    foodsDrawerDisclosure,
  })
  const editNotesModalDisclosure = useDisclosure()

  const { mealFormStatsTree, ingredientsStats } = useGetAndUpdateStats({
    mealForm,
    index,
    selectedVariantFormFieldId,
  })

  return (
    <Draggable
      key={mealForm.fieldId}
      draggableId={mealForm.fieldId}
      index={index}
    >
      {(provided, snapshot) => (
        <PresenceAnimation
          shouldAnimate={mealFormEvents.shouldAnimate}
          isVisible={mealFormEvents.isVisible}
          onAnimationComplete={mealFormEvents.onAnimationComplete}
          isDragging={isDragging}
        >
          <Flex
            ref={provided.innerRef}
            {...provided.draggableProps}
            style={provided.draggableProps.style}
            flexDirection="column"
            borderRadius={10}
            backgroundColor="white"
            boxShadow={
              snapshot.isDragging
                ? 'rgba(0, 0, 0, 0.2) 0px 5px 10px, rgba(0, 0, 0, 0.4) 0px 15px 40px'
                : 'base'
            }
            {...rest}
          >
            <Header
              {...provided.dragHandleProps}
              variantIndex={variantIndex}
              ingredientsStatsSum={mealFormStatsTree.stats}
              getMealNameInputRefById={getMealNameInputRefById}
              index={index}
              mealForm={mealForm}
              onRemove={mealFormEvents.onRemoveRequest}
              onAddIngredient={foodsDrawerDisclosure.onOpen}
              onClone={mealFormEvents.onClone}
              onEditNotes={editNotesModalDisclosure.onOpen}
            />

            <Box px={3}>
              <Divider />
            </Box>

            <IngredientsList
              ingredientsForms={mealForm.ingredientsForms}
              ingredientsStats={ingredientsStats}
              mealFormFieldId={mealForm.fieldId}
              mealIndex={index}
              variantIndex={variantIndex}
              onAddIngredients={foodsDrawerDisclosure.onOpen}
              shouldAddRadiusToLastBottomBorder={!mealForm.notes}
            />

            {mealForm.notes && <Notes notes={mealForm.notes} />}

            <EditNotesModal
              isOpen={editNotesModalDisclosure.isOpen}
              onClose={editNotesModalDisclosure.onClose}
              notes={mealForm.notes}
              onEditNotes={mealFormEvents.onEditNotes}
              fieldId={mealForm.fieldId}
              ownerName={mealForm.name}
              size="xl"
              textAreaHeight="150px"
            />

            <FoodsDrawer
              isOpen={foodsDrawerDisclosure.isOpen}
              onClose={foodsDrawerDisclosure.onClose}
              mealName={mealForm.name}
              mealForm={mealForm}
              onSelectedFoods={mealFormEvents.onAddFoods}
            />
          </Flex>
        </PresenceAnimation>
      )}
    </Draggable>
  )
}
Example #24
Source File: index.tsx    From calories-in with MIT License 4 votes vote down vote up
function VariantStats({ ...rest }: Props) {
  const dietForm = useDietForm()
  const { variantsForms, selectedVariantFormIndex } = dietForm
  const selectedVariantForm = variantsForms[selectedVariantFormIndex]
  const variantsDetailsModalDisclosure = useDisclosure()

  const {
    variantStats,
    proteinPercent,
    carbsPercent,
    fatPercent,
    energyDiff,
  } = useVariantStats({ variantFormFieldId: selectedVariantForm.fieldId })

  const { saturatedFat } = variantStats
  const saturatedFatEnergyEstimate = getFatEnergyEstimate(saturatedFat)
  const { energyEstimate } = getStatsEnergiesEstimates(variantStats)
  const saturatedFatPercent = Math.round(
    getMacroEnergyPercent(saturatedFatEnergyEstimate, energyEstimate)
  )

  const hasAtLeastOneMeal = selectedVariantForm.mealsForms.length > 0

  return (
    <VStack
      p={5}
      spacing={3}
      align="stretch"
      alignSelf="flex-start"
      justify="left"
      {...rest}
    >
      <Text fontSize="lg" textAlign="center" textColor="gray.500">
        Daily totals
      </Text>
      <Divider />
      <EnergyStat
        energy={variantStats.energy}
        energyDiff={energyDiff}
        hasAtLeastOneMeal={hasAtLeastOneMeal}
      />

      <VariantStat
        label="Protein"
        detail={`${proteinPercent}%`}
        value={variantStats.protein}
        type="primaryMacro"
        isDisabled={!hasAtLeastOneMeal}
        tooltipLabel="% calories from protein"
      />
      <VariantStat
        label="Carbs"
        detail={`${carbsPercent}%`}
        value={variantStats.carbs}
        type="primaryMacro"
        isDisabled={!hasAtLeastOneMeal}
        tooltipLabel="% calories from carbs"
      />
      <VariantStat
        label="Fat"
        detail={`${fatPercent}%`}
        value={variantStats.fat}
        type="primaryMacro"
        isDisabled={!hasAtLeastOneMeal}
        tooltipLabel="% calories from fat"
      />

      <VariantStat
        label="Saturated fat"
        detail={`${saturatedFatPercent}%`}
        value={variantStats.saturatedFat}
        type="secondaryMacro"
        isDisabled={!hasAtLeastOneMeal}
        tooltipLabel="% calories from saturated fat"
      />
      <VariantStat
        label="Sugar"
        value={variantStats.sugar}
        type="secondaryMacro"
        isDisabled={!hasAtLeastOneMeal}
      />

      <Divider />

      <Button
        colorScheme="teal"
        variant="link"
        leftIcon={<Info size={16} />}
        isDisabled={!hasAtLeastOneMeal}
        onClick={variantsDetailsModalDisclosure.onOpen}
      >
        View details
      </Button>

      <VariantsDetailsModal
        isOpen={variantsDetailsModalDisclosure.isOpen}
        onClose={variantsDetailsModalDisclosure.onClose}
        initialVariantForm={selectedVariantForm}
      />
    </VStack>
  )
}
Example #25
Source File: top-nav.tsx    From notebook with MIT License 4 votes vote down vote up
TopNav: React.SFC<TopNavProps> = ({ handleNoteCreate }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();

  return (
    <>
      <Flex mb={"30px"} align="center">
        <HStack>
          <Box p="2" as={Link} to="/">
            <motion.div whileHover={{ scale: 1.1 }}>
              <Heading
                as="h1"
                size="xl"
                bgGradient="linear(to-l, #7928CA,#FF0080)"
                bgClip="text"
                _focus={{ boxShadow: "none", outline: "none" }}
                _hover={{
                  textDecoration: "none",
                  bgGradient: "linear(to-r, red.500, yellow.500)"
                }}
              >
                Notebook App
              </Heading>
            </motion.div>
          </Box>
        </HStack>
        <Spacer />
        <Box>
          <HStack>
            <HStack d={["none", "none", "block"]}>
              <Button
                leftIcon={<AddIcon />}
                bgGradient="linear(to-l, #7928CA,#FF0080)"
                _hover={{ bgGradient: "linear(to-r, red.500, yellow.500)" }}
                variant="solid"
                size="sm"
                onClick={onOpen}
              >
                Add new note
              </Button>
              <Button
                leftIcon={<ArrowRightIcon />}
                bgGradient="linear(to-l, #7928CA,#FF0080)"
                _hover={{ bgGradient: "linear(to-r, red.500, yellow.500)" }}
                variant="solid"
                size="sm"
                as={Link}
                to="/projects"
              >
                Open source
              </Button>
            </HStack>
            <Box d={["block", "block", "none"]}>
              <Menu>
                <MenuButton
                  as={IconButton}
                  aria-label="Options"
                  icon={<HamburgerIcon />}
                  transition="all 0.2s"
                  size="md"
                  variant="outline"
                  _hover={{ bg: "gray.400" }}
                  _focus={{ boxShadow: "outline" }}
                />
                <MenuList fontSize="sm" zIndex={5}>
                  <MenuItem icon={<AddIcon />} onClick={onOpen}>
                    {" "}
                    <Text textShadow="1px 1px #9c1786">Add new note</Text>
                  </MenuItem>
                  <MenuDivider />
                  <MenuItem icon={<ArrowRightIcon />} as={Link} to="/projects">
                    {" "}
                    <Text textShadow="1px 1px #9c1786">
                      Open source repositories
                    </Text>
                  </MenuItem>
                </MenuList>
              </Menu>
            </Box>
            <ColorModeSwitcher justifySelf="flex-end" />
          </HStack>
        </Box>
      </Flex>
      <NoteForm
        isOpen={isOpen}
        onClose={onClose}
        handleNoteCreate={handleNoteCreate}
      />
    </>
  );
}
Example #26
Source File: TopNavigation.tsx    From website with MIT License 4 votes vote down vote up
TopNavigation: React.FC<TopNavigationProps> = ({ title }) => {
  const { isOpen, onOpen, onClose } = useDisclosure()
  return (
    <Grid
      as="nav"
      templateColumns={`1fr 1fr minmax(auto, ${theme.sizes['6xl']}) 1fr 1fr`}
      backgroundColor="gray.900"
      color="white"
      height={['88px', '80px']}
      zIndex={50}
    >
      <List display="flex" flexWrap="wrap" alignItems="center" gridColumn="3/4" m={0} p={0}>
        <ListItem display="flex" alignItems="center" pos="relative" h="100%" mr="auto">
          <NextChakraLink
            href="/"
            display="flex"
            alignItems="center"
            py=".5rem"
            px="1rem"
            h="100%"
            _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
          >
            <Logo height={40} fill={theme.colors.white} title={title} />
          </NextChakraLink>
        </ListItem>

        <ListItem display={['none', 'flex']} alignItems="center" h="100%">
          <NextChakraLink
            href="/community"
            display="flex"
            alignItems="center"
            py="1.5rem"
            px="1rem"
            color="inherit"
            h="100%"
            lineHeight={1}
            _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
          >
            Komunitas
          </NextChakraLink>
        </ListItem>

        <ListItem display={['none', 'flex']} alignItems="center" h="100%">
          <NextChakraLink
            href="/submit-a-talk"
            display="flex"
            alignItems="center"
            py="1.5rem"
            px="1rem"
            color="inherit"
            h="100%"
            lineHeight={1}
            _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
          >
            Ajukan Topik
          </NextChakraLink>
        </ListItem>

        <ListItem display={['none', 'flex']} alignItems="center" h="100%">
          <NextChakraLink
            href="/faq"
            display="flex"
            alignItems="center"
            py="1.5rem"
            px="1rem"
            color="inherit"
            h="100%"
            lineHeight={1}
            _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
          >
            FAQ
          </NextChakraLink>
        </ListItem>

        <ListItem py="1.5rem" px="1rem" display={['flex', 'none']} alignItems="center" h="100%">
          <IconButton variant="outline" aria-label="Open menu" icon={<HamburgerIcon />} onClick={onOpen} />

          <Drawer isOpen={isOpen} placement="right" onClose={onClose}>
            <DrawerOverlay />
            <DrawerContent>
              <DrawerCloseButton />
              <DrawerHeader>Menu Utama</DrawerHeader>

              <DrawerBody>
                <NextChakraLink
                  href="/community"
                  display="flex"
                  alignItems="center"
                  py="1.5rem"
                  px="1rem"
                  color="inherit"
                  lineHeight={1}
                  _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
                >
                  Komunitas
                </NextChakraLink>

                <NextChakraLink
                  href="/submit-a-talk"
                  display="flex"
                  alignItems="center"
                  py="1.5rem"
                  px="1rem"
                  color="inherit"
                  lineHeight={1}
                  _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
                >
                  Ajukan Topik
                </NextChakraLink>

                <NextChakraLink
                  href="/faq"
                  display="flex"
                  alignItems="center"
                  py="1.5rem"
                  px="1rem"
                  color="inherit"
                  lineHeight={1}
                  _hover={{ bg: 'rgba(255, 255, 255, 0.1)', textDecoration: 'none' }}
                >
                  FAQ
                </NextChakraLink>
              </DrawerBody>
            </DrawerContent>
          </Drawer>
        </ListItem>
      </List>
    </Grid>
  )
}
Example #27
Source File: Inspector.tsx    From openchakra with MIT License 4 votes vote down vote up
Inspector = () => {
  const dispatch = useDispatch()
  const component = useSelector(getSelectedComponent)
  const { isOpen, onOpen, onClose } = useDisclosure()
  const [componentName, onChangeComponentName] = useState('')
  const componentsNames = useSelector(getComponentNames)

  const { clearActiveProps } = useInspectorUpdate()

  const saveComponent = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    dispatch.components.setComponentName({
      componentId: component.id,
      name: componentName,
    })
    onClose()
    onChangeComponentName('')
  }
  const isValidComponentName = useMemo(() => {
    return (
      !!componentName.match(/^[A-Z]\w*$/g) &&
      !componentsNames.includes(componentName) &&
      // @ts-ignore
      !componentsList.includes(componentName)
    )
  }, [componentName, componentsNames])

  const { type, rootParentType, id, children } = component

  const isRoot = id === 'root'
  const parentIsRoot = component.parent === 'root'

  const docType = rootParentType || type
  const componentHasChildren = children.length > 0

  useEffect(() => {
    clearActiveProps()
  }, [clearActiveProps])

  return (
    <>
      <Box bg="white">
        <Box
          fontWeight="semibold"
          fontSize="md"
          color="yellow.900"
          py={2}
          px={2}
          boxShadow="sm"
          bg="yellow.100"
          display="flex"
          justifyContent="space-between"
          flexDir="column"
        >
          {isRoot ? 'Document' : type}
          {!!component.componentName && (
            <Text fontSize="xs" fontWeight="light">
              {component.componentName}
            </Text>
          )}
        </Box>
        {!isRoot && (
          <Stack
            direction="row"
            py={2}
            spacing={2}
            align="center"
            zIndex={99}
            px={2}
            flexWrap="wrap"
            justify="flex-end"
          >
            <CodeActionButton />
            {!component.componentName && (
              <ActionButton
                label="Name component"
                icon={<EditIcon path="" />}
                onClick={onOpen}
              />
            )}
            <ActionButton
              label="Duplicate"
              onClick={() => dispatch.components.duplicate()}
              icon={<CopyIcon path="" />}
            />
            <ActionButton
              label="Reset props"
              icon={<IoMdRefresh />}
              onClick={() => dispatch.components.resetProps(component.id)}
            />
            <ActionButton
              label="Chakra UI Doc"
              as={Link}
              onClick={() => {
                window.open(
                  `https://chakra-ui.com/${docType.toLowerCase()}`,
                  '_blank',
                )
              }}
              icon={<GoRepo />}
            />
            <ActionButton
              bg="red.500"
              label="Remove"
              onClick={() => dispatch.components.deleteComponent(component.id)}
              icon={<FiTrash2 />}
            />
          </Stack>
        )}
      </Box>

      <Box pb={1} bg="white" px={3}>
        <Panels component={component} isRoot={isRoot} />
      </Box>

      <StylesPanel
        isRoot={isRoot}
        showChildren={componentHasChildren}
        parentIsRoot={parentIsRoot}
      />
      <Modal onClose={onClose} isOpen={isOpen} isCentered>
        <ModalOverlay>
          <ModalContent>
            <form onSubmit={saveComponent}>
              <ModalHeader>Save this component</ModalHeader>
              <ModalCloseButton />
              <ModalBody>
                <FormControl isInvalid={!isValidComponentName}>
                  <FormLabel>Component name</FormLabel>
                  <Input
                    size="md"
                    autoFocus
                    variant="outline"
                    isFullWidth
                    focusBorderColor="blue.500"
                    errorBorderColor="red.500"
                    value={componentName}
                    onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                      onChangeComponentName(e.target.value)
                    }
                  />
                  {!isValidComponentName && (
                    <FormErrorMessage>
                      Component name must start with a capital character and
                      must not contain space or special character, and name
                      should not be already taken (including existing chakra-ui
                      components).
                    </FormErrorMessage>
                  )}
                  <FormHelperText>
                    This will name your component that you will see in the code
                    panel as a separated component.
                  </FormHelperText>
                </FormControl>
              </ModalBody>
              <ModalFooter>
                <Button
                  colorScheme="blue"
                  mr={3}
                  type="submit"
                  isDisabled={!isValidComponentName}
                >
                  Save
                </Button>
                <Button onClick={onClose}>Cancel</Button>
              </ModalFooter>
            </form>
          </ModalContent>
        </ModalOverlay>
      </Modal>
    </>
  )
}
Example #28
Source File: IconDetailOverlay.tsx    From lucide with ISC License 4 votes vote down vote up
IconDetailOverlay = ({ open = true, close, icon }) => {
  const toast = useToast();
  const { colorMode } = useColorMode();
  const { tags = [], name } = icon;
  const {color, strokeWidth, size} = useContext(IconStyleContext);
  const iconRef = useRef<SVGSVGElement>(null);
  const [isMobile] = useMediaQuery("(max-width: 560px)")
  const { isOpen, onOpen, onClose } = useDisclosure()

  const handleClose = () => {
    onClose();
    close();
  };

  useEffect(() => {
    if(open) {
      onOpen()
    }
  }, [open])

  const iconStyling = (isLight) => ({
    height: "25vw",
    width: "25vw",
    minHeight: "160px",
    minWidth: "160px",
    maxHeight: "240px",
    maxWidth: "240px",
    color: color,
  });

  const downloadIcon = ({src, name} : IconDownload) => download(src, `${name}.svg`, 'image/svg+xml');

  const copyIcon = ({src, name} : IconDownload) => {
    copy(src);
    toast({
      title: "Copied!",
      description: `Icon "${name}" copied to clipboard.`,
      status: "success",
      duration: 1500,
      isClosable: true
    });
  }

  const downloadPNG = ({src, name}: IconDownload) => {
    const canvas = document.createElement('canvas');
    canvas.width = size;
    canvas.height = size;
    const ctx = canvas.getContext("2d");

    const image = new Image();
    image.src = `data:image/svg+xml;base64,${btoa(src)}`;
    image.onload = function() {
      ctx.drawImage(image, 0, 0);

      const link = document.createElement('a');
      link.download = `${name}.png`;
      link.href = canvas.toDataURL('image/png')
      link.click();
    }
  }

  return (
    <Box
      position="fixed"
      bottom={0}
      zIndex={2}
      width="100%"
      left={0}
      height={0}
      key={name}
    >
      <Slide direction="bottom" in={isOpen} style={{ zIndex: 10 }}>
      <Flex
        alignItems="center"
        justifyContent="space-between"
        pt={4}
        pb={4}
        maxW="850px"
        margin="0 auto"
        w="full"
        px={8}
      >

          <Box
            borderWidth="1px"
            rounded="lg"
            width="full"
            boxShadow={theme.shadows.xl}
            position="relative"
            bg={
              colorMode == "light"
                ? theme.colors.white
                : theme.colors.gray[700]
            }
            padding={8}
          >
            <IconButton
              size="sm"
              aria-label="Close overlay"
              variant="ghost"
              color="current"
              ml="3"
              position="absolute"
              top={4}
              right={4}
              onClick={handleClose}
              icon={<Close />}
          />
            <Flex direction={['column', 'row']} alignItems={['center', 'flex-start']}>
              <Flex>
                <Box
                  borderWidth="1px"
                  rounded="md"
                  position="relative"
                  bg={
                    colorMode == "light"
                      ? theme.colors.whiteAlpha[800]
                      : theme.colors.blackAlpha[500]
                  }
                  padding={0}
                >
                  <div
                    style={iconStyling(colorMode == "light")}
                    className="icon-large"
                  >
                    <IconWrapper
                      content={icon.content}
                      stroke={color}
                      strokeWidth={strokeWidth}
                      height={size}
                      width={size}
                      ref={iconRef}
                    />
                  </div>

                  <svg className="icon-grid" width="24" height="24" viewBox={`0 0 ${size} ${size}`} fill="none" stroke={colorMode == "light" ? '#E2E8F0' : theme.colors.gray[600]} strokeWidth="0.1" xmlns="http://www.w3.org/2000/svg">
                    { Array.from({ length:(size - 1) }, (_, i) => (
                      <g key={`grid-${i}`}>
                        <line key={`horizontal-${i}`} x1={0} y1={i + 1} x2={size} y2={i + 1} />
                        <line key={`vertical-${i}`} x1={i + 1} y1={0} x2={i + 1} y2={size} />
                      </g>
                    )) }
                  </svg>
                </Box>
              </Flex>
              <Flex marginLeft={[0, 8]} w="100%">
                <Box w="100%">
                  <Flex
                    justify={isMobile ? 'center' : 'flex-start'}
                    marginTop={isMobile ? 10 : 0}
                  >
                    <Box
                      position="relative"
                      mb={1}
                      display="inline-block"
                      style={{ cursor: "pointer" }}
                      pr={6}
                    >
                      <Text fontSize="3xl">
                        {icon.name}
                      </Text>
                      { icon?.contributors?.length ? ( <ModifiedTooltip/> ) : null}
                    </Box>
                  </Flex>
                  <Box mb={4}>
                    { tags?.length ? (
                      <Text
                        fontSize="xl"
                        fontWeight="bold"
                        color={
                          colorMode === "light"
                          ? 'gray.600'
                          : 'gray.500'
                        }
                      >
                        { tags.join(' • ') }
                      </Text>
                    ) : ''}

                  {/* <Button size="sm" fontSize="md" variant="ghost" onClick={() => downloadIcon(icon)}>
                    Edit Tags
                  </Button> */}
                  </Box>
                  <Box overflowY="auto" w="100%" pt={1} pb={1}>
                    <ButtonGroup spacing={4}>
                      <Button variant="solid" onClick={() => downloadIcon({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
                        Download SVG
                      </Button>
                      <Button variant="solid" onClick={() => copyIcon({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
                        Copy SVG
                      </Button>
                      <Button variant="solid" onClick={() => downloadPNG({src: iconRef.current.outerHTML, name: icon.name})} mb={1}>
                        Download PNG
                      </Button>
                    </ButtonGroup>
                  </Box>
                  { icon?.contributors?.length ? (
                    <>
                      <Heading as="h5" size="sm" marginTop={4} marginBottom={2}>
                        Contributors:
                      </Heading>
                      <AvatarGroup size="md">
                        { icon.contributors.map((commit, index) => (
                          <Link href={`https://github.com/${commit.author}`} isExternal key={`${index}_${commit.sha}`}>
                            <Tooltip label={commit.author} key={commit.sha}>
                              <Avatar name={commit.author} src={`https://github.com/${commit.author}.png?size=88`} />
                            </Tooltip>
                          </Link>
                        )) }
                      </AvatarGroup>
                    </>
                  ) : null }
                </Box>
              </Flex>
            </Flex>
          </Box>

      </Flex>
      </Slide>
    </Box>
  );
}
Example #29
Source File: notes-list.tsx    From notebook with MIT License 4 votes vote down vote up
NotesList: React.SFC<NotesListProps> = ({
  notes,
  handleClick,
  setNotes
}) => {
  const bg = useColorModeValue("white", "#2f3244");
  const [selectedNote, setSelectedNote] = React.useState<note>();
  const toast = useToast();
  const { isOpen, onOpen, onClose } = useDisclosure();

  const onDelete = (
    id: string,
    e: React.MouseEvent<SVGElement, MouseEvent>
  ) => {
    const newNotes: note[] = notes.filter((note: note) => note.id !== id);
    setNotes(newNotes);
    showToast();
    e.stopPropagation();
  };

  const onClick = (id: string, e: React.MouseEvent<SVGElement, MouseEvent>) => {
    handleClick(id);
    e.stopPropagation();
  };

  const handleSelectedNote = (note: note) => {
    setSelectedNote(note);
    onOpen();
  };

  const showToast = () => {
    toast({
      title: "Note deleted.",
      status: "success",
      position: "top",
      duration: 2000,
      isClosable: true
    });
  };

  return (
    <>
      <AnimateSharedLayout type="crossfade">
        <Box minH={"50vh"}>
          {/* <SimpleGrid
            columns={[1, 2, 2, 3]}
            mt="40px"
            gridGap="10px"
            position="relative"
            overflow="hidden"
          > */}
          <StackGrid columnWidth={330}>
            {notes.map(note => (
              <Fade in={true}>
                <motion.div
                  whileHover={{ y: -10 }}
                  layoutId={note.id}
                  onClick={() => handleSelectedNote(note)}
                >
                  <Center py={2} px={2} key={note.id}>
                    <Box
                      maxH={"400px"}
                      w="100%"
                      boxShadow={"lg"}
                      rounded={"md"}
                      p={6}
                      overflow={"hidden"}
                      cursor="pointer"
                      _hover={{ boxShadow: "xl" }}
                      bg={bg}
                      role="group"
                      // onClick={() => handleClick(note.id, true)}
                    >
                      <Stack>
                        <Flex
                          _groupHover={{ justifyContent: "space-between" }}
                          justifyContent="center"
                          align="center"
                        >
                          <Box>
                            <Text
                              color={"green.500"}
                              textTransform={"uppercase"}
                              fontWeight={800}
                              fontSize={"sm"}
                              letterSpacing={1.1}
                            >
                              Note
                            </Text>
                          </Box>
                          <Box
                            _groupHover={{ display: "block" }}
                            display="none"
                          >
                            <HStack spacing="2">
                              <Icon
                                color={"green.500"}
                                _hover={{ color: "green.600" }}
                                _groupHover={{ display: "block" }}
                                as={EditIcon}
                                w={4}
                                h={4}
                                onClick={e => onClick(note.id, e)}
                              />
                              <Icon
                                color={"green.500"}
                                _hover={{ color: "#ca364a" }}
                                _groupHover={{ display: "block" }}
                                as={DeleteIcon}
                                w={4}
                                h={4}
                                onClick={e => onDelete(note.id, e)}
                              />
                            </HStack>
                          </Box>
                        </Flex>
                        <Heading
                          fontSize={"xl"}
                          fontFamily={"body"}
                          textTransform="capitalize"
                          noOfLines={2}
                        >
                          {note.title}
                        </Heading>

                        <Text
                          color={"gray.500"}
                          fontSize="md"
                          noOfLines={{ base: 3, md: 4 }}
                        >
                          {note.body}
                        </Text>
                      </Stack>
                    </Box>
                  </Center>
                </motion.div>
              </Fade>
            ))}
          </StackGrid>
          {/* </SimpleGrid> */}
        </Box>
        {isOpen ? (
          <NoteModal
            isOpen={isOpen}
            onClose={onClose}
            selectedNote={selectedNote}
          />
        ) : (
          ""
        )}
      </AnimateSharedLayout>
    </>
  );
}