diff --git a/src/renderer/components/layout/top-bar/top-bar.tsx b/src/renderer/components/layout/top-bar/top-bar.tsx
index 69397ccf18..adc5457747 100644
--- a/src/renderer/components/layout/top-bar/top-bar.tsx
+++ b/src/renderer/components/layout/top-bar/top-bar.tsx
@@ -11,7 +11,7 @@ import { Icon } from "../../icon";
import { observable } from "mobx";
import { ipcRendererOn } from "../../../../common/ipc";
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 { withInjectables } from "@ogre-tools/injectable-react";
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 catalogRouteInjectable from "../../../../common/front-end-routing/routes/catalog/catalog-route.injectable";
import routeIsActiveInjectable from "../../../routes/route-is-active.injectable";
+import { UpdateButton } from "../../update-button";
interface Dependencies {
navigateToCatalog: NavigateToCatalog;
@@ -129,6 +130,7 @@ const NonInjectedTopBar = observer(({
onClick={goForward}
disabled={!nextEnabled.get()}
/>
+
{renderRegisteredItems(items.get())}
diff --git a/src/renderer/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap b/src/renderer/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap
new file mode 100644
index 0000000000..3492065df4
--- /dev/null
+++ b/src/renderer/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` should render if warning level prop passed 1`] = `
+
+`;
diff --git a/src/renderer/components/update-button/__tests__/update-button.test.tsx b/src/renderer/components/update-button/__tests__/update-button.test.tsx
new file mode 100644
index 0000000000..ff52035a48
--- /dev/null
+++ b/src/renderer/components/update-button/__tests__/update-button.test.tsx
@@ -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("", () => {
+ beforeEach(() => {
+ update.mockClear();
+ });
+
+ it("should not render if no warning level prop passed", () => {
+ const { queryByTestId } = render();
+
+ expect(queryByTestId("update-button")).not.toBeInTheDocument();
+ });
+
+ it("should render if warning level prop passed", () => {
+ const { getByTestId } = render();
+
+ expect(getByTestId("update-button")).toMatchSnapshot();
+ });
+
+ it("should open menu when clicked", async () => {
+ const { getByTestId } = render();
+
+ 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();
+
+ 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();
+
+ const button = getByTestId("update-button");
+
+ expect(button.dataset.warningLevel).toBe("light");
+ });
+
+ it("should have medium warning level", () => {
+ const { getByTestId } = render();
+
+ const button = getByTestId("update-button");
+
+ expect(button.dataset.warningLevel).toBe("medium");
+ });
+
+ it("should have high warning level", () => {
+ const { getByTestId } = render();
+
+ const button = getByTestId("update-button");
+
+ expect(button.dataset.warningLevel).toBe("high");
+ });
+});
diff --git a/src/renderer/components/update-button/index.ts b/src/renderer/components/update-button/index.ts
new file mode 100644
index 0000000000..006a7f0d81
--- /dev/null
+++ b/src/renderer/components/update-button/index.ts
@@ -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";
diff --git a/src/renderer/components/update-button/styles.module.scss b/src/renderer/components/update-button/styles.module.scss
new file mode 100644
index 0000000000..ad4d39a7dd
--- /dev/null
+++ b/src/renderer/components/update-button/styles.module.scss
@@ -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);
+}
diff --git a/src/renderer/components/update-button/update-button.tsx b/src/renderer/components/update-button/update-button.tsx
new file mode 100644
index 0000000000..6da453de3d
--- /dev/null
+++ b/src/renderer/components/update-button/update-button.tsx
@@ -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 {
+ 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 (
+ <>
+
+
+ >
+ );
+}