Add right click menu to logo

This commit is contained in:
David Hill
2025-10-30 00:40:24 +00:00
parent 5ae00ba567
commit e265efec09
2 changed files with 101 additions and 32 deletions

View 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;
}

View File

@@ -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>