Skip to content

Commit 8cb5671

Browse files
lyzno1fatelei
authored andcommitted
fix(web): restore "Copied" feedback state on copy buttons (#35513)
1 parent ecd3dbc commit 8cb5671

3 files changed

Lines changed: 12 additions & 11 deletions

File tree

web/app/components/base/copy-feedback/__tests__/index.spec.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ describe('CopyFeedback', () => {
4040
expect(mockCopy).toHaveBeenCalledWith('test content')
4141
})
4242

43-
it('calls reset on mouse leave', () => {
43+
it('does not reset on mouse leave (relies on hook timeout)', () => {
4444
render(<CopyFeedback content="test content" />)
4545
const button = screen.getByRole('button')
4646
fireEvent.mouseLeave(button.firstChild as Element)
47-
expect(mockReset).toHaveBeenCalledTimes(1)
47+
expect(mockReset).not.toHaveBeenCalled()
4848
})
4949
})
5050
})
@@ -88,11 +88,11 @@ describe('CopyFeedbackNew', () => {
8888
expect(mockCopy).toHaveBeenCalledWith('test content')
8989
})
9090

91-
it('calls reset on mouse leave', () => {
91+
it('does not reset on mouse leave (relies on hook timeout)', () => {
9292
const { container } = render(<CopyFeedbackNew content="test content" />)
9393
const clickableArea = container.querySelector('.cursor-pointer')!.firstChild as HTMLElement
9494
fireEvent.mouseLeave(clickableArea)
95-
expect(mockReset).toHaveBeenCalledTimes(1)
95+
expect(mockReset).not.toHaveBeenCalled()
9696
})
9797
})
9898
})

web/app/components/base/copy-feedback/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ const prefixEmbedded = 'overview.appInfo.embedded'
1919

2020
const CopyFeedback = ({ content }: Props) => {
2121
const { t } = useTranslation()
22-
const { copied, copy, reset } = useClipboard()
22+
// Rely on useClipboard's own timer to flip `copied` back to false so the
23+
// "Copied" tooltip stays visible long enough to be read, matching the
24+
// KeyValueItem pattern. Do NOT reset on mouse leave.
25+
const { copied, copy } = useClipboard({ timeout: 2000 })
2326

2427
const tooltipText = copied
2528
? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' })
@@ -36,10 +39,7 @@ const CopyFeedback = ({ content }: Props) => {
3639
popupContent={safeText}
3740
>
3841
<ActionButton>
39-
<div
40-
onClick={handleCopy}
41-
onMouseLeave={reset}
42-
>
42+
<div onClick={handleCopy}>
4343
{copied && <RiClipboardFill className="h-4 w-4" />}
4444
{!copied && <RiClipboardLine className="h-4 w-4" />}
4545
</div>
@@ -52,7 +52,7 @@ export default CopyFeedback
5252

5353
export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className' | 'content'>) => {
5454
const { t } = useTranslation()
55-
const { copied, copy, reset } = useClipboard()
55+
const { copied, copy } = useClipboard({ timeout: 2000 })
5656

5757
const tooltipText = copied
5858
? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' })
@@ -73,7 +73,6 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
7373
>
7474
<div
7575
onClick={handleCopy}
76-
onMouseLeave={reset}
7776
className={`h-full w-full ${copyStyle.copyIcon} ${copied ? copyStyle.copied : ''}`}
7877
>
7978
</div>

web/hooks/use-clipboard.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ export function useClipboard({
4343
const copy = useCallback(async (valueToCopy: string) => {
4444
try {
4545
await writeTextToClipboard(valueToCopy)
46+
handleCopyResult(true)
4647
}
4748
catch (e) {
4849
if (usePromptAsFallback) {
4950
try {
5051
// eslint-disable-next-line no-alert -- prompt as fallback in case of copy error
5152
window.prompt(promptFallbackText, valueToCopy)
53+
handleCopyResult(true)
5254
}
5355
catch (e2) {
5456
handleCopyError(e2 as Error)

0 commit comments

Comments
 (0)