The UI is adapted to the RTL layout

This commit is contained in:
ErickSkrauch 2021-03-26 04:19:04 +01:00
parent 370725dd7e
commit 4525089725
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
41 changed files with 254 additions and 170 deletions

View File

@ -144,6 +144,7 @@
"loader-utils": "^2.0.0", "loader-utils": "^2.0.0",
"mini-css-extract-plugin": "^0.9.0", "mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"postcss-bidirection": "https://github.com/erickskrauch/postcss-bidirection.git#iss_23",
"postcss-import": "^12.0.1", "postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"postcss-scss": "^2.1.1", "postcss-scss": "^2.1.1",

View File

@ -119,6 +119,7 @@ interface State {
formsHeights: Record<PanelId, number>; formsHeights: Record<PanelId, number>;
} }
// TODO: completely broken for RTL languages
class PanelTransition extends React.PureComponent<Props, State> { class PanelTransition extends React.PureComponent<Props, State> {
state: State = { state: State = {
contextHeight: 0, contextHeight: 0,

View File

@ -16,7 +16,6 @@
display: block; display: block;
position: absolute; position: absolute;
left: 0;
bottom: 0; bottom: 0;
height: 3px; height: 3px;
width: 40px; width: 40px;

View File

@ -3,7 +3,7 @@
.accountSwitcher { .accountSwitcher {
background: $black; background: $black;
text-align: left; text-align: start;
} }
$border: 1px solid lighter($black); $border: 1px solid lighter($black);
@ -37,12 +37,12 @@ $border: 1px solid lighter($black);
.accountAvatar { .accountAvatar {
font-size: 35px; font-size: 35px;
margin-right: 15px; margin-inline-end: 15px;
} }
.accountInfo { .accountInfo {
flex-grow: 1; flex-grow: 1;
margin-right: 15px; margin-inline-end: 15px;
min-width: 0; // Fix for text-overflow. See https://stackoverflow.com/a/40612184 min-width: 0; // Fix for text-overflow. See https://stackoverflow.com/a/40612184
} }
@ -76,17 +76,25 @@ $border: 1px solid lighter($black);
composes: arrowRight from '~app/components/ui/icons.scss'; composes: arrowRight from '~app/components/ui/icons.scss';
position: relative; position: relative;
left: 0; inset-inline-start: 0;
font-size: 24px; font-size: 24px;
color: #4e4e4e; color: #4e4e4e;
line-height: 35px; line-height: 35px;
transition: color 0.25s, inset-inline-start 0.5s;
// TODO: right now transition property doesn't support the bidirectional value.
// See https://github.com/gasolin/postcss-bidirection/issues/25.
// noinspection CssOverwrittenProperties Graceful degradation
transition: color 0.25s, left 0.5s; transition: color 0.25s, left 0.5s;
html[dir='rtl'] & {
transition: color 0.25s, right 0.5s;
}
.item:hover & { .item:hover & {
color: #aaa; color: #aaa;
left: 5px; inset-inline-start: 5px;
} }
} }

View File

@ -16,7 +16,7 @@
position: relative; position: relative;
bottom: 1px; bottom: 1px;
padding-left: 3px; padding-inline-start: 3px;
color: #666666; color: #666666;
font-size: 10px; font-size: 10px;

View File

@ -4,18 +4,18 @@
.authInfo { .authInfo {
// Отступы сверху и снизу разные т.к. мы ужимаем высоту линии строки с логином на 2 пикселя и из-за этого теряем отступ снизу // Отступы сверху и снизу разные т.к. мы ужимаем высоту линии строки с логином на 2 пикселя и из-за этого теряем отступ снизу
padding: 5px 20px 7px; padding: 5px 20px 7px;
text-align: left; text-align: start;
} }
.authInfoAvatar { .authInfoAvatar {
$size: 30px; $size: 30px;
float: left; float: start;
height: $size; height: $size;
width: $size; width: $size;
font-size: $size; font-size: $size;
line-height: 1; line-height: 1;
margin-right: 10px; margin-inline-end: 10px;
margin-top: 2px; margin-top: 2px;
color: #aaa; color: #aaa;
@ -38,7 +38,7 @@
.permissionsContainer { .permissionsContainer {
padding: 15px 12px; padding: 15px 12px;
text-align: left; text-align: start;
} }
.permissionsTitle { .permissionsTitle {
@ -57,7 +57,7 @@
font-size: 14px; font-size: 14px;
line-height: 1.4; line-height: 1.4;
padding-bottom: 4px; padding-bottom: 4px;
padding-left: 17px; padding-inline-start: 17px;
position: relative; position: relative;
&:last-of-type { &:last-of-type {
@ -71,7 +71,7 @@
line-height: 9px; line-height: 9px;
position: absolute; position: absolute;
top: 6px; top: 6px;
left: -4px; inset-inline-start: -4px;
} }
} }
} }

View File

@ -37,7 +37,7 @@
width: 50%; width: 50%;
&:first-of-type { &:first-of-type {
margin-right: $popupPadding; margin-inline-end: $popupPadding;
} }
} }

View File

@ -160,7 +160,7 @@
composes: arrowRight from '~app/components/ui/icons.scss'; composes: arrowRight from '~app/components/ui/icons.scss';
position: relative; position: relative;
left: 0; inset-inline-start: 0;
font-size: 28px; font-size: 28px;
color: #ebe8e1; color: #ebe8e1;
@ -173,7 +173,11 @@
.appExpanded & { .appExpanded & {
color: #777; color: #777;
transform: rotate(360deg) !important; // Prevent it from hover rotating transform: rotate(360deg)!important; // Prevent it from hover rotating
html[dir='rtl'] & {
transform: rotate(0)!important;
}
} }
} }
@ -195,7 +199,7 @@ $appDetailsContainerRightLeftPadding: 30px;
.editAppLink { .editAppLink {
position: absolute; position: absolute;
top: 4px; top: 4px;
right: 0; inset-inline-end: 0;
font-size: 12px; font-size: 12px;
color: #9a9a9a; color: #9a9a9a;
@ -221,17 +225,19 @@ $appDetailsContainerRightLeftPadding: 30px;
} }
.appActionButton { .appActionButton {
margin: 0 10px 10px 0; margin-inline-end: 10px;
margin-bottom: 10px;
&:last-of-type { &:last-of-type {
margin-right: 0; margin-inline-end: 0;
} }
} }
.appActionContainer { .appActionContainer {
position: absolute; position: absolute;
width: calc(100% - #{$appDetailsContainerRightLeftPadding * 2});
top: 100%; top: 100%;
left: 0; inset-inline-start: 0;
padding: 0 $appDetailsContainerRightLeftPadding; padding: 0 $appDetailsContainerRightLeftPadding;
background: #f5f5f5; background: #f5f5f5;
} }
@ -244,7 +250,7 @@ $appDetailsContainerRightLeftPadding: 30px;
.continueActionButtonWrapper { .continueActionButtonWrapper {
display: inline-block; display: inline-block;
margin-left: 10px; margin-inline-start: 10px;
} }
.continueActionLink { .continueActionLink {

View File

@ -24,5 +24,5 @@
position: relative; position: relative;
bottom: 1px; bottom: 1px;
font-size: 11px; font-size: 11px;
margin-right: 3px; margin-inline-end: 3px;
} }

View File

@ -26,7 +26,7 @@
position: relative; position: relative;
top: 1px; top: 1px;
display: inline-block; display: inline-block;
margin-right: 4px; margin-inline-end: 4px;
height: $height; height: $height;
width: $height * 4 / 3; width: $height * 4 / 3;
box-shadow: 0 0 1px rgba(#000, 0.2); box-shadow: 0 0 1px rgba(#000, 0.2);

View File

@ -33,7 +33,7 @@
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; inset-inline-end: 12px;
font-size: 22px; font-size: 22px;
color: #edebe5; color: #edebe5;
pointer-events: none; // Иконка чисто декоративная, так что клик должен проходить сквозь неё pointer-events: none; // Иконка чисто декоративная, так что клик должен проходить сквозь неё
@ -94,7 +94,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
.languageIco { .languageIco {
display: inline-block; display: inline-block;
margin-right: 7px; margin-inline-end: 7px;
width: 40px; width: 40px;
height: 30px; height: 30px;
box-shadow: 0 0 1px rgba(#000, 0.2); box-shadow: 0 0 1px rgba(#000, 0.2);
@ -129,7 +129,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
box-sizing: border-box; box-sizing: border-box;
width: 22px; width: 22px;
height: 22px; height: 22px;
right: -32px; inset-inline-end: -32px;
font-size: 10px; font-size: 10px;
line-height: 18px; line-height: 18px;
@ -146,13 +146,13 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
} }
.languageItem:hover & { .languageItem:hover & {
right: 0; inset-inline-end: 0;
} }
.activeLanguageItem & { .activeLanguageItem & {
border-color: $green; border-color: $green;
background: $green; background: $green;
right: 0; inset-inline-end: 0;
&:before { &:before {
opacity: 1; opacity: 1;
@ -209,7 +209,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
color: lighter($blue); color: lighter($blue);
font-size: 22px; font-size: 22px;
margin-right: 10px; margin-inline-end: 10px;
} }
.improveTranslatesContent { .improveTranslatesContent {

View File

@ -19,12 +19,12 @@
li { li {
position: relative; position: relative;
padding-left: 11px; padding-inline-start: 11px;
&:before { &:before {
content: ''; content: '';
position: absolute; position: absolute;
left: 0; inset-inline-start: 0;
top: 2px; top: 2px;
} }

View File

@ -75,7 +75,7 @@ export default function OsInstruction({ os }: { os: OS }) {
<ul className={styles.appList}> <ul className={styles.appList}>
{linksByOs[os].featured.map((item) => ( {linksByOs[os].featured.map((item) => (
<li key={item.label}> <li key={item.label}>
<a href={item.link} target="_blank"> <a href={item.link} target="_blank" dir="ltr">
{item.label} {item.label}
</a> </a>
</li> </li>

View File

@ -22,7 +22,7 @@
.otherApps { .otherApps {
position: absolute; position: absolute;
right: 0; inset-inline-end: 0;
bottom: 5px; bottom: 5px;
font-size: 10px; font-size: 10px;
@ -96,7 +96,7 @@
.androidActive & { .androidActive & {
transform: translateX(0); transform: translateX(0);
left: 0; inset-inline-start: 0;
} }
.appleActive &, .appleActive &,
@ -111,21 +111,33 @@
$translateX: -51%; $translateX: -51%;
transform: translateX($translateX) scale(1); transform: translateX($translateX) scale(1);
left: 49%; inset-inline-start: 49%;
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(1);
}
&:hover { &:hover {
transform: translateX($translateX) scale(1.1); transform: translateX($translateX) scale(1.1);
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(1.1);
}
} }
.appleActive & { .appleActive & {
transform: translateX(0); transform: translateX(0)!important; // override dir='rtl'
left: 0; inset-inline-start: 0;
} }
.androidActive &, .androidActive &,
.windowsActive & { .windowsActive & {
transform: translateX($translateX) scale(0); transform: translateX($translateX) scale(0);
opacity: 0; opacity: 0;
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(0);
}
} }
} }
@ -134,21 +146,33 @@
$translateX: -100%; $translateX: -100%;
transform: translateX($translateX) scale(1); transform: translateX($translateX) scale(1);
left: 100%; inset-inline-start: 100%;
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(1);
}
&:hover { &:hover {
transform: translateX($translateX) scale(1.1); transform: translateX($translateX) scale(1.1);
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(1.1);
}
} }
.windowsActive & { .windowsActive & {
transform: translateX(0); transform: translateX(0)!important; // override dir='rtl'
left: 0; inset-inline-start: 0;
} }
.appleActive &, .appleActive &,
.androidActive & { .androidActive & {
transform: translateX($translateX) scale(0); transform: translateX($translateX) scale(0);
opacity: 0; opacity: 0;
html[dir='rtl'] & {
transform: translateX(-$translateX) scale(0);
}
} }
} }
@ -166,8 +190,8 @@
position: relative; position: relative;
z-index: 1; z-index: 1;
margin: 15px; margin: 15px;
margin-left: 30%; margin-inline-start: 30%;
padding-left: 15px; padding-inline-start: 15px;
padding-bottom: 15px; padding-bottom: 15px;
min-height: $boxHeight; min-height: $boxHeight;
} }
@ -212,7 +236,7 @@
.osName { .osName {
font-family: $font-family-title; font-family: $font-family-title;
font-size: 16px; font-size: 16px;
margin-left: 10px; margin-inline-start: 10px;
} }
@mixin commonNonActiveTile() { @mixin commonNonActiveTile() {

View File

@ -16,8 +16,8 @@ $maxQrCodeSize: 242px;
} }
.or { .or {
position: absolute; position: absolute; // Use absolute positioning to put an element between margin
left: 0; inset-inline-start: 0; // TODO: doesn't have any effect. Probably can be removed
width: 100%; width: 100%;
margin-top: -18px; margin-top: -18px;

View File

@ -13,7 +13,8 @@ $formColumnWidth: 416px;
} }
.descriptionColumn { .descriptionColumn {
padding: 12px 20px 0 0; padding-top: 12px;
padding-inline-end: 20px;
box-sizing: border-box; box-sizing: border-box;
} }
@ -97,7 +98,8 @@ $formColumnWidth: 416px;
} }
.paramMessage { .paramMessage {
padding: 10px 40px 0 0; padding-top: 10px;
padding-inline-end: 40px;
color: $red; color: $red;
font-size: 11px; font-size: 11px;
@ -168,7 +170,7 @@ $formColumnWidth: 416px;
} }
.paramEditIcon { .paramEditIcon {
margin-left: 5px; margin-inline-start: 5px;
vertical-align: top; vertical-align: top;
} }

View File

@ -9,7 +9,7 @@
.backButton { .backButton {
position: absolute; position: absolute;
left: -60px; inset-inline-start: -60px;
top: 15px; top: 15px;
width: 25px; width: 25px;
height: 25px; height: 25px;
@ -60,7 +60,6 @@
display: block; display: block;
position: absolute; position: absolute;
left: 0;
bottom: 0; bottom: 0;
height: 3px; height: 3px;
width: 86px; width: 86px;
@ -110,7 +109,7 @@
.backButton { .backButton {
top: 29px; top: 29px;
left: 27px; inset-inline-start: 27px;
padding: 0; padding: 0;
margin: 0; margin: 0;
width: auto; width: auto;

View File

@ -29,7 +29,8 @@
} }
.iconWrapper { .iconWrapper {
margin: 4px 12px 0 0; margin-top: 4px;
margin-inline-end: 12px;
} }
.dbIcon { .dbIcon {
@ -68,14 +69,15 @@
font-family: $font-family-title; font-family: $font-family-title;
font-size: 14px; font-size: 14px;
color: #9a9a9a; color: #9a9a9a;
margin: 0 0 5px 1px; // Add 1px from the left to make icon look visually aligned with texts margin-bottom: 5px;
margin-inline-start: 1px; // Add 1px from the left to make icon look visually aligned with texts
} }
.githubIcon { .githubIcon {
composes: github from '~app/components/ui/icons.scss'; composes: github from '~app/components/ui/icons.scss';
font-size: 12px; font-size: 12px;
margin-right: 2px; margin-inline-end: 2px;
position: relative; position: relative;
bottom: 1px; bottom: 1px;
} }

View File

@ -1,20 +0,0 @@
.horizontalGroup {
display: flex;
}
.item {
// TODO: in some cases we do not need overflow hidden
// probably, it is better to create a separate class for children, that will
// enable overflow hidden and ellipsis
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
$borderConfig: 1px solid rgba(#fff, 0.15);
border-left: $borderConfig;
&:last-child {
border-right: $borderConfig;
}
}

View File

@ -1,31 +1,31 @@
import React from 'react'; import React, { ReactNode } from 'react';
import { MessageDescriptor } from 'react-intl'; import { MessageDescriptor } from 'react-intl';
import i18n from 'app/services/i18n'; import i18n from 'app/services/i18n';
function isMessageDescriptor(value: any): value is MessageDescriptor {
return typeof value === 'object' && value.id;
}
export default class FormComponent<P, S = {}> extends React.Component<P, S> { export default class FormComponent<P, S = {}> extends React.Component<P, S> {
/** /**
* Formats message resolving intl translations * Formats message resolving intl translations
* *
* @param {string|object} message - message string, or intl message descriptor with an `id` field * @param {string|object} message - message string, or intl message descriptor with an `id` field
* *
* @deprecated
* @returns {string} * @returns {string}
*/ */
formatMessage(message: string | MessageDescriptor): string { formatMessage<T extends ReactNode | MessageDescriptor>(message: T): T extends MessageDescriptor ? string : T {
if (!message) { if (isMessageDescriptor(message)) {
throw new Error('A message is required'); // @ts-ignore
}
if (typeof message === 'string') {
return message;
}
if (!message.id) {
throw new Error(`Invalid message format: ${JSON.stringify(message)}`);
}
return i18n.getIntl().formatMessage(message); return i18n.getIntl().formatMessage(message);
} }
// @ts-ignore
return message;
}
/** /**
* Focuses this field * Focuses this field
*/ */

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { ReactNode } from 'react';
import { MessageDescriptor } from 'react-intl'; import { MessageDescriptor } from 'react-intl';
import clsx from 'clsx'; import clsx from 'clsx';
import { uniqueId, omit } from 'app/functions'; import { uniqueId, omit } from 'app/functions';
@ -17,7 +17,7 @@ export default class Input extends FormInputComponent<
color: Color; color: Color;
center: boolean; center: boolean;
disabled: boolean; disabled: boolean;
label?: string | MessageDescriptor; label?: ReactNode | MessageDescriptor;
placeholder?: string | MessageDescriptor; placeholder?: string | MessageDescriptor;
icon?: string; icon?: string;
copy?: boolean; copy?: boolean;

View File

@ -25,8 +25,9 @@ $dropdownPadding: 15px;
display: inline-block; display: inline-block;
box-sizing: border-box; box-sizing: border-box;
height: 50px; height: 50px;
padding-inline-start: $dropdownPadding;
// 28px - ширина иконки при заданном размере шрифта // 28px - ширина иконки при заданном размере шрифта
padding: 0 ($dropdownPadding * 2 + 28px) 0 $dropdownPadding; padding-inline-end: $dropdownPadding * 2 + 28px;
position: relative; position: relative;
font-family: $font-family-title; font-family: $font-family-title;
@ -48,6 +49,7 @@ $dropdownPadding: 15px;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
text-align: start;
} }
.opened { .opened {
@ -57,18 +59,26 @@ $dropdownPadding: 15px;
composes: selecter from '~app/components/ui/icons.scss'; composes: selecter from '~app/components/ui/icons.scss';
position: absolute; position: absolute;
right: $dropdownPadding; inset-inline-end: $dropdownPadding;
top: 16px; top: 16px;
font-size: 17px; font-size: 17px;
transition: right 0.3s cubic-bezier(0.23, 1, 0.32, 1); // easeOutQuint transition: inset-inline-end 0.3s cubic-bezier(0.23, 1, 0.32, 1); // easeOutQuint
// TODO: right now transition property doesn't support the bidirectional value.
// See https://github.com/gasolin/postcss-bidirection/issues/25.
// noinspection CssOverwrittenProperties Graceful degradation
transition: right 0.3s cubic-bezier(0.23, 1, 0.32, 1);
html[dir='rtl'] & {
transition: left 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}
.dropdown:hover & { .dropdown:hover & {
right: $dropdownPadding - 5px; inset-inline-end: $dropdownPadding - 5px;
} }
.dropdown:active &, .dropdown:active &,
.dropdown.opened & { .dropdown.opened & {
right: $dropdownPadding + 5px; inset-inline-end: $dropdownPadding + 5px;
} }
} }
@ -84,7 +94,7 @@ $dropdownPadding: 15px;
.menu { .menu {
position: absolute; position: absolute;
top: 60px; top: 60px;
left: 0; inset-inline-start: 0;
z-index: 10; z-index: 10;
width: 120%; width: 120%;

View File

@ -36,7 +36,7 @@
composes: formRow; composes: formRow;
.textField { .textField {
padding-left: 60px; padding-inline-start: 60px;
} }
} }
@ -80,7 +80,7 @@
.textFieldIcon { .textFieldIcon {
box-sizing: border-box; box-sizing: border-box;
position: absolute; position: absolute;
left: 0; inset-inline-start: 0;
top: 0; top: 0;
height: 50px; height: 50px;
width: 50px; width: 50px;
@ -95,7 +95,7 @@
.copyIcon { .copyIcon {
position: absolute; position: absolute;
right: 5px; inset-inline-end: 5px;
top: 10px; top: 10px;
padding: 5px; padding: 5px;
@ -175,6 +175,7 @@
font-family: $font-family-title; font-family: $font-family-title;
color: #666; color: #666;
font-size: 18px; font-size: 18px;
text-align: start;
} }
.fieldError { .fieldError {
@ -248,7 +249,7 @@
.markableContainer { .markableContainer {
display: inline-block; display: inline-block;
position: relative; position: relative;
padding-left: 27px; padding-inline-start: 27px;
font-family: $font-family-title; font-family: $font-family-title;
font-size: 16px; font-size: 16px;
@ -260,7 +261,7 @@
.markPosition { .markPosition {
position: absolute; position: absolute;
box-sizing: border-box; box-sizing: border-box;
left: 0; inset-inline-start: 0;
top: 0; top: 0;
margin: 0; margin: 0;

View File

@ -15,10 +15,30 @@
@extend .arrow; @extend .arrow;
transform: rotate(270deg); transform: rotate(270deg);
html[dir='rtl'] & {
transform: rotate(90deg);
}
} }
.arrowLeft { .arrowLeft {
@extend .arrow; @extend .arrow;
transform: rotate(90deg); transform: rotate(90deg);
html[dir='rtl'] & {
transform: rotate(270deg);
}
}
html[dir='rtl'] {
.brush,
.exit,
.key,
.pencil,
.search {
&:before {
transform: scaleX(-1);
}
}
} }

View File

@ -1,4 +1,6 @@
.loader-overlay { .loader-overlay {
direction: ltr;
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
position: fixed; position: fixed;
top: 0; top: 0;

View File

@ -77,6 +77,7 @@ class SlideMotion extends React.PureComponent<Props, State> {
<div <div
className={styles.container} className={styles.container}
style={{ style={{
// TODO: inverse for RTL language
WebkitTransform: `translateX(-${interpolatingStyle.transform}%)`, WebkitTransform: `translateX(-${interpolatingStyle.transform}%)`,
transform: `translateX(-${interpolatingStyle.transform}%)`, transform: `translateX(-${interpolatingStyle.transform}%)`,
}} }}

View File

@ -25,12 +25,12 @@ $headerHeight: 60px;
.headerControl { .headerControl {
composes: black from '~app/components/ui/buttons.scss'; composes: black from '~app/components/ui/buttons.scss';
float: left; float: start;
overflow: hidden; overflow: hidden;
height: $headerHeight - 1px; height: $headerHeight - 1px;
width: 49px; width: 49px;
padding: 0; padding: 0;
border-right: 1px solid lighter($black); border-inline-end: 1px solid lighter($black);
line-height: 1; line-height: 1;
text-align: center; text-align: center;
@ -122,7 +122,7 @@ $bodyTopBottomPadding: 15px;
composes: close from '~app/components/ui/icons.scss'; composes: close from '~app/components/ui/icons.scss';
position: absolute; position: absolute;
right: 5px; inset-inline-end: 5px;
top: 5px; top: 5px;
font-size: 10px; font-size: 10px;

View File

@ -59,7 +59,7 @@ $popupMargin: 20px; // Outer popup margins
.popup { .popup {
white-space: normal; white-space: normal;
text-align: left; text-align: start;
background: #fff; background: #fff;
box-shadow: 0 0 10px rgba(#000, 0.2); box-shadow: 0 0 10px rgba(#000, 0.2);
@ -95,7 +95,7 @@ $popupMargin: 20px; // Outer popup margins
composes: close from '~app/components/ui/icons.scss'; composes: close from '~app/components/ui/icons.scss';
position: absolute; position: absolute;
right: 0; inset-inline-end: 0;
top: 0; top: 0;
padding: 15px; padding: 15px;
cursor: pointer; cursor: pointer;
@ -122,6 +122,10 @@ $popupMargin: 20px; // Outer popup margins
opacity: 0; opacity: 0;
transform: translate(100%); transform: translate(100%);
transition: 0s; transition: 0s;
html[dir='rtl'] & {
transform: translate(-100%);
}
} }
} }

View File

@ -47,7 +47,7 @@
position: absolute; position: absolute;
top: 0.16em; top: 0.16em;
left: -0.145em; inset-inline-start: -0.145em;
font-size: 0.7em; font-size: 0.7em;
color: rgba($red, 0.75); color: rgba($red, 0.75);
} }

View File

@ -8,7 +8,7 @@
.step { .step {
position: relative; position: relative;
text-align: right; text-align: end;
width: 100%; width: 100%;
height: 4px; height: 4px;
@ -24,8 +24,8 @@
position: absolute; position: absolute;
height: 4px; height: 4px;
left: 0; inset-inline-start: 0;
right: 100%; inset-inline-end: 100%;
top: 50%; top: 50%;
margin-top: -2px; margin-top: -2px;
@ -53,7 +53,7 @@
.activeStep { .activeStep {
&:before { &:before {
right: 0; inset-inline-end: 0;
transition-delay: unset; transition-delay: unset;
} }

View File

@ -47,7 +47,7 @@ const AccountSwitcher: ComponentType<Props> = ({
<div className={clsx(styles.accountSwitcher)} data-testid="account-switcher"> <div className={clsx(styles.accountSwitcher)} data-testid="account-switcher">
<div className={styles.item} data-testid="active-account"> <div className={styles.item} data-testid="active-account">
<PseudoAvatar className={styles.activeAccountIcon} /> <PseudoAvatar className={styles.activeAccountIcon} />
<div className={styles.activeAccountInfo}> <div>
<div className={styles.activeAccountUsername}>{activeAccount.username}</div> <div className={styles.activeAccountUsername}>{activeAccount.username}</div>
<div className={clsx(styles.accountEmail, styles.activeAccountEmail)}>{activeAccount.email}</div> <div className={clsx(styles.accountEmail, styles.activeAccountEmail)}>{activeAccount.email}</div>
<div className={styles.links}> <div className={styles.links}>
@ -81,16 +81,16 @@ const AccountSwitcher: ComponentType<Props> = ({
> >
<PseudoAvatar index={index + 1} deleted={account.isDeleted} className={styles.accountIcon} /> <PseudoAvatar index={index + 1} deleted={account.isDeleted} className={styles.accountIcon} />
<div className={styles.accountInfo}>
<div className={styles.accountUsername}>{account.username}</div>
<div className={styles.accountEmail}>{account.email}</div>
</div>
<div <div
className={styles.logoutIcon} className={styles.logoutIcon}
data-testid="logout-account" data-testid="logout-account"
onClick={onAccountRemoveCallback(account)} onClick={onAccountRemoveCallback(account)}
/> />
<div className={styles.accountInfo}>
<div className={styles.accountUsername}>{account.username}</div>
<div className={styles.accountEmail}>{account.email}</div>
</div>
</div> </div>
))} ))}
<Link to="/login" onClick={onLoginClick}> <Link to="/login" onClick={onLoginClick}>

View File

@ -8,8 +8,6 @@ $bodyLeftRightPadding: 20px;
$lightBorderColor: #eee; $lightBorderColor: #eee;
.accountSwitcher { .accountSwitcher {
text-align: left;
background: #fff; background: #fff;
color: #444; color: #444;
min-width: 205px; min-width: 205px;
@ -20,9 +18,6 @@ $lightBorderColor: #eee;
border-bottom: 7px solid darker($green); border-bottom: 7px solid darker($green);
} }
.accountInfo {
}
.accountUsername, .accountUsername,
.accountEmail { .accountEmail {
overflow: hidden; overflow: hidden;
@ -30,6 +25,7 @@ $lightBorderColor: #eee;
} }
.item { .item {
display: flex;
padding: 15px; padding: 15px;
border-bottom: 1px solid $lightBorderColor; border-bottom: 1px solid $lightBorderColor;
} }
@ -50,8 +46,7 @@ $lightBorderColor: #eee;
.accountIcon { .accountIcon {
font-size: 27px; font-size: 27px;
width: 20px; width: 20px;
text-align: center; margin-inline-end: 9px;
float: left;
} }
.activeAccountIcon { .activeAccountIcon {
@ -60,10 +55,6 @@ $lightBorderColor: #eee;
font-size: 40px; font-size: 40px;
} }
.activeAccountInfo {
margin-left: 29px;
}
.activeAccountUsername { .activeAccountUsername {
font-family: $font-family-title; font-family: $font-family-title;
font-size: 20px; font-size: 20px;
@ -88,8 +79,7 @@ $lightBorderColor: #eee;
} }
.accountInfo { .accountInfo {
margin-left: 29px; flex-grow: 1;
margin-right: 25px;
} }
.accountUsername { .accountUsername {
@ -117,15 +107,16 @@ $lightBorderColor: #eee;
color: $green; color: $green;
position: relative; position: relative;
bottom: 1px; bottom: 1px;
margin-right: 3px; margin-inline-end: 3px;
} }
.logoutIcon { .logoutIcon {
composes: exit from '~app/components/ui/icons.scss'; composes: exit from '~app/components/ui/icons.scss';
align-self: center;
margin-inline-start: 9px;
color: #cdcdcd; color: #cdcdcd;
float: right;
line-height: 27px;
transition: 0.25s; transition: 0.25s;
&:hover { &:hover {

View File

@ -27,6 +27,10 @@
.expandIcon { .expandIcon {
transform: rotate(-180deg); transform: rotate(-180deg);
html[dir='rtl'] & {
transform: rotate(180deg); // Fix spin direction
}
} }
} }
@ -36,13 +40,13 @@
position: relative; position: relative;
bottom: 2px; bottom: 2px;
padding-right: 5px; padding-inline-end: 5px;
} }
.expandIcon { .expandIcon {
composes: caret from '~app/components/ui/icons.scss'; composes: caret from '~app/components/ui/icons.scss';
margin-left: 4px; margin-inline-start: 4px;
font-size: 6px; font-size: 6px;
color: #ccc; color: #ccc;
transition: 0.2s; transition: 0.2s;
@ -54,7 +58,7 @@
.accountSwitcherContainer { .accountSwitcherContainer {
position: absolute; position: absolute;
top: 100%; top: 100%;
right: -2px; inset-inline-end: -2px;
cursor: auto; cursor: auto;
display: none; display: none;

View File

@ -26,7 +26,11 @@
width: 50px; width: 50px;
height: 50px; height: 50px;
background: white; background: white;
animation: cubeRotate 1s ease-out infinite; animation: cubeRotateLTR 1s ease-out infinite;
html[dir='rtl'] & {
animation-name: cubeRotateRTL;
}
} }
.road { .road {
@ -34,12 +38,12 @@
width: 100%; width: 100%;
height: 1px; height: 1px;
background: white; background: white;
left: 0; inset-inline-start: 0;
bottom: 0; bottom: 0;
animation: roadStab 1s ease-out infinite; animation: roadStab 1s ease-out infinite;
} }
@keyframes cubeRotate { @keyframes cubeRotateLTR {
0% { 0% {
transform: rotate(0deg) translate3D(0, 0, 0); transform: rotate(0deg) translate3D(0, 0, 0);
} }
@ -54,6 +58,21 @@
} }
} }
@keyframes cubeRotateRTL {
0% {
transform: rotate(0deg) translate3D(0, 0, 0);
}
65% {
transform: rotate(-45deg) translate3D(0, -13px, 0);
}
90% {
transform: rotate(-70deg) translate3D(0, -8px, 0);
}
100% {
transform: rotate(-90deg) translate3D(0, 0, 0);
}
}
@keyframes roadStab { @keyframes roadStab {
0% { 0% {
transform: translate3D(0, 0, 0); transform: translate3D(0, 0, 0);
@ -91,7 +110,7 @@
height: 100%; height: 100%;
position: absolute; position: absolute;
bottom: -50px; bottom: -50px;
left: 0; inset-inline-start: 0;
overflow: hidden; overflow: hidden;
animation: roadStab 1s ease-out infinite; animation: roadStab 1s ease-out infinite;
} }
@ -103,7 +122,7 @@
border-right: 2px solid transparent; border-right: 2px solid transparent;
border-bottom: 4px solid white; border-bottom: 4px solid white;
bottom: $bottom; bottom: $bottom;
right: -2%; inset-inline-end: -2%;
animation: rockTravelling 10s $delay ease-out infinite; animation: rockTravelling 10s $delay ease-out infinite;
} }
} }
@ -116,37 +135,37 @@
@keyframes rockTravelling { @keyframes rockTravelling {
0% { 0% {
right: -2%; inset-inline-end: -2%;
} }
10% { 10% {
right: 8%; inset-inline-end: 8%;
} }
20% { 20% {
right: 18%; inset-inline-end: 18%;
} }
30% { 30% {
right: 29%; inset-inline-end: 29%;
} }
40% { 40% {
right: 40%; inset-inline-end: 40%;
} }
50% { 50% {
right: 51%; inset-inline-end: 51%;
} }
60% { 60% {
right: 62%; inset-inline-end: 62%;
} }
70% { 70% {
right: 72%; inset-inline-end: 72%;
} }
80% { 80% {
right: 82%; inset-inline-end: 82%;
} }
90% { 90% {
right: 92%; inset-inline-end: 92%;
} }
100% { 100% {
right: 102%; inset-inline-end: 102%;
} }
} }
@ -158,7 +177,7 @@
animation: roadStab 1s ease-out infinite, cloudStab 1s ease-out infinite; animation: roadStab 1s ease-out infinite, cloudStab 1s ease-out infinite;
position: absolute; position: absolute;
bottom: -50px; bottom: -50px;
left: -50%; inset-inline-start: -50%;
overflow: hidden; overflow: hidden;
} }
@ -183,7 +202,7 @@
composes: cloud; composes: cloud;
top: 65px; top: 65px;
right: -30%; inset-inline-end: -30%;
width: 50px; width: 50px;
height: 16px; height: 16px;
animation: cloudTravelling 21s 5s linear infinite; animation: cloudTravelling 21s 5s linear infinite;
@ -193,7 +212,7 @@
composes: cloud; composes: cloud;
top: 40px; top: 40px;
right: -30%; inset-inline-end: -30%;
width: 70px; width: 70px;
height: 22px; height: 22px;
animation: cloudTravelling 26s 11s linear infinite; animation: cloudTravelling 26s 11s linear infinite;
@ -201,10 +220,10 @@
@keyframes cloudTravelling { @keyframes cloudTravelling {
0% { 0% {
right: -30%; inset-inline-end: -30%;
} }
100% { 100% {
right: 110%; inset-inline-end: 110%;
} }
} }

View File

@ -34,12 +34,10 @@ $sidebar-width: 320px;
@media (min-width: 720px) { @media (min-width: 720px) {
.content { .content {
padding: 55px 50px; padding: 55px 50px;
margin-left: $sidebar-width; margin-inline-start: $sidebar-width;
} }
.sidebar { .sidebar {
right: auto;
width: $sidebar-width; width: $sidebar-width;
} }

View File

@ -6,7 +6,7 @@
width: 100%; width: 100%;
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
left: 0; inset-inline-start: 0; // TODO: does nothing. Maybe should be reimplemented?
text-align: center; text-align: center;
} }

View File

@ -6,7 +6,7 @@
width: 100%; width: 100%;
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
left: 0; inset-inline-start: 0;
text-align: center; text-align: center;
} }

View File

@ -32,7 +32,7 @@ $toolbarHeight: 50px;
.toolbarContent { .toolbarContent {
composes: wrapper; composes: wrapper;
position: relative; display: flex;
} }
.siteName { .siteName {
@ -44,15 +44,11 @@ $toolbarHeight: 50px;
font-family: $font-family-title; font-family: $font-family-title;
font-size: 33px; font-size: 33px;
color: #fff!important; // TODO: why? color: #fff!important; // Important to remove hover effect, which is inherited from the global <a> style
} }
.userBar { .userBar {
position: absolute; margin-inline-start: auto;
right: 0;
left: 115px;
top: 0;
text-align: right;
} }
.body { .body {

View File

@ -50,7 +50,7 @@
.rulesList { .rulesList {
padding: 0; padding: 0;
margin: 0; margin: 0;
padding-left: 20px; padding-inline-start: 20px;
} }
.rulesItem { .rulesItem {
@ -71,7 +71,7 @@
content: ''; content: '';
position: absolute; position: absolute;
top: -10px; top: -10px;
left: -40px; inset-inline-start: -40px;
width: calc(100% + 60px); width: calc(100% + 60px);
height: calc(100% + 20px); height: calc(100% + 20px);
background: $white; background: $white;

View File

@ -47,6 +47,7 @@ module.exports = ({ webpack: loader }) => ({
return defaultLoad(filename, importOptions); return defaultLoad(filename, importOptions);
})(require('postcss-import/lib/load-content')), })(require('postcss-import/lib/load-content')),
}, },
'postcss-bidirection': {},
// TODO: for some reason cssnano strips out @mixin declarations // TODO: for some reason cssnano strips out @mixin declarations
// cssnano: { // cssnano: {
// /** // /**

View File

@ -12540,6 +12540,12 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
"postcss-bidirection@https://github.com/erickskrauch/postcss-bidirection.git#iss_23":
version "2.7.2"
resolved "https://github.com/erickskrauch/postcss-bidirection.git#feabf42c8ab5cf6b0e22f78de04984e22cf42ba4"
dependencies:
postcss "^7.0.13"
postcss-calc@^7.0.1: postcss-calc@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436"
@ -12922,6 +12928,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.2
source-map "^0.6.1" source-map "^0.6.1"
supports-color "^6.1.0" supports-color "^6.1.0"
postcss@^7.0.13:
version "7.0.35"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
dependencies:
chalk "^2.4.2"
source-map "^0.6.1"
supports-color "^6.1.0"
postcss@^7.0.26: postcss@^7.0.26:
version "7.0.26" version "7.0.26"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587"