diff --git a/app/components/copy-button.js b/app/components/copy-button.js new file mode 100644 index 00000000..42510c6b --- /dev/null +++ b/app/components/copy-button.js @@ -0,0 +1,58 @@ +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; + +export default class CopyButtonComponent extends Component { + @tracked isCopied = false; + @tracked copyError = false; + + @action + async copyText() { + try { + await navigator.clipboard.writeText(this.args.textToCopy); + this.isCopied = true; + this.copyError = false; + + setTimeout(() => { + this.isCopied = false; + }, 2000); + } catch (err) { + console.error('Failed to copy text:', err); + this.copyError = true; + + setTimeout(() => { + this.copyError = false; + }, 2000); + } + } + + get buttonLabel() { + if (this.isCopied) { + return 'ROR ID copied to clipboard'; + } + if (this.copyError) { + return 'Failed to copy ROR ID'; + } + return 'Copy ROR ID to clipboard'; + } + + get buttonTitle() { + if (this.isCopied) { + return 'Copied!'; + } + if (this.copyError) { + return 'Copy failed'; + } + return 'Copy ROR ID'; + } + + get iconClass() { + if (this.isCopied) { + return 'fa-solid fa-check'; + } + if (this.copyError) { + return 'fa-solid fa-exclamation-triangle'; + } + return 'fa-solid fa-copy'; + } +} diff --git a/app/styles/app.scss b/app/styles/app.scss index 17d5fb3f..30072fa2 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -1,5 +1,6 @@ @import 'ember-power-select'; @import "components/organizations/api-client-registration-form"; +@import "components/copy-button"; $green: #53baa1; $dark-grey: #505759; diff --git a/app/styles/components/copy-button.scss b/app/styles/components/copy-button.scss new file mode 100644 index 00000000..af8dee7d --- /dev/null +++ b/app/styles/components/copy-button.scss @@ -0,0 +1,65 @@ +.copy-button { + display: inline-block; + margin-left: 0.5rem; + margin-bottom: 0.25rem; + padding: 0; + background-color: transparent; + border: none; + color: #293030; + font-size: 1.25rem; + line-height: 1; + cursor: pointer; + transition: color 0.2s ease, opacity 0.2s ease; + vertical-align: middle; + opacity: 0.7; + + &:hover { + color: #53baa1; + opacity: 1; + } + + &:focus { + outline: none; + } + + &:focus-visible { + outline: 2px solid #53baa1; + outline-offset: 2px; + border-radius: 2px; + opacity: 1; + } + + &:active { + transform: scale(0.95); + } + + &.copy-button--success { + opacity: 1; + } + + &.copy-button--error { + color: #da3200; + opacity: 1; + } + + i { + pointer-events: none; + } + + @media screen and (max-width: 420px) { + font-size: 1rem; + margin-left: 0.35rem; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} diff --git a/app/templates/components/copy-button.hbs b/app/templates/components/copy-button.hbs new file mode 100644 index 00000000..ec42886d --- /dev/null +++ b/app/templates/components/copy-button.hbs @@ -0,0 +1,14 @@ + + + {{#if this.isCopied}} + ROR ID copied to clipboard + {{/if}} + diff --git a/app/templates/components/organization-item.hbs b/app/templates/components/organization-item.hbs index a70c20c8..cc43345c 100644 --- a/app/templates/components/organization-item.hbs +++ b/app/templates/components/organization-item.hbs @@ -7,6 +7,7 @@