Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into resizable-appsdrawer

 Conflicts:
	res/css/views/rooms/_AppsDrawer.scss
This commit is contained in:
Michael Telatynski 2020-08-20 10:26:35 +01:00
commit ae65ed5c2e
1200 changed files with 50388 additions and 28790 deletions

View file

@ -6,25 +6,20 @@ src/components/structures/RoomView.js
src/components/structures/ScrollPanel.js
src/components/structures/SearchBox.js
src/components/structures/UploadBar.js
src/components/views/avatars/BaseAvatar.js
src/components/views/avatars/MemberAvatar.js
src/components/views/create_room/RoomAlias.js
src/components/views/dialogs/SetPasswordDialog.js
src/components/views/dialogs/UnknownDeviceDialog.js
src/components/views/elements/AddressSelector.js
src/components/views/elements/DirectorySearchBox.js
src/components/views/elements/MemberEventListSummary.js
src/components/views/elements/UserSelector.js
src/components/views/globals/MatrixToolbar.js
src/components/views/globals/NewVersionBar.js
src/components/views/globals/UpdateCheckBar.js
src/components/views/messages/MFileBody.js
src/components/views/messages/TextualBody.js
src/components/views/room_settings/ColorSettings.js
src/components/views/rooms/Autocomplete.js
src/components/views/rooms/AuxPanel.js
src/components/views/rooms/LinkPreviewWidget.js
src/components/views/rooms/MemberDeviceInfo.js
src/components/views/rooms/MemberInfo.js
src/components/views/rooms/MemberList.js
src/components/views/rooms/RoomList.js

View file

@ -1,121 +1,34 @@
const path = require('path');
// get the path of the js-sdk so we can extend the config
// eslint supports loading extended configs by module,
// but only if they come from a module that starts with eslint-config-
// So we load the filename directly (and it could be in node_modules/
// or or ../node_modules/ etc)
//
// We add a `..` to the end because the js-sdk lives out of lib/, but the eslint
// config is at the project root.
const matrixJsSdkPath = path.join(path.dirname(require.resolve('matrix-js-sdk')), '..');
module.exports = {
extends: ["matrix-org", "matrix-org/react-legacy"],
parser: "babel-eslint",
extends: [matrixJsSdkPath + "/.eslintrc.js"],
plugins: [
"react",
"react-hooks",
"flowtype",
"babel"
],
env: {
browser: true,
node: true,
},
globals: {
LANGUAGES_FILE: "readonly",
},
env: {
es6: true,
},
parserOptions: {
ecmaFeatures: {
jsx: true,
legacyDecorators: true,
}
},
rules: {
// eslint's built in no-invalid-this rule breaks with class properties
"no-invalid-this": "off",
// so we replace it with a version that is class property aware
"babel/no-invalid-this": "error",
// Things we do that break the ideal style
"no-constant-condition": "off",
"prefer-promise-reject-errors": "off",
"no-async-promise-executor": "off",
"quotes": "off",
"indent": "off",
},
// We appear to follow this most of the time, so let's enforce it instead
// of occasionally following it (or catching it in review)
"keyword-spacing": "error",
overrides: [{
"files": ["src/**/*.{ts, tsx}"],
"extends": ["matrix-org/ts"],
"rules": {
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off",
// We'd rather not do this but we do
"@typescript-eslint/ban-ts-comment": "off",
/** react **/
// This just uses the react plugin to help eslint known when
// variables have been used in JSX
"react/jsx-uses-vars": "error",
// Don't mark React as unused if we're using JSX
"react/jsx-uses-react": "error",
// bind or arrow function in props causes performance issues
// (but we currently use them in some places)
// It's disabled here, but we should using it sparingly.
"react/jsx-no-bind": "off",
"react/jsx-key": ["error"],
// Components in JSX should always be defined.
"react/jsx-no-undef": "error",
// Assert no spacing in JSX curly brackets
// <Element prop={ consideredError} prop={notConsideredError} />
//
// https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/docs/rules/jsx-curly-spacing.md
//
// Disabled for now - if anything we'd like to *enforce* spacing in JSX
// curly brackets for legibility, but in practice it's not clear that the
// consistency particularly improves legibility here. --Matthew
//
// "react/jsx-curly-spacing": ["error", {"when": "never", "children": {"when": "always"}}],
// Assert spacing before self-closing JSX tags, and no spacing before or
// after the closing slash, and no spacing after the opening bracket of
// the opening tag or closing tag.
//
// https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/docs/rules/jsx-tag-spacing.md
"react/jsx-tag-spacing": ["error"],
/** flowtype **/
"flowtype/require-parameter-type": ["warn", {
"excludeArrowFunctions": true,
"quotes": "off",
"no-extra-boolean-cast": "off",
},
}],
"flowtype/define-flow-type": "warn",
"flowtype/require-return-type": ["warn",
"always",
{
"annotateUndefined": "never",
"excludeArrowFunctions": true,
}
],
"flowtype/space-after-type-colon": ["warn", "always"],
"flowtype/space-before-type-colon": ["warn", "never"],
/*
* things that are errors in the js-sdk config that the current
* code does not adhere to, turned down to warn
*/
"max-len": ["warn", {
// apparently people believe the length limit shouldn't apply
// to JSX.
ignorePattern: '^\\s*<',
ignoreComments: true,
ignoreRegExpLiterals: true,
code: 120,
}],
"valid-jsdoc": ["warn"],
"new-cap": ["warn"],
"key-spacing": ["warn"],
"prefer-const": ["warn"],
// crashes currently: https://github.com/eslint/eslint/issues/6274
"generator-star-spacing": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
},
settings: {
flowtype: {
onlyFilesWithFlowAnnotation: true
},
},
};

View file

@ -17,7 +17,7 @@ module.exports = {
"at-rule-no-unknown": null,
"no-descending-specificity": null,
"scss/at-rule-no-unknown": [true, {
// https://github.com/vector-im/riot-web/issues/10544
// https://github.com/vector-im/element-web/issues/10544
"ignoreAtRules": ["define-mixin"],
}],
}

File diff suppressed because it is too large Load diff

View file

@ -11,14 +11,14 @@ a 'skin'. A skin provides:
* The containing application
* Zero or more 'modules' containing non-UI functionality
As of Aug 2018, the only skin that exists is `vector-im/riot-web`; it and
As of Aug 2018, the only skin that exists is `vector-im/element-web`; it and
`matrix-org/matrix-react-sdk` should effectively
be considered as a single project (for instance, matrix-react-sdk bugs
are currently filed against vector-im/riot-web rather than this project).
are currently filed against vector-im/element-web rather than this project).
Translation Status
==================
[![Translation status](https://translate.riot.im/widgets/riot-web/-/multi-auto.svg)](https://translate.riot.im/engage/riot-web/?utm_source=widget)
[![Translation status](https://translate.riot.im/widgets/element-web/-/multi-auto.svg)](https://translate.riot.im/engage/element-web/?utm_source=widget)
Developer Guide
===============
@ -41,10 +41,10 @@ https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md
Code should be committed as follows:
* All new components: https://github.com/matrix-org/matrix-react-sdk/tree/master/src/components
* Riot-specific components: https://github.com/vector-im/riot-web/tree/master/src/components
* Element-specific components: https://github.com/vector-im/element-web/tree/master/src/components
* In practice, `matrix-react-sdk` is still evolving so fast that the maintenance
burden of customising and overriding these components for Riot can seriously
impede development. So right now, there should be very few (if any) customisations for Riot.
burden of customising and overriding these components for Element can seriously
impede development. So right now, there should be very few (if any) customisations for Element.
* CSS: https://github.com/matrix-org/matrix-react-sdk/tree/master/res/css
* Theme specific CSS & resources: https://github.com/matrix-org/matrix-react-sdk/tree/master/res/themes
@ -71,7 +71,7 @@ practices that anyone working with the SDK needs to be be aware of and uphold:
* The view's CSS file MUST have the same name (e.g. view/rooms/MessageTile.css).
CSS for matrix-react-sdk currently resides in
https://github.com/vector-im/riot-web/tree/master/src/skins/vector/css/matrix-react-sdk.
https://github.com/vector-im/element-web/tree/master/src/skins/vector/css/matrix-react-sdk.
* Per-view CSS is optional - it could choose to inherit all its styling from
the context of the rest of the app, although this is unusual for any but
@ -125,7 +125,7 @@ from it.
Github Issues
=============
All issues should be filed under https://github.com/vector-im/riot-web/issues
All issues should be filed under https://github.com/vector-im/element-web/issues
for now.
Development
@ -133,8 +133,10 @@ Development
Ensure you have the latest LTS version of Node.js installed.
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install
guide](https://yarnpkg.com/docs/install/) if you do not have it already.
Using `yarn` instead of `npm` is recommended. Please see the Yarn 1 [install
guide](https://classic.yarnpkg.com/docs/install) if you do not have it
already. This project has not yet been migrated to Yarn 2, so please ensure
`yarn --version` shows a version from the 1.x series.
`matrix-react-sdk` depends on `matrix-js-sdk`. To make use of changes in the
latter and to ensure tests run against the develop branch of `matrix-js-sdk`,
@ -172,5 +174,5 @@ yarn test
## End-to-End tests
Make sure you've got your Riot development server running (by doing `yarn start` in riot-web), and then in this project, run `yarn run e2etests`.
Make sure you've got your Element development server running (by doing `yarn start` in element-web), and then in this project, run `yarn run e2etests`.
See `test/end-to-end-tests/README.md` for more information.

View file

@ -4,7 +4,7 @@ Matrix JavaScript/ECMAScript Style Guide
The intention of this guide is to make Matrix's JavaScript codebase clean,
consistent with other popular JavaScript styles and consistent with the rest of
the Matrix codebase. For reference, the Matrix Python style guide can be found
at https://github.com/matrix-org/synapse/blob/master/docs/code_style.rst
at https://github.com/matrix-org/synapse/blob/master/docs/code_style.md
This document reflects how we would like Matrix JavaScript code to look, with
acknowledgement that a significant amount of code is written to older
@ -17,7 +17,7 @@ writing in modern ECMAScript and using a transpile step to generate the file
that applications can then include. There are significant benefits in being
able to use modern ECMAScript, although the tooling for doing so can be awkward
for library code, especially with regard to translating source maps and line
number throgh from the original code to the final application.
number through from the original code to the final application.
General Style
-------------
@ -151,6 +151,7 @@ General Style
Don't set things to undefined. Reserve that value to mean "not yet set to anything."
Boolean objects are verboten.
- Use JSDoc
- Use switch-case statements where there are 5 or more branches running against the same variable.
ECMAScript
----------

View file

@ -1,6 +1,6 @@
# The CIDER (Contenteditable-Input-Diff-Error-Reconcile) editor
The CIDER editor is a custom editor written for Riot.
The CIDER editor is a custom editor written for Element.
Most of the code can be found in the `/editor/` directory of the `matrix-react-sdk` project.
It is used to power the composer main composer (both to send and edit messages), and might be used for other usecases where autocomplete is desired (invite box, ...).

BIN
docs/img/RoomListStore2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View file

@ -25,7 +25,7 @@ which takes several parameters:
be null.
The react-sdk will assume that `jitsi.html` is at the path of wherever it is currently
being served. For example, `https://riot.im/develop/jitsi.html` or `vector://webapp/jitsi.html`.
being served. For example, `https://develop.element.io/jitsi.html` or `vector://webapp/jitsi.html`.
The `jitsi.html` wrapper can use the react-sdk's `WidgetApi` to communicate, making
it easier to actually implement the feature.

39
docs/local-echo-dev.md Normal file
View file

@ -0,0 +1,39 @@
# Local echo (developer docs)
The React SDK provides some local echo functionality to allow for components to do something
quickly and fall back when it fails. This is all available in the `local-echo` directory within
`stores`.
Echo is handled in EchoChambers, with `GenericEchoChamber` being the base implementation for all
chambers. The `EchoChamber` class is provided as semantic access to a `GenericEchoChamber`
implementation, such as the `RoomEchoChamber` (which handles echoable details of a room).
Anything that can be locally echoed will be provided by the `GenericEchoChamber` implementation.
The echo chamber will also need to deal with external changes, and has full control over whether
or not something has successfully been echoed.
An `EchoContext` is provided to echo chambers (usually with a matching type: `RoomEchoContext`
gets provided to a `RoomEchoChamber` for example) with details about their intended area of
effect, as well as manage `EchoTransaction`s. An `EchoTransaction` is simply a unit of work that
needs to be locally echoed.
The `EchoStore` manages echo chamber instances, builds contexts, and is generally less semantically
accessible than the `EchoChamber` class. For separation of concerns, and to try and keep things
tidy, this is an intentional design decision.
**Note**: The local echo stack uses a "whenable" pattern, which is similar to thenables and
`EventEmitter`. Whenables are ways of actioning a changing condition without having to deal
with listeners being torn down. Once the reference count of the Whenable causes garbage collection,
the Whenable's listeners will also be torn down. This is accelerated by the `IDestroyable` interface
usage.
## Audit functionality
The UI supports a "Server isn't responding" dialog which includes a partial audit log-like
structure to it. This is partially the reason for added complexity of `EchoTransaction`s
and `EchoContext`s - this information feeds the UI states which then provide direct retry
mechanisms.
The `EchoStore` is responsible for ensuring that the appropriate non-urgent toast (lower left)
is set up, where the dialog then drives through the contexts and transactions.

151
docs/room-list-store.md Normal file
View file

@ -0,0 +1,151 @@
# Room list sorting
It's so complicated it needs its own README.
![](img/RoomListStore2.png)
Legend:
* Orange = External event.
* Purple = Deterministic flow.
* Green = Algorithm definition.
* Red = Exit condition/point.
* Blue = Process definition.
## Algorithms involved
There's two main kinds of algorithms involved in the room list store: list ordering and tag sorting.
Throughout the code an intentional decision has been made to call them the List Algorithm and Sorting
Algorithm respectively. The list algorithm determines the primary ordering of a given tag whereas the
tag sorting defines how rooms within that tag get sorted, at the discretion of the list ordering.
Behaviour of the overall room list (sticky rooms, etc) are determined by the generically-named Algorithm
class. Here is where much of the coordination from the room list store is done to figure out which list
algorithm to call, instead of having all the logic in the room list store itself.
Tag sorting is effectively the comparator supplied to the list algorithm. This gives the list algorithm
the power to decide when and how to apply the tag sorting, if at all. For example, the importance algorithm,
later described in this document, heavily uses the list ordering behaviour to break the tag into categories.
Each category then gets sorted by the appropriate tag sorting algorithm.
### Tag sorting algorithm: Alphabetical
When used, rooms in a given tag will be sorted alphabetically, where the alphabet's order is a problem
for the browser. All we do is a simple string comparison and expect the browser to return something
useful.
### Tag sorting algorithm: Manual
Manual sorting makes use of the `order` property present on all tags for a room, per the
[Matrix specification](https://matrix.org/docs/spec/client_server/r0.6.0#room-tagging). Smaller values
of `order` cause rooms to appear closer to the top of the list.
### Tag sorting algorithm: Recent
Rooms get ordered by the timestamp of the most recent useful message. Usefulness is yet another algorithm
in the room list system which determines whether an event type is capable of bubbling up in the room list.
Normally events like room messages, stickers, and room security changes will be considered useful enough
to cause a shift in time.
Note that this is reliant on the event timestamps of the most recent message. Because Matrix is eventually
consistent this means that from time to time a room might plummet or skyrocket across the tag due to the
timestamp contained within the event (generated server-side by the sender's server).
### List ordering algorithm: Natural
This is the easiest of the algorithms to understand because it does essentially nothing. It imposes no
behavioural changes over the tag sorting algorithm and is by far the simplest way to order a room list.
Historically, it's been the only option in Element and extremely common in most chat applications due to
its relative deterministic behaviour.
### List ordering algorithm: Importance
On the other end of the spectrum, this is the most complicated algorithm which exists. There's major
behavioural changes, and the tag sorting algorithm gets selectively applied depending on circumstances.
Each tag which is not manually ordered gets split into 4 sections or "categories". Manually ordered tags
simply get the manual sorting algorithm applied to them with no further involvement from the importance
algorithm. There are 4 categories: Red, Grey, Bold, and Idle. Each has their own definition based off
relative (perceived) importance to the user:
* **Red**: The room has unread mentions waiting for the user.
* **Grey**: The room has unread notifications waiting for the user. Notifications are simply unread
messages which cause a push notification or badge count. Typically, this is the default as rooms get
set to 'All Messages'.
* **Bold**: The room has unread messages waiting for the user. Essentially this is a grey room without
a badge/notification count (or 'Mentions Only'/'Muted').
* **Idle**: No useful (see definition of useful above) activity has occurred in the room since the user
last read it.
Conveniently, each tag gets ordered by those categories as presented: red rooms appear above grey, grey
above bold, etc.
Once the algorithm has determined which rooms belong in which categories, the tag sorting algorithm
gets applied to each category in a sub-list fashion. This should result in the red rooms (for example)
being sorted alphabetically amongst each other as well as the grey rooms sorted amongst each other, but
collectively the tag will be sorted into categories with red being at the top.
## Sticky rooms
When the user visits a room, that room becomes 'sticky' in the list, regardless of ordering algorithm.
From a code perspective, the underlying algorithm is not aware of a sticky room and instead the base class
manages which room is sticky. This is to ensure that all algorithms handle it the same.
The sticky flag is simply to say it will not move higher or lower down the list while it is active. For
example, if using the importance algorithm, the room would naturally become idle once viewed and thus
would normally fly down the list out of sight. The sticky room concept instead holds it in place, never
letting it fly down until the user moves to another room.
Only one room can be sticky at a time. Room updates around the sticky room will still hold the sticky
room in place. The best example of this is the importance algorithm: if the user has 3 red rooms and
selects the middle room, they will see exactly one room above their selection at all times. If they
receive another notification which causes the room to move into the topmost position, the room that was
above the sticky room will move underneath to allow for the new room to take the top slot, maintaining
the sticky room's position.
Though only applicable to the importance algorithm, the sticky room is not aware of category boundaries
and thus the user can see a shift in what kinds of rooms move around their selection. An example would
be the user having 4 red rooms, the user selecting the third room (leaving 2 above it), and then having
the rooms above it read on another device. This would result in 1 red room and 1 other kind of room
above the sticky room as it will try to maintain 2 rooms above the sticky room.
An exception for the sticky room placement is when there's suddenly not enough rooms to maintain the placement
exactly. This typically happens if the user selects a room and leaves enough rooms where it cannot maintain
the N required rooms above the sticky room. In this case, the sticky room will simply decrease N as needed.
The N value will never increase while selection remains unchanged: adding a bunch of rooms after having
put the sticky room in a position where it's had to decrease N will not increase N.
## Responsibilities of the store
The store is responsible for the ordering, upkeep, and tracking of all rooms. The room list component simply gets
an object containing the tags it needs to worry about and the rooms within. The room list component will
decide which tags need rendering (as it commonly filters out empty tags in most cases), and will deal with
all kinds of filtering.
## Filtering
Filters are provided to the store as condition classes, which are then passed along to the algorithm
implementations. The implementations then get to decide how to actually filter the rooms, however in
practice the base `Algorithm` class deals with the filtering in a more optimized/generic way.
The results of filters get cached to avoid needlessly iterating over potentially thousands of rooms,
as the old room list store does. When a filter condition changes, it emits an update which (in this
case) the `Algorithm` class will pick up and act accordingly. Typically, this also means filtering a
minor subset where possible to avoid over-iterating rooms.
All filter conditions are considered "stable" by the consumers, meaning that the consumer does not
expect a change in the condition unless the condition says it has changed. This is intentional to
maintain the caching behaviour described above.
## Class breakdowns
The `RoomListStore` is the major coordinator of various algorithm implementations, which take care
of the various `ListAlgorithm` and `SortingAlgorithm` options. The `Algorithm` class is responsible
for figuring out which tags get which rooms, as Matrix specifies them as a reverse map: tags get
defined on rooms and are not defined as a collection of rooms (unlike how they are presented to the
user). Various list-specific utilities are also included, though they are expected to move somewhere
more general when needed. For example, the `membership` utilities could easily be moved elsewhere
as needed.
The various bits throughout the room list store should also have jsdoc of some kind to help describe
what they do and how they work.

View file

@ -13,7 +13,7 @@ ScrollPanel supports a mode to prevent it shrinking. This is used to prevent a j
BACAT scrolling implements a different way of restoring the scroll position in the timeline while tiles out of view are changing height or tiles are being added or removed. It was added in https://github.com/matrix-org/matrix-react-sdk/pull/2842.
The motivation for the changes is having noticed that setting scrollTop while scrolling tends to not work well, with it interrupting ongoing scrolling and also querying scrollTop reporting outdated values and consecutive scroll adjustments cancelling each out previous ones. This seems to be worse on macOS than other platforms, presumably because of a higher resolution in scroll events there. Also see https://github.com/vector-im/riot-web/issues/528. The BACAT approach allows to only have to change the scroll offset when adding or removing tiles.
The motivation for the changes is having noticed that setting scrollTop while scrolling tends to not work well, with it interrupting ongoing scrolling and also querying scrollTop reporting outdated values and consecutive scroll adjustments cancelling each out previous ones. This seems to be worse on macOS than other platforms, presumably because of a higher resolution in scroll events there. Also see https://github.com/vector-im/element-web/issues/528. The BACAT approach allows to only have to change the scroll offset when adding or removing tiles.
The approach taken instead is to vertically align the timeline tiles to the bottom of the scroll container (using flexbox) and give the timeline inside the scroll container an explicit height, initially set to a multiple of the PAGE_SIZE (400px at time of writing) as needed by the content. When scrolled up, we can compensate for anything that grew below the viewport by changing the height of the timeline to maintain what's currently visible in the viewport without adjusting the scrollTop and hence without jumping.

View file

@ -9,7 +9,7 @@ of dealing with the different levels and exposes easy to use getters and setters
## Levels
Granular Settings rely on a series of known levels in order to use the correct value for the scenario. These levels, in
order of prioirty, are:
order of priority, are:
* `device` - The current user's device
* `room-device` - The current user's device, but only when in a specific room
* `room-account` - The current user's account, but only when in a specific room
@ -25,33 +25,10 @@ that room administrators cannot force account-only settings upon participants.
## Settings
Settings are the different options a user may set or experience in the application. These are pre-defined in
`src/settings/Settings.js` under the `SETTINGS` constant and have the following minimum requirements:
```
// The ID is used to reference the setting throughout the application. This must be unique.
"theSettingId": {
// The levels this setting supports is required. In `src/settings/Settings.js` there are various pre-set arrays
// for this option - they should be used where possible to avoid copy/pasting arrays across settings.
supportedLevels: [...],
`src/settings/Settings.ts` under the `SETTINGS` constant, and match the `ISetting` interface as defined there.
// The default for this setting serves two purposes: It provides a value if the setting is not defined at other
// levels, and it serves to demonstrate the expected type to other developers. The value isn't enforced, but it
// should be respected throughout the code. The default may be any data type.
default: false,
// The display name has two notations: string and object. The object notation allows for different translatable
// strings to be used for different levels, while the string notation represents the string for all levels.
displayName: _td("Change something"), // effectively `displayName: { "default": _td("Change something") }`
displayName: {
"room": _td("Change something for participants of this room"),
// Note: the default will be used if the level requested (such as `device`) does not have a string defined here.
"default": _td("Change something"),
}
}
```
Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some settings, like the "theme" setting, are special cased in the config file):
Settings that support the config level can be set in the config file under the `settingDefaults` key (note that some
settings, like the "theme" setting, are special cased in the config file):
```json
{
...
@ -119,38 +96,29 @@ for you. If a display name cannot be found, it will return `null`.
## Features
Occasionally some parts of the application may be undergoing testing and are not quite production ready. These are
commonly known to be behind a "labs flag". Features behind lab flags must go through the granular settings system, and
look and act very much normal settings. The exception is that they must supply `isFeature: true` as part of the setting
definition and should go through the helper functions on `SettingsStore`.
Feature flags are just like regular settings with some underlying semantics for how they are meant to be used. Usually
a feature flag is used when a portion of the application is under development or not ready for full release yet, such
as new functionality or experimental ideas. In these cases, the feature name *should* be named with the `feature_*`
convention and must be tagged with `isFeature: true` in the setting definition. By doing so, the feature will automatically
appear in the "labs" section of the user's settings.
Although features have levels and a default value, the calculation of those options is blocked by the feature's state.
A feature's state is determined from the `SdkConfig` and is a little complex. If `enableLabs` (a legacy flag) is `true`
then the feature's state is `labs`, if it is `false`, the state is `disable`. If `enableLabs` is not set then the state
is determined from the `features` config, such as in the following:
Features can be controlled at the config level using the following structure:
```json
"features": {
"feature_lazyloading": "labs"
"feature_lazyloading": true
}
```
In this example, `feature_lazyloading` is in the `labs` state. It may also be in the `enable` or `disable` state with a
similar approach. If the state is invalid, the feature is in the `disable` state. A feature's levels are only calculated
if it is in the `labs` state, therefore the default only applies in that scenario. If the state is `enable`, the feature
is always-on.
Once a feature flag has served its purpose, it is generally recommended to remove it and the associated feature flag
checks. This would enable the feature implicitly as it is part of the application now.
When `true`, the user will see the feature as enabled. Similarly, when `false` the user will see the feature as disabled.
The user will only be able to change/see these states if `showLabsSettings: true` is in the config.
### Determining if a feature is enabled
A simple call to `SettingsStore.isFeatureEnabled` will tell you if the feature is enabled. This will perform all the
required calculations to determine if the feature is enabled based upon the configuration and user selection.
Call `SettingsStore.getValue()` as you would for any other setting.
### Enabling a feature
Features can only be enabled if the feature is in the `labs` state, otherwise this is a no-op. To find the current set
of features in the `labs` state, call `SettingsStore.getLabsFeatures`. To set the value, call
`SettingsStore.setFeatureEnabled`.
Call `SettingsStore.setValue("feature_name", null, SettingLevel.DEVICE, true)`.
## Setting controllers
@ -162,7 +130,7 @@ kept up to date with the setting where it is otherwise not possible. An example
they can only be considered enabled if the platform supports notifications, and enabling notifications requires
additional steps to actually enable notifications.
For more information, see `src/settings/controllers/SettingController.js`.
For more information, see `src/settings/controllers/SettingController.ts`.
## Local echo
@ -222,7 +190,7 @@ The `SettingsStore` uses the hardcoded `LEVEL_ORDER` constant to ensure that it
The array is checked from left to right, simulating the behaviour of overriding values from the higher levels. Each
level should be defined in this array, including `default`.
Handlers (`src/settings/handlers/SettingsHandler.js`) represent a single level and are responsible for getting and
Handlers (`src/settings/handlers/SettingsHandler.ts`) represent a single level and are responsible for getting and
setting values at that level. Handlers also provide additional information to the `SettingsStore` such as if the level
is supported or if the current user may set values at the level. The `SettingsStore` will use the handler to enforce
checks and manipulate settings. Handlers are also responsible for dealing with migration patterns or legacy settings for
@ -230,7 +198,7 @@ their level (for example, a setting being renamed or using a different key from
Handlers are provided to the `SettingsStore` via the `LEVEL_HANDLERS` constant. `SettingsStore` will optimize lookups by
only considering handlers that are supported on the platform.
Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.js` which acts as a wrapper around a given
Local echo is achieved through `src/settings/handlers/LocalEchoWrapper.ts` which acts as a wrapper around a given
handler. This is automatically applied to all defined `LEVEL_HANDLERS` and proxies the calls to the wrapped handler
where possible. The echo is achieved by a simple object cache stored within the class itself. The cache is invalidated
immediately upon the proxied save call succeeding or failing.
@ -240,20 +208,7 @@ Controllers are notified of changes by the `SettingsStore`, and are given the op
### Features
Features automatically get considered as `disabled` if they are not listed in the `SdkConfig` or `enableLabs` is
false/not set. Features are always checked against the configuration before going through the level order as they have
the option of being forced-on or forced-off for the application. This is done by the `features` section and looks
something like this:
```
"features": {
"feature_groups": "enable",
"feature_pinning": "disable", // the default
"feature_presence": "labs"
}
```
If `enableLabs` is true in the configuration, the default for features becomes `"labs"`.
See above for feature reference.
### Watchers

View file

@ -5,9 +5,9 @@ letting the browser and user interact with the resulting data may be dangerous,
previously `usercontent.riot.im` was used to act as a sandbox on a different origin to close the attack surface,
it is now possible to do by using a combination of a sandboxed iframe and some code written into the app which consumes this SDK.
Usercontent is an iframe sandbox target for allowing a user to safely download a decrypted attachment from a sandboxed origin where it cannot be used to XSS your riot session out from under you.
Usercontent is an iframe sandbox target for allowing a user to safely download a decrypted attachment from a sandboxed origin where it cannot be used to XSS your Element session out from under you.
Its function is to create an Object URL for the user/browser to use but bound to an origin different to that of the riot instance to protect against XSS.
Its function is to create an Object URL for the user/browser to use but bound to an origin different to that of the Element instance to protect against XSS.
It exposes a function over a postMessage API, when sent an object with the matching fields to render a download link with the Object URL:
@ -24,4 +24,4 @@ It exposes a function over a postMessage API, when sent an object with the match
If only imgSrc, imgStyle and style are passed then just update the existing link without overwriting other things about it.
It is expected that this target be available at `usercontent/` relative to the root of the app, this can be seen in riot-web's webpack config.
It is expected that this target be available at `usercontent/` relative to the root of the app, this can be seen in element-web's webpack config.

View file

@ -1,6 +1,6 @@
{
"name": "matrix-react-sdk",
"version": "2.3.1",
"version": "3.2.0",
"description": "SDK for matrix.org using React",
"author": "matrix.org",
"repository": {
@ -45,118 +45,135 @@
"start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all",
"start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
"lint:ts": "tslint --project ./tsconfig.json -t stylish",
"lint:types": "tsc --noEmit --jsx react",
"lint:style": "stylelint 'res/css/**/*.scss'",
"test": "jest",
"test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
},
"dependencies": {
"@babel/runtime": "^7.8.3",
"blueimp-canvas-to-blob": "^3.5.0",
"@babel/runtime": "^7.10.5",
"await-lock": "^2.0.1",
"blueimp-canvas-to-blob": "^3.27.0",
"browser-encrypt-attachment": "^0.3.0",
"browser-request": "^0.3.3",
"classnames": "^2.1.2",
"commonmark": "^0.28.1",
"counterpart": "^0.18.0",
"create-react-class": "^15.6.0",
"diff-dom": "^4.1.3",
"diff-match-patch": "^1.0.4",
"emojibase-data": "^4.0.2",
"emojibase-regex": "^3.0.0",
"classnames": "^2.2.6",
"commonmark": "^0.29.1",
"counterpart": "^0.18.6",
"create-react-class": "^15.6.3",
"diff-dom": "^4.1.6",
"diff-match-patch": "^1.0.5",
"emojibase-data": "^5.0.1",
"emojibase-regex": "^4.0.1",
"escape-html": "^1.0.3",
"file-saver": "^1.3.3",
"filesize": "3.5.6",
"file-saver": "^1.3.8",
"filesize": "3.6.1",
"flux": "2.1.1",
"focus-visible": "^5.0.2",
"fuse.js": "^2.2.0",
"gfm.css": "^1.1.1",
"focus-visible": "^5.1.0",
"fuse.js": "^2.7.4",
"gfm.css": "^1.1.2",
"glob-to-regexp": "^0.4.1",
"highlight.js": "^9.15.8",
"html-entities": "^1.2.1",
"highlight.js": "^10.1.2",
"html-entities": "^1.3.1",
"is-ip": "^2.0.0",
"linkifyjs": "^2.1.6",
"lodash": "^4.17.14",
"linkifyjs": "^2.1.9",
"lodash": "^4.17.19",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"minimist": "^1.2.0",
"pako": "^1.0.5",
"minimist": "^1.2.5",
"pako": "^1.0.11",
"parse5": "^5.1.1",
"png-chunks-extract": "^1.0.0",
"project-name-generator": "^2.1.7",
"prop-types": "^15.5.8",
"prop-types": "^15.7.2",
"qrcode": "^1.4.4",
"qrcode-react": "^0.1.16",
"qs": "^6.6.0",
"react": "^16.9.0",
"qs": "^6.9.4",
"re-resizable": "^6.5.4",
"react": "^16.13.1",
"react-beautiful-dnd": "^4.0.1",
"react-dom": "^16.9.0",
"react-focus-lock": "^2.2.1",
"resize-observer-polyfill": "^1.5.0",
"sanitize-html": "^1.18.4",
"text-encoding-utf-8": "^1.0.1",
"react-dom": "^16.13.1",
"react-focus-lock": "^2.4.1",
"react-transition-group": "^4.4.1",
"resize-observer-polyfill": "^1.5.1",
"sanitize-html": "^1.27.1",
"tar-js": "^0.3.0",
"text-encoding-utf-8": "^1.0.2",
"url": "^0.11.0",
"velocity-animate": "^1.5.2",
"what-input": "^5.2.6",
"what-input": "^5.2.10",
"zxcvbn": "^4.4.2"
},
"devDependencies": {
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-decorators": "^7.7.4",
"@babel/plugin-proposal-export-default-from": "^7.7.4",
"@babel/plugin-proposal-numeric-separator": "^7.7.4",
"@babel/plugin-proposal-object-rest-spread": "^7.7.4",
"@babel/plugin-transform-flow-comments": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.7.6",
"@babel/preset-flow": "^7.7.4",
"@babel/preset-react": "^7.7.4",
"@babel/preset-typescript": "^7.7.4",
"@babel/register": "^7.7.4",
"@peculiar/webcrypto": "^1.0.22",
"@babel/cli": "^7.10.5",
"@babel/core": "^7.10.5",
"@babel/parser": "^7.11.0",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-proposal-decorators": "^7.10.5",
"@babel/plugin-proposal-export-default-from": "^7.10.4",
"@babel/plugin-proposal-numeric-separator": "^7.10.4",
"@babel/plugin-proposal-object-rest-spread": "^7.10.4",
"@babel/plugin-transform-flow-comments": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.10.5",
"@babel/preset-env": "^7.10.4",
"@babel/preset-flow": "^7.10.4",
"@babel/preset-react": "^7.10.4",
"@babel/preset-typescript": "^7.10.4",
"@babel/register": "^7.10.5",
"@babel/traverse": "^7.11.0",
"@peculiar/webcrypto": "^1.1.2",
"@types/classnames": "^2.2.10",
"@types/counterpart": "^0.18.1",
"@types/flux": "^3.1.9",
"@types/linkifyjs": "^2.1.3",
"@types/lodash": "^4.14.158",
"@types/modernizr": "^3.5.3",
"@types/react": "16.9",
"babel-eslint": "^10.0.3",
"@types/node": "^12.12.51",
"@types/pako": "^1.0.1",
"@types/qrcode": "^1.3.4",
"@types/react": "^16.9",
"@types/react-dom": "^16.9.8",
"@types/react-transition-group": "^4.4.0",
"@types/sanitize-html": "^1.23.3",
"@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^3.7.0",
"@typescript-eslint/parser": "^3.7.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^24.9.0",
"chokidar": "^3.3.1",
"concurrently": "^4.0.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint": "^5.12.0",
"eslint-config-google": "^0.7.1",
"eslint-plugin-babel": "^5.2.1",
"eslint-plugin-flowtype": "^2.30.0",
"eslint-plugin-jest": "^23.0.4",
"eslint-plugin-react": "^7.7.0",
"eslint-plugin-react-hooks": "^2.0.1",
"estree-walker": "^0.5.0",
"chokidar": "^3.4.1",
"concurrently": "^4.1.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"eslint": "7.5.0",
"eslint-config-matrix-org": "^0.1.2",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-flowtype": "^2.50.3",
"eslint-plugin-react": "^7.20.3",
"eslint-plugin-react-hooks": "^2.5.1",
"file-loader": "^3.0.1",
"flow-parser": "^0.57.3",
"glob": "^5.0.14",
"glob": "^5.0.15",
"jest": "^24.9.0",
"jest-canvas-mock": "^2.2.0",
"lolex": "^5.1.2",
"matrix-mock-request": "^1.2.3",
"matrix-react-test-utils": "^0.2.2",
"react-test-renderer": "^16.9.0",
"rimraf": "^2.4.3",
"source-map-loader": "^0.2.3",
"react-test-renderer": "^16.13.1",
"rimraf": "^2.7.1",
"source-map-loader": "^0.2.4",
"stylelint": "^9.10.1",
"stylelint-config-standard": "^18.2.0",
"stylelint-scss": "^3.9.0",
"tslint": "^5.20.1",
"typescript": "^3.7.3",
"walk": "^2.3.9",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.1"
"stylelint-config-standard": "^18.3.0",
"stylelint-scss": "^3.18.0",
"typescript": "^3.9.7",
"walk": "^2.3.14",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
},
"jest": {
"testMatch": [
"<rootDir>/test/**/*-test.js"
],
"setupFiles": [
"jest-canvas-mock"
],
"setupFilesAfterEnv": [
"<rootDir>/test/setupTests.js"
],

View file

@ -19,7 +19,7 @@ limitations under the License.
@import "./_font-sizes.scss";
:root {
font-size: 15px;
font-size: 10px;
}
html {
@ -38,7 +38,7 @@ body {
margin: 0px;
// needed to match the designs correctly on macOS
// see https://github.com/vector-im/riot-web/issues/11425
// see https://github.com/vector-im/element-web/issues/11425
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@ -160,9 +160,8 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
background-color: transparent;
color: $input-darker-fg-color;
border-radius: 4px;
border: 1px solid $dialog-close-fg-color;
// these things should probably not be defined
// globally
border: 1px solid rgba($primary-fg-color, .1);
// these things should probably not be defined globally
margin: 9px;
flex: 0 0 auto;
}
@ -175,7 +174,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
:not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=text]::placeholder,
:not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search]::placeholder,
.mx_textinput input::placeholder {
color: $roomsublist-label-fg-color;
color: rgba($input-darker-fg-color, .75);
}
}
@ -227,7 +226,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
}
#mx_theme_tertiaryAccentColor {
color: $roomsublist-label-bg-color;
color: $tertiary-accent-color;
}
/* Expected z-indexes for dialogs:
@ -264,7 +263,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
padding: 25px 30px 30px 30px;
max-height: 80%;
box-shadow: 2px 15px 30px 0 $dialog-shadow-color;
border-radius: 4px;
border-radius: 8px;
overflow-y: auto;
}
@ -319,7 +318,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
}
.mx_Dialog_titleImage {
vertical-align: middle;
vertical-align: sub;
width: 25px;
height: 25px;
margin-left: -2px;
@ -335,6 +334,9 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
.mx_Dialog_header.mx_Dialog_headerWithButton > .mx_Dialog_title {
text-align: center;
}
.mx_Dialog_header.mx_Dialog_headerWithCancel > .mx_Dialog_title {
margin-right: 20px; // leave space for the 'X' cancel button
}
.mx_Dialog_title.danger {
color: $warning-color;
@ -425,12 +427,16 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
border-radius: 8px;
padding: 0px;
box-shadow: none;
/* Don't show scroll-bars on spinner dialogs */
overflow-x: hidden;
overflow-y: hidden;
}
// TODO: Review mx_GeneralButton usage to see if it can use a different class
// These classes were brought in from the old UserSettings and are included here to avoid
// breaking the app.
// Ref: https://github.com/vector-im/riot-web/issues/8420
// Ref: https://github.com/vector-im/element-web/issues/8420
.mx_GeneralButton {
@mixin mx_DialogButton;
display: inline;
@ -578,3 +584,36 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
// So it fits in the space provided by the page
max-width: 120px;
}
@define-mixin ProgressBarColour $colour {
color: $colour;
&::-moz-progress-bar {
background-color: $colour;
}
&::-webkit-progress-value {
background-color: $colour;
}
}
@define-mixin ProgressBarBorderRadius $radius {
border-radius: $radius;
&::-moz-progress-bar {
border-radius: $radius;
}
&::-webkit-progress-bar,
&::-webkit-progress-value {
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;
}
}

View file

@ -1,6 +1,7 @@
// autogenerated by rethemendex.sh
@import "./_common.scss";
@import "./_font-sizes.scss";
@import "./_font-weights.scss";
@import "./structures/_AutoHideScrollbar.scss";
@import "./structures/_CompatibilityPage.scss";
@import "./structures/_ContextualMenu.scss";
@ -15,19 +16,20 @@
@import "./structures/_MainSplit.scss";
@import "./structures/_MatrixChat.scss";
@import "./structures/_MyGroups.scss";
@import "./structures/_NonUrgentToastContainer.scss";
@import "./structures/_NotificationPanel.scss";
@import "./structures/_RightPanel.scss";
@import "./structures/_RoomDirectory.scss";
@import "./structures/_RoomSearch.scss";
@import "./structures/_RoomStatusBar.scss";
@import "./structures/_RoomSubList.scss";
@import "./structures/_RoomView.scss";
@import "./structures/_ScrollPanel.scss";
@import "./structures/_SearchBox.scss";
@import "./structures/_TabbedView.scss";
@import "./structures/_TagPanel.scss";
@import "./structures/_ToastContainer.scss";
@import "./structures/_TopLeftMenuButton.scss";
@import "./structures/_UploadBar.scss";
@import "./structures/_UserMenu.scss";
@import "./structures/_ViewSource.scss";
@import "./structures/auth/_CompleteSecurity.scss";
@import "./structures/auth/_Login.scss";
@ -41,11 +43,15 @@
@import "./views/auth/_CountryDropdown.scss";
@import "./views/auth/_InteractiveAuthEntryComponents.scss";
@import "./views/auth/_LanguageSelector.scss";
@import "./views/auth/_PassphraseField.scss";
@import "./views/auth/_ServerConfig.scss";
@import "./views/auth/_ServerTypeSelector.scss";
@import "./views/auth/_Welcome.scss";
@import "./views/avatars/_BaseAvatar.scss";
@import "./views/avatars/_DecoratedRoomAvatar.scss";
@import "./views/avatars/_MemberStatusMessageAvatar.scss";
@import "./views/avatars/_PulsedAvatar.scss";
@import "./views/context_menus/_IconizedContextMenu.scss";
@import "./views/context_menus/_MessageContextMenu.scss";
@import "./views/context_menus/_RoomTileContextMenu.scss";
@import "./views/context_menus/_StatusMessageContextMenu.scss";
@ -54,15 +60,14 @@
@import "./views/context_menus/_WidgetContextMenu.scss";
@import "./views/dialogs/_AddressPickerDialog.scss";
@import "./views/dialogs/_Analytics.scss";
@import "./views/dialogs/_BugReportDialog.scss";
@import "./views/dialogs/_ChangelogDialog.scss";
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
@import "./views/dialogs/_ConfirmUserActionDialog.scss";
@import "./views/dialogs/_CreateGroupDialog.scss";
@import "./views/dialogs/_CreateRoomDialog.scss";
@import "./views/dialogs/_DeactivateAccountDialog.scss";
@import "./views/dialogs/_DeviceVerifyDialog.scss";
@import "./views/dialogs/_DevtoolsDialog.scss";
@import "./views/dialogs/_EncryptedEventDialog.scss";
@import "./views/dialogs/_GroupAddressPicker.scss";
@import "./views/dialogs/_IncomingSasDialog.scss";
@import "./views/dialogs/_InviteDialog.scss";
@ -73,6 +78,7 @@
@import "./views/dialogs/_RoomSettingsDialogBridges.scss";
@import "./views/dialogs/_RoomUpgradeDialog.scss";
@import "./views/dialogs/_RoomUpgradeWarningDialog.scss";
@import "./views/dialogs/_ServerOfflineDialog.scss";
@import "./views/dialogs/_SetEmailDialog.scss";
@import "./views/dialogs/_SetMxIdDialog.scss";
@import "./views/dialogs/_SetPasswordDialog.scss";
@ -81,7 +87,6 @@
@import "./views/dialogs/_SlashCommandHelpDialog.scss";
@import "./views/dialogs/_TabbedIntegrationManagerDialog.scss";
@import "./views/dialogs/_TermsDialog.scss";
@import "./views/dialogs/_UnknownDeviceDialog.scss";
@import "./views/dialogs/_UploadConfirmDialog.scss";
@import "./views/dialogs/_UserSettingsDialog.scss";
@import "./views/dialogs/_WidgetOpenIDPermissionsDialog.scss";
@ -104,16 +109,19 @@
@import "./views/elements/_IconButton.scss";
@import "./views/elements/_ImageView.scss";
@import "./views/elements/_InlineSpinner.scss";
@import "./views/elements/_InteractiveTooltip.scss";
@import "./views/elements/_ManageIntegsButton.scss";
@import "./views/elements/_PowerSelector.scss";
@import "./views/elements/_ProgressBar.scss";
@import "./views/elements/_QRCode.scss";
@import "./views/elements/_ReplyThread.scss";
@import "./views/elements/_ResizeHandle.scss";
@import "./views/elements/_RichText.scss";
@import "./views/elements/_RoleButton.scss";
@import "./views/elements/_RoomAliasField.scss";
@import "./views/elements/_Slider.scss";
@import "./views/elements/_Spinner.scss";
@import "./views/elements/_StyledCheckbox.scss";
@import "./views/elements/_StyledRadioButton.scss";
@import "./views/elements/_SyntaxHighlight.scss";
@import "./views/elements/_TextWithTooltip.scss";
@import "./views/elements/_ToggleSwitch.scss";
@ -121,7 +129,6 @@
@import "./views/elements/_TooltipButton.scss";
@import "./views/elements/_Validation.scss";
@import "./views/emojipicker/_EmojiPicker.scss";
@import "./views/globals/_MatrixToolbar.scss";
@import "./views/groups/_GroupPublicityToggle.scss";
@import "./views/groups/_GroupRoomList.scss";
@import "./views/groups/_GroupUserSettings.scss";
@ -139,7 +146,7 @@
@import "./views/messages/_MjolnirBody.scss";
@import "./views/messages/_ReactionsRow.scss";
@import "./views/messages/_ReactionsRowButton.scss";
@import "./views/messages/_ReactionsRowButtonTooltip.scss";
@import "./views/messages/_RedactedBody.scss";
@import "./views/messages/_RoomAvatarEvent.scss";
@import "./views/messages/_SenderProfile.scss";
@import "./views/messages/_TextualEvent.scss";
@ -159,31 +166,31 @@
@import "./views/rooms/_EditMessageComposer.scss";
@import "./views/rooms/_EntityTile.scss";
@import "./views/rooms/_EventTile.scss";
@import "./views/rooms/_InviteOnlyIcon.scss";
@import "./views/rooms/_GroupLayout.scss";
@import "./views/rooms/_IRCLayout.scss";
@import "./views/rooms/_JumpToBottomButton.scss";
@import "./views/rooms/_LinkPreviewWidget.scss";
@import "./views/rooms/_MemberDeviceInfo.scss";
@import "./views/rooms/_MemberInfo.scss";
@import "./views/rooms/_MemberList.scss";
@import "./views/rooms/_MessageComposer.scss";
@import "./views/rooms/_MessageComposerFormatBar.scss";
@import "./views/rooms/_NotificationBadge.scss";
@import "./views/rooms/_PinnedEventTile.scss";
@import "./views/rooms/_PinnedEventsPanel.scss";
@import "./views/rooms/_PresenceLabel.scss";
@import "./views/rooms/_ReplyPreview.scss";
@import "./views/rooms/_RoomBreadcrumbs.scss";
@import "./views/rooms/_RoomDropTarget.scss";
@import "./views/rooms/_RoomHeader.scss";
@import "./views/rooms/_RoomList.scss";
@import "./views/rooms/_RoomPreviewBar.scss";
@import "./views/rooms/_RoomRecoveryReminder.scss";
@import "./views/rooms/_RoomSublist.scss";
@import "./views/rooms/_RoomTile.scss";
@import "./views/rooms/_RoomUpgradeWarningBar.scss";
@import "./views/rooms/_SearchBar.scss";
@import "./views/rooms/_SendMessageComposer.scss";
@import "./views/rooms/_Stickers.scss";
@import "./views/rooms/_TopUnreadMessagesBar.scss";
@import "./views/rooms/_UserOnlineDot.scss";
@import "./views/rooms/_WhoIsTypingTile.scss";
@import "./views/settings/_AvatarSetting.scss";
@import "./views/settings/_CrossSigningPanel.scss";
@ -197,10 +204,12 @@
@import "./views/settings/_ProfileSettings.scss";
@import "./views/settings/_SetIdServer.scss";
@import "./views/settings/_SetIntegrationManager.scss";
@import "./views/settings/_UpdateCheckButton.scss";
@import "./views/settings/tabs/_SettingsTab.scss";
@import "./views/settings/tabs/room/_GeneralRoomSettingsTab.scss";
@import "./views/settings/tabs/room/_RolesRoomSettingsTab.scss";
@import "./views/settings/tabs/room/_SecurityRoomSettingsTab.scss";
@import "./views/settings/tabs/user/_AppearanceUserSettingsTab.scss";
@import "./views/settings/tabs/user/_GeneralUserSettingsTab.scss";
@import "./views/settings/tabs/user/_HelpUserSettingsTab.scss";
@import "./views/settings/tabs/user/_MjolnirUserSettingsTab.scss";
@ -209,7 +218,8 @@
@import "./views/settings/tabs/user/_SecurityUserSettingsTab.scss";
@import "./views/settings/tabs/user/_VoiceUserSettingsTab.scss";
@import "./views/terms/_InlineTermsAgreement.scss";
@import "./views/toasts/_NonUrgentEchoFailureToast.scss";
@import "./views/verification/_VerificationShowSas.scss";
@import "./views/voip/_CallContainer.scss";
@import "./views/voip/_CallView.scss";
@import "./views/voip/_IncomingCallbox.scss";
@import "./views/voip/_VideoView.scss";

View file

@ -14,58 +14,60 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
$font-1px: 0.067rem;
$font-2px: 0.133rem;
$font-3px: 0.200rem;
$font-4px: 0.267rem;
$font-5px: 0.333rem;
$font-6px: 0.400rem;
$font-7px: 0.467rem;
$font-8px: 0.533rem;
$font-9px: 0.600rem;
$font-10px: 0.667rem;
$font-10-4px: 0.693rem;
$font-11px: 0.733rem;
$font-12px: 0.800rem;
$font-13px: 0.867rem;
$font-14px: 0.933rem;
$font-15px: 1.000rem;
$font-16px: 1.067rem;
$font-17px: 1.133rem;
$font-18px: 1.200rem;
$font-19px: 1.267rem;
$font-20px: 1.333rem;
$font-21px: 1.400rem;
$font-22px: 1.467rem;
$font-23px: 1.533rem;
$font-24px: 1.600rem;
$font-25px: 1.667rem;
$font-26px: 1.733rem;
$font-27px: 1.800rem;
$font-28px: 1.867rem;
$font-29px: 1.933rem;
$font-30px: 2.000rem;
$font-31px: 2.067rem;
$font-32px: 2.133rem;
$font-33px: 2.200rem;
$font-34px: 2.267rem;
$font-35px: 2.333rem;
$font-36px: 2.400rem;
$font-37px: 2.467rem;
$font-38px: 2.533rem;
$font-39px: 2.600rem;
$font-40px: 2.667rem;
$font-41px: 2.733rem;
$font-42px: 2.800rem;
$font-43px: 2.867rem;
$font-44px: 2.933rem;
$font-45px: 3.000rem;
$font-46px: 3.067rem;
$font-47px: 3.133rem;
$font-48px: 3.200rem;
$font-49px: 3.267rem;
$font-50px: 3.333rem;
$font-51px: 3.400rem;
$font-52px: 3.467rem;
$font-88px: 5.887rem;
$font-400px: 26.667rem;
$font-1px: 0.1rem;
$font-1-5px: 0.15rem;
$font-2px: 0.2rem;
$font-3px: 0.3rem;
$font-4px: 0.4rem;
$font-5px: 0.5rem;
$font-6px: 0.6rem;
$font-7px: 0.7rem;
$font-8px: 0.8rem;
$font-9px: 0.9rem;
$font-10px: 1.0rem;
$font-10-4px: 1.04rem;
$font-11px: 1.1rem;
$font-12px: 1.2rem;
$font-13px: 1.3rem;
$font-14px: 1.4rem;
$font-15px: 1.5rem;
$font-16px: 1.6rem;
$font-17px: 1.7rem;
$font-18px: 1.8rem;
$font-19px: 1.9rem;
$font-20px: 2.0rem;
$font-21px: 2.1rem;
$font-22px: 2.2rem;
$font-23px: 2.3rem;
$font-24px: 2.4rem;
$font-25px: 2.5rem;
$font-26px: 2.6rem;
$font-27px: 2.7rem;
$font-28px: 2.8rem;
$font-29px: 2.9rem;
$font-30px: 3.0rem;
$font-31px: 3.1rem;
$font-32px: 3.2rem;
$font-33px: 3.3rem;
$font-34px: 3.4rem;
$font-35px: 3.5rem;
$font-36px: 3.6rem;
$font-37px: 3.7rem;
$font-38px: 3.8rem;
$font-39px: 3.9rem;
$font-40px: 4.0rem;
$font-41px: 4.1rem;
$font-42px: 4.2rem;
$font-43px: 4.3rem;
$font-44px: 4.4rem;
$font-45px: 4.5rem;
$font-46px: 4.6rem;
$font-47px: 4.7rem;
$font-48px: 4.8rem;
$font-49px: 4.9rem;
$font-50px: 5.0rem;
$font-51px: 5.1rem;
$font-52px: 5.2rem;
$font-78px: 7.8rem;
$font-88px: 8.8rem;
$font-400px: 40rem;

View file

@ -0,0 +1,17 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
$font-semi-bold: 600;

View file

@ -31,7 +31,7 @@ limitations under the License.
}
.mx_ContextualMenu {
border-radius: 4px;
border-radius: 8px;
box-shadow: 4px 4px 12px 0 $menu-box-shadow-color;
background-color: $menu-bg-color;
color: $primary-fg-color;

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// TODO: Update design for custom tags to match new designs
.mx_LeftPanel_tagPanelContainer {
display: flex;
flex-direction: column;
@ -50,7 +52,7 @@ limitations under the License.
background-color: $accent-color-alt;
width: 5px;
position: absolute;
left: -15px;
left: -9px;
border-radius: 0 3px 3px 0;
top: 2px; // 10 [padding-top] - (56 - 40)/2
top: 5px; // just feels right (see comment above about designs needing to be updated)
}

View file

@ -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;
}
@ -109,3 +115,7 @@ limitations under the License.
.mx_FilePanel .mx_EventTile:hover .mx_EventTile_line {
background-color: $primary-bg-color;
}
.mx_FilePanel_empty::before {
mask-image: url('$(res)/img/element-icons/room/files.svg');
}

View file

@ -29,12 +29,12 @@ limitations under the License.
align-items: center;
display: flex;
padding-bottom: 10px;
padding-left: 19px;
}
.mx_GroupView_header_view {
border-bottom: 1px solid $primary-hairline-color;
padding-bottom: 0px;
padding-left: 19px;
padding-right: 8px;
}
@ -63,11 +63,11 @@ limitations under the License.
}
.mx_GroupHeader_editButton::before {
mask-image: url('$(res)/img/feather-customised/settings.svg');
mask-image: url('$(res)/img/element-icons/settings.svg');
}
.mx_GroupHeader_shareButton::before {
mask-image: url('$(res)/img/icons-share.svg');
mask-image: url('$(res)/img/element-icons/room/share.svg');
}
.mx_GroupView_hostingSignup img {
@ -182,6 +182,7 @@ limitations under the License.
.mx_GroupView_body {
flex-grow: 1;
margin: 0 24px;
}
.mx_GroupView_rooms {
@ -250,6 +251,7 @@ limitations under the License.
.mx_GroupView_membershipSubSection {
justify-content: space-between;
display: flex;
padding-bottom: 8px;
}
.mx_GroupView_membershipSubSection .mx_Spinner {

View file

@ -22,7 +22,7 @@ limitations under the License.
content: "";
background-color: $header-divider-color;
opacity: 0.5;
margin: 0 15px;
margin: 6px 8px;
border-radius: 1px;
width: 1px;
}

View file

@ -72,7 +72,7 @@ limitations under the License.
&:hover {
color: $accent-color;
background: rgba(#03b381, 0.06);
background: rgba($accent-color, 0.06);
&::before {
background-color: $accent-color;

View file

@ -1,6 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -15,163 +14,182 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_LeftPanel_container {
display: flex;
/* LeftPanel 260px */
min-width: 260px;
flex: 0 0 auto;
}
.mx_LeftPanel_container.collapsed {
min-width: unset;
/* Collapsed LeftPanel 50px */
flex: 0 0 50px;
}
.mx_LeftPanel_container.collapsed.mx_LeftPanel_container_hasTagPanel {
/* TagPanel 70px + Collapsed LeftPanel 50px */
flex: 0 0 120px;
}
.mx_LeftPanel_tagPanelContainer {
flex: 0 0 70px;
height: 100%;
}
.mx_LeftPanel_hideButton {
position: absolute;
top: 10px;
right: 0px;
padding: 8px;
cursor: pointer;
}
$tagPanelWidth: 56px; // only applies in this file, used for calculations
.mx_LeftPanel {
flex: 1;
overflow-x: hidden;
background-color: $roomlist-bg-color;
min-width: 260px;
max-width: 50%;
// Create a row-based flexbox for the TagPanel and the room list
display: flex;
.mx_LeftPanel_tagPanelContainer {
flex-grow: 0;
flex-shrink: 0;
flex-basis: $tagPanelWidth;
height: 100%;
// Create another flexbox so the TagPanel fills the container
display: flex;
// TagPanel handles its own CSS
}
&:not(.mx_LeftPanel_hasTagPanel) {
.mx_LeftPanel_roomListContainer {
width: 100%;
}
}
// Note: The 'room list' in this context is actually everything that isn't the tag
// panel, such as the menu options, breadcrumbs, filtering, etc
.mx_LeftPanel_roomListContainer {
width: calc(100% - $tagPanelWidth);
background-color: $roomlist-bg-color;
// Create another flexbox (this time a column) for the room list components
display: flex;
flex-direction: column;
min-height: 0;
}
.mx_LeftPanel .mx_AppTile_mini {
height: 132px;
}
.mx_LeftPanel_userHeader {
/* 12px top, 12px sides, 20px bottom (using 13px bottom to account
* for internal whitespace in the breadcrumbs)
*/
padding: 12px;
flex-shrink: 0; // to convince safari's layout engine the flexbox is fine
.mx_LeftPanel .mx_RoomList_scrollbar {
order: 1;
flex: 1 1 0;
overflow-y: auto;
z-index: 6;
}
.mx_LeftPanel .mx_BottomLeftMenu {
order: 3;
border-top: 1px solid $panel-divider-color;
margin-left: 16px; /* gutter */
margin-right: 16px; /* gutter */
flex: 0 0 60px;
z-index: 1;
}
.mx_LeftPanel_container.collapsed .mx_BottomLeftMenu {
flex: 0 0 160px;
margin-bottom: 9px;
}
.mx_LeftPanel .mx_BottomLeftMenu_options {
margin-top: 18px;
}
.mx_BottomLeftMenu_options object {
pointer-events: none;
}
.mx_BottomLeftMenu_options > div {
display: inline-block;
}
.mx_BottomLeftMenu_options .mx_RoleButton {
margin-left: 0px;
margin-right: 10px;
height: 30px;
}
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings {
float: right;
}
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton {
margin-right: 0px;
}
.mx_LeftPanel_container.collapsed .mx_BottomLeftMenu_settings {
float: none;
}
.mx_MatrixChat_useCompactLayout {
.mx_LeftPanel .mx_BottomLeftMenu {
flex: 0 0 50px;
}
.mx_LeftPanel_container.collapsed .mx_BottomLeftMenu {
flex: 0 0 160px;
}
.mx_LeftPanel .mx_BottomLeftMenu_options {
margin-top: 12px;
}
}
.mx_LeftPanel_exploreAndFilterRow {
// Create another flexbox column for the rows to stack within
display: flex;
.mx_SearchBox {
flex: 1 1 0;
min-width: 0;
margin: 4px 9px 1px 9px;
flex-direction: column;
}
}
.mx_LeftPanel_explore {
flex: 0 0 50%;
overflow: hidden;
transition: flex-basis 0.2s;
box-sizing: border-box;
.mx_LeftPanel_breadcrumbsContainer {
overflow-y: hidden;
overflow-x: scroll;
margin: 12px 12px 0 12px;
flex: 0 0 auto;
// Create yet another flexbox, this time within the row, to ensure items stay
// aligned correctly. This is also a row-based flexbox.
display: flex;
align-items: center;
&.mx_LeftPanel_explore_hidden {
&.mx_IndicatorScrollbar_leftOverflow {
mask-image: linear-gradient(90deg, transparent, black 5%);
}
&.mx_IndicatorScrollbar_rightOverflow {
mask-image: linear-gradient(90deg, black, black 95%, transparent);
}
&.mx_IndicatorScrollbar_rightOverflow.mx_IndicatorScrollbar_leftOverflow {
mask-image: linear-gradient(90deg, transparent, black 5%, black 95%, transparent);
}
}
.mx_LeftPanel_filterContainer {
margin-left: 12px;
margin-right: 12px;
flex-shrink: 0; // to convince safari's layout engine the flexbox is fine
// Create a flexbox to organize the inputs
display: flex;
align-items: center;
.mx_RoomSearch_focused, .mx_RoomSearch_hasQuery {
& + .mx_LeftPanel_exploreButton {
// Cheaty way to return the occupied space to the filter input
flex-basis: 0;
margin: 0;
width: 0;
// Don't forget to hide the masked ::before icon,
// using display:none or visibility:hidden would break accessibility
&::before {
content: none;
}
}
}
.mx_AccessibleButton {
font-size: $font-14px;
margin: 4px 0 1px 9px;
padding: 9px;
padding-left: 42px;
font-weight: 600;
color: $notice-secondary-color;
.mx_LeftPanel_exploreButton {
width: 32px;
height: 32px;
border-radius: 8px;
background-color: $roomlist-button-bg-color;
position: relative;
border-radius: 4px;
&:hover {
background-color: $primary-bg-color;
}
margin-left: 8px;
&::before {
cursor: pointer;
mask: url('$(res)/img/explore.svg');
mask-repeat: no-repeat;
mask-position: center center;
content: "";
left: 14px;
top: 10px;
content: '';
position: absolute;
top: 8px;
left: 8px;
width: 16px;
height: 16px;
background-color: $notice-secondary-color;
position: absolute;
mask-image: url('$(res)/img/element-icons/roomlist/explore.svg');
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $secondary-fg-color;
}
}
}
.mx_LeftPanel_roomListFilterCount {
font-size: $font-13px;
font-weight: $font-semi-bold;
margin-left: 12px;
margin-top: 14px;
margin-bottom: -4px; // to counteract the normal roomListWrapper margin-top
}
.mx_LeftPanel_roomListWrapper {
overflow: hidden;
margin-top: 10px; // so we're not up against the search/filter
flex: 1 0 0; // needed in Safari to properly set flex-basis
&.mx_LeftPanel_roomListWrapper_stickyBottom {
padding-bottom: 32px;
}
&.mx_LeftPanel_roomListWrapper_stickyTop {
padding-top: 32px;
}
}
.mx_LeftPanel_actualRoomListContainer {
position: relative; // for sticky headers
height: 100%; // ensure scrolling still works
}
}
// These styles override the defaults for the minimized (66px) layout
&.mx_LeftPanel_minimized {
min-width: unset;
// We have to forcefully set the width to override the resizer's style attribute.
&.mx_LeftPanel_hasTagPanel {
width: calc(68px + $tagPanelWidth) !important;
}
&:not(.mx_LeftPanel_hasTagPanel) {
width: 68px !important;
}
.mx_LeftPanel_roomListContainer {
width: 68px;
.mx_LeftPanel_filterContainer {
// Organize the flexbox into a centered column layout
flex-direction: column;
justify-content: center;
.mx_LeftPanel_exploreButton {
margin-left: 0;
margin-top: 8px;
background-color: transparent;
}
}
}
}
}

View file

@ -21,8 +21,22 @@ limitations under the License.
height: 100%;
}
// move hit area 5px to the right so it doesn't overlap with the timeline scrollbar
.mx_MainSplit > .mx_ResizeHandle.mx_ResizeHandle_horizontal {
margin: 0 -10px 0 0;
padding: 0 10px 0 0;
.mx_MainSplit > .mx_RightPanel_ResizeWrapper {
padding: 5px;
// margin left to not allow the handle to not encroach on the space for the scrollbar
margin-left: 8px;
&:hover .mx_RightPanel_ResizeHandle {
// Need to use important to override element style attributes
// set by re-resizable
top: 50% !important;
transform: translate(0, -50%);
height: 64px !important; // to match width of the ones on roomlist
width: 4px !important;
border-radius: 4px !important;
background-color: $primary-fg-color;
opacity: 0.8;
}
}

View file

@ -41,10 +41,6 @@ limitations under the License.
height: 40px;
}
.mx_MatrixChat_toolbarShowing {
height: auto;
}
.mx_MatrixChat {
width: 100%;
height: 100%;
@ -70,15 +66,36 @@ limitations under the License.
}
/* not the left panel, and not the resize handle, so the roomview/groupview/... */
.mx_MatrixChat > :not(.mx_LeftPanel_container):not(.mx_ResizeHandle) {
.mx_MatrixChat > :not(.mx_LeftPanel):not(.mx_ResizeHandle) {
background-color: $primary-bg-color;
flex: 1 1 0;
min-width: 0;
/* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari
/* To fix https://github.com/vector-im/element-web/issues/3298 where Safari
needed height 100% all the way down to the HomePage. Height does not
have to be auto, empirically.
*/
height: 100%;
}
.mx_MatrixChat > .mx_LeftPanel2:hover + .mx_ResizeHandle_horizontal,
.mx_MatrixChat > .mx_ResizeHandle_horizontal:hover {
position: relative;
&::before {
position: absolute;
left: 6px;
top: 50%;
transform: translate(0, -50%);
height: 64px; // to match width of the ones on roomlist
width: 4px;
border-radius: 4px;
content: ' ';
background-color: $primary-fg-color;
opacity: 0.8;
}
}

View file

@ -0,0 +1,35 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_NonUrgentToastContainer {
position: absolute;
bottom: 30px;
left: 28px;
z-index: 101; // same level as other toasts
.mx_NonUrgentToastContainer_toast {
padding: 10px 12px;
border-radius: 8px;
width: 320px;
font-size: $font-13px;
margin-top: 8px;
// We don't use variables on the colours because we want it to be the same
// in all themes.
background-color: #17191c;
color: #fff;
}
}

View file

@ -63,6 +63,10 @@ limitations under the License.
padding-left: 32px;
padding-top: 8px;
position: relative;
a {
display: flex;
}
}
.mx_NotificationPanel .mx_EventTile_roomName a,
@ -95,3 +99,7 @@ limitations under the License.
.mx_NotificationPanel .mx_EventTile_content {
margin-right: 0px;
}
.mx_NotificationPanel_empty::before {
mask-image: url('$(res)/img/element-icons/notifications.svg');
}

View file

@ -19,9 +19,16 @@ limitations under the License.
overflow-x: hidden;
flex: 0 0 auto;
position: relative;
min-width: 264px;
display: flex;
flex-direction: column;
border-radius: 8px;
padding: 4px 0;
box-sizing: border-box;
height: 100%;
.mx_RoomView_MessageList {
padding: 14px 18px; // top and bottom is 4px smaller to balance with the padding set above
}
}
.mx_RightPanel_header {
@ -43,56 +50,67 @@ limitations under the License.
.mx_RightPanel_headerButton {
cursor: pointer;
flex: 0 0 auto;
vertical-align: top;
margin-left: 5px;
margin-right: 5px;
text-align: center;
border-bottom: 2px solid transparent;
height: 20px;
width: 20px;
margin-left: 1px;
margin-right: 1px;
height: 32px;
width: 32px;
position: relative;
border-radius: 100%;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 20px;
width: 20px;
background-color: $rightpanel-button-color;
top: 4px; // center with parent of 32px
left: 4px; // center with parent of 32px
height: 24px;
width: 24px;
background-color: $icon-button-color;
mask-repeat: no-repeat;
mask-size: contain;
}
}
.mx_RightPanel_membersButton::before {
mask-image: url('$(res)/img/feather-customised/user.svg');
mask-image: url('$(res)/img/element-icons/room/members.svg');
mask-position: center;
}
.mx_RightPanel_filesButton::before {
mask-image: url('$(res)/img/feather-customised/files.svg');
mask-image: url('$(res)/img/element-icons/room/files.svg');
mask-position: center;
}
.mx_RightPanel_notifsButton::before {
mask-image: url('$(res)/img/feather-customised/notifications.svg');
mask-image: url('$(res)/img/element-icons/notifications.svg');
mask-position: center;
}
.mx_RightPanel_groupMembersButton::before {
mask-image: url('$(res)/img/icons-people.svg');
mask-image: url('$(res)/img/element-icons/community-members.svg');
mask-position: center;
}
.mx_RightPanel_roomsButton::before {
mask-image: url('$(res)/img/icons-room-nobg.svg');
mask-image: url('$(res)/img/element-icons/community-rooms.svg');
mask-position: center;
}
.mx_RightPanel_headerButton_highlight::after {
content: '';
position: absolute;
bottom: -6px;
left: 0;
right: 0;
height: 2px;
background-color: $button-bg-color;
.mx_RightPanel_headerButton_highlight {
background: rgba($accent-color, 0.25);
// make the icon the accent color too
&::before {
background-color: $accent-color !important;
}
}
.mx_RightPanel_headerButton:not(.mx_RightPanel_headerButton_highlight) {
&:hover {
background: rgba($accent-color, 0.1);
&::before {
background-color: $accent-color;
}
}
}
.mx_RightPanel_headerButton_badge {
@ -126,3 +144,28 @@ limitations under the License.
order: 2;
margin: auto;
}
.mx_RightPanel_empty {
margin-right: -42px;
h2 {
font-weight: 700;
margin: 16px 0;
}
h2, p {
font-size: $font-14px;
}
&::before {
content: '';
display: block;
margin: 11px auto 29px auto;
height: 42px;
width: 42px;
background-color: $rightpanel-button-color;
mask-repeat: no-repeat;
mask-size: contain;
mask-position: center;
}
}

View file

@ -0,0 +1,94 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Note: this component expects to be contained within a flexbox
.mx_RoomSearch {
flex: 1;
border-radius: 8px;
background-color: $roomlist-button-bg-color;
// keep border thickness consistent to prevent movement
border: 1px solid transparent;
height: 28px;
padding: 2px;
// Create a flexbox for the icons (easier to manage)
display: flex;
align-items: center;
.mx_RoomSearch_icon {
width: 16px;
height: 16px;
mask: url('$(res)/img/element-icons/roomlist/search.svg');
mask-repeat: no-repeat;
background-color: $secondary-fg-color;
margin-left: 7px;
}
.mx_RoomSearch_input {
border: none !important; // !important to override default app-wide styles
flex: 1 !important; // !important to override default app-wide styles
color: $primary-fg-color !important; // !important to override default app-wide styles
padding: 0;
height: 100%;
width: 100%;
font-size: $font-12px;
line-height: $font-16px;
&:not(.mx_RoomSearch_inputExpanded)::placeholder {
color: $tertiary-fg-color !important; // !important to override default app-wide styles
}
}
&.mx_RoomSearch_hasQuery {
border-color: $secondary-fg-color;
}
&.mx_RoomSearch_focused {
box-shadow: 0 0 4px 4px rgba(0, 132, 255, 0.5);
border-color: transparent;
}
&.mx_RoomSearch_focused, &.mx_RoomSearch_hasQuery {
background-color: $roomlist-filter-active-bg-color;
.mx_RoomSearch_clearButton {
width: 16px;
height: 16px;
mask-image: url('$(res)/img/element-icons/roomlist/search-clear.svg');
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background-color: $secondary-fg-color;
margin-right: 8px;
}
}
.mx_RoomSearch_clearButton {
width: 0;
height: 0;
}
&.mx_RoomSearch_minimized {
border-radius: 32px;
height: auto;
width: auto;
padding: 8px;
.mx_RoomSearch_icon {
margin-left: 0;
}
}
}

View file

@ -1,187 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* a word of explanation about the flex-shrink values employed here:
there are 3 priotized categories of screen real-estate grabbing,
each with a flex-shrink difference of 4 order of magnitude,
so they ideally wouldn't affect each other.
lowest category: .mx_RoomSubList
flex-shrink: 10000000
distribute size of items within the same category by their size
middle category: .mx_RoomSubList.resized-sized
flex-shrink: 1000
applied when using the resizer, will have a max-height set to it,
to limit the size
highest category: .mx_RoomSubList.resized-all
flex-shrink: 1
small flex-shrink value (1), is only added if you can drag the resizer so far
so in practice you can only assign this category if there is enough space.
*/
.mx_RoomSubList {
display: flex;
flex-direction: column;
}
.mx_RoomSubList_nonEmpty .mx_AutoHideScrollbar_offset {
padding-bottom: 4px;
}
.mx_RoomSubList_labelContainer {
display: flex;
flex-direction: row;
align-items: center;
flex: 0 0 auto;
margin: 0 8px;
padding: 0 8px;
height: 36px;
}
.mx_RoomSubList_labelContainer.focus-visible:focus-within {
background-color: $roomtile-focused-bg-color;
}
.mx_RoomSubList_label {
flex: 1;
cursor: pointer;
display: flex;
align-items: center;
padding: 0 6px;
}
.mx_RoomSubList_label > span {
flex: 1 1 auto;
text-transform: uppercase;
color: $roomsublist-label-fg-color;
font-weight: 700;
font-size: $font-12px;
margin-left: 8px;
}
.mx_RoomSubList_badge > div {
flex: 0 0 auto;
border-radius: $font-16px;
font-weight: 600;
font-size: $font-12px;
padding: 0 5px;
color: $roomtile-badge-fg-color;
background-color: $roomtile-name-color;
cursor: pointer;
}
.mx_RoomSubList_addRoom, .mx_RoomSubList_badge {
margin-left: 7px;
}
.mx_RoomSubList_addRoom {
background-color: $roomheader-addroom-bg-color;
border-radius: 10px; // 16/2 + 2 padding
height: 16px;
flex: 0 0 16px;
position: relative;
&::before {
background-color: $roomheader-addroom-fg-color;
mask: url('$(res)/img/icons-room-add.svg');
mask-repeat: no-repeat;
mask-position: center;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
}
.mx_RoomSubList_badgeHighlight > div {
color: $accent-fg-color;
background-color: $warning-color;
}
.mx_RoomSubList_chevron {
pointer-events: none;
mask: url('$(res)/img/feather-customised/dropdown-arrow.svg');
mask-repeat: no-repeat;
transition: transform 0.2s ease-in;
width: 10px;
height: 6px;
margin-left: 2px;
background-color: $roomsublist-label-fg-color;
}
.mx_RoomSubList_chevronDown {
transform: rotateZ(0deg);
}
.mx_RoomSubList_chevronUp {
transform: rotateZ(180deg);
}
.mx_RoomSubList_chevronRight {
transform: rotateZ(-90deg);
}
.mx_RoomSubList_scroll {
/* let rooms list grab as much space as it needs (auto),
potentially overflowing and showing a scrollbar */
flex: 0 1 auto;
padding: 0 8px;
}
.collapsed {
.mx_RoomSubList_scroll {
padding: 0;
}
.mx_RoomSubList_labelContainer {
margin-right: 8px;
margin-left: 2px;
padding: 0;
}
.mx_RoomSubList_addRoom {
margin-left: 3px;
margin-right: 10px;
}
.mx_RoomSubList_label > span {
display: none;
}
}
// overflow indicators
.mx_RoomSubList:not(.resized-all) > .mx_RoomSubList_scroll {
&.mx_IndicatorScrollbar_topOverflow::before {
position: sticky;
content: "";
top: 0;
left: 0;
right: 0;
height: 8px;
z-index: 100;
display: block;
pointer-events: none;
transition: background-image 0.1s ease-in;
background: linear-gradient(to top, $panel-gradient);
}
&.mx_IndicatorScrollbar_topOverflow {
margin-top: -8px;
}
}

View file

@ -261,7 +261,7 @@ hr.mx_RoomView_myReadMarker {
.mx_RoomView_voipButton {
float: right;
margin-right: 13px;
margin-top: 10px;
margin-top: 13px;
cursor: pointer;
}

View file

@ -33,7 +33,7 @@ limitations under the License.
.mx_TagPanel .mx_TagPanel_clearButton_container {
/* Constant height within flex mx_TagPanel */
height: 70px;
width: 60px;
width: 56px;
flex: none;
@ -51,7 +51,7 @@ limitations under the License.
.mx_TagPanel .mx_TagPanel_divider {
height: 0px;
width: 42px;
width: 34px;
border-bottom: 1px solid $panel-divider-color;
display: none;
}
@ -66,15 +66,13 @@ limitations under the License.
flex-direction: column;
align-items: center;
height: 100%;
padding-top: 6px;
}
.mx_TagPanel .mx_TagPanel_tagTileContainer > div {
height: $font-40px;
padding: 10px 0 9px 0;
margin: 6px 0;
}
.mx_TagPanel .mx_TagTile {
margin: 9px 0;
// opacity: 0.5;
position: relative;
}
@ -86,8 +84,8 @@ limitations under the License.
.mx_TagPanel .mx_TagTile_plus {
margin-bottom: 12px;
height: 40px;
width: 40px;
height: 32px;
width: 32px;
border-radius: 20px;
background-color: $roomheader-addroom-bg-color;
position: relative;
@ -110,13 +108,12 @@ limitations under the License.
.mx_TagPanel .mx_TagTile.mx_TagTile_selected::before {
content: '';
height: calc(100% + 16px);
height: 100%;
background-color: $accent-color;
width: 5px;
width: 4px;
position: absolute;
left: -15px;
left: -12px;
border-radius: 0 3px 3px 0;
top: -8px; // (16px / 2)
}
.mx_TagPanel .mx_TagTile.mx_AccessibleButton:focus {
@ -159,7 +156,7 @@ limitations under the License.
font-weight: 600;
font-size: $font-14px;
padding: 0 5px;
background-color: $roomtile-name-color;
background-color: $muted-fg-color;
}
.mx_TagTile_badgeHighlight {

View file

@ -28,8 +28,8 @@ limitations under the License.
margin: 0 4px;
grid-row: 2 / 4;
grid-column: 1;
background-color: white;
box-shadow: 0px 4px 12px $menu-box-shadow-color;
background-color: $dark-panel-bg-color;
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.5);
border-radius: 8px;
}
@ -37,26 +37,28 @@ limitations under the License.
grid-row: 1 / 3;
grid-column: 1;
color: $primary-fg-color;
background-color: $primary-bg-color;
box-shadow: 0px 4px 12px $menu-box-shadow-color;
background-color: $dark-panel-bg-color;
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.5);
border-radius: 8px;
overflow: hidden;
display: grid;
grid-template-columns: 20px 1fr;
column-gap: 10px;
grid-template-columns: 22px 1fr;
column-gap: 8px;
row-gap: 4px;
padding: 8px;
padding-right: 16px;
&.mx_Toast_hasIcon {
&::after {
&::before, &::after {
content: "";
width: 22px;
height: 22px;
grid-column: 1;
grid-row: 1;
mask-size: 100%;
mask-position: center;
mask-repeat: no-repeat;
background-size: 100%;
background-repeat: no-repeat;
}
&.mx_Toast_icon_verification::after {
@ -64,14 +66,40 @@ limitations under the License.
background-color: $primary-fg-color;
}
&.mx_Toast_icon_verification_warning::after {
background-image: url("$(res)/img/e2e/warning.svg");
&.mx_Toast_icon_verification_warning {
// white infill for the hollow svg mask
&::before {
background-color: #ffffff;
mask-image: url('$(res)/img/e2e/normal.svg');
mask-size: 90%;
}
h2, .mx_Toast_body {
&::after {
mask-image: url("$(res)/img/e2e/warning.svg");
background-color: $notice-primary-color;
}
}
.mx_Toast_title, .mx_Toast_body {
grid-column: 2;
}
}
&:not(.mx_Toast_hasIcon) {
padding-left: 12px;
.mx_Toast_title {
grid-column: 1 / -1;
}
}
.mx_Toast_title,
.mx_Toast_description {
padding-right: 8px;
}
.mx_Toast_title {
width: 100%;
box-sizing: border-box;
h2 {
grid-column: 1 / 3;
@ -79,6 +107,18 @@ limitations under the License.
margin: 0;
font-size: $font-15px;
font-weight: 600;
display: inline;
width: auto;
vertical-align: middle;
}
span {
padding-left: 8px;
float: right;
font-size: $font-12px;
line-height: $font-22px;
color: $muted-fg-color;
}
}
.mx_Toast_body {
@ -87,7 +127,13 @@ limitations under the License.
}
.mx_Toast_buttons {
float: right;
display: flex;
.mx_FormButton {
min-width: 96px;
box-sizing: border-box;
}
}
.mx_Toast_description {
@ -96,6 +142,15 @@ limitations under the License.
text-overflow: ellipsis;
margin: 4px 0 11px 0;
font-size: $font-12px;
.mx_AccessibleButton_kind_link {
font-size: inherit;
padding: 0;
}
a {
text-decoration: none;
}
}
.mx_Toast_deviceID {

View file

@ -1,49 +0,0 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_TopLeftMenuButton {
flex: 0 0 52px;
border-bottom: 1px solid $panel-divider-color;
color: $topleftmenu-color;
background-color: $primary-bg-color;
display: flex;
align-items: center;
min-width: 0;
padding: 0 4px;
overflow: hidden;
}
.mx_TopLeftMenuButton .mx_BaseAvatar {
margin: 0 7px;
}
.mx_TopLeftMenuButton_name {
margin: 0 7px;
font-size: $font-18px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-weight: 600;
}
.mx_TopLeftMenuButton_chevron {
margin: 0 7px;
mask: url('$(res)/img/feather-customised/dropdown-arrow.svg');
mask-repeat: no-repeat;
width: 10px;
height: 6px;
background-color: $roomsublist-label-fg-color;
}

View file

@ -0,0 +1,196 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_UserMenu {
// to make the ... button sort of aligned with the explore button below
padding-right: 6px;
.mx_UserMenu_headerButtons {
width: 16px;
height: 16px;
position: relative;
display: block;
&::before {
content: '';
width: 16px;
height: 16px;
position: absolute;
top: 0;
left: 0;
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $primary-fg-color;
mask-image: url('$(res)/img/element-icons/context-menu.svg');
}
}
.mx_UserMenu_row {
// Create a row-based flexbox to ensure items stay aligned correctly.
display: flex;
align-items: center;
.mx_UserMenu_userAvatarContainer {
position: relative; // to make default avatars work
margin-right: 8px;
height: 32px; // to remove the unknown 4px gap the browser puts below it
.mx_UserMenu_userAvatar {
border-radius: 32px; // should match avatar size
object-fit: cover;
}
}
.mx_UserMenu_userName {
font-weight: 600;
font-size: $font-15px;
line-height: $font-20px;
flex: 1;
// Ellipsize any text overflow
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.mx_UserMenu_headerButtons {
// No special styles: the rest of the layout happens to make it work.
}
}
&.mx_UserMenu_minimized {
.mx_UserMenu_userHeader {
.mx_UserMenu_row {
justify-content: center;
}
.mx_UserMenu_userAvatarContainer {
margin-right: 0;
}
}
}
}
.mx_UserMenu_contextMenu {
width: 247px;
&.mx_IconizedContextMenu .mx_IconizedContextMenu_optionList_red {
.mx_AccessibleButton {
padding-top: 16px;
padding-bottom: 16px;
}
}
.mx_UserMenu_contextMenu_header {
padding: 20px;
// Create a flexbox to organize the header a bit easier
display: flex;
align-items: center;
.mx_UserMenu_contextMenu_name {
// Create another flexbox of columns to handle large user IDs
display: flex;
flex-direction: column;
width: calc(100% - 40px); // 40px = 32px theme button + 8px margin to theme button
* {
// Automatically grow all subelements to fit the container
flex: 1;
width: 100%;
// Ellipsize any text overflow
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.mx_UserMenu_contextMenu_displayName {
font-weight: bold;
font-size: $font-15px;
line-height: $font-20px;
}
.mx_UserMenu_contextMenu_userId {
font-size: $font-15px;
line-height: $font-24px;
}
}
.mx_UserMenu_contextMenu_themeButton {
min-width: 32px;
max-width: 32px;
width: 32px;
height: 32px;
margin-left: 8px;
border-radius: 32px;
background-color: $theme-button-bg-color;
cursor: pointer;
// to make alignment easier, create flexbox for the image
display: flex;
align-items: center;
justify-content: center;
}
}
.mx_IconizedContextMenu_icon {
width: 16px;
height: 16px;
display: block;
&::before {
content: '';
width: 16px;
height: 16px;
display: block;
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $primary-fg-color;
}
}
.mx_UserMenu_iconHome::before {
mask-image: url('$(res)/img/element-icons/roomlist/home.svg');
}
.mx_UserMenu_iconBell::before {
mask-image: url('$(res)/img/element-icons/notifications.svg');
}
.mx_UserMenu_iconLock::before {
mask-image: url('$(res)/img/element-icons/security.svg');
}
.mx_UserMenu_iconSettings::before {
mask-image: url('$(res)/img/element-icons/settings.svg');
}
.mx_UserMenu_iconArchive::before {
mask-image: url('$(res)/img/element-icons/roomlist/archived.svg');
}
.mx_UserMenu_iconMessage::before {
mask-image: url('$(res)/img/element-icons/roomlist/feedback.svg');
}
.mx_UserMenu_iconSignOut::before {
mask-image: url('$(res)/img/element-icons/leave.svg');
}
}

View file

@ -128,6 +128,11 @@ limitations under the License.
margin-top: 16px;
font-size: $font-15px;
line-height: $font-24px;
.mx_InlineSpinner img {
vertical-align: sub;
margin-right: 5px;
}
}
.mx_AuthBody_paddedFooter_subtitle {
@ -147,26 +152,11 @@ limitations under the License.
margin: 1em 0;
}
.mx_AuthBody_passwordScore {
width: 100%;
appearance: none;
height: 4px;
border: 0;
border-radius: 2px;
position: absolute;
top: -12px;
&::-moz-progress-bar {
border-radius: 2px;
background-color: $accent-color;
}
&::-webkit-progress-bar,
&::-webkit-progress-value {
border-radius: 2px;
}
&::-webkit-progress-value {
background-color: $accent-color;
@media only screen and (max-width: 480px) {
.mx_AuthBody {
border-radius: 4px;
width: auto;
max-width: 500px;
padding: 10px;
}
}

View file

@ -21,3 +21,9 @@ limitations under the License.
padding: 25px 40px;
box-sizing: border-box;
}
@media only screen and (max-width: 480px) {
.mx_AuthHeader {
display: none;
}
}

View file

@ -23,3 +23,9 @@ limitations under the License.
.mx_AuthHeaderLogo img {
width: 100%;
}
@media only screen and (max-width: 480px) {
.mx_AuthHeaderLogo {
display: none;
}
}

View file

@ -29,3 +29,9 @@ limitations under the License.
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.33);
background-color: $authpage-modal-bg-color;
}
@media only screen and (max-width: 480px) {
.mx_AuthPage_modal {
margin-top: 0;
}
}

View file

@ -0,0 +1,37 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
$PassphraseStrengthHigh: $accent-color;
$PassphraseStrengthMedium: $username-variant5-color;
$PassphraseStrengthLow: $notice-primary-color;
progress.mx_PassphraseField_progress {
appearance: none;
width: 100%;
border: 0;
height: 4px;
position: absolute;
top: -12px;
@mixin ProgressBarBorderRadius "2px";
@mixin ProgressBarColour $PassphraseStrengthLow;
&[value="2"], &[value="3"] {
@mixin ProgressBarColour $PassphraseStrengthMedium;
}
&[value="4"] {
@mixin ProgressBarColour $PassphraseStrengthHigh;
}
}

View file

@ -22,7 +22,7 @@ limitations under the License.
// different results during full reflow of the page vs. incremental reflow
// of small portions. While that's surely a browser bug, we can avoid it by
// using `inline-block` instead of the default `inline`.
// https://github.com/vector-im/riot-web/issues/5594
// https://github.com/vector-im/element-web/issues/5594
// https://bugzilla.mozilla.org/show_bug.cgi?id=1535053
// https://bugzilla.mozilla.org/show_bug.cgi?id=255139
display: inline-block;

View file

@ -0,0 +1,73 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// XXX: We shouldn't be using TemporaryTile anywhere - delete it.
.mx_DecoratedRoomAvatar, .mx_TemporaryTile {
position: relative;
&.mx_DecoratedRoomAvatar_cutout .mx_BaseAvatar {
mask-image: url('$(res)/img/element-icons/roomlist/decorated-avatar-mask.svg');
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
}
.mx_DecoratedRoomAvatar_icon {
position: absolute;
bottom: -2px;
right: -2px;
margin: 4px;
width: 8px;
height: 8px;
border-radius: 50%;
}
.mx_DecoratedRoomAvatar_icon::before {
content: '';
width: 8px;
height: 8px;
position: absolute;
border-radius: 8px;
}
.mx_DecoratedRoomAvatar_icon_globe::before {
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $secondary-fg-color;
mask-image: url('$(res)/img/globe.svg');
}
.mx_DecoratedRoomAvatar_icon_offline::before {
background-color: $presence-offline;
}
.mx_DecoratedRoomAvatar_icon_online::before {
background-color: $presence-online;
}
.mx_DecoratedRoomAvatar_icon_away::before {
background-color: $presence-away;
}
.mx_NotificationBadge, .mx_RoomTile_badgeContainer {
position: absolute;
top: 0;
right: 0;
height: 18px;
width: 18px;
}
}

View file

@ -0,0 +1,30 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_PulsedAvatar {
@keyframes shadow-pulse {
0% {
box-shadow: 0 0 0 0px rgba($accent-color, 0.2);
}
100% {
box-shadow: 0 0 0 6px rgba($accent-color, 0);
}
}
img {
animation: shadow-pulse 1s infinite;
}
}

View file

@ -0,0 +1,148 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// A context menu that largely fits the | [icon] [label] | format.
.mx_IconizedContextMenu {
min-width: 146px;
.mx_IconizedContextMenu_optionList {
& > * {
padding-left: 20px;
padding-right: 20px;
}
// the notFirst class is for cases where the optionList might be under a header of sorts.
&:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst {
// 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
// around the problem. PostCSS doesn't support the opacity() function, and if we
// use something like postcss-functions we quickly run into an issue where the
// function we would define gets passed a CSS variable for custom themes, which
// can't be converted easily even when considering https://stackoverflow.com/a/41265350/7037379
//
// Therefore, we just hack in a line and border the thing ourselves
&::before {
border-top: 1px solid $primary-fg-color;
opacity: 0.1;
content: '';
// Counteract the padding problems (width: 100% ignores the 40px padding,
// unless we position it absolutely then it does the right thing).
width: 100%;
position: absolute;
left: 0;
}
}
// round the top corners of the top button for the hover effect to be bounded
&:first-child .mx_AccessibleButton:first-child {
border-radius: 8px 8px 0 0; // radius matches .mx_ContextualMenu
}
// 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 8px 8px; // radius matches .mx_ContextualMenu
}
.mx_AccessibleButton {
// pad the inside of the button so that the hover background is padded too
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;
}
img, .mx_IconizedContextMenu_icon { // icons
width: 16px;
min-width: 16px;
max-width: 16px;
}
span.mx_IconizedContextMenu_label { // labels
padding-left: 14px;
width: 100%;
flex: 1;
// Ellipsize any text overflow
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
.mx_IconizedContextMenu_icon {
position: relative;
width: 16px;
height: 16px;
&::before {
content: '';
width: 16px;
height: 16px;
position: absolute;
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $primary-fg-color;
}
}
.mx_IconizedContextMenu_optionList_red {
.mx_AccessibleButton {
color: $warning-color !important;
}
.mx_IconizedContextMenu_icon::before {
background-color: $warning-color;
}
}
.mx_IconizedContextMenu_active {
&.mx_AccessibleButton, .mx_AccessibleButton {
color: $accent-color !important;
}
.mx_IconizedContextMenu_icon::before {
background-color: $accent-color;
}
}
&.mx_IconizedContextMenu_compact {
.mx_IconizedContextMenu_optionList > * {
padding: 8px 16px 8px 11px;
}
}
.mx_IconizedContextMenu_checked {
margin-left: 16px;
margin-right: -5px;
&::before {
mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg');
}
}
}

View file

@ -15,9 +15,8 @@ limitations under the License.
*/
.mx_TagTileContextMenu_item {
padding-top: 8px;
padding: 8px;
padding-right: 20px;
padding-bottom: 8px;
cursor: pointer;
white-space: nowrap;
display: flex;
@ -25,15 +24,22 @@ limitations under the License.
line-height: $font-16px;
}
.mx_TagTileContextMenu_item object {
pointer-events: none;
.mx_TagTileContextMenu_item::before {
content: '';
height: 15px;
width: 15px;
background-color: currentColor;
mask-repeat: no-repeat;
mask-size: contain;
margin-right: 8px;
}
.mx_TagTileContextMenu_viewCommunity::before {
mask-image: url('$(res)/img/element-icons/view-community.svg');
}
.mx_TagTileContextMenu_item_icon {
padding-right: 8px;
padding-left: 4px;
display: inline-block;
.mx_TagTileContextMenu_hideCommunity::before {
mask-image: url('$(res)/img/element-icons/hide.svg');
}
.mx_TagTileContextMenu_separator {

View file

@ -0,0 +1,23 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_BugReportDialog {
.mx_BugReportDialog_download {
.mx_AccessibleButton_kind_link {
padding-left: 0;
}
}
}

View file

@ -18,8 +18,3 @@ limitations under the License.
margin-top: 10px;
display: flex;
}
.mx_GroupAddressPicker_checkboxContainer input[type="checkbox"] {
/* Stop flex from shrinking the checkbox */
width: 20px;
}

View file

@ -18,19 +18,19 @@ limitations under the License.
// ==========================================================
.mx_RoomSettingsDialog_settingsIcon::before {
mask-image: url('$(res)/img/feather-customised/settings.svg');
mask-image: url('$(res)/img/element-icons/settings.svg');
}
.mx_RoomSettingsDialog_securityIcon::before {
mask-image: url('$(res)/img/feather-customised/lock.svg');
mask-image: url('$(res)/img/element-icons/security.svg');
}
.mx_RoomSettingsDialog_rolesIcon::before {
mask-image: url('$(res)/img/feather-customised/users-sm.svg');
mask-image: url('$(res)/img/element-icons/room/settings/roles.svg');
}
.mx_RoomSettingsDialog_notificationsIcon::before {
mask-image: url('$(res)/img/feather-customised/notifications.svg');
mask-image: url('$(res)/img/element-icons/notifications.svg');
}
.mx_RoomSettingsDialog_bridgesIcon::before {
@ -39,7 +39,7 @@ limitations under the License.
}
.mx_RoomSettingsDialog_warningIcon::before {
mask-image: url('$(res)/img/feather-customised/warning-triangle.svg');
mask-image: url('$(res)/img/element-icons/room/settings/advanced.svg');
}
.mx_RoomSettingsDialog .mx_Dialog_title {

View file

@ -0,0 +1,72 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_ServerOfflineDialog {
.mx_ServerOfflineDialog_content {
padding-right: 85px;
color: $primary-fg-color;
hr {
border-color: $primary-fg-color;
opacity: 0.1;
border-bottom: none;
}
ul {
padding: 16px;
li:nth-child(n + 2) {
margin-top: 16px;
}
}
.mx_ServerOfflineDialog_content_context {
.mx_ServerOfflineDialog_content_context_timestamp {
display: inline-block;
width: 115px;
color: $muted-fg-color;
line-height: 24px; // same as avatar
vertical-align: top;
}
.mx_ServerOfflineDialog_content_context_timeline {
display: inline-block;
width: calc(100% - 155px); // 115px timestamp width + 40px right margin
.mx_ServerOfflineDialog_content_context_timeline_header {
span {
margin-left: 8px;
vertical-align: middle;
}
}
.mx_ServerOfflineDialog_content_context_txn {
position: relative;
margin-top: 8px;
.mx_ServerOfflineDialog_content_context_txn_desc {
width: calc(100% - 100px); // 100px is an arbitrary margin for the button
}
.mx_AccessibleButton {
float: right;
padding: 0;
}
}
}
}
}
}

View file

@ -51,10 +51,12 @@ 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;
background-repeat: no-repeat;
}
.mx_ShareDialog_split {
@ -64,9 +66,6 @@ limitations under the License.
.mx_ShareDialog_qrcode_container {
float: left;
background-color: #ffffff;
padding: 5px; // makes qr code more readable in dark theme
border-radius: 5px;
height: 256px;
width: 256px;
margin-right: 64px;

View file

@ -1,48 +0,0 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_UnknownDeviceDialog {
height: 100%;
display: flex;
flex-direction: column;
}
.mx_UnknownDeviceDialog ul {
list-style: none;
padding: 0;
}
// userid
.mx_UnknownDeviceDialog p {
font-weight: bold;
font-size: $font-16px;
}
.mx_UnknownDeviceDialog .mx_DeviceVerifyButtons {
flex-direction: row !important;
}
.mx_UnknownDeviceDialog .mx_Dialog_content {
margin-bottom: 24px;
overflow-y: scroll;
}
.mx_UnknownDeviceDialog_deviceList > li {
padding: 4px;
}
.mx_UnknownDeviceDialog_deviceList > li > * {
padding-bottom: 0;
}

View file

@ -18,37 +18,41 @@ limitations under the License.
// ==========================================================
.mx_UserSettingsDialog_settingsIcon::before {
mask-image: url('$(res)/img/feather-customised/settings.svg');
mask-image: url('$(res)/img/element-icons/settings.svg');
}
.mx_UserSettingsDialog_appearanceIcon::before {
mask-image: url('$(res)/img/element-icons/settings/appearance.svg');
}
.mx_UserSettingsDialog_voiceIcon::before {
mask-image: url('$(res)/img/feather-customised/phone.svg');
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
}
.mx_UserSettingsDialog_bellIcon::before {
mask-image: url('$(res)/img/feather-customised/notifications.svg');
mask-image: url('$(res)/img/element-icons/notifications.svg');
}
.mx_UserSettingsDialog_preferencesIcon::before {
mask-image: url('$(res)/img/feather-customised/sliders.svg');
mask-image: url('$(res)/img/element-icons/settings/preference.svg');
}
.mx_UserSettingsDialog_securityIcon::before {
mask-image: url('$(res)/img/feather-customised/lock.svg');
mask-image: url('$(res)/img/element-icons/security.svg');
}
.mx_UserSettingsDialog_helpIcon::before {
mask-image: url('$(res)/img/feather-customised/help-circle.svg');
mask-image: url('$(res)/img/element-icons/settings/help.svg');
}
.mx_UserSettingsDialog_labsIcon::before {
mask-image: url('$(res)/img/feather-customised/flag.svg');
mask-image: url('$(res)/img/element-icons/settings/lab-flags.svg');
}
.mx_UserSettingsDialog_mjolnirIcon::before {
mask-image: url('$(res)/img/feather-customised/face.svg');
mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg');
}
.mx_UserSettingsDialog_flairIcon::before {
mask-image: url('$(res)/img/feather-customised/flair.svg');
mask-image: url('$(res)/img/element-icons/settings/flair.svg');
}

View file

@ -35,17 +35,6 @@ limitations under the License.
align-items: flex-start;
}
.mx_CreateKeyBackupDialog_passPhraseHelp {
flex: 1;
height: 85px;
margin-left: 20px;
font-size: 80%;
}
.mx_CreateKeyBackupDialog_passPhraseHelp progress {
width: 100%;
}
.mx_CreateKeyBackupDialog_passPhraseInput {
flex: none;
width: 250px;

View file

@ -15,20 +15,79 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_AccessSecretStorageDialog_titleWithIcon::before {
content: '';
display: inline-block;
width: 24px;
height: 24px;
margin-right: 8px;
position: relative;
top: 5px;
background-color: $primary-fg-color;
}
.mx_AccessSecretStorageDialog_secureBackupTitle::before {
mask-image: url('$(res)/img/feather-customised/secure-backup.svg');
}
.mx_AccessSecretStorageDialog_securePhraseTitle::before {
mask-image: url('$(res)/img/feather-customised/secure-phrase.svg');
}
.mx_AccessSecretStorageDialog_keyStatus {
height: 30px;
}
.mx_AccessSecretStorageDialog_primaryContainer {
/* FIXME: plinth colour in new theme(s). background-color: $accent-color; */
padding: 20px;
}
.mx_AccessSecretStorageDialog_passPhraseInput,
.mx_AccessSecretStorageDialog_recoveryKeyInput {
.mx_AccessSecretStorageDialog_passPhraseInput {
width: 300px;
border: 1px solid $accent-color;
border-radius: 5px;
padding: 10px;
}
.mx_AccessSecretStorageDialog_recoveryKeyEntry {
display: flex;
align-items: center;
}
.mx_AccessSecretStorageDialog_recoveryKeyEntry_textInput {
flex-grow: 1;
}
.mx_AccessSecretStorageDialog_recoveryKeyEntry_entryControlSeparatorText {
margin: 16px;
}
.mx_AccessSecretStorageDialog_recoveryKeyFeedback {
&::before {
content: "";
display: inline-block;
vertical-align: bottom;
width: 20px;
height: 20px;
mask-repeat: no-repeat;
mask-position: center;
mask-size: 20px;
margin-right: 5px;
}
}
.mx_AccessSecretStorageDialog_recoveryKeyFeedback_valid {
color: $input-valid-border-color;
&::before {
mask-image: url('$(res)/img/feather-customised/check.svg');
background-color: $input-valid-border-color;
}
}
.mx_AccessSecretStorageDialog_recoveryKeyFeedback_invalid {
color: $input-invalid-border-color;
&::before {
mask-image: url('$(res)/img/feather-customised/x.svg');
background-color: $input-invalid-border-color;
}
}
.mx_AccessSecretStorageDialog_recoveryKeyEntry_fileInput {
display: none;
}

View file

@ -48,6 +48,29 @@ limitations under the License.
margin-bottom: 1em;
}
.mx_CreateSecretStorageDialog_titleWithIcon::before {
content: '';
display: inline-block;
width: 24px;
height: 24px;
margin-right: 8px;
position: relative;
top: 5px;
background-color: $primary-fg-color;
}
.mx_CreateSecretStorageDialog_secureBackupTitle::before {
mask-image: url('$(res)/img/feather-customised/secure-backup.svg');
}
.mx_CreateSecretStorageDialog_securePhraseTitle::before {
mask-image: url('$(res)/img/feather-customised/secure-phrase.svg');
}
.mx_CreateSecretStorageDialog_centeredTitle, .mx_CreateSecretStorageDialog_centeredBody {
text-align: center;
}
.mx_CreateSecretStorageDialog_primaryContainer {
/* FIXME: plinth colour in new theme(s). background-color: $accent-color; */
padding-top: 20px;
@ -59,6 +82,36 @@ limitations under the License.
display: block;
}
.mx_CreateSecretStorageDialog_primaryContainer .mx_RadioButton {
margin-bottom: 16px;
padding: 11px;
}
.mx_CreateSecretStorageDialog_optionTitle {
color: $dialog-title-fg-color;
font-weight: 600;
font-size: $font-18px;
padding-bottom: 10px;
}
.mx_CreateSecretStorageDialog_optionIcon {
display: inline-block;
width: 24px;
height: 24px;
margin-right: 8px;
position: relative;
top: 5px;
background-color: $primary-fg-color;
}
.mx_CreateSecretStorageDialog_optionIcon_securePhrase {
mask-image: url('$(res)/img/feather-customised/secure-phrase.svg');
}
.mx_CreateSecretStorageDialog_optionIcon_secureBackup {
mask-image: url('$(res)/img/feather-customised/secure-backup.svg');
}
.mx_CreateSecretStorageDialog_passPhraseContainer {
display: flex;
align-items: flex-start;
@ -68,49 +121,47 @@ limitations under the License.
margin-top: 0px;
}
.mx_CreateSecretStorageDialog_passPhraseHelp {
flex: 1;
height: 64px;
margin-left: 20px;
font-size: 80%;
}
.mx_CreateSecretStorageDialog_passPhraseHelp progress {
width: 100%;
}
.mx_CreateSecretStorageDialog_passPhraseMatch {
width: 200px;
margin-left: 20px;
}
.mx_CreateSecretStorageDialog_recoveryKeyHeader {
margin-bottom: 1em;
}
.mx_CreateSecretStorageDialog_recoveryKeyContainer {
display: flex;
width: 380px;
margin-left: auto;
margin-right: auto;
}
.mx_CreateSecretStorageDialog_recoveryKey {
width: 262px;
font-weight: bold;
text-align: center;
padding: 20px;
color: $info-plinth-fg-color;
background-color: $info-plinth-bg-color;
margin-right: 12px;
border-radius: 6px;
word-spacing: 1em;
margin-bottom: 20px;
}
.mx_CreateSecretStorageDialog_recoveryKeyButtons {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
}
.mx_CreateSecretStorageDialog_recoveryKeyButtons .mx_AccessibleButton {
margin-right: 10px;
}
.mx_CreateSecretStorageDialog_recoveryKeyButtons button {
flex: 1;
width: 160px;
padding-left: 0px;
padding-right: 0px;
white-space: nowrap;
}
.mx_CreateSecretStorageDialog_continueSpinner {
margin-top: 33px;
text-align: right;
}
.mx_CreateSecretStorageDialog_continueSpinner img {
width: 20px;
height: 20px;
}

View file

@ -145,13 +145,14 @@ limitations under the License.
&::after {
content: "";
position: absolute;
width: 24px;
height: 24px;
right: -28px; // - (24 + 4)
width: 26px;
height: 26px;
right: -27.5px; // - (width: 26 + spacing to align with X above: 1.5)
top: -3px;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
mask-image: url('$(res)/img/feather-customised/chevron-down-thin.svg');
background-color: $primary-fg-color;
}

View file

@ -23,6 +23,7 @@ limitations under the License.
border-radius: 3px;
border: solid 1px $accent-color;
cursor: pointer;
z-index: 1;
}
.mx_AddressSelector.mx_AddressSelector_empty {

View file

@ -77,12 +77,18 @@ limitations under the License.
white-space: nowrap;
}
.mx_Dropdown_option img {
.mx_Dropdown_option img,
.mx_Dropdown_option .mx_Dropdown_option_emoji {
margin: 5px;
width: 16px;
vertical-align: middle;
}
.mx_Dropdown_option_emoji {
font-size: $font-16px;
line-height: $font-16px;
}
input.mx_Dropdown_option,
input.mx_Dropdown_option:focus {
font-weight: normal;

View file

@ -191,5 +191,5 @@ limitations under the License.
}
.mx_Field .mx_CountryDropdown {
width: 67px;
width: $font-78px;
}

View file

@ -37,7 +37,7 @@ limitations under the License.
order: 2;
/* min-width hack needed for FF */
min-width: 0px;
max-height: 90%;
height: 90%;
flex: 15 15 0;
display: flex;
align-items: center;

View file

@ -18,7 +18,7 @@ limitations under the License.
display: inline;
}
.mx_InlineSpinner img {
.mx_InlineSpinner_spin img {
margin: 0px 6px;
vertical-align: -3px;
}

View file

@ -1,91 +0,0 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_InteractiveTooltip_wrapper {
position: fixed;
z-index: 5000;
}
.mx_InteractiveTooltip {
border-radius: 3px;
background-color: $interactive-tooltip-bg-color;
color: $interactive-tooltip-fg-color;
position: absolute;
font-size: $font-10px;
font-weight: 600;
padding: 6px;
z-index: 5001;
}
.mx_InteractiveTooltip.mx_InteractiveTooltip_withChevron_top {
top: 10px; // 8px chevron + 2px spacing
}
.mx_InteractiveTooltip_chevron_top {
position: absolute;
left: calc(50% - 8px);
top: -8px;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-bottom: 8px solid $interactive-tooltip-bg-color;
border-right: 8px solid transparent;
}
// Adapted from https://codyhouse.co/blog/post/css-rounded-triangles-with-clip-path
// by Sebastiano Guerriero (@guerriero_se)
@supports (clip-path: polygon(0% 0%, 100% 100%, 0% 100%)) {
.mx_InteractiveTooltip_chevron_top {
height: 16px;
width: 16px;
background-color: inherit;
border: none;
clip-path: polygon(0% 0%, 100% 100%, 0% 100%);
transform: rotate(135deg);
border-radius: 0 0 0 3px;
top: calc(-8px / 1.414); // sqrt(2) because of rotation
}
}
.mx_InteractiveTooltip.mx_InteractiveTooltip_withChevron_bottom {
bottom: 10px; // 8px chevron + 2px spacing
}
.mx_InteractiveTooltip_chevron_bottom {
position: absolute;
left: calc(50% - 8px);
bottom: -8px;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-top: 8px solid $interactive-tooltip-bg-color;
border-right: 8px solid transparent;
}
// Adapted from https://codyhouse.co/blog/post/css-rounded-triangles-with-clip-path
// by Sebastiano Guerriero (@guerriero_se)
@supports (clip-path: polygon(0% 0%, 100% 100%, 0% 100%)) {
.mx_InteractiveTooltip_chevron_bottom {
height: 16px;
width: 16px;
background-color: inherit;
border: none;
clip-path: polygon(0% 0%, 100% 100%, 0% 100%);
transform: rotate(-45deg);
border-radius: 0 0 0 3px;
bottom: calc(-8px / 1.414); // sqrt(2) because of rotation
}
}

View file

@ -1,5 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,12 +14,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_ProgressBar {
height: 5px;
border: 1px solid $progressbar-color;
}
progress.mx_ProgressBar {
height: 4px;
width: 60px;
border-radius: 10px;
overflow: hidden;
appearance: none;
border: 0;
.mx_ProgressBar_fill {
height: 100%;
background-color: $progressbar-color;
@mixin ProgressBarBorderRadius "10px";
@mixin ProgressBarColour $accent-color;
::-webkit-progress-value {
transition: width 1s;
}
::-moz-progress-bar {
transition: padding-bottom 1s;
padding-bottom: var(--value);
transform-origin: 0 0;
transform: rotate(-90deg) translateX(-15px);
padding-left: 15px;
height: 0;
}
}

View file

@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// converts a pixel value to rem.
export default function(pixelVal) {
return pixelVal / 15 + "rem";
.mx_QRCode {
img {
border-radius: 8px;
}
}

View file

@ -34,7 +34,7 @@ limitations under the License.
.mx_MatrixChat > .mx_ResizeHandle.mx_ResizeHandle_horizontal {
margin: 0 -10px 0 0;
padding: 0 10px 0 0;
padding: 0 8px 0 0;
}
.mx_ResizeHandle > div {

View file

@ -0,0 +1,99 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_Slider {
position: relative;
margin: 0px;
flex-grow: 1;
}
.mx_Slider_dotContainer {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.mx_Slider_bar {
display: flex;
box-sizing: border-box;
position: absolute;
height: 1em;
width: 100%;
padding: 0 0.5em; // half the width of a dot.
align-items: center;
}
.mx_Slider_bar > hr {
width: 100%;
height: 0.4em;
background-color: $slider-background-color;
border: 0;
}
.mx_Slider_selection {
display: flex;
align-items: center;
width: calc(100% - 1em); // 2 * half the width of a dot
height: 1em;
position: absolute;
pointer-events: none;
}
.mx_Slider_selectionDot {
position: absolute;
width: 1.1em;
height: 1.1em;
background-color: $slider-selection-color;
border-radius: 50%;
box-shadow: 0 0 6px lightgrey;
z-index: 10;
}
.mx_Slider_selection > hr {
margin: 0;
border: 0.2em solid $slider-selection-color;
}
.mx_Slider_dot {
height: 1em;
width: 1em;
border-radius: 50%;
background-color: $slider-background-color;
z-index: 0;
}
.mx_Slider_dotActive {
background-color: $slider-selection-color;
}
.mx_Slider_dotValue {
display: flex;
flex-direction: column;
align-items: center;
color: $slider-background-color;
}
// The following is a hack to center the labels without adding
// any width to the slider's dots.
.mx_Slider_labelContainer {
width: 1em;
}
.mx_Slider_label {
position: relative;
width: fit-content;
left: -50%;
}

View file

@ -0,0 +1,90 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_Checkbox {
$size: $font-16px;
$border-size: $font-1-5px;
$border-radius: $font-4px;
display: flex;
align-items: flex-start;
input[type=checkbox] {
appearance: none;
margin: 0;
padding: 0;
& + label {
display: flex;
align-items: center;
flex-grow: 1;
}
& + label > .mx_Checkbox_background {
display: inline-flex;
position: relative;
flex-shrink: 0;
height: $size;
width: $size;
size: 0.5rem;
border: $border-size solid rgba($muted-fg-color, 0.5);
box-sizing: border-box;
border-radius: $border-radius;
img {
display: none;
height: 100%;
width: 100%;
filter: invert(100%);
}
}
&:checked + label > .mx_Checkbox_background {
background: $accent-color;
border-color: $accent-color;
img {
display: block;
}
}
& + label > *:not(.mx_Checkbox_background) {
margin-left: 10px;
}
&:disabled + label {
opacity: 0.5;
cursor: not-allowed;
}
&:checked:disabled + label > .mx_Checkbox_background {
background-color: $accent-color;
border-color: $accent-color;
}
&.focus-visible {
& + label .mx_Checkbox_background {
@mixin unreal-focus;
}
}
}
}

View file

@ -0,0 +1,124 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* This component expects the parent to specify a positive padding and
* width
*/
.mx_RadioButton {
$radio-circle-color: $muted-fg-color;
$active-radio-circle-color: $accent-color;
position: relative;
display: flex;
align-items: baseline;
flex-grow: 1;
> .mx_RadioButton_content {
flex-grow: 1;
display: flex;
flex-direction: column;
margin-left: 8px;
margin-right: 8px;
}
.mx_RadioButton_spacer {
flex-shrink: 0;
flex-grow: 0;
height: $font-16px;
width: $font-16px;
}
> input[type=radio] {
// Remove the OS's representation
margin: 0;
padding: 0;
appearance: none;
+ div {
flex-shrink: 0;
flex-grow: 0;
display: flex;
align-items: center;
justify-content: center;
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;
> div {
box-sizing: border-box;
height: $font-8px;
width: $font-8px;
border-radius: $font-8px;
}
}
&.focus-visible {
& + div {
@mixin unreal-focus;
}
}
&:checked {
& + div {
border-color: $active-radio-circle-color;
& > div {
background: $active-radio-circle-color;
}
}
}
&:disabled {
& + div,
& + div + span {
opacity: 0.5;
cursor: not-allowed;
}
& + div {
border-color: $radio-circle-color;
}
}
&:checked:disabled {
& + div > div {
background-color: $radio-circle-color;
}
}
}
}
.mx_RadioButton_outlined {
border: 1px solid $input-darker-bg-color;
border-radius: 8px;
}
.mx_RadioButton_checked {
border-color: $accent-color;
}

View file

@ -24,11 +24,6 @@ limitations under the License.
background-color: $togglesw-off-color;
opacity: 0.5;
display: flex;
flex-direction: row;
flex: 0 0 auto;
align-items: center;
}
.mx_ToggleSwitch_enabled {
@ -38,16 +33,18 @@ limitations under the License.
.mx_ToggleSwitch.mx_ToggleSwitch_on {
background-color: $togglesw-on-color;
> .mx_ToggleSwitch_ball {
left: calc(100% - $font-20px);
}
}
.mx_ToggleSwitch_ball {
transition: left 0.15s ease-out 0.1s;
position: relative;
width: $font-20px;
height: $font-20px;
border-radius: $font-20px;
background-color: $togglesw-ball-color;
}
.mx_ToggleSwitch_on {
flex-direction: row-reverse;
transition: left 0.15s ease-out 0.1s;
left: 0;
}

View file

@ -51,21 +51,27 @@ limitations under the License.
.mx_Tooltip {
display: none;
position: fixed;
border: 1px solid $menu-border-color;
border-radius: 4px;
border-radius: 8px;
box-shadow: 4px 4px 12px 0 $menu-box-shadow-color;
background-color: $menu-bg-color;
z-index: 4000; // Higher than dialogs so tooltips can be used in dialogs
z-index: 6000; // Higher than context menu so tooltips can be used everywhere
padding: 10px;
pointer-events: none;
line-height: $font-14px;
font-size: $font-12px;
font-weight: 600;
color: $primary-fg-color;
font-weight: 500;
max-width: 200px;
word-break: break-word;
margin-right: 50px;
background-color: $inverted-bg-color;
color: $accent-fg-color;
border: 0;
text-align: center;
.mx_Tooltip_chevron {
display: none;
}
&.mx_Tooltip_visible {
animation: mx_fadein 0.2s forwards;
}
@ -75,18 +81,23 @@ limitations under the License.
}
}
.mx_Tooltip_timeline {
box-shadow: none;
background-color: $tooltip-timeline-bg-color;
color: $tooltip-timeline-fg-color;
text-align: center;
border: none;
border-radius: 3px;
font-size: $font-14px;
line-height: 1.2;
padding: 6px 8px;
// These tooltips use an older style with a chevron
.mx_Field_tooltip {
background-color: $menu-bg-color;
color: $primary-fg-color;
border: 1px solid $menu-border-color;
text-align: unset;
.mx_Tooltip_chevron::after {
border-right-color: $tooltip-timeline-bg-color;
.mx_Tooltip_chevron {
display: unset;
}
}
.mx_Tooltip_title {
font-weight: 600;
}
.mx_Tooltip_sub {
opacity: 0.7;
margin-top: 4px;
}

View file

@ -190,7 +190,7 @@ limitations under the License.
.mx_EmojiPicker_footer {
border-top: 1px solid $message-action-bar-border-color;
height: 72px;
min-height: 72px;
display: flex;
align-items: center;

View file

@ -1,73 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_MatrixToolbar {
background-color: $accent-color;
color: $accent-fg-color;
display: flex;
align-items: center;
}
.mx_MatrixToolbar_warning {
margin-left: 16px;
margin-right: 8px;
margin-top: -2px;
}
.mx_MatrixToolbar_info {
padding-left: 16px;
padding-right: 8px;
background-color: $info-bg-color;
}
.mx_MatrixToolbar_error {
padding-left: 16px;
padding-right: 8px;
background-color: $warning-bg-color;
}
.mx_MatrixToolbar_content {
flex: 1;
}
.mx_MatrixToolbar_link {
color: $accent-fg-color !important;
text-decoration: underline !important;
cursor: pointer;
}
.mx_MatrixToolbar_clickable {
cursor: pointer;
}
.mx_MatrixToolbar_close {
cursor: pointer;
}
.mx_MatrixToolbar_close img {
display: block;
float: right;
margin-right: 10px;
}
.mx_MatrixToolbar_action {
margin-right: 16px;
}
.mx_MatrixToolbar_changelog {
white-space: pre;
}

View file

@ -25,6 +25,7 @@ limitations under the License.
height: 100%;
left: 0;
top: 0;
border-radius: 4px;
}
.mx_MImageBody_thumbnail_container {

View file

@ -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.
@ -41,7 +41,7 @@ limitations under the License.
width: calc(10px + 48px + 100% + 8px);
// safe area + action bar
height: calc(20px + 100%);
top: -20px;
top: -12px;
left: -58px;
z-index: -1;
cursor: initial;
@ -91,17 +91,17 @@ limitations under the License.
}
.mx_MessageActionBar_reactButton::after {
mask-image: url('$(res)/img/react.svg');
mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg');
}
.mx_MessageActionBar_replyButton::after {
mask-image: url('$(res)/img/reply.svg');
mask-image: url('$(res)/img/element-icons/room/message-bar/reply.svg');
}
.mx_MessageActionBar_editButton::after {
mask-image: url('$(res)/img/edit.svg');
mask-image: url('$(res)/img/element-icons/room/message-bar/edit.svg');
}
.mx_MessageActionBar_optionsButton::after {
mask-image: url('$(res)/img/icon_context.svg');
mask-image: url('$(res)/img/element-icons/context-menu.svg');
}

View file

@ -17,4 +17,5 @@ limitations under the License.
.mx_MessageTimestamp {
color: $event-timestamp-color;
font-size: $font-10px;
font-variant-numeric: tabular-nums;
}

View file

@ -16,7 +16,6 @@ limitations under the License.
.mx_ReactionsRowButton {
display: inline-flex;
height: 20px;
line-height: $font-21px;
margin-right: 6px;
padding: 0 6px;
@ -35,11 +34,6 @@ limitations under the License.
border-color: $reaction-row-button-selected-border-color;
}
// ignore mouse events for all children, treat it as one entire hoverable entity
* {
pointer-events: none;
}
.mx_ReactionsRowButton_content {
max-width: 100px;
overflow: hidden;

View file

@ -0,0 +1,36 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_RedactedBody {
white-space: pre-wrap;
color: $muted-fg-color;
vertical-align: middle;
padding-left: 20px;
position: relative;
&::before {
height: 14px;
width: 14px;
background-color: $muted-fg-color;
mask-image: url('$(res)/img/feather-customised/trash.custom.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
content: '';
position: absolute;
top: 2px;
left: 0;
}
}

View file

@ -15,28 +15,45 @@ limitations under the License.
*/
.mx_cryptoEvent {
display: grid;
grid-template-columns: 24px minmax(0, 1fr) min-content;
&.mx_cryptoEvent_icon::before,
&.mx_cryptoEvent_icon::after {
grid-column: 1;
grid-row: 1 / 3;
width: 16px;
height: 16px;
content: "";
background-image: url("$(res)/img/e2e/normal.svg");
background-repeat: no-repeat;
background-size: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
mask-image: url('$(res)/img/e2e/normal.svg');
background-color: $composer-e2e-icon-color;
margin-top: 4px;
}
// white infill for the transparency
&.mx_cryptoEvent_icon::before {
background-color: #ffffff;
mask-image: url('$(res)/img/e2e/normal.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: 90%;
}
&.mx_cryptoEvent_icon_verified::after {
background-image: url("$(res)/img/e2e/verified.svg");
mask-image: url("$(res)/img/e2e/verified.svg");
background-color: $accent-color;
}
&.mx_cryptoEvent_icon_warning::after {
background-image: url("$(res)/img/e2e/warning.svg");
mask-image: url("$(res)/img/e2e/warning.svg");
background-color: $notice-primary-color;
}
.mx_cryptoEvent_title, .mx_cryptoEvent_subtitle, .mx_cryptoEvent_state {

View file

@ -53,7 +53,7 @@ limitations under the License.
}
.mx_UserInfo_separator {
border-bottom: 1px solid lightgray;
border-bottom: 1px solid rgba($primary-fg-color, .1);
}
.mx_UserInfo_memberDetailsContainer {
@ -121,7 +121,7 @@ limitations under the License.
h3 {
text-transform: uppercase;
color: $notice-secondary-color;
font-weight: bold;
font-weight: 600;
font-size: $font-12px;
margin: 4px 0;
}

View file

@ -49,7 +49,7 @@ $MiniAppTileHeight: 114px;
order: 2;
cursor: pointer;
padding: 0;
margin: 5px auto 5px 0px;
margin: 5px auto 5px 0;
color: $accent-color;
font-size: $font-12px;
}
@ -87,7 +87,7 @@ $MiniAppTileHeight: 114px;
margin: 0;
padding: 0;
border: 5px solid $widget-menu-bar-bg-color;
border-radius: 4px;
border-radius: 8px;
display: flex;
flex-direction: column;
}
@ -117,6 +117,7 @@ $MiniAppTileHeight: 114px;
.mx_AppTile_persistedWrapper div {
width: 100%;
height: 100%;
min-width: 300px;
}
.mx_AppTileMenuBar {

View file

@ -6,9 +6,10 @@
border: 1px solid $primary-hairline-color;
background: $primary-bg-color;
border-bottom: none;
border-radius: 4px 4px 0 0;
border-radius: 8px 8px 0 0;
max-height: 50vh;
overflow: auto;
box-shadow: 0px -16px 32px $composer-shadow-color;
}
.mx_Autocomplete_ProviderSection {

View file

@ -22,9 +22,10 @@ limitations under the License.
display: block;
}
.mx_E2EIcon_warning::after,
.mx_E2EIcon_normal::after,
.mx_E2EIcon_verified::after {
.mx_E2EIcon_warning,
.mx_E2EIcon_normal,
.mx_E2EIcon_verified {
&::before, &::after {
content: "";
display: block;
position: absolute;
@ -32,18 +33,47 @@ limitations under the License.
bottom: 0;
left: 0;
right: 0;
background-repeat: no-repeat;
background-size: contain;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
}
}
// white infill for the transparency
.mx_E2EIcon::before {
background-color: #ffffff;
mask-image: url('$(res)/img/e2e/normal.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: 90%;
}
// transparent-looking border surrounding the shield for when overlain over avatars
.mx_E2EIcon_bordered {
mask-image: url('$(res)/img/e2e/normal.svg');
background-color: $header-panel-bg-color;
// shrink the actual badge
&::after {
mask-size: 75%;
}
// shrink the infill of the badge
&::before {
mask-size: 65%;
}
}
.mx_E2EIcon_warning::after {
background-image: url('$(res)/img/e2e/warning.svg');
mask-image: url('$(res)/img/e2e/warning.svg');
background-color: $notice-primary-color;
}
.mx_E2EIcon_normal::after {
background-image: url('$(res)/img/e2e/normal.svg');
mask-image: url('$(res)/img/e2e/normal.svg');
background-color: $composer-e2e-icon-color;
}
.mx_E2EIcon_verified::after {
background-image: url('$(res)/img/e2e/verified.svg');
mask-image: url('$(res)/img/e2e/verified.svg');
background-color: $accent-color;
}

View file

@ -26,8 +26,6 @@ limitations under the License.
position: absolute;
bottom: 2px;
right: 7px;
height: 15px;
width: 15px;
}
}

View file

@ -15,6 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
$left-gutter: 64px;
.mx_EventTile {
max-width: 100%;
clear: both;
@ -37,7 +39,6 @@ limitations under the License.
}
.mx_EventTile_avatar {
position: absolute;
top: 14px;
left: 8px;
cursor: pointer;
@ -46,7 +47,7 @@ limitations under the License.
.mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
top: $font-8px;
left: 65px;
left: $left-gutter;
}
.mx_EventTile_continuation {
@ -68,15 +69,13 @@ limitations under the License.
display: inline-block; /* anti-zalgo, with overflow hidden */
overflow: hidden;
cursor: pointer;
padding-left: 65px; /* left gutter */
padding-bottom: 0px;
padding-top: 0px;
margin: 0px;
line-height: $font-17px;
/* the next three lines, along with overflow hidden, truncate long display names */
white-space: nowrap;
text-overflow: ellipsis;
max-width: calc(100% - 65px);
max-width: calc(100% - $left-gutter);
}
.mx_EventTile .mx_SenderProfile .mx_Flair {
@ -104,9 +103,7 @@ limitations under the License.
visibility: hidden;
white-space: nowrap;
left: 0px;
width: 46px; /* 8 + 30 (avatar) + 8 */
text-align: center;
position: absolute;
user-select: none;
}
@ -116,17 +113,14 @@ limitations under the License.
.mx_EventTile_line, .mx_EventTile_reply {
position: relative;
padding-left: 65px; /* left gutter */
padding-top: 3px;
padding-bottom: 3px;
padding-left: $left-gutter;
border-radius: 4px;
line-height: $font-22px;
}
.mx_RoomView_timeline_rr_enabled,
// on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter
.mx_EventListSummary {
.mx_EventTile_line, .mx_EventTile_reply {
.mx_EventTile_line {
/* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
margin-right: 110px;
}
@ -151,10 +145,6 @@ limitations under the License.
margin-right: 10px;
}
.mx_EventTile_info .mx_EventTile_line {
padding-left: 83px;
}
/* HACK to override line-height which is already marked important elsewhere */
.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
font-size: 48px !important;
@ -171,10 +161,15 @@ limitations under the License.
}
// Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
// The first set is to handle the 'group layout' (default) and the second for the IRC layout
.mx_EventTile_last > div > a > .mx_MessageTimestamp,
.mx_EventTile:hover > div > a > .mx_MessageTimestamp,
.mx_EventTile.mx_EventTile_actionBarFocused > div > a > .mx_MessageTimestamp,
.mx_EventTile.focus-visible:focus-within > div > a > .mx_MessageTimestamp {
.mx_EventTile.focus-visible:focus-within > div > a > .mx_MessageTimestamp,
.mx_IRCLayout .mx_EventTile_last > a > .mx_MessageTimestamp,
.mx_IRCLayout .mx_EventTile:hover > a > .mx_MessageTimestamp,
.mx_IRCLayout .mx_EventTile.mx_EventTile_actionBarFocused > a > .mx_MessageTimestamp,
.mx_IRCLayout .mx_EventTile.focus-visible:focus-within > a > .mx_MessageTimestamp {
visibility: visible;
}
@ -189,7 +184,7 @@ limitations under the License.
* TODO: ultimately we probably want some transition on here.
*/
.mx_EventTile_selected > .mx_EventTile_line {
border-left: $accent-color 5px solid;
border-left: $accent-color 4px solid;
padding-left: 60px;
background-color: $event-selected-color;
}
@ -244,34 +239,6 @@ limitations under the License.
color: $event-notsent-color;
}
.mx_EventTile_redacted .mx_EventTile_line .mx_UnknownBody,
.mx_EventTile_redacted .mx_EventTile_reply .mx_UnknownBody {
--lozenge-color: $event-redacted-fg-color;
--lozenge-border-color: $event-redacted-border-color;
display: block;
height: 22px;
width: 250px;
border-radius: 11px;
background:
repeating-linear-gradient(
-45deg,
var(--lozenge-color),
var(--lozenge-color) 3px,
transparent 3px,
transparent 6px
);
box-shadow: 0px 0px 3px var(--lozenge-border-color) inset;
}
.mx_EventTile_sending.mx_EventTile_redacted .mx_UnknownBody {
opacity: 0.4;
}
div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
--lozenge-color: $event-notsent-color;
--lozenge-border-color: $event-notsent-color;
}
.mx_EventTile_contextual {
opacity: 0.4;
}
@ -363,29 +330,67 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
.mx_EventTile_e2eIcon {
position: absolute;
top: 6px;
left: 46px;
width: 15px;
height: 15px;
left: 44px;
width: 14px;
height: 14px;
display: block;
bottom: 0;
right: 0;
opacity: 0.2;
background-repeat: no-repeat;
background-size: contain;
&::before, &::after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
}
&::before {
background-color: #ffffff;
mask-image: url('$(res)/img/e2e/normal.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: 90%;
}
}
.mx_EventTile_e2eIcon_undecryptable, .mx_EventTile_e2eIcon_unverified {
background-image: url('$(res)/img/e2e/warning.svg');
&::after {
mask-image: url('$(res)/img/e2e/warning.svg');
background-color: $notice-primary-color;
}
opacity: 1;
}
.mx_EventTile_e2eIcon_unknown {
background-image: url('$(res)/img/e2e/warning.svg');
&::after {
mask-image: url('$(res)/img/e2e/warning.svg');
background-color: $notice-primary-color;
}
opacity: 1;
}
.mx_EventTile_e2eIcon_unencrypted {
background-image: url('$(res)/img/e2e/warning.svg');
&::after {
mask-image: url('$(res)/img/e2e/warning.svg');
background-color: $notice-primary-color;
}
opacity: 1;
}
.mx_EventTile_e2eIcon_unauthenticated {
&::after {
mask-image: url('$(res)/img/e2e/normal.svg');
background-color: $composer-e2e-icon-color;
}
opacity: 1;
}
@ -427,10 +432,6 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
margin-bottom: 0px;
}
.mx_EventTile_12hr .mx_EventTile_e2eIcon {
padding-left: 5px;
}
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line,
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
@ -438,15 +439,15 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
}
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
border-left: $e2e-verified-color 5px solid;
border-left: $e2e-verified-color 4px solid;
}
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
border-left: $e2e-unverified-color 5px solid;
border-left: $e2e-unverified-color 4px solid;
}
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
border-left: $e2e-unknown-color 5px solid;
border-left: $e2e-unknown-color 4px solid;
}
.mx_EventTile:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
@ -539,7 +540,8 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
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,
@ -567,7 +569,6 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
.mx_EventTile_content .markdown-body a {
color: $accent-color-alt;
text-decoration: underline;
}
.mx_EventTile_content .markdown-body .hljs {
@ -588,84 +589,6 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
/* end of overrides */
.mx_MatrixChat_useCompactLayout {
.mx_EventTile {
padding-top: 4px;
}
.mx_EventTile.mx_EventTile_info {
// same as the padding for non-compact .mx_EventTile.mx_EventTile_info
padding-top: 0px;
font-size: $font-13px;
.mx_EventTile_line, .mx_EventTile_reply {
line-height: $font-20px;
}
.mx_EventTile_avatar {
top: 4px;
}
}
.mx_EventTile .mx_SenderProfile {
font-size: $font-13px;
}
.mx_EventTile.mx_EventTile_emote {
// add a bit more space for emotes so that avatars don't collide
padding-top: 8px;
.mx_EventTile_avatar {
top: 2px;
}
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0px;
padding-bottom: 1px;
}
}
.mx_EventTile.mx_EventTile_emote.mx_EventTile_continuation {
padding-top: 0;
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0px;
padding-bottom: 0px;
}
}
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0px;
padding-bottom: 0px;
}
.mx_EventTile_avatar {
top: 2px;
}
.mx_EventTile_e2eIcon {
top: 3px;
}
.mx_EventTile_readAvatars {
top: 27px;
}
.mx_EventTile_continuation .mx_EventTile_readAvatars,
.mx_EventTile_emote .mx_EventTile_readAvatars {
top: 5px;
}
.mx_EventTile_info .mx_EventTile_readAvatars {
top: 4px;
}
.mx_RoomView_MessageList h2 {
margin-top: 6px;
}
.mx_EventTile_content .markdown-body {
p, ul, ol, dl, blockquote, pre, table {
margin-bottom: 4px; // 1/4 of the non-compact margin-bottom
}
}
}
.mx_EventTile_tileError {
color: red;
text-align: center;
@ -685,3 +608,14 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
margin-left: 1em;
}
}
@media only screen and (max-width: 480px) {
.mx_EventTile_line, .mx_EventTile_reply {
padding-left: 0;
margin-right: 0;
}
.mx_EventTile_content {
margin-top: 10px;
margin-right: 0;
}
}

View file

@ -0,0 +1,130 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
$left-gutter: 64px;
.mx_GroupLayout {
.mx_EventTile {
> .mx_SenderProfile {
line-height: $font-17px;
padding-left: $left-gutter;
}
> .mx_EventTile_line {
padding-left: $left-gutter;
}
> .mx_EventTile_avatar {
position: absolute;
}
.mx_MessageTimestamp {
position: absolute;
width: 46px; /* 8 + 30 (avatar) + 8 */
}
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 3px;
padding-bottom: 3px;
line-height: $font-22px;
}
}
.mx_EventTile_info .mx_EventTile_line {
padding-left: calc($left-gutter + 18px);
}
}
/* Compact layout overrides */
.mx_MatrixChat_useCompactLayout {
.mx_EventTile {
padding-top: 4px;
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0;
padding-bottom: 0;
}
&.mx_EventTile_info {
// same as the padding for non-compact .mx_EventTile.mx_EventTile_info
padding-top: 0px;
font-size: $font-13px;
.mx_EventTile_line, .mx_EventTile_reply {
line-height: $font-20px;
}
.mx_EventTile_avatar {
top: 4px;
}
}
.mx_SenderProfile {
font-size: $font-13px;
}
&.mx_EventTile_emote {
// add a bit more space for emotes so that avatars don't collide
padding-top: 8px;
.mx_EventTile_avatar {
top: 2px;
}
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0px;
padding-bottom: 1px;
}
}
&.mx_EventTile_emote.mx_EventTile_continuation {
padding-top: 0;
.mx_EventTile_line, .mx_EventTile_reply {
padding-top: 0px;
padding-bottom: 0px;
}
}
.mx_EventTile_avatar {
top: 2px;
}
.mx_EventTile_e2eIcon {
top: 3px;
}
.mx_EventTile_readAvatars {
top: 27px;
}
&.mx_EventTile_continuation .mx_EventTile_readAvatars,
&.mx_EventTile_emote .mx_EventTile_readAvatars {
top: 5px;
}
&.mx_EventTile_info .mx_EventTile_readAvatars {
top: 4px;
}
.mx_EventTile_content .markdown-body {
p, ul, ol, dl, blockquote, pre, table {
margin-bottom: 4px; // 1/4 of the non-compact margin-bottom
}
}
}
.mx_RoomView_MessageList h2 {
margin-top: 6px;
}
}

View file

@ -0,0 +1,225 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
$icon-width: 14px;
$timestamp-width: 45px;
$right-padding: 5px;
$irc-line-height: $font-18px;
.mx_IRCLayout {
--name-width: 70px;
line-height: $irc-line-height !important;
.mx_EventTile {
// timestamps are links which shouldn't be underlined
> a {
text-decoration: none;
}
display: flex;
flex-direction: row;
align-items: flex-start;
padding-top: 0;
> * {
margin-right: $right-padding;
}
> .mx_EventTile_msgOption {
order: 5;
flex-shrink: 0;
.mx_EventTile_readAvatars {
top: 0.2rem; // ($irc-line-height - avatar height) / 2
}
}
> .mx_SenderProfile {
order: 2;
flex-shrink: 0;
width: var(--name-width);
text-overflow: ellipsis;
text-align: left;
display: flex;
align-items: center;
overflow: visible;
justify-content: flex-end;
}
.mx_EventTile_line, .mx_EventTile_reply {
padding: 0;
display: flex;
flex-direction: column;
order: 3;
flex-grow: 1;
flex-shrink: 1;
min-width: 0;
}
> .mx_EventTile_avatar {
order: 1;
position: relative;
top: 0;
left: 0;
flex-shrink: 0;
height: $irc-line-height;
display: flex;
align-items: center;
// Need to use important to override the js provided height and width values.
> .mx_BaseAvatar, > .mx_BaseAvatar > * {
height: $font-14px !important;
width: $font-14px !important;
font-size: $font-10px !important;
line-height: $font-15px !important;
}
}
.mx_MessageTimestamp {
font-size: $font-10px;
width: $timestamp-width;
text-align: right;
}
> .mx_EventTile_e2eIcon {
position: absolute;
right: unset;
left: unset;
top: 0;
padding: 0;
flex-shrink: 0;
flex-grow: 0;
height: $font-18px;
background-position: center;
}
.mx_EventTile_line {
.mx_EventTile_e2eIcon,
.mx_TextualEvent,
.mx_MTextBody,
.mx_ReplyThread_wrapper_empty {
display: inline-block;
}
}
.mx_EventTile_reply {
order: 4;
}
.mx_EditMessageComposer_buttons {
position: relative;
}
}
.mx_EventTile_emote {
> .mx_EventTile_avatar {
margin-left: calc(var(--name-width) + $icon-width + $right-padding);
}
}
blockquote {
margin: 0;
}
.mx_EventListSummary {
> .mx_EventTile_line {
padding-left: calc(var(--name-width) + $icon-width + $timestamp-width + 3 * $right-padding); // 15 px of padding
}
.mx_EventListSummary_avatars {
padding: 0;
margin: 0 9px 0 0;
}
}
.mx_EventTile.mx_EventTile_info {
.mx_EventTile_avatar {
left: calc(var(--name-width) + 10px + $icon-width);
top: 0;
}
.mx_EventTile_line {
left: calc(var(--name-width) + 10px + $icon-width);
}
.mx_TextualEvent {
line-height: $irc-line-height;
}
}
// Suppress highlight thing from the normal Layout.
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line,
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
padding-left: 0;
border-left: 0;
}
.mx_SenderProfile_hover {
background-color: $primary-bg-color;
overflow: hidden;
> span {
display: flex;
> .mx_SenderProfile_name,
> .mx_SenderProfile_aux {
overflow: hidden;
text-overflow: ellipsis;
min-width: var(--name-width);
}
}
}
.mx_SenderProfile:hover {
justify-content: flex-start;
}
.mx_SenderProfile_hover:hover {
overflow: visible;
width: max(auto, 100%);
z-index: 10;
}
.mx_ReplyThread {
margin: 0;
.mx_SenderProfile {
width: unset;
max-width: var(--name-width);
}
}
.mx_ProfileResizer {
position: absolute;
height: 100%;
width: 15px;
left: calc(80px + var(--name-width));
cursor: col-resize;
z-index: 100;
}
// Need to use important to override the js provided height and width values.
.mx_Flair > img {
height: $font-14px !important;
width: $font-14px !important;
}
}

View file

@ -1,58 +0,0 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
@define-mixin mx_InviteOnlyIcon {
width: 12px;
height: 12px;
position: relative;
display: block !important;
}
@define-mixin mx_InviteOnlyIcon_padlock {
background-color: $roomtile-name-color;
mask-image: url("$(res)/img/feather-customised/lock-solid.svg");
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.mx_InviteOnlyIcon_large {
@mixin mx_InviteOnlyIcon;
margin: 0 4px;
&::before {
@mixin mx_InviteOnlyIcon_padlock;
width: 12px;
height: 12px;
}
}
.mx_InviteOnlyIcon_small {
@mixin mx_InviteOnlyIcon;
left: -2px;
&::before {
@mixin mx_InviteOnlyIcon_padlock;
width: 10px;
height: 10px;
}
}

View file

@ -41,6 +41,11 @@ limitations under the License.
// with text-align in parent
display: inline-block;
padding: 0 4px;
color: $accent-fg-color;
background-color: $muted-fg-color;
}
.mx_JumpToBottomButton_highlight .mx_JumpToBottomButton_badge {
color: $secondary-accent-color;
background-color: $warning-color;
}
@ -51,7 +56,7 @@ limitations under the License.
border-radius: 19px;
box-sizing: border-box;
background: $primary-bg-color;
border: 1.3px solid $roomtile-name-color;
border: 1.3px solid $muted-fg-color;
cursor: pointer;
}
@ -62,8 +67,8 @@ limitations under the License.
bottom: 0;
left: 0;
right: 0;
mask: url('$(res)/img/icon-jump-to-bottom.svg');
mask-image: url('$(res)/img/feather-customised/chevron-down-thin.svg');
mask-repeat: no-repeat;
mask-position: 9px 14px;
background: $roomtile-name-color;
mask-size: contain;
background: $muted-fg-color;
}

View file

@ -1,95 +0,0 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_MemberDeviceInfo {
display: flex;
padding-bottom: 10px;
align-items: flex-start;
}
.mx_MemberDeviceInfo_icon {
margin-top: 4px;
width: 12px;
height: 12px;
mask-repeat: no-repeat;
mask-size: 100%;
}
.mx_MemberDeviceInfo_icon_blacklisted {
mask-image: url('$(res)/img/e2e/blacklisted.svg');
background-color: $warning-color;
}
.mx_MemberDeviceInfo_icon_verified {
mask-image: url('$(res)/img/e2e/verified.svg');
background-color: $accent-color;
}
.mx_MemberDeviceInfo_icon_unverified {
mask-image: url('$(res)/img/e2e/warning.svg');
background-color: $warning-color;
}
.mx_MemberDeviceInfo > .mx_DeviceVerifyButtons {
display: flex;
flex-direction: column;
flex: 0 1 auto;
align-items: stretch;
}
.mx_MemberDeviceInfo_textButton {
@mixin mx_DialogButton_small;
margin: 2px;
flex: 1;
}
.mx_MemberDeviceInfo_textButton:hover {
@mixin mx_DialogButton_hover;
}
.mx_MemberDeviceInfo_deviceId {
word-break: break-word;
font-size: $font-13px;
}
.mx_MemberDeviceInfo_deviceInfo {
margin: 0 5px 5px 8px;
flex: 1;
}
/* "Unblacklist" is too long for a regular button: make it wider and
reduce the padding. */
.mx_EncryptedEventDialog .mx_MemberDeviceInfo_blacklist,
.mx_EncryptedEventDialog .mx_MemberDeviceInfo_unblacklist {
padding-left: 1em;
padding-right: 1em;
}
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified,
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified,
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_blacklisted {
float: right;
padding-left: 1em;
}
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified {
color: $e2e-verified-color;
}
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified {
color: $e2e-unverified-color;
}
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_blacklisted {
color: $e2e-warning-color;
}

View file

@ -26,6 +26,10 @@ limitations under the License.
flex: 1 0 auto;
}
.mx_SearchBox {
margin-bottom: 5px;
}
h2 {
text-transform: uppercase;
color: $h3-color;
@ -59,32 +63,27 @@ limitations under the License.
.mx_GroupMemberList_query,
.mx_GroupRoomList_query {
flex: 1 1 0;
// stricter rule to override the one in _common.scss
&[type="text"] {
font-size: $font-12px;
}
}
.mx_MemberList_wrapper {
padding: 10px;
}
.mx_MemberList_invite,
.mx_RightPanel_invite {
.mx_MemberList_invite {
flex: 0 0 auto;
position: relative;
background-color: $button-bg-color;
border-radius: 4px;
padding: 8px;
margin: 9px;
margin: 5px 9px 9px;
display: flex;
justify-content: center;
color: $button-fg-color;
font-weight: 600;
.mx_RightPanel_icon {
padding-right: 5px;
padding-top: 2px;
}
}
.mx_MemberList_invite.mx_AccessibleButton_disabled {
@ -93,8 +92,17 @@ limitations under the License.
}
.mx_MemberList_invite span {
background-image: url('$(res)/img/feather-customised/user-add.svg');
background-image: url('$(res)/img/element-icons/room/invite.svg');
background-repeat: no-repeat;
background-position: center left;
padding-left: 25px;
background-size: 20px;
padding: 8px 0 8px 25px;
}
.mx_MemberList_inviteCommunity span {
background-image: url('$(res)/img/icon-invite-people.svg');
}
.mx_MemberList_addRoomToCommunity span {
background-image: url('$(res)/img/icons-room-add.svg');
}

View file

@ -20,7 +20,8 @@ limitations under the License.
margin: auto;
border-top: 1px solid $primary-hairline-color;
position: relative;
padding-left: 84px;
padding-left: 82px;
padding-right: 6px;
}
.mx_MessageComposer_replaced_wrapper {
@ -60,7 +61,7 @@ limitations under the License.
.mx_MessageComposer .mx_MessageComposer_avatar {
position: absolute;
left: 27px;
left: 26px;
}
.mx_MessageComposer .mx_MessageComposer_avatar .mx_BaseAvatar {
@ -76,8 +77,8 @@ limitations under the License.
left: 60px;
margin-right: 0; // Counteract the E2EIcon class
margin-left: 3px; // Counteract the E2EIcon class
width: 15px;
height: 15px;
width: 12px;
height: 12px;
}
.mx_MessageComposer_noperm_error {
@ -178,44 +179,72 @@ 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;
}
}
.mx_MessageComposer_upload::before {
mask-image: url('$(res)/img/feather-customised/paperclip.svg');
mask-image: url('$(res)/img/element-icons/room/composer/attach.svg');
}
.mx_MessageComposer_hangup::before {
mask-image: url('$(res)/img/hangup.svg');
mask-image: url('$(res)/img/element-icons/call/hangup.svg');
}
.mx_MessageComposer_voicecall::before {
mask-image: url('$(res)/img/feather-customised/phone.svg');
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
}
.mx_MessageComposer_videocall::before {
mask-image: url('$(res)/img/feather-customised/video.svg');
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
}
.mx_MessageComposer_emoji::before {
mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg');
}
.mx_MessageComposer_stickers::before {
mask-image: url('$(res)/img/feather-customised/face.svg');
mask-image: url('$(res)/img/element-icons/room/composer/sticker.svg');
}
.mx_MessageComposer_formatting {
@ -279,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;

View file

@ -75,23 +75,23 @@ limitations under the License.
}
.mx_MessageComposerFormatBar_buttonIconBold::after {
mask-image: url('$(res)/img/format/bold.svg');
mask-image: url('$(res)/img/element-icons/room/format-bar/bold.svg');
}
.mx_MessageComposerFormatBar_buttonIconItalic::after {
mask-image: url('$(res)/img/format/italics.svg');
mask-image: url('$(res)/img/element-icons/room/format-bar/italic.svg');
}
.mx_MessageComposerFormatBar_buttonIconStrikethrough::after {
mask-image: url('$(res)/img/format/strikethrough.svg');
mask-image: url('$(res)/img/element-icons/room/format-bar/strikethrough.svg');
}
.mx_MessageComposerFormatBar_buttonIconQuote::after {
mask-image: url('$(res)/img/format/quote.svg');
mask-image: url('$(res)/img/element-icons/room/format-bar/quote.svg');
}
.mx_MessageComposerFormatBar_buttonIconCode::after {
mask-image: url('$(res)/img/format/code.svg');
mask-image: url('$(res)/img/element-icons/room/format-bar/code.svg');
}
}

View file

@ -0,0 +1,72 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_NotificationBadge {
&:not(.mx_NotificationBadge_visible) {
display: none;
}
// Badges are structured a bit weirdly to work around issues with non-monospace
// font styles. The badge pill is actually a background div and the count floats
// within that. For example:
//
// ( 99+ ) <-- Rounded pill is a _bg class.
// ^- The count is an element floating within that.
&.mx_NotificationBadge_visible {
background-color: $roomtile-default-badge-bg-color;
// Create a flexbox to order the count a bit easier
display: flex;
align-items: center;
justify-content: center;
&.mx_NotificationBadge_highlighted {
// TODO: Use a more specific variable
background-color: $warning-color;
}
// These are the 3 background types
&.mx_NotificationBadge_dot {
background-color: $primary-fg-color; // increased visibility
width: 6px;
height: 6px;
border-radius: 6px;
}
&.mx_NotificationBadge_2char {
width: $font-16px;
height: $font-16px;
border-radius: $font-16px;
}
&.mx_NotificationBadge_3char {
width: $font-26px;
height: $font-16px;
border-radius: $font-16px;
}
// The following is the floating badge
.mx_NotificationBadge_count {
font-size: $font-10px;
line-height: $font-14px;
color: #fff; // TODO: Variable
}
}
}

View file

@ -15,16 +15,13 @@ limitations under the License.
*/
.mx_ReplyPreview {
position: absolute;
bottom: 0;
z-index: 1000;
width: 100%;
border: 1px solid $primary-hairline-color;
background: $primary-bg-color;
border-bottom: none;
border-radius: 4px 4px 0 0;
border-radius: 8px 8px 0 0;
max-height: 50vh;
overflow: auto;
box-shadow: 0px -16px 32px $composer-shadow-color;
}
.mx_ReplyPreview_section {

View file

@ -1,5 +1,5 @@
/*
Copyright 2019 New Vector Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -15,98 +15,42 @@ limitations under the License.
*/
.mx_RoomBreadcrumbs {
position: relative;
height: 42px;
padding: 8px;
padding-bottom: 0;
width: 100%;
// Create a flexbox for the crumbs
display: flex;
flex-direction: row;
// repeating circles as empty placeholders
background:
radial-gradient(
circle at center,
$breadcrumb-placeholder-bg-color,
$breadcrumb-placeholder-bg-color 15px,
transparent 16px
);
background-size: 36px;
background-position: 6px -1px;
background-repeat: repeat-x;
// Autohide the scrollbar
overflow-x: hidden;
&:hover {
overflow-x: visible;
}
.mx_AutoHideScrollbar {
display: flex;
flex-direction: row;
height: 100%;
}
align-items: flex-start;
.mx_RoomBreadcrumbs_crumb {
margin-left: 4px;
height: 32px;
display: inline-block;
transition: transform 0.3s, width 0.3s;
position: relative;
.mx_RoomTile_badge {
position: absolute;
top: -3px;
right: -4px;
}
.mx_RoomBreadcrumbs_dmIndicator {
position: absolute;
bottom: 0;
right: -4px;
}
}
.mx_RoomBreadcrumbs_animate {
margin-left: 0;
margin-right: 8px;
width: 32px;
transform: scale(1);
}
.mx_RoomBreadcrumbs_preAnimate {
width: 0;
transform: scale(0);
// These classes come from the CSSTransition component. There's many more classes we
// could care about, but this is all we worried about for now. The animation works by
// first triggering the enter state with the newest breadcrumb off screen (-40px) then
// sliding it into view.
&.mx_RoomBreadcrumbs-enter {
margin-left: -40px; // 32px for the avatar, 8px for the margin
}
&.mx_RoomBreadcrumbs-enter-active {
margin-left: 0;
// Timing function is as-requested by design.
// NOTE: The transition time MUST match the value passed to CSSTransition!
transition: margin-left 640ms cubic-bezier(0.66, 0.02, 0.36, 1);
}
.mx_RoomBreadcrumbs_left {
opacity: 0.5;
}
// Note: we have to manually control the gradient and stuff, but the IndicatorScrollbar
// will deal with left/right positioning for us. Normally we'd use position:sticky on
// a few key elements, however that doesn't work in horizontal scrolling scenarios.
.mx_IndicatorScrollbar_leftOverflowIndicator,
.mx_IndicatorScrollbar_rightOverflowIndicator {
display: none;
}
.mx_IndicatorScrollbar_leftOverflowIndicator {
background: linear-gradient(to left, $panel-gradient);
}
.mx_IndicatorScrollbar_rightOverflowIndicator {
background: linear-gradient(to right, $panel-gradient);
}
&.mx_IndicatorScrollbar_leftOverflow .mx_IndicatorScrollbar_leftOverflowIndicator,
&.mx_IndicatorScrollbar_rightOverflow .mx_IndicatorScrollbar_rightOverflowIndicator {
position: absolute;
top: 0;
bottom: 0;
width: 15px;
display: block;
pointer-events: none;
z-index: 100;
.mx_RoomBreadcrumbs_placeholder {
font-weight: 600;
font-size: $font-14px;
line-height: 32px; // specifically to match the height this is not scaled
height: 32px;
}
}
.mx_RoomBreadcrumbs_Tooltip {
margin-left: -42px;
margin-top: -42px;
}

View file

@ -1,55 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_RoomDropTarget_container {
background-color: $secondary-accent-color;
padding-left: 18px;
padding-right: 18px;
padding-top: 8px;
padding-bottom: 7px;
}
.collapsed .mx_RoomDropTarget_container {
padding-right: 10px;
padding-left: 10px;
}
.mx_RoomDropTarget {
font-size: $font-13px;
padding-top: 5px;
padding-bottom: 5px;
border: 1px dashed $accent-color;
color: $primary-fg-color;
background-color: $droptarget-bg-color;
border-radius: 4px;
}
.mx_RoomDropTarget_label {
position: relative;
margin-top: 3px;
line-height: $font-21px;
z-index: 1;
text-align: center;
}
.collapsed .mx_RoomDropTarget_avatar {
float: none;
}
.collapsed .mx_RoomDropTarget_label {
display: none;
}

View file

@ -15,26 +15,34 @@ limitations under the License.
*/
.mx_RoomHeader {
flex: 0 0 52px;
flex: 0 0 50px;
border-bottom: 1px solid $primary-hairline-color;
background-color: $roomheader-bg-color;
.mx_RoomHeader_e2eIcon {
height: 12px;
width: 12px;
.mx_E2EIcon {
margin: 0;
position: absolute;
bottom: -2px;
right: -6px;
height: 15px;
width: 15px;
height: 12px;
width: 12px;
}
}
}
.mx_RoomHeader_wrapper {
margin: auto;
height: 52px;
height: 50px;
display: flex;
align-items: center;
min-width: 0;
padding: 0 10px 0 19px;
padding: 0 10px 0 18px;
.mx_InviteOnlyIcon_large {
margin: 0;
}
}
.mx_RoomHeader_spinner {
@ -67,7 +75,6 @@ limitations under the License.
.mx_RoomHeader_buttons {
display: flex;
background-color: $primary-bg-color;
padding-right: 5px;
}
.mx_RoomHeader_info {
@ -173,7 +180,7 @@ limitations under the License.
.mx_RoomHeader_avatar {
flex: 0;
margin: 0 7px;
margin: 0 6px 0 7px;
position: relative;
}
@ -201,41 +208,53 @@ limitations under the License.
.mx_RoomHeader_button {
position: relative;
margin-left: 10px;
margin-left: 1px;
margin-right: 1px;
cursor: pointer;
height: 20px;
width: 20px;
height: 32px;
width: 32px;
border-radius: 100%;
&::before {
content: '';
position: absolute;
height: 20px;
width: 20px;
background-color: $roomheader-button-color;
top: 4px; // center with parent of 32px
left: 4px; // center with parent of 32px
height: 24px;
width: 24px;
background-color: $icon-button-color;
mask-repeat: no-repeat;
mask-size: contain;
}
&:hover {
background: rgba($accent-color, 0.1);
&::before {
background-color: $accent-color;
}
}
}
.mx_RoomHeader_settingsButton::before {
mask-image: url('$(res)/img/feather-customised/settings.svg');
mask-image: url('$(res)/img/element-icons/settings.svg');
}
.mx_RoomHeader_forgetButton::before {
mask-image: url('$(res)/img/leave.svg');
mask-image: url('$(res)/img/element-icons/leave.svg');
width: 26px;
}
.mx_RoomHeader_searchButton::before {
mask-image: url('$(res)/img/feather-customised/search.svg');
mask-image: url('$(res)/img/element-icons/room/search-inset.svg');
}
.mx_RoomHeader_shareButton::before {
mask-image: url('$(res)/img/feather-customised/share.svg');
mask-image: url('$(res)/img/element-icons/room/share.svg');
}
.mx_RoomHeader_manageIntegsButton::before {
mask-image: url('$(res)/img/feather-customised/grid.svg');
mask-image: url('$(res)/img/element-icons/room/integrations.svg');
}
.mx_RoomHeader_showPanel {
@ -251,7 +270,7 @@ limitations under the License.
}
.mx_RoomHeader_pinnedButton::before {
mask-image: url('$(res)/img/icons-pin.svg');
mask-image: url('$(res)/img/element-icons/room/pin.svg');
}
.mx_RoomHeader_pinsIndicator {
@ -267,3 +286,12 @@ limitations under the License.
.mx_RoomHeader_pinsIndicatorUnread {
background-color: $pinned-unread-color;
}
@media only screen and (max-width: 480px) {
.mx_RoomHeader_wrapper {
padding: 0;
}
.mx_RoomHeader {
overflow: hidden;
}
}

Some files were not shown because too many files have changed in this diff Show more