diff --git a/res/css/_common.scss b/res/css/_common.scss index 47aa295540..a22d77f3d3 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -605,3 +605,15 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { border-radius: $radius; } } + +@define-mixin unreal-focus { + outline-width: 2px; + outline-style: solid; + outline-color: Highlight; + + /* WebKit gets its native focus styles. */ + @media (-webkit-min-device-pixel-ratio: 0) { + outline-color: -webkit-focus-ring-color; + outline-style: auto; + } +} diff --git a/res/css/structures/_FilePanel.scss b/res/css/structures/_FilePanel.scss index 50b01b4a14..21b30d804a 100644 --- a/res/css/structures/_FilePanel.scss +++ b/res/css/structures/_FilePanel.scss @@ -41,13 +41,19 @@ limitations under the License. .mx_FilePanel .mx_EventTile { word-break: break-word; + margin-top: 32px; } .mx_FilePanel .mx_EventTile .mx_MImageBody { margin-right: 0px; } +.mx_FilePanel .mx_EventTile .mx_MFileBody { + line-height: 2.4rem; +} + .mx_FilePanel .mx_EventTile .mx_MFileBody_download { + padding-top: 8px; display: flex; font-size: $font-14px; color: $event-timestamp-color; @@ -60,7 +66,7 @@ limitations under the License. .mx_FilePanel .mx_EventTile .mx_MImageBody_size { flex: 1 0 0; - font-size: $font-11px; + font-size: $font-14px; text-align: right; white-space: nowrap; } @@ -80,7 +86,7 @@ limitations under the License. flex: 1 1 auto; line-height: initial; padding: 0px; - font-size: $font-11px; + font-size: $font-14px; opacity: 1.0; color: $event-timestamp-color; } @@ -90,7 +96,7 @@ limitations under the License. text-align: right; visibility: visible; position: initial; - font-size: $font-11px; + font-size: $font-14px; opacity: 1.0; color: $event-timestamp-color; } diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 120f44db90..c7c0d6fac4 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -64,7 +64,7 @@ limitations under the License. left: 4px; // center with parent of 32px height: 24px; width: 24px; - background-color: $rightpanel-button-color; + background-color: $icon-button-color; mask-repeat: no-repeat; mask-size: contain; } @@ -99,7 +99,7 @@ limitations under the License. background: rgba($accent-color, 0.25); // make the icon the accent color too &::before { - background-color: $accent-color; + background-color: $accent-color !important; } } diff --git a/res/css/views/dialogs/_ShareDialog.scss b/res/css/views/dialogs/_ShareDialog.scss index d2fe98e8f9..c343b872fd 100644 --- a/res/css/views/dialogs/_ShareDialog.scss +++ b/res/css/views/dialogs/_ShareDialog.scss @@ -51,7 +51,8 @@ limitations under the License. display: inherit; } .mx_ShareDialog_matrixto_copy > div { - background-image: url($copy-button-url); + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; margin-left: 5px; width: 20px; height: 20px; diff --git a/res/css/views/elements/_StyledCheckbox.scss b/res/css/views/elements/_StyledCheckbox.scss index 60f1bf0277..e2d61c033b 100644 --- a/res/css/views/elements/_StyledCheckbox.scss +++ b/res/css/views/elements/_StyledCheckbox.scss @@ -80,5 +80,11 @@ limitations under the License. background-color: $accent-color; border-color: $accent-color; } + + &.focus-visible { + & + label .mx_Checkbox_background { + @mixin unreal-focus; + } + } } } diff --git a/res/css/views/elements/_StyledRadioButton.scss b/res/css/views/elements/_StyledRadioButton.scss index ffa1337ebb..62fb5c5512 100644 --- a/res/css/views/elements/_StyledRadioButton.scss +++ b/res/css/views/elements/_StyledRadioButton.scss @@ -63,6 +63,7 @@ limitations under the License. box-sizing: border-box; height: $font-16px; width: $font-16px; + margin-left: 2px; // For the highlight on focus border: $font-1-5px solid $radio-circle-color; border-radius: $font-16px; @@ -77,6 +78,12 @@ limitations under the License. } } + &.focus-visible { + & + div { + @mixin unreal-focus; + } + } + &:checked { & + div { border-color: $active-radio-circle-color; diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index 547b16e9ad..2faea41709 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -34,6 +34,8 @@ limitations under the License. // Make sure the _thumbnail is positioned relative to the _container position: relative; + + border-radius: 4px; } .mx_MImageBody_thumbnail_spinner { diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index e3ccd99611..d2ff551668 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -24,7 +24,7 @@ limitations under the License. line-height: $font-24px; border-radius: 4px; background: $message-action-bar-bg-color; - top: -18px; + top: -26px; right: 8px; user-select: none; // Ensure the action bar appears above over things, like the read marker. diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 2a2191b799..eb0e1dd7b0 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -536,11 +536,12 @@ $left-gutter: 64px; display: inline-block; visibility: hidden; cursor: pointer; - top: 8px; + top: 6px; right: 6px; width: 19px; height: 19px; - background-image: url($copy-button-url); + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; } .mx_EventTile_body .mx_EventTile_pre_container:focus-within .mx_EventTile_copyButton, diff --git a/res/css/views/rooms/_IRCLayout.scss b/res/css/views/rooms/_IRCLayout.scss index ed60c220e7..958d718b11 100644 --- a/res/css/views/rooms/_IRCLayout.scss +++ b/res/css/views/rooms/_IRCLayout.scss @@ -54,7 +54,7 @@ $irc-line-height: $font-18px; flex-shrink: 0; width: var(--name-width); text-overflow: ellipsis; - text-align: right; + text-align: left; display: flex; align-items: center; overflow: visible; diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index ec95403262..a403a8dc4c 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -21,6 +21,7 @@ limitations under the License. border-top: 1px solid $primary-hairline-color; position: relative; padding-left: 82px; + padding-right: 6px; } .mx_MessageComposer_replaced_wrapper { @@ -178,25 +179,44 @@ limitations under the License. color: $accent-color; } +.mx_MessageComposer_button_highlight { + background: rgba($accent-color, 0.25); + // make the icon the accent color too + &::before { + background-color: $accent-color !important; + } +} + .mx_MessageComposer_button { position: relative; - margin-right: 12px; + margin-right: 6px; cursor: pointer; - height: 20px; - width: 20px; + height: 26px; + width: 26px; + border-radius: 100%; &::before { content: ''; position: absolute; + top: 3px; + left: 3px; height: 20px; width: 20px; - background-color: $composer-button-color; + background-color: $icon-button-color; mask-repeat: no-repeat; mask-size: contain; mask-position: center; } + &:hover { + background: rgba($accent-color, 0.1); + + &::before { + background-color: $accent-color; + } + } + &.mx_MessageComposer_hangup::before { background-color: $warning-color; } @@ -288,7 +308,7 @@ limitations under the License. mask-size: contain; mask-position: center; mask-repeat: no-repeat; - background-color: $composer-button-color; + background-color: $icon-button-color; &.mx_MessageComposer_markdownDisabled { opacity: 0.2; diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index ba46100ea6..a880a7bee2 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -222,7 +222,7 @@ limitations under the License. left: 4px; // center with parent of 32px height: 24px; width: 24px; - background-color: $roomheader-button-color; + background-color: $icon-button-color; mask-repeat: no-repeat; mask-size: contain; } diff --git a/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss b/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss index b5a57dfefb..23dcc532b2 100644 --- a/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss +++ b/res/css/views/settings/tabs/room/_SecurityRoomSettingsTab.scss @@ -14,10 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SecurityRoomSettingsTab label { - display: block; -} - .mx_SecurityRoomSettingsTab_warning { display: block; diff --git a/res/img/feather-customised/clipboard.svg b/res/img/feather-customised/clipboard.svg new file mode 100644 index 0000000000..b25b97176c --- /dev/null +++ b/res/img/feather-customised/clipboard.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/icon_copy_message.svg b/res/img/icon_copy_message.svg deleted file mode 100644 index 8d8887bb22..0000000000 --- a/res/img/icon_copy_message.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - image/svg+xml - - ED5D3E59-2561-4AC1-9B43-82FBC51767FC - - - - - - ED5D3E59-2561-4AC1-9B43-82FBC51767FC - Created with sketchtool. - - - - - - - - - diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index e39bb29044..8175e7d33d 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -46,7 +46,7 @@ $inverted-bg-color: $base-color; $selected-color: $room-highlight-color; // selected for hoverover & selected event tiles -$event-selected-color: $header-panel-bg-color; +$event-selected-color: #21262c; // used for the hairline dividers in RoomView $primary-hairline-color: transparent; @@ -100,10 +100,9 @@ $roomheader-bg-color: $bg-color; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.3); $roomheader-addroom-fg-color: $text-primary-color; $tagpanel-button-color: $header-panel-text-primary-color; -$roomheader-button-color: $header-panel-text-primary-color; $groupheader-button-color: $header-panel-text-primary-color; $rightpanel-button-color: $header-panel-text-primary-color; -$composer-button-color: $header-panel-text-primary-color; +$icon-button-color: #8E99A4; $roomtopic-color: $text-secondary-color; $eventtile-meta-color: $roomtopic-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 7ecfcf13d9..4268fad030 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -95,10 +95,9 @@ $roomheader-color: $text-primary-color; $roomheader-addroom-bg-color: #3c4556; // $search-placeholder-color at 0.5 opacity $roomheader-addroom-fg-color: $text-primary-color; $tagpanel-button-color: $header-panel-text-primary-color; -$roomheader-button-color: $header-panel-text-primary-color; $groupheader-button-color: $header-panel-text-primary-color; $rightpanel-button-color: $header-panel-text-primary-color; -$composer-button-color: $header-panel-text-primary-color; +$icon-button-color: $header-panel-text-primary-color; $roomtopic-color: $text-secondary-color; $eventtile-meta-color: $roomtopic-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 3465aa307e..5ebb4ccc02 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -162,10 +162,9 @@ $roomheader-bg-color: $primary-bg-color; $roomheader-addroom-bg-color: #91a1c0; $roomheader-addroom-fg-color: $accent-fg-color; $tagpanel-button-color: #91a1c0; -$roomheader-button-color: #91a1c0; $groupheader-button-color: #91a1c0; $rightpanel-button-color: #91a1c0; -$composer-button-color: #91a1c0; +$icon-button-color: #91a1c0; $roomtopic-color: #9e9e9e; $eventtile-meta-color: $roomtopic-color; @@ -228,7 +227,8 @@ $event-redacted-border-color: #cccccc; // event timestamp $event-timestamp-color: #acacac; -$copy-button-url: "$(res)/img/icon_copy_message.svg"; +$copy-button-url: "$(res)/img/feather-customised/clipboard.svg"; + // e2e $e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index e67bcdf89a..e9ade7eb97 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -74,7 +74,7 @@ $droptarget-bg-color: rgba(255,255,255,0.5); $selected-color: $secondary-accent-color; // selected for hoverover & selected event tiles -$event-selected-color: $header-panel-bg-color; +$event-selected-color: #f6f7f8; // used for the hairline dividers in RoomView $primary-hairline-color: transparent; @@ -158,10 +158,9 @@ $roomheader-bg-color: $primary-bg-color; $roomheader-addroom-bg-color: rgba(92, 100, 112, 0.2); $roomheader-addroom-fg-color: #5c6470; $tagpanel-button-color: #91A1C0; -$roomheader-button-color: #91A1C0; $groupheader-button-color: #91A1C0; $rightpanel-button-color: #91A1C0; -$composer-button-color: #91A1C0; +$icon-button-color: #C1C6CD; $roomtopic-color: #9e9e9e; $eventtile-meta-color: $roomtopic-color; @@ -230,7 +229,7 @@ $event-redacted-border-color: #cccccc; // event timestamp $event-timestamp-color: #acacac; -$copy-button-url: "$(res)/img/icon_copy_message.svg"; +$copy-button-url: "$(res)/img/feather-customised/clipboard.svg"; // e2e $e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx index 2e1529cbf1..dc2a987f13 100644 --- a/src/components/views/dialogs/ShareDialog.tsx +++ b/src/components/views/dialogs/ShareDialog.tsx @@ -30,6 +30,7 @@ import * as ContextMenu from "../../structures/ContextMenu"; import {toRightOf} from "../../structures/ContextMenu"; import {copyPlaintext, selectText} from "../../../utils/strings"; import StyledCheckbox from '../elements/StyledCheckbox'; +import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; const socials = [ { @@ -210,10 +211,11 @@ export default class ShareDialog extends React.PureComponent { > { matrixToUrl } - - { _t('COPY') } -
 
-
+ { checkbox }
diff --git a/src/components/views/elements/StyledRadioGroup.tsx b/src/components/views/elements/StyledRadioGroup.tsx index ea8f65d12b..6b9e992f92 100644 --- a/src/components/views/elements/StyledRadioGroup.tsx +++ b/src/components/views/elements/StyledRadioGroup.tsx @@ -25,6 +25,7 @@ interface IDefinition { disabled?: boolean; label: React.ReactChild; description?: React.ReactChild; + checked?: boolean; // If provided it will override the value comparison done in the group } interface IProps { @@ -33,7 +34,7 @@ interface IProps { definitions: IDefinition[]; value?: T; // if not provided no options will be selected outlined?: boolean; - onChange(newValue: T); + onChange(newValue: T): void; } function StyledRadioGroup({name, definitions, value, className, outlined, onChange}: IProps) { @@ -46,7 +47,7 @@ function StyledRadioGroup({name, definitions, value, className { constructor(props: IProps) { super(props); diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index bf4700ed97..c4f400c872 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -15,6 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ import React, {createRef} from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import CallHandler from '../../../CallHandler'; @@ -29,7 +30,6 @@ import E2EIcon from './E2EIcon'; import SettingsStore from "../../../settings/SettingsStore"; import {aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu} from "../../structures/ContextMenu"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; - function ComposerAvatar(props) { const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar'); return
@@ -117,9 +117,19 @@ const EmojiButton = ({addEmoji}) => { ; } + const className = classNames( + "mx_MessageComposer_button", + "mx_MessageComposer_emoji", + { + "mx_MessageComposer_button_highlight": menuDisplayed, + }, + ); + + // TODO: replace ContextMenuTooltipButton with a unified representation of + // the header buttons and the right panel buttons return ; diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js index fb2f8fa983..48115146f1 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js @@ -22,6 +22,7 @@ import * as sdk from "../../../../.."; import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; import Modal from "../../../../../Modal"; import QuestionDialog from "../../../dialogs/QuestionDialog"; +import StyledRadioGroup from '../../../elements/StyledRadioGroup'; import {SettingLevel} from "../../../../../settings/SettingLevel"; export default class SecurityRoomSettingsTab extends React.Component { @@ -144,7 +145,7 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onRoomAccessRadioToggle = (ev) => { + _onRoomAccessRadioToggle = (roomAccess) => { // join_rule // INVITE | PUBLIC // ----------------------+---------------- @@ -161,7 +162,7 @@ export default class SecurityRoomSettingsTab extends React.Component { let joinRule = "invite"; let guestAccess = "can_join"; - switch (ev.target.value) { + switch (roomAccess) { case "invite_only": // no change - use defaults above break; @@ -190,11 +191,11 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onHistoryRadioToggle = (ev) => { + _onHistoryRadioToggle = (history) => { const beforeHistory = this.state.history; - this.setState({history: ev.target.value}); + this.setState({history: history}); MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", { - history_visibility: ev.target.value, + history_visibility: history, }, "").catch((e) => { console.error(e); this.setState({history: beforeHistory}); @@ -257,27 +258,31 @@ export default class SecurityRoomSettingsTab extends React.Component {
{guestWarning} {aliasWarning} - - - +
); } @@ -294,34 +299,33 @@ export default class SecurityRoomSettingsTab extends React.Component { {_t('Changes to who can read history will only apply to future messages in this room. ' + 'The visibility of existing history will be unchanged.')}
- - - - + ); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 006e7e67bf..b636b5470e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1787,7 +1787,7 @@ "Share Community": "Share Community", "Share Room Message": "Share Room Message", "Link to selected message": "Link to selected message", - "COPY": "COPY", + "Copy": "Copy", "Command Help": "Command Help", "To help us prevent this in future, please send us logs.": "To help us prevent this in future, please send us logs.", "Missing session data": "Missing session data", @@ -2228,7 +2228,6 @@ "Confirm your recovery passphrase": "Confirm your recovery passphrase", "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.": "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.", "Download": "Download", - "Copy": "Copy", "Unable to query secret storage status": "Unable to query secret storage status", "Retry": "Retry", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.", diff --git a/test/end-to-end-tests/src/usecases/room-settings.js b/test/end-to-end-tests/src/usecases/room-settings.js index fac3fa0855..11e2f52c6e 100644 --- a/test/end-to-end-tests/src/usecases/room-settings.js +++ b/test/end-to-end-tests/src/usecases/room-settings.js @@ -162,7 +162,7 @@ async function changeRoomSettings(session, settings) { if (settings.visibility) { session.log.step(`sets visibility to ${settings.visibility}`); - const radios = await session.queryAll(".mx_RoomSettingsDialog input[type=radio]"); + const radios = await session.queryAll(".mx_RoomSettingsDialog label"); assert.equal(radios.length, 7); const inviteOnly = radios[0]; const publicNoGuests = radios[1];