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;
|
||||
overflow: hidden;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RoomSublist2_headerContainer {
|
||||
.mx_RoomSublist2_headerText {
|
||||
.mx_RoomSublist2_collapseBtn {
|
||||
visibility: visible;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.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");
|
||||
|
||||
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`;
|
||||
|
|
|
@ -134,7 +134,28 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
|||
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[] {
|
||||
if (this.props.layout && this.props.layout.isCollapsed) return []; // don't waste time on rendering
|
||||
|
||||
const tiles: React.ReactElement[] = [];
|
||||
|
||||
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({
|
||||
'mx_RoomSublist2_headerContainer': true,
|
||||
'mx_RoomSublist2_headerContainer_withAux': !!addRoomButton,
|
||||
|
@ -264,7 +290,9 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
|||
className={"mx_RoomSublist2_headerText"}
|
||||
role="treeitem"
|
||||
aria-level={1}
|
||||
onClick={this.onHeaderClick}
|
||||
>
|
||||
<span className={collapseClasses} />
|
||||
<span>{this.props.label}</span>
|
||||
</AccessibleButton>
|
||||
{this.renderMenu()}
|
||||
|
|
|
@ -21,11 +21,13 @@ const TILE_HEIGHT_PX = 44;
|
|||
interface ISerializedListLayout {
|
||||
numTiles: number;
|
||||
showPreviews: boolean;
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
export class ListLayout {
|
||||
private _n = 0;
|
||||
private _previews = false;
|
||||
private _collapsed = false;
|
||||
|
||||
constructor(public readonly tagId: TagID) {
|
||||
const serialized = localStorage.getItem(this.key);
|
||||
|
@ -34,9 +36,19 @@ export class ListLayout {
|
|||
const parsed = <ISerializedListLayout>JSON.parse(serialized);
|
||||
this._n = parsed.numTiles;
|
||||
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 {
|
||||
return this._previews;
|
||||
}
|
||||
|
@ -100,6 +112,7 @@ export class ListLayout {
|
|||
return {
|
||||
numTiles: this.visibleTiles,
|
||||
showPreviews: this.showPreviews,
|
||||
collapsed: this.isCollapsed,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue