Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 78e1db9

Browse files
authored
Merge pull request #4741 from matrix-org/travis/room-list/resize-handle
Update resize handle for new designs in new room list
2 parents a4ea5b5 + 8ec6d4c commit 78e1db9

File tree

4 files changed

+132
-37
lines changed

4 files changed

+132
-37
lines changed

res/css/views/rooms/_RoomSublist2.scss

+66-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ limitations under the License.
1616

1717
// TODO: Rename to mx_RoomSublist during replacement of old component
1818

19-
// TODO: Just use the 3 selectors we need from this instead of importing it.
20-
// We're going to end up with heavy modifications anyways.
21-
@import "../../../../node_modules/react-resizable/css/styles.css";
22-
2319
.mx_RoomSublist2 {
2420
// The sublist is a column of rows, essentially
2521
display: flex;
@@ -63,18 +59,83 @@ limitations under the License.
6359
}
6460

6561
.mx_RoomSublist2_resizeBox {
62+
margin-bottom: 4px; // for the resize handle
63+
position: relative;
64+
6665
// Create another flexbox column for the tiles
6766
display: flex;
6867
flex-direction: column;
6968
overflow: hidden;
7069

7170
.mx_RoomSublist2_showMoreButton {
72-
height: 44px; // 1 room tile high
7371
cursor: pointer;
72+
font-size: $font-13px;
73+
line-height: $font-18px;
74+
color: $roomtile2-preview-color;
75+
76+
// This is the same color as the left panel background because it needs
77+
// to occlude the lastmost tile in the list.
78+
background-color: $header-panel-bg-color;
79+
80+
// Update the render() function for RoomSublist2 if these change
81+
// Update the ListLayout class for minVisibleTiles if these change.
82+
//
83+
// At 24px high and 8px padding on the top this equates to 0.65 of
84+
// a tile due to how the padding calculations work.
85+
height: 24px;
86+
padding-top: 8px;
87+
88+
// We force this to the bottom so it will overlap rooms as needed.
89+
// We account for the space it takes up (24px) in the code through padding.
90+
position: absolute;
91+
bottom: 4px; // the height of the resize handle
92+
left: 0;
93+
right: 0;
7494

7595
// We create a flexbox to cheat at alignment
7696
display: flex;
7797
align-items: center;
98+
99+
.mx_RoomSublist2_showMoreButtonChevron {
100+
position: relative;
101+
width: 16px;
102+
height: 16px;
103+
margin-left: 12px;
104+
margin-right: 18px;
105+
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
106+
mask-position: center;
107+
mask-size: contain;
108+
mask-repeat: no-repeat;
109+
background: $roomtile2-preview-color;
110+
}
111+
}
112+
113+
// Class name comes from the ResizableBox component
114+
// The hover state needs to use the whole sublist, not just the resizable box,
115+
// so that selector is below and one level higher.
116+
.react-resizable-handle {
117+
cursor: ns-resize;
118+
border-radius: 2px;
119+
120+
// This is positioned directly below the 'show more' button.
121+
position: absolute;
122+
bottom: 0;
123+
left: 0;
124+
right: 0;
125+
126+
// This is to visually align the bar in the list. Should be 12px from
127+
// either side of the list. We define this after the positioning to
128+
// trick the browser.
129+
margin-left: 4px;
130+
margin-right: 8px;
78131
}
79132
}
133+
134+
// The aforementioned selector for the hover state.
135+
&:hover .react-resizable-handle {
136+
opacity: 0.2;
137+
138+
// Update the render() function for RoomSublist2 if this changes
139+
border: 2px solid $primary-fg-color;
140+
}
80141
}

src/components/views/rooms/RoomSublist2.tsx

+46-30
Original file line numberDiff line numberDiff line change
@@ -178,46 +178,61 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
178178

179179
let content = null;
180180
if (tiles.length > 0) {
181+
const layout = this.props.layout; // to shorten calls
182+
181183
// TODO: Lazy list rendering
182184
// TODO: Whatever scrolling magic needs to happen here
183-
const layout = this.props.layout; // to shorten calls
184-
const minTilesPx = layout.tilesToPixels(Math.min(tiles.length, layout.minVisibleTiles));
185-
const maxTilesPx = layout.tilesToPixels(tiles.length);
186-
const tilesPx = layout.tilesToPixels(Math.min(tiles.length, layout.visibleTiles));
187-
let handles = ['s'];
188-
if (layout.visibleTiles >= tiles.length && tiles.length <= layout.minVisibleTiles) {
189-
handles = []; // no handles, we're at a minimum
190-
}
191185

192-
// TODO: This might need adjustment, however for now it is fine as a round.
193-
const nVisible = Math.round(layout.visibleTiles);
186+
const nVisible = Math.floor(layout.visibleTiles);
194187
const visibleTiles = tiles.slice(0, nVisible);
195188

196189
// If we're hiding rooms, show a 'show more' button to the user. This button
197-
// replaces the last visible tile, so will always show 2+ rooms. We do this
198-
// because if it said "show 1 more room" we had might as well show that room
199-
// instead. We also replace the last item so we don't have to adjust our math
200-
// on pixel heights, etc. It's much easier to pretend the button is a tile.
190+
// floats above the resize handle, if we have one present
191+
let showMoreButton = null;
201192
if (tiles.length > nVisible) {
202193
// we have a cutoff condition - add the button to show all
203-
204-
// we +1 to account for the room we're about to hide with our 'show more' button
205-
// this results in the button always being 1+, and not needing an i18n `count`.
206-
const numMissing = (tiles.length - visibleTiles.length) + 1;
207-
208-
// TODO: CSS TBD
209-
// TODO: Make this an actual tile
210-
// TODO: This is likely to pop out of the list, consider that.
211-
visibleTiles.splice(visibleTiles.length - 1, 1, (
212-
<div
213-
onClick={this.onShowAllClick}
214-
className='mx_RoomSublist2_showMoreButton'
215-
key='showall'
216-
>
217-
{_t("Show %(n)s more", {n: numMissing})}
194+
const numMissing = tiles.length - visibleTiles.length;
195+
showMoreButton = (
196+
<div onClick={this.onShowAllClick} className='mx_RoomSublist2_showMoreButton'>
197+
<span className='mx_RoomSublist2_showMoreButtonChevron'>
198+
{/* set by CSS masking */}
199+
</span>
200+
<span className='mx_RoomSublist2_showMoreButtonText'>
201+
{_t("Show %(count)s more", {count: numMissing})}
202+
</span>
218203
</div>
219-
));
204+
);
205+
}
206+
207+
// Figure out if we need a handle
208+
let handles = ['s'];
209+
if (layout.visibleTiles >= tiles.length && tiles.length <= layout.minVisibleTiles) {
210+
handles = []; // no handles, we're at a minimum
220211
}
212+
213+
// We have to account for padding so we can accommodate a 'show more' button and
214+
// the resize handle, which are pinned to the bottom of the container. This is the
215+
// easiest way to have a resize handle below the button as otherwise we're writing
216+
// our own resize handling and that doesn't sound fun.
217+
//
218+
// The layout class has some helpers for dealing with padding, as we don't want to
219+
// apply it in all cases. If we apply it in all cases, the resizing feels like it
220+
// goes backwards and can become wildly incorrect (visibleTiles says 18 when there's
221+
// only mathematically 7 possible).
222+
223+
const showMoreHeight = 32; // As defined by CSS
224+
const resizeHandleHeight = 4; // As defined by CSS
225+
226+
// The padding is variable though, so figure out what we need padding for.
227+
let padding = 0;
228+
if (showMoreButton) padding += showMoreHeight;
229+
if (handles.length > 0) padding += resizeHandleHeight;
230+
231+
const minTilesPx = layout.calculateTilesToPixelsMin(tiles.length, layout.minVisibleTiles, padding);
232+
const maxTilesPx = layout.tilesToPixelsWithPadding(tiles.length, padding);
233+
const tilesWithoutPadding = Math.min(tiles.length, layout.visibleTiles);
234+
const tilesPx = layout.calculateTilesToPixelsMin(tiles.length, tilesWithoutPadding, padding);
235+
221236
content = (
222237
<ResizableBox
223238
width={-1}
@@ -230,6 +245,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
230245
className="mx_RoomSublist2_resizeBox"
231246
>
232247
{visibleTiles}
248+
{showMoreButton}
233249
</ResizableBox>
234250
)
235251
}

src/i18n/strings/en_EN.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,8 @@
11351135
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
11361136
"Not now": "Not now",
11371137
"Don't ask me again": "Don't ask me again",
1138-
"Show %(n)s more": "Show %(n)s more",
1138+
"Show %(count)s more|other": "Show %(count)s more",
1139+
"Show %(count)s more|one": "Show %(count)s more",
11391140
"Options": "Options",
11401141
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
11411142
"%(count)s unread messages including mentions.|one": "1 unread mention.",

src/stores/room-list/ListLayout.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,24 @@ export class ListLayout {
5252
}
5353

5454
public get minVisibleTiles(): number {
55-
return 3;
55+
// the .65 comes from the CSS where the show more button is
56+
// mathematically 65% of a tile when floating.
57+
return 4.65;
58+
}
59+
60+
public calculateTilesToPixelsMin(maxTiles: number, n: number, possiblePadding: number): number {
61+
// Only apply the padding if we're about to use maxTiles as we need to
62+
// plan for the padding. If we're using n, the padding is already accounted
63+
// for by the resizing stuff.
64+
let padding = 0;
65+
if (maxTiles < n) {
66+
padding = possiblePadding;
67+
}
68+
return this.tilesToPixels(Math.min(maxTiles, n)) + padding;
69+
}
70+
71+
public tilesToPixelsWithPadding(n: number, padding: number): number {
72+
return this.tilesToPixels(n) + padding;
5673
}
5774

5875
public tilesToPixels(n: number): number {

0 commit comments

Comments
 (0)