diff --git a/docs/.eleventy.js b/docs/.eleventy.js index af42e2d21e..19693a6e7f 100644 --- a/docs/.eleventy.js +++ b/docs/.eleventy.js @@ -6,6 +6,7 @@ const highlightPlugin = require("./plugins/highlight"); const iconPlugin = require("./plugins/icons"); const tipPlugin = require("./plugins/tip"); const markdownPlugin = require("./plugins/markdown"); +const copyButtonPlugin = require("./plugins/copy-button"); module.exports = function(eleventyConfig) { eleventyConfig.setQuietMode(true); // Reduce the console output @@ -15,6 +16,7 @@ module.exports = function(eleventyConfig) { eleventyConfig.addPlugin(iconPlugin); eleventyConfig.addPlugin(headerPlugin); eleventyConfig.addPlugin(tipPlugin); + eleventyConfig.addPlugin(copyButtonPlugin); // Version shortcode eleventyConfig.addLiquidShortcode("version", function() { diff --git a/docs/assets/js/controllers/clipboard.ts b/docs/assets/js/controllers/clipboard.ts new file mode 100644 index 0000000000..d1f2d7f751 --- /dev/null +++ b/docs/assets/js/controllers/clipboard.ts @@ -0,0 +1,39 @@ +import * as Stacks from '../../../../lib/ts/stacks'; + +Stacks.application.register("clipboard", class extends Stacks.StacksController { + static targets = ["source"]; + sourceTarget!: HTMLElement; + + connect() { + super.connect(); + }; + + copy() { + const text = this.sourceTarget.innerText; + navigator.clipboard.writeText(text); + this.handleVisible(); + } + + private handleVisible() { + const { scope } = this.targets; + + const hideElements = scope.findAllElements('[data-hide-on-copy]'); + const showElements = scope.findAllElements('[data-show-on-copy]'); + + hideElements.forEach(el => { + el.classList.add("d-none"); + }); + showElements.forEach(el => { + el.classList.remove("d-none"); + }); + + setTimeout(function () { + hideElements.forEach(el => { + el.classList.remove("d-none"); + }); + showElements.forEach(el => { + el.classList.add("d-none"); + }); + }, 3000); + } +}); diff --git a/docs/assets/js/index.ts b/docs/assets/js/index.ts index c8b10faf6b..7976761cec 100644 --- a/docs/assets/js/index.ts +++ b/docs/assets/js/index.ts @@ -1,5 +1,6 @@ import "../../../lib/ts/index"; import "../less/stacks-documentation.less"; +import "./controllers/clipboard"; import "./controllers/docs-resizer"; import * as Stacks from "../../../lib/ts/index"; diff --git a/docs/assets/less/stacks-documentation.less b/docs/assets/less/stacks-documentation.less index 5273b68af8..020203744d 100644 --- a/docs/assets/less/stacks-documentation.less +++ b/docs/assets/less/stacks-documentation.less @@ -231,6 +231,20 @@ white-space: normal; } +// ============================================================================ +// $ CODE COPY BUTTON +// ---------------------------------------------------------------------------- +.stacks-copy-btn { + .svg-icon, + .svg-icon * { + pointer-events: none; + } + + .iconCheckmark { + color: var(--green-500); + } +} + // ============================================================================ // $ LISTS @@ -255,11 +269,26 @@ box-shadow: none; }); - > pre.s-code-block { + .stacks-copy-btn { + right: var(--su-static8); + top: var(--su-static8); + } + + > pre.s-code-block, + > .stacks-clipboard-content pre.s-code-block { border-radius: var(--br-md) var(--br-md) 0 0; border: 1px solid var(--bc-medium); + display: flex; // flex layout for scroll padding max-height: 24rem; - + padding-right: var(--su32); + + // pseudo element to pad scrollable region to compensate for copy button + &:after { + content: ""; + display: block; + height: var(--su-static1); + width: var(--su-static128); + } .dark-mode({ border-color: var(--bc-lighter); }); diff --git a/docs/plugins/copy-button.js b/docs/plugins/copy-button.js new file mode 100644 index 0000000000..98885795ee --- /dev/null +++ b/docs/plugins/copy-button.js @@ -0,0 +1,36 @@ +const { default: Icons } = require("@stackoverflow/stacks-icons"); + +module.exports = { + configFunction(eleventyConfig) { + eleventyConfig.addPairedShortcode("copybutton", function(content, classes, btnClasses) { + var tooltipId = "tooltip-" + Math.floor(Math.random() * 1000); + + var output = ` +
The base card styling applies a border and padding to the card.
Cards can be any size and it’s ok to increase the body text size for larger cards.
Applying a .bs-*
class adds a box shadow to a card. Useful when giving users the impression they can interact with the card.
The .s-card
class can be applied to an <a>
tag for instances where a whole card should link somewhere. If possible, linked cards should visually indication that they’re interactive (ex. including an .s-btn
or .s-link
somewhere).
A :hover
style for border color is automatically added to all linked cards. For linked cards with a box shadow (.bs-*
), adding a .h:bs-*
class will apply a hover style to the box shadow as well. Increasing the .bs-
size by a factor of one is usually best.
…
{% endhighlight %} +{% endcopybutton %}