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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/** @jsx h */
|
||||
import { h } from 'preact';
|
||||
|
||||
export default ({ id }) => (
|
||||
<div className="auth-panel__user-id" title={id}>
|
||||
{id}
|
||||
export default props => (
|
||||
<div className={b('auth-panel__user-id', props)} title={props.id}>
|
||||
{props.id}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
.auth-panel__user-id {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
@@ -0,0 +1,5 @@
|
||||
.auth-panel_theme_dark {
|
||||
.auth-panel__user-id {
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
.auth-panel_theme_light {
|
||||
.auth-panel__user-id {
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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 (
|
||||
<img
|
||||
className={b('avatar-icon', { mix: className }, { default: !picture })}
|
||||
className={b('avatar-icon', props, { default: !picture })}
|
||||
src={picture || require('./avatar-icon.svg')}
|
||||
alt=""
|
||||
/>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -15,6 +15,5 @@
|
||||
&::before {
|
||||
content: '•';
|
||||
margin-right: 8px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.blocked-users__user-id {
|
||||
color: #888;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.blocked-users__user-id {
|
||||
color: #888;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.blocked-users_theme_dark {
|
||||
.blocked-users__action {
|
||||
&::before {
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.blocked-users__user-id {
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.blocked-users_theme_light {
|
||||
.blocked-users__action {
|
||||
&::before {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
.blocked-users__user-id {
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
|
||||
-6
@@ -1,9 +1,3 @@
|
||||
.button_kind_text {
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.button_kind_link {
|
||||
border: none;
|
||||
background: transparent;
|
||||
@@ -0,0 +1,5 @@
|
||||
.button_kind_text {
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -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 (
|
||||
<button
|
||||
{...rest}
|
||||
className={b('button', { mix, mods }, { clicked: isClicked, focused: isFocused })}
|
||||
{...localProps}
|
||||
className={b('button', props, { clicked: isClicked, focused: isFocused })}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onBlur={this.onBlur}
|
||||
onFocus={this.onFocus}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
export { default } from './button';
|
||||
import withTheme from 'components/with-theme';
|
||||
import Button from './button';
|
||||
|
||||
export default withTheme(Button);
|
||||
|
||||
require('./button.scss');
|
||||
require('./_kind/button_kind.scss');
|
||||
|
||||
require('./_kind/_link/button_kind_link.scss');
|
||||
require('./_kind/_text/button_kind_text.scss');
|
||||
|
||||
require('./_focused/button_focused.scss');
|
||||
|
||||
+1
-5
@@ -9,9 +9,8 @@
|
||||
font-size: 12px;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
color: #ddd;
|
||||
|
||||
&:hover {
|
||||
border-color: #0aa;
|
||||
@@ -19,9 +18,6 @@
|
||||
}
|
||||
|
||||
&.comment__action_selected {
|
||||
background: #ddd;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: #0aa;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.comment__action_type_delete {
|
||||
color: #a6a6a6;
|
||||
|
||||
&:hover {
|
||||
color: #31c7c5;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.comment__action_type_edit {
|
||||
color: #a6a6a6;
|
||||
|
||||
&:hover {
|
||||
color: #31c7c5;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
content: '•';
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
|
||||
&::after {
|
||||
content: '▾';
|
||||
margin-left: 2px;
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
&,
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #999;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
user-select: none;
|
||||
color: #a6a6a6;
|
||||
margin-left: 8px;
|
||||
|
||||
+ .comment__controls {
|
||||
@@ -10,7 +9,6 @@
|
||||
content: '•';
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
font-size: 0;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
color: #c4c4c4;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
font-weight: 700;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
.comment__user-id {
|
||||
color: #888;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
vertical-align: middle;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
color: #777;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
.comment__input {
|
||||
border: 12px solid #eee;
|
||||
border: 12px solid;
|
||||
}
|
||||
|
||||
.comment__score {
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/* it isn't mobile first, but it's fine here */
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border: 8px solid #eee;
|
||||
border: 8px solid;
|
||||
padding-bottom: 0;
|
||||
|
||||
.comment__body {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.comment_replying {
|
||||
.comment__input {
|
||||
border: 12px solid #eee;
|
||||
border: 12px solid;
|
||||
}
|
||||
|
||||
.comment__score {
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/* it isn't mobile first, but it's fine here */
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border: 8px solid #eee;
|
||||
border: 8px solid;
|
||||
padding-bottom: 0;
|
||||
|
||||
.comment__body {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
.comment_theme_dark {
|
||||
border-bottom: 1px solid #333;
|
||||
|
||||
.comment__action_type_collapse {
|
||||
border-color: #555;
|
||||
color: #555;
|
||||
|
||||
&.comment__action_selected {
|
||||
background: #555;
|
||||
color: #22201c;
|
||||
}
|
||||
}
|
||||
|
||||
.comment__action_type_delete {
|
||||
color: #6a6a6a;
|
||||
}
|
||||
|
||||
.comment__action_type_edit {
|
||||
color: #6a6a6a;
|
||||
}
|
||||
|
||||
.comment__action {
|
||||
+ .comment__controls {
|
||||
&::before {
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment__control_view_inactive {
|
||||
&,
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.comment__edit-timer {
|
||||
color: #a6a6a6;
|
||||
+ .comment__controls {
|
||||
&::before {
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment__score {
|
||||
color: #c4c4c4;
|
||||
}
|
||||
|
||||
.comment__status {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.comment__time {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.comment__user-id {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.comment__username {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
&.comment_editing {
|
||||
.comment__input {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border-color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
&.comment_replying {
|
||||
.comment__input {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border-color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
&.comment_view_preview {
|
||||
.comment__info {
|
||||
&::after {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
.comment_theme_light {
|
||||
border-bottom: 1px solid #fcfcfc;
|
||||
|
||||
.comment__action_type_collapse {
|
||||
border-color: #ddd;
|
||||
color: #ddd;
|
||||
|
||||
&.comment__action_selected {
|
||||
background: #ddd;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.comment__action_type_delete {
|
||||
color: #a6a6a6;
|
||||
}
|
||||
|
||||
.comment__action_type_edit {
|
||||
color: #a6a6a6;
|
||||
}
|
||||
|
||||
.comment__action {
|
||||
+ .comment__controls {
|
||||
&::before {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment__control_view_inactive {
|
||||
&,
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.comment__edit-timer {
|
||||
color: #a6a6a6;
|
||||
+ .comment__controls {
|
||||
&::before {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment__score {
|
||||
color: #c4c4c4;
|
||||
}
|
||||
|
||||
.comment__status {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.comment__time {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.comment__user-id {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.comment__username {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
&.comment_editing {
|
||||
.comment__input {
|
||||
border-color: #eee;
|
||||
}
|
||||
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
&.comment_replying {
|
||||
.comment__input {
|
||||
border-color: #eee;
|
||||
}
|
||||
|
||||
@media (-moz-touch-enabled: 1) and (max-width: 768px), (pointer: coarse) and (max-width: 768px) {
|
||||
border-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
&.comment_view_preview {
|
||||
.comment__info {
|
||||
&::after {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
.comment_useless {
|
||||
.comment__body {
|
||||
opacity: 0.35;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -410,7 +410,10 @@ export default class Comment extends Component {
|
||||
{o.user.name}
|
||||
</a>
|
||||
</div>{' '}
|
||||
<div className={b('comment__text', { mix: 'raw-content' })} dangerouslySetInnerHTML={{ __html: o.text }} />
|
||||
<div
|
||||
className={b('comment__text', { mix: b('raw-content', {}, { theme: mods.theme }) })}
|
||||
dangerouslySetInnerHTML={{ __html: o.text }}
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
@@ -529,7 +532,7 @@ export default class Comment extends Component {
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={b('comment__text', { mix: 'raw-content' })}
|
||||
className={b('comment__text', { mix: b('raw-content', {}, { theme: mods.theme }) })}
|
||||
ref={r => (this.textNode = r)}
|
||||
dangerouslySetInnerHTML={{ __html: o.text }}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #fcfcfc;
|
||||
font-size: 16px;
|
||||
line-height: 1.2;
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <div className={b('dropdown__item', { mix, mods }, { separator })}>{children}</div>;
|
||||
return <div className={b('dropdown__item', props, { separator })}>{children}</div>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import withTheme from 'components/with-theme';
|
||||
import Dropdown__Item from './dropdown__item';
|
||||
|
||||
export default withTheme(Dropdown__Item);
|
||||
@@ -0,0 +1,9 @@
|
||||
.dropdown_theme_dark {
|
||||
.dropdown__title {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.dropdown__content {
|
||||
background-color: #22201c;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
.dropdown_theme_light {
|
||||
.dropdown__title {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.dropdown__content {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-top: 8px;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
.input__button_type_preview {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
box-shadow: inset 0 0 0 2px #0aa;
|
||||
|
||||
@@ -3,7 +3,4 @@
|
||||
padding: 10px 12px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
border-top: 8px solid #eee;
|
||||
background: #ffd7d7;
|
||||
color: #9a0000;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
.input__preview-wrapper {
|
||||
overflow: hidden;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
|
||||
@@ -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 && (
|
||||
<div className="input__preview-wrapper">
|
||||
<div
|
||||
className={b('input__preview', { mix: 'raw-content' })}
|
||||
className={b('input__preview', { mix: b('raw-content', {}, { theme: mods.theme }) })}
|
||||
dangerouslySetInnerHTML={{ __html: preview }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
require('./raw-content.scss');
|
||||
|
||||
require('./_theme/_dark/raw-content_theme_dark.scss');
|
||||
require('./_theme/_light/raw-content_theme_light.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 {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.root__copyright-link {
|
||||
color: #aaa;
|
||||
}
|
||||
@@ -2,5 +2,4 @@
|
||||
margin: 48px 0 0;
|
||||
font-size: 12px;
|
||||
text-align: right;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.root__pinned-comment {
|
||||
border-bottom-color: #e2efef;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
border-bottom: 0;
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
margin-top: 24px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 2px;
|
||||
background: #edf6f7;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
|
||||
@@ -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 (
|
||||
<div id={NODE_ID}>
|
||||
<div className="root">
|
||||
<div className={b('root', props, { theme })}>
|
||||
<Preloader mix="root__preloader" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -257,7 +281,7 @@ export default class Root extends Component {
|
||||
|
||||
return (
|
||||
<div id={NODE_ID}>
|
||||
<div className="root">
|
||||
<div className={b('root', props, { theme })}>
|
||||
<AuthPanel
|
||||
user={user}
|
||||
sort={sort}
|
||||
|
||||
@@ -3,6 +3,5 @@
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
color: #888;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
.user-info_theme_light {
|
||||
.user-info {
|
||||
border-color: #efefef;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.user-info__id {
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,5 @@ require('./__id/user-info__id.scss');
|
||||
require('./__preloader/user-info__preloader.scss');
|
||||
require('./__title/user-info__title.scss');
|
||||
require('./__avatar/user-info__avatar.scss');
|
||||
|
||||
require('./_theme/_light/user-info_theme_light.scss');
|
||||
|
||||
@@ -51,7 +51,7 @@ class UserInfo extends Component {
|
||||
|
||||
return (
|
||||
<div className={b('user-info', props)}>
|
||||
<Avatar className="user-info__avatar" picture={isDefaultPicture ? null : picture} />
|
||||
<Avatar mix="user-info__avatar" picture={isDefaultPicture ? null : picture} />
|
||||
<p className="user-info__title">Last comments by {name}</p>
|
||||
<p className="user-info__id">{id}</p>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './with-theme';
|
||||
@@ -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 <PlainComponent {...props} mods={{ theme, ...mods }} />;
|
||||
};
|
||||
|
||||
return ThemedComponent;
|
||||
};
|
||||
|
||||
export default withTheme;
|
||||
@@ -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 }), '*');
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+27
-1
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
@@ -15,7 +15,32 @@
|
||||
max-width: 800px;
|
||||
margin: 40px;
|
||||
}
|
||||
|
||||
.document_theme_dark {
|
||||
background: #22201c;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.document_theme_dark a {
|
||||
color: #5e5eff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function toggleTheme() {
|
||||
var body = document.querySelector('body');
|
||||
|
||||
if (body.classList.contains('document_theme_dark')) {
|
||||
body.classList.add('document_theme_light');
|
||||
body.classList.remove('document_theme_dark');
|
||||
window.REMARK42.changeTheme('light');
|
||||
} else {
|
||||
body.classList.add('document_theme_dark');
|
||||
body.classList.remove('document_theme_light');
|
||||
window.REMARK42.changeTheme('dark');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
@@ -26,6 +51,7 @@
|
||||
<li><a href="/web/last-comments.html">Last comments widget</a></li>
|
||||
<li><a href="/web/counter.html">Counter widget</a></li>
|
||||
</ul>
|
||||
<p><Button onclick="toggleTheme()">Toggle theme</Button></p>
|
||||
<div id="remark42"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
Reference in New Issue
Block a user