mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 12:13:58 -06:00
UX: Horizontal scroll bar on top of user directory (when needed) (#13553)
This commit is contained in:
parent
7d0d13c32e
commit
d03aee4642
@ -2,16 +2,103 @@ import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["directory-table-container"],
|
||||
lastScrollPosition: 0,
|
||||
ticking: false,
|
||||
_topHorizontalScrollBar: null,
|
||||
_tableContainer: null,
|
||||
_table: null,
|
||||
_fakeScrollContent: null,
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
this.setProperties({
|
||||
_tableContainer: this.element.querySelector(".directory-table-container"),
|
||||
_topHorizontalScrollBar: this.element.querySelector(
|
||||
".directory-table-top-scroll"
|
||||
),
|
||||
_fakeScrollContent: this.element.querySelector(
|
||||
".directory-table-top-scroll-fake-content"
|
||||
),
|
||||
_table: this.element.querySelector(".directory-table"),
|
||||
});
|
||||
|
||||
this._tableContainer.addEventListener("scroll", this.onBottomScroll);
|
||||
this._topHorizontalScrollBar.addEventListener("scroll", this.onTopScroll);
|
||||
|
||||
// Set active header might have already scrolled the _tableContainer.
|
||||
// Call onHorizontalScroll manually to scroll the _topHorizontalScrollBar
|
||||
this.onResize();
|
||||
this.onHorizontalScroll(this._tableContainer, this._topHorizontalScrollBar);
|
||||
window.addEventListener("resize", this.onResize);
|
||||
},
|
||||
|
||||
@action
|
||||
onResize() {
|
||||
if (
|
||||
this._tableContainer.getBoundingClientRect().bottom < window.innerHeight
|
||||
) {
|
||||
// Bottom of the table is visible. Hide the scrollbar
|
||||
this._fakeScrollContent.style.height = 0;
|
||||
} else {
|
||||
this._fakeScrollContent.style.width = `${this._table.offsetWidth}px`;
|
||||
this._fakeScrollContent.style.height = "1px";
|
||||
}
|
||||
},
|
||||
|
||||
@action
|
||||
onTopScroll() {
|
||||
this.onHorizontalScroll(this._topHorizontalScrollBar, this._tableContainer);
|
||||
},
|
||||
|
||||
@action
|
||||
onBottomScroll() {
|
||||
this.onHorizontalScroll(this._tableContainer, this._topHorizontalScrollBar);
|
||||
},
|
||||
|
||||
@action
|
||||
onHorizontalScroll(primary, replica) {
|
||||
if (this.lastScrollPosition === primary.scrollLeft) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("lastScrollPosition", primary.scrollLeft);
|
||||
|
||||
if (!this.ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
replica.scrollLeft = this.lastScrollPosition;
|
||||
this.set("ticking", false);
|
||||
});
|
||||
|
||||
this.set("ticking", true);
|
||||
}
|
||||
},
|
||||
|
||||
willDestoryElement() {
|
||||
this._tableContainer.removeEventListener("scroll", this.onBottomScroll);
|
||||
this._topHorizontalScrollBar.removeEventListener(
|
||||
"scroll",
|
||||
this.onTopScroll
|
||||
);
|
||||
window.removeEventListener("resize", this.onResize);
|
||||
},
|
||||
|
||||
@action
|
||||
setActiveHeader(header) {
|
||||
// After render, scroll table left to ensure the order by column is visible
|
||||
if (!this._tableContainer) {
|
||||
this.set(
|
||||
"_tableContainer",
|
||||
document.querySelector(".directory-table-container")
|
||||
);
|
||||
}
|
||||
const scrollPixels =
|
||||
header.offsetLeft + header.offsetWidth + 10 - this.element.offsetWidth;
|
||||
header.offsetLeft +
|
||||
header.offsetWidth +
|
||||
10 -
|
||||
this._tableContainer.offsetWidth;
|
||||
|
||||
if (scrollPixels > 0) {
|
||||
this.element.scrollLeft = scrollPixels;
|
||||
this._tableContainer.scrollLeft = scrollPixels;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -1,25 +1,31 @@
|
||||
<table>
|
||||
<thead>
|
||||
{{table-header-toggle field="username" order=order asc=asc}}
|
||||
{{#each columns as |column|}}
|
||||
{{table-header-toggle
|
||||
field=column.name
|
||||
icon=column.icon
|
||||
order=order
|
||||
asc=asc
|
||||
automatic=(directory-column-is-automatic column=column)
|
||||
translated=column.user_field_id
|
||||
onActiveRender=setActiveHeader
|
||||
}}
|
||||
{{/each}}
|
||||
<div class="directory-table-top-scroll">
|
||||
<div class="directory-table-top-scroll-fake-content"></div>
|
||||
</div>
|
||||
|
||||
{{#if showTimeRead}}
|
||||
<th>{{i18n "directory.time_read"}}</th>
|
||||
{{/if}}
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each items as |item|}}
|
||||
{{directory-item item=item columns=columns showTimeRead=showTimeRead}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="directory-table-container">
|
||||
<table class="directory-table">
|
||||
<thead>
|
||||
{{table-header-toggle field="username" order=order asc=asc}}
|
||||
{{#each columns as |column|}}
|
||||
{{table-header-toggle
|
||||
field=column.name
|
||||
icon=column.icon
|
||||
order=order
|
||||
asc=asc
|
||||
automatic=(directory-column-is-automatic column=column)
|
||||
translated=column.user_field_id
|
||||
onActiveRender=setActiveHeader
|
||||
}}
|
||||
{{/each}}
|
||||
|
||||
{{#if showTimeRead}}
|
||||
<th>{{i18n "directory.time_read"}}</th>
|
||||
{{/if}}
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each items as |item|}}
|
||||
{{directory-item item=item columns=columns showTimeRead=showTimeRead}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -6,6 +6,11 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.directory-table-top-scroll {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.open-edit-columns-btn {
|
||||
vertical-align: top;
|
||||
padding: 0.45em 0.8em;
|
||||
|
Loading…
Reference in New Issue
Block a user