From 823b104a9e150414dbaca1e2b927cf342cac1e3a Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 11 Oct 2023 17:56:05 -0700 Subject: [PATCH] feat(html): "copy to clipboard" for text attachments (#27556) Mostly copied from trace viewer. Not reused due to different colors/icons. Screenshot: copy-to-clipboard --- .../html-reporter/src/copyToClipboard.css | 34 +++++++++++++++++ .../html-reporter/src/copyToClipboard.tsx | 38 +++++++++++++++++++ packages/html-reporter/src/icons.tsx | 7 ++++ packages/html-reporter/src/links.css | 7 ++++ packages/html-reporter/src/links.tsx | 3 +- 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 packages/html-reporter/src/copyToClipboard.css create mode 100644 packages/html-reporter/src/copyToClipboard.tsx diff --git a/packages/html-reporter/src/copyToClipboard.css b/packages/html-reporter/src/copyToClipboard.css new file mode 100644 index 0000000000..5790b626c0 --- /dev/null +++ b/packages/html-reporter/src/copyToClipboard.css @@ -0,0 +1,34 @@ +/* + Copyright (c) Microsoft Corporation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +.copy-icon { + flex: none; + height: 24px; + width: 24px; + border: none; + outline: none; + color: var(--color-fg-default); + background: transparent; + padding: 4px; + cursor: pointer; + display: inline-flex; + align-items: center; + border-radius: 4px; +} + +.copy-icon:not(:disabled):hover { + background-color: var(--color-border-default); +} diff --git a/packages/html-reporter/src/copyToClipboard.tsx b/packages/html-reporter/src/copyToClipboard.tsx new file mode 100644 index 0000000000..a24015a671 --- /dev/null +++ b/packages/html-reporter/src/copyToClipboard.tsx @@ -0,0 +1,38 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as React from 'react'; +import * as icons from './icons'; +import './copyToClipboard.css'; + +export const CopyToClipboard: React.FunctionComponent<{ + value: string, +}> = ({ value }) => { + type IconType = 'copy' | 'check' | 'cross'; + const [icon, setIcon] = React.useState('copy'); + const handleCopy = React.useCallback(() => { + navigator.clipboard.writeText(value).then(() => { + setIcon('check'); + setTimeout(() => { + setIcon('copy'); + }, 3000); + }, () => { + setIcon('cross'); + }); + }, [value]); + const iconElement = icon === 'check' ? icons.check() : icon === 'cross' ? icons.cross() : icons.copy(); + return ; +}; diff --git a/packages/html-reporter/src/icons.tsx b/packages/html-reporter/src/icons.tsx index 86376bdab4..c3eb471b4d 100644 --- a/packages/html-reporter/src/icons.tsx +++ b/packages/html-reporter/src/icons.tsx @@ -106,3 +106,10 @@ export const trace = () => { export const empty = () => { return ; }; + +export const copy = () => { + return ; +}; diff --git a/packages/html-reporter/src/links.css b/packages/html-reporter/src/links.css index 73ae3e64d4..4abe8a6caa 100644 --- a/packages/html-reporter/src/links.css +++ b/packages/html-reporter/src/links.css @@ -102,4 +102,11 @@ line-height: normal; padding: 8px; font-family: monospace; + position: relative; +} + +.attachment-body .copy-icon { + position: absolute; + right: 5px; + top: 5px; } diff --git a/packages/html-reporter/src/links.tsx b/packages/html-reporter/src/links.tsx index 2aa835d7d6..daece0aefe 100644 --- a/packages/html-reporter/src/links.tsx +++ b/packages/html-reporter/src/links.tsx @@ -18,6 +18,7 @@ import type { TestAttachment } from './types'; import * as React from 'react'; import * as icons from './icons'; import { TreeItem } from './treeItem'; +import { CopyToClipboard } from './copyToClipboard'; import './links.css'; export function navigate(href: string) { @@ -71,7 +72,7 @@ export const AttachmentLink: React.FunctionComponent<{ {attachment.path && {linkName || attachment.name}} {attachment.body && {attachment.name}} } loadChildren={attachment.body ? () => { - return [
{attachment.body}
]; + return [
{attachment.body}
]; } : undefined} depth={0} style={{ lineHeight: '32px' }}>; };