Room list: update the visuals in order to have better contrast (#32421)

* fix(sc): use correct icon size for room list icons

* feat(sc): implement new selection and hover design for room list item

* feat(sc): set room list item height

* chore(sc): add story for long room and message preview

* fix(sc): use correct letter-spacing for room list item

* feat(sc): use new padding for room list filters

* feat(sc): update room list header style

* test(sc): update unit tests

* test(sc): update visual tests

* test: update playwright screenshots

* doc: update figma link in item story

* test: fix sliding sync test

The notification pop up was at the top of the room list filters (less
top padding) and it was unable to click on the People filter.

* chore: fix `VirtuaalizedRoomListView` comment

* test: update playwright screenshot

* fix(sc): add ellipsis on room name
This commit is contained in:
Florian Duros
2026-02-17 09:58:16 +00:00
committed by GitHub
parent d6317b671f
commit 55cc7ba597
90 changed files with 9964 additions and 9530 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB

@@ -6,8 +6,13 @@
*/ */
.header { .header {
flex: 0 0 60px; min-height: 60px;
padding: 0 var(--cpd-space-3x); padding: 0 var(--cpd-space-4x) 0 var(--cpd-space-3x);
}
.container {
flex: 1;
padding-bottom: var(--cpd-space-3x);
} }
.title { .title {
@@ -130,30 +130,33 @@ export function RoomListHeaderView({ vm }: Readonly<RoomListHeaderViewProps>): J
as="header" as="header"
className={styles.header} className={styles.header}
aria-label={_t("room|context_menu|title")} aria-label={_t("room|context_menu|title")}
justify="space-between" align="end"
align="center"
data-testid="room-list-header" data-testid="room-list-header"
> >
<Flex className={styles.title} align="center" gap="var(--cpd-space-1x)"> <Flex className={styles.container} justify="space-between" align="center" gap="var(--cpd-space-3x)">
<H1 size="sm" title={title}> <Flex className={styles.title} align="center" gap="var(--cpd-space-1x)">
{title} <H1 size="sm" title={title}>
</H1> {title}
{displaySpaceMenu && <SpaceMenuView vm={vm} />} </H1>
</Flex> {displaySpaceMenu && <SpaceMenuView vm={vm} />}
<Flex align="center" gap="var(--cpd-space-2x)"> </Flex>
<OptionMenuView vm={vm} /> <Flex align="center" gap="var(--cpd-space-2x)">
<OptionMenuView vm={vm} />
{/* If we don't display the compose menu, it means that the user can only send DM */} {/* If we don't display the compose menu, it means that the user can only send DM */}
{displayComposeMenu ? ( {displayComposeMenu ? (
<ComposeMenuView vm={vm} /> <ComposeMenuView vm={vm} />
) : ( ) : (
<IconButton <IconButton
onClick={(e) => vm.createChatRoom(e.nativeEvent)} size="28px"
tooltip={_t("action|new_conversation")} style={{ padding: "4px" }}
> onClick={(e) => vm.createChatRoom(e.nativeEvent)}
<ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden /> tooltip={_t("action|new_conversation")}
</IconButton> >
)} <ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
</IconButton>
)}
</Flex>
</Flex> </Flex>
</Flex> </Flex>
); );
@@ -6,123 +6,128 @@ exports[`RoomListHeaderView > renders the default state 1`] = `
aria-label="Room options" aria-label="Room options"
class="flex header" class="flex header"
data-testid="room-list-header" data-testid="room-list-header"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: end; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
> >
<div <div
class="flex title" class="flex container"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
> >
<h1 <div
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93" class="flex title"
title="Rooms" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
> >
Rooms <h1
</h1> class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93"
<button title="Rooms"
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Open space menu"
class="_icon-button_1215g_8 button"
data-kind="primary"
data-state="closed"
id="radix-_r_0_"
role="button"
style="--cpd-icon-button-size: 24px; padding: 2px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
> >
<svg Rooms
fill="currentColor" </h1>
height="1em" <button
viewBox="0 0 24 24" aria-disabled="false"
width="1em" aria-expanded="false"
xmlns="http://www.w3.org/2000/svg" aria-haspopup="menu"
> aria-label="Open space menu"
<path class="_icon-button_1215g_8 button"
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063" data-kind="primary"
/> data-state="closed"
</svg> id="radix-_r_0_"
</div> role="button"
</button> style="--cpd-icon-button-size: 24px; padding: 2px;"
</div> tabindex="0"
<div type="button"
class="flex"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_4_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_2_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
> >
<svg <div
fill="currentColor" class="_indicator-icon_147l5_17"
height="1em" style="--cpd-icon-button-size: 100%;"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
> >
<path <svg
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14" fill="currentColor"
/> height="1em"
</svg> viewBox="0 0 24 24"
</div> width="1em"
</button> xmlns="http://www.w3.org/2000/svg"
<button >
aria-disabled="false" <path
aria-expanded="false" d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
aria-haspopup="menu" />
aria-labelledby="_r_b_" </svg>
class="_icon-button_1215g_8" </div>
data-kind="primary" </button>
data-state="closed" </div>
id="radix-_r_9_" <div
role="button" class="flex"
style="--cpd-icon-button-size: 36px; padding: 6px;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
tabindex="0"
type="button"
> >
<div <button
class="_indicator-icon_147l5_17" aria-disabled="false"
style="--cpd-icon-button-size: 100%;" aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_4_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_2_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
> >
<svg <div
aria-hidden="true" class="_indicator-icon_147l5_17"
fill="currentColor" style="--cpd-icon-button-size: 100%;"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
> >
<path <svg
clip-rule="evenodd" fill="currentColor"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z" height="1em"
fill-rule="evenodd" viewBox="0 0 24 24"
/> width="1em"
<path xmlns="http://www.w3.org/2000/svg"
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" >
/> <path
</svg> d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
</div> />
</button> </svg>
</div>
</button>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-labelledby="_r_b_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_9_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
>
<svg
aria-hidden="true"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
fill-rule="evenodd"
/>
<path
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
/>
</svg>
</div>
</button>
</div>
</div> </div>
</header> </header>
</div> </div>
@@ -134,118 +139,123 @@ exports[`RoomListHeaderView > renders without compose menu 1`] = `
aria-label="Room options" aria-label="Room options"
class="flex header" class="flex header"
data-testid="room-list-header" data-testid="room-list-header"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: end; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
> >
<div <div
class="flex title" class="flex container"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
> >
<h1 <div
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93" class="flex title"
title="Rooms" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
> >
Rooms <h1
</h1> class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93"
<button title="Rooms"
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Open space menu"
class="_icon-button_1215g_8 button"
data-kind="primary"
data-state="closed"
id="radix-_r_i_"
role="button"
style="--cpd-icon-button-size: 24px; padding: 2px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
> >
<svg Rooms
fill="currentColor" </h1>
height="1em" <button
viewBox="0 0 24 24" aria-disabled="false"
width="1em" aria-expanded="false"
xmlns="http://www.w3.org/2000/svg" aria-haspopup="menu"
> aria-label="Open space menu"
<path class="_icon-button_1215g_8 button"
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063" data-kind="primary"
/> data-state="closed"
</svg> id="radix-_r_i_"
</div> role="button"
</button> style="--cpd-icon-button-size: 24px; padding: 2px;"
</div> tabindex="0"
<div type="button"
class="flex"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_m_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_k_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
> >
<svg <div
fill="currentColor" class="_indicator-icon_147l5_17"
height="1em" style="--cpd-icon-button-size: 100%;"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
> >
<path <svg
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14" fill="currentColor"
/> height="1em"
</svg> viewBox="0 0 24 24"
</div> width="1em"
</button> xmlns="http://www.w3.org/2000/svg"
<button >
aria-labelledby="_r_r_" <path
class="_icon-button_1215g_8" d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
data-kind="primary" />
role="button" </svg>
style="--cpd-icon-button-size: 32px;" </div>
tabindex="0" </button>
</div>
<div
class="flex"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
> >
<div <button
class="_indicator-icon_147l5_17" aria-disabled="false"
style="--cpd-icon-button-size: 100%;" aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_m_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_k_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
> >
<svg <div
aria-hidden="true" class="_indicator-icon_147l5_17"
color="var(--cpd-color-icon-secondary)" style="--cpd-icon-button-size: 100%;"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
> >
<path <svg
clip-rule="evenodd" fill="currentColor"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z" height="1em"
fill-rule="evenodd" viewBox="0 0 24 24"
/> width="1em"
<path xmlns="http://www.w3.org/2000/svg"
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" >
/> <path
</svg> d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
</div> />
</button> </svg>
</div>
</button>
<button
aria-labelledby="_r_r_"
class="_icon-button_1215g_8"
data-kind="primary"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
>
<svg
aria-hidden="true"
color="var(--cpd-color-icon-secondary)"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
fill-rule="evenodd"
/>
<path
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
/>
</svg>
</div>
</button>
</div>
</div> </div>
</header> </header>
</div> </div>
@@ -257,92 +267,97 @@ exports[`RoomListHeaderView > renders without space menu 1`] = `
aria-label="Room options" aria-label="Room options"
class="flex header" class="flex header"
data-testid="room-list-header" data-testid="room-list-header"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: end; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
> >
<div <div
class="flex title" class="flex container"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
> >
<h1 <div
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93" class="flex title"
title="Rooms" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
> >
Rooms <h1
</h1> class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93"
</div> title="Rooms"
<div
class="flex"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_14_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_12_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
> >
<svg Rooms
fill="currentColor" </h1>
height="1em" </div>
viewBox="0 0 24 24" <div
width="1em" class="flex"
xmlns="http://www.w3.org/2000/svg" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
>
<path
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
/>
</svg>
</div>
</button>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-labelledby="_r_1b_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_19_"
role="button"
style="--cpd-icon-button-size: 36px; padding: 6px;"
tabindex="0"
type="button"
> >
<div <button
class="_indicator-icon_147l5_17" aria-disabled="false"
style="--cpd-icon-button-size: 100%;" aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="_r_14_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_12_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
> >
<svg <div
aria-hidden="true" class="_indicator-icon_147l5_17"
fill="currentColor" style="--cpd-icon-button-size: 100%;"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
> >
<path <svg
clip-rule="evenodd" fill="currentColor"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z" height="1em"
fill-rule="evenodd" viewBox="0 0 24 24"
/> width="1em"
<path xmlns="http://www.w3.org/2000/svg"
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" >
/> <path
</svg> d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
</div> />
</button> </svg>
</div>
</button>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-labelledby="_r_1b_"
class="_icon-button_1215g_8"
data-kind="primary"
data-state="closed"
id="radix-_r_19_"
role="button"
style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_147l5_17"
style="--cpd-icon-button-size: 100%;"
>
<svg
aria-hidden="true"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
fill-rule="evenodd"
/>
<path
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
/>
</svg>
</div>
</button>
</div>
</div> </div>
</header> </header>
</div> </div>
@@ -45,8 +45,8 @@ export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
title={_t("action|open_menu")} title={_t("action|open_menu")}
align="start" align="start"
trigger={ trigger={
// 36px button with a 24px icon // 28px button with a 20px icon
<IconButton size="36px" style={{ padding: "6px" }} tooltip={_t("action|new_conversation")}> <IconButton size="28px" style={{ padding: "4px" }} tooltip={_t("action|new_conversation")}>
<ComposeIcon aria-hidden /> <ComposeIcon aria-hidden />
</IconButton> </IconButton>
} }
@@ -12,7 +12,7 @@ exports[`<ComposeMenuView /> > should match snapshot 1`] = `
data-state="closed" data-state="closed"
id="radix-_r_0_" id="radix-_r_0_"
role="button" role="button"
style="--cpd-icon-button-size: 36px; padding: 6px;" style="--cpd-icon-button-size: 28px; padding: 4px;"
tabindex="0" tabindex="0"
type="button" type="button"
> >
@@ -54,6 +54,7 @@ export function RoomListItemMoreOptionsMenu({ vm }: RoomListItemMoreOptionsMenuP
tooltip={_t("room_list|room|more_options")} tooltip={_t("room_list|room|more_options")}
aria-label={_t("room_list|room|more_options")} aria-label={_t("room_list|room|more_options")}
size="24px" size="24px"
style={{ padding: "2px" }}
> >
<OverflowHorizontalIcon /> <OverflowHorizontalIcon />
</IconButton> </IconButton>
@@ -51,6 +51,7 @@ export function RoomListItemNotificationMenu({ vm }: RoomListItemNotificationMen
trigger={ trigger={
<IconButton <IconButton
size="24px" size="24px"
style={{ padding: "2px" }}
tooltip={_t("room_list|notification_options")} tooltip={_t("room_list|notification_options")}
aria-label={_t("room_list|notification_options")} aria-label={_t("room_list|notification_options")}
> >
@@ -5,15 +5,6 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
/**
* The RoomListItem has the following structure:
* button--------------------------------------------------|
* | <-12px-> container------------------------------------|
* | | room avatar <-8px-> content----------------|
* | | | room_name <- 20px ->|
* | | | --------------------| <-- border
* |-------------------------------------------------------|
*/
.roomListItem { .roomListItem {
/* Remove button default style */ /* Remove button default style */
background: unset; background: unset;
@@ -21,13 +12,17 @@
padding: 0; padding: 0;
text-align: unset; text-align: unset;
/* Needed to position the selected marker */
position: relative;
cursor: pointer; cursor: pointer;
height: 48px; height: 44px;
width: 100%; width: 100%;
/* Gap between items, accounted for in ROOM_LIST_ITEM_HEIGHT */
margin-bottom: var(--cpd-space-2x);
padding-left: var(--cpd-space-3x);
font: var(--cpd-font-body-md-regular); font: var(--cpd-font-body-md-regular);
color: var(--cpd-color-text-primary); letter-spacing: var(--cpd-font-letter-spacing-body-md);
color: var(--cpd-color-text-secondary);
/* Hide the menu by default */ /* Hide the menu by default */
.hoverMenu { .hoverMenu {
@@ -42,7 +37,16 @@
.roomListItem[data-state="open"], .roomListItem[data-state="open"],
/* When the options and notifications menu are opened */ /* When the options and notifications menu are opened */
.roomListItem:has(.hoverMenu > button[data-state="open"]) { .roomListItem:has(.hoverMenu > button[data-state="open"]) {
background-color: var(--cpd-color-bg-action-secondary-hovered); color: var(--cpd-color-text-primary);
.container {
background-color: var(--cpd-color-bg-action-tertiary-hovered);
}
/* Preserve selected background on hover/focus/menu-open states */
&.selected .container {
background-color: var(--cpd-color-bg-action-tertiary-selected);
}
.hoverMenu { .hoverMenu {
display: flex; display: flex;
@@ -52,52 +56,57 @@
.notificationDecoration { .notificationDecoration {
display: none; display: none;
} }
}
/** .container {
* The figma uses 16px padding (--cpd-space-4x) but due to https://github.com/element-hq/compound-web/issues/331 flex: 1;
* the icon size of the menu is 18px instead of 20px with a different internal padding height: 100%;
* We need to use 18px to align the icon with the others icons margin: 0 var(--cpd-space-3x);
* 18px is not available in compound spacing padding: 0 var(--cpd-space-2x);
*/ border-radius: 8px;
.content { min-width: 0;
padding-right: 18px;
}
} }
.content { .content {
height: 100%;
flex: 1; flex: 1;
/* The border is only under the room name and the future hover menu */
border-bottom: var(--cpd-border-width-0-5) solid var(--cpd-color-bg-subtle-secondary);
box-sizing: border-box;
min-width: 0; min-width: 0;
padding-right: var(--cpd-space-5x);
} }
.text { .text {
min-width: 0; min-width: 0;
} }
.ellipsis,
.roomName { .roomName {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.messagePreview {
font: var(--cpd-font-body-sm-regular);
color: var(--cpd-color-text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.selected { .selected {
background-color: var(--cpd-color-bg-action-secondary-pressed); .container {
background-color: var(--cpd-color-bg-action-tertiary-selected);
font: var(--cpd-font-body-md-semibold);
color: var(--cpd-color-text-primary);
}
/* Visual marker at the left on the container when the room is selected */
.container::before {
content: "";
position: absolute;
/* Marker height is 34px, room list item height is 44px. So position is at 5px and top and bottom */
top: 5px;
bottom: 5px;
left: 0;
width: 4px;
background-color: var(--cpd-color-bg-accent-rest);
border-radius: 0 8px 8px 0;
}
} }
.bold .roomName { .bold .roomName {
font: var(--cpd-font-body-md-semibold); font: var(--cpd-font-body-md-semibold);
color: var(--cpd-color-text-primary);
} }
/* Set icon color for hover menu buttons */ /* Set icon color for hover menu buttons */
@@ -102,7 +102,7 @@ const meta = {
parameters: { parameters: {
design: { design: {
type: "figma", type: "figma",
url: "https://www.figma.com/design/vlmt46QDdE4dgXDiyBJXqp/ER-33-Left-Panel?node-id=101-13062", url: "https://www.figma.com/design/rTaQE2nIUSLav4Tg3nozq7/Compound-Web-Components?node-id=10800-21153&t=gFDc2D7TMEffSSCo-0",
}, },
}, },
} satisfies Meta<typeof RoomListItemWrapper>; } satisfies Meta<typeof RoomListItemWrapper>;
@@ -112,6 +112,13 @@ type Story = StoryObj<typeof meta>;
export const Default: Story = {}; export const Default: Story = {};
export const LongContent: Story = {
args: {
name: "Loooooooooooooooooooooooooooooooooooooong name",
messagePreview: "Loooooooooooooooooooooooooooooooooooooong preview",
},
};
export const Selected: Story = { export const Selected: Story = {
args: { args: {
isSelected: true, isSelected: true,
@@ -7,6 +7,7 @@
import React, { type JSX, memo, useEffect, useRef, type ReactNode } from "react"; import React, { type JSX, memo, useEffect, useRef, type ReactNode } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { Text } from "@vector-im/compound-web";
import { Flex } from "../../utils/Flex"; import { Flex } from "../../utils/Flex";
import { NotificationDecoration, type NotificationDecorationData } from "./NotificationDecoration"; import { NotificationDecoration, type NotificationDecorationData } from "./NotificationDecoration";
@@ -174,31 +175,33 @@ export const RoomListItemView = memo(function RoomListItemView({
tabIndex={isFocused ? 0 : -1} tabIndex={isFocused ? 0 : -1}
{...props} {...props}
> >
{renderAvatar(item.room)} <Flex className={styles.container} gap="var(--cpd-space-3x)" align="center">
<Flex className={styles.content} gap="var(--cpd-space-2x)" align="center" justify="space-between"> {renderAvatar(item.room)}
{/* We truncate the room name when too long. Title here is to show the full name on hover */} <Flex className={styles.content} gap="var(--cpd-space-2x)" align="center" justify="space-between">
<div className={styles.text}> {/* We truncate the room name when too long. Title here is to show the full name on hover */}
<div className={styles.roomName} title={item.name} data-testid="room-name"> <div className={styles.ellipsis}>
{item.name} <div className={styles.roomName} title={item.name} data-testid="room-name">
</div> {item.name}
{item.messagePreview && (
<div className={styles.messagePreview} title={item.messagePreview}>
{item.messagePreview}
</div> </div>
{item.messagePreview && (
<Text as="div" size="sm" className={styles.ellipsis} title={item.messagePreview}>
{item.messagePreview}
</Text>
)}
</div>
{(item.showMoreOptionsMenu || item.showNotificationMenu) && (
<RoomListItemHoverMenu
showMoreOptionsMenu={item.showMoreOptionsMenu}
showNotificationMenu={item.showNotificationMenu}
vm={vm}
/>
)} )}
</div>
{(item.showMoreOptionsMenu || item.showNotificationMenu) && (
<RoomListItemHoverMenu
showMoreOptionsMenu={item.showMoreOptionsMenu}
showNotificationMenu={item.showNotificationMenu}
vm={vm}
/>
)}
{/* aria-hidden because we summarise the unread count/notification status in a11yLabel */} {/* aria-hidden because we summarise the unread count/notification status in a11yLabel */}
<div className={styles.notificationDecoration} aria-hidden={true}> <div className={styles.notificationDecoration} aria-hidden={true}>
<NotificationDecoration {...item.notification} /> <NotificationDecoration {...item.notification} />
</div> </div>
</Flex>
</Flex> </Flex>
</Flex> </Flex>
); );
@@ -6,7 +6,7 @@
*/ */
.roomListPrimaryFilters { .roomListPrimaryFilters {
padding: var(--cpd-space-2x) var(--cpd-space-4x) var(--cpd-space-2x) var(--cpd-space-3x); padding: 0 var(--cpd-space-4x) var(--cpd-space-5x) var(--cpd-space-3x);
} }
/* Hide filters that are wrapping when collapsed */ /* Hide filters that are wrapping when collapsed */
@@ -34,7 +34,7 @@ const {
const renderWithMockContext = (component: React.ReactElement): ReturnType<typeof render> => { const renderWithMockContext = (component: React.ReactElement): ReturnType<typeof render> => {
return render(component, { return render(component, {
wrapper: ({ children }) => ( wrapper: ({ children }) => (
<VirtuosoMockContext.Provider value={{ viewportHeight: 600, itemHeight: 48 }}> <VirtuosoMockContext.Provider value={{ viewportHeight: 600, itemHeight: 52 }}>
{children} {children}
</VirtuosoMockContext.Provider> </VirtuosoMockContext.Provider>
), ),
@@ -18,7 +18,7 @@ const { Default } = composeStories(stories);
const renderWithMockContext = (component: React.ReactElement): ReturnType<typeof render> => { const renderWithMockContext = (component: React.ReactElement): ReturnType<typeof render> => {
return render(component, { return render(component, {
wrapper: ({ children }) => ( wrapper: ({ children }) => (
<VirtuosoMockContext.Provider value={{ viewportHeight: 600, itemHeight: 48 }}> <VirtuosoMockContext.Provider value={{ viewportHeight: 600, itemHeight: 52 }}>
{children} {children}
</VirtuosoMockContext.Provider> </VirtuosoMockContext.Provider>
), ),
@@ -53,8 +53,8 @@ export interface VirtualizedRoomListViewProps {
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void; onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
} }
/** Height of a single room list item in pixels */ /** Height of a single room list item in pixels (44px item + 8px margin bottom) */
const ROOM_LIST_ITEM_HEIGHT = 48; const ROOM_LIST_ITEM_HEIGHT = 52;
/** /**
* Type for context used in ListView * Type for context used in ListView
@@ -71,7 +71,9 @@ test.describe("Sliding Sync", () => {
}); });
// Load the user fixture for all tests // Load the user fixture for all tests
test.beforeEach(({ user }) => {}); test.beforeEach(async ({ app, user }) => {
await app.closeNotificationToast();
});
test("should render the Rooms list in reverse chronological order by default and allowing sorting A-Z", async ({ test("should render the Rooms list in reverse chronological order by default and allowing sorting A-Z", async ({
page, page,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB