make copy button appear on hover, revert variant changes

This commit is contained in:
Anthony Roberts 2024-08-22 10:33:39 +10:00
parent 9b2e777c20
commit 99664f26d5
5 changed files with 40 additions and 25 deletions

View file

@ -20,7 +20,7 @@
width: 24px; width: 24px;
border: none; border: none;
outline: none; outline: none;
color: var(--color-fg-default); color: var(--color-fg-muted);
background: transparent; background: transparent;
padding: 4px; padding: 4px;
cursor: pointer; cursor: pointer;
@ -34,15 +34,17 @@
margin: 0; margin: 0;
} }
.copy-icon.small {
color: var(--color-fg-muted);
}
.copy-icon.small svg {
height: 14px;
width: 14px;
}
.copy-icon:not(:disabled):hover { .copy-icon:not(:disabled):hover {
background-color: var(--color-border-default); background-color: var(--color-border-default);
} }
.copy-button-container {
visibility: hidden;
display: inline-flex;
margin-left: 8px;
vertical-align: bottom;
}
.copy-value-container:hover .copy-button-container {
visibility: visible;
}

View file

@ -18,10 +18,14 @@ import * as React from 'react';
import * as icons from './icons'; import * as icons from './icons';
import './copyToClipboard.css'; import './copyToClipboard.css';
export const CopyToClipboard: React.FunctionComponent<{ type CopyToClipboardProps = {
value: string, value: string;
variant: 'small' | 'large' };
}> = ({ value, variant }) => {
/**
* A copy to clipboard button.
*/
export const CopyToClipboard: React.FunctionComponent<CopyToClipboardProps> = ({ value }) => {
type IconType = 'copy' | 'check' | 'cross'; type IconType = 'copy' | 'check' | 'cross';
const [icon, setIcon] = React.useState<IconType>('copy'); const [icon, setIcon] = React.useState<IconType>('copy');
const handleCopy = React.useCallback(() => { const handleCopy = React.useCallback(() => {
@ -35,5 +39,21 @@ export const CopyToClipboard: React.FunctionComponent<{
}); });
}, [value]); }, [value]);
const iconElement = icon === 'check' ? icons.check() : icon === 'cross' ? icons.cross() : icons.copy(); const iconElement = icon === 'check' ? icons.check() : icon === 'cross' ? icons.cross() : icons.copy();
return <button className={`copy-icon ${variant}`} onClick={handleCopy}>{iconElement}</button>; return <button className="copy-icon" onClick={handleCopy}>{iconElement}</button>;
};
type CopyToClipboardContainerProps = CopyToClipboardProps & {
children: React.ReactNode
};
/**
* Container for displaying a copy to clipboard button alongside children.
*/
export const CopyToClipboardContainer: React.FunctionComponent<CopyToClipboardContainerProps> = ({ children, value }) => {
return <span className='copy-value-container'>
{children}
<span className='copy-button-container'>
<CopyToClipboard value={value} />
</span>
</span>;
}; };

View file

@ -75,8 +75,3 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
.copy-button-container {
display: inline-flex;
margin-left: 8px;
vertical-align: bottom;
}

View file

@ -79,6 +79,7 @@ test('should render test case', async ({ mount }) => {
test('should render copy buttons for annotations', async ({ mount }) => { test('should render copy buttons for annotations', async ({ mount }) => {
const component = await mount(<TestCaseView projectNames={['chromium', 'webkit']} test={testCase} run={0} anchor=''></TestCaseView>); const component = await mount(<TestCaseView projectNames={['chromium', 'webkit']} test={testCase} run={0} anchor=''></TestCaseView>);
await expect(component.getByText('Annotation text', { exact: false }).first()).toBeVisible(); await expect(component.getByText('Annotation text', { exact: false }).first()).toBeVisible();
component.getByText('Annotation text', { exact: false }).first().hover();
await expect(component.getByRole('button').first()).toBeVisible(); await expect(component.getByRole('button').first()).toBeVisible();
}); });

View file

@ -26,7 +26,7 @@ import { TestResultView } from './testResultView';
import { linkifyText } from '@web/renderUtils'; import { linkifyText } from '@web/renderUtils';
import { hashStringToInt, msToString } from './utils'; import { hashStringToInt, msToString } from './utils';
import { clsx } from '@web/uiUtils'; import { clsx } from '@web/uiUtils';
import { CopyToClipboard } from './copyToClipboard'; import { CopyToClipboardContainer } from './copyToClipboard';
export const TestCaseView: React.FC<{ export const TestCaseView: React.FC<{
projectNames: string[], projectNames: string[],
@ -74,10 +74,7 @@ function TestCaseAnnotationView({ annotation: { type, description } }: { annotat
return ( return (
<div className='test-case-annotation'> <div className='test-case-annotation'>
<span style={{ fontWeight: 'bold' }}>{type}</span> <span style={{ fontWeight: 'bold' }}>{type}</span>
{description && <span>: {linkifyText(description)}</span>} {description && <CopyToClipboardContainer value={description}>: {linkifyText(description)}</CopyToClipboardContainer>}
{description && <span className='copy-button-container'>
<CopyToClipboard value={description} variant='small'/>
</span>}
</div> </div>
); );
} }