Skip to content

feat: Add clipboard icon to copy value of key-value element in info panel #2871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/components/AggregationPanel/AggregationPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,15 @@ const AggregationPanel = ({
case 'text':
return <TextElement key={idx} text={item.text} style={item.style} />;
case 'keyValue':
return <KeyValueElement key={idx} item={item} appName={appName} style={item.style} />;
return (
<KeyValueElement
key={idx}
item={item}
appName={appName}
showNote={showNote}
style={item.style}
/>
);
case 'table':
return <TableElement key={idx} columns={item.columns} rows={item.rows} style={item.style} />;
case 'image':
Expand Down
13 changes: 13 additions & 0 deletions src/components/AggregationPanel/AggregationPanel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
font-size: 14px;
display: flex;
gap: 10px;
align-items: center;

.copyIcon {
display: none;
cursor: pointer;
margin-left: 4px;
color: inherit;
opacity: 0.6;
}

&:hover .copyIcon {
display: inline-block;
}
}

.video {
Expand Down
38 changes: 26 additions & 12 deletions src/components/AggregationPanel/AggregationPanelComponents.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';
import copy from 'copy-to-clipboard';
import Icon from 'components/Icon/Icon.react';
Comment on lines +2 to +3
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the imported dependencies are available.

Ensure that copy-to-clipboard library and the Icon component with "clone-icon" name are available in the project.


🏁 Script executed:

#!/bin/bash
# Check if copy-to-clipboard is available in package.json
echo "Checking copy-to-clipboard dependency:"
cat package.json | jq '.dependencies."copy-to-clipboard", .devDependencies."copy-to-clipboard"'

# Check if Icon component exists and supports clone-icon
echo "Checking Icon component:"
fd -t f "Icon.react.js" -x cat {}

# Search for clone-icon usage or definition
echo "Searching for clone-icon definition:"
rg "clone-icon" -A 2 -B 2

Length of output: 2473


Dependencies verified: [email protected] and Icon('clone-icon') are available

The copy-to-clipboard package is listed in package.json and the Icon component supports the clone-icon sprite (see src/icons/clone-icon.svg).

Next steps (src/components/AggregationPanel/AggregationPanelComponents.js):

  • Add accessibility attributes to the copy icon wrapper:
    • e.g. <span role="button" aria-label="Copy value" …>
  • Introduce error handling around the copy operation in handleCopy:
    • wrap copy(String(item.value)) in try/catch and surface failures (toast, console.warn, etc.)
🤖 Prompt for AI Agents
In src/components/AggregationPanel/AggregationPanelComponents.js around lines 2
to 3, enhance accessibility by adding role="button" and aria-label="Copy value"
attributes to the span wrapping the copy icon. Additionally, update the
handleCopy function to wrap the copy(String(item.value)) call in a try/catch
block, and handle any errors by displaying a toast notification or logging a
warning to the console.

import styles from './AggregationPanel.scss';

// Text Element Component
Expand All @@ -9,18 +11,30 @@ export const TextElement = ({ text, style}) => (
);

// Key-Value Element Component
export const KeyValueElement = ({ item, appName, style }) => (
<div className={styles.keyValue} style={style}>
{item.key}:
{item.url ? (
<a href={item.isRelativeUrl ? `apps/${appName}/${item.url}` : item.url} target="_blank" rel="noreferrer">
{item.value}
</a>
) : (
<span>{item.value}</span>
)}
</div>
);
export const KeyValueElement = ({ item, appName, style, showNote }) => {
const handleCopy = () => {
copy(String(item.value));
if (showNote) {
showNote('Value copied to clipboard', false);
}
};

return (
<div className={styles.keyValue} style={style}>
{item.key}:
{item.url ? (
<a href={item.isRelativeUrl ? `apps/${appName}/${item.url}` : item.url} target="_blank" rel="noreferrer">
{item.value}
</a>
) : (
<span>{item.value}</span>
)}
<span className={styles.copyIcon} onClick={handleCopy}>
<Icon name="clone-icon" width={12} height={12} fill="currentColor" />
</span>
</div>
);
};

// Table Element Component
export const TableElement = ({ columns, rows, style }) => (
Expand Down
Loading