diff --git a/web/.eslintrc.js b/web/.eslintrc.js
index 79673a7c8..e25c5092d 100644
--- a/web/.eslintrc.js
+++ b/web/.eslintrc.js
@@ -19,6 +19,7 @@ module.exports = {
sourceType: 'module',
},
plugins: ['react', 'prettier', '@typescript-eslint'],
+ ignorePatterns: ['!./storybook/**'],
rules: {
'prettier/prettier': 'error',
'react/react-in-jsx-scope': 'off',
diff --git a/web/.gitignore b/web/.gitignore
index 6f9f825cf..32885bae4 100644
--- a/web/.gitignore
+++ b/web/.gitignore
@@ -5,3 +5,4 @@ node_modules
out
lefthook.yml
+storybook-static
diff --git a/web/.storybook/main.js b/web/.storybook/main.js
index bbe91b517..9af782912 100644
--- a/web/.storybook/main.js
+++ b/web/.storybook/main.js
@@ -1,4 +1,7 @@
module.exports = {
+ core: {
+ builder: 'webpack5',
+ },
stories: ['../stories/**/*.stories.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
@@ -7,5 +10,21 @@ module.exports = {
'@storybook/preset-scss',
'@storybook/addon-postcss',
],
+ webpackFinal: async (config, { configType }) => {
+ config.module.rules.push({
+ test: /\.less$/,
+ use: [
+ require.resolve('style-loader'),
+ require.resolve('css-loader'),
+ {
+ loader: require.resolve('less-loader'),
+ options: {
+ lessOptions: { javascriptEnabled: true },
+ },
+ },
+ ],
+ });
+ return config;
+ },
framework: '@storybook/react',
};
diff --git a/web/.storybook/preview.js b/web/.storybook/preview.js
index 2105d9b21..34fe7dfb6 100644
--- a/web/.storybook/preview.js
+++ b/web/.storybook/preview.js
@@ -1,5 +1,4 @@
-import 'antd/dist/antd.css';
-import '../styles/globals.scss';
+import '../styles/global.less';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
diff --git a/web/next.config.js b/web/next.config.js
index a94cfa43a..1ed3dd98f 100644
--- a/web/next.config.js
+++ b/web/next.config.js
@@ -1,4 +1,6 @@
-module.exports = {
- basePath: "/admin",
+const withLess = require('next-with-less');
+
+module.exports = withLess({
+ basePath: '/admin',
trailingSlash: true,
-};
+});
diff --git a/web/package.json b/web/package.json
index 9d3957e8c..b5138ddcd 100644
--- a/web/package.json
+++ b/web/package.json
@@ -22,6 +22,7 @@
"lodash": "4.17.21",
"markdown-it": "12.3.2",
"next": "^12.1.5",
+ "next-with-less": "^2.0.5",
"postcss-flexbugs-fixes": "^5.0.2",
"prop-types": "15.8.1",
"rc-overflow": "1.2.4",
@@ -41,6 +42,8 @@
"@storybook/addon-interactions": "^6.4.22",
"@storybook/addon-links": "^6.4.22",
"@storybook/addon-postcss": "^2.0.0",
+ "@storybook/builder-webpack5": "^6.4.22",
+ "@storybook/manager-webpack5": "^6.4.22",
"@storybook/preset-scss": "^1.0.3",
"@storybook/testing-library": "^0.0.9",
"@types/chart.js": "2.9.35",
@@ -54,7 +57,7 @@
"@typescript-eslint/eslint-plugin": "5.10.2",
"@typescript-eslint/parser": "5.10.2",
"babel-loader": "^8.2.4",
- "css-loader": "^5.2.6",
+ "css-loader": "^5.2.7",
"eslint": "8.8.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-next": "12.0.10",
@@ -66,11 +69,14 @@
"eslint-plugin-react-hooks": "4.3.0",
"eslint-plugin-storybook": "^0.5.10",
"html-webpack-plugin": "^5.5.0",
+ "less": "^4.1.2",
+ "less-loader": "^10.2.0",
"prettier": "2.5.1",
"sass": "^1.50.0",
"sass-loader": "^10.1.1",
"sb": "^6.4.22",
+ "storybook-preset-less": "^1.1.2",
"style-loader": "^2.0.0",
"typescript": "4.5.5"
}
-}
\ No newline at end of file
+}
diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx
index 3f83e8c2c..81ce6f08d 100644
--- a/web/pages/_app.tsx
+++ b/web/pages/_app.tsx
@@ -1,9 +1,9 @@
// order matters!
-import 'antd/dist/antd.css';
+import '../styles/global.less';
+// import '../styles/globals.scss';
import '../styles/variables.scss';
-import '../styles/ant-overrides.scss';
+// import '../styles/ant-overrides.scss';
import '../styles/markdown-editor.scss';
-import '../styles/globals.scss';
import '../styles/main-layout.scss';
diff --git a/web/stories/Introduction.stories.mdx b/web/stories/Introduction.stories.mdx
index 42c4a8714..869019fea 100644
--- a/web/stories/Introduction.stories.mdx
+++ b/web/stories/Introduction.stories.mdx
@@ -114,74 +114,19 @@ import StackAlt from './assets/stackalt.svg';
`}
-# Welcome to Storybook
+# Owncast Component Library
-Storybook helps you build UI components in isolation from your app's business logic, data, and context.
-That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA.
+This is a place to build and experiment with styling individual components.
-Browse example stories now by navigating to them in the sidebar.
-View their code in the `src/stories` directory to learn how they work.
-We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.
+This approach helps build UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.
-
Configure
+## How to Edit
-
+In the web project edit the `styles/theme.less` file to change or add variables used in the components. When customizing Ant Design components refer to the list of variables at https://github.com/ant-design/ant-design/blob/master/components/style/themes/dark.less that you can override.
Learn
-
-
- TipEdit the Markdown in{' '}
- src/stories/Introduction.stories.mdx
diff --git a/web/styles/global.less b/web/styles/global.less
new file mode 100644
index 000000000..b871f6ed3
--- /dev/null
+++ b/web/styles/global.less
@@ -0,0 +1,5 @@
+// @import '~antd/dist/antd.less'; // Import Ant Design styles by less entry
+// @import '~antd/dist/antd.less';
+@import '~antd/dist/antd.dark.less'; // Introduce the official dark less style entry file
+@import './theme.less'; // Import owncast theme styles
+
diff --git a/web/styles/home.scss b/web/styles/home.scss
index 6c55feedc..6e5d35a7f 100644
--- a/web/styles/home.scss
+++ b/web/styles/home.scss
@@ -4,17 +4,17 @@
.online-details-card {
border-color: var(--online-color);
}
- .ant-statistic {
- text-align: center;
- }
- .ant-statistic-title {
- color: var(--white-50);
- }
+ // .ant-statistic {
+ // text-align: center;
+ // }
+ // .ant-statistic-title {
+ // color: var(--white-50);
+ // }
}
- .ant-card-head {
- color: var(--online-color);
- }
+ // .ant-card-head {
+ // color: var(--online-color);
+ // }
.stream-details-item-container {
margin: 1em 0;
@@ -22,17 +22,17 @@
margin-top: 0;
}
}
- .ant-statistic.stream-details-item {
- background-color: var(--black-50);
- padding: 1em;
- .ant-statistic-title {
- color: var(--blue);
- }
- .ant-statistic-content {
- font-size: 1.25em;
- white-space: nowrap;
- }
- }
+ // .ant-statistic.stream-details-item {
+ // background-color: var(--black-50);
+ // padding: 1em;
+ // .ant-statistic-title {
+ // color: var(--blue);
+ // }
+ // .ant-statistic-content {
+ // font-size: 1.25em;
+ // white-space: nowrap;
+ // }
+ // }
.stream-details {
> .ant-card-bordered {
@@ -46,16 +46,16 @@
.offline-content {
.logo-section {
- .ant-result-title {
- font-size: 2rem;
- }
- .ant-result-subtitle {
- font-size: 1rem;
- }
- .ant-result-icon svg {
- height: 8rem;
- width: 8rem;
- }
+ // .ant-result-title {
+ // font-size: 2rem;
+ // }
+ // .ant-result-subtitle {
+ // font-size: 1rem;
+ // }
+ // .ant-result-icon svg {
+ // height: 8rem;
+ // width: 8rem;
+ // }
}
.list-section {
background-color: var(--container-bg-color-alt);
@@ -65,13 +65,13 @@
> .ant-card {
background-color: var(--black);
margin-bottom: 1em;
- .ant-card-meta-avatar {
- margin-top: 0.25rem;
- svg {
- height: 1.5em;
- width: 1.5em;
- }
- }
+ // .ant-card-meta-avatar {
+ // margin-top: 0.25rem;
+ // svg {
+ // height: 1.5em;
+ // width: 1.5em;
+ // }
+ // }
}
}
}
diff --git a/web/styles/main-layout.scss b/web/styles/main-layout.scss
index 658b811c5..146247b46 100644
--- a/web/styles/main-layout.scss
+++ b/web/styles/main-layout.scss
@@ -112,15 +112,15 @@
align-items: center;
margin-bottom: 0;
- .ant-input-affix-wrapper {
- border-color: var(--owncast-purple-50);
- }
- input.ant-input {
- &::placeholder {
- color: var(--owncast-purple);
- text-align: center;
- }
- }
+ // .ant-input-affix-wrapper {
+ // border-color: var(--owncast-purple-50);
+ // }
+ // input.ant-input {
+ // &::placeholder {
+ // color: var(--owncast-purple);
+ // text-align: center;
+ // }
+ // }
.input-side {
width: 400px;
diff --git a/web/styles/theme.less b/web/styles/theme.less
new file mode 100644
index 000000000..8327b821f
--- /dev/null
+++ b/web/styles/theme.less
@@ -0,0 +1,40 @@
+@theme: owncast;
+
+// These overrides are only used for customizing the style of Ant Design
+// components and do not impact any custom components. Therefore CSS variables
+// should be set in a centralized place and used here so changes only need
+// to be made once.
+
+// Variable names can be found in
+// https://github.com/ant-design/ant-design/blob/master/components/style/themes/dark.less
+
+// From color palette
+@green-1: #D15AD5;
+@green-2: #6CE9A6;
+@green-3: #12B76A;
+@green-4: #027A48;
+@green-5: #054F31;
+// Defaults
+@green-6: mix(@green-base, @component-background, 85%);
+@green-7: mix(color(~`colorPalette('@{green-base}', 5) `), @component-background, 90%);
+@green-8: mix(color(~`colorPalette('@{green-base}', 4) `), @component-background, 95%);
+@green-9: mix(color(~`colorPalette('@{green-base}', 3) `), @component-background, 97%);
+@green-10: mix(color(~`colorPalette('@{green-base}', 2) `), @component-background, 98%);
+
+// From color palette
+@purple-1: #F4EBFF;
+@purple-2: #D6BBFB;
+@purple-3: #9E77ED;
+@purple-4: #6941C6;
+@purple-5: #42307D;
+// Defaults
+@purple-6: mix(@purple-base, @component-background, 85%);
+@purple-7: mix(color(~`colorPalette('@{purple-base}', 5) `), @component-background, 90%);
+@purple-8: mix(color(~`colorPalette('@{purple-base}', 4) `), @component-background, 95%);
+@purple-9: mix(color(~`colorPalette('@{purple-base}', 3) `), @component-background, 97%);
+@purple-10: mix(color(~`colorPalette('@{purple-base}', 2) `), @component-background, 98%);
+
+
+@primary-color: #d62222; // split border inside a component
+@text-color: green;
+@text-color-secondary: orange;
diff --git a/web/styles/variables.scss b/web/styles/variables.scss
index 6ff4856ba..037bef8c3 100644
--- a/web/styles/variables.scss
+++ b/web/styles/variables.scss
@@ -1,3 +1,4 @@
+// See theme.less for specific Ant Design overrides.
:root {
// colors
--white: rgba(255, 255, 255, 1);