Skip to content
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

Clipboard & Copy Button - Fix handling of empty string and zero values (HDS-4447) #2685

Merged
merged 9 commits into from
Feb 7, 2025
7 changes: 7 additions & 0 deletions .changeset/early-knives-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@hashicorp/design-system-components": patch
---

`Copy Button` - Fixed issue preventing copying of empty string and zero number values.
KristinLBradley marked this conversation as resolved.
Show resolved Hide resolved

`Copy Snippet` - Fixed issue preventing copying of empty string and zero number values.
10 changes: 7 additions & 3 deletions packages/components/src/modifiers/hds-clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const getTextToCopy = (text: TextToCopy): string => {
textToCopy = text.toString();
} else {
assert(
`\`hds-clipboard\` modifier - \`text\` argument must be a string - provided: ${typeof text}`
`\`hds-clipboard\` modifier - \`text\` argument must be a string or number - provided: ${typeof text}`
);
}
}
Expand Down Expand Up @@ -109,7 +109,7 @@ export const writeTextToClipboard = async (
): Promise<boolean> => {
// finally copy the text to the clipboard using the Clipboard API
// https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
if (textToCopy) {
if (textToCopy || textToCopy === '') {
try {
// notice: the "clipboard-write" permission is granted automatically to pages when they are in the active tab
// https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write
Expand Down Expand Up @@ -151,7 +151,11 @@ export const copyToClipboard = async (
): Promise<boolean> => {
let textToCopy: string = '';

if (text) {
if (text === '') {
textToCopy = '';
} else if (text === 0) {
textToCopy = '0';
} else if (text) {
KristinLBradley marked this conversation as resolved.
Show resolved Hide resolved
textToCopy = getTextToCopy(text);
} else if (target) {
const targetElement = getTargetElement(target);
Expand Down
11 changes: 11 additions & 0 deletions showcase/app/templates/components/copy/button.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@
</SF.Item>
</Shw::Flex>

<Shw::Text::H4>Special cases</Shw::Text::H4>
KristinLBradley marked this conversation as resolved.
Show resolved Hide resolved

<Shw::Flex as |SF|>
<SF.Item>
<Hds::Copy::Button @text="Copy an empty string" @textToCopy="" />
</SF.Item>
<SF.Item>
<Hds::Copy::Button @text="Copy the number '0'" @textToCopy={{0}} />
</SF.Item>
</Shw::Flex>

<Shw::Divider @level={{2}} />

<Shw::Text::H3>With <code>target</code> element</Shw::Text::H3>
Expand Down
24 changes: 24 additions & 0 deletions showcase/tests/integration/modifiers/hds-clipboard-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,18 @@ module('Integration | Modifier | hds-clipboard', function (hooks) {
assert.true(this.success);
});

test('it should copy an empty string provided as a `@text` argument', async function (assert) {
await render(
hbs`<button id="test-button" {{hds-clipboard
text=""
onSuccess=this.onSuccess
onError=this.onError
}}>Test</button>`
);
await click('button#test-button');
assert.true(this.success);
});

// context: https://github.com/hashicorp/design-system/pull/1564
test('it should allow to copy an `integer` provided as `@text` argument', async function (assert) {
await render(
Expand All @@ -278,6 +290,18 @@ module('Integration | Modifier | hds-clipboard', function (hooks) {
assert.true(this.success);
});

test('it should copy a zero number value provided as a `@text` argument', async function (assert) {
await render(
hbs`<button id="test-button" {{hds-clipboard
text=0
didoo marked this conversation as resolved.
Show resolved Hide resolved
onSuccess=this.onSuccess
onError=this.onError
}}>Test</button>`
);
await click('button#test-button');
assert.true(this.success);
});

// @TARGET ARGUMENT

test('it should allow to target an element using a `string` selector for the `@target` argument', async function (assert) {
Expand Down