new layout / UI cleanup (#323)

* undo awkward backgrounds, transparencies, etc.  hope to sharpen up the active blocks and the grey/transparent backgrounds were getting in the way

* block UI and cmdinput UI overhaul

* updates for cmdinput spacing, input-sep fonts

* remove nth-child special case, fix sidebar margins

* sidebar styles

* bring back selected line

* codeedit fixes for layout / colors
This commit is contained in:
Mike Sawka 2024-02-23 16:19:01 -08:00 committed by GitHub
parent 6cd74028ef
commit 5a749d674d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 156 additions and 67 deletions

View File

@ -17,12 +17,14 @@ body {
font-size: 12px;
font-weight: 300;
line-height: 1.5;
background: @base-background-transparent;
background-color: black;
color: @base-color;
}
body.is-dev {
background-color: @base-background-dev;
body {
&.is-dev .sidebar {
background-color: @base-background-dev;
}
}
textarea {
@ -231,6 +233,7 @@ a.a-block {
display: flex;
flex-direction: row;
height: 100%;
position: relative;
.history-view,
.bookmarks-view,
@ -246,6 +249,17 @@ a.a-block {
}
overflow: auto;
}
.main-content-bottom-color {
position: absolute;
width: 100%;
left: 0;
right: 0;
bottom: 0;
height: 30%;
pointer-events: none;
background-color: @main-content-bottom-background;
}
}
}

View File

@ -115,6 +115,7 @@ class App extends React.Component<{}, {}> {
onContextMenu={this.handleContextMenu}
>
<div ref={this.mainContentRef} className="main-content">
<div className="main-content-bottom-color" />
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
<ErrorBoundary>
<PluginsView />

View File

@ -1,7 +1,7 @@
@base-color: #eceeec;
@base-background: rgba(21, 23, 21, 1);
@base-background-transparent: rgba(21, 23, 21, 0.7);
@base-background-dev: rgba(21, 23, 48, 0.7);
@base-background-transparent: rgba(15, 17, 15, 0.7);
@base-background-dev: rgba(21, 23, 48, 1);
@base-border: rgba(241, 246, 243, 0.08);
@background-session: rgba(13, 13, 13, 0.85);
@background-session-components: rgba(48, 49, 48, 0.6);
@ -15,8 +15,9 @@
@button-disabled-background: rgb(30, 29, 29);
@success-green: rgb(38, 97, 26);
@error-red: #cc0000;
@error-red-brightened: #ff8888;
@warning-yellow: #ffa500;
@textarea-background: #2a2a2a;
@textarea-background: #171717;
@text-primary: #fff;
@text-secondary: #c3c8c2;
@ -76,3 +77,6 @@
@markdown-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji";
@markdown-highlight: rgb(35, 35, 35);
@thin-border-color: #333;
@main-content-bottom-background: #333;

View File

@ -9,7 +9,7 @@
const themes = [
{
id: "default",
terminal: { foreground: "#eceeec", background: "rgba(21, 23, 21, 1)" },
terminal: { foreground: "#eceeec", background: "black" },
},
];

View File

@ -1,15 +1,14 @@
@import "@/common/themes/themes.less";
.line {
margin: 1rem 1rem 0 1rem;
padding: var(--termpad) var(--termpad) var(--termpad) var(--termpad);
border-radius: 6px;
margin: 0 10px 0 0;
padding: var(--termpad) var(--termpad) calc(var(--termpad) + 1px) calc(var(--termpad) * 2);
display: flex;
overflow: hidden;
flex-shrink: 0;
position: relative;
background: @base-background;
border: 1px solid transparent;
font-weight: normal;
font-family: var(--termfontfamily);
&.line-cmd {
flex-direction: column;
@ -36,13 +35,46 @@
}
&.selected {
border: 1px solid rgba(@base-color, 0.8) !important;
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
.line-mask {
border-left: 4px solid #ccc;
}
&.has-error {
.line-mask {
border-left: 4px solid rgba(@error-red-brightened, 0.8);
}
}
}
&.active {
border: 1px solid rgba(@wave-green, 0.8) !important;
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
&.active.selected {
.line-mask {
background-color: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(@wave-green, 0.8);
border-left: 4px solid rgba(@wave-green, 0.8);
}
&.has-error {
.line-mask {
border: 2px solid rgba(@error-red, 0.8);
border-left: 4px solid rgba(@error-red, 0.8);
}
}
}
.line-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
z-index: 10;
pointer-events: none;
&.error-mask {
background-color: rgba(200, 0, 0, 0.1);
border-left: 4px solid rgba(@error-red, 0.8);
}
}
.load-error-text {
@ -114,12 +146,6 @@
padding: 10px;
}
&:nth-child(2) {
margin: 0px 5px 5px 5px;
padding: 0px 5px 5px 12px;
border-top: none;
}
&:hover .meta .termopts {
display: block;
}
@ -169,7 +195,7 @@
}
.meta.meta-line1 {
color: rgba(@base-color, 0.6) !important;
color: @text-caption;
}
.meta.meta-line2 {

View File

@ -31,6 +31,10 @@ import "./line.less";
dayjs.extend(localizedFormat);
function cmdHasError(cmd: Cmd): boolean {
return cmd.getStatus() == "error" || cmd.getExitCode() != 0;
}
@mobxReact.observer
class SmallLineAvatar extends React.Component<{ line: LineType; cmd: Cmd; onRightClick?: (e: any) => void }, {}> {
render() {
@ -637,13 +641,15 @@ class LineCmd extends React.Component<
.get();
const isRunning = cmd.isRunning();
const isExpanded = this.isCmdExpanded.get();
const cmdError = cmdHasError(cmd);
const mainDivCn = cn(
"line",
"line-cmd",
{ selected: isSelected },
{ active: isSelected && isFocused },
{ "cmd-done": !isRunning },
{ "has-rtnstate": isRtnState }
{ "has-rtnstate": isRtnState },
{ "has-error": cmdError }
);
let rendererPlugin: RendererPluginType = null;
const isNoneRenderer = line.renderer == "none";
@ -663,6 +669,9 @@ class LineCmd extends React.Component<
data-linenum={line.linenum}
data-screenid={line.screenid}
>
<If condition={isSelected || cmdError}>
<div key="mask" className={cn("line-mask", { "error-mask": cmdError })}></div>
</If>
<div
key="header"
className={cn("line-header", { "is-expanded": isExpanded }, { "hide-prompt": hidePrompt })}

View File

@ -4,7 +4,7 @@
display: flex;
flex-direction: column;
overflow: auto;
padding: 0 0 10px 0;
padding: 0;
flex-grow: 1;
position: relative;
overflow-x: hidden;
@ -32,26 +32,34 @@
flex-grow: 1;
}
.line-sep {
.line-sep-labeled {
display: flex;
align-items: center;
margin-top: 1em;
color: rgba(@base-color, 0.5);
color: @text-caption;
font-family: var(--termfontfamily);
line-height: var(--termlineheight);
font-size: var(--termfontsize);
}
.line-sep::before,
.line-sep::after {
.line-sep-labeled::before,
.line-sep-labeled::after {
content: "";
height: 1px;
flex-grow: 1;
background-color: rgba(@base-color, 0.5);
}
.line-sep::before {
.line-sep-labeled::before {
margin-right: 1rem;
}
.line-sep::after {
.line-sep-labeled::after {
margin-left: 1rem;
}
.line-sep {
width: 100%;
height: 1px;
border-bottom: 1px solid @thin-border-color;
}
}

View File

@ -471,11 +471,13 @@ class LinesView extends React.Component<
prevDateStr = curDateStr;
if (dateSepStr != null) {
let sepElem = (
<div key={"sep-" + line.lineid} className="line-sep">
<div key={"sep-" + line.lineid} className="line-sep-labeled">
{dateSepStr}
</div>
);
lineElements.push(sepElem);
} else if (idx > 0) {
lineElements.push(<div key={"sep-" + line.lineid} className="line-sep"></div>);
}
let topBorder = dateSepStr == null && this.hasTopBorder(lines, idx);
let lineProps = {

View File

@ -10,6 +10,9 @@
line-height: 20px;
backdrop-filter: blur(4px);
z-index: 20;
border-radius: 10px;
border-left: 1px solid @thin-border-color;
border-bottom: 1px solid @thin-border-color;
.title-bar-drag {
-webkit-app-region: drag;

View File

@ -1,25 +1,17 @@
@import "@/common/themes/themes.less";
.cmd-input {
border-radius: 6px;
max-height: max(300px, 40%);
display: flex;
flex-direction: column;
position: absolute;
bottom: var(--termfontsize);
right: var(--termfontsize);
width: calc(100% - 2 * var(--termfontsize));
bottom: 0;
width: 100%;
padding: var(--termfontsize);
z-index: 100;
background: @background-session-components;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.5), 0px 3px 8px 0px rgba(0, 0, 0, 0.35),
0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
backdrop-filter: blur(20px);
border: 1px solid transparent;
border-top: 1px solid @thin-border-color;
&.active {
border: 1px solid rgba(@wave-green, 0.8) !important;
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
}
&.has-info {

View File

@ -4,6 +4,7 @@
.screen-view {
flex-grow: 1;
position: relative;
border-top: 1px solid @thin-border-color;
}
.screen-sidebar,
@ -17,19 +18,36 @@
right: 0;
display: flex;
flex-direction: column;
height: calc(100% - 0.5rem);
height: 100%;
overflow: hidden;
margin-left: 5px;
padding-left: 5px;
overflow-y: auto;
border-left: 1px solid @thin-border-color;
.sidebar-header {
/* sidebar-header height linked to MagicLayout.ScreenSidebarHeaderHeight */
display: flex;
flex-direction: row;
padding: 3px 5px;
border-radius: 3px;
margin: 3px 5px 0 5px;
padding: 3px 0;
margin: 0;
border-bottom: 1px solid @thin-border-color;
font-size: var(--termfontsize);
font-family: var(--termfontfamily);
font-weight: normal;
line-height: var(--termlineheight);
color: @text-caption;
&:hover {
color: white;
}
div.pane-name {
visibility: hidden;
margin-left: calc(var(--termpad) * 2);
}
&:hover div.pane-name {
visibility: visible;
}
i {
padding: 3px;
@ -73,7 +91,7 @@
display: flex;
flex-direction: column;
position: absolute;
height: calc(100% - 0.5rem);
height: 100%;
overflow-x: hidden;
.rendermode-tag {

View File

@ -300,6 +300,7 @@ class ScreenSidebar extends React.Component<{ screen: Screen; width: string }, {
return (
<div className="screen-sidebar" style={{ width: width }} ref={this.sidebarRef}>
<div className="sidebar-header">
<div className="pane-name">sidebar</div>
<div className="flex-spacer" />
<div onClick={this.sidebarOpenHalf} title="Set Sidebar Width to 50%">
<i className="fa-sharp fa-solid fa-table-columns" />
@ -307,8 +308,8 @@ class ScreenSidebar extends React.Component<{ screen: Screen; width: string }, {
<div onClick={this.sidebarOpenPartial} title="Set Sidebar Width to 500px">
<i className="fa-sharp fa-solid fa-sidebar-flip" />
</div>
<div onClick={this.sidebarClose} style={{ marginLeft: 5 }}>
<i className="fa-sharp fa-solid fa-xmark" />
<div onClick={this.sidebarClose} style={{ marginLeft: 5, marginRight: 10 }}>
<i className="fa-sharp fa-solid fa-xmark-large" />
</div>
</div>
<If condition={!sidebarOk}>

View File

@ -8,12 +8,12 @@
&.is-hidden {
display: none;
}
background: @background-session;
border: 1px solid @base-border;
border-radius: 8px;
// transition: width 0.2s ease;
margin-bottom: 0.5em;
margin-right: 0.5em;
border-radius: 10px;
border-radius: 0 0 6px 6px;
border-bottom: 1px solid @thin-border-color;
border-right: 1px solid @thin-border-color;
border-left: 1px solid @thin-border-color;
background-color: black;
.center-message {
display: flex;

View File

@ -36,7 +36,6 @@ class WorkspaceView extends React.Component<{}, {}> {
if (cmdInputHeight == 0) {
cmdInputHeight = MagicLayout.CmdInputHeight; // this is the base size of cmdInput (measured using devtools)
}
cmdInputHeight += MagicLayout.CmdInputBottom; // reference to .cmd-input, bottom: 12px
let isHidden = GlobalModel.activeMainView.get() != "session";
let mainSidebarModel = GlobalModel.mainSidebarModel;

View File

@ -4,7 +4,7 @@
.monaco-editor {
.monaco-editor-background,
.margin-view-overlays {
background-color: @base-background !important;
background-color: black !important;
}
.scrollbar {
height: 4px !important;
@ -16,7 +16,6 @@
}
.buttonContainer {
opacity: 0;
transition: opacity 0.2s;
position: absolute;
padding: 0.5rem;
right: 0;
@ -49,7 +48,7 @@
}
}
section {
transition: height 0.3s ease-in-out;
// transition: height 0.3s ease-in-out;
}
.messageContainer {
position: absolute;

View File

@ -8,11 +8,24 @@ import { Markdown } from "@/elements";
import { GlobalModel, GlobalCommandRunner } from "@/models";
import Split from "react-split-it";
import loader from "@monaco-editor/loader";
loader.config({ paths: { vs: "./node_modules/monaco-editor/min/vs" } });
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import "./code.less";
document.addEventListener("DOMContentLoaded", () => {
loader.config({ paths: { vs: "./node_modules/monaco-editor/min/vs" } });
loader.init().then(() => {
monaco.editor.defineTheme("wave-theme", {
base: "hc-black",
inherit: true,
rules: [],
colors: {
"editor.background": "#000000",
},
});
});
});
function renderCmdText(text: string): any {
return <span>&#x2318;{text}</span>;
}
@ -330,7 +343,7 @@ class SourceCodeRenderer extends React.Component<
<div style={{ maxHeight: this.props.opts.maxSize.height }}>
{this.state.showReadonly && <div className="readonly">{"read-only"}</div>}
<Editor
theme="hc-black"
theme="wave-theme"
height={this.state.editorHeight}
defaultLanguage={this.state.selectedLanguage}
value={this.state.code}

View File

@ -189,7 +189,7 @@ class TermWrap {
return;
}
this.terminal.focus();
setTimeout(() => this.terminal._core.viewport.syncScrollArea(true), 0);
setTimeout(() => this.terminal?._core?.viewport?.syncScrollArea(true), 0);
}
disconnectElem() {