From 7e6c8c4177acadb06946210d371113cd2c5c8491 Mon Sep 17 00:00:00 2001 From: Jeff Daley Date: Wed, 5 Apr 2023 14:45:56 -0400 Subject: [PATCH] Document sidebar header refactor (tooltips, scroll border, copy button) (#106) * Start of padding * Improve scrollbars * Add min-height and increase thumb width * Tweak padding * Adjust FF style * Tooltip improvements * Tweak tooltip behavior * Padding tweak * CopyURLButton component and test * Improve scrolled-header styles * Merge styles * Fix tests * Mock clipboard with Sinon * Cleanup * Fix external link * Add /header tests --- web/app/components/copy-u-r-l-button.hbs | 13 + web/app/components/copy-u-r-l-button.ts | 85 +++ web/app/components/document/index.hbs | 4 +- web/app/components/document/share-button.hbs | 15 - web/app/components/document/share-button.ts | 19 - web/app/components/document/sidebar.hbs | 584 +++++++++--------- web/app/components/document/sidebar.js | 51 +- .../components/document/sidebar/header.hbs | 46 ++ web/app/components/document/sidebar/header.ts | 31 + web/app/modifiers/tooltip.ts | 85 ++- web/app/styles/components/sidebar.scss | 59 +- web/app/styles/components/tooltip.scss | 8 + web/app/styles/hashicorp/product-badge.scss | 2 - web/app/types/document.d.ts | 5 +- web/tailwind.config.js | 3 + .../components/copy-u-r-l-button-test.ts | 76 +++ .../document/sidebar/header-test.ts | 124 ++++ .../integration/modifiers/tooltip-test.ts | 5 +- 18 files changed, 815 insertions(+), 400 deletions(-) create mode 100644 web/app/components/copy-u-r-l-button.hbs create mode 100644 web/app/components/copy-u-r-l-button.ts delete mode 100644 web/app/components/document/share-button.hbs delete mode 100644 web/app/components/document/share-button.ts create mode 100644 web/app/components/document/sidebar/header.hbs create mode 100644 web/app/components/document/sidebar/header.ts create mode 100644 web/tests/integration/components/copy-u-r-l-button-test.ts create mode 100644 web/tests/integration/components/document/sidebar/header-test.ts diff --git a/web/app/components/copy-u-r-l-button.hbs b/web/app/components/copy-u-r-l-button.hbs new file mode 100644 index 000000000..50c04b499 --- /dev/null +++ b/web/app/components/copy-u-r-l-button.hbs @@ -0,0 +1,13 @@ + + + diff --git a/web/app/components/copy-u-r-l-button.ts b/web/app/components/copy-u-r-l-button.ts new file mode 100644 index 000000000..7bbc8277d --- /dev/null +++ b/web/app/components/copy-u-r-l-button.ts @@ -0,0 +1,85 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import Ember from "ember"; +import FlashMessageService from "ember-cli-flash/services/flash-messages"; +import { restartableTask, timeout } from "ember-concurrency"; +import { inject as service } from "@ember/service"; +import { Placement } from "@floating-ui/dom"; +import { action } from "@ember/object"; +import { assert } from "@ember/debug"; + +interface CopyURLButtonComponentSignature { + Element: HTMLButtonElement; + Args: { + url: string; + tooltipPlacement?: Placement; + }; +} + +export default class CopyURLButtonComponent extends Component { + @service declare flashMessages: FlashMessageService; + + /** + * Whether the URL was recently copied to the clipboard. + * Used to determine if the tooltip should say "Copy URL" or "Copied." + * Temporarily set true when the URL is successfully copied. + */ + @tracked protected urlWasRecentlyCopied = false; + + /** + * The button element. + * Used to get the tooltip's ID by way of the `aria-describedby` attribute. + */ + @tracked private button: HTMLElement | null = null; + + /** + * The action called when the button is clicked. + * Registers the button element locally. + */ + @action protected didInsertButton(e: HTMLElement) { + this.button = e; + } + + /** + * The action called when the button is clicked. + * Copies the URL to the clipboard and temporarily + * triggers the "Copied" start of the tooltip. + */ + protected copyURL = restartableTask(async () => { + try { + await navigator.clipboard.writeText(this.args.url); + + if (navigator.clipboard.readText) { + const result = await navigator.clipboard.readText(); + if (result === this.args.url) { + this.urlWasRecentlyCopied = true; + assert("button must exist", this.button); + + let tooltipId = this.button.getAttribute("aria-describedby"); + + assert("tooltipId must exist", tooltipId); + + document + .getElementById(tooltipId) + ?.setAttribute("data-url-copied", "true"); + + await timeout(Ember.testing ? 0 : 2000); + + this.urlWasRecentlyCopied = false; + + document + .getElementById(tooltipId) + ?.setAttribute("data-url-copied", "false"); + } + } + } catch (e) { + this.flashMessages.add({ + title: "Error copying link", + message: e as string, + type: "critical", + timeout: 5000, + extendedTimeout: 1000, + }); + } + }); +} diff --git a/web/app/components/document/index.hbs b/web/app/components/document/index.hbs index ff52a97eb..56ea25bc7 100644 --- a/web/app/components/document/index.hbs +++ b/web/app/components/document/index.hbs @@ -1,4 +1,4 @@ -
+
-
+
- - - diff --git a/web/app/components/document/share-button.ts b/web/app/components/document/share-button.ts deleted file mode 100644 index 346592c19..000000000 --- a/web/app/components/document/share-button.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { inject as service } from "@ember/service"; -import Component from "@glimmer/component"; -import ConfigService from "hermes/services/config"; -import { HermesDocument } from "hermes/types/document"; - -interface DocumentShareButtonComponentSignature { - Args: { - document: HermesDocument; - isDownscaled?: boolean; - }; -} - -export default class DocumentShareButtonComponent extends Component { - @service('config') declare configSvc: ConfigService; - - protected get shortLinkBaseURL() { - return this.configSvc.config.short_link_base_url; - } -} diff --git a/web/app/components/document/sidebar.hbs b/web/app/components/document/sidebar.hbs index 2aaf5e545..43b868f71 100644 --- a/web/app/components/document/sidebar.hbs +++ b/web/app/components/document/sidebar.hbs @@ -1,59 +1,17 @@ -