diff --git a/package.json b/package.json index 189e3fb0..73d41103 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "impro", - "version": "0.17.8", + "version": "0.17.9", "type": "module", "scripts": { "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve", diff --git a/src/css/style.css b/src/css/style.css index c6260b82..deea595d 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -179,7 +179,7 @@ html { --floating-back-button-z-index: 3; --reply-prompt-z-index: 4; --message-input-z-index: 4; - --reaction-palette-z-index: 4; + --reaction-palette-z-index: 5; --toast-z-index: 5; --floating-compose-button-z-index: 6; --sidebar-z-index: 8; @@ -850,7 +850,7 @@ header { height: var(--chat-detail-header-height); } -#chat-detail-view .header-row .member-avatar-stack { +#chat-detail-view .header-row .avatar-group { width: var(--avatar-size-post); height: var(--avatar-size-post); } @@ -3328,60 +3328,89 @@ image-carousel { height: var(--avatar-size-convo); } -.member-avatar-stack { +.avatar-group { position: relative; width: var(--avatar-size-convo); height: var(--avatar-size-convo); } -.member-avatar-stack-item { +.avatar-group-item { position: absolute; } -.member-avatar-stack-item .avatar-image-frame { +.avatar-group-item .avatar-image-frame { + display: block; width: 100%; height: 100%; } -.member-avatar-stack-2 .member-avatar-stack-item { - width: 63%; - height: 63%; +.avatar-group-2 .avatar-group-item { + width: 63.3%; + height: 63.3%; } -.member-avatar-stack-2 .member-avatar-stack-item:nth-child(1) { +.avatar-group-2 .avatar-group-item:nth-child(1) { top: 0; left: 0; z-index: 1; } -.member-avatar-stack-2 .member-avatar-stack-item:nth-child(2) { - bottom: 0; - right: 0; +.avatar-group-2 .avatar-group-item:nth-child(2) { + top: 35%; + left: 35%; } -.member-avatar-stack-2 .member-avatar-stack-item .avatar-image-frame { +.avatar-group-2 .avatar-group-item .avatar-image-frame { border: 2px solid var(--background-color); } -.member-avatar-stack-3 .member-avatar-stack-item:nth-child(1) { - width: 57%; - height: 57%; +.avatar-group-3 .avatar-group-item:nth-child(1) { + width: 56.7%; + height: 56.7%; top: 0; left: 0; } -.member-avatar-stack-3 .member-avatar-stack-item:nth-child(2) { - width: 47%; - height: 47%; - bottom: 0; - left: 32%; +.avatar-group-3 .avatar-group-item:nth-child(2) { + width: 46.7%; + height: 46.7%; + top: 51.7%; + left: 31.7%; } -.member-avatar-stack-3 .member-avatar-stack-item:nth-child(3) { - width: 38%; - height: 38%; +.avatar-group-3 .avatar-group-item:nth-child(3) { + width: 38.3%; + height: 38.3%; top: 15%; - right: 0; + left: 59.2%; +} + +.avatar-group-4 .avatar-group-item:nth-child(1) { + width: 56.7%; + height: 56.7%; + top: 0; + left: 0; +} + +.avatar-group-4 .avatar-group-item:nth-child(2) { + width: 46.7%; + height: 46.7%; + top: 40.8%; + left: 50%; +} + +.avatar-group-4 .avatar-group-item:nth-child(3) { + width: 35%; + height: 35%; + top: 61.7%; + left: 11.7%; +} + +.avatar-group-4 .avatar-group-item:nth-child(4) { + width: 26.7%; + height: 26.7%; + top: 7.5%; + left: 60%; } .convo-content { @@ -3795,6 +3824,7 @@ chat-input { .message-input-field { flex: 1; + width: 100%; padding: 12px 16px; border: 1px solid var(--highlight-color); border-radius: var(--message-input-border-radius); @@ -3821,6 +3851,67 @@ chat-input { opacity: 0.6; } +.message-input-field-wrapper { + position: relative; + flex: 1; + display: flex; +} + +.message-input-emoji-wrapper { + position: absolute; + right: 6px; + bottom: 6px; + display: flex; + align-items: center; +} + +@media (max-width: 799px) { + .message-input-emoji-wrapper { + display: none; + } +} + +@media (min-width: 800px) { + .message-input-field-wrapper .message-input-field { + padding-right: 46px; + } +} + +.message-input-emoji-button { + flex-shrink: 0; + width: 32px; + height: 32px; + border-radius: 50%; + background: transparent; + border: none; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: var(--text-color-muted); + padding: 0; + transition: + background-color 0.2s, + color 0.2s; +} + +@media (min-width: 800px) { + .message-input-emoji-button:hover:not(:disabled) { + background-color: var(--post-hover-color); + color: var(--text-color); + } +} + +.message-input-emoji-button:disabled { + opacity: 0.5; + cursor: default; +} + +.message-input-emoji-button .emoji-icon { + width: 22px; + height: 22px; +} + .message-input-send-button { flex-shrink: 0; width: 40px; diff --git a/src/img/icons/custom/emoji-smile-line.svg b/src/img/icons/custom/emoji-smile-line.svg new file mode 100644 index 00000000..75ff3f1e --- /dev/null +++ b/src/img/icons/custom/emoji-smile-line.svg @@ -0,0 +1 @@ + diff --git a/src/js/components/chat-input.js b/src/js/components/chat-input.js index 2341feac..4e467ddc 100644 --- a/src/js/components/chat-input.js +++ b/src/js/components/chat-input.js @@ -1,7 +1,9 @@ import { Component } from "/js/components/component.js"; import { html, render } from "/js/lib/lit-html.js"; import { sendIconTemplate } from "/js/templates/icons/sendIcon.template.js"; +import { emojiIconTemplate } from "/js/templates/icons/emojiIcon.template.js"; import { isMobileViewport } from "/js/utils.js"; +import "/js/components/emoji-picker-dialog.js"; class ChatInput extends Component { static get observedAttributes() { @@ -82,6 +84,29 @@ class ChatInput extends Component { } } + handleEmojiButtonClick(event) { + const dialog = this.querySelector("emoji-picker-dialog"); + if (!dialog) return; + if (dialog.isOpen) { + dialog.close(); + } else { + dialog.open(event.currentTarget); + } + } + + handleEmojiSelect(emoji) { + const textarea = this.querySelector(".message-input-field"); + if (!textarea) return; + const start = textarea.selectionStart ?? textarea.value.length; + const end = textarea.selectionEnd ?? textarea.value.length; + textarea.value = + textarea.value.slice(0, start) + emoji + textarea.value.slice(end); + const cursor = start + emoji.length; + textarea.focus(); + textarea.setSelectionRange(cursor, cursor); + textarea.dispatchEvent(new InputEvent("input", { bubbles: true })); + } + handleKeyDown(e) { if (e.key === "Enter" && !e.shiftKey) { if (isMobileViewport()) return; @@ -93,15 +118,34 @@ class ChatInput extends Component { render() { const template = html`
- +
+ +
+ + { + this.handleEmojiSelect(e.detail.emoji); + e.currentTarget.close(); + }} + > +
+