Skip to content
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
34 changes: 34 additions & 0 deletions showcase/app/components/page-components/code-block/index.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import type { TemplateOnlyComponent } from '@ember/component/template-only';

import { pageTitle } from 'ember-page-title';

import ShwTextH1 from 'showcase/components/shw/text/h1';
import ShwDivider from 'showcase/components/shw/divider';

import SubSectionContent from 'showcase/components/page-components/code-block/sub-sections/content';
import SubSectionOptions from 'showcase/components/page-components/code-block/sub-sections/options';
import SubSectionBaseElements from 'showcase/components/page-components/code-block/sub-sections/base-elements';
import SubSectionDemo from 'showcase/components/page-components/code-block/sub-sections/demo';

const CodeBlockIndex: TemplateOnlyComponent = <template>
{{pageTitle "CodeBlock Component"}}

<ShwTextH1>CodeBlock</ShwTextH1>

<section data-test-percy>
<SubSectionContent />
<ShwDivider />
<SubSectionOptions />
<ShwDivider />
<SubSectionBaseElements />
<ShwDivider />
<SubSectionDemo />
</section>
</template>;

export default CodeBlockIndex;
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import Component from '@glimmer/component';
import { capitalize } from '@ember/string';
import { array } from '@ember/helper';
import { modifier } from 'ember-modifier';

import ShwGrid from 'showcase/components/shw/grid';
import ShwTextH2 from 'showcase/components/shw/text/h2';
import ShwTextH3 from 'showcase/components/shw/text/h3';

import { HdsCodeBlockCopyButton } from '@hashicorp/design-system-components/components';
import {
SUCCESS_ICON,
ERROR_ICON,
} from '@hashicorp/design-system-components/components/hds/copy/button/index';

const STATES = ['default', 'hover', 'active', 'focus'];

export default class SubSectionBaseElements extends Component {
replaceCopyStatus = modifier((container: HTMLDivElement) => {
container.querySelectorAll('[mock-copy-status]').forEach((element) => {
const status = element.getAttribute('mock-copy-status');
element.classList.remove('hds-copy-button--status-idle');
element.classList.add(`hds-copy-button--status-${status}`);

const icon = element.querySelector('svg use');

if (icon) {
if (status === 'success') {
// eg. href="#flight-clipboard-checked-16"
icon.setAttribute('href', `#flight-${SUCCESS_ICON}-16`);
} else if (status === 'error') {
icon.setAttribute('href', `#flight-${ERROR_ICON}-16`);
}
}
});
});

<template>
<ShwTextH2>CodeBlockCopyButton</ShwTextH2>

<ShwTextH3>States</ShwTextH3>

<span class="shw-component-code-block-display-none" id="test-target">Copy me</span>

<ShwGrid @columns={{6}} {{this.replaceCopyStatus}} as |SG|>
{{#each STATES as |state|}}
<SG.Item
@label={{capitalize state}}
class="shw-component-code-block-copy-button"
>
<HdsCodeBlockCopyButton
mock-state-value={{state}}
@targetToCopy="#test-target"
class="hds-code-block--theme-dark"
/>
</SG.Item>
{{/each}}
{{#let (array "success" "error") as |statuses|}}
{{#each statuses as |status|}}
<SG.Item
@label={{capitalize status}}
class="shw-component-code-block-copy-button"
>
<HdsCodeBlockCopyButton
mock-copy-status={{status}}
@targetToCopy="#test-target"
class="hds-code-block--theme-dark"
/>
</SG.Item>
{{/each}}
{{/let}}
</ShwGrid>
</template>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';

import ShwDivider from 'showcase/components/shw/divider';
import ShwGrid from 'showcase/components/shw/grid';
import ShwTextBody from 'showcase/components/shw/text/body';
import ShwTextH2 from 'showcase/components/shw/text/h2';
import ShwTextH3 from 'showcase/components/shw/text/h3';

import { HdsCodeBlock } from '@hashicorp/design-system-components/components';

export default class SubSectionContent extends Component {
@tracked input: string | undefined = '';

textWithNewLine = `Vagrant.configure("2") do |config|\nconfig.vm.box "ubuntu/noble64"\nend`;

get codeValue() {
let value = `codeLang = 'ruby';`;

if (this.input !== '') {
value += `\n\n${this.input} = "the input is: ${this.input}"`;
}

return value;
}

updateCodeValue = () => {
this.input = ['rand1', 'rand2', 'rand3', ''][Math.floor(Math.random() * 4)];
};

updateInput = (event: Event) => {
this.input = (event.target as HTMLInputElement).value;
};

<template>
<ShwTextH2>Content</ShwTextH2>

<ShwGrid @columns={{2}} @gap="2rem" as |SG|>
<SG.Item @label="one line">
<HdsCodeBlock
@language="bash"
@ariaLabel="one line"
@value="aws ec2 --region us-west-1 accept-vpc-peering-connection"
/>
</SG.Item>
<SG.Item @label="multi-line">
<HdsCodeBlock
@language="go"
@ariaLabel="multi-line"
@value="package main
import 'fmt'
func main() {
res = 'Lorem ipsum dolor sit amet'
fmt.Println(res)
}"
/>
</SG.Item>
</ShwGrid>

<ShwTextBody>New lines handling</ShwTextBody>

<ShwGrid @columns={{2}} @gap="2rem" as |SG|>
<SG.Item @label="new lines in Handlebars" @forceMinWidth={{true}}>
<HdsCodeBlock
@language="go"
@ariaLabel="new lines in Handlebars"
@value="package main
import 'fmt'
func main() {
res = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam'
fmt.Println(res)
}"
/>
</SG.Item>
<SG.Item @forceMinWidth={{true}} as |SGI|>
<SGI.Label>new lines with
<code>\n</code>
escape sequence in Ruby
</SGI.Label>
<HdsCodeBlock
@language="ruby"
@ariaLabel="new lines with escape sequence in Ruby"
@value={{this.textWithNewLine}}
/>
</SG.Item>
<SG.Item @forceMinWidth={{true}} as |SGI|>
<SGI.Label><code>\n</code>
in Handlebars (not interpreted as newline)
</SGI.Label>
<HdsCodeBlock
@language="ruby"
@ariaLabel="\n in Handlebars (not interpreted as newline)"
@value='Vagrant.configure("2") do |config|\nconfig.vm.box "ubuntu/noble64"\nend'
/>
</SG.Item>
<SG.Item @forceMinWidth={{true}} as |SGI|>
<SGI.Label>Line numbering start changed to "5"
</SGI.Label>
{{! template-lint-disable no-whitespace-for-layout }}
<HdsCodeBlock
@language="go"
@maxHeight="105px"
@lineNumberStart={{5}}
@ariaLabel="Line numbering start changed to 5"
@value="package main
import 'fmt'
func main() {
res = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam'
fmt.Println(res)
}"
/>
{{! template-lint-enable no-whitespace-for-layout }}
</SG.Item>
</ShwGrid>

<ShwDivider @level={{2}} />

<ShwTextH3>Title and description</ShwTextH3>

<ShwGrid @columns={{2}} @gap="2rem" as |SG|>
<SG.Item @label="title">
<HdsCodeBlock
@value='Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/noble64"
end'
@language="ruby"
as |CB|
>
<CB.Title>Title</CB.Title>
</HdsCodeBlock>
</SG.Item>
<SG.Item @label="description">
<HdsCodeBlock
@value='Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/noble64"
end'
@language="ruby"
@ariaLabel="description"
as |CB|
>
<CB.Description>Description</CB.Description>
</HdsCodeBlock>
</SG.Item>
<SG.Item @label="title and description">
<HdsCodeBlock
@value='Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/noble64"
end'
@language="ruby"
as |CB|
>
<CB.Title>Title that may wrap on multiple lines if the parent
container is limiting its width</CB.Title>
<CB.Description>
Description that could contain
<a href="#">a link</a>
or other basic styling such as
<b>bold</b>,
<i>italic</i>
or even
<code>code</code>.
</CB.Description>
</HdsCodeBlock>
</SG.Item>
<SG.Item @label="custom title tag">
<HdsCodeBlock
@value='Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/noble64"
end'
@language="ruby"
as |CB|
>
<CB.Title @tag="h2">Title</CB.Title>
</HdsCodeBlock>
</SG.Item>
</ShwGrid>

<ShwDivider @level={{2}} />

<ShwTextH3>Dynamic content</ShwTextH3>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: I would make this one a code fragment, just to group the functionality code closer to the template code. But you dont have to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I'm going to leave it here for now because it's a small block and not reusable. If that's alright.


<ShwTextBody>
<button type="button" {{on "click" this.updateCodeValue}}>
Update value
</button>
</ShwTextBody>

<ShwTextBody>
<label for="input">Change input value:</label>
<input
id="input"
type="text"
value={{this.input}}
{{on "input" this.updateInput}}
/>
</ShwTextBody>

<HdsCodeBlock
@value={{this.codeValue}}
@language="ruby"
@hasCopyButton={{true}}
@hasLineNumbers={{false}}
id="code-block-with-dynamic-content"
as |CB|
>
<CB.Title>
Dynamic content
</CB.Title>
</HdsCodeBlock>
</template>
}
Loading