Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wallet-ext: copy to clipboard use toast for confirmation feedback #7583

Merged
merged 1 commit into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ function AccountAddress({
return address ? (
<span className={cl(st.addressContainer, className)}>
{copyable ? (
<CopyToClipboard txt={address} mode={cpIconMode}>
<CopyToClipboard
txt={address}
mode={cpIconMode}
copySuccessMessage="Address copied"
>
{addressLink}
</CopyToClipboard>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,4 @@
&.plain {
font-weight: 100;
}

&.copied {
transform: scale(150%, 150%);
color: colors.$sui-blue;
opacity: 1;

&.plain {
color: inherit;
}
}
}
40 changes: 7 additions & 33 deletions apps/wallet/src/ui/app/components/copy-to-clipboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@
// SPDX-License-Identifier: Apache-2.0

import cl from 'classnames';
import { memo, useCallback, useEffect, useState } from 'react';

import { useCopyToClipboard } from '../../hooks/useCopyToClipboard';
import Icon, { SuiIcons } from '_components/icon';

import type { ReactNode, MouseEventHandler } from 'react';
import type { ReactNode } from 'react';

import st from './CopyToClipboard.module.scss';

const COPY_CHECKMARK_MILLIS = 600;

export type CopyToClipboardProps = {
txt: string;
children: ReactNode;
copyOnlyOnIconClick?: boolean;
className?: string;
mode?: 'normal' | 'highlighted' | 'plain';
copySuccessMessage?: string;
};

function CopyToClipboard({
Expand All @@ -26,42 +25,17 @@ function CopyToClipboard({
copyOnlyOnIconClick = false,
className,
mode = 'normal',
copySuccessMessage,
}: CopyToClipboardProps) {
const [copied, setCopied] = useState(false);
const copyToClipboard = useCallback<MouseEventHandler<HTMLElement>>(
async (e) => {
e.stopPropagation();
e.preventDefault();
if (!txt) {
return;
}
await navigator.clipboard.writeText(txt);
setCopied(true);
},
[txt]
);
useEffect(() => {
let timeout: number;
if (copied) {
timeout = window.setTimeout(
() => setCopied(false),
COPY_CHECKMARK_MILLIS
);
}
return () => {
if (timeout) {
clearTimeout(timeout);
}
};
}, [copied]);
const copyToClipboard = useCopyToClipboard(txt, { copySuccessMessage });
return (
<span
className={cl(st.container, className)}
onClick={!copyOnlyOnIconClick ? copyToClipboard : undefined}
>
{children}
<Icon
className={cl(st.copyIcon, st[mode], { [st.copied]: copied })}
className={cl(st.copyIcon, st[mode])}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use Tailwind here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can but this component has other usages of css modules and classes and I think it's better to address them in an another PR that will do only that

icon={SuiIcons.Copy}
onClick={copyToClipboard}
title="Copy to clipboard"
Expand All @@ -70,4 +44,4 @@ function CopyToClipboard({
);
}

export default memo(CopyToClipboard);
export default CopyToClipboard;

This file was deleted.

This file was deleted.

24 changes: 0 additions & 24 deletions apps/wallet/src/ui/app/components/sui-object/field/index.tsx

This file was deleted.

94 changes: 0 additions & 94 deletions apps/wallet/src/ui/app/components/sui-object/index.tsx

This file was deleted.

28 changes: 28 additions & 0 deletions apps/wallet/src/ui/app/hooks/useCopyToClipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { type MouseEventHandler, useCallback } from 'react';
import { toast } from 'react-hot-toast';

export type CopyOptions = {
copySuccessMessage?: string;
};

export function useCopyToClipboard(
textToCopy: string,
{ copySuccessMessage = 'Copied' }: CopyOptions = {}
) {
return useCallback<MouseEventHandler>(
async (e) => {
e.stopPropagation();
e.preventDefault();
try {
await navigator.clipboard.writeText(textToCopy);
toast.success(copySuccessMessage);
} catch (e) {
// silence clipboard errors
}
},
[textToCopy, copySuccessMessage]
);
}