Skip to content

Instantly share code, notes, and snippets.

@thinkawitch
Created October 2, 2020 10:56
Show Gist options
  • Save thinkawitch/b382da09bff116c9de47cfad9eaf9fe2 to your computer and use it in GitHub Desktop.
Save thinkawitch/b382da09bff116c9de47cfad9eaf9fe2 to your computer and use it in GitHub Desktop.
vertical resize for css grid in react hooks
/* css vars names must be unique */
:root {
--ezc-color-gray-100: #f8f9fa;
--ezc-color-gray-200: #e9ecef;
--ezc-color-gray-300: #dee2e6;
--ezc-color-gray-400: #ced4da;
--ezc-color-gray-500: #adb5bd;
--ezc-color-gray-600: #6c757d;
--ezc-color-gray-700: #495057;
--ezc-color-gray-800: #343a40;
--ezc-color-gray-900: #212529;
--ezc-color-body: #fefefe;
--ezc-color-black: #000000;
--ezc-messages-width-min: 250px;
--ezc-messages-width: auto;
--ezc-vresize-width: 10px;
--ezc-users-width-min: 150px;
--ezc-users-width-max: 300px;
--ezc-users-width: 200px;
--ezc-send-message-height: 40px;
--ezc-header-tabs-height: 26px;
--ezc-header-tabs-border-radius: 3px;
}
@function css_var($var-name) {
@return var(--#{$var-name});
}
// scss variables
$ez-ml-panel-padding: 4px; // inner padding of main panel with active tab
import React, { Fragment, useEffect } from 'react';
import { updateCssVar, getCssVarPx } from '../utils/css';
import MessagesContainer from './messages-container';
import UsersContainer from './users-container';
function MainContainer(props) {
useEffect(effectToResizeUsersColumn);
return (
<Fragment>
<div className="ezchat-main-layout">
<div className="ez-ml-messages">
<MessagesContainer />
</div>
<div className="ez-ml-send-message">[send message]</div>
<div className="ez-ml-vresize for-users">
<div className="v-resize-bar" />
</div>
<div className="ez-ml-users">
<UsersContainer />
</div>
<div className="ez-ml-vresize for-actions">
<div className="v-resize-bar" />
</div>
<div className="ez-ml-actions">actions</div>
</div>
</Fragment>
);
}
export default MainContainer;
// layout resizers
function effectToResizeUsersColumn() {
const messagesMinWidth = getCssVarPx('--ezc-messages-width-min');
const vresizeWidth = getCssVarPx('--ezc-vresize-width');
const usersMinWidth = getCssVarPx('--ezc-users-width-min');
const usersMaxWidth = getCssVarPx('--ezc-users-width-max');
//console.log('usersMinWidth', usersMinWidth, 'usersMaxWidth', usersMaxWidth)
let pageWidth = window.innerWidth;
//let resizedByUser = false;
let origX = null;
let origWidth = null;
function resize(e) {
if (origX === null) {
origX = e.pageX;
origWidth = document.querySelector('.ez-ml-users').getBoundingClientRect().width;
}
var newWidth = origX - e.pageX + origWidth;
if (newWidth < usersMinWidth) newWidth = usersMinWidth;
if (newWidth > usersMaxWidth) newWidth = usersMaxWidth;
window.requestAnimationFrame(() => {
updateCssVar('--ezc-users-width', newWidth+'px');
});
}
function stopResize() {
el.classList.remove('resizing');
window.removeEventListener('mousemove', resize);
origX = null;
document.body.style.cursor = 'default';
}
function onMouseDown(e) {
e.preventDefault();
document.body.style.cursor = 'ew-resize';
//resizedByUser = true;
el.classList.add('resizing');
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', stopResize);
}
const el = document.querySelector('.ez-ml-vresize.for-users');
el.addEventListener('mousedown', onMouseDown);
function onWindowResize() {
if (/*resizedByUser &&*/ window.innerWidth < pageWidth) {
const diff = (pageWidth - window.innerWidth);
let fullWidth = document.querySelector('.ezchat-main-layout').getBoundingClientRect().width - diff;
const messagesWidth = document.querySelector('.ez-ml-messages').getBoundingClientRect().width - diff;
const usersWidth = document.querySelector('.ez-ml-users').getBoundingClientRect().width;
//console.log('fullWidth', fullWidth, 'messagesWidth', messagesWidth, 'usersWidth', usersWidth);
let newWidth = usersWidth;
if (messagesWidth <= messagesMinWidth) {
newWidth = fullWidth - messagesMinWidth - vresizeWidth;
if (newWidth < usersMinWidth) newWidth = usersMinWidth;
}
window.requestAnimationFrame(function() {
updateCssVar('--ezc-users-width', newWidth+'px');
});
}
pageWidth = window.innerWidth;
}
window.addEventListener('resize', onWindowResize);
return () => {
// undo effect
window.removeEventListener('mousemove', resize);
window.removeEventListener('mouseup', stopResize);
window.removeEventListener('resize', onWindowResize);
el.removeEventListener('mousedown', onMouseDown);
}
}
function effectToResizeMessagesColumn() {
const messagesMinWidth = 580;
let messagesMaxWidth = getMessagesMaxWidth();
let pageWidth = window.innerWidth;
let resizedByUser = false;
function getMessagesMaxWidth() {
return document.querySelector('.ezchat-main-layout').getBoundingClientRect().width - 250;
}
let origX = null;
let origWidth = null;
function resize(e) {
if (origX === null) {
origX = e.pageX;
origWidth = document.querySelector('.ez-ml-messages').getBoundingClientRect().width;
}
var newWidth = origX + e.pageX - origWidth;
if (newWidth < messagesMinWidth) newWidth = messagesMinWidth;
if (newWidth > messagesMaxWidth) newWidth = messagesMaxWidth;
window.requestAnimationFrame(() => {
updateCssVar('--ezc-messages-width', newWidth+'px');
});
}
function stopResize() {
el.classList.remove('resizing');
window.removeEventListener('mousemove', resize);
origX = null;
document.body.style.cursor = 'default';
}
function onMouseDown(e) {
e.preventDefault();
document.body.style.cursor = 'ew-resize';
resizedByUser = true;
el.classList.add('resizing');
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', stopResize);
}
const el = document.querySelector('.ez-ml-vresize.for-messages');
el.addEventListener('mousedown', onMouseDown);
function onWindowResize() {
messagesMaxWidth = getMessagesMaxWidth();
if (resizedByUser && window.innerWidth < pageWidth) {
var newWidth = document.querySelector('.ez-ml-messages').getBoundingClientRect().width - (pageWidth - window.innerWidth);
if (newWidth < messagesMinWidth) newWidth = messagesMinWidth;
window.requestAnimationFrame(function() {
updateCssVar('--ezc-messages-width', newWidth+'px');
});
}
pageWidth = window.innerWidth;
}
window.addEventListener('resize', onWindowResize);
return () => {
// undo effect
window.removeEventListener('mousemove', resize);
window.removeEventListener('mouseup', stopResize);
window.removeEventListener('resize', onWindowResize);
el.removeEventListener('mousedown', onMouseDown);
}
}
.ezchat-main-layout {
display: grid;
height: 100%;
grid-template-areas:
"messages vresize users"
"send-message vresize users";
grid-template-rows: auto var(--ezc-send-message-height);
grid-template-columns: minmax(var(--ezc-messages-width-min),auto) 10px var(--ezc-users-width);
.ez-ml-vresize.for-actions { display: none; }
.ez-ml-actions { display: none; }
&.with-moderation {
grid-template-areas:
"messages vresize users vresize actions"
"send-message vresize users vresize actions";
.ez-ml-vresize.for-actions { display: none; }
.ez-ml-actions { display: block; }
}
}
.ez-ml-messages {
grid-area: messages;
background-color: lightgoldenrodyellow;
}
.ez-ml-send-message {
grid-area: send-message;
background-color: lightcyan;
}
.ez-ml-vresize {
grid-area: vresize;
background-color: seashell;
}
.ez-ml-users {
grid-area: users;
background-color: honeydew;
}
.ez-ml-actions {
grid-area: actions;
}
/* vertical resize panel */
.ez-ml-vresize {
width: var(--ezc-vresize-width);
padding: 3px 0;
cursor: ew-resize;
.v-resize-bar {
width: 1px;
background-color: var(--ezc-color-gray-300);
margin: 0 auto;
height: 100%;
}
&.resizing {
background-color: var(--ezc-color-gray-500);
.v-resize-bar {
background-color: var(--color-dark);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment