diff --git a/packages/core/src/components/CopyTextButton/CopyTextButton.js b/packages/core/src/components/CopyTextButton/CopyTextButton.js
new file mode 100644
index 0000000000..49489319b3
--- /dev/null
+++ b/packages/core/src/components/CopyTextButton/CopyTextButton.js
@@ -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:
+ *
+ */
+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 (
+
+ (this.clipboardInput = el)}
+ type="text"
+ style={{ position: 'absolute', top: '-9999px', left: '-9999px' }}
+ defaultValue={text}
+ />
+
+
+
+
+
+
+ );
+ }
+}
+
+export default withStyles(buttonStyles)(CopyTextButton);
diff --git a/packages/core/src/components/CopyTextButton/CopyTextButton.stories.tsx b/packages/core/src/components/CopyTextButton/CopyTextButton.stories.tsx
new file mode 100644
index 0000000000..9f5618ad0e
--- /dev/null
+++ b/packages/core/src/components/CopyTextButton/CopyTextButton.stories.tsx
@@ -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 = () => (
+
+);
+
+export const WithTooltip = () => (
+
+);
diff --git a/packages/core/src/components/CopyTextButton/CopyTextButton.test.js b/packages/core/src/components/CopyTextButton/CopyTextButton.test.js
new file mode 100644
index 0000000000..c1c2212be7
--- /dev/null
+++ b/packages/core/src/components/CopyTextButton/CopyTextButton.test.js
@@ -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('', () => {
+ it('renders without exploding', () => {
+ const { getByDisplayValue } = render(
+ wrapInThemedTestApp(),
+ );
+ getByDisplayValue('mockText');
+ });
+
+ it('displays tooltip on click', () => {
+ const spy = jest.fn();
+ Object.defineProperty(document, 'execCommand', { value: spy });
+ const rendered = render(wrapInThemedTestApp());
+ const button = rendered.getByTitle('mockTooltip');
+ button.click();
+ expect(spy).toHaveBeenCalled();
+ rendered.getByText('mockTooltip');
+ });
+});
diff --git a/packages/core/src/components/CopyTextButton/index.ts b/packages/core/src/components/CopyTextButton/index.ts
new file mode 100644
index 0000000000..22fd7f05bb
--- /dev/null
+++ b/packages/core/src/components/CopyTextButton/index.ts
@@ -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';
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 740a4cc803..c94068b556 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -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';