Initial attempt at sticky headers

Docs enclosed in diff.
This commit is contained in:
Travis Ralston 2020-06-13 11:54:40 -06:00
parent cbe9ade1c9
commit 1bbf2e053b
4 changed files with 154 additions and 10 deletions

View file

@ -86,6 +86,70 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
}
};
// TODO: Apply this on resize, init, etc for reliability
private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => {
const list = ev.target as HTMLDivElement;
const rlRect = list.getBoundingClientRect();
const bottom = rlRect.bottom;
const top = rlRect.top;
const sublists = list.querySelectorAll<HTMLDivElement>(".mx_RoomSublist2");
const headerHeight = 32; // Note: must match the CSS!
const headerRightMargin = 24; // calculated from margins and widths to align with non-sticky tiles
const headerStickyWidth = rlRect.width - headerRightMargin;
let gotBottom = false;
for (const sublist of sublists) {
const slRect = sublist.getBoundingClientRect();
const header = sublist.querySelector<HTMLDivElement>(".mx_RoomSublist2_headerText");
if (slRect.top + headerHeight > bottom && !gotBottom) {
console.log(`${header.textContent} is off the bottom`);
header.classList.add("mx_RoomSublist2_headerContainer_sticky");
header.classList.add("mx_RoomSublist2_headerContainer_stickyBottom");
header.style.width = `${headerStickyWidth}px`;
gotBottom = true;
} else if (slRect.top < top) {
console.log(`${header.textContent} is off the top`);
header.classList.add("mx_RoomSublist2_headerContainer_sticky");
header.classList.add("mx_RoomSublist2_headerContainer_stickyTop");
header.style.width = `${headerStickyWidth}px`;
header.style.top = `${rlRect.top}px`;
} else {
header.classList.remove("mx_RoomSublist2_headerContainer_sticky");
header.classList.remove("mx_RoomSublist2_headerContainer_stickyTop");
header.classList.remove("mx_RoomSublist2_headerContainer_stickyBottom");
header.style.width = `unset`;
}
// const name = header.textContent;
// if (hRect.bottom + headerHeight < top) {
// // Before the content (top of list)
// header.classList.add(
// "mx_RoomSublist2_headerContainer_sticky",
// "mx_RoomSublist2_headerContainer_stickyTop",
// );
// } else {
// header.classList.remove(
// "mx_RoomSublist2_headerContainer_sticky",
// "mx_RoomSublist2_headerContainer_stickyTop",
// "mx_RoomSublist2_headerContainer_stickyBottom",
// );
// }
// if (!hitMiddle && (headerHeight + hRect.top) >= bottom) {
// // if we got here, the header is visible
// hitMiddle = true;
// header.style.backgroundColor = 'red';
// } else {
// header.style.top = "0px";
// header.style.bottom = "unset";
// header.style.backgroundColor = "unset";
// }
}
};
private renderHeader(): React.ReactNode {
// TODO: Update when profile info changes
// TODO: Presence
@ -191,7 +255,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
<aside className="mx_LeftPanel2_roomListContainer">
{this.renderHeader()}
{this.renderSearchExplore()}
<div className="mx_LeftPanel2_actualRoomListContainer">
<div className="mx_LeftPanel2_actualRoomListContainer" onScroll={this.onScroll}>
{roomList}
</div>
</aside>