@material-ui/core#SvgIcon TypeScript Examples

The following examples show how to use @material-ui/core#SvgIcon. 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: social.tsx    From lobis-frontend with MIT License 6 votes vote down vote up
export default function Social() {
    return (
        <div className="social-row">
            <Link href="https://github.com/LobisHQWorkspace" target="_blank">
                <SvgIcon color="primary" component={GitHub} />
            </Link>

            <Link href="https://twitter.com/LobisHQ" target="_blank">
                <SvgIcon color="primary" component={Twitter} />
            </Link>

            <Link href="https://discord.gg/2X44WhkFHz" target="_blank">
                <SvgIcon color="primary" component={Discord} />
            </Link>
        </div>
    );
}
Example #2
Source File: AdrHeader.tsx    From log4brains with Apache License 2.0 6 votes vote down vote up
function getRepositoryIcon(provider: string): JSX.Element {
  switch (provider) {
    case "github":
      return (
        <SvgIcon>
          <GithubRIcon />
        </SvgIcon>
      );
      break;

    case "gitlab":
      return (
        <SvgIcon>
          <GitlabRIcon />
        </SvgIcon>
      );
      break;

    case "bitbucket":
      return (
        <SvgIcon>
          <BitbucketRIcon />
        </SvgIcon>
      );
      break;

    default:
      return (
        <SvgIcon>
          <GitRIcon />
        </SvgIcon>
      );
      break;
  }
}
Example #3
Source File: social.tsx    From rugenerous-frontend with MIT License 6 votes vote down vote up
export default function Social() {
  return (
    <div className="social-row">
      <Link href="https://github.com/Rugenerous" target="_blank">
        <SvgIcon color="primary" component={GitHub} />
      </Link>

      <Link href="https://twitter.com/rugenerous" target="_blank">
        <SvgIcon color="primary" component={Twitter} />
      </Link>

      <Link href="https://discord.gg/eKxwjUYUPc" target="_blank">
        <SvgIcon color="primary" component={Discord} />
      </Link>
    </div>
  );
}
Example #4
Source File: AzurePipelinesIcon.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
AzurePipelinesIcon = (props: SvgIconProps) => (
  <SvgIcon {...props} viewBox="0 0 512 512">
    <path
      fill="none"
      stroke="currentColor"
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="32"
      d="M461.81 53.81a4.4 4.4 0 00-3.3-3.39c-54.38-13.3-180 34.09-248.13 102.17a294.9 294.9 0 00-33.09 39.08c-21-1.9-42-.3-59.88 7.5-50.49 22.2-65.18 80.18-69.28 105.07a9 9 0 009.8 10.4l81.07-8.9a180.29 180.29 0 001.1 18.3 18.15 18.15 0 005.3 11.09l31.39 31.39a18.15 18.15 0 0011.1 5.3 179.91 179.91 0 0018.19 1.1l-8.89 81a9 9 0 0010.39 9.79c24.9-4 83-18.69 105.07-69.17 7.8-17.9 9.4-38.79 7.6-59.69a293.91 293.91 0 0039.19-33.09c68.38-68 115.47-190.86 102.37-247.95zM298.66 213.67a42.7 42.7 0 1160.38 0 42.65 42.65 0 01-60.38 0z"
    />
    <path
      fill="none"
      stroke="currentColor"
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="32"
      d="M109.64 352a45.06 45.06 0 00-26.35 12.84C65.67 382.52 64 448 64 448s65.52-1.67 83.15-19.31A44.73 44.73 0 00160 402.32"
    />
  </SvgIcon>
)
Example #5
Source File: ExpandIcon.tsx    From clearflask with Apache License 2.0 6 votes vote down vote up
ExpandIcon = (props: {
  expanded?: boolean,
  onExpandChanged?: (expanded: boolean) => void,
  IconButtonProps?: React.ComponentProps<typeof IconButton>,
  IconProps?: React.ComponentProps<typeof SvgIcon>,
}) => {
  const classes = useStyles();
  const { expanded, ...SvgIconProps } = props;
  return (
    <IconButton
      onClick={e => props.onExpandChanged?.(!props.expanded)}
      {...props.IconButtonProps}
    >
      <Icon
        {...SvgIconProps}
        className={classNames(
          classes.expandIcon,
          !!expanded && classes.expandIconExpanded,
          props.IconProps?.className,
        )}
      />
    </IconButton>
  );
}
Example #6
Source File: social.tsx    From wonderland-frontend with MIT License 6 votes vote down vote up
export default function Social() {
    return (
        <div className="social-row">
            <Link href="https://github.com/Wonderland-Money/wonderland-frontend" target="_blank">
                <SvgIcon color="primary" component={GitHub} />
            </Link>

            <Link href="https://twitter.com/wonderland_fi?s=21" target="_blank">
                <SvgIcon color="primary" component={Twitter} />
            </Link>

            <Link href="https://t.me/joinchat/6UybL5rJMEhjN2Y5" target="_blank">
                <SvgIcon viewBox="0 0 32 32" color="primary" component={Telegram} />
            </Link>

            <Link href="https://discord.gg/thDHseaHUt" target="_blank">
                <SvgIcon color="primary" component={Discord} />
            </Link>
        </div>
    );
}
Example #7
Source File: Minus.tsx    From storefront with MIT License 5 votes vote down vote up
Minus: React.VFC<SvgIconProps> = (props) => <SvgIcon {...props} component={MinusSVG} />
Example #8
Source File: index.tsx    From knests with MIT License 5 votes vote down vote up
export default function Google(props) {
  return (
    <SvgIcon {...props}>
      <path d="M21,12.2177419 C21,13.9112905 20.6311475,15.4233869 19.8934426,16.7540323 C19.1557377,18.0846776 18.1168031,19.1249998 16.7766393,19.875 C15.4364756,20.6250002 13.8934424,21 12.147541,21 C10.4999998,21 8.97540984,20.5947579 7.57377049,19.7842742 C6.17213115,18.9737905 5.05942604,17.8790323 4.23565574,16.5 C3.41188543,15.1209677 3,13.6209679 3,12 C3,10.3790321 3.41188543,8.87903226 4.23565574,7.5 C5.05942604,6.12096774 6.17213115,5.02620949 7.57377049,4.21572581 C8.97540984,3.40524212 10.4999998,3 12.147541,3 C14.5327871,3 16.5737705,3.78629051 18.2704918,5.35887097 L15.7991803,7.71774194 C15.0122953,6.96774175 14.0655738,6.52016129 12.9590164,6.375 C11.9262295,6.22983871 10.9057375,6.375 9.89754098,6.81048387 C8.88934445,7.24596774 8.07786904,7.89919355 7.46311475,8.77016129 C6.79918033,9.71370968 6.46721311,10.7903228 6.46721311,12 C6.46721311,13.0403228 6.72540984,13.9899192 7.24180328,14.8487903 C7.75819672,15.7076615 8.4467215,16.3971776 9.30737705,16.9173387 C10.1680326,17.4374998 11.1147541,17.6975806 12.147541,17.6975806 C13.2540984,17.6975806 14.2254096,17.455645 15.0614754,16.9717742 C15.7254098,16.5846772 16.2786885,16.0645161 16.7213115,15.4112903 C17.0409838,14.8790321 17.2499998,14.3467744 17.3483607,13.8145161 L12.147541,13.8145161 L12.147541,10.6935484 L20.852459,10.6935484 C20.9508199,11.2258066 21,11.7338712 21,12.2177419 Z" />
    </SvgIcon>
  );
}
Example #9
Source File: Pin.tsx    From storefront with MIT License 5 votes vote down vote up
Pin: React.VFC<SvgIconProps> = (props) => <SvgIcon {...props} component={PinSVG} />
Example #10
Source File: AzureGitTagsIcon.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
AzureGitTagsIcon = (props: SvgIconProps) => (
  <SvgIcon {...props} viewBox="0 0 32 32">
    <path d="M22.5 12C23.8807 12 25 10.8807 25 9.5C25 8.11929 23.8807 7 22.5 7C21.1193 7 20 8.11929 20 9.5C20 10.8807 21.1193 12 22.5 12ZM18.6842 3C17.6695 3 16.6927 3.38568 15.9516 4.07892L3.77041 15.4742C2.01578 17.1157 1.96966 19.8841 3.66863 21.5831L9.99455 27.909C11.6543 29.5687 14.3452 29.5687 16.005 27.909L27.8282 16.0858C28.5783 15.3356 28.9998 14.3182 28.9998 13.2574V6.5C28.9998 4.567 27.4328 3 25.4998 3H18.6842ZM17.3179 5.53946C17.6884 5.19284 18.1769 5 18.6842 5H25.4998C26.3282 5 26.9998 5.67157 26.9998 6.5V13.2574C26.9998 13.7878 26.789 14.2965 26.414 14.6716L14.5907 26.4948C13.7121 27.3735 12.2874 27.3735 11.4088 26.4948L5.08284 20.1689C4.18339 19.2694 4.20781 17.8038 5.13673 16.9348L17.3179 5.53946Z" />
  </SvgIcon>
)
Example #11
Source File: DAOStatsRow.tsx    From homebase-app with MIT License 5 votes vote down vote up
IconContainer = styled(SvgIcon)({
  width: "auto",
  height: 64,
})
Example #12
Source File: head.tsx    From sphinx-win-linux-desktop with MIT License 5 votes vote down vote up
function BotIcon() {
  return (
    <SvgIcon viewBox="64 64 896 896" height="21">
      <path d="M300 328a60 60 0 10120 0 60 60 0 10-120 0zM852 64H172c-17.7 0-32 14.3-32 32v660c0 17.7 14.3 32 32 32h680c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-32 660H204V128h616v596zM604 328a60 60 0 10120 0 60 60 0 10-120 0zm250.2 556H169.8c-16.5 0-29.8 14.3-29.8 32v36c0 4.4 3.3 8 7.4 8h729.1c4.1 0 7.4-3.6 7.4-8v-36c.1-17.7-13.2-32-29.7-32zM664 508H360c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z" />
    </SvgIcon>
  );
}
Example #13
Source File: index.tsx    From knests with MIT License 5 votes vote down vote up
export default function Facebook(props) {
  return (
    <SvgIcon {...props}>
      <path d="M9.53144612,22.005 L9.53144612,13.0552149 L6.44166667,13.0552149 L6.44166667,9.49875 L9.53144612,9.49875 L9.53144612,6.68484375 C9.53144612,5.19972656 9.95946769,4.04680661 10.8155103,3.22608401 C11.6715529,2.4053613 12.808485,1.995 14.2263057,1.995 C15.3766134,1.995 16.3129099,2.04710915 17.0351961,2.15132812 L17.0351961,5.3169726 L15.1090998,5.3169726 C14.3868137,5.3169726 13.8919142,5.47330073 13.6244006,5.78595698 C13.4103902,6.04650407 13.3033846,6.46337874 13.3033846,7.03658198 L13.3033846,9.49875 L16.71418,9.49875 L16.2326559,13.0552149 L13.3033846,13.0552149 L13.3033846,22.005 L9.53144612,22.005 Z" />
    </SvgIcon>
  );
}
Example #14
Source File: createMaterialIcon.ts    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
export function createMaterialIcon(Icon: ComponentType): typeof SvgIcon {
  return createSvgIcon(
    createElement(Icon),
    Icon.displayName || 'OPTControlIcon',
  );
}
Example #15
Source File: Cart.tsx    From storefront with MIT License 5 votes vote down vote up
Cart: React.VFC<SvgIconProps> = (props) => <SvgIcon {...props} component={CartSVG} />
Example #16
Source File: AdvancedSettings.tsx    From lobis-frontend with MIT License 5 votes vote down vote up
function AdvancedSettings({ open, handleClose, slippage, recipientAddress, onRecipientAddressChange, onSlippageChange }: IAdvancedSettingsProps) {
    return (
        <Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
            <Paper className="ohm-card ohm-popover">
                <div className="cross-wrap">
                    <IconButton onClick={handleClose}>
                        <SvgIcon color="primary" component={XIcon} />
                    </IconButton>
                </div>

                <Box className="card-content">
                    <InputLabel htmlFor="slippage">
                        <p className="input-lable">Slippage</p>
                    </InputLabel>
                    <FormControl variant="outlined" color="primary" fullWidth>
                        <OutlinedInput
                            id="slippage"
                            value={slippage}
                            onChange={onSlippageChange}
                            fullWidth
                            type="number"
                            //@ts-ignore
                            max="100"
                            min="100"
                            className="bond-input"
                            endAdornment={
                                <InputAdornment position="end">
                                    <p className="percent">%</p>
                                </InputAdornment>
                            }
                        />
                        <div className="help-text">
                            <p className="text-bond-desc">Transaction may revert if price changes by more than slippage %</p>
                        </div>
                    </FormControl>
                </Box>
            </Paper>
        </Modal>
    );
}
Example #17
Source File: AdvancedSettings.tsx    From rugenerous-frontend with MIT License 5 votes vote down vote up
function AdvancedSettings({
  open,
  handleClose,
  slippage,
  recipientAddress,
  onRecipientAddressChange,
  onSlippageChange,
}: IAdvancedSettingsProps) {
  const [value, setValue] = useState(slippage);

  useEffect(() => {
    let timeount: any = null;
    clearTimeout(timeount);

    timeount = setTimeout(() => onSlippageChange(value), 1000);
    return () => clearTimeout(timeount);
  }, [value]);

  return (
    <Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
      <Paper className="ohm-card ohm-popover">
        <div className="cross-wrap">
          <IconButton onClick={handleClose}>
            <SvgIcon color="primary" component={XIcon} />
          </IconButton>
        </div>

        <p className="hades-title">Settings</p>

        <Box className="card-content">
          <InputLabel htmlFor="slippage">
            <p className="input-lable">Slippage</p>
          </InputLabel>
          <FormControl variant="outlined" color="primary" fullWidth>
            <OutlinedInput
              id="slippage"
              value={value}
              onChange={(e: any) => setValue(e.target.value)}
              fullWidth
              type="number"
              className="bond-input"
              endAdornment={
                <InputAdornment position="end">
                  <p className="percent">%</p>
                </InputAdornment>
              }
            />
            <div className="help-text">
              <p className="text-bond-desc">Transaction may revert if price changes by more than slippage %</p>
            </div>
          </FormControl>

          <InputLabel htmlFor="recipient">
            <p className="input-lable">Recipient Address</p>
          </InputLabel>
          <FormControl variant="outlined" color="primary" fullWidth>
            <OutlinedInput
              className="bond-input"
              id="recipient"
              value={recipientAddress}
              onChange={onRecipientAddressChange}
              type="text"
            />
            <div className="help-text">
              <p className="text-bond-desc">
                Choose recipient address. By default, this is your currently connected address
              </p>
            </div>
          </FormControl>
        </Box>
      </Paper>
    </Modal>
  );
}
Example #18
Source File: price-units.tsx    From wonderland-frontend with MIT License 5 votes vote down vote up
priceUnits = (bond: IAllBondData) => {
    if (bond.name === mim.name) return <SvgIcon component={MimImg} viewBox="0 0 32 32" style={{ height: "15px", width: "15px" }} />;

    return "$";
}
Example #19
Source File: Account.tsx    From storefront with MIT License 5 votes vote down vote up
Account: React.VFC<SvgIconProps> = (props) => <SvgIcon {...props} component={AccountSVG} />
Example #20
Source File: index.tsx    From wonderland-frontend with MIT License 4 votes vote down vote up
function Wrap({ open, handleClose }: IAdvancedSettingsProps) {
    const dispatch = useDispatch();
    const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();

    const [value, setValue] = useState("");

    const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);

    const memoBalance = useSelector<IReduxState, string>(state => {
        return state.account.balances && state.account.balances.memo;
    });
    const wmemoBalance = useSelector<IReduxState, string>(state => {
        return state.account.balances && state.account.balances.wmemo;
    });

    const wrapValue = useSelector<IReduxState, string>(state => {
        return state.wrapping && state.wrapping.wrapValue;
    });

    const wrapPrice = useSelector<IReduxState, number>(state => {
        return state.wrapping && state.wrapping.wrapPrice;
    });

    const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
        return state.pendingTransactions;
    });

    const memoAllowance = useSelector<IReduxState, number>(state => {
        return state.account.wrapping && state.account.wrapping.memo;
    });

    const [isWrap, setIsWrap] = useState(true);
    const [isWrapPrice, setIsWrapPrice] = useState(true);

    const setMax = () => {
        if (isWrap) {
            setValue(memoBalance);
        } else {
            setValue(wmemoBalance);
        }
    };

    const handleSwap = () => {
        setValue("");
        const value = !isWrap;
        setIsWrap(value);
        setIsWrapPrice(value);
    };

    const handleValueChange = (e: any) => {
        const value = e.target.value;
        setValue(value);
    };

    useEffect(() => {
        dispatch(calcWrapDetails({ isWrap, provider, value, networkID: chainID }));
    }, [value]);

    useEffect(() => {
        dispatch(calcWrapPrice({ isWrap: isWrapPrice, provider, networkID: chainID }));
    }, [isWrapPrice]);

    const onClose = () => {
        setValue("");
        setIsWrap(true);
        setIsWrapPrice(true);
        dispatch(calcWrapDetails({ isWrap, provider, value: "", networkID: chainID }));
        handleClose();
    };

    const hasAllowance = useCallback(() => memoAllowance > 0, [memoAllowance]);

    const trimmedMemoBalance = trim(Number(memoBalance), 6);
    const trimmedWmemoBalance = trim(Number(wmemoBalance), 6);

    const getBalance = () => (isWrap ? `${trimmedMemoBalance} MEMO` : `${trimmedWmemoBalance} wMEMO`);

    const handleOnWrap = async () => {
        if (await checkWrongNetwork()) return;

        if (value === "" || parseFloat(value) === 0) {
            dispatch(warning({ text: isWrap ? messages.before_wrap : messages.before_unwrap }));
        } else {
            await dispatch(changeWrap({ isWrap, value, provider, networkID: chainID, address }));
            setValue("");
        }
    };

    const onSeekApproval = async () => {
        if (await checkWrongNetwork()) return;

        await dispatch(changeApproval({ address, provider, networkID: chainID }));
    };

    return (
        <Modal id="hades" open={open} onClose={onClose} hideBackdrop>
            <Paper className="ohm-card ohm-popover wrap-token-poper">
                <div className="cross-wrap wrap-cros-wrap">
                    <IconButton onClick={onClose}>
                        <SvgIcon color="primary" component={XIcon} />
                    </IconButton>
                    <div className="wrap-price" onClick={() => setIsWrapPrice(!isWrapPrice)}>
                        <p>
                            1 {isWrapPrice ? "MEMO" : "wMEMO"} = {`${trim(wrapPrice, 4)} ${isWrapPrice ? "wMEMO" : "MEMO"}`}
                        </p>
                    </div>
                </div>

                <div className="wrap-header-conteiner">
                    <p className="wrap-header-title">{isWrap ? "Wrap" : "Unwrap"}</p>
                    <p className="wrap-header-balance">Balance: {isAppLoading ? <Skeleton width="80px" /> : <>{getBalance()}</>}</p>
                </div>

                <div className="wrap-container">
                    <OutlinedInput
                        placeholder="Amount"
                        value={value}
                        onChange={handleValueChange}
                        fullWidth
                        type="number"
                        className="bond-input wrap-input"
                        startAdornment={
                            <InputAdornment position="start">
                                <div className="wrap-action-input-text">
                                    <p>{isWrap ? "MEMO" : "wMEMO"}</p>
                                </div>
                            </InputAdornment>
                        }
                        endAdornment={
                            <InputAdornment position="end">
                                <div onClick={setMax} className="wrap-action-input-btn">
                                    <p>Max</p>
                                </div>
                            </InputAdornment>
                        }
                    />
                    <div className="wrap-toggle">
                        <IconButton onClick={handleSwap}>
                            <SvgIcon color="primary" component={ArrowsIcon} />
                        </IconButton>
                    </div>
                    <OutlinedInput
                        placeholder="Amount"
                        value={wrapValue}
                        disabled
                        fullWidth
                        type="number"
                        className="bond-input wrap-input"
                        startAdornment={
                            <InputAdornment position="start">
                                <div className="wrap-action-input-text">
                                    <p>{isWrap ? "wMEMO" : "MEMO"}</p>
                                </div>
                            </InputAdornment>
                        }
                    />
                    {hasAllowance() ? (
                        <div
                            className="wrap-btn"
                            onClick={() => {
                                const inPending = isWrap ? isPendingTxn(pendingTransactions, "wrapping") : isPendingTxn(pendingTransactions, "unwrapping");
                                if (inPending) return;
                                handleOnWrap();
                            }}
                        >
                            <p>{isWrap ? txnButtonText(pendingTransactions, "wrapping", "Wrap") : txnButtonText(pendingTransactions, "unwrapping", "Unwrap")}</p>
                        </div>
                    ) : (
                        <div
                            className="wrap-btn"
                            onClick={() => {
                                if (isPendingTxn(pendingTransactions, "approve_wrapping")) return;
                                onSeekApproval();
                            }}
                        >
                            <p>{txnButtonText(pendingTransactions, "approve_wrapping", "Approve")}</p>
                        </div>
                    )}
                    {!hasAllowance() && (
                        <div className="wrap-help-text">
                            <p>Note: The "Approve" transaction is only needed when</p>
                            <p>wrapping for the first time; subsequent wrapping only</p>
                            <p>requires you to perform the "Wrap" transaction.</p>
                        </div>
                    )}
                </div>
            </Paper>
        </Modal>
    );
}
Example #21
Source File: index.tsx    From rugenerous-frontend with MIT License 4 votes vote down vote up
function Zapin({ open, handleClose, bond }: IZapinProps) {
  const { tokens } = useTokens();
  const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
  const dispatch = useDispatch();

  const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
  const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
    return state.pendingTransactions;
  });

  let defaultToken = tokens.find(token => token.name === avax.name);

  // if (bond.name === wavax.name) {
  //   defaultToken = tokens.find(token => token.name === mim.name);
  // }

  const [quantity, setQuantity] = useState<string>("");
  //@ts-ignore
  const [token, setToken] = useState<IAllTokenData>(defaultToken);
  const [chooseTokenOpen, setChooseTokenOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [slippage, setSlippage] = useState(2);
  const [recipientAddress, setRecipientAddress] = useState(address);
  const [swapInfo, setSwapInfo] = useState<ITokenZapinResponse>({ swapData: "", swapTarget: "", amount: "" });
  const [priceToken, setPriceToken] = useState<number>(0);

  const [loading, setLoading] = useState(false);

  const hasAllowance = useCallback(() => {
    return token.allowance > 0;
  }, [token.allowance]);

  const onSeekApproval = async () => {
    if (await checkWrongNetwork()) return;

    dispatch(changeApproval({ address, token, provider, networkID: chainID }));
  };

  const onMint = async () => {
    if (await checkWrongNetwork()) return;

    if (!swapInfo.amount || !swapInfo.swapData || !swapInfo.swapTarget) {
      return dispatch(warning({ text: messages.something_wrong }));
    }

    dispatch(
      zapinMint({
        provider,
        networkID: chainID,
        bond,
        token,
        value: quantity,
        minReturnAmount: swapInfo.amount,
        swapTarget: swapInfo.swapTarget,
        swapData: swapInfo.swapData,
        slippage,
        address,
      }),
    );
  };

  const onRecipientAddressChange = (value: any) => {
    return setRecipientAddress(value);
  };

  const onSlippageChange = (value: any) => {
    return setSlippage(value);
  };

  const setMax = () => {
    const maxBondPriceToken = bond.maxBondPriceToken / priceToken;
    let amount: any = Math.min(maxBondPriceToken, token.isAvax ? token.balance * 0.99 : token.balance);

    if (amount) {
      amount = trim(amount);
    }

    setQuantity((amount || "").toString());
  };

  useEffect(() => {
    if (address) setRecipientAddress(address);
  }, [provider, address]);

  useEffect(() => {
    let timeount: any = null;

    clearTimeout(timeount);

    if (Number(quantity) > 0) {
      setLoading(true);
      timeount = setTimeout(async () => {
        const info = await calcZapinDetails({
          token,
          provider,
          networkID: chainID,
          bond,
          value: quantity,
          slippage,
          dispatch,
        });
        if (info.amount) {
          const amount = utils.formatEther(info.amount);
          dispatch(calcBondDetails({ bond, value: amount, provider, networkID: chainID }));
        } else {
          dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
        }
        setSwapInfo(info);
        setLoading(false);
      }, 1000);
    } else {
      setSwapInfo({ swapData: "", swapTarget: "", amount: "" });
      dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
      setLoading(false);
    }
    return () => clearTimeout(timeount);
  }, [quantity, slippage]);

  useEffect(() => {
    setTimeout(async () => {
      const { amount } = await calcZapinDetails({
        token,
        provider,
        networkID: chainID,
        bond,
        value: "1",
        slippage,
        dispatch,
      });
      if (amount) {
        const amountValue = utils.formatEther(amount);
        setPriceToken(Number(amountValue));
      }
    }, 500);
  }, [token, slippage]);

  let minimumReceivedAmount = "0";

  if (swapInfo.amount) {
    const minimumReceivedAmountValue = utils.formatEther(swapInfo.amount);
    minimumReceivedAmount = trim(Number(minimumReceivedAmountValue), 6);
  }

  const handleChooseTokenOpen = () => {
    setChooseTokenOpen(true);
  };

  const handleChooseTokenClose = () => {
    setChooseTokenOpen(false);
  };

  const handleChooseTokenSelect = (token: IAllTokenData) => {
    setQuantity("");
    setToken(token);
    setChooseTokenOpen(false);
  };

  const handleSettingsOpen = () => {
    setSettingsOpen(true);
  };

  const handleSettingsClose = () => {
    setSettingsOpen(false);
  };

  const isLoading = isBondLoading || loading;

  return (
    <Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
      <Paper className="ohm-card ohm-popover zapin-poper">
        <div className="cross-wrap">
          <IconButton onClick={handleClose}>
            <SvgIcon color="primary" component={XIcon} />
          </IconButton>
          <IconButton style={{ marginLeft: "auto" }} onClick={handleSettingsOpen}>
            <SvgIcon color="primary" component={SettingsIcon} />
          </IconButton>
        </div>
        <Box className="card-content">
          <div className="zapin-header">
            <div className="zapin-header-token-select-wrap">
              <p className="zapin-header-token-select-title">Zapin & Mint</p>
              <OutlinedInput
                type="number"
                placeholder="Amount"
                className="zapin-header-token-select-input"
                value={quantity}
                onChange={e => setQuantity(e.target.value)}
                labelWidth={0}
                startAdornment={
                  <InputAdornment position="start">
                    <div onClick={handleChooseTokenOpen} className="zapin-header-token-select-input-token-select">
                      <img className="zapin-header-token-select-input-token-select-logo" src={token.img} alt="" />
                      <p>{token.name}</p>
                      <Box display="flex" alignItems="center" justifyContent="center" width={"16px"}>
                        <img src={ArrowUpImg} style={{ height: "16px", width: "16px" }} />
                      </Box>
                    </div>
                  </InputAdornment>
                }
                endAdornment={
                  <InputAdornment position="end">
                    <div className="zapin-header-token-select-input-btn" onClick={setMax}>
                      <p>Max</p>
                    </div>
                  </InputAdornment>
                }
              />
              {hasAllowance() || token.isAvax ? (
                <div
                  className="zapin-header-token-select-btn"
                  onClick={async () => {
                    if (isPendingTxn(pendingTransactions, "zapin_" + token.name + "_" + bond.name)) return;
                    await onMint();
                  }}
                >
                  <p>{txnButtonText(pendingTransactions, "zapin_" + token.name + "_" + bond.name, "Mint")}</p>
                </div>
              ) : (
                <div
                  className="zapin-header-token-select-btn"
                  onClick={async () => {
                    if (isPendingTxn(pendingTransactions, "approve_" + token.address)) return;
                    await onSeekApproval();
                  }}
                >
                  <p>{txnButtonText(pendingTransactions, "approve_" + token.address, "Approve")}</p>
                </div>
              )}
            </div>
            {!hasAllowance() && !token.isAvax && (
              <div className="zapin-header-help-text">
                <p>Note: The "Approve" transaction is only needed when bonding for the first rug</p>
                <p>for each token; subsequent bonding only requires you to perform the</p>
                <p>"zapin&mint" transaction.</p>
              </div>
            )}
          </div>
          <div className="zapin-body">
            <div className="zapin-body-header">
              <BondLogo bond={bond} />
              <div className="zapin-body-header-name">
                <p>TX settings</p>
              </div>
            </div>
            <div className="zapin-body-params">
              <div className="data-row">
                <p className="data-row-name">Destination token </p>
                <p className="data-row-value">{bond.displayName}</p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Slippage Tolerance</p>
                <p className="data-row-value">{trim(slippage)}%</p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Your Balance</p>
                <p className="data-row-value">{`${trim(token.balance, 6)} ${token.name}`}</p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Minimum Received Amount</p>
                <p className="data-row-value">
                  {isLoading ? <Skeleton width="100px" /> : `${minimumReceivedAmount} ${bond.displayUnits}`}
                </p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Approximately you will get</p>
                <p className="data-row-value">
                  {isLoading ? <Skeleton width="100px" /> : `~ ${trim(bond.bondQuote, 4)} RUG`}
                </p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Max You Can Buy</p>
                <p className="data-row-value">
                  {isLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} RUG`}
                </p>
              </div>
              <div className="data-row">
                <p className="data-row-name">ROI</p>
                <p className="data-row-value">
                  {isLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}
                </p>
              </div>
              <div className="data-row">
                <p className="data-row-name">Minimum purchase</p>
                <p className="data-row-value">0.01 RUG</p>
              </div>
              {recipientAddress !== address && (
                <div className="data-row">
                  <p className="data-row-name">Recipient</p>
                  <p className="data-row-value">{shorten(recipientAddress)}</p>
                </div>
              )}
            </div>
          </div>
          <ChooseToken
            open={chooseTokenOpen}
            handleClose={handleChooseTokenClose}
            handleSelect={handleChooseTokenSelect}
            bond={bond}
          />
          <AdvancedSettings
            open={settingsOpen}
            handleClose={handleSettingsClose}
            slippage={slippage}
            recipientAddress={recipientAddress}
            onRecipientAddressChange={onRecipientAddressChange}
            onSlippageChange={onSlippageChange}
          />
        </Box>
      </Paper>
    </Modal>
  );
}
Example #22
Source File: index.tsx    From react-app-architecture with Apache License 2.0 4 votes vote down vote up
export default function Header(): ReactElement {
  const classes = useStyles();
  const history = useHistory();
  const { isLoggedIn, data: authData } = useStateSelector(({ authState }) => authState);
  const user = authData?.user;

  const isWriter = checkRole(user, Roles.WRITER);
  const isEditor = checkRole(user, Roles.EDITOR);

  const [openAuthDialog, setOpenAuthDialog] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [popupMoreAnchorEl, setPopupMoreAnchorEl] = useState<HTMLElement | null>(null);
  const isPopupMenuOpen = Boolean(popupMoreAnchorEl);
  const dispatch = useDispatch();

  function handlePopupMenuClose() {
    setPopupMoreAnchorEl(null);
  }

  function handlePopupMenuOpen(event: MouseEvent<HTMLElement>) {
    setPopupMoreAnchorEl(event.currentTarget);
  }

  function toggleDrawer() {
    setDrawerOpen(!drawerOpen);
  }

  const renderProfileView = (onClick: (event: MouseEvent<HTMLButtonElement>) => void) => {
    if (!user) return null;
    return (
      <CardActionArea onClick={onClick}>
        {user.profilePicUrl ? (
          <CardHeader
            title={user.name.split(' ')[0]}
            avatar={
              <Avatar className={classes.avatar} aria-label={user.name} src={user.profilePicUrl} />
            }
          />
        ) : (
          <CardHeader title={user.name.split(' ')[0]} avatar={<FirstLetter text={user.name} />} />
        )}
      </CardActionArea>
    );
  };

  const popupMenuId = 'menu-popup';
  const popupMenu = (
    <Menu
      anchorEl={popupMoreAnchorEl}
      anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
      id={popupMenuId}
      keepMounted
      transformOrigin={{ vertical: 'top', horizontal: 'right' }}
      open={isPopupMenuOpen}
      onClose={handlePopupMenuClose}
      PopoverClasses={{ paper: classes.paper }}
    >
      {isLoggedIn && renderProfileView(handlePopupMenuClose)}
      {isWriter && (
        <MenuItem
          className={classes.menuItem}
          onClick={() => {
            history.push('/write/blog');
            handlePopupMenuClose();
          }}
        >
          <IconButton color="inherit">
            <CreateIcon />
          </IconButton>
          <p>Write Blog</p>
        </MenuItem>
      )}
      {isWriter && (
        <MenuItem
          className={classes.menuItem}
          onClick={() => {
            history.push('/writer/blogs');
            handlePopupMenuClose();
          }}
        >
          <IconButton color="inherit">
            <ListIcon />
          </IconButton>
          <p>My Blogs</p>
        </MenuItem>
      )}
      {isEditor && (
        <MenuItem
          className={classes.menuItem}
          onClick={() => {
            history.push('/editor/blogs');
            handlePopupMenuClose();
          }}
        >
          <IconButton color="inherit">
            <SupervisorAccountIcon />
          </IconButton>
          <p>Blogs Admin</p>
        </MenuItem>
      )}
      {isLoggedIn && (
        <MenuItem
          className={classes.menuItem}
          onClick={() => {
            dispatch(logout());
            handlePopupMenuClose();
          }}
        >
          <IconButton color="inherit">
            <SvgIcon>
              <path d={mdiLogout} />
            </SvgIcon>
          </IconButton>
          <p>Logout</p>
        </MenuItem>
      )}
    </Menu>
  );

  const mobileDrawerMenu = (
    <Drawer anchor="top" open={drawerOpen} onClose={toggleDrawer}>
      {isLoggedIn && renderProfileView(toggleDrawer)}
      <List component="nav">
        {[
          {
            title: 'About Project',
            href: 'https://github.com/afteracademy/react-app-architecture',
            icon: <InfoIcon />,
          },
          {
            title: 'Contact',
            href: 'https://github.com/afteracademy/react-app-architecture/issues',
            icon: <EmailIcon />,
          },
        ].map(({ title, href, icon }, position) => (
          <ListItem
            key={position}
            className={classes.drawerItem}
            button
            href={href}
            target="_blank"
            onClick={toggleDrawer}
            component="a"
          >
            <ListItemIcon className={classes.drawerIcon}>{icon}</ListItemIcon>
            <ListItemText primary={title} />
          </ListItem>
        ))}
        {[{ title: 'Blogs', link: '/blogs', icon: <WebIcon /> }].map(
          ({ title, link, icon }, position) => (
            <ListItem
              key={position}
              className={classes.drawerItem}
              button
              component={Link}
              to={link}
              onClick={toggleDrawer}
            >
              <ListItemIcon className={classes.drawerIcon}>{icon}</ListItemIcon>
              <ListItemText primary={title} />
            </ListItem>
          ),
        )}
        {isWriter && <Divider />}
        {isWriter &&
          [
            { title: 'Write Blog', link: '/write/blog', icon: <CreateIcon /> },
            { title: 'My Blogs', link: '/writer/blogs', icon: <WebIcon /> },
          ].map(({ title, link, icon }, position) => (
            <ListItem
              key={position}
              className={classes.drawerItem}
              button
              component={Link}
              to={link}
              onClick={toggleDrawer}
            >
              <ListItemIcon className={classes.drawerIcon}>{icon}</ListItemIcon>
              <ListItemText primary={title} />
            </ListItem>
          ))}
        <Divider />
        {isEditor && <Divider />}
        {isEditor &&
          [{ title: 'Blog Admin', link: '/editor/blogs', icon: <SupervisorAccountIcon /> }].map(
            ({ title, link, icon }, position) => (
              <ListItem
                key={position}
                className={classes.drawerItem}
                button
                component={Link}
                to={link}
                onClick={toggleDrawer}
              >
                <ListItemIcon className={classes.drawerIcon}>{icon}</ListItemIcon>
                <ListItemText primary={title} />
              </ListItem>
            ),
          )}
        {isLoggedIn && (
          <ListItem
            className={classes.drawerItem}
            onClick={() => {
              dispatch(logout());
              toggleDrawer();
            }}
            button
          >
            <ListItemIcon className={classes.drawerIcon}>
              <SvgIcon>
                <path d={mdiLogout} />
              </SvgIcon>
            </ListItemIcon>
            <ListItemText primary="Logout" />
          </ListItem>
        )}
        {!isLoggedIn && (
          <ListItem
            className={classes.drawerItem}
            onClick={() => {
              setOpenAuthDialog(true);
              toggleDrawer();
            }}
            button
          >
            <ListItemIcon className={classes.drawerIcon}>
              <SvgIcon>
                <path d={mdiLogin} />
              </SvgIcon>
            </ListItemIcon>
            <ListItemText primary="Login" />
          </ListItem>
        )}
      </List>
      <div className={classes.drawerCloseButtonContainer}>
        <IconButton className={classes.drawerCloseButton} onClick={toggleDrawer}>
          <CloseIcon />
        </IconButton>
      </div>
    </Drawer>
  );

  return (
    <div className={classes.root}>
      <AppBar position="fixed" color="secondary" className={classes.appbar}>
        <Toolbar>
          <Avatar
            alt="Logo"
            src={afterAcademyLogo}
            className={classes.logo}
            component={Link}
            to={'/'}
          />
          <Typography variant="h6" className={classes.brandName}>
            AfterAcademy React
          </Typography>
          <div className={classes.sectionDesktop}>
            {[
              {
                title: 'About Project',
                href: 'https://github.com/afteracademy/react-app-architecture',
              },
              {
                title: 'Contact',
                href: 'https://github.com/afteracademy/react-app-architecture/issues',
              },
            ].map(({ title, href }, position) => (
              <Button
                key={position}
                color="inherit"
                className={classes.button}
                href={href}
                target="_blank"
              >
                {title}
              </Button>
            ))}
            {[{ title: 'Blogs', link: '/blogs' }].map(({ title, link }, position) => (
              <Button
                key={position}
                color="inherit"
                className={classes.button}
                component={Link}
                to={link}
              >
                {title}
              </Button>
            ))}
            {user?.profilePicUrl ? (
              <Avatar alt={user.name} src={user.profilePicUrl} className={classes.avatar} />
            ) : (
              user?.name && <FirstLetter text={user.name} />
            )}
            {isLoggedIn ? (
              <IconButton
                aria-label="show more"
                aria-haspopup="true"
                onClick={handlePopupMenuOpen}
                color="primary"
              >
                <MenuIcon />
              </IconButton>
            ) : (
              <Fab
                variant="extended"
                size="medium"
                color="primary"
                aria-label="login"
                className={classes.loginButton}
                onClick={() => setOpenAuthDialog(true)}
              >
                Login
              </Fab>
            )}
          </div>
          <div className={classes.sectionMobile}>
            <IconButton
              aria-label="show more"
              aria-haspopup="true"
              color="inherit"
              onClick={toggleDrawer}
            >
              <MenuIcon />
            </IconButton>
          </div>
        </Toolbar>
      </AppBar>
      {popupMenu}
      {mobileDrawerMenu}
      <AuthDialog open={openAuthDialog} onClose={() => setOpenAuthDialog(false)} />
    </div>
  );
}
Example #23
Source File: Landing.tsx    From homebase-app with MIT License 4 votes vote down vote up
Landing: React.FC = () => {
  const theme = useTheme();
  const isExtraSmall = useMediaQuery(theme.breakpoints.down("xs"));

  return (
    <Background
      container
      direction="column"
      justifyContent="space-between"
      wrap="nowrap"
    >
      {!isExtraSmall && (
        <Grid item>
          <Header />
        </Grid>
      )}
      <Grid item>
        <Grid container justifyContent="center">
          <Grid item>
            <MainContainer item>
              <Grid
                container
                justify="space-between"
                direction={isExtraSmall ? "column-reverse" : "row"}
                style={isExtraSmall ? { gap: 50 } : {}}
              >
                <Grid item xs>
                  <Grid
                    container
                    direction="column"
                    style={{ gap: 32 }}
                    justifyContent="center"
                  >
                    {!isExtraSmall && (
                      <Grid item>
                        <TitleText>Tezos Homebase</TitleText>
                      </Grid>
                    )}

                    <Grid item>
                      <SubtitleText align={isExtraSmall ? "center" : "left"}>
                        Homebase is a web application that enables users to
                        create and manage/use DAOs on the Tezos blockchain. This
                        application aims to help empower community members and
                        developers to launch and participate in Tezos-based DAOs
                      </SubtitleText>
                    </Grid>
                    <Grid item>
                      <Grid
                        container
                        style={{ gap: 16 }}
                        wrap="nowrap"
                        justifyContent={isExtraSmall ? "center" : "flex-start"}
                      >
                        <Grid item>
                          <Link href="/explorer" underline="none">
                            <MainButton variant="contained" color="secondary">
                              Enter App
                            </MainButton>
                          </Link>
                        </Grid>
                        <Grid item>
                          <Link href="/faq" underline="none">
                            <MainButton variant="contained" color="secondary">
                              Learn More
                            </MainButton>
                          </Link>
                        </Grid>
                      </Grid>
                    </Grid>
                  </Grid>
                </Grid>
                <Grid item xs>
                  <Grid
                    container
                    direction="column"
                    alignItems="flex-end"
                    justify="center"
                    style={{ gap: 20 }}
                  >
                    {isExtraSmall && (
                      <Grid item>
                        <TitleText>Tezos Homebase</TitleText>
                      </Grid>
                    )}
                    <Grid item>
                      <LogoContainer>
                        <BigLogo src={HomebaseLogo} />
                      </LogoContainer>
                    </Grid>
                  </Grid>
                </Grid>
              </Grid>
            </MainContainer>
          </Grid>
        </Grid>
      </Grid>

      <Grid item>
        <StyledToolbar
          container
          direction="row"
          alignItems="center"
          wrap="wrap"
          justifyContent={isExtraSmall ? "center" : "flex-start"}
          style={{ gap: 25 }}
        >
          <Grid item>
            <Link
              target="_blank"
              href="https://github.com/dOrgTech/homebase-app"
            >
              <IconContainer>
                <GitHubIcon color="secondary" />
              </IconContainer>
            </Link>
          </Grid>
          <Grid item>
            <Link target="_blank" href="https://discord.gg/XufcBNu277">
              <IconContainer>
                <SvgIcon>
                  <DiscordIcon />
                </SvgIcon>
              </IconContainer>
            </Link>
          </Grid>
        </StyledToolbar>
      </Grid>
    </Background>
  );
}
Example #24
Source File: PaymentMethods.tsx    From storefront with MIT License 4 votes vote down vote up
PaymentMethods: React.VFC<Props> = ({
  customer,
  onSubmit,
  paymentMethod: initialPaymentMethod,
}) => {
  const creditCardFormRef = useRef<HTMLFormElement>(null);

  const [paymentMethod, setPaymentMethod] = useState(initialPaymentMethod);
  const [loading, setLoading] = useState(false);

  const { data: { paymentGateways } = { data: undefined }, loading: paymentGatewaysLoading } =
    usePaymentGatewaysQuery();

  const handleSubmitCreditCard = async (values: CreditCardFormData) => {
    setLoading(true);
    const data = await makePayment(process.env.BRAINTREE_TOKENIZATION_KEY, {
      billingAddress: {
        postalCode: customer.billing?.postcode ?? undefined,
      },
      cvv: values.ccCsc,
      expirationDate: values.ccExp,
      number: values.ccNumber,
    });
    setLoading(false);
    onSubmit({
      creditCard: {
        cardType: data.cardType,
        lastFour: data.lastFour,
      },
      paymentMethod,
      paymentNonce: data.nonce,
    });
  };

  const handleSubmit = () => {
    if (creditCardFormRef.current != null) {
      if (creditCardFormRef.current.checkValidity()) {
        // The following line is not working anymore for some reason:
        // creditCardFormRef.current.dispatchEvent(new Event('submit', { cancelable: true }));
        // So I have overridden the `submit` method, see in `CreditCardForm`
        creditCardFormRef.current.submit();
      } else {
        creditCardFormRef.current.reportValidity();
      }
    }
    if (paymentMethod === 'braintree_paypal') {
      onSubmit({ paymentMethod });
    }
  };

  const handleChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
    setPaymentMethod(ev.target.value);
  };

  return (
    <>
      <RadioGroup name="paymentMode" value={paymentMethod} onChange={handleChange}>
        {paymentGateways?.nodes?.map(
          (paymentGateway) =>
            paymentGateway != null && (
              <Box
                key={paymentGateway.id}
                component="label"
                htmlFor={`paymentMode-${paymentGateway.id}`}
                sx={{
                  alignItems: 'center',
                  backgroundColor: 'background.paper',
                  cursor: 'pointer',
                  display: 'flex',
                  mb: 2,
                  p: 2,
                }}
              >
                <div>
                  <Radio value={paymentGateway.id} id={`paymentMode-${paymentGateway.id}`} />
                </div>
                <Box sx={{ flexGrow: 1, ml: 2 }}>
                  <Typography variant="h5">{paymentGateway.title}</Typography>
                  {paymentGateway.icon != null ? (
                    <img src={paymentGateway.icon} alt="" height="24" />
                  ) : (
                    paymentGateway.id === 'braintree_cc' && (
                      <>
                        <SvgIcon component={AmexSvg} viewBox="0 0 30 30" fontSize="large" />{' '}
                        <SvgIcon component={VisaSvg} viewBox="0 0 30 30" fontSize="large" />
                      </>
                    )
                  )}
                  {!isBlank(paymentGateway.description) && (
                    <Typography variant="body2">{paymentGateway.description}</Typography>
                  )}
                  {paymentGateway.id === 'braintree_cc' && paymentMethod === paymentGateway.id && (
                    <CreditCardForm ref={creditCardFormRef} onSubmit={handleSubmitCreditCard} />
                  )}
                </Box>
              </Box>
            ),
        )}
      </RadioGroup>
      <Box sx={{ mt: 2 }}>
        <Button
          type="submit"
          color="primary"
          loading={paymentGatewaysLoading || loading}
          onClick={handleSubmit}
        >
          Continue to Review Your Order
        </Button>
      </Box>
    </>
  );
}
Example #25
Source File: SearchBox.tsx    From log4brains with Apache License 2.0 4 votes vote down vote up
export function SearchBox(props: SearchBoxProps) {
  const classes = useStyles();

  const {
    onOpen,
    onClose,
    open: openProp,
    onQueryChange,
    query,
    results,
    loading = false,
    ...otherProps
  } = props;

  const [open, setOpenState] = useControlled({
    controlled: openProp,
    default: false,
    name: "SearchBox",
    state: "open"
  });

  const handleOpen = (event: React.ChangeEvent<{}>) => {
    if (open) {
      return;
    }
    setOpenState(true);
    if (onOpen) {
      onOpen(event);
    }
  };

  const router = useRouter();

  const handleClose = (
    event: React.ChangeEvent<{}>,
    reason: AutocompleteCloseReason
  ) => {
    if (!open) {
      return;
    }
    setOpenState(false);
    if (onClose) {
      onClose(event, reason);
    }
  };

  let noOptionsText: React.ReactNode = "Type to start searching";
  if (loading) {
    noOptionsText = (
      <div style={{ textAlign: "center" }}>
        <CircularProgress size={20} />
      </div>
    );
  } else if (query) {
    noOptionsText = "No matching documents";
  }

  return (
    <Autocomplete
      {...otherProps}
      classes={{ paper: classes.acPaper }}
      options={results ?? []}
      getOptionLabel={(result) => result.title}
      renderInput={(params) => (
        <SearchBar
          {...params}
          open={open}
          onClear={(event) =>
            onQueryChange && onQueryChange(event, "", "clear")
          }
          className={classes.searchBar}
        />
      )}
      inputValue={query}
      onInputChange={(event, value, reason) => {
        // We don't want to replace the inputValue by the selected value
        if (reason !== "reset" && onQueryChange) {
          onQueryChange(event, value, reason);
        }
      }}
      open={open}
      onOpen={handleOpen}
      onClose={handleClose}
      filterOptions={(r) => r} // We hijack Autocomplete's behavior to display search results as options
      renderOption={(result) => (
        <>
          <SvgIcon fontSize="small">
            <AdrIcon />
          </SvgIcon>
          <Typography className={classes.resultTitle}>
            {result.title}
          </Typography>
        </>
      )}
      noOptionsText={noOptionsText}
      onChange={async (_, result) => {
        if (result) {
          await router.push(result.href);
        }
      }}
    />
  );
}