diff --git a/doczrc.js b/doczrc.js
index e92fecb5e..ec1200ff1 100644
--- a/doczrc.js
+++ b/doczrc.js
@@ -5,6 +5,18 @@ const path = require("path");
const fs = require("fs");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const extensions = [".ts", ".tsx", ".js"];
+// TODO: There is some weird issue with including paths.ts here
+const postCSSConfigPath = "./src/core/build/postcss.config";
+const isProduction = process.NODE_ENV === "production";
+const appDirectory = fs.realpathSync(process.cwd());
+
+const styleLoader = {
+ loader: require.resolve("style-loader"),
+ options: {
+ sourceMap: true,
+ hmr: true,
+ },
+};
export default {
title: "Talk 5.0",
@@ -14,27 +26,69 @@ export default {
port: parseInt(process.env.DOCZ_PORT, 10) || 3030,
codeSandbox: false, // Too large to create code sandboxes..
modifyBundlerConfig: config => {
+ config.entry.app.push(
+ `${appDirectory}/src/core/client/ui/theme/variables.css.ts`
+ );
config.module.rules.push({
- test: /\.css$/,
+ test: /\.css\.ts$/,
use: [
- require.resolve("style-loader"),
+ isProduction ? MiniCssExtractPlugin.loader : styleLoader,
{
loader: require.resolve("css-loader"),
options: {
modules: true,
- importLoaders: 1,
- localIdentName:
- process.env.NODE_ENV === "production"
- ? "[hash:base64]"
- : "[name]-[local]-[hash:base64:5]",
+ importLoaders: 2,
+ localIdentName: "[name]-[local]-[hash:base64:5]",
+ sourceMap: true,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
- // TODO: There is some weird issue with including paths.ts here
- path: "./src/core/build/postcss.config",
+ path: postCSSConfigPath,
+ },
+ parser: "postcss-js",
+ },
+ },
+ {
+ loader: require.resolve("babel-loader"),
+ options: {
+ configFile: false,
+ babelrc: false,
+ presets: [
+ "@babel/typescript",
+ [
+ "@babel/env",
+ { targets: { node: "10.0.0" }, modules: "commonjs" },
+ ],
+ ],
+ // This is a feature of `babel-loader` for webpack (not Babel itself).
+ // It enables caching results in ./node_modules/.cache/babel-loader/
+ // directory for faster rebuilds.
+ cacheDirectory: true,
+ },
+ },
+ ],
+ });
+ config.module.rules.push({
+ test: /\.css$/,
+ use: [
+ styleLoader,
+ {
+ loader: require.resolve("css-loader"),
+ options: {
+ modules: true,
+ importLoaders: 1,
+ localIdentName: "[name]-[local]-[hash:base64:5]",
+ sourceMap: true,
+ },
+ },
+ {
+ loader: require.resolve("postcss-loader"),
+ options: {
+ config: {
+ path: postCSSConfigPath,
},
},
},
diff --git a/package-lock.json b/package-lock.json
index d101c5608..e01d1ce4c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2317,13 +2317,13 @@
}
},
"@babel/preset-typescript": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.1.0.tgz",
- "integrity": "sha512-LYveByuF9AOM8WrsNne5+N79k1YxjNB6gmpCQsnuSBAcV8QUeB+ZUxQzL7Rz7HksPbahymKkq2qBR+o36ggFZA==",
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz",
+ "integrity": "sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-transform-typescript": "^7.1.0"
+ "@babel/plugin-transform-typescript": "^7.3.2"
}
},
"@babel/runtime": {
@@ -3568,6 +3568,12 @@
"@types/express": "*"
}
},
+ "@types/flat": {
+ "version": "0.0.28",
+ "resolved": "https://registry.npmjs.org/@types/flat/-/flat-0.0.28.tgz",
+ "integrity": "sha1-XHiBSdhabPj/X18ACs3ZEs3qQnQ=",
+ "dev": true
+ },
"@types/fs-extra": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz",
@@ -4620,9 +4626,13 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
},
"ansi-wrap": {
"version": "0.1.0",
@@ -5360,6 +5370,14 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
}
}
@@ -6296,6 +6314,16 @@
"semver": "^5.3.0"
}
},
+ "@babel/preset-typescript": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.1.0.tgz",
+ "integrity": "sha512-LYveByuF9AOM8WrsNne5+N79k1YxjNB6gmpCQsnuSBAcV8QUeB+ZUxQzL7Rz7HksPbahymKkq2qBR+o36ggFZA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-transform-typescript": "^7.1.0"
+ }
+ },
"@babel/template": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
@@ -9258,6 +9286,12 @@
"supports-color": "^2.0.0"
},
"dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@@ -14658,6 +14692,14 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
}
}
@@ -16105,6 +16147,14 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
}
}
@@ -20768,6 +20818,14 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
},
"figures": {
@@ -25140,50 +25198,19 @@
}
},
"postcss-js": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.0.tgz",
- "integrity": "sha512-9kAApW9G5kN8FkQ0ZdvSmbgbHIRrKmXtde2ZWYbwrW51gfEWfGsLlUu57mTpioPrmQlQFOgEvaeGYp+poqlX0A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.1.tgz",
+ "integrity": "sha512-8XQGohCbj6+kq8e3w6WlexkGaSjb5S8zoXnH49eB8JC6+qN2kQW+ib6fTjRgCpRRN9eeFOhMlD0NDjThW1DCBg==",
"dev": true,
"requires": {
- "camelcase-css": "^2.0.0",
- "postcss": "^7.0.0"
+ "camelcase-css": "^2.0.1",
+ "postcss": "^7.0.14"
},
"dependencies": {
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
"postcss": {
- "version": "7.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz",
- "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==",
+ "version": "7.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz",
+ "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
@@ -26467,6 +26494,12 @@
"supports-color": "^2.0.0"
},
"dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@@ -29321,6 +29354,14 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
},
"cliui": {
@@ -35102,6 +35143,11 @@
"xtend": "^4.0.0"
},
"dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
diff --git a/package.json b/package.json
index e4a5367af..09ce80367 100644
--- a/package.json
+++ b/package.json
@@ -135,6 +135,7 @@
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@babel/preset-react": "^7.0.0",
+ "@babel/preset-typescript": "^7.3.3",
"@coralproject/rte": "^0.10.13",
"@intervolga/optimize-cssnano-plugin": "^1.0.6",
"@types/basic-auth": "^1.1.2",
@@ -155,6 +156,7 @@
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/eventemitter2": "^4.1.0",
"@types/express": "^4.16.0",
+ "@types/flat": "0.0.28",
"@types/fs-extra": "^5.0.4",
"@types/graphql": "^0.13.3",
"@types/html-minifier": "^3.5.2",
@@ -210,6 +212,7 @@
"@types/webpack-dev-server": "^3.1.5",
"@types/ws": "^5.1.2",
"acorn": "^6.1.1",
+ "ansi-styles": "^3.2.0",
"autoprefixer": "^9.5.1",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^23.6.0",
@@ -271,6 +274,7 @@
"postcss-flexbugs-fixes": "^4.1.0",
"postcss-font-magician": "^2.2.1",
"postcss-import": "^11.1.0",
+ "postcss-js": "^2.0.1",
"postcss-loader": "^3.0.0",
"postcss-mixins": "^6.2.1",
"postcss-nested": "^4.1.1",
diff --git a/src/core/build/createWebpackConfig.ts b/src/core/build/createWebpackConfig.ts
index d4bb1c904..b5b4711ef 100644
--- a/src/core/build/createWebpackConfig.ts
+++ b/src/core/build/createWebpackConfig.ts
@@ -92,7 +92,7 @@ export default function createWebpackConfig(
fallbackLocale: "en-US",
// Common fluent files are always included in the locale bundles.
- commonFiles: ["framework.ftl", "common.ftl"],
+ commonFiles: ["framework.ftl", "common.ftl", "ui.ftl"],
// Locales that come with the main bundle. Others are loaded on demand.
bundled: ["en-US"],
@@ -350,6 +350,48 @@ export default function createWebpackConfig(
: "assets/media/[name].[ext]",
},
},
+ {
+ test: /\.css\.ts$/,
+ use: [
+ !watch ? MiniCssExtractPlugin.loader : styleLoader,
+ {
+ loader: require.resolve("css-loader"),
+ options: {
+ modules: true,
+ importLoaders: 2,
+ localIdentName: "[name]-[local]-[hash:base64:5]",
+ sourceMap: !disableSourcemaps,
+ },
+ },
+ {
+ loader: require.resolve("postcss-loader"),
+ options: {
+ config: {
+ path: paths.appPostCssConfig,
+ },
+ parser: "postcss-js",
+ },
+ },
+ {
+ loader: require.resolve("babel-loader"),
+ options: {
+ configFile: false,
+ babelrc: false,
+ presets: [
+ "@babel/typescript",
+ [
+ "@babel/env",
+ { targets: { node: "10.0.0" }, modules: "commonjs" },
+ ],
+ ],
+ // This is a feature of `babel-loader` for webpack (not Babel itself).
+ // It enables caching results in ./node_modules/.cache/babel-loader/
+ // directory for faster rebuilds.
+ cacheDirectory: true,
+ },
+ },
+ ],
+ },
// Process JS with Babel.
{
test: /\.(ts|tsx)$/,
@@ -373,7 +415,7 @@ export default function createWebpackConfig(
},
},
{
- loader: "ts-loader",
+ loader: require.resolve("ts-loader"),
options: {
configFile: paths.appTsconfig,
compilerOptions: {
diff --git a/src/core/build/postcss.config.js b/src/core/build/postcss.config.js
index 6bbf0123b..03c0a3b04 100644
--- a/src/core/build/postcss.config.js
+++ b/src/core/build/postcss.config.js
@@ -9,7 +9,6 @@ const paths = require("./paths").default;
const autoprefixer = require("autoprefixer");
const postcssFontMagician = require("postcss-font-magician");
const postcssFlexbugsFixes = require("postcss-flexbugs-fixes");
-const postcssVariables = require("postcss-css-variables");
const postcssPresetEnv = require("postcss-preset-env");
const postcssNested = require("postcss-nested");
const postcssImport = require("postcss-import");
@@ -49,7 +48,7 @@ module.exports = {
// This allows us to define dynamic css variables.
postcssPrependImports({
path: "",
- files: [paths.appThemeVariablesCSS, paths.appThemeMixinsCSS],
+ files: [paths.appThemeMixinsCSS],
}),
// Needed by above plugin.
postcssImport(),
@@ -59,10 +58,6 @@ module.exports = {
postcssNested(),
// Sass style variables to be used in media queries.
postcssAdvancedVariables({ variables: mediaQueryVariables }),
- // CSS standard variables for everything else.
- postcssVariables({
- variables: cssVariables,
- }),
// Provides a modern CSS environment.
postcssPresetEnv(),
// Does all the font handling logic.
diff --git a/src/core/client/account/index.tsx b/src/core/client/account/index.tsx
index db74f736f..7318db694 100644
--- a/src/core/client/account/index.tsx
+++ b/src/core/client/account/index.tsx
@@ -6,6 +6,9 @@ import App from "./App";
import { initLocalState } from "./local";
import localesData from "./locales";
+// Import css variables.
+import "talk-ui/theme/variables.css";
+
async function main() {
const ManagedTalkContextProvider = await createManaged({
initLocalState,
diff --git a/src/core/client/admin/index.tsx b/src/core/client/admin/index.tsx
index d42226900..e86246149 100644
--- a/src/core/client/admin/index.tsx
+++ b/src/core/client/admin/index.tsx
@@ -6,6 +6,9 @@ import EntryContainer from "./containers/EntryContainer";
import { initLocalState } from "./local";
import localesData from "./locales";
+// Import css variables.
+import "talk-ui/theme/variables.css";
+
async function main() {
const ManagedTalkContextProvider = await createManaged({
initLocalState,
diff --git a/src/core/client/auth/index.tsx b/src/core/client/auth/index.tsx
index 14c11ebbc..aa12ccf79 100644
--- a/src/core/client/auth/index.tsx
+++ b/src/core/client/auth/index.tsx
@@ -10,6 +10,9 @@ import { initLocalState } from "./local";
import localesData from "./locales";
import AppQuery from "./queries/AppQuery";
+// Import css variables.
+import "talk-ui/theme/variables.css";
+
/**
* Adapt popup height to current content every 100ms.
*
diff --git a/src/core/client/framework/testHelpers/createFluentBundle.ts b/src/core/client/framework/testHelpers/createFluentBundle.ts
index 1edc6d701..bbd9ca37b 100644
--- a/src/core/client/framework/testHelpers/createFluentBundle.ts
+++ b/src/core/client/framework/testHelpers/createFluentBundle.ts
@@ -7,7 +7,7 @@ import fs from "fs";
import path from "path";
// These locale prefixes are always loaded.
-const commonPrefixes = ["common", "framework"];
+const commonPrefixes = ["ui", "common", "framework"];
function decorateErrorWhenMissing(bundle: FluentBundle) {
const originalHasMessage = bundle.hasMessage;
diff --git a/src/core/client/install/index.tsx b/src/core/client/install/index.tsx
index ab548fb3e..879c7cd7e 100644
--- a/src/core/client/install/index.tsx
+++ b/src/core/client/install/index.tsx
@@ -7,6 +7,9 @@ import { createManaged } from "talk-framework/lib/bootstrap";
import App from "./components/App";
import localesData from "./locales";
+// Import css variables.
+import "talk-ui/theme/variables.css";
+
async function main() {
const ManagedTalkContextProvider = await createManaged({
localesData,
diff --git a/src/core/client/stream/index.tsx b/src/core/client/stream/index.tsx
index d1f311dc3..ee7cb7029 100644
--- a/src/core/client/stream/index.tsx
+++ b/src/core/client/stream/index.tsx
@@ -16,6 +16,9 @@ import {
import { initLocalState } from "./local";
import localesData from "./locales";
+// Import css variables.
+import "talk-ui/theme/variables.css";
+
const listeners = (
<>
diff --git a/src/core/client/ui/components/Brand/BrandName.tsx b/src/core/client/ui/components/Brand/BrandName.tsx
index 9f5f10d9a..8d5d69bab 100644
--- a/src/core/client/ui/components/Brand/BrandName.tsx
+++ b/src/core/client/ui/components/Brand/BrandName.tsx
@@ -22,7 +22,7 @@ const BrandName: FunctionComponent = ({
size,
...rest
}) => (
-
+
v.toString()),
+ (_, k) => `--${kebabCase(k)}`
+);
+
+// These are the default css standard variables.
+const cssVariables = pickBy(
+ flatKebabVariables,
+ (v, k) => !k.startsWith("breakpoints-")
+);
+
+const style = {
+ ":root": {
+ ...cssVariables,
+ "--mini-unit": "calc(1px * var(--mini-unit-small))",
+ },
+ [`@media (min-width: ${variables.breakpoints.xs}px)`]: {
+ ":root": {
+ "--mini-unit": "calc(1px * var(--mini-unit-large))",
+ },
+ },
+};
+
+module.exports = style;
diff --git a/src/locales/en-US/admin.ftl b/src/locales/en-US/admin.ftl
index f62898109..9c09dc43f 100644
--- a/src/locales/en-US/admin.ftl
+++ b/src/locales/en-US/admin.ftl
@@ -1,8 +1,6 @@
### Localization for Admin
## General
-
-general-brandName = { -product-name }
general-notAvailable = Not available
## Story Status
diff --git a/src/locales/en-US/ui.ftl b/src/locales/en-US/ui.ftl
new file mode 100644
index 000000000..dd9ad4825
--- /dev/null
+++ b/src/locales/en-US/ui.ftl
@@ -0,0 +1 @@
+ui-brandName = { -product-name }