diff --git a/js/src/clipboard.js b/js/src/clipboard.js index d86b928..d17f4c6 100644 --- a/js/src/clipboard.js +++ b/js/src/clipboard.js @@ -16,6 +16,9 @@ export const toImageOptionKeys = [ "filename", ]; +// SVG path of the clipboard icon +const clipboard_path = "M280 64h40c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128C0 92.7 28.7 64 64 64h40 9.6C121 27.5 153.3 0 192 0s71 27.5 78.4 64H280zM64 112c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320c8.8 0 16-7.2 16-16V128c0-8.8-7.2-16-16-16H304v24c0 13.3-10.7 24-24 24H192 104c-13.3 0-24-10.7-24-24V112H64zm128-8a24 24 0 1 0 0-48 24 24 0 1 0 0 48z" + /** * Update the provided container to eventually add a clipboard header and modify the plot_obj. * @@ -65,22 +68,22 @@ function addClipboardEventListener(CONTAINER) { /** * Adds a tooltip listener to the provided config span element. * - * @param {import("./typedef.js").ImageOptionSpan} span - The config span element to add the tooltip listener to. + * @param {HTMLElement} target - The HTML element which should trigger the tooltip appearance. + * @param {HTMLElement} tooltip - The tooltip element whose position should be updated while hovering over the target. * @param {import("./typedef.js").JSDeps} js_deps - The dependencies object containing the necessary tools for the tooltip listener. * @return {void} This function does not return a value. */ -function addTooltipListener(span, js_deps) { +function addTooltipListener(target, tooltip, js_deps) { const { floatingUI } = js_deps; const { computePosition, flip, shift, offset } = floatingUI; - const { label, config_span } = span; - label.onmouseenter = (e) => { - computePosition(label, config_span, { + target.onmouseenter = (e) => { + computePosition(target, tooltip, { strategy: "fixed", placement: "top-start", middleware: [offset(6), flip(), shift()], }).then(({ x, y }) => { - config_span.style.top = y + "px"; - config_span.style.left = x + "px"; + tooltip.style.top = y + "px"; + tooltip.style.left = x + "px"; }); }; } @@ -94,8 +97,8 @@ function addTooltipListener(span, js_deps) { export function addSingleConfigSpan(CONTAINER, name) { const { CLIPBOARD_HEADER } = CONTAINER; const { html, lodash } = CONTAINER.js_deps; - const config_span = html``; - const label = html``; + const label = html`${config_span}${lodash.capitalize(name)}:`; const ui_span = html``; @@ -146,7 +149,7 @@ export function addSingleConfigSpan(CONTAINER, name) { } ); // Add the tooltip listener - addTooltipListener(container, CONTAINER.js_deps); + addTooltipListener(label, config_span, CONTAINER.js_deps); // Add the listener for imageOptions change const listener = (/** @type {CustomEvent} */ e) => { checkConfigSync(container); @@ -186,11 +189,22 @@ function addOptionSpans(CONTAINER) { function addHelpIcon(CONTAINER) { const { html } = CONTAINER.js_deps; const { CLIPBOARD_HEADER } = CONTAINER; - CLIPBOARD_HEADER.appendChild( - html`
- -
` - ) + const tooltip = html`
+

This floating container can be used to modify the plot appearance before copying to the clipboard or downloading the image corresponding to the plot within this container.

+ +

+ + + + This is the icon to copy the plot to the clipboard (as a png). +

+
` + const help = html`
+ +
` + help.appendChild(tooltip) + addTooltipListener(help, tooltip, CONTAINER.js_deps) + CLIPBOARD_HEADER.appendChild(help) } /** @@ -653,6 +667,7 @@ function DualClick(single_func, dbl_func) { }; } + function modifyModebarButtons(CONTAINER) { const { plot_obj, js_deps, togglePopout, Plotly } = CONTAINER; const { lodash } = js_deps; @@ -671,7 +686,7 @@ function modifyModebarButtons(CONTAINER) { icon: { height: 520, width: 520, - path: "M280 64h40c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128C0 92.7 28.7 64 64 64h40 9.6C121 27.5 153.3 0 192 0s71 27.5 78.4 64H280zM64 112c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320c8.8 0 16-7.2 16-16V128c0-8.8-7.2-16-16-16H304v24c0 13.3-10.7 24-24 24H192 104c-13.3 0-24-10.7-24-24V112H64zm128-8a24 24 0 1 0 0-48 24 24 0 1 0 0 48z", + path: clipboard_path, }, direction: "up", click: DualClick( diff --git a/js/src/styles.js b/js/src/styles.js index 070cf05..0e62c2d 100644 --- a/js/src/styles.js +++ b/js/src/styles.js @@ -18,8 +18,6 @@ export function addContainerStyle(CONTAINER, deps = CONTAINER.js_deps) { background: var(--main-bg-color, var(--bg-color)); border: 3px solid var(--kbd-border-color, var(--border-color)); border-radius: 12px; - border-top-left-radius: 12px; - border-top-right-radius: 12px; top: var(--element-top, 'auto'); left: var(--element-left, 'auto'); box-sizing: content-box; @@ -97,6 +95,9 @@ export function addClipboardHeaderStyle(element, deps = {}) { padding-left: 2px; cursor: text; } + & .help .tooltip { + min-width: 400px; + } & .help { display: inline-block; position: absolute; @@ -111,8 +112,14 @@ export function addClipboardHeaderStyle(element, deps = {}) { & .help svg { color: var(--pluto-output-color, var(--output-color)); fill: var(--pluto-output-color, var(--output-color)); + width: var(--icon-size); + height: var(--icon-size); + } + & .help svg.plotly-icon { + --icon-size: 15px; + display: inline-block; } - & .config-value { + & .tooltip { font-weight: normal; display: block; visibility: hidden; @@ -125,16 +132,16 @@ export function addClipboardHeaderStyle(element, deps = {}) { max-width: 250px; transition: visibility 0.25s; } - & .config-value p:first-child { + & .tooltip p:first-child { margin-block-start: 0; } - & .config-value p:last-child { + & .tooltip p:last-child { margin-block-end: 0; } & .label { user-select: none; } - .plutoplotly-container:not(.dragging) & .label:hover span.config-value { + .plutoplotly-container:not(.dragging) & .tooltip-target:hover .tooltip { visibility: visible; transition: visibility 0s; }