mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
TopBar Update button (#5376)
* UpdateButton skeleton Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Show UpdateButton in topbar Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Default button styles Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Add update icon to menu item Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Replace colors for medium & high levels Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fine-tune colors for light theme Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fix keyboard events bug Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Hide <UpdateButton> from topbar Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Clean up Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Using dropdown icon instead of sandwich Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Used determenistic id for the button Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Respect id prop Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Add small space Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Using accent color directly from active theme Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Update snapshots Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fix open/close Menu errors Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Linter fix Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fix linter harder Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Clean up tests Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Fix act() wrapper console.error Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Remove aria-expanded attribute Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
54b92aa9b6
commit
c2b4fed5c3
@ -11,7 +11,7 @@ import { Icon } from "../../icon";
|
|||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { ipcRendererOn } from "../../../../common/ipc";
|
import { ipcRendererOn } from "../../../../common/ipc";
|
||||||
import { watchHistoryState } from "../../../remote-helpers/history-updater";
|
import { watchHistoryState } from "../../../remote-helpers/history-updater";
|
||||||
import { cssNames } from "../../../utils";
|
import { cssNames, noop } from "../../../utils";
|
||||||
import topBarItemsInjectable from "./top-bar-items/top-bar-items.injectable";
|
import topBarItemsInjectable from "./top-bar-items/top-bar-items.injectable";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import type { TopBarRegistration } from "./top-bar-registration";
|
import type { TopBarRegistration } from "./top-bar-registration";
|
||||||
@ -23,6 +23,7 @@ import type { NavigateToCatalog } from "../../../../common/front-end-routing/rou
|
|||||||
import navigateToCatalogInjectable from "../../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
|
import navigateToCatalogInjectable from "../../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
|
||||||
import catalogRouteInjectable from "../../../../common/front-end-routing/routes/catalog/catalog-route.injectable";
|
import catalogRouteInjectable from "../../../../common/front-end-routing/routes/catalog/catalog-route.injectable";
|
||||||
import routeIsActiveInjectable from "../../../routes/route-is-active.injectable";
|
import routeIsActiveInjectable from "../../../routes/route-is-active.injectable";
|
||||||
|
import { UpdateButton } from "../../update-button";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
navigateToCatalog: NavigateToCatalog;
|
navigateToCatalog: NavigateToCatalog;
|
||||||
@ -129,6 +130,7 @@ const NonInjectedTopBar = observer(({
|
|||||||
onClick={goForward}
|
onClick={goForward}
|
||||||
disabled={!nextEnabled.get()}
|
disabled={!nextEnabled.get()}
|
||||||
/>
|
/>
|
||||||
|
<UpdateButton update={noop} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.items}>
|
<div className={styles.items}>
|
||||||
{renderRegisteredItems(items.get())}
|
{renderRegisteredItems(items.get())}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<UpdateButton/> should render if warning level prop passed 1`] = `
|
||||||
|
<button
|
||||||
|
class="updateButton"
|
||||||
|
data-testid="update-button"
|
||||||
|
data-warning-level="light"
|
||||||
|
id="update-lens-button"
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
<i
|
||||||
|
class="Icon icon material focusable"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="icon"
|
||||||
|
data-icon-name="arrow_drop_down"
|
||||||
|
>
|
||||||
|
arrow_drop_down
|
||||||
|
</span>
|
||||||
|
</i>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { render, act } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import { UpdateButton } from "../update-button";
|
||||||
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
|
|
||||||
|
const update = jest.fn();
|
||||||
|
|
||||||
|
describe("<UpdateButton/>", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
update.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not render if no warning level prop passed", () => {
|
||||||
|
const { queryByTestId } = render(<UpdateButton update={update} />);
|
||||||
|
|
||||||
|
expect(queryByTestId("update-button")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render if warning level prop passed", () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="light" />);
|
||||||
|
|
||||||
|
expect(getByTestId("update-button")).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should open menu when clicked", async () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="light" />);
|
||||||
|
|
||||||
|
const button = getByTestId("update-button");
|
||||||
|
|
||||||
|
act(() => button.click());
|
||||||
|
|
||||||
|
expect(getByTestId("update-lens-menu-item")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call update function when menu item clicked", () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="light" />);
|
||||||
|
|
||||||
|
const button = getByTestId("update-button");
|
||||||
|
|
||||||
|
act(() => button.click());
|
||||||
|
|
||||||
|
const menuItem = getByTestId("update-lens-menu-item");
|
||||||
|
|
||||||
|
menuItem.click();
|
||||||
|
|
||||||
|
expect(update).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have light warning level", () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="light" />);
|
||||||
|
|
||||||
|
const button = getByTestId("update-button");
|
||||||
|
|
||||||
|
expect(button.dataset.warningLevel).toBe("light");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have medium warning level", () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="medium" />);
|
||||||
|
|
||||||
|
const button = getByTestId("update-button");
|
||||||
|
|
||||||
|
expect(button.dataset.warningLevel).toBe("medium");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have high warning level", () => {
|
||||||
|
const { getByTestId } = render(<UpdateButton update={update} warningLevel="high" />);
|
||||||
|
|
||||||
|
const button = getByTestId("update-button");
|
||||||
|
|
||||||
|
expect(button.dataset.warningLevel).toBe("high");
|
||||||
|
});
|
||||||
|
});
|
||||||
6
src/renderer/components/update-button/index.ts
Normal file
6
src/renderer/components/update-button/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from "./update-button";
|
||||||
52
src/renderer/components/update-button/styles.module.scss
Normal file
52
src/renderer/components/update-button/styles.module.scss
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.updateButton {
|
||||||
|
--accent-color: var(--colorOk);
|
||||||
|
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--accent-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 8px;
|
||||||
|
gap: 6px;
|
||||||
|
cursor: default;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover::before{
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
box-shadow: 0 0 0 2px var(--blue);
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
background: var(--accent-color);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
opacity: 0.15;
|
||||||
|
z-index: -1;
|
||||||
|
transition: opacity 0.1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warningMedium {
|
||||||
|
--accent-color: var(--colorWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.warningHigh {
|
||||||
|
--accent-color: var(--colorSoftError);
|
||||||
|
}
|
||||||
64
src/renderer/components/update-button/update-button.tsx
Normal file
64
src/renderer/components/update-button/update-button.tsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import styles from "./styles.module.scss";
|
||||||
|
|
||||||
|
import type { HTMLAttributes } from "react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Menu, MenuItem } from "../menu";
|
||||||
|
import { cssNames } from "../../utils";
|
||||||
|
import type { IconProps } from "../icon";
|
||||||
|
import { Icon } from "../icon";
|
||||||
|
|
||||||
|
interface UpdateButtonProps extends HTMLAttributes<HTMLButtonElement> {
|
||||||
|
warningLevel?: "light" | "medium" | "high";
|
||||||
|
update: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpdateButton({ warningLevel, update, id }: UpdateButtonProps) {
|
||||||
|
const buttonId = id ?? "update-lens-button";
|
||||||
|
const menuIconProps: IconProps = { material: "update", small: true };
|
||||||
|
const [opened, setOpened] = useState(false);
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
setOpened(!opened);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!warningLevel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
data-testid="update-button"
|
||||||
|
data-warning-level={warningLevel}
|
||||||
|
id={buttonId}
|
||||||
|
className={cssNames(styles.updateButton, {
|
||||||
|
[styles.warningHigh]: warningLevel === "high",
|
||||||
|
[styles.warningMedium]: warningLevel === "medium",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
<Icon material="arrow_drop_down" className={styles.icon}/>
|
||||||
|
</button>
|
||||||
|
<Menu
|
||||||
|
usePortal
|
||||||
|
htmlFor={buttonId}
|
||||||
|
isOpen={opened}
|
||||||
|
close={toggle}
|
||||||
|
open={toggle}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
icon={menuIconProps}
|
||||||
|
onClick={update}
|
||||||
|
data-testid="update-lens-menu-item"
|
||||||
|
>
|
||||||
|
Relaunch to Update Lens
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user