diff --git a/apps/web/src/components/transfer-chain-section.tsx b/apps/web/src/components/transfer-chain-section.tsx index a0d9b760..8d97aa50 100644 --- a/apps/web/src/components/transfer-chain-section.tsx +++ b/apps/web/src/components/transfer-chain-section.tsx @@ -1,6 +1,6 @@ import { ChainConfig, Token } from "../types"; import TransferSection from "./transfer-section"; -import TransferChainSelect from "./transfer-chain-select"; +import TransferChainSelector from "./transfer-chain-selector"; import TransferSwitch from "./transfer-switch"; import ComponentLoading from "../ui/component-loading"; import { Address } from "viem"; @@ -62,7 +62,7 @@ export default function TransferChainSection({
}> - - void; - onTokenChange?: (token: Token) => void; + label: JSX.Element; } -export default function TransferChainSelect({ - chain, - token, - chainOptions, - tokenOptions, - onChainChange, - onTokenChange, -}: Props) { - const [search, setSearch] = useState(""); +export default function TransferChainSelect({ children, label }: PropsWithChildren) { + const [isOpen, setIsOpen] = useState(false); - return ( -
- { - e.stopPropagation(); - }} - onChange={(e) => { - setSearch(e.target.value); - }} - /> -
-
-
- {chainOptions - .filter(({ name }) => name.toLowerCase().includes(search.toLowerCase())) - .map((option) => ( - - ))} -
- - ) : ( -
- No data -
- )} - + const { refs, context, floatingStyles } = useFloating({ + open: isOpen, + onOpenChange: setIsOpen, + placement: "bottom", + middleware: [ + offset(6), + size({ + apply({ rects, elements }) { + Object.assign(elements.floating.style, { width: `${rects.reference.width}px` }); + }, + }), + ], + }); - {tokenOptions.length > 1 ? ( - - ) : null} -
- ); -} + const { styles, isMounted } = useTransitionStyles(context, { + initial: { transform: "translateY(-10px)", opacity: 0 }, + open: { transform: "translateY(0)", opacity: 1 }, + close: { transform: "translateY(-10px)", opacity: 0 }, + }); -function ChainOption({ - selected, - option, - token, - onSelect = () => undefined, -}: { - selected: ChainConfig; - option: ChainConfig; - token: Token; - onSelect?: (chain: ChainConfig) => void; -}) { - const { balanceAll } = useApp(); + const click = useClick(context); + const dismiss = useDismiss(context); + const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]); return ( - - ); -} - -function TokenOption({ - selected, - option, - onSelect = () => undefined, -}: { - selected: Token; - option: Token; - onSelect?: (token: Token) => void; -}) { - return ( - + <> + + {isMounted && ( + +
+
setIsOpen(false)} + style={styles} + > + {children} +
+
+
+ )} + ); } diff --git a/apps/web/src/components/transfer-chain-selector.tsx b/apps/web/src/components/transfer-chain-selector.tsx new file mode 100644 index 00000000..f5eaa705 --- /dev/null +++ b/apps/web/src/components/transfer-chain-selector.tsx @@ -0,0 +1,182 @@ +import { useApp } from "../hooks"; +import { ChainConfig, Token } from "../types"; +import Select from "../ui/select"; +import { formatBalance, getChainLogoSrc, getTokenLogoSrc } from "../utils"; +import { useState } from "react"; +import TransferChainSelect from "./transfer-chain-select"; + +interface Props { + chain: ChainConfig; + token: Token; + chainOptions: ChainConfig[]; + tokenOptions: Token[]; + onChainChange?: (chain: ChainConfig) => void; + onTokenChange?: (token: Token) => void; +} + +export default function TransferChainSelector({ + chain, + token, + chainOptions, + tokenOptions, + onChainChange, + onTokenChange, +}: Props) { + const [search, setSearch] = useState(""); + + return ( +
+ + Chain + {chain.name} + + } + > + {chainOptions.length ? ( + <> +
+ Search + { + e.stopPropagation(); + }} + onChange={(e) => { + setSearch(e.target.value); + }} + /> +
+
+
+ {chainOptions + .filter(({ name }) => name.toLowerCase().includes(search.toLowerCase())) + .map((option) => ( + + ))} +
+ + ) : ( +
+ No data +
+ )} + + + {tokenOptions.length > 1 ? ( + + ) : null} +
+ ); +} + +function ChainOption({ + selected, + option, + token, + onSelect = () => undefined, +}: { + selected: ChainConfig; + option: ChainConfig; + token: Token; + onSelect?: (chain: ChainConfig) => void; +}) { + const { balanceAll } = useApp(); + + return ( + + ); +} + +function TokenOption({ + selected, + option, + onSelect = () => undefined, +}: { + selected: Token; + option: Token; + onSelect?: (token: Token) => void; +}) { + return ( + + ); +}