diff --git a/assets/images/copy.license b/assets/images/copy.license
new file mode 100644
index 00000000..b253ad42
--- /dev/null
+++ b/assets/images/copy.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: 2024 John Livingston
+
+SPDX-License-Identifier: AGPL-3.0-only
diff --git a/assets/images/copy.svg b/assets/images/copy.svg
new file mode 100644
index 00000000..64721e98
--- /dev/null
+++ b/assets/images/copy.svg
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/styles/configuration.scss b/assets/styles/configuration.scss
index 9949d188..4b64052c 100644
--- a/assets/styles/configuration.scss
+++ b/assets/styles/configuration.scss
@@ -88,7 +88,8 @@ livechat-help-button {
input[type="reset"],
button[type="submit"],
button[type="reset"],
- .peertube-plugin-livechat-configuration-actions button {
+ .peertube-plugin-livechat-configuration-actions button,
+ .peertube-plugin-livechat-tags-input-copy {
// Peertube rounded-line-height-1-5 mixins
line-height: $button-calc-line-height;
@@ -104,7 +105,8 @@ livechat-help-button {
input[type="submit"],
button[type="submit"],
- .peertube-plugin-livechat-configuration-actions button {
+ .peertube-plugin-livechat-configuration-actions button,
+ .peertube-plugin-livechat-tags-input-copy {
// Peertube orange-button mixin
&,
&:active,
@@ -331,6 +333,13 @@ livechat-tags-input {
flex-wrap: wrap;
max-width: 320px;
+ .livechat-tags-container {
+ align-items: center;
+ display: flex;
+ flex-flow: row;
+ justify-content: space-between;
+ }
+
// stylelint trying to rearrange unrelated root blocks because of smaller blocks in them
/* stylelint-disable-next-line no-descending-specificity */
input {
@@ -347,46 +356,50 @@ livechat-tags-input {
}
}
- #tags,
- #tags-searched {
+ .livechat-tags,
+ .livechat-tags-searched {
display: flex;
flex-wrap: wrap;
padding: 0;
margin: var(--tag-padding-vertical) 0;
max-height: 150px;
overflow-y: auto;
- border-bottom: 1px dashed var(--greyForegroundColor);
transition-property: height, margin;
transition-duration: 0.3s;
- &.empty {
- height: 0;
- margin: 0;
- border: none;
- }
-
@supports (scrollbar-width: auto) {
scrollbar-color: var(--greyForegroundColor) transparent;
scrollbar-width: thin;
}
}
- #tags-searched {
+ .livechat-tags-container,
+ .livechat-tags-searched {
+ border-bottom: 1px dashed var(--greyForegroundColor);
+
+ &.livechat-empty {
+ height: 0;
+ margin: 0;
+ border: none;
+ }
+ }
+
+ .livechat-tags-searched {
&::after {
content: "\1F50D";
flex-grow: 1;
text-align: right;
}
- &.empty {
+ &.livechat-empty {
&::after {
display: none;
}
}
}
- .tag,
- .tag-searched {
+ .livechat-tag,
+ .livechat-tag-searched {
width: auto;
height: 24px;
display: flex;
@@ -400,7 +413,7 @@ livechat-tags-input {
margin: 0 3px 3px 0;
transition: 0.3s filter;
- .tag-close {
+ .livechat-tag-close {
display: block;
width: 12px;
height: 12px;
@@ -424,7 +437,7 @@ livechat-tags-input {
color: #fff;
background-color: var(--mainColor);
- .tag-close {
+ .livechat-tag-close {
color: var(--mainColor);
}
}
@@ -433,7 +446,7 @@ livechat-tags-input {
color: #fff;
background-color: var(--mainHoverColor);
- .tag-close {
+ .livechat-tag-close {
color: var(--mainHoverColor);
}
}
@@ -444,12 +457,12 @@ livechat-tags-input {
color: #fff;
background-color: var(--inputBorderColor);
- .tag-close {
+ .livechat-tag-close {
color: var(--inputBorderColor);
}
}
- .tag-name {
+ .livechat-tag-name {
margin-top: 3px;
text-overflow: ellipsis;
overflow: hidden;
@@ -458,7 +471,7 @@ livechat-tags-input {
}
}
- #tags.unfocused .tag {
+ .livechat-tags.livechat-unfocused .livechat-tag {
filter: opacity(50%) grayscale(80%);
}
}
diff --git a/client/@types/global.d.ts b/client/@types/global.d.ts
index 468ce51f..02f40a25 100644
--- a/client/@types/global.d.ts
+++ b/client/@types/global.d.ts
@@ -23,6 +23,7 @@ declare const LOC_SHOW_SCROLLBARR: string
declare const LOC_TRANSPARENT_BACKGROUND: string
declare const LOC_TIPS_FOR_STREAMERS: string
declare const LOC_COPY: string
+declare const LOC_COPIED: string
declare const LOC_LINK_COPIED: string
declare const LOC_ERROR: string
declare const LOC_OPEN: string
diff --git a/client/common/lib/elements/tags-input.ts b/client/common/lib/elements/tags-input.ts
index fcea98cf..ad7f57a3 100644
--- a/client/common/lib/elements/tags-input.ts
+++ b/client/common/lib/elements/tags-input.ts
@@ -2,14 +2,30 @@
//
// SPDX-License-Identifier: AGPL-3.0-only
-import { html } from 'lit'
-import { customElement, property, state } from 'lit/decorators.js'
import { LivechatElement } from './livechat'
+import { ptTr } from '../directives/translation'
+import { html } from 'lit'
+import { unsafeHTML } from 'lit/directives/unsafe-html.js'
+import { customElement, property, state } from 'lit/decorators.js'
import { ifDefined } from 'lit/directives/if-defined.js'
import { classMap } from 'lit/directives/class-map.js'
import { animate, fadeOut, fadeIn } from '@lit-labs/motion'
import { repeat } from 'lit/directives/repeat.js'
+// FIXME: find a better way to store this image.
+// This content comes from the file assets/images/copy.svg, after svgo cleaning.
+// To get the formated content, you can do:
+// xmllint dist/client/images/copy.svg --format
+// Then replace the main color by «currentColor»
+const copySVG = `
+ ` +
+ // eslint-disable-next-line max-len
+ ' ' +
+ // eslint-disable-next-line max-len
+ ' ' +
+ `
+ `
+
@customElement('livechat-tags-input')
export class TagsInputElement extends LivechatElement {
@property({ attribute: false })
@@ -71,30 +87,55 @@ export class TagsInputElement extends LivechatElement {
}
protected override render = (): unknown => {
- return html`
-