Support list collapsing and jumping
Fixes https://github.com/vector-im/riot-web/issues/14036
This commit is contained in:
parent
8596905cee
commit
4186070489
5 changed files with 81 additions and 2 deletions
|
@ -138,6 +138,34 @@ limitations under the License.
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.mx_RoomSublist2_collapseBtn {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
// Default hidden
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
left: 1px;
|
||||||
|
mask-position: center;
|
||||||
|
mask-size: contain;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
background: $primary-fg-color;
|
||||||
|
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_RoomSublist2_collapseBtn_collapsed::before {
|
||||||
|
mask-image: url('$(res)/img/feather-customised/chevron-right.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +279,17 @@ limitations under the License.
|
||||||
background-color: $roomlist2-button-bg-color;
|
background-color: $roomlist2-button-bg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_RoomSublist2_headerContainer {
|
||||||
|
.mx_RoomSublist2_headerText {
|
||||||
|
.mx_RoomSublist2_collapseBtn {
|
||||||
|
visibility: visible;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mx_RoomSublist2_minimized {
|
&.mx_RoomSublist2_minimized {
|
||||||
|
|
1
res/img/feather-customised/chevron-right.svg
Normal file
1
res/img/feather-customised/chevron-right.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
After Width: | Height: | Size: 270 B |
|
@ -105,13 +105,11 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
const header = sublist.querySelector<HTMLDivElement>(".mx_RoomSublist2_stickable");
|
const header = sublist.querySelector<HTMLDivElement>(".mx_RoomSublist2_stickable");
|
||||||
|
|
||||||
if (slRect.top + headerHeight > bottom && !gotBottom) {
|
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_sticky");
|
||||||
header.classList.add("mx_RoomSublist2_headerContainer_stickyBottom");
|
header.classList.add("mx_RoomSublist2_headerContainer_stickyBottom");
|
||||||
header.style.width = `${headerStickyWidth}px`;
|
header.style.width = `${headerStickyWidth}px`;
|
||||||
gotBottom = true;
|
gotBottom = true;
|
||||||
} else if (slRect.top < top) {
|
} 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_sticky");
|
||||||
header.classList.add("mx_RoomSublist2_headerContainer_stickyTop");
|
header.classList.add("mx_RoomSublist2_headerContainer_stickyTop");
|
||||||
header.style.width = `${headerStickyWidth}px`;
|
header.style.width = `${headerStickyWidth}px`;
|
||||||
|
|
|
@ -134,7 +134,28 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
this.forceUpdate(); // because the layout doesn't trigger a re-render
|
this.forceUpdate(); // because the layout doesn't trigger a re-render
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onHeaderClick = (ev: React.MouseEvent<HTMLDivElement>) => {
|
||||||
|
let target = ev.target as HTMLDivElement;
|
||||||
|
if (!target.classList.contains('mx_RoomSublist2_headerText')) {
|
||||||
|
// If we don't have the headerText class, the user clicked the span in the headerText.
|
||||||
|
target = target.parentElement as HTMLDivElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const possibleSticky = target.parentElement;
|
||||||
|
const sublist = possibleSticky.parentElement.parentElement;
|
||||||
|
if (possibleSticky.classList.contains('mx_RoomSublist2_headerContainer_sticky')) {
|
||||||
|
// is sticky - jump to list
|
||||||
|
sublist.scrollIntoView({behavior: 'smooth'});
|
||||||
|
} else {
|
||||||
|
// on screen - toggle collapse
|
||||||
|
this.props.layout.isCollapsed = !this.props.layout.isCollapsed;
|
||||||
|
this.forceUpdate(); // because the layout doesn't trigger an update
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private renderTiles(): React.ReactElement[] {
|
private renderTiles(): React.ReactElement[] {
|
||||||
|
if (this.props.layout && this.props.layout.isCollapsed) return []; // don't waste time on rendering
|
||||||
|
|
||||||
const tiles: React.ReactElement[] = [];
|
const tiles: React.ReactElement[] = [];
|
||||||
|
|
||||||
if (this.props.rooms) {
|
if (this.props.rooms) {
|
||||||
|
@ -249,6 +270,11 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const collapseClasses = classNames({
|
||||||
|
'mx_RoomSublist2_collapseBtn': true,
|
||||||
|
'mx_RoomSublist2_collapseBtn_collapsed': this.props.layout && this.props.layout.isCollapsed,
|
||||||
|
});
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'mx_RoomSublist2_headerContainer': true,
|
'mx_RoomSublist2_headerContainer': true,
|
||||||
'mx_RoomSublist2_headerContainer_withAux': !!addRoomButton,
|
'mx_RoomSublist2_headerContainer_withAux': !!addRoomButton,
|
||||||
|
@ -264,7 +290,9 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
className={"mx_RoomSublist2_headerText"}
|
className={"mx_RoomSublist2_headerText"}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
aria-level={1}
|
aria-level={1}
|
||||||
|
onClick={this.onHeaderClick}
|
||||||
>
|
>
|
||||||
|
<span className={collapseClasses} />
|
||||||
<span>{this.props.label}</span>
|
<span>{this.props.label}</span>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
{this.renderMenu()}
|
{this.renderMenu()}
|
||||||
|
|
|
@ -21,11 +21,13 @@ const TILE_HEIGHT_PX = 44;
|
||||||
interface ISerializedListLayout {
|
interface ISerializedListLayout {
|
||||||
numTiles: number;
|
numTiles: number;
|
||||||
showPreviews: boolean;
|
showPreviews: boolean;
|
||||||
|
collapsed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ListLayout {
|
export class ListLayout {
|
||||||
private _n = 0;
|
private _n = 0;
|
||||||
private _previews = false;
|
private _previews = false;
|
||||||
|
private _collapsed = false;
|
||||||
|
|
||||||
constructor(public readonly tagId: TagID) {
|
constructor(public readonly tagId: TagID) {
|
||||||
const serialized = localStorage.getItem(this.key);
|
const serialized = localStorage.getItem(this.key);
|
||||||
|
@ -34,9 +36,19 @@ export class ListLayout {
|
||||||
const parsed = <ISerializedListLayout>JSON.parse(serialized);
|
const parsed = <ISerializedListLayout>JSON.parse(serialized);
|
||||||
this._n = parsed.numTiles;
|
this._n = parsed.numTiles;
|
||||||
this._previews = parsed.showPreviews;
|
this._previews = parsed.showPreviews;
|
||||||
|
this._collapsed = parsed.collapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get isCollapsed(): boolean {
|
||||||
|
return this._collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set isCollapsed(v: boolean) {
|
||||||
|
this._collapsed = v;
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
public get showPreviews(): boolean {
|
public get showPreviews(): boolean {
|
||||||
return this._previews;
|
return this._previews;
|
||||||
}
|
}
|
||||||
|
@ -100,6 +112,7 @@ export class ListLayout {
|
||||||
return {
|
return {
|
||||||
numTiles: this.visibleTiles,
|
numTiles: this.visibleTiles,
|
||||||
showPreviews: this.showPreviews,
|
showPreviews: this.showPreviews,
|
||||||
|
collapsed: this.isCollapsed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue