Add CopyTextButton
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { IconButton, Tooltip, withStyles } from '@material-ui/core';
|
||||
import CopyIcon from '@material-ui/icons/FileCopy';
|
||||
|
||||
const buttonStyles = theme => ({
|
||||
button: {
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.highlight,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Copy text button with visual feedback in the form of
|
||||
* - a hover color
|
||||
* - click ripple
|
||||
* - Tooltip shown when user has clicked
|
||||
*
|
||||
* Properties:
|
||||
* - text: the text to be copied
|
||||
* - tooltipDelay: Number os ms to show the tooltip, default: 1000ms
|
||||
* - tooltipText: Text to show in the tooltip when user has clicked the button, default: "Text
|
||||
* copied to clipboard"
|
||||
*
|
||||
* Example:
|
||||
* <CopyTextButton text="My text that I want to be copied to the clipboard" />
|
||||
*/
|
||||
class CopyTextButton extends React.Component {
|
||||
static propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
tooltipDelay: PropTypes.number,
|
||||
tooltipText: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
tooltipDelay: 1000,
|
||||
tooltipText: 'Text copied to clipboard',
|
||||
};
|
||||
|
||||
state = {
|
||||
open: false,
|
||||
};
|
||||
|
||||
handleTooltipClose = () => {
|
||||
this.setState({ open: false });
|
||||
};
|
||||
|
||||
handleTooltipOpen = () => {
|
||||
this.setState({ open: true });
|
||||
};
|
||||
|
||||
handleCopyClick = e => {
|
||||
e.stopPropagation();
|
||||
this.handleTooltipOpen();
|
||||
try {
|
||||
this.clipboardInput.select();
|
||||
document.execCommand('copy');
|
||||
} catch (error) {
|
||||
// console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes, text, tooltipDelay, tooltipText } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<input
|
||||
ref={el => (this.clipboardInput = el)}
|
||||
type="text"
|
||||
style={{ position: 'absolute', top: '-9999px', left: '-9999px' }}
|
||||
defaultValue={text}
|
||||
/>
|
||||
<Tooltip
|
||||
id="copy-test-tooltip"
|
||||
title={tooltipText}
|
||||
placement="top"
|
||||
leaveDelay={tooltipDelay}
|
||||
onClose={this.handleTooltipClose}
|
||||
open={this.state.open}
|
||||
>
|
||||
<IconButton onClick={this.handleCopyClick} className={classes.button}>
|
||||
<CopyIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(buttonStyles)(CopyTextButton);
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 React from 'react';
|
||||
import CopyTextButton from '.';
|
||||
|
||||
export default {
|
||||
title: 'CopyTextButton',
|
||||
component: CopyTextButton,
|
||||
};
|
||||
|
||||
export const Default = () => (
|
||||
<CopyTextButton text="The text to copy to clipboard" />
|
||||
);
|
||||
|
||||
export const WithTooltip = () => (
|
||||
<CopyTextButton
|
||||
text="The text to copy to clipboard"
|
||||
tooltipText="Custom tooltip shown on button click"
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { wrapInThemedTestApp } from '@backstage/test-utils';
|
||||
import CopyTextButton from 'shared/components/CopyTextButton';
|
||||
|
||||
const props = {
|
||||
text: 'mockText',
|
||||
tooltipDelay: 2,
|
||||
tooltipText: 'mockTooltip',
|
||||
};
|
||||
|
||||
describe('<CopyTextButton />', () => {
|
||||
it('renders without exploding', () => {
|
||||
const { getByDisplayValue } = render(
|
||||
wrapInThemedTestApp(<CopyTextButton {...props} />),
|
||||
);
|
||||
getByDisplayValue('mockText');
|
||||
});
|
||||
|
||||
it('displays tooltip on click', () => {
|
||||
const spy = jest.fn();
|
||||
Object.defineProperty(document, 'execCommand', { value: spy });
|
||||
const rendered = render(wrapInThemedTestApp(<CopyTextButton {...props} />));
|
||||
const button = rendered.getByTitle('mockTooltip');
|
||||
button.click();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
rendered.getByText('mockTooltip');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { default } from './CopyTextButton';
|
||||
@@ -27,6 +27,7 @@ export * from './layout/Sidebar';
|
||||
export { default as HorizontalScrollGrid } from './components/HorizontalScrollGrid';
|
||||
export { default as ProgressCard } from './components/ProgressCard';
|
||||
export { default as CircleProgress } from './components/CircleProgress';
|
||||
export { default as CopyTextButton } from './components/CopyTextButton';
|
||||
export { default as Progress } from './components/Progress';
|
||||
export { AlphaLabel, BetaLabel } from './components/Lifecycle';
|
||||
export { default as SupportButton } from './components/SupportButton';
|
||||
|
||||
Reference in New Issue
Block a user