feat(code-snippet): add copy functionality

- docs: add custom feedback copy text example
This commit is contained in:
Eric Y Liu 2021-04-01 14:19:11 -07:00
commit 50b93c8a17
15 changed files with 91 additions and 94 deletions

View file

@ -501,12 +501,12 @@ None.
### Props
| Prop name | Kind | Reactive | Type | Default value | Description |
| :-------------------- | :--------------- | :------- | :--------------------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| :-------------------- | :--------------- | :------- | :--------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ref | <code>let</code> | Yes | <code>null &#124; HTMLPreElement</code> | <code>null</code> | Obtain a reference to the pre HTML element |
| showMoreLess | <code>let</code> | Yes | <code>boolean</code> | <code>false</code> | Set to `true` to enable the show more/less button |
| expanded | <code>let</code> | Yes | <code>boolean</code> | <code>false</code> | Set to `true` to expand a multi-line code snippet (type="multi") |
| type | <code>let</code> | No | <code>"single" &#124; "inline" &#124; "multi"</code> | <code>"single"</code> | Set the type of code snippet |
| code | <code>let</code> | No | <code>string</code> | -- | Set the code snippet text<br />Alternatively, use the default slot (e.g., &lt;CodeSnippet&gt;{`code`}&lt;/CodeSnippet&gt;) |
| code | <code>let</code> | No | <code>string</code> | -- | Set the code snippet text<br />Alternatively, use the default slot (e.g., &lt;CodeSnippet&gt;{`code`}&lt;/CodeSnippet&gt;)<br />You must use the `code` prop to copy the code |
| hideCopyButton | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to hide the copy button |
| disabled | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` for the disabled variant<br />Only applies to the "single", "multi" types |
| wrapText | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to wrap the text<br />Note that `type` must be "multi" |
@ -529,12 +529,13 @@ None.
### Events
| Event name | Type | Detail |
| :----------- | :-------- | :----- |
| :----------- | :--------- | :----- |
| click | forwarded | -- |
| mouseover | forwarded | -- |
| mouseenter | forwarded | -- |
| mouseleave | forwarded | -- |
| animationend | forwarded | -- |
| copy | dispatched | -- |
## `CodeSnippetSkeleton`

View file

@ -11,7 +11,7 @@
"devDependencies": {
"@sveltech/routify": "^1.9.9",
"autoprefixer": "^10.2.3",
"carbon-components": "10.31.0",
"carbon-components": "10.32.0-rc.0",
"carbon-components-svelte": "../",
"clipboard-copy": "^3.1.0",
"mdsvex": "^0.8.8",

View file

@ -805,7 +805,7 @@
{
"name": "code",
"kind": "let",
"description": "Set the code snippet text\nAlternatively, use the default slot (e.g., <CodeSnippet>{`code`}</CodeSnippet>)",
"description": "Set the code snippet text\nAlternatively, use the default slot (e.g., <CodeSnippet>{`code`}</CodeSnippet>)\nYou must use the `code` prop to copy the code",
"type": "string",
"isFunction": false,
"constant": false,
@ -989,7 +989,12 @@
"name": "mouseleave",
"element": "CodeSnippetSkeleton"
},
{ "type": "forwarded", "name": "animationend", "element": "CopyButton" }
{
"type": "forwarded",
"name": "animationend",
"element": "CopyButton"
},
{ "type": "dispatched", "name": "copy" }
],
"typedefs": [],
"rest_props": { "type": "InlineComponent", "name": "CodeSnippetSkeleton" }

View file

@ -2,17 +2,10 @@
export let code = "";
import { CodeSnippet } from "carbon-components-svelte";
import copy from "clipboard-copy";
</script>
<div>
<CodeSnippet
code="{code}"
type="inline"
on:click="{() => {
copy(code);
}}"
/>
<CodeSnippet code="{code}" type="inline" />
</div>
<style>

View file

@ -6,7 +6,6 @@
import { CodeSnippet, Button } from "carbon-components-svelte";
import Launch16 from "carbon-icons-svelte/lib/Launch16";
import copy from "clipboard-copy";
import { url } from "@sveltech/routify";
import { theme } from "../store";
@ -41,7 +40,7 @@
{/if}
</div>
<div class="code-override">
<CodeSnippet type="multi" on:click="{() => copy(codeRaw)}">
<CodeSnippet type="multi" code="{codeRaw}">
{@html code}
</CodeSnippet>
</div>

View file

@ -105,7 +105,11 @@
>
{child.title}
{#if deprecated.includes(child.title)}
<Tag size="sm" type="red" style="margin-top: 0; margin-bottom: 0">
<Tag
size="sm"
type="red"
style="margin-top: 0; margin-bottom: 0; cursor: inherit"
>
Deprecated
</Tag>
{/if}
@ -113,7 +117,7 @@
<Tag
size="sm"
type="green"
style="margin-top: 0; margin-bottom: 0"
style="margin-top: 0; margin-bottom: 0; cursor: inherit"
>
New
</Tag>

View file

@ -28,21 +28,27 @@ let comment = `
</script>
<InlineNotification svx-ignore title="Note:" kind="info" hideCloseButton>
<div class="body-short-01">By design, the copy button does not copy text to the clipboard. You will need to write your own logic. Refer to the <Link href="/recipes/CopyableCodeSnippet">CopyableCodeSnippet recipe</Link> for an example.</div>
<div class="body-short-01">As of version 0.32, the CodeSnippet will copy the provided `code` text when clicking the copy button.</div>
</InlineNotification>
### Default (single-line)
<CodeSnippet>yarn add -D carbon-components-svelte</CodeSnippet>
<CodeSnippet code="yarn add -D carbon-components-svelte" />
### Inline
<CodeSnippet type="inline">rm -rf node_modules/</CodeSnippet>
<CodeSnippet type="inline" code="rm -rf node_modules/" />
### Multi-line
<CodeSnippet type="multi" {code} />
### Custom copy feedback text
Use the `feedback` prop to override the default copy button feedback text.
<CodeSnippet type="multi" {code} feedback="Copied to clipboard" />
### Hidden copy button
<CodeSnippet type="multi" {code} hideCopyButton />
@ -51,7 +57,7 @@ let comment = `
The `disabled` prop applies only to the `"single"` and `"multi"` code snippet types.
<CodeSnippet disabled>yarn add -D carbon-components-svelte</CodeSnippet>
<CodeSnippet disabled code="yarn add -D carbon-components-svelte" />
<br />
<CodeSnippet disabled type="multi" code="{comment}" />

View file

@ -9,7 +9,6 @@
} from "carbon-components-svelte";
import TileCard from "../components/TileCard.svelte";
import { metatags } from "@sveltech/routify";
import copy from "clipboard-copy";
metatags.title = "Carbon Components Svelte";
metatags.description =
@ -53,21 +52,9 @@
<Column>
<h3>Install</h3>
<h4>Installing with yarn:</h4>
<CodeSnippet
code="{installYarn}"
on:click="{() => {
copy(installYarn);
}}"
/>
<CodeSnippet code="{installYarn}" />
<h4>Using npm:</h4>
<CodeSnippet
code="{installNpm}"
on:click="{() => {
copy(installNpm);
}}"
/>
<CodeSnippet code="{installNpm}" />
</Column>
</Row>
<Row>

View file

@ -1,17 +0,0 @@
---
layout: recipe
---
<script>
import Preview from "../../components/Preview.svelte";
</script>
The [CodeSnippet](/components/CodeSnippet) and [CopyButton](/components/CopyButton) components do not include logic to copy the supplied `code` text.
You can use a third party open source module like [clipboard-copy](https://www.npmjs.com/package/clipboard-copy) that is compatible with modern web browsers.
## clipboard-copy
This documentation website uses [clipboard-copy](https://www.npmjs.com/package/clipboard-copy).
<FileSource src="/framed/CopyableCodeSnippet/CopyableCodeSnippet" />

View file

@ -837,25 +837,25 @@ caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001178:
integrity sha512-n8JVqXuZMVSPKiPiypjFtDTXc4jWIdjxull0f92WLo7e1MSi3uJ3NvveakSh/aCl1QKFAvIz3vIj0v+0K+FrXw==
carbon-components-svelte@../:
version "0.30.0"
version "0.31.1"
dependencies:
carbon-icons-svelte "^10.21.0"
carbon-icons-svelte "^10.27.0"
flatpickr "4.6.9"
carbon-components@10.31.0:
version "10.31.0"
resolved "https://registry.yarnpkg.com/carbon-components/-/carbon-components-10.31.0.tgz#050751e7fb4d845b7d1c6e8ac7fdfa9c71403c12"
integrity sha512-gUXRky9rUHavqFLJJQf+Lzouk8GHsXJUjxRgTOUQ6vdBfA0ks6ugwptG8fiFGwCJJht/CW9/YsKb5w8N9a39sg==
carbon-components@10.32.0-rc.0:
version "10.32.0-rc.0"
resolved "https://registry.yarnpkg.com/carbon-components/-/carbon-components-10.32.0-rc.0.tgz#e5886b6ebce37f378159938a08eae09da5d1cb04"
integrity sha512-+0hwzLWa3YUG3i+Re1HgX0BslzuLLe/5EPRugGUEmklJsozUv4SjmMPZU4yk1As4kCqsxQ+h3sRSFSsPRpL1bg==
dependencies:
"@carbon/telemetry" "0.0.0-alpha.6"
flatpickr "4.6.1"
lodash.debounce "^4.0.8"
warning "^3.0.0"
carbon-icons-svelte@^10.21.0:
version "10.21.0"
resolved "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.21.0.tgz#9bbdd37d5513d484e9706d6335c121f60f3186c4"
integrity sha512-5NNaRdmbS4N36dUGNj72Ys3VqVjH3fZ69AhYUHx+bH02GFYCwAaE49qjtP77kP7DKMtDV9NmMEti/P/JB83aYQ==
carbon-icons-svelte@^10.27.0:
version "10.28.0"
resolved "https://registry.yarnpkg.com/carbon-icons-svelte/-/carbon-icons-svelte-10.28.0.tgz#812a6eae858d0c9e043067c714910fcfb6249cd2"
integrity sha512-C3K+U2PRy63WHFZme1HQNju89rhVIQmUkfgBrZzcezdutkhXbSPOY+o/MI0B2mDcQ7G9gfhEpqsXET8gBTWfJQ==
caseless@~0.12.0:
version "0.12.0"

View file

@ -24,6 +24,7 @@
},
"dependencies": {
"carbon-icons-svelte": "^10.27.0",
"clipboard-copy": "3.2.0",
"flatpickr": "4.6.9"
},
"devDependencies": {
@ -31,7 +32,7 @@
"@rollup/plugin-node-resolve": "^11.1.1",
"@tsconfig/svelte": "^1.0.10",
"autoprefixer": "^10.2.4",
"carbon-components": "10.31.0",
"carbon-components": "10.32.0-rc.0",
"gh-pages": "^3.1.0",
"husky": "^4.3.8",
"lint-staged": "^10.5.3",

View file

@ -1,5 +1,5 @@
{
"version": "0.31.0",
"version": "0.31.1",
"components": {
"Accordion": {
"path": "carbon-components-svelte/src/Accordion/Accordion.svelte"

View file

@ -8,6 +8,7 @@
/**
* Set the code snippet text
* Alternatively, use the default slot (e.g., <CodeSnippet>{`code`}</CodeSnippet>)
* You must use the `code` prop to copy the code
* @type {string}
*/
export let code = undefined;
@ -75,18 +76,26 @@
/** Obtain a reference to the pre HTML element */
export let ref = null;
import { tick } from "svelte";
import { createEventDispatcher, tick } from "svelte";
import copy from "clipboard-copy";
import ChevronDown16 from "carbon-icons-svelte/lib/ChevronDown16/ChevronDown16.svelte";
import Button from "../Button/Button.svelte";
import Copy from "../Copy/Copy.svelte";
import CopyButton from "../CopyButton/CopyButton.svelte";
import CodeSnippetSkeleton from "./CodeSnippetSkeleton.svelte";
const dispatch = createEventDispatcher();
function setShowMoreLess() {
const { height } = ref.getBoundingClientRect();
if (height > 0) showMoreLess = ref.getBoundingClientRect().height > 255;
}
function copyCode() {
copy(code);
dispatch("copy");
}
$: expandText = expanded ? showLessText : showMoreText;
$: if (type === "multi" && ref) {
if (code === undefined) setShowMoreLess();
@ -138,6 +147,7 @@
{wrapText && 'bx--snippet--wraptext'}"
{...$$restProps}
on:click
on:click="{copyCode}"
on:mouseover
on:mouseenter
on:mouseleave
@ -182,6 +192,7 @@
feedbackTimeout="{feedbackTimeout}"
iconDescription="{copyButtonDescription}"
on:click
on:click="{copyCode}"
on:animationend
/>
{/if}

View file

@ -11,6 +11,7 @@ export interface CodeSnippetProps {
/**
* Set the code snippet text
* Alternatively, use the default slot (e.g., <CodeSnippet>{`code`}</CodeSnippet>)
* You must use the `code` prop to copy the code
*/
code?: string;
@ -115,6 +116,7 @@ export default class CodeSnippet extends SvelteComponentTyped<
mouseenter: WindowEventMap["mouseenter"];
mouseleave: WindowEventMap["mouseleave"];
animationend: WindowEventMap["animationend"];
copy: CustomEvent<any>;
},
{ default: {} }
> {}

View file

@ -453,10 +453,10 @@ caniuse-lite@^1.0.30001181:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz#7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2"
integrity sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw==
carbon-components@10.31.0:
version "10.31.0"
resolved "https://registry.yarnpkg.com/carbon-components/-/carbon-components-10.31.0.tgz#050751e7fb4d845b7d1c6e8ac7fdfa9c71403c12"
integrity sha512-gUXRky9rUHavqFLJJQf+Lzouk8GHsXJUjxRgTOUQ6vdBfA0ks6ugwptG8fiFGwCJJht/CW9/YsKb5w8N9a39sg==
carbon-components@10.32.0-rc.0:
version "10.32.0-rc.0"
resolved "https://registry.yarnpkg.com/carbon-components/-/carbon-components-10.32.0-rc.0.tgz#e5886b6ebce37f378159938a08eae09da5d1cb04"
integrity sha512-+0hwzLWa3YUG3i+Re1HgX0BslzuLLe/5EPRugGUEmklJsozUv4SjmMPZU4yk1As4kCqsxQ+h3sRSFSsPRpL1bg==
dependencies:
"@carbon/telemetry" "0.0.0-alpha.6"
flatpickr "4.6.1"
@ -540,6 +540,11 @@ cli-truncate@^2.1.0:
slice-ansi "^3.0.0"
string-width "^4.2.0"
clipboard-copy@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.2.0.tgz#3c5b8651d3512dcfad295d77a9eb09e7fac8d5fb"
integrity sha512-vooFaGFL6ulEP1liiaWFBmmfuPm3cY3y7T9eB83ZTnYc/oFeAKsq3NcDrOkBC8XaauEE8zHQwI7k0+JSYiVQSQ==
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"