Skip to content

Commit 109d71f

Browse files
shleewhitedchyun
andauthoredFeb 12, 2025
CodeEditor and CodeBlock: add ability to customize the copy button text (#2696)
Co-authored-by: Dylan Hyun <dylan.hyun@hashicorp.com>
1 parent 19f6bf2 commit 109d71f

File tree

13 files changed

+75
-13
lines changed

13 files changed

+75
-13
lines changed
 

‎.changeset/orange-chefs-learn.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@hashicorp/design-system-components": minor
3+
---
4+
5+
`CodeBlock` - Added `@copyButtonText` argument to `CodeBlock` and `@text` argument to the `CodeBlock::CopyButton` subcomponent to customize the `aria-label` of the Copy Button. The default label is still "Copy".
6+
7+
`CodeEditor` - Added `@copyButtonText` argument to customize the `aria-label` of the Copy Button. The default label is still "Copy".

‎packages/components/src/components/hds/code-block/copy-button.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<Hds::Copy::Button
77
class="hds-code-block__copy-button"
8-
@text="Copy"
8+
@text={{this.text}}
99
@isIconOnly={{true}}
1010
@size="small"
1111
@targetToCopy={{@targetToCopy}}

‎packages/components/src/components/hds/code-block/copy-button.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33
* SPDX-License-Identifier: MPL-2.0
44
*/
55

6-
import templateOnlyComponent from '@ember/component/template-only';
6+
import Component from '@glimmer/component';
7+
78
import type { HdsCopyButtonSignature } from '../copy/button';
89

910
export interface HdsCodeBlockCopyButtonSignature {
1011
Args: {
1112
targetToCopy?: HdsCopyButtonSignature['Args']['targetToCopy'];
13+
text?: HdsCopyButtonSignature['Args']['text'];
1214
};
1315
Blocks: {
1416
default: [];
1517
};
1618
Element: HdsCopyButtonSignature['Element'];
1719
}
1820

19-
const HdsCodeBlockCopyButton =
20-
templateOnlyComponent<HdsCodeBlockCopyButtonSignature>();
21-
22-
export default HdsCodeBlockCopyButton;
21+
export default class HdsCodeBlockCopyButton extends Component<HdsCodeBlockCopyButtonSignature> {
22+
get text(): HdsCopyButtonSignature['Args']['text'] {
23+
return this.args.text ? this.args.text : 'Copy';
24+
}
25+
}

‎packages/components/src/components/hds/code-block/index.hbs

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
</code></pre>
2323

2424
{{#if @hasCopyButton}}
25-
<Hds::CodeBlock::CopyButton @targetToCopy="#{{this._preCodeId}}" aria-describedby={{this._preCodeId}} />
25+
<Hds::CodeBlock::CopyButton
26+
@targetToCopy="#{{this._preCodeId}}"
27+
aria-describedby={{this._preCodeId}}
28+
@text={{this.copyButtonText}}
29+
/>
2630
{{/if}}
2731
</div>
2832
</div>

‎packages/components/src/components/hds/code-block/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type { HdsCodeBlockTitleSignature } from './title';
2020
import type { HdsCodeBlockDescriptionSignature } from './description';
2121
import { HdsCodeBlockLanguageValues } from './types.ts';
2222
import type { HdsCodeBlockLanguages } from './types.ts';
23+
import type { HdsCopyButtonSignature } from '../copy/button/index.ts';
2324

2425
import 'prismjs/plugins/line-numbers/prism-line-numbers';
2526
import 'prismjs/plugins/line-highlight/prism-line-highlight';
@@ -52,6 +53,7 @@ export interface HdsCodeBlockSignature {
5253
language?: HdsCodeBlockLanguages;
5354
maxHeight?: string;
5455
value: string;
56+
copyButtonText?: HdsCopyButtonSignature['Args']['text'];
5557
};
5658
Blocks: {
5759
default: [
@@ -134,6 +136,10 @@ export default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {
134136
return this.args.hasLineWrapping ?? false;
135137
}
136138

139+
get copyButtonText(): HdsCopyButtonSignature['Args']['text'] {
140+
return this.args.copyButtonText ? this.args.copyButtonText : 'Copy';
141+
}
142+
137143
@action
138144
setPrismCode(element: HTMLElement): void {
139145
const code = this.code;

‎packages/components/src/components/hds/code-editor/index.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
class="hds-code-editor__button hds-code-editor__copy-button"
3434
@isIconOnly={{true}}
3535
@size="small"
36-
@text="Copy"
36+
@text={{this.copyButtonText}}
3737
@textToCopy={{this._value}}
3838
/>
3939
{{/if}}

‎packages/components/src/components/hds/code-editor/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import type { HdsCodeEditorTitleSignature } from './title';
1515
import type { HdsCodeEditorGenericSignature } from './generic';
1616
import type { EditorView } from '@codemirror/view';
1717
import { guidFor } from '@ember/object/internals';
18+
import type { HdsCopyButtonSignature } from '../copy/button/index.ts';
1819

1920
export interface HdsCodeEditorSignature {
2021
Args: {
2122
hasCopyButton?: boolean;
2223
hasFullScreenButton?: boolean;
2324
isStandalone?: boolean;
25+
copyButtonText?: HdsCopyButtonSignature['Args']['text'];
2426
} & HdsCodeEditorModifierSignature['Args']['Named'];
2527
Blocks: {
2628
default: [
@@ -103,6 +105,10 @@ export default class HdsCodeEditor extends Component<HdsCodeEditorSignature> {
103105
return classes.join(' ');
104106
}
105107

108+
get copyButtonText(): HdsCopyButtonSignature['Args']['text'] {
109+
return this.args.copyButtonText ? this.args.copyButtonText : 'Copy';
110+
}
111+
106112
@action
107113
registerTitleElement(element: HdsCodeEditorTitleSignature['Element']): void {
108114
this._titleId = element.id;

‎showcase/tests/integration/components/hds/code-block/index-test.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,19 @@ module('Integration | Component | hds/code-block/index', function (hooks) {
140140
await render(hbs`
141141
<Hds::CodeBlock @value="console.log('Hello world');" @hasCopyButton={{true}} />
142142
`);
143-
assert.dom('.hds-code-block__copy-button').exists();
143+
144+
assert
145+
.dom('.hds-code-block__copy-button')
146+
.exists()
147+
.hasAria('label', 'Copy');
148+
});
149+
150+
test('it renders a Copy button with custom text', async function (assert) {
151+
await render(hbs`
152+
<Hds::CodeBlock @value="console.log('Hello world');" @hasCopyButton={{true}} @copyButtonText="Foo" />
153+
`);
154+
155+
assert.dom('.hds-code-block__copy-button').exists().hasAria('label', 'Foo');
144156
});
145157

146158
// hasLineNumbers

‎showcase/tests/integration/components/hds/code-editor/index-test.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,24 @@ module('Integration | Component | hds/code-editor/index', function (hooks) {
8787
await setupCodeEditor(
8888
hbs`<Hds::CodeEditor @ariaLabel="code editor" @hasCopyButton={{true}} />`
8989
);
90-
assert.dom('.hds-code-editor__copy-button').exists();
90+
assert
91+
.dom('.hds-code-editor__copy-button')
92+
.exists()
93+
.hasAria('label', 'Copy');
9194
});
9295
test('it should not render a copy button when the `@hasCopyButton` argument is not provided', async function (assert) {
9396
await setupCodeEditor(hbs`<Hds::CodeEditor @ariaLabel="code editor" />`);
9497
assert.dom('.hds-code-editor__copy-button').doesNotExist();
9598
});
99+
test('it renders a copy button with custom text', async function (assert) {
100+
await setupCodeEditor(
101+
hbs`<Hds::CodeEditor @ariaLabel="code editor" @hasCopyButton={{true}} @copyButtonText="Foo" />`
102+
);
103+
assert
104+
.dom('.hds-code-editor__copy-button')
105+
.exists()
106+
.hasAria('label', 'Foo');
107+
});
96108
// @isStandalone
97109
test('it should render the component with a standalone style when the `@isStandalone` argument is true and when the argument is ommitted', async function (assert) {
98110
this.set('isStandalone', true);

‎website/docs/components/code-block/partials/code/component-api.md

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ This component uses [prism.js](https://prismjs.com/) under the hood.
2222
</C.Property>
2323
<C.Property @name="hasCopyButton" @type="boolean" @default="false">
2424
Used to control whether a copy button for copying the code/text content will be displayed.
25+
</C.Property>
26+
<C.Property @name="copyButtonText" @type="string" @default="'Copy'">
27+
Override this value to provide a meaningful `aria-label` for the [`Copy::Button`](/components/copy/button) component.
2528
</C.Property>
2629
<C.Property @name="hasLineNumbers" @type="boolean" @default="true">
2730
Used to control display of line numbers. Note that due to technical limitations, if the `@value` changes dynamically the line numbers will fail to update.

‎website/docs/components/code-block/partials/code/how-to-use.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,13 @@ func main() {
8181

8282
### Copy button
8383

84-
Set `hasCopyButton` to `true` to display a button for users to copy `CodeBlock` content to their computer clipboard.
84+
Set `hasCopyButton` to `true` to display a button for users to copy `CodeBlock` content to their computer clipboard. Use `copyButtonText` to provide a meaningful and unique label for the copy button.
8585

8686
```handlebars
8787
<Hds::CodeBlock
8888
@language="javascript"
8989
@hasCopyButton={{true}}
90+
@copyButtonText="Copy javascript code"
9091
@value="let codeLang=`JavaScript`;
9192
console.log(`I am ${codeLang} code`);"
9293
/>

‎website/docs/components/code-editor/partials/code/component-api.md

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ This component uses [CodeMirror 6](https://codemirror.net/) under the hood.
2323
<C.Property @name="hasCopyButton" @type="boolean" @default="false">
2424
Used to control whether a copy button for copying the code/text content will be displayed.
2525
</C.Property>
26+
<C.Property @name="copyButtonText" @type="string" @default="'Copy'">
27+
Override this value to provide a meaningful `aria-label` for the [`Copy::Button`](/components/copy/button) component.
28+
</C.Property>
2629
<C.Property @name="hasFullScreenButton" @type="boolean" @default="false">
2730
Used to control whether a toggle button for toggling full-screen mode will be displayed.
2831
</C.Property>

‎website/docs/components/code-editor/partials/code/how-to-use.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,15 @@ The `language` argument sets the syntax highlighting used. We support the follow
7171

7272
### Copy button
7373

74-
Set `hasCopyButton` to `true` to display a button for users to copy Code Editor content to their computer clipboard.
74+
Set `hasCopyButton` to `true` to display a button for users to copy Code Editor content to their computer clipboard. Use `copyButtonText` to provide a meaningful and unique label for the copy button.
7575

7676
```handlebars
77-
<Hds::CodeEditor @ariaLabel="copy button" @hasCopyButton={{true}} @value={{this.loremIpsum}} />
77+
<Hds::CodeEditor
78+
@ariaLabel="copy button"
79+
@hasCopyButton={{true}}
80+
@copyButtonText="Copy lorem ipsum code"
81+
@value={{this.loremIpsum}}
82+
/>
7883
```
7984

8085

0 commit comments

Comments
 (0)