mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 11:14:23 +01:00
Add right click menu to logo
This commit is contained in:
39
packages/console/app/src/component/header-context-menu.css
Normal file
39
packages/console/app/src/component/header-context-menu.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
.context-menu {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
min-width: 160px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: var(--space-1);
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--space-2-5) var(--space-3);
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
transition: background-color 0.15s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-bg-surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-divider {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--color-border);
|
||||||
|
margin: var(--space-1) 0;
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import { A, createAsync } from "@solidjs/router"
|
|||||||
import { createMemo, Match, Show, Switch } from "solid-js"
|
import { createMemo, Match, Show, Switch } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { github } from "~/lib/github"
|
import { github } from "~/lib/github"
|
||||||
|
import { createEffect, onCleanup } from "solid-js"
|
||||||
|
import "./header-context-menu.css"
|
||||||
|
|
||||||
export function Header(props: { zen?: boolean }) {
|
export function Header(props: { zen?: boolean }) {
|
||||||
const githubData = createAsync(() => github())
|
const githubData = createAsync(() => github())
|
||||||
@@ -18,14 +20,68 @@ export function Header(props: { zen?: boolean }) {
|
|||||||
|
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
mobileMenuOpen: false,
|
mobileMenuOpen: false,
|
||||||
|
contextMenuOpen: false,
|
||||||
|
contextMenuPosition: { x: 0, y: 0 },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const handleClickOutside = () => {
|
||||||
|
setStore("contextMenuOpen", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleContextMenu = (event: MouseEvent) => {
|
||||||
|
event.preventDefault()
|
||||||
|
setStore("contextMenuOpen", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store.contextMenuOpen) {
|
||||||
|
document.addEventListener("click", handleClickOutside)
|
||||||
|
document.addEventListener("contextmenu", handleContextMenu)
|
||||||
|
onCleanup(() => {
|
||||||
|
document.removeEventListener("click", handleClickOutside)
|
||||||
|
document.removeEventListener("contextmenu", handleContextMenu)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleLogoContextMenu = (event: MouseEvent) => {
|
||||||
|
event.preventDefault()
|
||||||
|
setStore("contextMenuPosition", { x: event.clientX, y: event.clientY })
|
||||||
|
setStore("contextMenuOpen", true)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section data-component="top">
|
<section data-component="top">
|
||||||
<A href="/">
|
<div onContextMenu={handleLogoContextMenu}>
|
||||||
<img data-slot="logo light" src={logoLight} alt="opencode logo light" />
|
<A href="/">
|
||||||
<img data-slot="logo dark" src={logoDark} alt="opencode logo dark" />
|
<img data-slot="logo light" src={logoLight} alt="opencode logo light" />
|
||||||
</A>
|
<img data-slot="logo dark" src={logoDark} alt="opencode logo dark" />
|
||||||
|
</A>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Show when={store.contextMenuOpen}>
|
||||||
|
<div
|
||||||
|
class="context-menu"
|
||||||
|
style={`left: ${store.contextMenuPosition.x}px; top: ${store.contextMenuPosition.y}px;`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="context-menu-item"
|
||||||
|
onClick={() => window.open("https://github.com/sst/opencode", "_blank")}
|
||||||
|
>
|
||||||
|
Copy logo as SVG
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="context-menu-item"
|
||||||
|
onClick={() => window.open("https://github.com/sst/opencode", "_blank")}
|
||||||
|
>
|
||||||
|
Copy wordmark as SVG
|
||||||
|
</button>
|
||||||
|
<button className="context-menu-item"
|
||||||
|
onClick={() => (window.location.href = "/brand")}>
|
||||||
|
Brand assets
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
<nav data-component="nav-desktop">
|
<nav data-component="nav-desktop">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -34,20 +90,7 @@ export function Header(props: { zen?: boolean }) {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs">Docs</a>
|
<a href="/brand">Brand assets</a>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<A href="/enterprise">Enterprise</A>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.zen}>
|
|
||||||
<a href="/auth">Login</a>
|
|
||||||
</Match>
|
|
||||||
<Match when={!props.zen}>
|
|
||||||
<A href="/zen">Zen</A>
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -108,20 +151,7 @@ export function Header(props: { zen?: boolean }) {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs">Docs</a>
|
<a href="/brand">Brand assets</a>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<A href="/enterprise">Enterprise</A>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.zen}>
|
|
||||||
<a href="/auth">Login</a>
|
|
||||||
</Match>
|
|
||||||
<Match when={!props.zen}>
|
|
||||||
<A href="/zen">Zen</A>
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
Reference in New Issue
Block a user