diff --git a/src/components/CodeSnippets.js b/src/components/CodeSnippets.js
index bacf9c6d..ca29fff6 100644
--- a/src/components/CodeSnippets.js
+++ b/src/components/CodeSnippets.js
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
-import { Clipboard } from './Clipboard';
+import { Clipboard } from './clipboard/Clipboard';
import { Highlight } from './Highlight';
import { color, spacing, typography } from './shared/styles';
diff --git a/src/components/Clipboard.stories.js b/src/components/clipboard/Clipboard.stories.tsx
similarity index 60%
rename from src/components/Clipboard.stories.js
rename to src/components/clipboard/Clipboard.stories.tsx
index 7c1bb4e9..edc21a0a 100644
--- a/src/components/Clipboard.stories.js
+++ b/src/components/clipboard/Clipboard.stories.tsx
@@ -1,17 +1,18 @@
import React from 'react';
-
+import { action } from '@storybook/addon-actions';
import { Clipboard } from './Clipboard';
-import { TooltipNote } from './tooltip/TooltipNote';
+// @ts-ignore
+import { TooltipNote } from '../tooltip/TooltipNote';
export default {
- title: 'Design System/Clipboard',
- decorators: [(storyFn) =>
{storyFn()}
],
+ title: 'Design System/Clipboard/Clipboard',
+ decorators: [(storyFn: any) => {storyFn()}
],
};
export const Default = () => Click to copy;
export const Callback = () => (
- 'linky from callback'}>Click to copy
+ Click to copy
);
export const Tooltips = () => (
@@ -19,6 +20,8 @@ export const Tooltips = () => (
toCopy="linky"
renderCopiedTooltip={() => }
renderUncopiedTooltip={() => }
+ // @ts-ignore
+ startOpen
>
Click to copy
diff --git a/src/components/Clipboard.js b/src/components/clipboard/Clipboard.tsx
similarity index 55%
rename from src/components/Clipboard.js
rename to src/components/clipboard/Clipboard.tsx
index a3db894e..c69c0605 100644
--- a/src/components/Clipboard.js
+++ b/src/components/clipboard/Clipboard.tsx
@@ -2,14 +2,25 @@ import copyToClipboard from 'copy-to-clipboard';
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
-
-import { TooltipNote } from './tooltip/TooltipNote';
-import WithTooltip from './tooltip/WithTooltip';
+// @ts-ignore
+import { TooltipNote } from '../tooltip/TooltipNote';
+// @ts-ignore
+import WithTooltip from '../tooltip/WithTooltip';
const Tooltip = styled(WithTooltip)`
cursor: pointer;
`;
+interface ClipboardProps {
+ children: React.ReactNode | ((copied: boolean) => React.ReactNode);
+ toCopy?: string;
+ getCopyContent?: () => string;
+ copyOptions?: any;
+ renderCopiedTooltip?: () => React.ReactNode;
+ renderUncopiedTooltip?: () => React.ReactNode;
+ resetTimeout?: number;
+}
+
export const Clipboard = ({
children,
toCopy,
@@ -19,19 +30,20 @@ export const Clipboard = ({
renderCopiedTooltip,
renderUncopiedTooltip,
...props
-}) => {
- const timeout = useRef();
+}: ClipboardProps) => {
const [copied, setCopied] = useState(false);
useEffect(() => {
- if (copied && timeout.current) {
- clearTimeout(timeout.current);
+ let timeoutId: NodeJS.Timeout;
+
+ if (copied && timeoutId) {
+ clearTimeout(timeoutId);
}
- if (copied && resetTimeout) {
- timeout.current = setTimeout(() => setCopied(false), resetTimeout);
+ if (copied && resetTimeout && timeoutId) {
+ timeoutId = setTimeout(() => setCopied(false), resetTimeout);
}
return () => {
- clearTimeout(timeout.current);
+ clearTimeout(timeoutId);
};
}, [copied]);
@@ -53,21 +65,11 @@ export const Clipboard = ({
);
};
-Clipboard.propTypes = {
- children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
- toCopy: PropTypes.string,
- getCopyContent: PropTypes.func,
- copyOptions: PropTypes.object, // eslint-disable-line
- renderCopiedTooltip: PropTypes.func,
- renderUncopiedTooltip: PropTypes.func,
- resetTimeout: PropTypes.number,
-};
-
Clipboard.defaultProps = {
copyOptions: undefined,
- renderCopiedTooltip: () => null,
- renderUncopiedTooltip: () => null,
+ renderCopiedTooltip: () => {},
+ renderUncopiedTooltip: () => {},
resetTimeout: 3000,
toCopy: undefined,
- getCopyContent: () => undefined,
+ getCopyContent: () => '',
};
diff --git a/src/components/clipboard/ClipboardCode.stories.tsx b/src/components/clipboard/ClipboardCode.stories.tsx
new file mode 100644
index 00000000..a872032c
--- /dev/null
+++ b/src/components/clipboard/ClipboardCode.stories.tsx
@@ -0,0 +1,20 @@
+/* eslint-disable import/no-extraneous-dependencies */
+import React from 'react';
+
+import { ClipboardCode } from './ClipboardCode';
+
+export default {
+ title: 'Design System/Clipboard/ClipboardCode',
+};
+
+export const Default = () => (
+
+
+
+);
+
+export const Wrapped = () => (
+
+
+
+);
diff --git a/src/components/clipboard/ClipboardCode.tsx b/src/components/clipboard/ClipboardCode.tsx
new file mode 100644
index 00000000..b7089404
--- /dev/null
+++ b/src/components/clipboard/ClipboardCode.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import { ClipboardIcon } from './ClipboardIcon';
+
+const Container = styled.div`
+ position: relative;
+`;
+
+const Code = styled.pre`
+ width: 100%;
+ display: block;
+ margin: 0;
+ padding-right: 32px;
+ overflow: hidden;
+`;
+
+const StyledClipboardIcon = styled(ClipboardIcon)`
+ position: absolute;
+ top: 8px;
+ right: 8px;
+`;
+
+interface ClipboardCodeProps {
+ code: string;
+}
+
+export const ClipboardCode = ({ code, ...props }: ClipboardCodeProps) => (
+
+
+ {code}
+
+
+
+);
diff --git a/src/components/clipboard/ClipboardIcon.stories.tsx b/src/components/clipboard/ClipboardIcon.stories.tsx
new file mode 100644
index 00000000..b4e246e3
--- /dev/null
+++ b/src/components/clipboard/ClipboardIcon.stories.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import { ClipboardIcon } from './ClipboardIcon';
+
+export default {
+ title: 'Design System/Clipboard/ClipboardIcon',
+};
+
+export const Default = () => (
+
+
+
+);
diff --git a/src/components/clipboard/ClipboardIcon.tsx b/src/components/clipboard/ClipboardIcon.tsx
new file mode 100644
index 00000000..a879faf2
--- /dev/null
+++ b/src/components/clipboard/ClipboardIcon.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import styled from 'styled-components';
+import { color } from '../shared/styles';
+import { Icon } from '../Icon';
+import { Clipboard } from './Clipboard';
+
+const StyledClipboard = styled(Clipboard)`
+ line-height: 14px;
+ padding: 5px;
+ color: ${color.mediumdark};
+ &:hover {
+ color: ${color.darker};
+ }
+`;
+
+interface StyledIconProps {
+ copied: boolean;
+}
+
+const StyledIcon = styled(Icon)`
+ width: 14px;
+ height: 14px;
+ vertical-align: top;
+ color: ${(props) => (props.copied ? color.positive : 'inherit')};
+`;
+
+type ClipboardIconProps = Omit, 'children'>;
+
+export const ClipboardIcon = (props: ClipboardIconProps) => (
+
+ {(copied) => }
+
+);
diff --git a/src/components/clipboard/ClipboardInput.stories.tsx b/src/components/clipboard/ClipboardInput.stories.tsx
new file mode 100644
index 00000000..e839d08b
--- /dev/null
+++ b/src/components/clipboard/ClipboardInput.stories.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+
+import { ClipboardInput } from './ClipboardInput';
+
+export default {
+ title: 'Design System/Clipboard/ClipboardInput',
+};
+
+export const Default = () => (
+
+
+
+);
+
+export const Clipped = () => (
+
+
+
+);
diff --git a/src/components/clipboard/ClipboardInput.tsx b/src/components/clipboard/ClipboardInput.tsx
new file mode 100644
index 00000000..45a2f925
--- /dev/null
+++ b/src/components/clipboard/ClipboardInput.tsx
@@ -0,0 +1,55 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import styled from 'styled-components';
+// @ts-ignore
+import { Input } from '../Input';
+import { color, spacing } from '../shared/styles';
+import { ClipboardIcon } from './ClipboardIcon';
+
+const Container = styled.div`
+ position: relative;
+ margin-top: 15px;
+`;
+
+const StyledInput = styled(Input)`
+ width: 100%;
+ display: block;
+ && input {
+ padding-top: 7px !important;
+ padding-bottom: 7px !important;
+ padding-right: 26px !important;
+ background: ${color.lightest};
+ border: 1px solid ${color.border};
+ border-radius: ${spacing.borderRadius.small}px;
+ font-size: 11px;
+ &:focus {
+ box-shadow: none;
+ border: 1px solid ${color.secondary};
+ }
+ }
+`;
+
+const StyledClipboardIcon = styled(ClipboardIcon)`
+ position: absolute;
+ top: 4px;
+ right: 4px;
+`;
+
+interface ClipboardInputProps extends React.ComponentPropsWithoutRef {
+ value: string;
+}
+
+export const ClipboardInput = ({ value, ...props }: ClipboardInputProps) => (
+
+
+
+
+);
diff --git a/src/components/index.js b/src/components/index.js
index cfdff00c..39614d65 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -35,7 +35,11 @@ export { default as WithModal } from './modal/WithModal';
export * from './table-of-contents/TableOfContents';
export * from './ShadowBoxCTA';
-export * from './Clipboard';
+export * from './clipboard/Clipboard';
+export * from './clipboard/ClipboardIcon';
+export * from './clipboard/ClipboardCode';
+export * from './clipboard/ClipboardInput';
+
export * from './LinkTabs';
export * from './CodeSnippets';