Add overlay scrollbar for main sidebar, adjust active session display behavior (#505)

* Add overlay scrollbar to left sidebar

* Keep active session bolded when mainview is not session

* fix color of scrollbar

* swap expression args

* add active color for scrollbar

* add active/highlight to history, connections, and settings
This commit is contained in:
Evan Simkowitz 2024-03-27 12:47:57 -07:00 committed by GitHub
parent 3e4ba1bf72
commit e867bcb398
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 56 additions and 19 deletions

View File

@ -36,6 +36,8 @@
"monaco-editor": "^0.44.0",
"mustache": "^4.2.0",
"node-fetch": "^3.2.10",
"overlayscrollbars": "^2.6.1",
"overlayscrollbars-react": "^0.5.5",
"papaparse": "^5.4.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",

View File

@ -67,6 +67,7 @@
--scrollbar-background-color: var(--app-bg-color);
--scrollbar-thumb-color: rgba(255, 255, 255, 0.3);
--scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.5);
--scrollbar-thumb-active-color: rgba(255, 255, 255, 0.6);
/* code color */
--pre-bg-color: rgb(0, 0, 0);
@ -112,7 +113,7 @@
--hotkey-text-color: var(--app-text-secondary-color);
/* sidebar colors */
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
--sidebar-highlight-color: var(--app-accent-bg-color);
--sidebar-font-size: 15px;
--sidebar-line-height: 1.5;
--sidebar-font-weight: normal;
@ -186,4 +187,11 @@
--datepicker-header-fade-color: rgba(255, 255, 255, 0.4);
--datepicker-year-header-bg-color: rgba(255, 255, 255, 0.2); /* Light grey background */
--datepicker-year-header-border-color: rgba(241, 246, 243, 0.15); /* Light grey border */
/* OverlayScrollbars styling */
.os-scrollbar {
--os-handle-bg: var(--scrollbar-thumb-color);
--os-handle-bg-hover: var(--scrollbar-thumb-hover-color);
--os-handle-bg-active: var(--scrollbar-thumb-active-color);
}
}

View File

@ -61,6 +61,7 @@
--scrollbar-background-color: var(--app-bg-color);
--scrollbar-thumb-color: rgba(0, 0, 0, 0.2);
--scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.4);
--scrollbar-thumb-active-color: rgba(0, 0, 0, 0.5);
/* line color */
--line-actions-bg-color: rgba(0, 0, 0, 0.1);

View File

@ -101,7 +101,7 @@ class App extends React.Component<{}, {}> {
return (
<div id="main" className={"platform-" + platform} onContextMenu={this.handleContextMenu}>
<div ref={this.mainContentRef} className="main-content">
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
<MainSideBar parentRef={this.mainContentRef} />
<div className="session-view" />
</div>
<If condition={dcWait}>
@ -151,7 +151,7 @@ class App extends React.Component<{}, {}> {
</div>
</If>
<div ref={this.mainContentRef} className="main-content">
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
<MainSideBar parentRef={this.mainContentRef} />
<ErrorBoundary>
<PluginsView />
<WorkspaceView />
@ -160,7 +160,7 @@ class App extends React.Component<{}, {}> {
<ConnectionsView model={remotesModel} />
<ClientSettingsView model={remotesModel} />
</ErrorBoundary>
<RightSideBar parentRef={this.mainContentRef} clientData={clientData} />
<RightSideBar parentRef={this.mainContentRef} />
</div>
<ModalsProvider />
</div>

View File

@ -60,15 +60,15 @@
margin-bottom: -4px;
}
.top {
padding-right: 6px;
}
.middle {
padding: 4px 6px 8px 6px;
border-bottom: 1px solid var(--app-border-color);
overflow-y: auto;
.item {
&.active {
background-color: var(--sidebar-highlight-color);
font-weight: var(--sidebar-highlight-font-weight);
}
.index {
font-size: 10px;
}
@ -87,6 +87,7 @@
left: 0;
width: 100%;
padding-top: 0.8rem;
padding-right: 6px;
}
.item {
@ -94,9 +95,6 @@
margin-left: 6px;
border-radius: 4px;
opacity: 1;
width: inherit;
max-width: inherit;
min-width: inherit;
display: flex;
flex-direction: row;
align-items: center;
@ -111,6 +109,13 @@
line-height: normal;
}
&.active {
font-weight: var(--sidebar-highlight-font-weight);
}
&.highlight {
background-color: var(--sidebar-highlight-color);
}
.item-contents {
flex-grow: 1;
}

View File

@ -8,7 +8,6 @@ import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import dayjs from "dayjs";
import { If } from "tsx-control-statements/components";
import { compareLoose } from "semver";
import { ReactComponent as AppsIcon } from "@/assets/icons/apps.svg";
import { ReactComponent as WorkspacesIcon } from "@/assets/icons/workspaces.svg";
@ -24,6 +23,9 @@ import * as appconst from "@/app/appconst";
import "./main.less";
import { ActionsIcon, CenteredIcon, FrontIcon, StatusIndicator } from "@/common/icons/icons";
import "overlayscrollbars/overlayscrollbars.css";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
dayjs.extend(localizedFormat);
class SideBarItem extends React.Component<{
@ -59,7 +61,6 @@ class HotKeyIcon extends React.Component<{ hotkey: string }> {
interface MainSideBarProps {
parentRef: React.RefObject<HTMLElement>;
clientData: ClientDataType;
}
@mobxReact.observer
@ -192,14 +193,15 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
}
}
return sessionList.map((session, index) => {
const isActive = GlobalModel.activeMainView.get() == "session" && activeSessionId == session.sessionId;
const isActive = activeSessionId == session.sessionId;
const showHighlight = isActive && GlobalModel.activeMainView.get() == "session";
const sessionScreens = GlobalModel.getSessionScreens(session.sessionId);
const sessionIndicator = Math.max(...sessionScreens.map((screen) => screen.statusIndicator.get()));
const sessionRunningCommands = sessionScreens.some((screen) => screen.numRunningCmds.get() > 0);
return (
<SideBarItem
key={session.sessionId}
className={`${isActive ? "active" : ""}`}
className={cn({ active: isActive, highlight: showHighlight })}
frontIcon={<span className="index">{index + 1}</span>}
contents={session.name.get()}
endIcons={[
@ -240,6 +242,10 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
}
render() {
let mainView = GlobalModel.activeMainView.get();
const historyActive = mainView == "history";
const connectionsActive = mainView == "connections";
const settingsActive = mainView == "clientsettings";
return (
<ResizableSidebar
model={GlobalModel.mainSidebarModel}
@ -263,6 +269,7 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
<SideBarItem
key="history"
frontIcon={<i className="fa-sharp fa-regular fa-clock-rotate-left icon" />}
className={cn({ active: historyActive, highlight: historyActive })}
contents="History"
endIcons={[<HotKeyIcon key="hotkey" hotkey="H" />]}
onClick={this.handleHistoryClick}
@ -271,6 +278,7 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
<SideBarItem
key="connections"
frontIcon={<i className="fa-sharp fa-regular fa-globe icon " />}
className={cn({ active: connectionsActive, highlight: connectionsActive })}
contents="Connections"
onClick={this.handleConnectionsClick}
/>
@ -291,15 +299,18 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
</CenteredIcon>,
]}
/>
<div
className="middle scrollbar-hide-until-hover"
<OverlayScrollbarsComponent
element="div"
className="middle"
id="sidebar-middle"
style={{
maxHeight: `calc(100vh - ${this.middleHeightSubtractor.get()}px)`,
}}
options={{ scrollbars: { autoHide: "leave" } }}
>
{this.getSessions()}
</div>
</OverlayScrollbarsComponent>
<div className="bottom" id="sidebar-bottom">
{this.getUpdateAppBanner()}
<If condition={GlobalModel.isDev}>
@ -314,6 +325,7 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
<SideBarItem
key="settings"
frontIcon={<SettingsIcon className="icon" />}
className={cn({ active: settingsActive, highlight: settingsActive })}
contents="Settings"
onClick={this.handleSettingsClick}
/>

View File

@ -15,7 +15,6 @@ dayjs.extend(localizedFormat);
interface RightSideBarProps {
parentRef: React.RefObject<HTMLElement>;
clientData: ClientDataType;
}
@mobxReact.observer

View File

@ -6311,6 +6311,16 @@ opener@^1.5.1, opener@^1.5.2:
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
overlayscrollbars-react@^0.5.5:
version "0.5.5"
resolved "https://registry.yarnpkg.com/overlayscrollbars-react/-/overlayscrollbars-react-0.5.5.tgz#983fcff9928cd12fff78351573fdb79f463ea414"
integrity sha512-PakK1QEV/PAi4XniiTykcSeyoBmfDvgv2uBQ290IaY5ThrwvWg3Zk3Z39hosJYkyrS4mJ0zuIWtlHX4AKd2nZQ==
overlayscrollbars@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-2.6.1.tgz#50210de1d869ed0bf027de11cf705f5b9591a097"
integrity sha512-V+ZAqWMYMyGBJNRDEcdRC7Ch+WT9RBx9hY8bfJSMyFObQeJoecs1Vqg7ZAzBVcpN6sCUXFAZldCbeySwmmD0RA==
p-cancelable@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"