fix: DNS copy buttons don't trigger/show tooltips like "Copied" (#4160)

## Description

closes #4152

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
This commit is contained in:
Ivan Starkov authored and GitHub committed 2024-09-25 20:36:50 +03:00
1 parent 329ddea871
commit d7af39652a
4 files changed
+87 -58

No files matched your search

@@ -36,6 +36,7 @@ import { $publisherHost } from "~/shared/nano-states";
import { extractCname } from "./cname";
import { useEffectEvent } from "~/shared/hook-utils/effect-event";
import DomainCheckbox from "./domain-checkbox";
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
export type Domain = Project["domainsVirtual"][number];
@@ -45,21 +46,6 @@ const InputEllipsis = styled(InputField, {
},
});
const CopyToClipboard = (props: { text: string }) => {
return (
<Tooltip content={"Copy to clipboard"}>
<NestedInputButton
type="button"
onClick={() => {
navigator.clipboard.writeText(props.text);
}}
>
<CopyIcon />
</NestedInputButton>
</Tooltip>
);
};
export const getStatus = (projectDomain: Domain) =>
projectDomain.verified
? (`VERIFIED_${projectDomain.status}` as const)
@@ -456,24 +442,48 @@ const DomainItem = (props: {
<InputEllipsis
readOnly
value={cnameRecord.host}
suffix={<CopyToClipboard text={cnameRecord.host} />}
suffix={
<CopyToClipboard text={cnameRecord.host}>
<NestedInputButton type="button">
<CopyIcon />
</NestedInputButton>
</CopyToClipboard>
}
/>
<InputEllipsis
readOnly
value={cnameRecord.value}
suffix={<CopyToClipboard text={cnameRecord.value} />}
suffix={
<CopyToClipboard text={cnameRecord.value}>
<NestedInputButton type="button">
<CopyIcon />
</NestedInputButton>
</CopyToClipboard>
}
/>
<InputEllipsis readOnly value="TXT" />
<InputEllipsis
readOnly
value={txtRecord.host}
suffix={<CopyToClipboard text={txtRecord.host} />}
suffix={
<CopyToClipboard text={txtRecord.host}>
<NestedInputButton type="button">
<CopyIcon />
</NestedInputButton>
</CopyToClipboard>
}
/>
<InputEllipsis
readOnly
value={txtRecord.value}
suffix={<CopyToClipboard text={txtRecord.value} />}
suffix={
<CopyToClipboard text={txtRecord.value}>
<NestedInputButton type="button">
<CopyIcon />
</NestedInputButton>
</CopyToClipboard>
}
/>
</Grid>
@@ -56,6 +56,7 @@ import { isFeatureEnabled } from "@webstudio-is/feature-flags";
import type { Templates } from "@webstudio-is/sdk";
import { formatDistance } from "date-fns/formatDistance";
import DomainCheckbox, { domainToPublishName } from "./domain-checkbox";
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
type ChangeProjectDomainProps = {
project: Project;
@@ -778,18 +779,11 @@ const ExportContent = (props: { projectId: Project["id"] }) => {
value={npxCommand}
/>
<Tooltip content={"Copy to clipboard"}>
<Button
type="button"
color="neutral"
onClick={() => {
navigator.clipboard.writeText(npxCommand);
}}
prefix={<CopyIcon />}
>
<CopyToClipboard text={npxCommand}>
<Button type="button" color="neutral" prefix={<CopyIcon />}>
Copy
</Button>
</Tooltip>
</CopyToClipboard>
</Flex>
</Grid>
<Grid columns={1} gap={2}>
@@ -820,21 +814,17 @@ const ExportContent = (props: { projectId: Project["id"] }) => {
.trimStart()
.replace(/ +$/, "")}
/>
<Tooltip content={"Copy to clipboard"}>
<CopyToClipboard text={deployTargets[deployTarget].command}>
<Button
type="button"
css={{ flexShrink: 0 }}
color="neutral"
onClick={() => {
navigator.clipboard.writeText(
deployTargets[deployTarget].command
);
}}
prefix={<CopyIcon />}
>
Copy
</Button>
</Tooltip>
</CopyToClipboard>
</Flex>
</Grid>
<Grid columns={1} gap={1}>
@@ -0,0 +1,42 @@
import { Tooltip } from "@webstudio-is/design-system";
import { useState } from "react";
export const CopyToClipboard = ({
text,
copyText = "Copy to clipboard",
copiedText = "Copied",
children,
}: {
text: string;
copyText?: string;
copiedText?: string;
children: React.ReactNode;
}) => {
const [isCopied, setIsCopied] = useState(false);
return (
<div
style={{ display: "contents" }}
onClick={() => {
navigator.clipboard.writeText(text);
setIsCopied(true);
}}
>
<Tooltip
// Tooltip sometimes receives onOpenChange with isOpen=false immediately after a click.
// Changing the key seems like a workaround to address this issue.
key={isCopied ? "copied" : "copy"}
disableHoverableContent
content={isCopied ? copiedText : copyText}
open={isCopied === true ? true : undefined}
onOpenChange={(isOpen) => {
if (isOpen === false) {
setIsCopied(false);
}
}}
>
{children}
</Tooltip>
</div>
);
};
@@ -31,6 +31,7 @@ import {
} from "@webstudio-is/icons";
import { Fragment, useState, type ComponentProps, type ReactNode } from "react";
import { useIds } from "../form-utils";
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
const Item = (props: ComponentProps<typeof Flex>) => (
<Flex
@@ -316,35 +317,21 @@ const SharedLinkItem = ({
hasProPlan,
}: SharedLinkItemType) => {
const [currentName, setCurrentName] = useState(value.name);
const [isCopied, setIsCopied] = useState(false);
return (
<Box className={itemStyle()}>
<Label css={{ flexGrow: 1 }}>{currentName}</Label>
<Tooltip
content={isCopied ? "Copied" : "Copy link"}
open={isCopied === true ? true : undefined}
onOpenChange={(isOpen) => {
if (isOpen === false) {
setIsCopied(false);
}
}}
<CopyToClipboard
text={builderUrl({
authToken: value.token,
mode: value.relation === "viewers" ? "preview" : "edit",
})}
copyText="Copy link"
>
<IconButton
aria-label="Copy link"
onClick={() => {
navigator.clipboard.writeText(
builderUrl({
authToken: value.token,
mode: value.relation === "viewers" ? "preview" : "edit",
})
);
setIsCopied(true);
}}
>
<IconButton aria-label="Copy link">
<CopyIcon aria-hidden />
</IconButton>
</Tooltip>
</CopyToClipboard>
<Menu
name={currentName}
value={value}