Skip to content

Commit

Permalink
Merge pull request #271 from skip-mev/detach-widget
Browse files Browse the repository at this point in the history
Detach widget
  • Loading branch information
codingki authored May 23, 2024
2 parents a722798 + cdd06aa commit f944a72
Show file tree
Hide file tree
Showing 29 changed files with 523 additions and 145 deletions.
2 changes: 1 addition & 1 deletion chain-registry
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@
"date-fns": "^3.3.1",
"dotenv": "^16.4.5",
"download": "^8.0.0",
"kujira.js": "0.9.x",
"match-sorter": "^6.3.3",
"next": "^14.1.0",
"next-seo": "^6.4.0",
"nuqs": "^1.17.4",
"postcss": "^8.4.33",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
8 changes: 2 additions & 6 deletions src/components/AdaptiveLink.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Link, { LinkProps } from "next/link";
import { ComponentPropsWithoutRef, useMemo } from "react";

export type AdaptiveLinkProps = LinkProps & Omit<ComponentPropsWithoutRef<"a">, "href"> & { isExternal?: boolean };
export type AdaptiveLinkProps = ComponentPropsWithoutRef<"a"> & { isExternal?: boolean };

export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: AdaptiveLinkProps) {
const isActuallyExternal = useMemo(() => {
Expand All @@ -11,9 +10,6 @@ export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: A
if (typeof href === "string") {
return href.startsWith("http");
}
if (typeof href === "object") {
return href.href?.startsWith("http");
}
}, [href, isExternal]);

const externalProps = useMemo(() => {
Expand All @@ -25,7 +21,7 @@ export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: A
}, [isActuallyExternal, rel, target]);

return (
<Link
<a
href={href}
{...externalProps}
{...props}
Expand Down
3 changes: 1 addition & 2 deletions src/components/ChainSelect/ChainSelectContent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ArrowLeftIcon } from "@heroicons/react/20/solid";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { matchSorter } from "match-sorter";
import Image from "next/image";
import { useEffect, useMemo, useRef, useState } from "react";

import { Chain } from "@/hooks/useChains";
Expand Down Expand Up @@ -87,7 +86,7 @@ function ChainSelectContent({ chains, onChange, onClose }: Props) {
onClick={() => onChange(chain)}
data-testid="chain-item"
>
<Image
<img
alt={chain.prettyName}
className="h-[48px] w-[48px] rounded-full object-contain"
width={48}
Expand Down
4 changes: 1 addition & 3 deletions src/components/ConnectedWalletButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Image from "next/image";
import { ComponentProps, forwardRef } from "react";

import { cn } from "@/utils/ui";
Expand All @@ -23,8 +22,7 @@ export const ConnectedWalletButton = forwardRef<HTMLButtonElement, Props>(
ref={ref}
>
{walletLogo && (
<Image
unoptimized
<img
height={16}
width={16}
alt={walletName}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dialog/DialogContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function DialogContent({ children, onInteractOutside }: Props) {
return (
<Dialog.Portal container={container.current}>
<Dialog.Content
className="absolute inset-0 z-10 animate-fade-zoom-in rounded-3xl bg-white"
className="absolute inset-0 z-10 animate-fade-zoom-in bg-white"
onInteractOutside={onInteractOutside}
>
{children}
Expand Down
22 changes: 22 additions & 0 deletions src/components/EmbedButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CodeBracketIcon } from "@heroicons/react/20/solid";

import { disclosure } from "@/context/disclosures";
import { cn } from "@/utils/ui";

import { SimpleTooltip } from "./SimpleTooltip";

export const EmbedButton = () => {
return (
<SimpleTooltip label="Embed swap widget">
<button
onClick={() => disclosure.open("embedDialog")}
className={cn(
"rounded-full p-2 text-black/80 hover:bg-neutral-100 hover:text-black/100",
"transition-colors focus:outline-none",
)}
>
<CodeBracketIcon className="h-4 w-4" />
</button>
</SimpleTooltip>
);
};
85 changes: 85 additions & 0 deletions src/components/EmbedDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { ArrowLeftIcon } from "@heroicons/react/20/solid";
import * as Dialog from "@radix-ui/react-dialog";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import toast from "react-hot-toast";

import { useDisclosureKey } from "@/context/disclosures";
import { cn } from "@/utils/ui";

export const EmbedDialog = ({ embedLink }: { embedLink: string }) => {
const [isOpen, { close }] = useDisclosureKey("embedDialog");

const embedCode = `<iframe allow="clipboard-read; clipboard-write" src="${embedLink}" height="820" width="450" />`;

return (
<Dialog.Root
modal
open={isOpen}
>
<Dialog.Content className="absolute inset-0 animate-fade-zoom-in rounded-3xl bg-white">
<div className="flex h-full flex-col space-y-2 px-4 py-6">
<div className="flex items-center gap-4 pb-2">
<button
className="flex h-8 w-8 items-center justify-center rounded-full transition-colors hover:bg-neutral-100"
onClick={close}
>
<ArrowLeftIcon className="h-6 w-6" />
</button>
<h3 className="text-xl font-bold">Embed Swap Widget</h3>
<div className="flex-grow" />
</div>
<ScrollArea.Root
className={cn(
"relative isolate -mx-4 overflow-hidden",
"before:absolute before:inset-x-0 before:bottom-0 before:z-10 before:h-2",
)}
>
<ScrollArea.Viewport className="h-full w-full px-6">
<div className="flex flex-col space-y-2">
<p>The swap widget can be embedded in your app by using the following code snippet:</p>
<pre className="text-wrap break-all rounded-lg border bg-neutral-50 p-2 font-mono text-xs">
{embedCode}
</pre>
<button
onClick={() => {
try {
navigator.clipboard.writeText(embedCode);
toast.success("Copied to clipboard");
} catch (error) {
toast.error("Failed to copy link to clipboard");
}
}}
className={cn(
"self-end rounded-md bg-[#FF486E] px-2 py-1 text-xs font-semibold uppercase text-white disabled:bg-red-200",
)}
>
Copy to clipboard
</button>

<p className="pt-4 text-sm">
<strong>Note: </strong>You can customize the default swap route by modifying the query parameters for
more information visit the{" "}
<a
href="https://api-docs.skip.money/docs"
target="_blank"
rel="noreferrer"
className="text-[#FF486E]"
>
docs
</a>
</p>
</div>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar
className="z-20 flex touch-none select-none transition-colors ease-out data-[orientation=horizontal]:h-2 data-[orientation=vertical]:w-2 data-[orientation=horizontal]:flex-col"
orientation="vertical"
>
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-neutral-500/50 transition-colors before:absolute before:left-1/2 before:top-1/2 before:h-2 before:w-2 before:-translate-x-1/2 before:-translate-y-1/2 before:content-[''] hover:bg-neutral-500" />
</ScrollArea.Scrollbar>
<ScrollArea.Corner />
</ScrollArea.Root>
</div>
</Dialog.Content>
</Dialog.Root>
);
};
7 changes: 4 additions & 3 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Image from "next/image";
import Link from "next/link";

import { AdaptiveLink } from "./AdaptiveLink";

function Footer() {
return (
<div className="relative flex flex-row items-center justify-center space-x-0 px-4 py-8 sm:py-12">
<p className="text-sm text-black sm:text-base">Crafted by</p>
<Link
<AdaptiveLink
href="https://skip.money/"
target="_blank"
>
Expand All @@ -20,7 +21,7 @@ function Footer() {
}}
/>
</div>
</Link>
</AdaptiveLink>
</div>
);
}
Expand Down
7 changes: 3 additions & 4 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import Link from "next/link";

import { AdaptiveLink } from "./AdaptiveLink";
import { IbcFunLogo } from "./IbcFunLogo";

function Header() {
return (
<nav className="relative flex items-center justify-center px-4 py-8 sm:py-12">
<Link href="/">
<AdaptiveLink href="/">
<IbcFunLogo className="h-8 sm:h-16" />
</Link>
</AdaptiveLink>
</nav>
);
}
Expand Down
25 changes: 15 additions & 10 deletions src/components/PreviewRoute/ChainStep.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ArrowRightIcon, FingerPrintIcon, PencilSquareIcon } from "@heroicons/react/20/solid";
import { RouteResponse } from "@skip-router/core";
import Image from "next/image";
import { Dispatch, SetStateAction, useEffect, useMemo } from "react";
import toast from "react-hot-toast";
import { FaExternalLinkAlt, FaKeyboard } from "react-icons/fa";
Expand Down Expand Up @@ -195,7 +194,7 @@ export const ChainStep = ({
)}
>
<div className="flex h-full w-full items-center justify-center rounded-full bg-white p-1">
<Image
<img
src={chain?.logoURI || "/logo-fallback.png"}
width={48}
height={48}
Expand Down Expand Up @@ -307,14 +306,17 @@ export const ChainStep = ({
<SimpleTooltip label={chainAddress.address}>
<button
onClick={() => {
navigator.clipboard.writeText(chainAddress.address || "");
toast.success("Address copied to clipboard");
try {
navigator.clipboard.writeText(chainAddress.address || "");
toast.success("Address copied to clipboard");
} catch (error) {
toast.error("Failed to copy address to clipboard");
}
}}
className="opacity-50"
>
{chainAddress?.source !== "input" ? (
<Image
unoptimized
<img
height={16}
width={16}
alt={"wallet"}
Expand Down Expand Up @@ -347,8 +349,7 @@ export const ChainStep = ({
{chainAddress?.address && !isIntermidiaryChain && (
<>
{chainAddress?.source !== "input" ? (
<Image
unoptimized
<img
height={16}
width={16}
alt={"wallet"}
Expand All @@ -369,8 +370,12 @@ export const ChainStep = ({
>
<button
onClick={() => {
navigator.clipboard.writeText(chainAddress.address || "");
toast.success("Address copied to clipboard");
try {
navigator.clipboard.writeText(chainAddress.address || "");
toast.success("Address copied to clipboard");
} catch (error) {
toast.error("Failed to copy address to clipboard");
}
}}
>
<p className={cn("text-md font-semibold", isNotFocused && "font-normal text-neutral-400")}>
Expand Down
4 changes: 1 addition & 3 deletions src/components/PreviewRoute/SetAddressDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ArrowLeftIcon } from "@heroicons/react/20/solid";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { Chain } from "@skip-router/core";
import { PublicKey } from "@solana/web3.js";
import Image from "next/image";
import { useMemo, useState } from "react";
import { FaKeyboard } from "react-icons/fa";
import { MdCheck, MdClose } from "react-icons/md";
Expand Down Expand Up @@ -183,8 +182,7 @@ export const SetAddressDialog = ({
disabled={chainType === "svm" && wallet.isAvailable !== true}
>
{wallet.walletInfo.logo && (
<Image
unoptimized
<img
height={36}
width={36}
alt={wallet.walletPrettyName}
Expand Down
29 changes: 29 additions & 0 deletions src/components/ShareButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ShareIcon } from "@heroicons/react/20/solid";
import toast from "react-hot-toast";

import { cn } from "@/utils/ui";

import { SimpleTooltip } from "./SimpleTooltip";

export const ShareButton = ({ shareableLink }: { shareableLink: string }) => {
return (
<SimpleTooltip label="Share">
<button
onClick={() => {
try {
navigator.clipboard.writeText(shareableLink);
toast.success("Link copied to clipboard");
} catch (error) {
toast.error("Failed to copy link to clipboard");
}
}}
className={cn(
"rounded-full p-2 text-black/80 hover:bg-neutral-100 hover:text-black/100",
"transition-colors focus:outline-none",
)}
>
<ShareIcon className="h-4 w-4" />
</button>
</SimpleTooltip>
);
};
Loading

0 comments on commit f944a72

Please sign in to comment.