From 6f1b9037d517129f5e702682c8c88c48ed4b8acb Mon Sep 17 00:00:00 2001 From: Igor Adamenko Date: Sun, 16 Dec 2018 01:10:41 +0200 Subject: [PATCH] Dark theme (#228) * add with-theme hoc * add dark theme styles for components * add toggle theme button to the dev demo page * add info about widget themes to README --- README.md | 16 +++- web/app/common/constants.js | 2 + web/app/common/settings.js | 3 + .../__user-id/auth-panel__user-id.jsx | 6 +- .../__user-id/auth-panel__user-id.scss | 1 - .../components/auth-panel/__user-id/index.js | 6 ++ .../_theme/_dark/auth-panel_theme_dark.scss | 5 + .../_theme/_light/auth-panel_theme_light.scss | 5 + web/app/components/auth-panel/auth-panel.jsx | 3 +- web/app/components/auth-panel/index.js | 8 +- .../components/avatar-icon/avatar-icon.jsx | 6 +- web/app/components/avatar-icon/index.js | 5 +- .../__action/blocked-users__action.scss | 1 - .../blocked-users__user-block-ttl.scss | 3 - .../__user-id/blocked-users__user-id.scss | 3 - .../_dark/blocked-users_theme_dark.scss | 11 +++ .../_light/blocked-users_theme_light.scss | 11 +++ web/app/components/blocked-users/index.js | 10 +- .../button_kind_link.scss} | 6 -- .../button/_kind/_text/button_kind_text.scss | 5 + web/app/components/button/button.jsx | 11 ++- web/app/components/button/index.js | 10 +- .../comment__action_type_collapse.scss | 6 +- .../_delete/comment__action_type_delete.scss | 2 - .../_edit/comment__action_type_edit.scss | 2 - .../comment/__action/comment__action.scss | 1 - .../_select/comment__control_select.scss | 1 + .../comment__control_view_inactive.scss | 1 - .../__edit-timer/comment__edit-timer.scss | 2 - .../comment/__score/comment__score.scss | 1 - .../comment/__status/comment__status.scss | 1 - .../comment/__time/comment__time.scss | 1 - .../comment/__user-id/comment__user-id.scss | 1 - .../comment/__username/comment__username.scss | 1 - .../comment/_editing/comment_editing.scss | 4 +- .../comment/_replying/comment_replying.scss | 4 +- .../_theme/_dark/comment_theme_dark.scss | 94 +++++++++++++++++++ .../_theme/_light/comment_theme_light.scss | 94 +++++++++++++++++++ .../comment/_useless/comment_useless.scss | 1 + web/app/components/comment/comment.jsx | 7 +- web/app/components/comment/comment.scss | 1 - web/app/components/comment/index.js | 7 +- .../dropdown/__content/dropdown__content.scss | 1 - .../dropdown/__item/dropdown__item.jsx | 4 +- web/app/components/dropdown/__item/index.js | 4 + .../_theme/_dark/dropdown_theme_dark.scss | 9 ++ .../_theme/_light/dropdown_theme_light.scss | 9 ++ web/app/components/dropdown/index.js | 11 ++- .../input/__actions/input__actions.scss | 1 - .../_preview/input__button_type_preview.scss | 3 - .../input/__error/input__error.scss | 3 - .../input/__field/input__field.scss | 1 - .../input__preview-wrapper.scss | 1 - .../input/__preview/input__preview.scss | 4 +- .../input/_theme/_dark/input_theme_dark.scss | 38 ++++++++ .../_theme/_light/input_theme_light.scss | 38 ++++++++ web/app/components/input/index.js | 7 +- web/app/components/input/input.jsx | 3 +- web/app/components/input/input.scss | 3 +- .../_theme/_dark/raw-content_theme_dark.scss | 28 ++++++ .../_light/raw-content_theme_light.scss | 28 ++++++ web/app/components/raw-content/index.js | 3 + .../components/raw-content/raw-content.scss | 8 -- .../root__copyright-link.scss | 3 - .../root/__copyright/root__copyright.scss | 1 - .../root__pinned-comment.scss | 2 - .../root__pinned-comments.scss | 1 - .../root/_theme/_dark/root_theme_dark.scss | 19 ++++ .../root/_theme/_light/root_theme_light.scss | 19 ++++ web/app/components/root/index.js | 4 +- web/app/components/root/root.jsx | 30 +++++- .../user-info/__id/user-info__id.scss | 1 - .../_theme/_light/user-info_theme_light.scss | 10 ++ web/app/components/user-info/index.js | 2 + web/app/components/user-info/user-info.jsx | 2 +- web/app/components/user-info/user-info.scss | 3 +- web/app/components/with-theme/index.js | 1 + web/app/components/with-theme/with-theme.jsx | 16 ++++ web/app/embed.js | 7 ++ web/counter.ejs | 2 +- web/iframe.html | 2 +- web/index.ejs | 28 +++++- web/last-comments.ejs | 2 +- 83 files changed, 626 insertions(+), 105 deletions(-) create mode 100644 web/app/components/auth-panel/__user-id/index.js create mode 100644 web/app/components/auth-panel/_theme/_dark/auth-panel_theme_dark.scss create mode 100644 web/app/components/auth-panel/_theme/_light/auth-panel_theme_light.scss delete mode 100644 web/app/components/blocked-users/__user-block-ttl/blocked-users__user-block-ttl.scss delete mode 100644 web/app/components/blocked-users/__user-id/blocked-users__user-id.scss create mode 100644 web/app/components/blocked-users/_theme/_dark/blocked-users_theme_dark.scss create mode 100644 web/app/components/blocked-users/_theme/_light/blocked-users_theme_light.scss rename web/app/components/button/_kind/{button_kind.scss => _link/button_kind_link.scss} (68%) create mode 100644 web/app/components/button/_kind/_text/button_kind_text.scss create mode 100644 web/app/components/comment/_theme/_dark/comment_theme_dark.scss create mode 100644 web/app/components/comment/_theme/_light/comment_theme_light.scss create mode 100644 web/app/components/dropdown/__item/index.js create mode 100644 web/app/components/dropdown/_theme/_dark/dropdown_theme_dark.scss create mode 100644 web/app/components/dropdown/_theme/_light/dropdown_theme_light.scss create mode 100644 web/app/components/input/_theme/_dark/input_theme_dark.scss create mode 100644 web/app/components/input/_theme/_light/input_theme_light.scss create mode 100644 web/app/components/raw-content/_theme/_dark/raw-content_theme_dark.scss create mode 100644 web/app/components/raw-content/_theme/_light/raw-content_theme_light.scss delete mode 100644 web/app/components/root/__copyright-link/root__copyright-link.scss create mode 100644 web/app/components/root/_theme/_dark/root_theme_dark.scss create mode 100644 web/app/components/root/_theme/_light/root_theme_light.scss create mode 100644 web/app/components/user-info/_theme/_light/user-info_theme_light.scss create mode 100644 web/app/components/with-theme/index.js create mode 100644 web/app/components/with-theme/with-theme.jsx 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 (
{' '} -
+
); @@ -529,7 +532,7 @@ export default class Comment extends Component {
(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; + } + +
@@ -26,6 +51,7 @@
  • Last comments widget
  • Counter widget
  • +

    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 @@ - +