UI updates for command prompt / cmdinput (#354)

* remove [local] from prompt, remove prompt icons, restore --term vars (remove --prompt vars)

* working on prompt colors, cmdtext

* more generous padding around commands (and cmdinput)

* fix cmdinput background color

* fixes for cmdinput info box
This commit is contained in:
Mike Sawka 2024-02-27 22:46:07 -08:00 committed by GitHub
parent 17990afd5d
commit 0464cccf0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 146 additions and 223 deletions

View File

@ -1,73 +1,72 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
.term-prompt {
font-weight: normal;
font-size: var(--termfontsize);
line-height: var(--termlineheight);
font-family: var(--termfontfamily);
.icon {
margin: 0 4px 0 2px;
vertical-align: middle;
width: 1.2em;
height: 1.2em;
fill: var(--app-accent-color);
}
color: var(--term-gray);
i {
margin-right: 0.25em; // em for relative sizing
}
}
.term-prompt.term-prompt-color {
.term-prompt-branch {
color: var(--prompt-white);
color: var(--term-white);
}
.term-prompt-python {
color: var(--prompt-bright-magenta);
color: var(--term-bright-magenta);
}
.term-prompt-remote {
}
.term-prompt-remote {
color: var(--prompt-bright-green);
color: var(--term-bright-green);
&.color-green {
color: var(--prompt-bright-green);
color: var(--term-bright-green);
}
&.color-red {
color: var(--prompt-bright-red);
color: var(--term-bright-red);
}
&.color-blue {
color: var(--prompt-bright-blue);
color: var(--term-bright-blue);
}
&.color-yellow {
color: var(--prompt-bright-yellow);
color: var(--term-bright-yellow);
}
&.color-magenta {
color: var(--prompt-bright-magenta);
color: var(--term-bright-magenta);
}
&.color-cyan {
color: var(--prompt-bright-cyan);
color: var(--termt-bright-cyan);
}
&.color-white {
color: var(--prompt-bright-white);
color: var(--term-bright-white);
}
&.color-orange {
color: var(--prompt-orange);
color: var(--term-orange);
}
}
.term-prompt-cwd {
color: var(--prompt-bright-green);
color: var(--term-bright-green);
}
.term-prompt-end {
color: var(--prompt-bright-green);
.term-prompt-end-user {
color: var(--term-bright-green);
}
.term-prompt-end-root {
color: var(--term-bright-red);
}
}

View File

@ -69,7 +69,7 @@ function getCwdStr(remote: RemoteType, state: Record<string, string>): string {
}
@mobxReact.observer
class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<string, string> }, {}> {
class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<string, string>; color: boolean }, {}> {
render() {
let rptr = this.props.rptr;
if (rptr == null || isBlank(rptr.remoteid)) {
@ -96,24 +96,30 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
}
let cwdElem = (
<span title="current directory" className="term-prompt-cwd">
<i className="fa-sharp fa-solid fa-folder" style={{ marginRight: Math.ceil(termFontSize / 4) }} />
{cwd}
</span>
);
let remoteElem = (
<span title={remoteTitle} className={cn("term-prompt-remote", remoteColorClass)}>
[{remoteStr}]{" "}
</span>
);
let rootIndicatorElem = <span className="term-prompt-end">{isRoot ? "#" : "$"}</span>;
let remoteElem = null;
if (remoteStr != "local") {
remoteElem = (
<span title={remoteTitle} className={cn("term-prompt-remote", remoteColorClass)}>
[{remoteStr}]{" "}
</span>
);
}
let rootIndicatorElem = null;
if (isRoot) {
rootIndicatorElem = <span className="term-prompt-end-root">#</span>;
} else {
rootIndicatorElem = <span className="term-prompt-end-user">$</span>;
}
let branchElem = null;
let pythonElem = null;
if (!isBlank(festate["PROMPTVAR_GITBRANCH"])) {
let branchName = festate["PROMPTVAR_GITBRANCH"];
branchElem = (
<span title="current git branch" className="term-prompt-branch">
<i className="fa-sharp fa-solid fa-code-branch" />
{branchName}{" "}
git:({branchName}){" "}
</span>
);
}
@ -122,16 +128,14 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
let venv = getShortVEnv(venvDir);
pythonElem = (
<span title="python venv" className="term-prompt-python">
<i className="fa-brands fa-python" />
{venv}{" "}
venv:({venv}){" "}
</span>
);
}
return (
<span className="term-prompt">
<span className={cn("term-prompt", { "term-prompt-color": this.props.color })}>
{remoteElem} {pythonElem}
{branchElem}
{cwdElem} {rootIndicatorElem}
{cwdElem} {branchElem} {rootIndicatorElem}
</span>
);
}

View File

@ -253,7 +253,7 @@
.line-container {
padding: 0px 10px 10px 10px;
overflow-x: auto;
background-color: var(--prompt-black);
background-color: var(--term-black);
}
.line-context {

View File

@ -1,6 +1,6 @@
.line {
margin: 0;
padding: var(--termpad) var(--termpad) calc(var(--termpad) + 1px) calc(var(--termpad) * 2);
padding: calc(var(--termpad) * 2) var(--termpad) calc(var(--termpad) * 2 + 1px) calc(var(--termpad) * 3);
display: flex;
overflow: hidden;
flex-shrink: 0;
@ -177,7 +177,7 @@
visibility: visible;
}
.line-icon + .line-icon {
.line-icon + .line-icon {p
margin-left: 5px;
}
@ -193,7 +193,7 @@
}
.meta.meta-line1 {
color: var(--line-meta-text-color);
color: var(--term-gray);
}
.meta.meta-line2 {
@ -280,6 +280,10 @@
color: var(--term-text-white);
cursor: pointer;
}
.meta-cmdtext {
color: var(--term-bright-white);
}
}
.cmdtext-expanded-wrapper {

View File

@ -231,7 +231,7 @@ class LineCmd extends React.Component<
<React.Fragment>
<div key="meta2" className="meta meta-line2">
<div className="metapart-mono cmdtext">
<Prompt rptr={cmd.remote} festate={cmd.getRemoteFeState()} />
<Prompt rptr={cmd.remote} festate={cmd.getRemoteFeState()} color={true} />
</div>
</div>
<div key="meta3" className="meta meta-line3 cmdtext-expanded-wrapper">
@ -244,9 +244,9 @@ class LineCmd extends React.Component<
return (
<div key="meta2" className="meta meta-line2" ref={this.cmdTextRef}>
<div className="metapart-mono cmdtext">
<Prompt rptr={cmd.remote} festate={cmd.getRemoteFeState()} />
<Prompt rptr={cmd.remote} festate={cmd.getRemoteFeState()} color={true} />
<span> </span>
<span>{lineutil.getSingleLineCmdText(cmd.getCmdStr())}</span>
<span className="meta-cmdtext">{lineutil.getSingleLineCmdText(cmd.getCmdStr())}</span>
</div>
<If condition={this.isOverflow.get() || isMultiLine}>
<div className="cmdtext-overflow" onClick={this.handleExpandCmd}>

View File

@ -22,7 +22,7 @@
.line-sep-labeled {
display: flex;
align-items: center;
color: var(--line-meta-text-color);
color: var(--term-gray);
font-family: var(--termfontfamily);
line-height: var(--termlineheight);
font-size: var(--termfontsize);

View File

@ -68,19 +68,24 @@
--tab-pink: rgb(224, 86, 119);
--tab-white: rgb(255, 255, 255);
// prompt colors
--prompt-black: rgb(0, 0, 0);
--prompt-white: rgb(211, 215, 207);
--prompt-orange: rgb(239, 113, 59);
--prompt-blue: rgb(52, 101, 164);
--prompt-bright-black: rgb(85, 87, 83);
--prompt-bright-red: rgb(239, 41, 41);
--prompt-bright-green: rgb(88, 193, 66);
--prompt-bright-yellow: rgb(252, 233, 79);
--prompt-bright-blue: rgb(50, 175, 255);
--prompt-bright-magenta: rgb(173, 127, 168);
--prompt-bright-cyan: rgb(52, 226, 226);
--prompt-bright-white: rgb(255, 255, 255);
// term colors
--term-black: #000000;
--term-red: #cc0000;
--term-green: #4e9a06;
--term-yellow: #c4a000;
--term-blue: #3465a4;
--term-magenta: #75507b;
--term-cyan: #06989a;
--term-white: #d3d7cf;
--term-bright-black: #555753;
--term-bright-red: #ef2929;
--term-bright-green: #58c142;
--term-bright-yellow: #fce94f;
--term-bright-blue: #32afff;
--term-bright-magenta: #ad7fa8;
--term-bright-cyan: #34e2e2;
--term-bright-white: #ffffff;
--term-gray: rgb(139, 145, 138); // not an official terminal color
// button colors
--button-text-color: rgb(255, 255, 255);
@ -164,7 +169,6 @@
--line-svg-hover-fill-color: #eceeec;
--line-selected-border-color: rgb(193, 195, 193);
--line-separator-color: rgb(126, 126, 126);
--line-meta-line1-color: rgb(150, 152, 150);
--line-error-color: #cc0000;
--line-warning-color: #ffa500;
--line-base-soft-blue-color: #729fcf;
@ -176,7 +180,6 @@
--line-error-bg-color: rgba(200, 0, 0, 0.1);
--line-error-border-left-color: rgba(204, 0, 0, 0.8);
--line-simple-text-color: rgba(236, 238, 236, 0.6);
--line-meta-text-color: rgb(139, 145, 138);
--line-meta-user-color: rgba(140, 184, 232);
--line-svg-color: rgba(236, 238, 236, 0.6);
--line-svg-hover-color: rgba(236, 238, 236, 1);
@ -201,11 +204,9 @@
// cmdinput colors
--cmdinput-textarea-bg-color: #171717;
--cmdinput-text-error-color: rgb(239, 41, 41);
--cmdinput-history-title-color: rgb(114, 159, 207);
--cmdinput-remote-title-color: rgb(6, 152, 154);
--cmdinput-title-color: rgb(114, 159, 207);
--cmdinput-history-item-error-color: rgb(220, 119, 118);
--cmdinput-history-item-selected-error-color: rgb(247, 148, 148);
--cmdinput-remote-field-control-color: rgb(0, 0, 0);
--cmdinput-warning-color: rgb(255, 165, 0);
--cmdinput-button-bg-color: rgb(88, 193, 66);
--cmdinput-comment-button-bg-color: rgb(57, 113, 255);

View File

@ -5,9 +5,10 @@
position: absolute;
bottom: 0;
width: 100%;
padding: var(--termfontsize);
padding: calc(var(--termpad) * 2) calc(var(--termpad) * 2) calc(var(--termpad) * 2) calc(var(--termpad) * 3 - 1px);
z-index: 100;
border-top: 1px solid var(--app-border-color);
background-color: var(--app-bg-color);
&.active {
}
@ -60,6 +61,10 @@
flex-grow: 1;
}
.base-cmdinput:not(:first-child) {
margin-top: var(--termpad);
}
.cmd-input-context {
color: #fff;
white-space: nowrap;
@ -162,12 +167,12 @@
}
&.inputmode-global .cmd-quick-context .button {
color: var(--app-black);
color: var(--app-bg-color);
background-color: var(--cmdinput-button-bg-color) !important;
}
&.inputmode-comment .cmd-quick-context .button {
color: var(--app-black);
color: var(--app-bg-color);
background-color: var(--cmdinput-comment-button-bg-color) !important;
}
@ -284,8 +289,8 @@
z-index: 102;
top: 5px;
left: 0;
background-color: var(--app-black);
color: var(--cmdinput-history-title-color);
background-color: var(--app-bg-color);
color: var(--cmdinput-title-color);
padding-bottom: 4px;
display: flex;
flex-direction: row;
@ -359,12 +364,35 @@
overflow-y: auto;
margin-bottom: var(--termpad);
.info-title {
position: absolute;
z-index: 102;
top: 5px;
left: 0;
background-color: var(--app-bg-color);
color: var(--cmdinput-title-color);
padding-bottom: 4px;
padding-left: calc(var(--termpad) * 2);
display: flex;
flex-direction: row;
width: 100%;
overflow-x: auto;
border-bottom: 1px solid var(--app-border-color);
}
.info-title + .info-msg,
.info-title + .info-lines,
.info-title + .info-comps,
.info-title + .info-error {
margin-top: 24px;
}
.info-msg {
color: var(--cmdinput-history-title-color);
padding-bottom: 2px;
a {
color: var(--prompt-blue);
color: var(--term-blue);
}
}
@ -394,7 +422,7 @@
}
.metacmd-comp {
color: var(--prompt-bright-green);
color: var(--term-bright-green);
}
}
@ -402,109 +430,5 @@
color: var(--cmdinput-text-error-color);
padding-bottom: 2px;
}
.info-remote-showall {
table.remotes-table {
th {
color: var(--app-text-color);
font-weight: bold;
}
th,
td {
padding: 3px 8px 3px 8px;
}
td {
cursor: pointer;
}
tr:hover td {
background-color: #333;
}
}
}
.info-remote {
color: #d3d7cf;
.info-remote-title {
font-weight: bold;
color: var(--cmdinput-remote-title-color);
}
.info-error,
.info-msg {
margin-top: 5px;
padding: 5px;
}
.remote-field {
display: flex;
flex-direction: row;
.remote-field-def {
white-space: pre;
width: 120px;
}
.remote-field-val {
white-space: pre;
display: flex;
flex-direction: row;
}
}
.remote-input-field {
display: flex;
flex-direction: row;
height: 25px;
align-items: center;
.remote-field-label {
white-space: pre;
width: 140px;
font-weight: bold;
color: var(--app-text-primary-color);
}
.undo-icon {
margin-left: 4px;
cursor: pointer;
padding: 2px;
}
.remote-field-control {
&.text-input {
input[type="text"],
input[type="number"],
input[type="password"] {
background-color: var(--app-black);
color: var(--app-text-color);
width: 200px;
}
}
&.checkbox-input {
input[type="checkbox"] {
position: relative;
top: 3px;
}
}
&.select-input {
select {
width: 200px;
background-color: var(--app-black);
color: var(--app-text-color);
}
}
}
}
}
.info-remote-showall {
color: #d3d7cf;
}
}
}

View File

@ -15,7 +15,6 @@ import { TextAreaInput } from "./textareainput";
import { InfoMsg } from "./infomsg";
import { HistoryInfo } from "./historyinfo";
import { Prompt } from "@/common/prompt/prompt";
import { ReactComponent as ExecIcon } from "@/assets/icons/exec.svg";
import { RotateIcon } from "@/common/icons/icons";
import { AIChat } from "./aichat";
@ -182,38 +181,40 @@ class CmdInput extends React.Component<{}, {}> {
</div>
</div>
</If>
<div key="prompt" className="cmd-input-context">
<div className="has-text-white">
<span ref={this.promptRef}>
<Prompt rptr={rptr} festate={feState} />
</span>
</div>
<If condition={numRunningLines > 0}>
<div onClick={() => this.toggleFilter(screen)} className="cmd-input-filter">
{numRunningLines}
<div className="avatar">
<RotateIcon className="warning spin" />
<div key="base-cmdinput" className="base-cmdinput">
<div key="prompt" className="cmd-input-context">
<div className="has-text-white">
<span ref={this.promptRef}>
<Prompt rptr={rptr} festate={feState} color={true} />
</span>
</div>
<If condition={numRunningLines > 0}>
<div onClick={() => this.toggleFilter(screen)} className="cmd-input-filter">
{numRunningLines}
<div className="avatar">
<RotateIcon className="warning spin" />
</div>
</div>
</div>
</If>
</div>
<div
key="input"
className={cn(
"cmd-input-field field has-addons",
inputMode != null ? "inputmode-" + inputMode : null
)}
>
<If condition={inputMode != null}>
<div className="control cmd-quick-context">
<div className="button is-static">{inputMode}</div>
</div>
</If>
<TextAreaInput
key={textAreaInputKey}
screen={screen}
onHeightChange={this.handleInnerHeightUpdate}
/>
</If>
</div>
<div
key="input"
className={cn(
"cmd-input-field field has-addons",
inputMode != null ? "inputmode-" + inputMode : null
)}
>
<If condition={inputMode != null}>
<div className="control cmd-quick-context">
<div className="button is-static">{inputMode}</div>
</div>
</If>
<TextAreaInput
key={textAreaInputKey}
screen={screen}
onHeightChange={this.handleInnerHeightUpdate}
/>
</div>
</div>
</div>
);

View File

@ -53,6 +53,9 @@ class InfoMsg extends React.Component<{}, {}> {
titleStr = infoMsg.infotitle;
}
let activeScreen = model.getActiveScreen();
if (!infoShow) {
return null;
}
return (
<div className="cmd-input-info" style={{ display: infoShow ? "block" : "none" }}>
<If condition={infoMsg?.infotitle}>
@ -68,14 +71,6 @@ class InfoMsg extends React.Component<{}, {}> {
<If condition={!infoMsg.infomsghtml}>{infoMsg.infomsg}</If>
</div>
</If>
<If condition={infoMsg?.websharelink && activeScreen != null}>
<div key="infomsg" className="info-msg">
started sharing screen at{" "}
<a target="_blank" href={makeExternLink(activeScreen.getWebShareUrl())} rel={"noopener"}>
[link]
</a>
</div>
</If>
<If condition={infoMsg?.infolines}>
<div key="infolines" className="info-lines">
<For index="idx" each="line" of={infoMsg.infolines}>

View File

@ -64,10 +64,6 @@ class ScreenTab extends React.Component<
<i title="archived" className="fa-sharp fa-solid fa-box-archive" />
) : null;
let webShared = screen.isWebShared() ? (
<i title="shared to web" className="fa-sharp fa-solid fa-share-nodes web-share-icon" />
) : null;
const statusIndicatorLevel = screen.statusIndicator.get();
const runningCommands = screen.numRunningCmds.get() > 0;
@ -94,7 +90,6 @@ class ScreenTab extends React.Component<
</CenteredIcon>
<div className="tab-name truncate">
{archived}
{webShared}
{screen.name.get()}
</div>
<div className="end-icons">

View File

@ -6,7 +6,7 @@
font-weight: normal;
.openai-role {
color: var(--prompt-bright-green);
color: var(--term-bright-green);
font-weight: bold;
width: 100px;
flex-shrink: 0;