diff --git a/src/renderer/bootstrap.tsx b/src/renderer/bootstrap.tsx
index 81f4a52e45..9be509ab61 100644
--- a/src/renderer/bootstrap.tsx
+++ b/src/renderer/bootstrap.tsx
@@ -98,9 +98,6 @@ export async function bootstrap(di: DependencyInjectionContainer) {
logger.info(`${logPrefix} initializing IpcRendererListeners`);
initializers.initIpcRendererListeners(extensionLoader);
- logger.info(`${logPrefix} initializing StatusBarRegistry`);
- initializers.initStatusBarRegistry();
-
extensionLoader.init();
const extensionDiscovery = di.inject(extensionDiscoveryInjectable);
diff --git a/src/renderer/components/cluster-manager/active-hotbar-name.tsx b/src/renderer/components/cluster-manager/active-hotbar-name.tsx
deleted file mode 100644
index 191a30957e..0000000000
--- a/src/renderer/components/cluster-manager/active-hotbar-name.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import React from "react";
-import { observer } from "mobx-react";
-import { Icon } from "../icon";
-import hotbarManagerInjectable from "../../../common/hotbar-store.injectable";
-import { HotbarSwitchCommand } from "../hotbar/hotbar-switch-command";
-import { withInjectables } from "@ogre-tools/injectable-react";
-import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
-
-interface Dependencies {
- openCommandOverlay: (component: React.ReactElement) => void;
- activeHotbarName: () => string | undefined;
-}
-
-const NonInjectedActiveHotbarName = observer(({ openCommandOverlay, activeHotbarName }: Dependencies) => (
-
openCommandOverlay()}
- >
-
- {activeHotbarName()}
-
-));
-
-export const ActiveHotbarName = withInjectables(NonInjectedActiveHotbarName, {
- getProps: (di, props) => ({
- activeHotbarName: () => di.inject(hotbarManagerInjectable).getActive()?.name,
- openCommandOverlay: di.inject(commandOverlayInjectable).open,
- ...props,
- }),
-});
diff --git a/src/renderer/components/cluster-manager/bottom-bar.test.tsx b/src/renderer/components/cluster-manager/bottom-bar.test.tsx
index dcad07d592..97539f0ea3 100644
--- a/src/renderer/components/cluster-manager/bottom-bar.test.tsx
+++ b/src/renderer/components/cluster-manager/bottom-bar.test.tsx
@@ -4,68 +4,24 @@
*/
import React from "react";
-import mockFs from "mock-fs";
-import { fireEvent } from "@testing-library/react";
+import { render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { BottomBar } from "./bottom-bar";
import { StatusBarRegistry } from "../../../extensions/registries";
-import hotbarManagerInjectable from "../../../common/hotbar-store.injectable";
-import { HotbarSwitchCommand } from "../hotbar/hotbar-switch-command";
-import { ActiveHotbarName } from "./active-hotbar-name";
-import { getDiForUnitTesting } from "../../getDiForUnitTesting";
-import { DiRender, renderFor } from "../test-utils/renderFor";
-import type { DependencyInjectionContainer } from "@ogre-tools/injectable";
-import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
-import { getEmptyHotbar } from "../../../common/hotbar-types";
-
jest.mock("electron", () => ({
app: {
- getName: () => "lens",
- setName: jest.fn(),
- setPath: jest.fn(),
- getPath: () => "tmp",
- },
- ipcMain: {
- handle: jest.fn(),
- on: jest.fn(),
- removeAllListeners: jest.fn(),
- off: jest.fn(),
- send: jest.fn(),
+ getPath: () => "/foo",
},
}));
-const foobarHotbar = getEmptyHotbar("foobar");
-
describe("", () => {
- let di: DependencyInjectionContainer;
- let render: DiRender;
-
- beforeEach(async () => {
- const mockOpts = {
- "tmp": {
- "test-store.json": JSON.stringify({}),
- },
- };
-
- di = getDiForUnitTesting({ doGeneralOverrides: true });
-
- mockFs(mockOpts);
-
- render = renderFor(di);
-
- di.override(hotbarManagerInjectable, () => ({
- getActive: () => foobarHotbar,
- } as any));
-
- await di.runSetups();
-
+ beforeEach(() => {
StatusBarRegistry.createInstance();
});
afterEach(() => {
StatusBarRegistry.resetInstance();
- mockFs.restore();
});
it("renders w/o errors", () => {
@@ -111,33 +67,6 @@ describe("", () => {
expect(getByTestId(testId)).toHaveTextContent(text);
});
- it("shows active hotbar name", () => {
- StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [
- { item: () => },
- ]);
- const { getByTestId } = render();
-
- expect(getByTestId("current-hotbar-name")).toHaveTextContent("foobar");
- });
-
- it("opens command palette on click", () => {
- const mockOpen = jest.fn();
-
- di.override(commandOverlayInjectable, () => ({
- open: mockOpen,
- }) as any);
-
- StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [
- { item: () => },
- ]);
- const { getByTestId } = render();
- const activeHotbar = getByTestId("current-hotbar-name");
-
- fireEvent.click(activeHotbar);
-
-
- expect(mockOpen).toHaveBeenCalledWith();
- });
it("sort positioned items properly", () => {
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [
diff --git a/src/renderer/components/hotbar/hotbar-selector.scss b/src/renderer/components/hotbar/hotbar-selector.module.scss
similarity index 85%
rename from src/renderer/components/hotbar/hotbar-selector.scss
rename to src/renderer/components/hotbar/hotbar-selector.module.scss
index 711486ba49..b95823f7fe 100644
--- a/src/renderer/components/hotbar/hotbar-selector.scss
+++ b/src/renderer/components/hotbar/hotbar-selector.module.scss
@@ -4,6 +4,8 @@
*/
.HotbarSelector {
+ display: flex;
+ align-items: center;
height: 26px;
background-color: var(--layoutBackground);
position: relative;
@@ -17,7 +19,13 @@
top: -20px;
}
- .SelectorIndex {
+ .HotbarIndex {
+ display: flex;
+ flex-grow: 1;
+ align-items: center;
+ }
+
+ .Badge {
cursor: pointer;
background: var(--secondaryBackground);
width: 100%;
diff --git a/src/renderer/components/hotbar/hotbar-selector.tsx b/src/renderer/components/hotbar/hotbar-selector.tsx
index 3922108ddc..68a8f0e81b 100644
--- a/src/renderer/components/hotbar/hotbar-selector.tsx
+++ b/src/renderer/components/hotbar/hotbar-selector.tsx
@@ -3,21 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import "./hotbar-selector.scss";
-import React from "react";
+import styles from "./hotbar-selector.module.scss";
+import React, { useRef, useState } from "react";
import { Icon } from "../icon";
import { Badge } from "../badge";
import hotbarManagerInjectable from "../../../common/hotbar-store.injectable";
import { HotbarSwitchCommand } from "./hotbar-switch-command";
-import { TooltipPosition } from "../tooltip";
+import { Tooltip, TooltipPosition } from "../tooltip";
import { observer } from "mobx-react";
import type { Hotbar } from "../../../common/hotbar-types";
import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
-
-export interface HotbarSelectorProps {
- hotbar: Hotbar;
-}
+import { cssNames } from "../../utils";
interface Dependencies {
hotbarManager: {
@@ -29,25 +26,63 @@ interface Dependencies {
openCommandOverlay: (component: React.ReactElement) => void;
}
-const NonInjectedHotbarSelector = observer(({ hotbar, hotbarManager, openCommandOverlay }: HotbarSelectorProps & Dependencies) => (
-
-
hotbarManager.switchToPrevious()} />
-
-
openCommandOverlay()}
- tooltip={{
- preferredPositions: [TooltipPosition.TOP, TooltipPosition.TOP_LEFT],
- children: hotbar.name,
- }}
- className="SelectorIndex"
+export interface HotbarSelectorProps extends Partial {
+ hotbar: Hotbar;
+}
+
+const NonInjectedHotbarSelector = observer(({ hotbar, hotbarManager, openCommandOverlay }: HotbarSelectorProps & Dependencies) => {
+ const [tooltipVisible, setTooltipVisible] = useState(false);
+ const tooltipTimeout = useRef();
+
+ function clearTimer() {
+ clearTimeout(tooltipTimeout.current);
+ }
+
+ function onTooltipShow() {
+ setTooltipVisible(true);
+ clearTimer();
+ tooltipTimeout.current = setTimeout(() => setTooltipVisible(false), 1500);
+ }
+
+ function onArrowClick(switchTo: () => void) {
+ onTooltipShow();
+ switchTo();
+ }
+
+ function onMouseEvent(event: React.MouseEvent) {
+ clearTimer();
+ setTooltipVisible(event.type == "mouseenter");
+ }
+
+ return (
+
+
onArrowClick(hotbarManager.switchToPrevious)}
/>
+
+ openCommandOverlay()}
+ className={styles.Badge}
+ onMouseEnter={onMouseEvent}
+ onMouseLeave={onMouseEvent}
+ />
+
+ {hotbar.name}
+
+
+ onArrowClick(hotbarManager.switchToNext)} />
- hotbarManager.switchToNext()} />
-
-));
+ );
+});
export const HotbarSelector = withInjectables(NonInjectedHotbarSelector, {
getProps: (di, props) => ({
diff --git a/src/renderer/components/tooltip/tooltip.scss b/src/renderer/components/tooltip/tooltip.scss
index 8747cbf2c6..10b7669679 100644
--- a/src/renderer/components/tooltip/tooltip.scss
+++ b/src/renderer/components/tooltip/tooltip.scss
@@ -25,14 +25,15 @@
pointer-events: none;
transition: opacity 150ms 150ms ease-in-out;
z-index: 100000;
- opacity: 1;
box-shadow: 0 8px 16px rgba(0,0,0,0.24);
+ left: 0;
+ top: 0;
+ opacity: 0;
+ visibility: hidden;
- &.invisible {
- left: 0;
- top: 0;
- opacity: 0;
- visibility: hidden;
+ &.visible {
+ opacity: 1;
+ visibility: visible;
}
&:empty {
diff --git a/src/renderer/components/tooltip/tooltip.tsx b/src/renderer/components/tooltip/tooltip.tsx
index cf0811b7a6..3e35c837a5 100644
--- a/src/renderer/components/tooltip/tooltip.tsx
+++ b/src/renderer/components/tooltip/tooltip.tsx
@@ -54,7 +54,7 @@ export class Tooltip extends React.Component {
@observable.ref elem: HTMLElement;
@observable activePosition: TooltipPosition;
- @observable isVisible = !!this.props.visible;
+ @observable isVisible = false;
constructor(props: TooltipProps) {
super(props);
@@ -78,6 +78,10 @@ export class Tooltip extends React.Component {
this.hoverTarget.addEventListener("mouseleave", this.onLeaveTarget);
}
+ componentDidUpdate() {
+ this.refreshPosition();
+ }
+
componentWillUnmount() {
this.hoverTarget.removeEventListener("mouseenter", this.onEnterTarget);
this.hoverTarget.removeEventListener("mouseleave", this.onLeaveTarget);
@@ -210,9 +214,9 @@ export class Tooltip extends React.Component {
}
render() {
- const { style, formatters, usePortal, children } = this.props;
+ const { style, formatters, usePortal, children, visible } = this.props;
const className = cssNames("Tooltip", this.props.className, formatters, this.activePosition, {
- invisible: !this.isVisible,
+ visible: visible ?? this.isVisible,
formatter: !!formatters,
});
const tooltip = (
diff --git a/src/renderer/initializers/index.ts b/src/renderer/initializers/index.ts
index 27fd3bcd6e..3965d45fcf 100644
--- a/src/renderer/initializers/index.ts
+++ b/src/renderer/initializers/index.ts
@@ -12,4 +12,3 @@ export * from "./kube-object-menu-registry";
export * from "./registries";
export * from "./workloads-overview-detail-registry";
export * from "./catalog-category-registry";
-export * from "./status-bar-registry";
diff --git a/src/renderer/initializers/status-bar-registry.tsx b/src/renderer/initializers/status-bar-registry.tsx
deleted file mode 100644
index c0a255a610..0000000000
--- a/src/renderer/initializers/status-bar-registry.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import React from "react";
-import { StatusBarRegistry } from "../../extensions/registries";
-import { ActiveHotbarName } from "../components/cluster-manager/active-hotbar-name";
-
-export function initStatusBarRegistry() {
- StatusBarRegistry.getInstance().add([
- {
- components: {
- Item: () => ,
- position: "left",
- },
- },
- ]);
-}