From 46df24cd0230cbd8e6cd333b79ecd1c6ee1dce5d Mon Sep 17 00:00:00 2001 From: Avinash Dwarapu Date: Wed, 20 May 2026 14:54:14 +0200 Subject: [PATCH 1/2] feat: Add wrapText property to copy to clipboard --- pages/copy-to-clipboard/permutations.page.tsx | 25 ++++++++++++++++++- .../__snapshots__/documenter.test.ts.snap | 8 ++++++ .../__tests__/copy-to-clipboard.test.tsx | 17 +++++++++++++ src/copy-to-clipboard/index.tsx | 2 ++ src/copy-to-clipboard/interfaces.ts | 6 +++++ src/copy-to-clipboard/internal.tsx | 5 ++-- src/copy-to-clipboard/styles.scss | 18 +++++++++++++ 7 files changed, 78 insertions(+), 3 deletions(-) diff --git a/pages/copy-to-clipboard/permutations.page.tsx b/pages/copy-to-clipboard/permutations.page.tsx index 56ea7120e5..fb5b30d571 100644 --- a/pages/copy-to-clipboard/permutations.page.tsx +++ b/pages/copy-to-clipboard/permutations.page.tsx @@ -37,13 +37,36 @@ const permutations = createPermutations([ copySuccessText: ['Text copied successfully'], copyErrorText: ['Copy failed.'], }, + { + wrapText: [true, false], + variant: ['inline'], + textToCopy: [ + 'Lorem ipsum dolor sit amet consectetur adipiscing elit cursus ut pharetra semper litora lobortis sed lacinia.', + ], + copyButtonText: ['Copy to clipboard'], + copySuccessText: ['Text copied successfully'], + copyErrorText: ['Copy failed.'], + }, + { + wrapText: [true, false], + variant: ['inline'], + textToDisplay: [ + + Inline block popover with relatively long content that should truncate when wrapText is false + , + ], + textToCopy: ['Lorem ipsum dolor sit amet.'], + copyButtonText: ['Copy to clipboard'], + copySuccessText: ['Text copied successfully'], + copyErrorText: ['Copy failed.'], + }, ]); export default function ButtonPermutations() { return ( <>

Button permutations

- + } /> diff --git a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap index aefe9e0a61..201273cc82 100644 --- a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap +++ b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap @@ -10206,6 +10206,14 @@ Defaults to \`button\`.", "optional": true, "type": "string", }, + { + "defaultValue": "true", + "description": "Specifies if the \`textToDisplay\` content should wrap. If you set it to false, it prevents the text +from wrapping and truncates it with an ellipsis. Only applies to \`variant="inline"\`.", + "name": "wrapText", + "optional": true, + "type": "boolean", + }, ], "regions": [ { diff --git a/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx b/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx index 5a7dda302c..5975af95e9 100644 --- a/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx +++ b/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx @@ -6,6 +6,8 @@ import { act, render, waitFor } from '@testing-library/react'; import CopyToClipboard from '../../../lib/components/copy-to-clipboard'; import createWrapper from '../../../lib/components/test-utils/dom'; +import styles from '../../../lib/components/copy-to-clipboard/styles.css.js'; + const defaultProps = { copyTarget: 'Test content', textToCopy: 'Text to copy', @@ -500,4 +502,19 @@ describe('CopyToClipboard', () => { expect(onCopyFailure).not.toHaveBeenCalled(); }); }); + + test('wraps text by default for variant="inline"', () => { + const { container } = render(); + expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).toBeNull(); + }); + + test('wraps text when wrapText=undefined', () => { + const { container } = render(); + expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).toBeNull(); + }); + + test('does not wrap text when wrapText=false', () => { + const { container } = render(); + expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).not.toBeNull(); + }); }); diff --git a/src/copy-to-clipboard/index.tsx b/src/copy-to-clipboard/index.tsx index 35776f0cee..dc2a789812 100644 --- a/src/copy-to-clipboard/index.tsx +++ b/src/copy-to-clipboard/index.tsx @@ -14,6 +14,7 @@ export { CopyToClipboardProps }; export default function CopyToClipboard({ variant = 'button', popoverRenderWithPortal = false, + wrapText = true, ...restProps }: CopyToClipboardProps) { const baseProps = useBaseComponent('CopyToClipboard', { @@ -25,6 +26,7 @@ export default function CopyToClipboard({ diff --git a/src/copy-to-clipboard/interfaces.ts b/src/copy-to-clipboard/interfaces.ts index 05577dcf8c..ad3aed10cc 100644 --- a/src/copy-to-clipboard/interfaces.ts +++ b/src/copy-to-clipboard/interfaces.ts @@ -36,6 +36,12 @@ export interface CopyToClipboardProps extends BaseComponentProps { */ textToDisplay?: React.ReactNode; + /** + * Specifies if the `textToDisplay` content should wrap. If you set it to false, it prevents the text + * from wrapping and truncates it with an ellipsis. Only applies to `variant="inline"`. + */ + wrapText?: boolean; + /** * The message shown when the text is copied successfully. */ diff --git a/src/copy-to-clipboard/internal.tsx b/src/copy-to-clipboard/internal.tsx index 2ffd9946b2..1bc2c42078 100644 --- a/src/copy-to-clipboard/internal.tsx +++ b/src/copy-to-clipboard/internal.tsx @@ -24,6 +24,7 @@ export default function InternalCopyToClipboard({ copyErrorText, textToCopy, textToDisplay, + wrapText = true, popoverRenderWithPortal, disabled, disabledReason, @@ -119,9 +120,9 @@ export default function InternalCopyToClipboard({ return ( {isInline ? ( - + {trigger} - + {textToDisplay !== undefined ? textToDisplay : textToCopy} diff --git a/src/copy-to-clipboard/styles.scss b/src/copy-to-clipboard/styles.scss index b6f3a20b09..961d37665f 100644 --- a/src/copy-to-clipboard/styles.scss +++ b/src/copy-to-clipboard/styles.scss @@ -15,4 +15,22 @@ &-trigger { margin-inline-end: awsui.$space-scaled-xxs; } + + &-no-wrap { + display: inline-flex; + align-items: start; + max-inline-size: 100%; + word-break: normal; + + > .inline-container-trigger { + flex-shrink: 0; + } + + > .text-to-display { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-inline-size: 0; + } + } } From 58c3e29c8dd08972c90b74ff10eb9d86d137ee3c Mon Sep 17 00:00:00 2001 From: Avinash Dwarapu Date: Wed, 20 May 2026 15:13:01 +0200 Subject: [PATCH 2/2] Appease CodeCov. --- .../__tests__/copy-to-clipboard.test.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx b/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx index 5975af95e9..56e2701146 100644 --- a/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx +++ b/src/copy-to-clipboard/__tests__/copy-to-clipboard.test.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { act, render, waitFor } from '@testing-library/react'; import CopyToClipboard from '../../../lib/components/copy-to-clipboard'; +import InternalCopyToClipboard from '../../../lib/components/copy-to-clipboard/internal'; import createWrapper from '../../../lib/components/test-utils/dom'; import styles from '../../../lib/components/copy-to-clipboard/styles.css.js'; @@ -508,8 +509,8 @@ describe('CopyToClipboard', () => { expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).toBeNull(); }); - test('wraps text when wrapText=undefined', () => { - const { container } = render(); + test('InternalCopyToClipboard wraps text by default for variant="inline"', () => { + const { container } = render(); expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).toBeNull(); }); @@ -517,4 +518,9 @@ describe('CopyToClipboard', () => { const { container } = render(); expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).not.toBeNull(); }); + + test('InternalCopyToClipboard does not wrap text when wrapText=false', () => { + const { container } = render(); + expect(container.querySelector(`.${styles['inline-container-no-wrap']}`)).not.toBeNull(); + }); });