-
Notifications
You must be signed in to change notification settings - Fork 227
feat(qrcode): add hover-to-copy functionality #2851 #3345
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
1d8afdd
933eb53
0a5b51a
4d0bd8f
224d790
549176e
2335131
9250b9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| import ReactQRCode from "react-qr-code"; | ||
| import { classNames, useTheme } from "~/app/utils"; | ||
| import { useState } from "react"; | ||
| import { useTranslation } from "react-i18next"; | ||
| import { CopyIcon } from "@bitcoin-design/bitcoin-icons-react/filled"; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use popicons |
||
|
|
||
| export type Props = { | ||
| value: string; | ||
|
|
@@ -15,21 +18,56 @@ export type Props = { | |
| // (meaning you have to aim your phone very precisely and have to wait longer for the reader | ||
| // to recognize the QR code) | ||
| level?: "Q" | undefined; | ||
| onCopy?: () => void; | ||
| }; | ||
|
|
||
| export default function QRCode({ value, size, level, className }: Props) { | ||
| export default function QRCode({ | ||
| value, | ||
| size, | ||
| level, | ||
| className, | ||
| onCopy, | ||
| }: Props) { | ||
| const theme = useTheme(); | ||
| const fgColor = theme === "dark" ? "#FFFFFF" : "#000000"; | ||
| const bgColor = theme === "dark" ? "#000000" : "#FFFFFF"; | ||
| const { t } = useTranslation("components"); | ||
| const [isHovering, setIsHovering] = useState(false); | ||
|
|
||
| const handleCopy = () => { | ||
| navigator.clipboard.writeText(value); | ||
| onCopy?.(); | ||
| }; | ||
|
Comment on lines
+29
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling for clipboard API.
🛡️ Proposed fix const handleCopy = () => {
- navigator.clipboard.writeText(value);
- toast.success(t("actions.copied_to_clipboard"));
+ navigator.clipboard.writeText(value)
+ .then(() => {
+ toast.success(t("actions.copied_to_clipboard"));
+ })
+ .catch((err) => {
+ console.error("Failed to copy:", err);
+ toast.error(t("actions.copy_failed"));
+ });
};Alternatively, using async/await: - const handleCopy = () => {
- navigator.clipboard.writeText(value);
- toast.success(t("actions.copied_to_clipboard"));
+ const handleCopy = async () => {
+ try {
+ await navigator.clipboard.writeText(value);
+ toast.success(t("actions.copied_to_clipboard"));
+ } catch (err) {
+ if (err instanceof Error) {
+ toast.error(err.message);
+ }
+ }
};Note: You may need to add a translation key for the error case (e.g., 🤖 Prompt for AI Agents |
||
|
|
||
| return ( | ||
| <ReactQRCode | ||
| value={value} | ||
| size={size} | ||
| fgColor={fgColor} | ||
| bgColor={bgColor} | ||
| className={classNames("w-full h-auto rounded-md", className ?? "")} | ||
| level={level} | ||
| /> | ||
| <div | ||
| className="relative cursor-pointer" | ||
| onClick={handleCopy} | ||
| onMouseEnter={() => setIsHovering(true)} | ||
| onMouseLeave={() => setIsHovering(false)} | ||
| > | ||
| <ReactQRCode | ||
| value={value} | ||
| size={size} | ||
| fgColor={fgColor} | ||
| bgColor={bgColor} | ||
| className={classNames( | ||
| "w-full h-auto rounded-md transition-opacity", | ||
| isHovering ? "opacity-80" : "opacity-100", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for hover why we need to use state varbiles? can use tailwind here only? eg. |
||
| className ?? "" | ||
| )} | ||
| level={level} | ||
| /> | ||
| {isHovering && ( | ||
| <div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 rounded-md"> | ||
| <div className="flex flex-col items-center"> | ||
| <CopyIcon className="h-8 w-8 text-white" /> | ||
| <span className="text-white font-medium mt-2"> | ||
| {t("allowance_menu.qrcode.click_to_copy")} | ||
| </span> | ||
| </div> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,6 +74,7 @@ function Receive() { | |
| value={lightningAddress} | ||
| size={192} | ||
| level="Q" | ||
| onCopy={() => toast.success("Copied to clipboard")} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this new callback was introduced? just to show success message? can't we do same within the qr code component? |
||
| /> | ||
| </> | ||
| )} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1216,7 +1216,10 @@ | |
| "always_allow": "Always allow", | ||
| "always_reject": "Always reject" | ||
| }, | ||
| "website_permissions": "Website Permissions" | ||
| "website_permissions": "Website Permissions", | ||
| "qrcode": { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we already have copy_clipboard and copied_to_clipboard in common section of translations. always check before introducing new ones |
||
| "click_to_copy": "Click to copy" | ||
| } | ||
| }, | ||
| "qrcode_scanner": { | ||
| "title": "Scan QR Code", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why new library for just one icon. we use popicons by default. and i guess copy icon should be there as well PopiconsCopyLine