mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-01 03:23:09 +03:00
Merge pull request #2340 from urbit/mp/os1/soto/spinner
soto: add light/dark mode, spinner, prevent overflow
This commit is contained in:
commit
f8dd807ae8
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 773 B After Width: | Height: | Size: 1.5 KiB |
@ -9,7 +9,6 @@
|
||||
<link rel="icon" type="image/png" href="/~launch/img/Favicon.png">
|
||||
</head>
|
||||
<body class="w-100 h-100">
|
||||
<div id="header" class="w-100"></div>
|
||||
<div id="root" class="w-100 h-100">
|
||||
</div>
|
||||
<script src="/~/channel/channel.js"></script>
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -53,13 +53,27 @@ a {
|
||||
font-family: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.mix-blend-diff {
|
||||
mix-blend-mode: difference;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.invert {
|
||||
filter: invert(1);
|
||||
/* spinner */
|
||||
|
||||
.spin-active {
|
||||
animation: spin 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {transform: rotate(0deg);}
|
||||
25% {transform: rotate(90deg);}
|
||||
50% {transform: rotate(180deg);}
|
||||
75% {transform: rotate(270deg);}
|
||||
100% {transform: rotate(360deg);}
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
@ -73,4 +87,49 @@ input {
|
||||
.h-100-m40-p1-ns {
|
||||
height: calc(100% - (40px + 1rem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #333;
|
||||
}
|
||||
.bg-black-d {
|
||||
background-color: black;
|
||||
}
|
||||
.white-d {
|
||||
color: white;
|
||||
}
|
||||
.gray1-d {
|
||||
color: #4d4d4d;
|
||||
}
|
||||
.gray2-d {
|
||||
color: #7f7f7f;
|
||||
}
|
||||
.gray3-d {
|
||||
color: #b1b2b3;
|
||||
}
|
||||
.gray4-d {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.bg-gray0-d {
|
||||
background-color: #333;
|
||||
}
|
||||
.bg-gray1-d {
|
||||
background-color: #4d4d4d;
|
||||
}
|
||||
.b--gray0-d {
|
||||
border-color: #333;
|
||||
}
|
||||
.b--gray1-d {
|
||||
border-color: #4d4d4d;
|
||||
}
|
||||
.b--gray2-d {
|
||||
border-color: #7f7f7f;
|
||||
}
|
||||
.invert-d {
|
||||
filter: invert(1);
|
||||
}
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
.spinner-pending {
|
||||
position: relative;
|
||||
content: "";
|
||||
border-radius: 100%;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
||||
background-color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.spinner-pending::after {
|
||||
content: "";
|
||||
background-color: rgba(128,128,128,1);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
clip: rect(0, 16px, 16px, 8px);
|
||||
|
||||
animation: spin 1s cubic-bezier(0.745, 0.045, 0.355, 1.000) infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {transform:rotate(0deg)}
|
||||
25% {transform:rotate(90deg)}
|
||||
50% {transform:rotate(180deg)}
|
||||
75% {transform:rotate(270deg)}
|
||||
100% {transform:rotate(360deg)}
|
||||
}
|
||||
|
||||
.spinner-nostart {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
content:'';
|
||||
background-color: black;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
@import 'css/indigo-static.css';
|
||||
@import 'css/fonts.css';
|
||||
@import 'css/spinner.css';
|
||||
@import 'css/custom.css';
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { HeaderBar } from '/components/lib/header-bar';
|
||||
import { Root } from '/components/root';
|
||||
import { api } from '/api';
|
||||
import { subscription } from "/subscription";
|
||||
@ -12,8 +11,6 @@ api.setAuthTokens({
|
||||
|
||||
subscription.start();
|
||||
|
||||
ReactDOM.render(<HeaderBar />, document.getElementById("header"));
|
||||
|
||||
ReactDOM.render((
|
||||
<Root />
|
||||
), document.querySelectorAll("#root")[0]);
|
||||
|
@ -1,5 +1,3 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import _ from 'lodash';
|
||||
|
||||
class UrbitApi {
|
||||
|
@ -9,12 +9,13 @@ export class History extends Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative flex flex-column-reverse overflow-container"
|
||||
className="relative flex flex-column-reverse overflow-container flex-auto"
|
||||
style={{ height: "calc(100% - 1rem)", resize: "none" }}>
|
||||
<div style={{ marginTop: "auto" }}>
|
||||
{this.props.commandLog.map((text, index) => {
|
||||
return (
|
||||
<p className="mono" key={index}>
|
||||
<p className="mono" key={index}
|
||||
style={{overflowWrap: "break-word"}}>
|
||||
{text}
|
||||
</p>
|
||||
);
|
||||
|
@ -25,6 +25,7 @@ export class Input extends Component {
|
||||
|
||||
// submit on enter
|
||||
if (e.key === "Enter") {
|
||||
store.setSpinner(true);
|
||||
api.soto("ret");
|
||||
}
|
||||
|
||||
@ -51,6 +52,7 @@ export class Input extends Component {
|
||||
|
||||
// tab completion
|
||||
else if (e.key === "Tab") {
|
||||
store.setSpinner(true);
|
||||
api.soto({tab: this.props.cursor});
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { IconHome } from '/components/lib/icons/icon-home';
|
||||
import { IconSpinner } from '/components/lib/icons/icon-spinner';
|
||||
import { Sigil } from '/components/lib/icons/sigil';
|
||||
|
||||
export class HeaderBar extends Component {
|
||||
render() {
|
||||
// let spin = (this.props.spinner)
|
||||
// ? <div className="absolute"
|
||||
// style={{width: 16, height: 16, top: 16, left: 55}}>
|
||||
// <IconSpinner/>
|
||||
// </div>
|
||||
// : null;
|
||||
|
||||
let popout = (window.location.href.includes("popout"))
|
||||
? "dn"
|
||||
@ -21,33 +14,42 @@ export class HeaderBar extends Component {
|
||||
? ""
|
||||
: document.title;
|
||||
|
||||
let spinner = !!this.props.spinner
|
||||
? this.props.spinner : false;
|
||||
|
||||
let spinnerClasses = "";
|
||||
|
||||
if (spinner === true) {
|
||||
spinnerClasses = "spin-active";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"bg-gray1 w-100 justify-between relative tc pt3 "
|
||||
<div className={"bg-white bg-gray1-d w-100 justify-between relative tc pt3 "
|
||||
+ popout}
|
||||
style={{ height: 40 }}>
|
||||
<a className="dib white f9 inter absolute left-1"
|
||||
<a className="dib black white-d f9 inter absolute left-1"
|
||||
href='/'
|
||||
style={{ top: 14 }}>
|
||||
<IconHome />
|
||||
<span className="ml2 white v-top lh-title"
|
||||
<IconHome classes={spinnerClasses} />
|
||||
<span className="ml2 black white-d v-top lh-title"
|
||||
style={{ paddingTop: 3 }}>
|
||||
Home
|
||||
</span>
|
||||
</a>
|
||||
<span className="f9 white inter dib"
|
||||
<span className="f9 black white-d inter dib"
|
||||
style={{
|
||||
verticalAlign: "text-top",
|
||||
paddingTop: 3
|
||||
}}>{title}</span>
|
||||
{/* {spin} */}
|
||||
<div className="absolute right-1 lh-copy"
|
||||
style={{ top: 12 }}>
|
||||
<Sigil
|
||||
ship={"~" + window.ship}
|
||||
size={16}
|
||||
color={"#4d4d4d"}
|
||||
color={"#000000"}
|
||||
classes="mix-blend-diff"
|
||||
/>
|
||||
<span className="mono white f9 ml2 v-top">{"~" + window.ship}</span>
|
||||
<span className="mono black white-d f9 ml2 v-top">{"~" + window.ship}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -2,10 +2,11 @@ import React, { Component } from "react";
|
||||
|
||||
export class IconHome extends Component {
|
||||
render() {
|
||||
|
||||
let classes = !!this.props.classes ? this.props.classes : "";
|
||||
return (
|
||||
//TODO relocate to ~launch when OS1 is ported
|
||||
<img
|
||||
className="invert"
|
||||
className={"invert-d " + classes}
|
||||
src="/~link/img/Home.png"
|
||||
width={16}
|
||||
height={16}
|
||||
|
@ -1,9 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export class IconSpinner extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="spinner-pending"></div>
|
||||
);
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ export class Sigil extends Component {
|
||||
render() {
|
||||
const { props } = this;
|
||||
|
||||
let classes = !!this.props.classes ? this.props.classes : "";
|
||||
|
||||
if (props.ship.length > 14) {
|
||||
return (
|
||||
<div className="bg-black flex-shrink-0" style={{ width: props.size, height: props.size }}>
|
||||
@ -13,7 +15,7 @@ export class Sigil extends Component {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className="dib flex-shrink-0" style={{ flexBasis: 32, backgroundColor: props.color }}>
|
||||
<div className={"dib flex-shrink-0 " + classes} style={{ flexBasis: 32, backgroundColor: props.color }}>
|
||||
{sigil({
|
||||
patp: props.ship,
|
||||
renderer: reactRenderer,
|
||||
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import { BrowserRouter, Route } from "react-router-dom";
|
||||
import classnames from 'classnames';
|
||||
import _ from 'lodash';
|
||||
import { HeaderBar } from './lib/header-bar';
|
||||
import { Popout } from './lib/icons/popout';
|
||||
import { History } from './history';
|
||||
import { Input } from './input';
|
||||
@ -18,7 +19,8 @@ export class Root extends Component {
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div className="w-100 h-100 bg-gray1">
|
||||
<div className="w-100 h-100 bg-white bg-gray1-d">
|
||||
<HeaderBar spinner={this.state.spinner}/>
|
||||
<Route
|
||||
exact path="/~dojo/:popout?"
|
||||
render={(props) => {
|
||||
@ -35,14 +37,14 @@ export class Root extends Component {
|
||||
return (
|
||||
<div className="w-100 h-100 flex-m flex-l flex-xl">
|
||||
<div
|
||||
className="db dn-m dn-l dn-xl inter bg-gray0 dt w-100"
|
||||
className="db dn-m dn-l dn-xl inter bg-white bg-gray0-d dt w-100"
|
||||
style={{ height: 40 }}>
|
||||
<a className="f8 pl3 white dtc h-100 v-mid" href="/">
|
||||
<a className="f8 pl3 black white-d dtc h-100 v-mid" href="/">
|
||||
⟵ Landscape
|
||||
</a>
|
||||
</div>
|
||||
<div className={"pa3 bg-gray0 white mono w-100 f8 relative" +
|
||||
" h-100-m40-s b--gray0 br2 " + popoutClasses}
|
||||
<div className={"pa3 bg-white bg-gray0-d black white-d mono w-100 f8 relative" +
|
||||
" h-100-m40-s b--gray0 br2 flex-auto " + popoutClasses}
|
||||
style={{
|
||||
lineHeight: "1.4",
|
||||
cursor: "text"
|
||||
|
@ -9,7 +9,8 @@ export class Store {
|
||||
txt: [],
|
||||
prompt: '',
|
||||
cursor: 0,
|
||||
input: ""
|
||||
input: "",
|
||||
spinner: false
|
||||
}
|
||||
this.sync = this.sync.bind(this);
|
||||
this.print = this.print.bind(this);
|
||||
@ -19,9 +20,19 @@ export class Store {
|
||||
// recursive handler
|
||||
if (data.data) {
|
||||
var dojoReply = data.data;
|
||||
} else {
|
||||
}
|
||||
else if (data.local) {
|
||||
if (data.local.spinner) {
|
||||
return this.setState({spinner: data.local.spinner})
|
||||
}
|
||||
}
|
||||
else {
|
||||
var dojoReply = data;
|
||||
}
|
||||
|
||||
// on response, disable spinner
|
||||
this.setState({spinner: false});
|
||||
|
||||
// %mor sole-effects are nested, so throw back to handler
|
||||
if (dojoReply.map) {
|
||||
return dojoReply.map(reply => this.handleEvent(reply));
|
||||
@ -75,6 +86,14 @@ export class Store {
|
||||
setStateHandler(setState) {
|
||||
this.setState = setState;
|
||||
}
|
||||
|
||||
setSpinner(boolean) {
|
||||
store.handleEvent({
|
||||
local: {
|
||||
spinner: boolean
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export let store = new Store();
|
||||
|
Loading…
Reference in New Issue
Block a user