forked from newthuhole/hole_thu_frontend
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,
|
||||
flow_render_key: +new Date(),
|
||||
token: localStorage['TOKEN']||null,
|
||||
darkmode: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
||||
};
|
||||
this.show_sidebar_bound=this.show_sidebar.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;
|
||||
}
|
||||
|
||||
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() {
|
||||
if(this.state.sidebar_title!==null)
|
||||
this.setState((prevState)=>({
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.root-dark-mode .bg-img {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.black-outline {
|
||||
text-shadow: /* also change .flow-item-row-with-prompt:hover::before */
|
||||
-1px -1px 0 rgba(0,0,0,.6),
|
||||
@@ -22,6 +26,23 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.root-dark-mode .search-query-highlight {
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.url-pid-link {
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
render() {
|
||||
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' ? <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==='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> :
|
||||
p
|
||||
}</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 {
|
||||
background-color: hsl(0,0%,97%);
|
||||
background-color: var(--box-bgcolor-light);
|
||||
color: black;
|
||||
border-radius: 5px;
|
||||
margin: 1em 0;
|
||||
padding: .5em;
|
||||
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 {
|
||||
min-width: 100px;
|
||||
z-index: 1;
|
||||
@@ -18,6 +34,11 @@
|
||||
text-shadow: 0 0 3px black;
|
||||
}
|
||||
|
||||
.root-dark-mode .box-danger {
|
||||
background-color: #d44;
|
||||
color: var(--foreground-dark);
|
||||
}
|
||||
|
||||
.left-container .flow-item {
|
||||
display: inline-block;
|
||||
width: 600px;
|
||||
@@ -139,6 +160,10 @@
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
.root-dark-mode .flow-item-row p.img img {
|
||||
filter: brightness(.8);
|
||||
}
|
||||
|
||||
.box-header-badge {
|
||||
float: right;
|
||||
margin: 0 .5em;
|
||||
@@ -157,6 +182,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.root-dark-mode .flow-item-dot {
|
||||
background-color: #eebb66;
|
||||
}
|
||||
|
||||
.left-container .flow-item-dot {
|
||||
display: block;
|
||||
}
|
||||
@@ -174,6 +203,10 @@
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.root-dark-mode .box-id {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.box-id a:hover::before {
|
||||
content: "复制全文";
|
||||
position: relative;
|
||||
@@ -225,3 +258,7 @@
|
||||
margin-right: .25em;
|
||||
padding: 0 .25em;
|
||||
}
|
||||
|
||||
.root-dark-mode .box-header-tag {
|
||||
background-color: #00a;
|
||||
}
|
||||
@@ -80,7 +80,8 @@ class Reply extends PureComponent {
|
||||
]);
|
||||
return (
|
||||
<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}>
|
||||
<div className="box-header">
|
||||
<code className="box-id">#{this.props.info.cid}</code>
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
.root-dark-mode .sidebar-on .sidebar-shadow {
|
||||
opacity: .5;
|
||||
}
|
||||
.root-dark-mode .sidebar-on .sidebar-shadow:active {
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
user-select: text;
|
||||
position: fixed;
|
||||
@@ -32,6 +39,10 @@
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.root-dark-mode .sidebar {
|
||||
background-color: hsla(0,0%,5%,.7);
|
||||
}
|
||||
|
||||
.sidebar, .sidebar-title {
|
||||
will-change: left;
|
||||
left: 100%;
|
||||
@@ -56,6 +67,13 @@
|
||||
backdrop-filter: blur(10px);
|
||||
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 {
|
||||
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 {
|
||||
z-index: 10;
|
||||
position: sticky;
|
||||
@@ -11,6 +19,10 @@
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.root-dark-mode .title-bar {
|
||||
background-color: hsla(0,0%,80%,.7);
|
||||
}
|
||||
|
||||
.control-bar {
|
||||
display: flex;
|
||||
margin-top: .5em;
|
||||
@@ -36,13 +48,17 @@
|
||||
.control-search {
|
||||
flex: auto;
|
||||
color: black;
|
||||
background-color: rgba(255,255,255,.3);
|
||||
background-color: rgba(255,255,255,.3) !important;
|
||||
margin: 0 .5em;
|
||||
min-width: 8em;
|
||||
}
|
||||
|
||||
.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 {
|
||||
|
||||
@@ -11,14 +11,17 @@ export class ColorPicker {
|
||||
get(name) {
|
||||
name=name.toLowerCase();
|
||||
if(name==='洞主')
|
||||
return 'hsl(0,0%,97%)';
|
||||
return ['hsl(0,0%,97%)','hsl(0,0%,25%)'];
|
||||
if(!window.config.color_picker)
|
||||
return 'hsl(0,0%,87%)';
|
||||
return ['hsl(0,0%,87%)','hsl(0,0%,13%)'];
|
||||
|
||||
if(!this.names[name]) {
|
||||
this.current_h+=golden_ratio_conjugate;
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ body {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
body.root-dark-mode {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
html::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
@@ -15,6 +19,10 @@ a {
|
||||
color: #00c;
|
||||
}
|
||||
|
||||
.root-dark-mode .left-container a, .root-dark-mode .sidebar a, .root-dark-mode .sidebar-title a {
|
||||
color: #9bf;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
border-radius: 5px;
|
||||
border: 1px solid black;
|
||||
@@ -39,6 +47,10 @@ button, .button {
|
||||
margin: 0 .5rem;
|
||||
}
|
||||
|
||||
.root-dark-mode button, .root-dark-mode .button {
|
||||
background-color: rgba(255,255,255,.6);
|
||||
}
|
||||
|
||||
button:hover, .button:hover {
|
||||
background-color: rgba(255,255,255,.7);
|
||||
}
|
||||
@@ -46,3 +58,7 @@ button:hover, .button:hover {
|
||||
button:disabled, .button:disabled {
|
||||
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