add dark mode
This commit is contained in:
23
src/App.js
23
src/App.js
@@ -21,6 +21,7 @@ class App extends Component {
|
|||||||
search_text: null,
|
search_text: null,
|
||||||
flow_render_key: +new Date(),
|
flow_render_key: +new Date(),
|
||||||
token: localStorage['TOKEN']||null,
|
token: localStorage['TOKEN']||null,
|
||||||
|
darkmode: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
||||||
};
|
};
|
||||||
this.show_sidebar_bound=this.show_sidebar.bind(this);
|
this.show_sidebar_bound=this.show_sidebar.bind(this);
|
||||||
this.set_mode_bound=this.set_mode.bind(this);
|
this.set_mode_bound=this.set_mode.bind(this);
|
||||||
@@ -30,6 +31,28 @@ class App extends Component {
|
|||||||
this.inpku_flag=window[atob('ZG9jdW1lbnQ')][atob('Y29va2ll')].indexOf(atob('cGt1X2lwX2ZsYWc9eWVz'))!==-1;
|
this.inpku_flag=window[atob('ZG9jdW1lbnQ')][atob('Y29va2ll')].indexOf(atob('cGt1X2lwX2ZsYWc9eWVz'))!==-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.update_color_scheme();
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addListener((e)=>{
|
||||||
|
this.setState({
|
||||||
|
darkmode: e.matches,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps,prevState) {
|
||||||
|
if(this.state.darkmode!==prevState.darkmode)
|
||||||
|
this.update_color_scheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
update_color_scheme() {
|
||||||
|
if(this.state.darkmode)
|
||||||
|
document.body.classList.add('root-dark-mode');
|
||||||
|
else
|
||||||
|
document.body.classList.remove('root-dark-mode');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
on_pressure() {
|
on_pressure() {
|
||||||
if(this.state.sidebar_title!==null)
|
if(this.state.sidebar_title!==null)
|
||||||
this.setState((prevState)=>({
|
this.setState((prevState)=>({
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .bg-img {
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
.black-outline {
|
.black-outline {
|
||||||
text-shadow: /* also change .flow-item-row-with-prompt:hover::before */
|
text-shadow: /* also change .flow-item-row-with-prompt:hover::before */
|
||||||
-1px -1px 0 rgba(0,0,0,.6),
|
-1px -1px 0 rgba(0,0,0,.6),
|
||||||
@@ -22,6 +26,23 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .search-query-highlight {
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
.url-pid-link {
|
.url-pid-link {
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--coloredspan-bgcolor-light: white;
|
||||||
|
--coloredspan-bgcolor-dark: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colored-span {
|
||||||
|
background-color: var(--coloredspan-bgcolor-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .colored-span {
|
||||||
|
background-color: var(--coloredspan-bgcolor-dark);
|
||||||
|
}
|
||||||
@@ -17,6 +17,15 @@ export function build_highlight_re(txt,split) {
|
|||||||
return txt ? new RegExp(`(${txt.split(split).filter((x)=>!!x).map(escape_regex).join('|')})`,'g') : /^$/g;
|
return txt ? new RegExp(`(${txt.split(split).filter((x)=>!!x).map(escape_regex).join('|')})`,'g') : /^$/g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ColoredSpan(props) {
|
||||||
|
return (
|
||||||
|
<span className="colored-span" style={{
|
||||||
|
'--coloredspan-bgcolor-light': props.colors[0],
|
||||||
|
'--coloredspan-bgcolor-dark': props.colors[1],
|
||||||
|
}}>{props.children}</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export class HighlightedText extends PureComponent {
|
export class HighlightedText extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
function normalize_url(url) {
|
function normalize_url(url) {
|
||||||
@@ -31,7 +40,7 @@ export class HighlightedText extends PureComponent {
|
|||||||
rule==='url_pid' ? <span className="url-pid-link" title={p}>/hole/##</span> :
|
rule==='url_pid' ? <span className="url-pid-link" title={p}>/hole/##</span> :
|
||||||
rule==='url' ? <a href={normalize_url(p)} target="_blank" rel="noopener">{p}</a> :
|
rule==='url' ? <a href={normalize_url(p)} target="_blank" rel="noopener">{p}</a> :
|
||||||
rule==='pid' ? <a href={'##'+p} onClick={(e)=>{e.preventDefault(); this.props.show_pid(p);}}>{p}</a> :
|
rule==='pid' ? <a href={'##'+p} onClick={(e)=>{e.preventDefault(); this.props.show_pid(p);}}>{p}</a> :
|
||||||
rule==='nickname' ? <span style={{backgroundColor: this.props.color_picker.get(p)}}>{p}</span> :
|
rule==='nickname' ? <ColoredSpan colors={this.props.color_picker.get(p)}>{p}</ColoredSpan> :
|
||||||
rule==='search' ? <span className="search-query-highlight">{p}</span> :
|
rule==='search' ? <span className="search-query-highlight">{p}</span> :
|
||||||
p
|
p
|
||||||
}</span>
|
}</span>
|
||||||
|
|||||||
@@ -1,11 +1,27 @@
|
|||||||
|
:root {
|
||||||
|
--box-bgcolor-light: hsl(0,0%,97%);
|
||||||
|
--box-bgcolor-dark: hsl(0,0%,20%);
|
||||||
|
--foreground-dark: hsl(0,0%,93%)
|
||||||
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
background-color: hsl(0,0%,97%);
|
background-color: var(--box-bgcolor-light);
|
||||||
|
color: black;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
box-shadow: 0 2px 5px rgba(0,0,0,.4);
|
box-shadow: 0 2px 5px rgba(0,0,0,.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .box {
|
||||||
|
background-color: var(--box-bgcolor-dark);
|
||||||
|
color: var(--foreground-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .sidebar .box {
|
||||||
|
--box-bgcolor-dark: hsl(0,0%,25%);
|
||||||
|
}
|
||||||
|
|
||||||
.box-tip {
|
.box-tip {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -18,6 +34,11 @@
|
|||||||
text-shadow: 0 0 3px black;
|
text-shadow: 0 0 3px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .box-danger {
|
||||||
|
background-color: #d44;
|
||||||
|
color: var(--foreground-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.left-container .flow-item {
|
.left-container .flow-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
@@ -139,6 +160,10 @@
|
|||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .flow-item-row p.img img {
|
||||||
|
filter: brightness(.8);
|
||||||
|
}
|
||||||
|
|
||||||
.box-header-badge {
|
.box-header-badge {
|
||||||
float: right;
|
float: right;
|
||||||
margin: 0 .5em;
|
margin: 0 .5em;
|
||||||
@@ -157,6 +182,10 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .flow-item-dot {
|
||||||
|
background-color: #eebb66;
|
||||||
|
}
|
||||||
|
|
||||||
.left-container .flow-item-dot {
|
.left-container .flow-item-dot {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -174,6 +203,10 @@
|
|||||||
color: #666666;
|
color: #666666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .box-id {
|
||||||
|
color: #bbbbbb;
|
||||||
|
}
|
||||||
|
|
||||||
.box-id a:hover::before {
|
.box-id a:hover::before {
|
||||||
content: "复制全文";
|
content: "复制全文";
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -225,3 +258,7 @@
|
|||||||
margin-right: .25em;
|
margin-right: .25em;
|
||||||
padding: 0 .25em;
|
padding: 0 .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .box-header-tag {
|
||||||
|
background-color: #00a;
|
||||||
|
}
|
||||||
@@ -80,7 +80,8 @@ class Reply extends PureComponent {
|
|||||||
]);
|
]);
|
||||||
return (
|
return (
|
||||||
<div className={'flow-reply box'} style={this.props.info._display_color ? {
|
<div className={'flow-reply box'} style={this.props.info._display_color ? {
|
||||||
backgroundColor: this.props.info._display_color,
|
'--box-bgcolor-light': this.props.info._display_color[0],
|
||||||
|
'--box-bgcolor-dark': this.props.info._display_color[1],
|
||||||
} : null}>
|
} : null}>
|
||||||
<div className="box-header">
|
<div className="box-header">
|
||||||
<code className="box-id">#{this.props.info.cid}</code>
|
<code className="box-id">#{this.props.info.cid}</code>
|
||||||
|
|||||||
@@ -20,6 +20,13 @@
|
|||||||
transition: unset;
|
transition: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .sidebar-on .sidebar-shadow {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.root-dark-mode .sidebar-on .sidebar-shadow:active {
|
||||||
|
opacity: .3;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
user-select: text;
|
user-select: text;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -32,6 +39,10 @@
|
|||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .sidebar {
|
||||||
|
background-color: hsla(0,0%,5%,.7);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar, .sidebar-title {
|
.sidebar, .sidebar-title {
|
||||||
will-change: left;
|
will-change: left;
|
||||||
left: 100%;
|
left: 100%;
|
||||||
@@ -56,6 +67,13 @@
|
|||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
box-shadow: 0 3px 5px rgba(0,0,0,.2);
|
box-shadow: 0 3px 5px rgba(0,0,0,.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .sidebar-title {
|
||||||
|
background-color: hsla(0,0%,20%,.6);
|
||||||
|
color: var(--foreground-dark);
|
||||||
|
text-shadow: 0 0 3px black;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-title a {
|
.sidebar-title a {
|
||||||
pointer-events: initial;
|
pointer-events: initial;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/* overriding infrastructure/widget.css */
|
||||||
|
.root-dark-mode .title-line {
|
||||||
|
color: var(--foreground-dark);
|
||||||
|
}
|
||||||
|
.root-dark-mode .title-line::before, .root-dark-mode .title-line::after {
|
||||||
|
background-color: var(--foreground-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.title-bar {
|
.title-bar {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@@ -11,6 +19,10 @@
|
|||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .title-bar {
|
||||||
|
background-color: hsla(0,0%,80%,.7);
|
||||||
|
}
|
||||||
|
|
||||||
.control-bar {
|
.control-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: .5em;
|
margin-top: .5em;
|
||||||
@@ -36,13 +48,17 @@
|
|||||||
.control-search {
|
.control-search {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
color: black;
|
color: black;
|
||||||
background-color: rgba(255,255,255,.3);
|
background-color: rgba(255,255,255,.3) !important;
|
||||||
margin: 0 .5em;
|
margin: 0 .5em;
|
||||||
min-width: 8em;
|
min-width: 8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-search:focus {
|
.control-search:focus {
|
||||||
background-color: white;
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .control-search:focus {
|
||||||
|
background-color: hsl(0,0%,90%) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-menu {
|
.list-menu {
|
||||||
|
|||||||
@@ -11,14 +11,17 @@ export class ColorPicker {
|
|||||||
get(name) {
|
get(name) {
|
||||||
name=name.toLowerCase();
|
name=name.toLowerCase();
|
||||||
if(name==='洞主')
|
if(name==='洞主')
|
||||||
return 'hsl(0,0%,97%)';
|
return ['hsl(0,0%,97%)','hsl(0,0%,25%)'];
|
||||||
if(!window.config.color_picker)
|
if(!window.config.color_picker)
|
||||||
return 'hsl(0,0%,87%)';
|
return ['hsl(0,0%,87%)','hsl(0,0%,13%)'];
|
||||||
|
|
||||||
if(!this.names[name]) {
|
if(!this.names[name]) {
|
||||||
this.current_h+=golden_ratio_conjugate;
|
this.current_h+=golden_ratio_conjugate;
|
||||||
this.current_h%=1;
|
this.current_h%=1;
|
||||||
this.names[name]=`hsl(${this.current_h*360}, 50%, 90%)`;
|
this.names[name]=[
|
||||||
|
`hsl(${this.current_h*360}, 50%, 90%)`,
|
||||||
|
`hsl(${this.current_h*360}, 60%, 25%)`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return this.names[name];
|
return this.names[name];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ body {
|
|||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.root-dark-mode {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
html::-webkit-scrollbar {
|
html::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -15,6 +19,10 @@ a {
|
|||||||
color: #00c;
|
color: #00c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode .left-container a, .root-dark-mode .sidebar a, .root-dark-mode .sidebar-title a {
|
||||||
|
color: #9bf;
|
||||||
|
}
|
||||||
|
|
||||||
input, textarea {
|
input, textarea {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
@@ -39,6 +47,10 @@ button, .button {
|
|||||||
margin: 0 .5rem;
|
margin: 0 .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode button, .root-dark-mode .button {
|
||||||
|
background-color: rgba(255,255,255,.6);
|
||||||
|
}
|
||||||
|
|
||||||
button:hover, .button:hover {
|
button:hover, .button:hover {
|
||||||
background-color: rgba(255,255,255,.7);
|
background-color: rgba(255,255,255,.7);
|
||||||
}
|
}
|
||||||
@@ -46,3 +58,7 @@ button:hover, .button:hover {
|
|||||||
button:disabled, .button:disabled {
|
button:disabled, .button:disabled {
|
||||||
background-color: rgba(128,128,128,.5);
|
background-color: rgba(128,128,128,.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-dark-mode input:not([type=file]), .root-dark-mode textarea {
|
||||||
|
background-color: hsl(0,0%,80%);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user