Browse Source

reimplementing multiselect chat input animation

master
morethanwords 3 years ago
parent
commit
2ff7c7050f
  1. 12
      src/components/chat/input.ts
  2. 32
      src/components/chat/selection.ts
  3. 276
      src/scss/partials/_chat.scss

12
src/components/chat/input.ts

@ -58,7 +58,7 @@ export default class ChatInput { @@ -58,7 +58,7 @@ export default class ChatInput {
public rowsWrapper: HTMLDivElement;
private newMessageWrapper: HTMLDivElement;
private btnToggleEmoticons: HTMLButtonElement;
private btnSendContainer: HTMLDivElement;
public btnSendContainer: HTMLDivElement;
public attachMenu: HTMLButtonElement;
private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[];
@ -128,9 +128,15 @@ export default class ChatInput { @@ -128,9 +128,15 @@ export default class ChatInput {
this.inputContainer.classList.add('chat-input-container');
this.rowsWrapper = document.createElement('div');
this.rowsWrapper.classList.add('rows-wrapper');
this.rowsWrapper.classList.add('rows-wrapper', 'chat-input-wrapper');
this.inputContainer.append(this.rowsWrapper);
const fakeRowsWrapper = document.createElement('div');
fakeRowsWrapper.classList.add('fake-wrapper', 'fake-rows-wrapper');
const fakeSelectionWrapper = document.createElement('div');
fakeSelectionWrapper.classList.add('fake-wrapper', 'fake-selection-wrapper');
this.inputContainer.append(this.rowsWrapper, fakeRowsWrapper, fakeSelectionWrapper);
this.chatInput.append(this.inputContainer);
this.goDownBtn = Button('bubbles-go-down btn-corner btn-circle z-depth-1 hide', {icon: 'arrow_down'});

32
src/components/chat/selection.ts

@ -21,6 +21,7 @@ export default class ChatSelection { @@ -21,6 +21,7 @@ export default class ChatSelection {
public selectedMids: Set<number> = new Set();
public isSelecting = false;
private selectionInputWrapper: HTMLElement;
private selectionContainer: HTMLElement;
private selectionCountEl: HTMLElement;
public selectionSendNowBtn: HTMLElement;
@ -274,12 +275,27 @@ export default class ChatSelection { @@ -274,12 +275,27 @@ export default class ChatSelection {
blurActiveElement(); // * for mobile keyboards
let transform = '';
const forwards = !!this.selectedMids.size || forceSelection;
if(forwards) {
const p = this.input.rowsWrapper.parentElement;
const widthFrom = p.querySelector('.fake-rows-wrapper').scrollWidth;
const widthTo = p.querySelector('.fake-selection-wrapper').scrollWidth;
const btnSendWidth = this.input.btnSendContainer.scrollWidth - (.5625 * 16);
if(widthFrom !== widthTo) {
const scale = widthTo / widthFrom;
transform = `translateX(${btnSendWidth * scale}px) scaleX(${scale})`;
//scale = widthTo / widthFrom;
}
}
SetTransition(this.input.rowsWrapper, 'is-centering', forwards, 200);
this.input.rowsWrapper.style.transform = transform;
SetTransition(bubblesContainer, 'is-selecting', forwards, 200, () => {
if(!this.isSelecting) {
this.selectionContainer.remove();
this.selectionContainer = this.selectionSendNowBtn = this.selectionForwardBtn = this.selectionDeleteBtn = null;
this.selectionInputWrapper.remove();
this.selectionInputWrapper = this.selectionContainer = this.selectionSendNowBtn = this.selectionForwardBtn = this.selectionDeleteBtn = null;
this.selectedText = undefined;
}
@ -292,6 +308,9 @@ export default class ChatSelection { @@ -292,6 +308,9 @@ export default class ChatSelection {
if(this.isSelecting) {
if(!this.selectionContainer) {
this.selectionInputWrapper = document.createElement('div');
this.selectionInputWrapper.classList.add('chat-input-wrapper', 'selection-wrapper');
this.selectionContainer = document.createElement('div');
this.selectionContainer.classList.add('selection-container');
@ -329,7 +348,12 @@ export default class ChatSelection { @@ -329,7 +348,12 @@ export default class ChatSelection {
this.selectionContainer.append(...[btnCancel, this.selectionCountEl, this.selectionSendNowBtn, this.selectionForwardBtn, this.selectionDeleteBtn].filter(Boolean));
this.input.rowsWrapper.append(this.selectionContainer);
this.selectionInputWrapper.style.opacity = '0';
this.selectionInputWrapper.append(this.selectionContainer);
this.input.rowsWrapper.parentElement.append(this.selectionInputWrapper);
void this.selectionInputWrapper.offsetLeft; // reflow
this.selectionInputWrapper.style.opacity = '';
}
}
@ -461,4 +485,4 @@ export default class ChatSelection { @@ -461,4 +485,4 @@ export default class ChatSelection {
public canSelectBubble(bubble: HTMLElement) {
return !bubble.classList.contains('service') && !bubble.classList.contains('is-sending');
}
}
}

276
src/scss/partials/_chat.scss

@ -203,6 +203,7 @@ $chat-helper-size: 39px; @@ -203,6 +203,7 @@ $chat-helper-size: 39px;
}
.btn-send {
transition: .2s transform !important;
color: #9e9e9e;
z-index: 3;
@ -357,24 +358,13 @@ $chat-helper-size: 39px; @@ -357,24 +358,13 @@ $chat-helper-size: 39px;
width: 0px;
}
}
.new-message-wrapper, .pinned-container {
opacity: 1;
transition: opacity .1s 0s;
}
.bubbles.is-selecting ~ & {
.new-message-wrapper, .pinned-container {
html:not(.is-safari) & {
transition: .1s opacity;
}
}
.selection-container {
opacity: 0;
}
.btn-send {
html:not(.is-safari) & {
transition: .2s transform;
}
}
.new-message-wrapper {
pointer-events: none;
}
@ -385,27 +375,15 @@ $chat-helper-size: 39px; @@ -385,27 +375,15 @@ $chat-helper-size: 39px;
opacity: 0;
}
.selection-container {
html:not(.is-safari) & {
animation: fade-in-opacity .1s .1s forwards;
}
html.is-safari & {
opacity: 1;
}
.selection-wrapper {
opacity: 1;
}
.rows-wrapper {
max-height: var(--chat-input-size);
width: 28.75rem;
//max-width: 28.75rem;
//box-shadow: none;
}
/* .reply-wrapper {
transform: none !important;
border-radius: inherit;
} */
.reply-wrapper {
height: 0 !important;
}
@ -417,15 +395,11 @@ $chat-helper-size: 39px; @@ -417,15 +395,11 @@ $chat-helper-size: 39px;
.bubbles.is-selecting.backwards ~ & {
.new-message-wrapper, .pinned-container {
html:not(.is-safari) & {
transition-delay: .1s;
}
transition: opacity .1s .1s;
}
.selection-container {
html:not(.is-safari) & {
animation: fade-in-backwards-opacity .1s forwards;
}
.selection-wrapper {
transition: opacity .1s 0s;
}
}
@ -611,7 +585,7 @@ $chat-helper-size: 39px; @@ -611,7 +585,7 @@ $chat-helper-size: 39px;
}
}
.rows-wrapper {
.chat-input-wrapper {
--padding-vertical: .3125rem;
--padding-horizontal: .5rem;
--padding: var(--padding-vertical) var(--padding-horizontal);
@ -636,86 +610,128 @@ $chat-helper-size: 39px; @@ -636,86 +610,128 @@ $chat-helper-size: 39px;
body.animation-level-0 & {
transition: none;
}
}
.chat-input.type-pinned & {
width: 17.125rem;
}
.chat-input.type-pinned.can-pin & {
width: 13.125rem;
}
.selection-wrapper {
position: absolute;
left: 50%;
top: 0;
width: 28.75rem;
transform: translateX(-50%);
border-radius: $border-radius-big;
//z-index: 2;
box-shadow: none;
transition: opacity .1s .1s;
opacity: 0;
&.is-centering {
html:not(.is-safari) & {
transition: width .2s, max-height .2s, border-bottom-right-radius .1s, transform .2s;
.selection-container {
display: flex;
justify-content: space-between;
height: 100%;
//background-color: #ccc;
border-radius: inherit;
padding: inherit;
user-select: none;
font-size: 15px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
&:after {
transition: transform .1s;
}
&-count {
color: #000;
font-weight: 500;
flex-grow: 1;
white-space: nowrap;
//padding-left: .5rem;
}
html.is-safari & {
transition: none;
.btn-icon {
margin: 0 5px 0 6px;
color: #3f454a;
height: 42px;
width: 42px;
line-height: 42px;
}
//will-change: transform;
}
&.is-centering:not(.backwards), &.is-centered {
border-bottom-right-radius: 12px;
transform-origin: left;
transform: translate3d(25%, 0, 0);
//transform: translate3d(calc(((var(--messages-container-width) - var(--chat-input-padding) * 2) - 100%) / 2), 0, 0);
//transform: translate3d(#{calc(28.75rem / 4)}, 0, 0);
.btn-primary {
height: 2.5rem;
width: auto;
/* html.is-safari & {
max-width: 28.75rem;
} */
/* transform: translateX(-50%);
left: 50%;
position: absolute; */
@include respond-to(handhelds) {
padding: 0 .5rem;
// left sidebar (420px) + 728px chat max width
@media only screen and (min-width: $floating-left-sidebar + 1) and (max-width: $large-screen / 4 + $messages-container-width) {
//transform: translateX(calc((100vw - 420px - 100%) / 2 - #{$chat-padding}));
transform: translate3d(calc((100vw - min(100vw / 2.5, #{$large-screen / 4}) - 100%) / 2 - #{$chat-padding}), 0, 0) !important;
}
&.tgico-send2 {
padding: 0 2px;
}
}
@media only screen and (max-width: 728px) {
//transform: translateX(calc((100vw - 420px - 100%) / 2 - #{$chat-padding}));
transform: translate3d(calc((100vw - 100%) / 2 - #{$chat-padding}), 0, 0) !important;
@media only screen and (max-width: 380px) {
font-size: 0;
&:before {
margin: 0;
}
}
}
@include respond-to(handhelds) {
transform: translate3d(calc((100vw - 100%) / 2 - #{$chat-padding-handhelds}), 0, 0) !important;
&-forward {
&:before {
margin-right: 14px;
}
}
&:after {
transform: scaleX(-1) translateX(#{.5625rem * 2});
&-delete {
margin-right: .625rem;
margin-left: .375rem;
&:before {
margin-right: 10px;
}
}
}
}
&.is-centered, &.is-centered.is-centering:not(.backwards) {
transform: translate3d(calc(((var(--messages-container-width) - var(--chat-input-padding) * 2) - 100%) / 2), 0, 0);
.fake-wrapper {
position: absolute;
z-index: -1;
visibility: hidden;
}
.fake-rows-wrapper {
width: calc(100% - var(--chat-input-size) - (var(--padding-horizontal) * 2) - .5625rem);
}
.fake-selection-wrapper {
width: 460px;
}
.rows-wrapper {
transform: scaleX(1);
transition: transform .2s, width .2s, max-height .2s, border-bottom-right-radius .1s;
&:after {
transition: transform .1s;
}
// ! Need due to reply transform under the container
&:before {
position: absolute;
z-index: 2;
left: 0;
top: 0;
bottom: 0;
right: 0;
background: inherit;
content: " ";
display: block;
border-radius: inherit;
.chat-input.type-pinned & {
width: 17.125rem;
}
.chat-input.type-pinned.can-pin & {
width: 13.125rem;
}
/* #chat-input.is-helper-active & {
border-top-left-radius: 0;
border-top-right-radius: 0;
&.is-centering:not(.backwards), &.is-centered {
border-bottom-right-radius: 12px;
&:after {
transform: scaleX(-1) translateX(#{.5625rem * 2});
}
}
/* &.is-centered, &.is-centered.is-centering:not(.backwards) {
transform: translate3d(calc(((var(--messages-container-width) - var(--chat-input-padding) * 2) - 100%) / 2), 0, 0);
} */
@include respond-to(handhelds) {
@ -851,70 +867,6 @@ $chat-helper-size: 39px; @@ -851,70 +867,6 @@ $chat-helper-size: 39px;
}
}
.selection-container {
position: absolute;
left: 0;
top: 0;
height: 100%;
//background-color: #ccc;
border-radius: inherit;
padding: inherit;
user-select: none;
font-size: 15px;
&-count {
color: #000;
font-weight: 500;
flex-grow: 1;
white-space: nowrap;
//padding-left: .5rem;
}
.btn-icon {
margin: 0 5px 0 6px;
color: #3f454a;
height: 42px;
width: 42px;
line-height: 42px;
}
.btn-primary {
height: 2.5rem;
width: auto;
@include respond-to(handhelds) {
padding: 0 .5rem;
&.tgico-send2 {
padding: 0 2px;
}
}
@media only screen and (max-width: 380px) {
font-size: 0;
&:before {
margin: 0;
}
}
}
&-forward {
&:before {
margin-right: 14px;
}
}
&-delete {
margin-right: .625rem;
margin-left: .375rem;
&:before {
margin-right: 10px;
}
}
}
.pinned-container {
width: 17.125rem;

Loading…
Cancel
Save