diff --git a/README.md b/README.md
index 2d4c732f..0130eb27 100644
--- a/README.md
+++ b/README.md
@@ -282,7 +282,8 @@ Add this snippet to the bottom of web page:
var remark_config = {
site_id: 'YOUR_SITE_ID',
url: 'PAGE_URL', // optional param; if it isn't defined window.location.href will be used
- max_shown_comments: 10, // optional param; if it isn't defined default value (15) will be used
+ max_shown_comments: 10, // optional param; if it isn't defined default value (15) will be used
+ theme: 'dark', // optional param; if it isn't defined default value ('light') will be used
};
(function() {
@@ -301,6 +302,19 @@ And then add this node in the place where you want to see Remark42 widget:
After that widget will be rendered inside this node.
+##### Themes
+
+Right now Remark has two themes: light and dark.
+You can pick one using configuration object,
+but there is also a possibility to switch between themes in runtime.
+For this purpose Remark adds to `window` object named `REMARK42`,
+which contains function `changeTheme`.
+Just call this function and pass a name of the theme that you want to turn on:
+
+```js
+window.REMARK42.changeTheme('light');
+```
+
#### Last comments
It's a widget which renders list of last comments from your site.
diff --git a/web/app/common/constants.js b/web/app/common/constants.js
index 5301d7ae..afa97c5f 100644
--- a/web/app/common/constants.js
+++ b/web/app/common/constants.js
@@ -39,6 +39,8 @@ export const BLOCKING_DURATIONS = [
},
];
+export const THEMES = ['light', 'dark'];
+
/**
* Defines if browser storage features (cookies, localsrotage)
* are available or blocked via browser preferences
diff --git a/web/app/common/settings.js b/web/app/common/settings.js
index 8cee687c..c26b6a43 100644
--- a/web/app/common/settings.js
+++ b/web/app/common/settings.js
@@ -1,3 +1,5 @@
+import { THEMES } from './constants';
+
const querySettings =
window.location.search
.substr(1)
@@ -12,3 +14,4 @@ export const siteId = querySettings['site_id'];
export const url = querySettings['url'];
export const maxShownComments = querySettings['max_shown_comments'];
export const token = querySettings['token'];
+export const theme = querySettings['theme'] || THEMES[0];
diff --git a/web/app/components/auth-panel/__user-id/auth-panel__user-id.jsx b/web/app/components/auth-panel/__user-id/auth-panel__user-id.jsx
index f04859f5..d4e7a66c 100644
--- a/web/app/components/auth-panel/__user-id/auth-panel__user-id.jsx
+++ b/web/app/components/auth-panel/__user-id/auth-panel__user-id.jsx
@@ -1,8 +1,8 @@
/** @jsx h */
import { h } from 'preact';
-export default ({ id }) => (
-
- {id}
+export default props => (
+
+ {props.id}
);
diff --git a/web/app/components/auth-panel/__user-id/auth-panel__user-id.scss b/web/app/components/auth-panel/__user-id/auth-panel__user-id.scss
index b33fd069..445a561e 100644
--- a/web/app/components/auth-panel/__user-id/auth-panel__user-id.scss
+++ b/web/app/components/auth-panel/__user-id/auth-panel__user-id.scss
@@ -1,5 +1,4 @@
.auth-panel__user-id {
overflow: hidden;
text-overflow: ellipsis;
- color: #888;
}
diff --git a/web/app/components/auth-panel/__user-id/index.js b/web/app/components/auth-panel/__user-id/index.js
new file mode 100644
index 00000000..a6c94313
--- /dev/null
+++ b/web/app/components/auth-panel/__user-id/index.js
@@ -0,0 +1,6 @@
+import withTheme from 'components/with-theme';
+import UserId from './auth-panel__user-id';
+
+export default withTheme(UserId);
+
+require('./auth-panel__user-id.scss');
diff --git a/web/app/components/auth-panel/_theme/_dark/auth-panel_theme_dark.scss b/web/app/components/auth-panel/_theme/_dark/auth-panel_theme_dark.scss
new file mode 100644
index 00000000..69f97941
--- /dev/null
+++ b/web/app/components/auth-panel/_theme/_dark/auth-panel_theme_dark.scss
@@ -0,0 +1,5 @@
+.auth-panel_theme_dark {
+ .auth-panel__user-id {
+ color: #eee;
+ }
+}
diff --git a/web/app/components/auth-panel/_theme/_light/auth-panel_theme_light.scss b/web/app/components/auth-panel/_theme/_light/auth-panel_theme_light.scss
new file mode 100644
index 00000000..d73c59b8
--- /dev/null
+++ b/web/app/components/auth-panel/_theme/_light/auth-panel_theme_light.scss
@@ -0,0 +1,5 @@
+.auth-panel_theme_light {
+ .auth-panel__user-id {
+ color: #888;
+ }
+}
diff --git a/web/app/components/auth-panel/auth-panel.jsx b/web/app/components/auth-panel/auth-panel.jsx
index 0926ddef..3e9064a0 100644
--- a/web/app/components/auth-panel/auth-panel.jsx
+++ b/web/app/components/auth-panel/auth-panel.jsx
@@ -1,13 +1,14 @@
/** @jsx h */
import { h, Component } from 'preact';
-import UserId from './__user-id/auth-panel__user-id';
import Dropdown, { DropdownItem } from 'components/dropdown';
import Button from 'components/button';
import { PROVIDER_NAMES, IS_STORAGE_AVAILABLE, IS_THIRD_PARTY } from 'common/constants';
import { requestDeletion } from 'utils/email';
import { getHandleClickProps } from 'common/accessibility';
+import UserId from './__user-id';
+
export default class AuthPanel extends Component {
constructor(props) {
super(props);
diff --git a/web/app/components/auth-panel/index.js b/web/app/components/auth-panel/index.js
index 5a8a50a1..6c34316d 100644
--- a/web/app/components/auth-panel/index.js
+++ b/web/app/components/auth-panel/index.js
@@ -1,4 +1,7 @@
-export { default } from './auth-panel';
+import withTheme from 'components/with-theme';
+import AuthPanel from './auth-panel';
+
+export default withTheme(AuthPanel);
require('./auth-panel.scss');
@@ -11,4 +14,7 @@ require('./__sort/auth-panel__sort.scss');
require('./__user-id/auth-panel__user-id.scss');
require('./__sign-out/auth-panel__sign-out.scss');
+require('./_theme/_dark/auth-panel_theme_dark.scss');
+require('./_theme/_light/auth-panel_theme_light.scss');
+
require('./_logged-in/auth-panel_logged-in.scss');
diff --git a/web/app/components/avatar-icon/avatar-icon.jsx b/web/app/components/avatar-icon/avatar-icon.jsx
index 604332b6..50f1762d 100644
--- a/web/app/components/avatar-icon/avatar-icon.jsx
+++ b/web/app/components/avatar-icon/avatar-icon.jsx
@@ -1,10 +1,12 @@
/** @jsx h */
import { h } from 'preact';
-export default function AvatarIcon({ picture, className }) {
+export default function AvatarIcon(props) {
+ const { picture } = props;
+
return (
diff --git a/web/app/components/avatar-icon/index.js b/web/app/components/avatar-icon/index.js
index 61f7a78d..ba733794 100644
--- a/web/app/components/avatar-icon/index.js
+++ b/web/app/components/avatar-icon/index.js
@@ -1,4 +1,7 @@
-export { default } from './avatar-icon';
+import withTheme from 'components/with-theme';
+import AvatarIcon from './avatar-icon';
+
+export default withTheme(AvatarIcon);
require('./avatar-icon.scss');
require('./_default/avatar-icon_default.scss');
diff --git a/web/app/components/blocked-users/__action/blocked-users__action.scss b/web/app/components/blocked-users/__action/blocked-users__action.scss
index c34eee15..940cc969 100644
--- a/web/app/components/blocked-users/__action/blocked-users__action.scss
+++ b/web/app/components/blocked-users/__action/blocked-users__action.scss
@@ -15,6 +15,5 @@
&::before {
content: '•';
margin-right: 8px;
- color: #777;
}
}
diff --git a/web/app/components/blocked-users/__user-block-ttl/blocked-users__user-block-ttl.scss b/web/app/components/blocked-users/__user-block-ttl/blocked-users__user-block-ttl.scss
deleted file mode 100644
index 1ec52c28..00000000
--- a/web/app/components/blocked-users/__user-block-ttl/blocked-users__user-block-ttl.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.blocked-users__user-id {
- color: #888;
-}
diff --git a/web/app/components/blocked-users/__user-id/blocked-users__user-id.scss b/web/app/components/blocked-users/__user-id/blocked-users__user-id.scss
deleted file mode 100644
index 1ec52c28..00000000
--- a/web/app/components/blocked-users/__user-id/blocked-users__user-id.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.blocked-users__user-id {
- color: #888;
-}
diff --git a/web/app/components/blocked-users/_theme/_dark/blocked-users_theme_dark.scss b/web/app/components/blocked-users/_theme/_dark/blocked-users_theme_dark.scss
new file mode 100644
index 00000000..aea5583a
--- /dev/null
+++ b/web/app/components/blocked-users/_theme/_dark/blocked-users_theme_dark.scss
@@ -0,0 +1,11 @@
+.blocked-users_theme_dark {
+ .blocked-users__action {
+ &::before {
+ color: #ddd;
+ }
+ }
+
+ .blocked-users__user-id {
+ color: #eee;
+ }
+}
diff --git a/web/app/components/blocked-users/_theme/_light/blocked-users_theme_light.scss b/web/app/components/blocked-users/_theme/_light/blocked-users_theme_light.scss
new file mode 100644
index 00000000..e176c75e
--- /dev/null
+++ b/web/app/components/blocked-users/_theme/_light/blocked-users_theme_light.scss
@@ -0,0 +1,11 @@
+.blocked-users_theme_light {
+ .blocked-users__action {
+ &::before {
+ color: #777;
+ }
+ }
+
+ .blocked-users__user-id {
+ color: #888;
+ }
+}
diff --git a/web/app/components/blocked-users/index.js b/web/app/components/blocked-users/index.js
index 454cfc95..ee27dcf1 100644
--- a/web/app/components/blocked-users/index.js
+++ b/web/app/components/blocked-users/index.js
@@ -1,4 +1,7 @@
-export { default } from './blocked-users';
+import withTheme from 'components/with-theme';
+import BlockedUsers from './blocked-users';
+
+export default withTheme(BlockedUsers);
require('./blocked-users.scss');
@@ -6,8 +9,9 @@ require('./__action/blocked-users__action.scss');
require('./__list/blocked-users__list.scss');
require('./__list-item/blocked-users__list-item.scss');
-require('./__user-block-ttl/blocked-users__user-block-ttl.scss');
require('./__list-item/_view/_invisible/blocked-users__list-item_view_invisible.scss');
-require('./__user-id/blocked-users__user-id.scss');
require('./__username/blocked-users__username.scss');
+
+require('./_theme/_dark/blocked-users_theme_dark.scss');
+require('./_theme/_light/blocked-users_theme_light.scss');
diff --git a/web/app/components/button/_kind/button_kind.scss b/web/app/components/button/_kind/_link/button_kind_link.scss
similarity index 68%
rename from web/app/components/button/_kind/button_kind.scss
rename to web/app/components/button/_kind/_link/button_kind_link.scss
index 32822926..b973fb8a 100644
--- a/web/app/components/button/_kind/button_kind.scss
+++ b/web/app/components/button/_kind/_link/button_kind_link.scss
@@ -1,9 +1,3 @@
-.button_kind_text {
- border: none;
- background: transparent;
- padding: 0;
-}
-
.button_kind_link {
border: none;
background: transparent;
diff --git a/web/app/components/button/_kind/_text/button_kind_text.scss b/web/app/components/button/_kind/_text/button_kind_text.scss
new file mode 100644
index 00000000..30bfeb2e
--- /dev/null
+++ b/web/app/components/button/_kind/_text/button_kind_text.scss
@@ -0,0 +1,5 @@
+.button_kind_text {
+ border: none;
+ background: transparent;
+ padding: 0;
+}
diff --git a/web/app/components/button/button.jsx b/web/app/components/button/button.jsx
index e1f9fab9..2dd78c6a 100644
--- a/web/app/components/button/button.jsx
+++ b/web/app/components/button/button.jsx
@@ -44,13 +44,18 @@ export default class Button extends Component {
}
render(props, state) {
- const { children, mix, mods, ...rest } = props;
+ const { children } = props;
const { isClicked, isFocused } = state;
+ const localProps = { ...props };
+ delete localProps.children;
+ delete localProps.mix;
+ delete localProps.mods;
+
return (
{' '}
- (this.textNode = r)}
dangerouslySetInnerHTML={{ __html: o.text }}
/>
diff --git a/web/app/components/comment/comment.scss b/web/app/components/comment/comment.scss
index 6f502f36..e6feb46d 100644
--- a/web/app/components/comment/comment.scss
+++ b/web/app/components/comment/comment.scss
@@ -4,7 +4,6 @@
overflow: hidden;
margin-bottom: 16px;
padding-bottom: 8px;
- border-bottom: 1px solid #fcfcfc;
font-size: 16px;
line-height: 1.2;
diff --git a/web/app/components/comment/index.js b/web/app/components/comment/index.js
index 5ac52caa..e6489d92 100644
--- a/web/app/components/comment/index.js
+++ b/web/app/components/comment/index.js
@@ -1,6 +1,8 @@
import 'components/raw-content';
+import withTheme from 'components/with-theme';
+import Comment from './comment';
-export { default } from './comment';
+export default withTheme(Comment);
require('./comment.scss');
@@ -51,3 +53,6 @@ require('./_useless/comment_useless.scss');
require('./_view/_admin/comment_view_admin.scss');
require('./_view/_preview/comment_view_preview.scss');
require('./_view/_user/comment_view_user.scss');
+
+require('./_theme/_dark/comment_theme_dark.scss');
+require('./_theme/_light/comment_theme_light.scss');
diff --git a/web/app/components/dropdown/__content/dropdown__content.scss b/web/app/components/dropdown/__content/dropdown__content.scss
index 590bcb20..80c94133 100644
--- a/web/app/components/dropdown/__content/dropdown__content.scss
+++ b/web/app/components/dropdown/__content/dropdown__content.scss
@@ -7,7 +7,6 @@
left: 50%;
transform: translate(-50%, 5px);
width: 170px;
- background-color: #fff;
border: 2px solid #259c9a;
border-radius: 3px;
padding: 0 0 5px;
diff --git a/web/app/components/dropdown/__item/dropdown__item.jsx b/web/app/components/dropdown/__item/dropdown__item.jsx
index 5abd8331..84ec0795 100644
--- a/web/app/components/dropdown/__item/dropdown__item.jsx
+++ b/web/app/components/dropdown/__item/dropdown__item.jsx
@@ -2,7 +2,7 @@
import { h } from 'preact';
export default function DropdownItem(props) {
- const { children, separator = false, mix, mods } = props;
+ const { children, separator = false } = props;
- return
{children}
;
+ return
{children}
;
}
diff --git a/web/app/components/dropdown/__item/index.js b/web/app/components/dropdown/__item/index.js
new file mode 100644
index 00000000..80204192
--- /dev/null
+++ b/web/app/components/dropdown/__item/index.js
@@ -0,0 +1,4 @@
+import withTheme from 'components/with-theme';
+import Dropdown__Item from './dropdown__item';
+
+export default withTheme(Dropdown__Item);
diff --git a/web/app/components/dropdown/_theme/_dark/dropdown_theme_dark.scss b/web/app/components/dropdown/_theme/_dark/dropdown_theme_dark.scss
new file mode 100644
index 00000000..98265b49
--- /dev/null
+++ b/web/app/components/dropdown/_theme/_dark/dropdown_theme_dark.scss
@@ -0,0 +1,9 @@
+.dropdown_theme_dark {
+ .dropdown__title {
+ color: #ddd;
+ }
+
+ .dropdown__content {
+ background-color: #22201c;
+ }
+}
diff --git a/web/app/components/dropdown/_theme/_light/dropdown_theme_light.scss b/web/app/components/dropdown/_theme/_light/dropdown_theme_light.scss
new file mode 100644
index 00000000..d35c1a03
--- /dev/null
+++ b/web/app/components/dropdown/_theme/_light/dropdown_theme_light.scss
@@ -0,0 +1,9 @@
+.dropdown_theme_light {
+ .dropdown__title {
+ color: #000;
+ }
+
+ .dropdown__content {
+ background-color: #fff;
+ }
+}
diff --git a/web/app/components/dropdown/index.js b/web/app/components/dropdown/index.js
index d9f285ee..054b0b4b 100644
--- a/web/app/components/dropdown/index.js
+++ b/web/app/components/dropdown/index.js
@@ -1,5 +1,9 @@
-export { default } from './dropdown';
-export { default as DropdownItem } from './__item/dropdown__item';
+import withTheme from 'components/with-theme';
+import Dropdown from './dropdown';
+
+export default withTheme(Dropdown);
+
+export { default as DropdownItem } from './__item';
require('./dropdown.scss');
require('./_active/dropdown_active.scss');
@@ -8,3 +12,6 @@ require('./__item/dropdown__item.scss');
require('./__items/dropdown__items.scss');
require('./__title/dropdown__title.scss');
require('./__content/dropdown__content.scss');
+
+require('./_theme/_dark/dropdown_theme_dark.scss');
+require('./_theme/_light/dropdown_theme_light.scss');
diff --git a/web/app/components/input/__actions/input__actions.scss b/web/app/components/input/__actions/input__actions.scss
index 49060e33..36c1e30c 100644
--- a/web/app/components/input/__actions/input__actions.scss
+++ b/web/app/components/input/__actions/input__actions.scss
@@ -2,5 +2,4 @@
display: flex;
align-items: center;
padding-top: 8px;
- background: #eee;
}
diff --git a/web/app/components/input/__button/_type/_preview/input__button_type_preview.scss b/web/app/components/input/__button/_type/_preview/input__button_type_preview.scss
index dfff3f52..5a1c55bb 100644
--- a/web/app/components/input/__button/_type/_preview/input__button_type_preview.scss
+++ b/web/app/components/input/__button/_type/_preview/input__button_type_preview.scss
@@ -1,7 +1,4 @@
.input__button_type_preview {
- background: #fff;
- color: #000;
-
&:hover,
&:focus {
box-shadow: inset 0 0 0 2px #0aa;
diff --git a/web/app/components/input/__error/input__error.scss b/web/app/components/input/__error/input__error.scss
index 18f29da4..5f71bc64 100644
--- a/web/app/components/input/__error/input__error.scss
+++ b/web/app/components/input/__error/input__error.scss
@@ -3,7 +3,4 @@
padding: 10px 12px;
font-size: 14px;
line-height: 18px;
- border-top: 8px solid #eee;
- background: #ffd7d7;
- color: #9a0000;
}
diff --git a/web/app/components/input/__field/input__field.scss b/web/app/components/input/__field/input__field.scss
index 966b6180..12950646 100644
--- a/web/app/components/input/__field/input__field.scss
+++ b/web/app/components/input/__field/input__field.scss
@@ -14,7 +14,6 @@
font-family: 'PT Sans', Helvetica, Arial, sans-serif;
font-size: $fontSize;
line-height: $lineHeight;
- background: #fff;
border: 0;
resize: none;
backface-visibility: hidden; /* let's try to fix blinking in Safari */
diff --git a/web/app/components/input/__preview-wrapper/input__preview-wrapper.scss b/web/app/components/input/__preview-wrapper/input__preview-wrapper.scss
index 78e523bd..e76ebcae 100644
--- a/web/app/components/input/__preview-wrapper/input__preview-wrapper.scss
+++ b/web/app/components/input/__preview-wrapper/input__preview-wrapper.scss
@@ -1,4 +1,3 @@
.input__preview-wrapper {
overflow: hidden;
- background: #eee;
}
diff --git a/web/app/components/input/__preview/input__preview.scss b/web/app/components/input/__preview/input__preview.scss
index 7e2b5dec..4a97624f 100644
--- a/web/app/components/input/__preview/input__preview.scss
+++ b/web/app/components/input/__preview/input__preview.scss
@@ -4,8 +4,6 @@
overflow: hidden;
font-size: 16px;
line-height: 1.2;
- border: 1px dashed #eee;
+ border: 1px dashed;
border-radius: 2px;
- background: #fff;
- color: #333;
}
diff --git a/web/app/components/input/_theme/_dark/input_theme_dark.scss b/web/app/components/input/_theme/_dark/input_theme_dark.scss
new file mode 100644
index 00000000..252cb424
--- /dev/null
+++ b/web/app/components/input/_theme/_dark/input_theme_dark.scss
@@ -0,0 +1,38 @@
+.input_theme_dark {
+ border-color: #333;
+ background: #22201c; /* try to fix textarea blinking in Safari */
+
+ .input__actions {
+ background: #333;
+ }
+
+ .input__button_type_preview {
+ background: #22201c;
+ color: #ddd;
+ }
+
+ .input__button_type_send {
+ color: #ddd;
+ }
+
+ .input__error {
+ border-top: 8px solid #333;
+ background: #672323;
+ color: #f98989;
+ }
+
+ .input__field {
+ background: #22201c;
+ color: #eee;
+ }
+
+ .input__preview {
+ border-color: #eee;
+ background: #fff;
+ color: #333;
+ }
+
+ .input__preview-wrapper {
+ background: #eee;
+ }
+}
diff --git a/web/app/components/input/_theme/_light/input_theme_light.scss b/web/app/components/input/_theme/_light/input_theme_light.scss
new file mode 100644
index 00000000..efb89b0b
--- /dev/null
+++ b/web/app/components/input/_theme/_light/input_theme_light.scss
@@ -0,0 +1,38 @@
+.input_theme_light {
+ border-color: #eee;
+ background: #fff; /* try to fix textarea blinking in Safari */
+
+ .input__actions {
+ background: #eee;
+ }
+
+ .input__button_type_preview {
+ background: #fff;
+ color: #000;
+ }
+
+ .input__button_type_send {
+ color: #fff;
+ }
+
+ .input__error {
+ border-top: 8px solid #eee;
+ background: #ffd7d7;
+ color: #9a0000;
+ }
+
+ .input__field {
+ background: #fff;
+ color: #000;
+ }
+
+ .input__preview {
+ border-color: #eee;
+ background: #fff;
+ color: #333;
+ }
+
+ .input__preview-wrapper {
+ background: #eee;
+ }
+}
diff --git a/web/app/components/input/index.js b/web/app/components/input/index.js
index b7753548..077bfe03 100644
--- a/web/app/components/input/index.js
+++ b/web/app/components/input/index.js
@@ -1,6 +1,8 @@
import 'components/raw-content';
+import withTheme from 'components/with-theme';
+import Input from './input';
-export { default } from './input';
+export default withTheme(Input);
require('./input.scss');
@@ -20,3 +22,6 @@ require('./__rss/input__rss.scss');
require('./__rss-link/input__rss-link.scss');
require('./__markdown/input__markdown.scss');
require('./__markdown-link/input__markdown-link.scss');
+
+require('./_theme/_dark/input_theme_dark.scss');
+require('./_theme/_light/input_theme_light.scss');
diff --git a/web/app/components/input/input.jsx b/web/app/components/input/input.jsx
index 68852b60..055e40d3 100644
--- a/web/app/components/input/input.jsx
+++ b/web/app/components/input/input.jsx
@@ -40,6 +40,7 @@ export default class Input extends Component {
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.id !== this.props.id ||
+ nextProps.mods !== this.props.mods ||
nextProps.pid !== this.props.pid ||
nextProps.value !== this.props.value ||
nextProps.errorMessage !== this.props.errorMessage ||
@@ -171,7 +172,7 @@ export default class Input extends Component {
!!preview && (
diff --git a/web/app/components/input/input.scss b/web/app/components/input/input.scss
index 27dcf745..062b7960 100644
--- a/web/app/components/input/input.scss
+++ b/web/app/components/input/input.scss
@@ -2,7 +2,6 @@
position: relative;
display: block;
font-size: 0;
- border: 12px solid #eee;
+ border: 12px solid;
border-radius: 2px;
- background: #fff; /* try to fix textarea blinking in Safari */
}
diff --git a/web/app/components/raw-content/_theme/_dark/raw-content_theme_dark.scss b/web/app/components/raw-content/_theme/_dark/raw-content_theme_dark.scss
new file mode 100644
index 00000000..507e0330
--- /dev/null
+++ b/web/app/components/raw-content/_theme/_dark/raw-content_theme_dark.scss
@@ -0,0 +1,28 @@
+.raw-content_theme_dark {
+ blockquote {
+ background: #393734;
+ }
+
+ table {
+ th,
+ td {
+ border: 1px solid #313133;
+ }
+
+ tr {
+ background-color: #22201c;
+
+ &:nth-child(2n) {
+ background-color: #393734;
+ }
+ }
+ }
+
+ pre {
+ background-color: #393734;
+ }
+
+ hr {
+ border-color: #393734;
+ }
+}
diff --git a/web/app/components/raw-content/_theme/_light/raw-content_theme_light.scss b/web/app/components/raw-content/_theme/_light/raw-content_theme_light.scss
new file mode 100644
index 00000000..00784e50
--- /dev/null
+++ b/web/app/components/raw-content/_theme/_light/raw-content_theme_light.scss
@@ -0,0 +1,28 @@
+.raw-content_theme_light {
+ blockquote {
+ background: #fafafa;
+ }
+
+ table {
+ th,
+ td {
+ border: 1px solid #dfe2e5;
+ }
+
+ tr {
+ background-color: #fff;
+
+ &:nth-child(2n) {
+ background-color: #f6f8fa;
+ }
+ }
+ }
+
+ pre {
+ background-color: #f6f8fa;
+ }
+
+ hr {
+ border-color: #f6f8fa;
+ }
+}
diff --git a/web/app/components/raw-content/index.js b/web/app/components/raw-content/index.js
index 12c85c14..b66e8692 100644
--- a/web/app/components/raw-content/index.js
+++ b/web/app/components/raw-content/index.js
@@ -1 +1,4 @@
require('./raw-content.scss');
+
+require('./_theme/_dark/raw-content_theme_dark.scss');
+require('./_theme/_light/raw-content_theme_light.scss');
diff --git a/web/app/components/raw-content/raw-content.scss b/web/app/components/raw-content/raw-content.scss
index 405b6f2d..dbe2e1a2 100644
--- a/web/app/components/raw-content/raw-content.scss
+++ b/web/app/components/raw-content/raw-content.scss
@@ -44,7 +44,6 @@
blockquote {
margin: 0;
padding: 8px 8px 8px 24px;
- background: #fafafa;
border-radius: 2px;
+ p {
@@ -66,16 +65,10 @@
th,
td {
padding: 6px 13px;
- border: 1px solid #dfe2e5;
}
tr {
- background-color: #fff;
border-top: 1px solid #b7dddd;
-
- &:nth-child(2n) {
- background-color: #f6f8fa;
- }
}
}
@@ -95,7 +88,6 @@
word-wrap: normal;
font-size: 85%;
line-height: 1.45;
- background-color: #f6f8fa;
border-radius: 3px;
&:first-child {
diff --git a/web/app/components/root/__copyright-link/root__copyright-link.scss b/web/app/components/root/__copyright-link/root__copyright-link.scss
deleted file mode 100644
index f91e583e..00000000
--- a/web/app/components/root/__copyright-link/root__copyright-link.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.root__copyright-link {
- color: #aaa;
-}
diff --git a/web/app/components/root/__copyright/root__copyright.scss b/web/app/components/root/__copyright/root__copyright.scss
index 8a61eb73..427cb5d6 100644
--- a/web/app/components/root/__copyright/root__copyright.scss
+++ b/web/app/components/root/__copyright/root__copyright.scss
@@ -2,5 +2,4 @@
margin: 48px 0 0;
font-size: 12px;
text-align: right;
- color: #aaa;
}
diff --git a/web/app/components/root/__pinned-comment/root__pinned-comment.scss b/web/app/components/root/__pinned-comment/root__pinned-comment.scss
index 79eca1f8..0765cfda 100644
--- a/web/app/components/root/__pinned-comment/root__pinned-comment.scss
+++ b/web/app/components/root/__pinned-comment/root__pinned-comment.scss
@@ -1,6 +1,4 @@
.root__pinned-comment {
- border-bottom-color: #e2efef;
-
&:last-child {
margin-bottom: 0;
border-bottom: 0;
diff --git a/web/app/components/root/__pinned-comments/root__pinned-comments.scss b/web/app/components/root/__pinned-comments/root__pinned-comments.scss
index e7da6774..43eb0ba6 100644
--- a/web/app/components/root/__pinned-comments/root__pinned-comments.scss
+++ b/web/app/components/root/__pinned-comments/root__pinned-comments.scss
@@ -2,5 +2,4 @@
margin-top: 24px;
padding: 8px 12px;
border-radius: 2px;
- background: #edf6f7;
}
diff --git a/web/app/components/root/_theme/_dark/root_theme_dark.scss b/web/app/components/root/_theme/_dark/root_theme_dark.scss
new file mode 100644
index 00000000..dcb8bfd6
--- /dev/null
+++ b/web/app/components/root/_theme/_dark/root_theme_dark.scss
@@ -0,0 +1,19 @@
+.root_theme_dark {
+ color: #ddd;
+
+ .root__copyright {
+ color: #aaa;
+ }
+
+ .root__copyright-link {
+ color: #aaa;
+ }
+
+ .root__pinned-comment {
+ border-bottom-color: #383838;
+ }
+
+ .root__pinned-comments {
+ background: #404040;
+ }
+}
diff --git a/web/app/components/root/_theme/_light/root_theme_light.scss b/web/app/components/root/_theme/_light/root_theme_light.scss
new file mode 100644
index 00000000..f5eb56b2
--- /dev/null
+++ b/web/app/components/root/_theme/_light/root_theme_light.scss
@@ -0,0 +1,19 @@
+.root_theme_light {
+ color: #000;
+
+ .root__copyright {
+ color: #aaa;
+ }
+
+ .root__copyright-link {
+ color: #aaa;
+ }
+
+ .root__pinned-comment {
+ border-bottom-color: #e2efef;
+ }
+
+ .root__pinned-comments {
+ background: #edf6f7;
+ }
+}
diff --git a/web/app/components/root/index.js b/web/app/components/root/index.js
index a3a0ec53..e4c3e46d 100644
--- a/web/app/components/root/index.js
+++ b/web/app/components/root/index.js
@@ -3,7 +3,6 @@ export { default } from './root';
require('./root.scss');
require('./__copyright/root__copyright.scss');
-require('./__copyright-link/root__copyright-link.scss');
require('./__input/root__input.scss');
require('./__preloader/root__preloader.scss');
require('./__pinned-comment/root__pinned-comment.scss');
@@ -11,3 +10,6 @@ require('./__pinned-comments/root__pinned-comments.scss');
require('./__show-more/root__show-more.scss');
require('./__thread/root__thread.scss');
require('./__threads/root__threads.scss');
+
+require('./_theme/_dark/root_theme_dark.scss');
+require('./_theme/_light/root_theme_light.scss');
diff --git a/web/app/components/root/root.jsx b/web/app/components/root/root.jsx
index be5a4e16..88ce933b 100644
--- a/web/app/components/root/root.jsx
+++ b/web/app/components/root/root.jsx
@@ -9,9 +9,10 @@ import {
DEFAULT_SORT,
COOKIE_SORT_KEY,
MAX_SHOWN_ROOT_COMMENTS,
+ THEMES,
} from 'common/constants';
import { getCookie, setCookie } from 'common/cookies';
-import { siteId, url, maxShownComments } from 'common/settings';
+import { siteId, url, maxShownComments, theme } from 'common/settings';
import store from 'common/store';
import AuthPanel from 'components/auth-panel';
@@ -39,6 +40,7 @@ export default class Root extends Component {
isLoaded: false,
isCommentsListLoading: false,
user: {},
+ theme: THEMES[0],
sort,
commentsShown: maxShownComments || MAX_SHOWN_ROOT_COMMENTS,
};
@@ -55,11 +57,22 @@ export default class Root extends Component {
this.onUnblockSomeone = this.onUnblockSomeone.bind(this);
this.checkUrlHash = this.checkUrlHash.bind(this);
this.showMore = this.showMore.bind(this);
+ this.onThemeUpdate = this.onThemeUpdate.bind(this);
}
componentWillMount() {
store.onUpdate('comments', comments => this.setState({ comments }));
store.onUpdate('info', info => this.setState({ info }));
+
+ if (THEMES.includes(theme)) {
+ store.set('theme', theme);
+ this.setState({ theme });
+ } else {
+ store.set('theme', THEMES[0]);
+ this.setState({ theme: THEMES[0] });
+ }
+
+ window.addEventListener('message', this.onThemeUpdate);
}
componentDidMount() {
@@ -109,6 +122,16 @@ export default class Root extends Component {
}
}
+ onThemeUpdate(event) {
+ try {
+ const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
+ if (data.theme && THEMES.includes(data.theme)) {
+ store.set('theme', data.theme);
+ this.setState({ theme: data.theme });
+ }
+ } catch (e) {}
+ }
+
onSignOut() {
api.logOut().then(() => {
store.set('user', {});
@@ -238,12 +261,13 @@ export default class Root extends Component {
isCommentsListLoading,
bannedUsers,
commentsShown,
+ theme,
}
) {
if (!isLoaded) {
return (
-
@@ -257,7 +281,7 @@ export default class Root extends Component {
return (
-
+
-
+
Last comments by {name}
{id}
diff --git a/web/app/components/user-info/user-info.scss b/web/app/components/user-info/user-info.scss
index fdebe7e2..4c826743 100644
--- a/web/app/components/user-info/user-info.scss
+++ b/web/app/components/user-info/user-info.scss
@@ -1,12 +1,11 @@
.user-info {
- border: 1px solid #efefef;
+ border: 1px solid;
border-radius: 2px;
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 100%;
- background: white;
padding: 10px;
box-sizing: border-box;
diff --git a/web/app/components/with-theme/index.js b/web/app/components/with-theme/index.js
new file mode 100644
index 00000000..38fb0793
--- /dev/null
+++ b/web/app/components/with-theme/index.js
@@ -0,0 +1 @@
+export { default } from './with-theme';
diff --git a/web/app/components/with-theme/with-theme.jsx b/web/app/components/with-theme/with-theme.jsx
new file mode 100644
index 00000000..0bfd461e
--- /dev/null
+++ b/web/app/components/with-theme/with-theme.jsx
@@ -0,0 +1,16 @@
+/** @jsx h */
+import { h } from 'preact';
+import store from 'common/store';
+
+const withTheme = PlainComponent => {
+ const ThemedComponent = props => {
+ const { mods = {} } = props;
+ const theme = store.get('theme');
+
+ return ;
+ };
+
+ return ThemedComponent;
+};
+
+export default withTheme;
diff --git a/web/app/embed.js b/web/app/embed.js
index 9c6b9997..6c61f401 100644
--- a/web/app/embed.js
+++ b/web/app/embed.js
@@ -29,6 +29,9 @@ function init() {
remark_config.url = (remark_config.url || window.location.href).split('#')[0];
+ window.REMARK42 = window.REMARK42 || {};
+ window.REMARK42.changeTheme = changeTheme;
+
const query = Object.keys(remark_config)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(remark_config[key])}`)
.join('&');
@@ -244,4 +247,8 @@ function init() {
iframe.contentWindow.postMessage(JSON.stringify({ clickOutside: true }), '*');
}
}
+
+ function changeTheme(theme) {
+ iframe.contentWindow.postMessage(JSON.stringify({ theme }), '*');
+ }
}
diff --git a/web/counter.ejs b/web/counter.ejs
index 8a7049ba..86094c56 100644
--- a/web/counter.ejs
+++ b/web/counter.ejs
@@ -1,5 +1,5 @@
-
+
diff --git a/web/iframe.html b/web/iframe.html
index e9dc515c..93bcf61e 100644
--- a/web/iframe.html
+++ b/web/iframe.html
@@ -34,7 +34,7 @@
width: 10px;
height: 10px;
margin-right: 3px;
- background-color: #333;
+ background-color: #888;
border-radius: 100%;
animation: iframePreloaderBounce 1.4s infinite ease-in-out both;
}
diff --git a/web/index.ejs b/web/index.ejs
index ca27b56e..6f9785f1 100644
--- a/web/index.ejs
+++ b/web/index.ejs
@@ -1,5 +1,5 @@
-
+
@@ -15,7 +15,32 @@
max-width: 800px;
margin: 40px;
}
+
+ .document_theme_dark {
+ background: #22201c;
+ color: #ddd;
+ }
+
+ .document_theme_dark a {
+ color: #5e5eff;
+ }
+
+
diff --git a/web/last-comments.ejs b/web/last-comments.ejs
index fc7d6ac1..339973eb 100644
--- a/web/last-comments.ejs
+++ b/web/last-comments.ejs
@@ -1,5 +1,5 @@
-
+