diff --git a/package-lock.json b/package-lock.json
index 66c994750..fef276257 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2618,6 +2618,142 @@
"sdp-transform": "2.3.0"
}
},
+ "@material-ui/core": {
+ "version": "4.11.3",
+ "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.3.tgz",
+ "integrity": "sha512-Adt40rGW6Uds+cAyk3pVgcErpzU/qxc7KBR94jFHBYretU4AtWZltYcNsbeMn9tXL86jjVL1kuGcIHsgLgFGRw==",
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "@material-ui/styles": "^4.11.3",
+ "@material-ui/system": "^4.11.3",
+ "@material-ui/types": "^5.1.0",
+ "@material-ui/utils": "^4.11.2",
+ "@types/react-transition-group": "^4.2.0",
+ "clsx": "^1.0.4",
+ "hoist-non-react-statics": "^3.3.2",
+ "popper.js": "1.16.1-lts",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.0 || ^17.0.0",
+ "react-transition-group": "^4.4.0"
+ },
+ "dependencies": {
+ "csstype": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
+ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
+ },
+ "dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "requires": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.13.17",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.17.tgz",
+ "integrity": "sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ }
+ }
+ },
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "popper.js": {
+ "version": "1.16.1-lts",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
+ "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA=="
+ },
+ "react-transition-group": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
+ "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ }
+ }
+ }
+ },
+ "@material-ui/styles": {
+ "version": "4.11.4",
+ "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
+ "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "@emotion/hash": "^0.8.0",
+ "@material-ui/types": "5.1.0",
+ "@material-ui/utils": "^4.11.2",
+ "clsx": "^1.0.4",
+ "csstype": "^2.5.2",
+ "hoist-non-react-statics": "^3.3.2",
+ "jss": "^10.5.1",
+ "jss-plugin-camel-case": "^10.5.1",
+ "jss-plugin-default-unit": "^10.5.1",
+ "jss-plugin-global": "^10.5.1",
+ "jss-plugin-nested": "^10.5.1",
+ "jss-plugin-props-sort": "^10.5.1",
+ "jss-plugin-rule-value-function": "^10.5.1",
+ "jss-plugin-vendor-prefixer": "^10.5.1",
+ "prop-types": "^15.7.2"
+ },
+ "dependencies": {
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ }
+ }
+ },
+ "@material-ui/system": {
+ "version": "4.11.3",
+ "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz",
+ "integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==",
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "@material-ui/utils": "^4.11.2",
+ "csstype": "^2.5.2",
+ "prop-types": "^15.7.2"
+ }
+ },
+ "@material-ui/types": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
+ "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A=="
+ },
+ "@material-ui/utils": {
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
+ "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.0 || ^17.0.0"
+ }
+ },
"@microsoft/microsoft-graph-client": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-1.1.0.tgz",
@@ -3848,11 +3984,46 @@
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
},
+ "@types/prop-types": {
+ "version": "15.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
+ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
+ },
"@types/q": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
},
+ "@types/react": {
+ "version": "17.0.4",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz",
+ "integrity": "sha512-onz2BqScSFMoTRdJUZUDD/7xrusM8hBA2Fktk2qgaTYPCgPvWnDEgkrOs8hhPUf2jfcIXkJ5yK6VfYormJS3Jw==",
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ },
+ "dependencies": {
+ "csstype": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
+ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
+ }
+ }
+ },
+ "@types/react-transition-group": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz",
+ "integrity": "sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
+ "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
+ },
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
@@ -6048,6 +6219,11 @@
"shallow-clone": "^0.1.2"
}
},
+ "clsx": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
+ "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -6686,6 +6862,25 @@
}
}
},
+ "css-vendor": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
+ "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==",
+ "requires": {
+ "@babel/runtime": "^7.8.3",
+ "is-in-browser": "^1.0.2"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.13.17",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.17.tgz",
+ "integrity": "sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ }
+ }
+ },
"css-what": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz",
@@ -9408,6 +9603,11 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"dev": true
},
+ "hyphenate-style-name": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+ },
"i18n-iso-countries": {
"version": "3.7.8",
"resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-3.7.8.tgz",
@@ -9603,6 +9803,14 @@
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
},
+ "indefinite-observable": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-2.0.1.tgz",
+ "integrity": "sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ==",
+ "requires": {
+ "symbol-observable": "1.2.0"
+ }
+ },
"indexes-of": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
@@ -9922,6 +10130,11 @@
"is-extglob": "^2.1.1"
}
},
+ "is-in-browser": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
+ "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
+ },
"is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@@ -10439,6 +10652,92 @@
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
},
+ "jss": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss/-/jss-10.6.0.tgz",
+ "integrity": "sha512-n7SHdCozmxnzYGXBHe0NsO0eUf9TvsHVq2MXvi4JmTn3x5raynodDVE/9VQmBdWFyyj9HpHZ2B4xNZ7MMy7lkw==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "csstype": "^3.0.2",
+ "indefinite-observable": "^2.0.1",
+ "is-in-browser": "^1.1.3",
+ "tiny-warning": "^1.0.2"
+ },
+ "dependencies": {
+ "csstype": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
+ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
+ }
+ }
+ },
+ "jss-plugin-camel-case": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.6.0.tgz",
+ "integrity": "sha512-JdLpA3aI/npwj3nDMKk308pvnhoSzkW3PXlbgHAzfx0yHWnPPVUjPhXFtLJzgKZge8lsfkUxvYSQ3X2OYIFU6A==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "hyphenate-style-name": "^1.0.3",
+ "jss": "10.6.0"
+ }
+ },
+ "jss-plugin-default-unit": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.6.0.tgz",
+ "integrity": "sha512-7y4cAScMHAxvslBK2JRK37ES9UT0YfTIXWgzUWD5euvR+JR3q+o8sQKzBw7GmkQRfZijrRJKNTiSt1PBsLI9/w==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "jss": "10.6.0"
+ }
+ },
+ "jss-plugin-global": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.6.0.tgz",
+ "integrity": "sha512-I3w7ji/UXPi3VuWrTCbHG9rVCgB4yoBQLehGDTmsnDfXQb3r1l3WIdcO8JFp9m0YMmyy2CU7UOV6oPI7/Tmu+w==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "jss": "10.6.0"
+ }
+ },
+ "jss-plugin-nested": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.6.0.tgz",
+ "integrity": "sha512-fOFQWgd98H89E6aJSNkEh2fAXquC9aZcAVjSw4q4RoQ9gU++emg18encR4AT4OOIFl4lQwt5nEyBBRn9V1Rk8g==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "jss": "10.6.0",
+ "tiny-warning": "^1.0.2"
+ }
+ },
+ "jss-plugin-props-sort": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.6.0.tgz",
+ "integrity": "sha512-oMCe7hgho2FllNc60d9VAfdtMrZPo9n1Iu6RNa+3p9n0Bkvnv/XX5San8fTPujrTBScPqv9mOE0nWVvIaohNuw==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "jss": "10.6.0"
+ }
+ },
+ "jss-plugin-rule-value-function": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.6.0.tgz",
+ "integrity": "sha512-TKFqhRTDHN1QrPTMYRlIQUOC2FFQb271+AbnetURKlGvRl/eWLswcgHQajwuxI464uZk91sPiTtdGi7r7XaWfA==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "jss": "10.6.0",
+ "tiny-warning": "^1.0.2"
+ }
+ },
+ "jss-plugin-vendor-prefixer": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.6.0.tgz",
+ "integrity": "sha512-doJ7MouBXT1lypLLctCwb4nJ6lDYqrTfVS3LtXgox42Xz0gXusXIIDboeh6UwnSmox90QpVnub7au8ybrb0krQ==",
+ "requires": {
+ "@babel/runtime": "^7.3.1",
+ "css-vendor": "^2.0.8",
+ "jss": "10.6.0"
+ }
+ },
"jssha": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz",
@@ -16892,6 +17191,11 @@
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-0.0.3.tgz",
"integrity": "sha512-SA2YwvDrCITM9fTvHTHRpq9W6L2fBsClbqm3maT5PZux4Z73SPPDYwJMtnoWh6WMgmCkJij/LaOlWiqJqFMK8g=="
},
+ "tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"tlds": {
"version": "1.203.1",
"resolved": "https://registry.npmjs.org/tlds/-/tlds-1.203.1.tgz",
diff --git a/package.json b/package.json
index 3ed72d3fe..65101a299 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@atlaskit/toggle": "12.0.3",
"@atlaskit/tooltip": "17.1.2",
"@jitsi/js-utils": "1.0.6",
+ "@material-ui/core": "4.11.3",
"@microsoft/microsoft-graph-client": "1.1.0",
"@react-native-async-storage/async-storage": "1.13.2",
"@react-native-community/google-signin": "3.0.1",
@@ -145,6 +146,7 @@
"license": "Apache-2.0",
"scripts": {
"lint": "eslint . && flow",
+ "lint-fix": "eslint --fix .",
"postinstall": "jetify",
"validate": "npm ls",
"start": "make dev",
diff --git a/react/features/app/components/App.web.js b/react/features/app/components/App.web.js
index e8e029ae9..f19edb7f9 100644
--- a/react/features/app/components/App.web.js
+++ b/react/features/app/components/App.web.js
@@ -4,6 +4,7 @@ import { AtlasKitThemeProvider } from '@atlaskit/theme';
import React from 'react';
import { DialogContainer } from '../../base/dialog';
+import JitsiThemeProvider from '../../base/ui/components/JitsiThemeProvider';
import { ChromeExtensionBanner } from '../../chrome-extension-banner';
import { AbstractApp } from './AbstractApp';
@@ -26,10 +27,12 @@ export class App extends AbstractApp {
*/
_createMainElement(component, props) {
return (
-
-
- { super._createMainElement(component, props) }
-
+
+
+
+ { super._createMainElement(component, props) }
+
+
);
}
diff --git a/react/features/base/ui/Tokens.js b/react/features/base/ui/Tokens.js
new file mode 100644
index 000000000..04ee329ca
--- /dev/null
+++ b/react/features/base/ui/Tokens.js
@@ -0,0 +1,325 @@
+// @flow
+
+// Default color pallete
+export const colors = {
+ error03: '#7A141F',
+ error04: '#A21B29',
+ error05: '#CB2233',
+ error06: '#E04757',
+ error08: '#EAA7AD',
+
+ primary01: '#00112D',
+ primary02: '#00225A',
+ primary03: '#003486',
+ primary04: '#0045B3',
+ primary05: '#0056E0',
+ primary06: '#246FE5',
+ primary07: '#669AEC',
+ primary08: '#99BBF3',
+ primary09: '#CCDDF9',
+
+ surface01: '#040404',
+ surface02: '#141414',
+ surface03: '#292929',
+ surface04: '#3D3D3D',
+ surface05: '#525252',
+ surface06: '#666',
+ surface07: '#858585',
+ surface08: '#A3A3A3',
+ surface09: '#C2C2C2',
+ surface10: '#E0E0E0',
+ surface11: '#FFF',
+
+ success04: '#189B55',
+ success05: '#1EC26A',
+
+ warning05: '#F8AE1A'
+};
+
+// Mapping between the token used and the color
+export const colorMap = {
+ // Default page background
+ uiBackground: 'surface01',
+
+ // Container background
+ ui01: 'surface02',
+ ui02: 'surface03',
+ ui03: 'surface04',
+ ui04: 'surface05',
+ ui05: 'surface06',
+
+ // Primary buttons
+ action01: 'primary05',
+
+ // Hover state for primary buttons
+ action01Hover: 'primary06',
+
+ // Active state for primary buttons
+ action01Active: 'primary04',
+
+ // Focus border color
+ action01Focus: 'primary08',
+
+ // Disabled state for primary buttons
+ action01Disabled: 'primary02',
+
+ // Secondary buttons
+ action02: 'surface04',
+
+ // Hover state for secondary buttons
+ action02Hover: 'surface05',
+
+ // Active state for secondary buttons
+ action02Active: 'surface03',
+
+ // Focus border color
+ action02Focus: 'surface07',
+
+ // Disabled state for secondary buttons
+ action02Disabled: 'surface02',
+
+ // Tertiary buttons
+ action03: 'transparent',
+
+ // Hover state for tertiary buttons
+ action03Hover: 'surface05',
+
+ // Active state for tertiary buttons
+ action03Active: 'surface03',
+
+ // Focus border color
+ action03Focus: 'surface07',
+
+ // Disabled state for tertiary buttons
+ action03Disabled: 'transparent',
+
+ // Danger button background
+ actionDanger: 'error05',
+
+ // Hover state for danger buttons
+ actionDangerHover: 'error06',
+
+ // Active state for danger buttons
+ actionDangerActive: 'error04',
+
+ // Focus border color
+ actionDangerFocus: 'error08',
+
+ // Disabled state for danger buttons
+ actionDangerDisabled: 'error03',
+
+ // Primary text – default color for body copy & headers
+ text01: 'surface11',
+
+ // Secondary text with medium contrast
+ text02: 'surface09',
+
+ // Tertiary text with low contrast – placeholders, disabled actions, label for disabled buttons
+ text03: 'surface07',
+
+ // error messages
+ textError: 'error06',
+
+ // Primary color for icons
+ icon01: 'surface11',
+
+ // Secondary color for input fields
+ icon02: 'surface09',
+
+ // Tertiary color for disabled actions
+ icon03: 'surface07',
+
+ // Error message
+ iconError: 'error06',
+
+ // Forms
+ // Default background for input fields
+ field01: 'surface01',
+
+ // Hover background for input fields
+ field01Hover: 'surface03',
+
+ // Focus border color
+ field01Focus: 'primary05',
+
+ // Disabled background for input fields
+ field01Disabled: 'surface05',
+
+ // Background for high-contrast input fields
+ field02: 'surface11',
+
+ // Background for high-contrast input fields on hover
+ field02Hover: 'primary09',
+
+ // Focus border color
+ field02Focus: 'primary05',
+
+ // Disabled background for high-contrast input fields
+ field02Disabled: 'surface06',
+
+ // Borders
+ // Border for the input fields in hover state
+ border01: 'surface08',
+
+ // Border for the input fields
+ border02: 'surface06',
+
+ // Line separators
+ border03: 'surface04',
+
+ // Color for error border & message
+ borderError: 'error06',
+
+ // Links
+ // Default color for links
+ link01: 'primary07',
+
+ // Color for links in the hover state
+ link01Hover: 'primary08',
+
+ // Color for links in the active state
+ link01Active: 'primary06',
+
+ // Support
+ // Color for positive messages applied to icons & borders
+ success01: 'success05',
+
+ // Color for positive messages applied tobackgrounds
+ success02: 'success05',
+
+ // Color for warning messages applied to icons, borders & backgrounds
+ warning01: 'warning05'
+};
+
+
+export const font = {
+ weightRegular: 400,
+ weightSemiBold: 600
+};
+
+export const shape = {
+ borderRadius: 6
+};
+
+export const spacing = [ 0, 4, 8, 16, 24, 32, 40, 48, 56 ];
+
+export const typography = {
+ labelRegular: {
+ fontSize: 12,
+ lineHeight: 16,
+ fontWeight: font.weightRegular,
+ letterSpacing: 0.16
+ },
+
+ labelBold: {
+ fontSize: 12,
+ lineHeight: 16,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0.16
+ },
+
+ labelButton: {
+ fontSize: 14,
+ lineHeight: 24,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ labelButtonLarge: {
+ fontSize: 16,
+ lineHeight: 24,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ bodyShortRegular: {
+ fontSize: 14,
+ lineHeight: 18,
+ fontWeight: font.weightRegular,
+ letterSpacing: 0
+ },
+
+ bodyShortBold: {
+ fontSize: 14,
+ lineHeight: 18,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ bodyShortRegularLarge: {
+ fontSize: 16,
+ lineHeight: 24,
+ fontWeight: font.weightRegular,
+ letterSpacing: 0
+ },
+
+ bodyShortBoldLarge: {
+ fontSize: 16,
+ lineHeight: 24,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ bodyLongRegular: {
+ fontSize: 14,
+ lineHeight: 24,
+ fontWeight: font.weightRegular,
+ letterSpacing: 0
+ },
+
+ bodyLongBold: {
+ fontSize: 14,
+ lineHeight: 24,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading1: {
+ fontSize: 54,
+ lineHeight: 64,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading2: {
+ fontSize: 42,
+ lineHeight: 50,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading3: {
+ fontSize: 32,
+ lineHeight: 40,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading4: {
+ fontSize: 28,
+ lineHeight: 36,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading5: {
+ fontSize: 20,
+ lineHeight: 28,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading6: {
+ fontSize: 16,
+ lineHeight: 26,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ },
+
+ heading7: {
+ fontSize: 14,
+ lineHeight: 24,
+ fontWeight: font.weightSemiBold,
+ letterSpacing: 0
+ }
+};
diff --git a/react/features/base/ui/components/BaseTheme.web.js b/react/features/base/ui/components/BaseTheme.web.js
new file mode 100644
index 000000000..687418ddc
--- /dev/null
+++ b/react/features/base/ui/components/BaseTheme.web.js
@@ -0,0 +1,13 @@
+// @flow
+
+import { font, colors, colorMap, spacing, shape, typography } from '../Tokens';
+import { createWebTheme } from '../functions';
+
+export default createWebTheme({
+ font,
+ colors,
+ colorMap,
+ spacing,
+ shape,
+ typography
+});
diff --git a/react/features/base/ui/components/JitsiThemeProvider.web.js b/react/features/base/ui/components/JitsiThemeProvider.web.js
new file mode 100644
index 000000000..2a98facb2
--- /dev/null
+++ b/react/features/base/ui/components/JitsiThemeProvider.web.js
@@ -0,0 +1,24 @@
+// @flow
+
+import { ThemeProvider } from '@material-ui/core/styles';
+import * as React from 'react';
+
+import BaseTheme from './BaseTheme';
+
+type Props = {
+
+ /**
+ * The children of the component.
+ */
+ children: React.ChildrenArray
+}
+
+/**
+ * The theme provider for the web app.
+ *
+ * @param {Object} props - The props of the component.
+ * @returns {React.ReactNode}
+ */
+export default function JitsiThemeProvider(props: Props) {
+ return { props.children };
+}
diff --git a/react/features/base/ui/functions.js b/react/features/base/ui/functions.js
new file mode 100644
index 000000000..952f4bb38
--- /dev/null
+++ b/react/features/base/ui/functions.js
@@ -0,0 +1,44 @@
+// @flow
+
+import { createMuiTheme } from '@material-ui/core/styles';
+
+/**
+ * Creates the color tokens based on the color theme and the association map.
+ * If a key is not fonund in the association map it defaults to the current value.
+ *
+ * @param {Object} colorMap - A map between the token name and the actual color value.
+ * @param {Object} colors - An object containing all the theme colors.
+ * @returns {Object}
+ */
+function createColorTokens(colorMap: Object, colors: Object): Object {
+ return Object.entries(colorMap)
+ .reduce((result, [ token, value ]) =>
+ Object.assign(result, { [token]: colors[value] || value }), {});
+}
+
+/**
+ * Creates a MUI theme based on local UI tokens.
+ *
+ * @param {Object} arg - The ui tokens.
+ * @returns {Object}
+ */
+export function createWebTheme({ font, colors, colorMap, shape, spacing, typography }: Object) {
+ return createMuiTheme({
+ props: {
+ // disable ripple effect on buttons globally
+ MuiButtonBase: {
+ disableRipple: true
+ }
+ },
+
+ // use token spacing array
+ spacing
+ }, {
+ palette: createColorTokens(colorMap, colors),
+ shape,
+ typography: {
+ font,
+ ...typography
+ }
+ });
+}