Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Room Tile context menu, notifications, indicator and placement #4858

Merged
merged 13 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 43 additions & 72 deletions res/css/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -588,27 +588,16 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {

// A context menu that largely fits the | [icon] [label] | format.
.mx_IconizedContextMenu {
// Put 20px of padding around the whole menu. We do this instead of a
// simple `padding: 20px` rule so the horizontal rules added by the
// optionLists is rendered correctly (full width).
> * {
padding-left: 20px;
padding-right: 20px;

&:first-child {
padding-top: 20px;
}
min-width: 146px;

&:last-child {
padding-bottom: 16px;
.mx_IconizedContextMenu_optionList {
& > * {
padding-left: 20px;
padding-right: 20px;
}
}

.mx_IconizedContextMenu_optionList {
// the notFirst class is for cases where the optionList might be under a header of sorts.
&:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst {
margin-top: 12px;

// This is a bit of a hack when we could just use a simple border-top property,
// however we have a (kinda) good reason for doing it this way: we need opacity.
// To get the right color, we need an opacity modifier which means we have to work
Expand All @@ -631,72 +620,54 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
}
}

ul {
list-style: none;
margin: 0;
padding: 0;

li {
margin: 0;
padding: 12px 0 0;

.mx_AccessibleButton {
text-decoration: none;
color: $primary-fg-color;
font-size: $font-15px;
line-height: $font-24px;

// Create a flexbox to more easily define the list items
display: flex;
align-items: center;

img, .mx_IconizedContextMenu_icon { // icons
width: 16px;
min-width: 16px;
max-width: 16px;
}

span:last-child { // labels
padding-left: 14px;
width: 100%;
flex: 1;

// Ellipsize any text overflow
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
// round the top corners of the top button for the hover effect to be bounded
&:first-child .mx_AccessibleButton:first-child {
border-radius: 4px 4px 0 0; // radius matches .mx_ContextualMenu
}
}

&.mx_IconizedContextMenu_compact {
> * {
padding-left: 11px;
padding-right: 16px;
// round the bottom corners of the bottom button for the hover effect to be bounded
&:last-child .mx_AccessibleButton:last-child {
border-radius: 0 0 4px 4px; // radius matches .mx_ContextualMenu
}

&:first-child {
padding-top: 13px;
.mx_AccessibleButton {
padding-top: 12px;
padding-bottom: 12px;
text-decoration: none;
color: $primary-fg-color;
font-size: $font-15px;
line-height: $font-24px;

// Create a flexbox to more easily define the list items
display: flex;
align-items: center;

&:hover {
background-color: $menu-selected-color;
}

&:last-child {
padding-bottom: 13px;
img, .mx_IconizedContextMenu_icon { // icons
width: 16px;
min-width: 16px;
max-width: 16px;
}
}

.mx_IconizedContextMenu_optionList {
&:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst {
margin-top: 10px;
span.mx_IconizedContextMenu_label { // labels
padding-left: 14px;
width: 100%;
flex: 1;

li:first-child {
padding-top: 10px;
}
// Ellipsize any text overflow
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}

li:first-child {
padding-top: 0;
}
&.mx_IconizedContextMenu_compact {
.mx_IconizedContextMenu_optionList > * {
padding: 8px 16px 8px 11px;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions res/css/structures/_UserMenu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ limitations under the License.

.mx_UserMenu_contextMenu_redRow {
.mx_AccessibleButton {
padding-top: 16px;
padding-bottom: 16px;
color: $warning-color !important; // !important to override styles from context menu
}

Expand All @@ -95,6 +97,8 @@ limitations under the License.
}

.mx_UserMenu_contextMenu_header {
padding: 20px;

// Create a flexbox to organize the header a bit easier
display: flex;
align-items: center;
Expand Down
50 changes: 36 additions & 14 deletions res/css/views/rooms/_RoomTile2.scss
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,17 @@ limitations under the License.
justify-content: center;
}

// The menu button is hidden by default
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
// TODO: [Notifications] Use mx_RoomTile2_notificationsButton, similar to the following approach:
// https://github.com/matrix-org/matrix-react-sdk/blob/2180a56074f3698fc0241c309a72ba6cad802d1c/res/css/views/rooms/_RoomSublist2.scss#L48-L76
// You'll need to do the same down below on the &:hover selector for the tile.
// See https://github.com/vector-im/riot-web/issues/13961.
// ... also remove this 5 line TODO comment.
.mx_RoomTile2_menuButton,
.mx_RoomTile2_notificationsButton {
width: 0;
height: 0;
visibility: hidden;
width: 20px;
height: 20px;
margin: auto 0 auto 8px;
position: relative;
display: none;

&::before {
top: 2px;
left: 2px;
content: '';
width: 16px;
height: 16px;
Expand All @@ -117,9 +114,11 @@ limitations under the License.
}
}

.mx_RoomTile2_notificationsButton.mx_RoomTile2_notificationsButton_show {
display: block;
}

.mx_RoomTile2_menuButton::before {
top: 8px;
left: -1px; // this is off-center to align it with the badges
mask-image: url('$(res)/img/feather-customised/more-horizontal.svg');
}

Expand All @@ -132,10 +131,9 @@ limitations under the License.
visibility: hidden;
}

.mx_RoomTile2_notificationsButton,
.mx_RoomTile2_menuButton {
width: 18px;
height: 32px;
visibility: visible;
display: block;
}
}
}
Expand All @@ -158,6 +156,20 @@ limitations under the License.
}
}

// We use these both in context menus and the room tiles
.mx_RoomTile2_iconBell::before {
mask-image: url('$(res)/img/feather-customised/bell.svg');
}
.mx_RoomTile2_iconBellDot::before {
mask-image: url('$(res)/img/feather-customised/bell-notification.custom.svg');
}
.mx_RoomTile2_iconBellCrossed::before {
mask-image: url('$(res)/img/feather-customised/bell-crossed.svg');
}
.mx_RoomTile2_iconCheck::before {
mask-image: url('$(res)/img/feather-customised/check.svg');
}

.mx_RoomTile2_contextMenu {
.mx_RoomTile2_contextMenu_redRow {
.mx_AccessibleButton {
Expand All @@ -169,6 +181,16 @@ limitations under the License.
}
}

.mx_RoomTile2_contextMenu_activeRow {
&.mx_AccessibleButton, .mx_AccessibleButton {
color: $accent-color !important; // !important to override styles from context menu
}

.mx_IconizedContextMenu_icon::before {
background-color: $accent-color;
}
}

.mx_IconizedContextMenu_icon {
position: relative;
width: 16px;
Expand Down
4 changes: 4 additions & 0 deletions res/img/feather-customised/bell-crossed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions res/img/feather-customised/bell-notification.custom.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions res/img/feather-customised/bell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 31 additions & 49 deletions src/components/structures/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,20 +191,18 @@ export default class UserMenu extends React.Component<IProps, IState> {
let homeButton = null;
if (this.hasHomePage) {
homeButton = (
<li>
<AccessibleButton onClick={this.onHomeClick}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconHome" />
<span>{_t("Home")}</span>
</AccessibleButton>
</li>
<AccessibleButton onClick={this.onHomeClick}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconHome" />
<span>{_t("Home")}</span>
</AccessibleButton>
);
}

const elementRect = this.buttonRef.current.getBoundingClientRect();
return (
<ContextMenu
chevronFace="none"
left={elementRect.width + elementRect.left}
left={elementRect.width + elementRect.left - 20}
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
top={elementRect.top + elementRect.height}
onFinished={this.onCloseMenu}
>
Expand Down Expand Up @@ -232,49 +230,33 @@ export default class UserMenu extends React.Component<IProps, IState> {
</div>
{hostingLink}
<div className="mx_IconizedContextMenu_optionList mx_IconizedContextMenu_optionList_notFirst">
<ul>
{homeButton}
<li>
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconBell" />
<span>{_t("Notification settings")}</span>
</AccessibleButton>
</li>
<li>
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, USER_SECURITY_TAB)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconLock" />
<span>{_t("Security & privacy")}</span>
</AccessibleButton>
</li>
<li>
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, null)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconSettings" />
<span>{_t("All settings")}</span>
</AccessibleButton>
</li>
<li>
<AccessibleButton onClick={this.onShowArchived}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconArchive" />
<span>{_t("Archived rooms")}</span>
</AccessibleButton>
</li>
<li>
<AccessibleButton onClick={this.onProvideFeedback}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconMessage" />
<span>{_t("Feedback")}</span>
</AccessibleButton>
</li>
</ul>
{homeButton}
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconBell" />
<span className="mx_IconizedContextMenu_label">{_t("Notification settings")}</span>
</AccessibleButton>
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, USER_SECURITY_TAB)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconLock" />
<span className="mx_IconizedContextMenu_label">{_t("Security & privacy")}</span>
</AccessibleButton>
<AccessibleButton onClick={(e) => this.onSettingsOpen(e, null)}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconSettings" />
<span className="mx_IconizedContextMenu_label">{_t("All settings")}</span>
</AccessibleButton>
<AccessibleButton onClick={this.onShowArchived}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconArchive" />
<span className="mx_IconizedContextMenu_label">{_t("Archived rooms")}</span>
</AccessibleButton>
<AccessibleButton onClick={this.onProvideFeedback}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconMessage" />
<span className="mx_IconizedContextMenu_label">{_t("Feedback")}</span>
</AccessibleButton>
</div>
<div className="mx_IconizedContextMenu_optionList">
<ul>
<li className="mx_UserMenu_contextMenu_redRow">
<AccessibleButton onClick={this.onSignOutClick}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconSignOut" />
<span>{_t("Sign out")}</span>
</AccessibleButton>
</li>
</ul>
<div className="mx_IconizedContextMenu_optionList mx_UserMenu_contextMenu_redRow">
<AccessibleButton onClick={this.onSignOutClick}>
<span className="mx_IconizedContextMenu_icon mx_UserMenu_iconSignOut" />
<span className="mx_IconizedContextMenu_label">{_t("Sign out")}</span>
</AccessibleButton>
</div>
</div>
</ContextMenu>
Expand Down
Loading