Skip to content

feat: add copy to clipboard as valid item type for button group#4736

Merged
pan-kot merged 7 commits into
cloudscape-design:mainfrom
shannenigans:main
Jul 22, 2026
Merged

feat: add copy to clipboard as valid item type for button group#4736
pan-kot merged 7 commits into
cloudscape-design:mainfrom
shannenigans:main

Conversation

@shannenigans

Copy link
Copy Markdown
Contributor

Description

Add icon-copy-to-clipboard as a valid item type in the ButtonGroup component. This
allows users to embed a copy-to-clipboard action directly within a button group
alongside existing item types (icon-button, icon-toggle-button, icon-file-input,
menu-dropdown).

Changes:

  • Added IconCopyToClipboard interface with properties: id, text, textToCopy,
    copySuccessText, copyErrorText, disabled, and disabledReason
  • Added onCopySuccess and onCopyFailure event handlers to ButtonGroupProps
  • Created CopyToClipboardItem component that wraps InternalCopyToClipboard with
    tooltip support
  • Updated ItemRuntime, Item, and InternalItem union types to include the new
    item type
  • Wired up copy event handlers through internal.tsx and item-element.tsx

Related links, issue #, if available: n/a

How has this been tested?

  • Verified TypeScript compilation with the new type additions
  • Manually tested rendering a button group with an icon-copy-to-clipboard item
  • Confirmed copy success/failure callbacks fire correctly
  • Confirmed tooltip behavior matches other button group item types
Review checklist

The following items are to be evaluated by the author(s) and the reviewer(s).

Correctness

  • Changes include appropriate documentation updates.
  • Changes are backward-compatible if not indicated, see [CONTRIBUTING.md](https://
    github.com/cloudscape-design/components/blob/main/CONTRIBUTING.md#public-apis).
  • Changes do not include unsupported browser features, see
    [CONTRIBUTING.md](https://github.com/cloudscape-design/components/blob/main/CONTRIB
    UTING.md#browsers-support).
  • Changes were manually tested for accessibility, see accessibility
    guidelines
    .

Security

Testing

  • Changes are covered with new/existing unit tests?
  • Changes are covered with new/existing integration tests?

@shannenigans
shannenigans marked this pull request as ready for review July 16, 2026 16:23
@shannenigans
shannenigans requested a review from a team as a code owner July 16, 2026 16:23
@shannenigans
shannenigans requested review from taheramr and removed request for a team July 16, 2026 16:23
@pan-kot
pan-kot requested review from pan-kot and removed request for taheramr July 16, 2026 16:52
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.61%. Comparing base (bcde582) to head (0e560ad).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4736      +/-   ##
==========================================
+ Coverage   97.60%   97.61%   +0.01%     
==========================================
  Files         951      952       +1     
  Lines       30744    30816      +72     
  Branches    11281    11317      +36     
==========================================
+ Hits        30007    30081      +74     
- Misses        690      728      +38     
+ Partials       47        7      -40     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/button-group/interfaces.ts Outdated
Comment thread src/button-group/index.tsx
Comment thread src/button-group/__tests__/button-group-copy-to-clipboard.test.tsx
Comment thread src/button-group/item-element.tsx Outdated

const onCopyFailureHandler: NonCancelableEventHandler<CopyToClipboardProps.CopyFailureDetail> = event => {
fireCancelableEvent(onCopyFailure, event.detail);
setTooltip(null);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not really work. The tooltip is hidden initially, but then it re-appears if the item is hovered.

Image

In button group we use a customised tooltip implementation that transitions from tooltip to popover state if needed - that was used precisely to implement copy-to-clipboard items (which required a bit of extra code to actually do copy to clipboard).

I think reusing the copy to clipboard component here does not really work - it is best to use a custom implementation but reuse relevant utilities from the copy to clipboard component instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Just want to clarify that the expected behavior is that the success/failure popover and the tooltip should render as one component as opposed to being rendered on top of the other here, which can't be accomplished with simply reusing the copy to clipboard component?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tooltip does not have to remain the same dom element when transitioning from tooltip to popover state, but we should not display both at the same time.

Comment thread src/button-group/item-element.tsx
function renderButtonGroup(props: Partial<ButtonGroupProps>) {
const { container } = render(<ButtonGroup variant="icon" ariaLabel="Chat actions" items={[copyItem]} {...props} />);
const wrapper = createWrapper(container).findButtonGroup()!;
const copyToClipboard = createWrapper(container).findCopyToClipboard()!;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong: the button dropdown wrapper must receive its findCopyToClipboardById() helper instead.

@shannenigans shannenigans Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this due to the possibility that there can be multiple copy to clipboard buttons?

edit: since I'm updating this to a cusotm implementation using iconbutton, updating this to findButtonById()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but also to ensure consistency when it comes to different item types. Even if there is only one copy button - the consumers should use the button group's utils for that - as whether we implement it by reusing the copy-to-clipboard component, or use a custom solution - is an implementation detail.

@github-actions
github-actions Bot temporarily deployed to fork-dev-pages-react16 July 20, 2026 16:20 Inactive
@github-actions
github-actions Bot temporarily deployed to fork-dev-pages-react18 July 20, 2026 16:20 Inactive
Comment thread src/button-group/__tests__/button-group-copy-to-clipboard.test.tsx
function renderButtonGroup(props: Partial<ButtonGroupProps>) {
const { container } = render(<ButtonGroup variant="icon" ariaLabel="Chat actions" items={[copyItem]} {...props} />);
const wrapper = createWrapper(container).findButtonGroup()!;
const copyToClipboard = wrapper.findButtonById('copy')!;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to introduce findCopyToClipboardById() util. This is needed for consistency but also it gives consumers the ability to validate item's type this way.

pan-kot
pan-kot previously approved these changes Jul 22, 2026
@pan-kot
pan-kot enabled auto-merge July 22, 2026 04:51
auto-merge was automatically disabled July 22, 2026 15:02

Head branch was pushed to by a user without write access

@pan-kot
pan-kot enabled auto-merge July 22, 2026 21:21
@github-actions
github-actions Bot temporarily deployed to fork-dev-pages-react18 July 22, 2026 21:32 Inactive
@github-actions
github-actions Bot temporarily deployed to fork-dev-pages-react16 July 22, 2026 21:33 Inactive
@pan-kot
pan-kot added this pull request to the merge queue Jul 22, 2026
Merged via the queue into cloudscape-design:main with commit f97729a Jul 22, 2026
100 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants