diff --git a/assets/css/components.css b/assets/css/components.css index efd63c08c..9d2da14b8 100644 --- a/assets/css/components.css +++ b/assets/css/components.css @@ -54,11 +54,11 @@ } .icon-button { - @apply p-1 flex items-center justify-center text-gray-400 hover:text-gray-800; + @apply p-1 flex items-center justify-center text-gray-400 hover:text-gray-800 rounded-full; } .icon-button:focus { - @apply rounded-full bg-gray-100; + @apply bg-gray-100; } .icon-button i { diff --git a/assets/css/js_interop.css b/assets/css/js_interop.css index 0ffa25a7d..4a80d88e5 100644 --- a/assets/css/js_interop.css +++ b/assets/css/js_interop.css @@ -121,3 +121,7 @@ solely client-side operations. [data-element="clients-list-item"][data-js-followed] [data-meta="follow"] { @apply hidden; } + +[phx-hook="VirtualizedLines"]:not(:hover) [data-clipboard] { + @apply hidden; +} diff --git a/assets/js/virtualized_lines/index.js b/assets/js/virtualized_lines/index.js index fff23bab6..48de1ba1c 100644 --- a/assets/js/virtualized_lines/index.js +++ b/assets/js/virtualized_lines/index.js @@ -23,6 +23,8 @@ import { getLineHeight } from "../lib/utils"; * * * one annotated with `data-content` where the visible elements are rendered, * it should contain any styling relevant for the container + * + * Also a `data-clipboard` child button is used for triggering copy-to-clipboard. */ const VirtualizedLines = { mounted() { @@ -62,6 +64,18 @@ const VirtualizedLines = { this.state.contentElement, config ); + + this.el + .querySelector("[data-clipboard]") + .addEventListener("click", (event) => { + const content = Array.from(this.state.templateElement.children) + .map((child) => child.innerText) + .join(""); + + if ("clipboard" in navigator) { + navigator.clipboard.writeText(content); + } + }); }, updated() { diff --git a/lib/livebook_web/live/output/text_component.ex b/lib/livebook_web/live/output/text_component.ex new file mode 100644 index 000000000..99f6b487c --- /dev/null +++ b/lib/livebook_web/live/output/text_component.ex @@ -0,0 +1,29 @@ +defmodule LivebookWeb.Output.TextComponent do + use LivebookWeb, :live_component + + @impl true + def render(assigns) do + ~L""" +