fix(ui): remove left sidebar and back/forward nav when no project
parent
e718db624f
commit
eb0a67695e
|
|
@ -58,6 +58,7 @@ export function Titlebar() {
|
||||||
})
|
})
|
||||||
|
|
||||||
const path = () => `${location.pathname}${location.search}${location.hash}`
|
const path = () => `${location.pathname}${location.search}${location.hash}`
|
||||||
|
const home = createMemo(() => !params.dir)
|
||||||
const creating = createMemo(() => {
|
const creating = createMemo(() => {
|
||||||
if (!params.dir) return false
|
if (!params.dir) return false
|
||||||
if (params.id) return false
|
if (params.id) return false
|
||||||
|
|
@ -175,113 +176,119 @@ export function Titlebar() {
|
||||||
>
|
>
|
||||||
<Show when={mac()}>
|
<Show when={mac()}>
|
||||||
<div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} />
|
<div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} />
|
||||||
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
|
<Show when={!home()}>
|
||||||
<IconButton
|
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
|
||||||
icon="menu"
|
<IconButton
|
||||||
variant="ghost"
|
icon="menu"
|
||||||
class="titlebar-icon rounded-md"
|
variant="ghost"
|
||||||
onClick={layout.mobileSidebar.toggle}
|
class="titlebar-icon rounded-md"
|
||||||
aria-label={language.t("sidebar.menu.toggle")}
|
onClick={layout.mobileSidebar.toggle}
|
||||||
aria-expanded={layout.mobileSidebar.opened()}
|
aria-label={language.t("sidebar.menu.toggle")}
|
||||||
/>
|
aria-expanded={layout.mobileSidebar.opened()}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={!mac()}>
|
<Show when={!mac()}>
|
||||||
<div class="xl:hidden w-[48px] shrink-0 flex items-center justify-center">
|
<Show when={!home()}>
|
||||||
<IconButton
|
<div class="xl:hidden w-[48px] shrink-0 flex items-center justify-center">
|
||||||
icon="menu"
|
<IconButton
|
||||||
variant="ghost"
|
icon="menu"
|
||||||
class="titlebar-icon rounded-md"
|
variant="ghost"
|
||||||
onClick={layout.mobileSidebar.toggle}
|
class="titlebar-icon rounded-md"
|
||||||
aria-label={language.t("sidebar.menu.toggle")}
|
onClick={layout.mobileSidebar.toggle}
|
||||||
aria-expanded={layout.mobileSidebar.opened()}
|
aria-label={language.t("sidebar.menu.toggle")}
|
||||||
/>
|
aria-expanded={layout.mobileSidebar.opened()}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="flex items-center gap-1 shrink-0">
|
<div class="flex items-center gap-1 shrink-0">
|
||||||
<TooltipKeybind
|
<Show when={!home()}>
|
||||||
class={web() ? "hidden xl:flex shrink-0 ml-14" : "hidden xl:flex shrink-0 ml-2"}
|
<TooltipKeybind
|
||||||
placement="bottom"
|
class={web() ? "hidden xl:flex shrink-0 ml-14" : "hidden xl:flex shrink-0 ml-2"}
|
||||||
title={language.t("command.sidebar.toggle")}
|
placement="bottom"
|
||||||
keybind={command.keybind("sidebar.toggle")}
|
title={language.t("command.sidebar.toggle")}
|
||||||
>
|
keybind={command.keybind("sidebar.toggle")}
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
class="group/sidebar-toggle titlebar-icon w-8 h-6 p-0 box-border"
|
|
||||||
onClick={layout.sidebar.toggle}
|
|
||||||
aria-label={language.t("command.sidebar.toggle")}
|
|
||||||
aria-expanded={layout.sidebar.opened()}
|
|
||||||
>
|
>
|
||||||
<Icon size="small" name={layout.sidebar.opened() ? "sidebar-active" : "sidebar"} />
|
<Button
|
||||||
</Button>
|
variant="ghost"
|
||||||
</TooltipKeybind>
|
class="group/sidebar-toggle titlebar-icon w-8 h-6 p-0 box-border"
|
||||||
<div class="hidden xl:flex items-center shrink-0">
|
onClick={layout.sidebar.toggle}
|
||||||
<Show when={params.dir}>
|
aria-label={language.t("command.sidebar.toggle")}
|
||||||
<div
|
aria-expanded={layout.sidebar.opened()}
|
||||||
class="flex items-center shrink-0 w-8 mr-1"
|
|
||||||
aria-hidden={layout.sidebar.opened() ? "true" : undefined}
|
|
||||||
>
|
>
|
||||||
|
<Icon size="small" name={layout.sidebar.opened() ? "sidebar-active" : "sidebar"} />
|
||||||
|
</Button>
|
||||||
|
</TooltipKeybind>
|
||||||
|
<div class="hidden xl:flex items-center shrink-0">
|
||||||
|
<Show when={params.dir}>
|
||||||
<div
|
<div
|
||||||
class="transition-opacity"
|
class="flex items-center shrink-0 w-8 mr-1"
|
||||||
classList={{
|
aria-hidden={layout.sidebar.opened() ? "true" : undefined}
|
||||||
"opacity-100 duration-120 ease-out": !layout.sidebar.opened(),
|
|
||||||
"opacity-0 duration-120 ease-in delay-0 pointer-events-none": layout.sidebar.opened(),
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<TooltipKeybind
|
<div
|
||||||
placement="bottom"
|
class="transition-opacity"
|
||||||
title={language.t("command.session.new")}
|
classList={{
|
||||||
keybind={command.keybind("session.new")}
|
"opacity-100 duration-120 ease-out": !layout.sidebar.opened(),
|
||||||
openDelay={2000}
|
"opacity-0 duration-120 ease-in delay-0 pointer-events-none": layout.sidebar.opened(),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<TooltipKeybind
|
||||||
variant="ghost"
|
placement="bottom"
|
||||||
icon={creating() ? "new-session-active" : "new-session"}
|
title={language.t("command.session.new")}
|
||||||
class="titlebar-icon w-8 h-6 p-0 box-border"
|
keybind={command.keybind("session.new")}
|
||||||
disabled={layout.sidebar.opened()}
|
openDelay={2000}
|
||||||
tabIndex={layout.sidebar.opened() ? -1 : undefined}
|
>
|
||||||
onClick={() => {
|
<Button
|
||||||
if (!params.dir) return
|
variant="ghost"
|
||||||
navigate(`/${params.dir}/session`)
|
icon={creating() ? "new-session-active" : "new-session"}
|
||||||
}}
|
class="titlebar-icon w-8 h-6 p-0 box-border"
|
||||||
aria-label={language.t("command.session.new")}
|
disabled={layout.sidebar.opened()}
|
||||||
aria-current={creating() ? "page" : undefined}
|
tabIndex={layout.sidebar.opened() ? -1 : undefined}
|
||||||
/>
|
onClick={() => {
|
||||||
</TooltipKeybind>
|
if (!params.dir) return
|
||||||
|
navigate(`/${params.dir}/session`)
|
||||||
|
}}
|
||||||
|
aria-label={language.t("command.session.new")}
|
||||||
|
aria-current={creating() ? "page" : undefined}
|
||||||
|
/>
|
||||||
|
</TooltipKeybind>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Show>
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-0 transition-transform"
|
||||||
|
classList={{
|
||||||
|
"translate-x-0": !layout.sidebar.opened(),
|
||||||
|
"-translate-x-[36px]": layout.sidebar.opened(),
|
||||||
|
"duration-180 ease-out": !layout.sidebar.opened(),
|
||||||
|
"duration-180 ease-in": layout.sidebar.opened(),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip placement="bottom" value={language.t("common.goBack")} openDelay={2000}>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
icon="chevron-left"
|
||||||
|
class="titlebar-icon w-6 h-6 p-0 box-border"
|
||||||
|
disabled={!canBack()}
|
||||||
|
onClick={back}
|
||||||
|
aria-label={language.t("common.goBack")}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip placement="bottom" value={language.t("common.goForward")} openDelay={2000}>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
icon="chevron-right"
|
||||||
|
class="titlebar-icon w-6 h-6 p-0 box-border"
|
||||||
|
disabled={!canForward()}
|
||||||
|
onClick={forward}
|
||||||
|
aria-label={language.t("common.goForward")}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
|
||||||
<div
|
|
||||||
class="flex items-center gap-0 transition-transform"
|
|
||||||
classList={{
|
|
||||||
"translate-x-0": !layout.sidebar.opened(),
|
|
||||||
"-translate-x-[36px]": layout.sidebar.opened(),
|
|
||||||
"duration-180 ease-out": !layout.sidebar.opened(),
|
|
||||||
"duration-180 ease-in": layout.sidebar.opened(),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Tooltip placement="bottom" value={language.t("common.goBack")} openDelay={2000}>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
icon="chevron-left"
|
|
||||||
class="titlebar-icon w-6 h-6 p-0 box-border"
|
|
||||||
disabled={!canBack()}
|
|
||||||
onClick={back}
|
|
||||||
aria-label={language.t("common.goBack")}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip placement="bottom" value={language.t("common.goForward")} openDelay={2000}>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
icon="chevron-right"
|
|
||||||
class="titlebar-icon w-6 h-6 p-0 box-border"
|
|
||||||
disabled={!canForward()}
|
|
||||||
onClick={forward}
|
|
||||||
aria-label={language.t("common.goForward")}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<div id="opencode-titlebar-left" class="flex items-center gap-3 min-w-0 px-2" />
|
<div id="opencode-titlebar-left" class="flex items-center gap-3 min-w-0 px-2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ export default function Layout(props: ParentProps) {
|
||||||
let scrollContainerRef: HTMLDivElement | undefined
|
let scrollContainerRef: HTMLDivElement | undefined
|
||||||
|
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
|
const home = createMemo(() => !params.dir)
|
||||||
const globalSDK = useGlobalSDK()
|
const globalSDK = useGlobalSDK()
|
||||||
const globalSync = useGlobalSync()
|
const globalSync = useGlobalSync()
|
||||||
const layout = useLayout()
|
const layout = useLayout()
|
||||||
|
|
@ -2241,7 +2242,7 @@ export default function Layout(props: ParentProps) {
|
||||||
const sidebarContent = (mobile?: boolean) => (
|
const sidebarContent = (mobile?: boolean) => (
|
||||||
<SidebarContent
|
<SidebarContent
|
||||||
mobile={mobile}
|
mobile={mobile}
|
||||||
opened={() => layout.sidebar.opened()}
|
opened={() => (home() ? false : layout.sidebar.opened())}
|
||||||
aimMove={aim.move}
|
aimMove={aim.move}
|
||||||
projects={projects}
|
projects={projects}
|
||||||
renderProject={(project) => (
|
renderProject={(project) => (
|
||||||
|
|
@ -2285,7 +2286,7 @@ export default function Layout(props: ParentProps) {
|
||||||
"absolute inset-y-0 left-0": true,
|
"absolute inset-y-0 left-0": true,
|
||||||
"z-10": true,
|
"z-10": true,
|
||||||
}}
|
}}
|
||||||
style={{ width: `${Math.max(layout.sidebar.width(), 244)}px` }}
|
style={{ width: home() ? "4rem" : `${Math.max(layout.sidebar.width(), 244)}px` }}
|
||||||
ref={(el) => {
|
ref={(el) => {
|
||||||
setState("nav", el)
|
setState("nav", el)
|
||||||
}}
|
}}
|
||||||
|
|
@ -2294,13 +2295,14 @@ export default function Layout(props: ParentProps) {
|
||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
aim.reset()
|
aim.reset()
|
||||||
|
if (home()) return
|
||||||
if (!sidebarHovering()) return
|
if (!sidebarHovering()) return
|
||||||
|
|
||||||
arm()
|
arm()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="@container w-full h-full contain-strict">{sidebarContent()}</div>
|
<div class="@container w-full h-full contain-strict">{sidebarContent()}</div>
|
||||||
<Show when={layout.sidebar.opened()}>
|
<Show when={!home() && layout.sidebar.opened()}>
|
||||||
<div onPointerDown={() => setState("sizing", true)}>
|
<div onPointerDown={() => setState("sizing", true)}>
|
||||||
<ResizeHandle
|
<ResizeHandle
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
|
|
@ -2325,46 +2327,54 @@ export default function Layout(props: ParentProps) {
|
||||||
style={{ left: "calc(4rem + 12px)" }}
|
style={{ left: "calc(4rem + 12px)" }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="xl:hidden">
|
<Show when={!home()}>
|
||||||
<div
|
<div class="xl:hidden">
|
||||||
classList={{
|
<div
|
||||||
"fixed inset-x-0 top-10 bottom-0 z-40 transition-opacity duration-200": true,
|
classList={{
|
||||||
"opacity-100 pointer-events-auto": layout.mobileSidebar.opened(),
|
"fixed inset-x-0 top-10 bottom-0 z-40 transition-opacity duration-200": true,
|
||||||
"opacity-0 pointer-events-none": !layout.mobileSidebar.opened(),
|
"opacity-100 pointer-events-auto": layout.mobileSidebar.opened(),
|
||||||
}}
|
"opacity-0 pointer-events-none": !layout.mobileSidebar.opened(),
|
||||||
onClick={(e) => {
|
}}
|
||||||
if (e.target === e.currentTarget) layout.mobileSidebar.hide()
|
onClick={(e) => {
|
||||||
}}
|
if (e.target === e.currentTarget) layout.mobileSidebar.hide()
|
||||||
/>
|
}}
|
||||||
<nav
|
/>
|
||||||
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
<nav
|
||||||
data-component="sidebar-nav-mobile"
|
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
||||||
classList={{
|
data-component="sidebar-nav-mobile"
|
||||||
"@container fixed top-10 bottom-0 left-0 z-50 w-full max-w-[400px] overflow-hidden border-r border-border-weaker-base bg-background-base transition-transform duration-200 ease-out": true,
|
classList={{
|
||||||
"translate-x-0": layout.mobileSidebar.opened(),
|
"@container fixed top-10 bottom-0 left-0 z-50 w-full max-w-[400px] overflow-hidden border-r border-border-weaker-base bg-background-base transition-transform duration-200 ease-out": true,
|
||||||
"-translate-x-full": !layout.mobileSidebar.opened(),
|
"translate-x-0": layout.mobileSidebar.opened(),
|
||||||
}}
|
"-translate-x-full": !layout.mobileSidebar.opened(),
|
||||||
onClick={(e) => e.stopPropagation()}
|
}}
|
||||||
>
|
onClick={(e) => e.stopPropagation()}
|
||||||
{sidebarContent(true)}
|
>
|
||||||
</nav>
|
{sidebarContent(true)}
|
||||||
</div>
|
</nav>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
classList={{
|
classList={{
|
||||||
"absolute inset-0": true,
|
"absolute inset-0": true,
|
||||||
"xl:inset-y-0 xl:right-0 xl:left-[var(--main-left)]": true,
|
"xl:inset-y-0 xl:right-0": true,
|
||||||
|
"xl:left-[var(--main-left)]": true,
|
||||||
"z-20": true,
|
"z-20": true,
|
||||||
"transition-[left] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[left] motion-reduce:transition-none":
|
"transition-[left] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[left] motion-reduce:transition-none":
|
||||||
!state.sizing,
|
!state.sizing,
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
"--main-left": layout.sidebar.opened() ? `${Math.max(layout.sidebar.width(), 244)}px` : "4rem",
|
"--main-left": home()
|
||||||
|
? "4rem"
|
||||||
|
: layout.sidebar.opened()
|
||||||
|
? `${Math.max(layout.sidebar.width(), 244)}px`
|
||||||
|
: "4rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<main
|
<main
|
||||||
classList={{
|
classList={{
|
||||||
"size-full overflow-x-hidden flex flex-col items-start contain-strict border-t border-border-weak-base bg-background-base xl:border-l xl:rounded-tl-[12px]": true,
|
"size-full overflow-x-hidden flex flex-col items-start contain-strict border-t border-border-weak-base bg-background-base": true,
|
||||||
|
"xl:border-l xl:rounded-tl-[12px]": true,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={!autoselecting()} fallback={<div class="size-full" />}>
|
<Show when={!autoselecting()} fallback={<div class="size-full" />}>
|
||||||
|
|
@ -2373,43 +2383,47 @@ export default function Layout(props: ParentProps) {
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<Show when={!home()}>
|
||||||
classList={{
|
<div
|
||||||
"hidden xl:flex absolute inset-y-0 left-16 z-30": true,
|
classList={{
|
||||||
"opacity-100 translate-x-0 pointer-events-auto": state.peeked && !layout.sidebar.opened(),
|
"hidden xl:flex absolute inset-y-0 left-16 z-30": true,
|
||||||
"opacity-0 -translate-x-2 pointer-events-none": !state.peeked || layout.sidebar.opened(),
|
"opacity-100 translate-x-0 pointer-events-auto": state.peeked && !layout.sidebar.opened(),
|
||||||
"transition-[opacity,transform] motion-reduce:transition-none": true,
|
"opacity-0 -translate-x-2 pointer-events-none": !state.peeked || layout.sidebar.opened(),
|
||||||
"duration-180 ease-out": state.peeked && !layout.sidebar.opened(),
|
"transition-[opacity,transform] motion-reduce:transition-none": true,
|
||||||
"duration-120 ease-in": !state.peeked || layout.sidebar.opened(),
|
"duration-180 ease-out": state.peeked && !layout.sidebar.opened(),
|
||||||
}}
|
"duration-120 ease-in": !state.peeked || layout.sidebar.opened(),
|
||||||
onMouseMove={disarm}
|
}}
|
||||||
onMouseEnter={() => {
|
onMouseMove={disarm}
|
||||||
disarm()
|
onMouseEnter={() => {
|
||||||
aim.reset()
|
disarm()
|
||||||
}}
|
aim.reset()
|
||||||
onPointerDown={disarm}
|
}}
|
||||||
onMouseLeave={() => {
|
onPointerDown={disarm}
|
||||||
arm()
|
onMouseLeave={() => {
|
||||||
}}
|
arm()
|
||||||
>
|
}}
|
||||||
<Show when={peekProject()}>
|
>
|
||||||
<SidebarPanel project={peekProject} merged={false} />
|
<Show when={peekProject()}>
|
||||||
</Show>
|
<SidebarPanel project={peekProject} merged={false} />
|
||||||
</div>
|
</Show>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<div
|
<Show when={!home()}>
|
||||||
classList={{
|
<div
|
||||||
"hidden xl:block pointer-events-none absolute inset-y-0 right-0 z-25 overflow-hidden": true,
|
classList={{
|
||||||
"opacity-100 translate-x-0": state.peeked && !layout.sidebar.opened(),
|
"hidden xl:block pointer-events-none absolute inset-y-0 right-0 z-25 overflow-hidden": true,
|
||||||
"opacity-0 -translate-x-2": !state.peeked || layout.sidebar.opened(),
|
"opacity-100 translate-x-0": state.peeked && !layout.sidebar.opened(),
|
||||||
"transition-[opacity,transform] motion-reduce:transition-none": true,
|
"opacity-0 -translate-x-2": !state.peeked || layout.sidebar.opened(),
|
||||||
"duration-180 ease-out": state.peeked && !layout.sidebar.opened(),
|
"transition-[opacity,transform] motion-reduce:transition-none": true,
|
||||||
"duration-120 ease-in": !state.peeked || layout.sidebar.opened(),
|
"duration-180 ease-out": state.peeked && !layout.sidebar.opened(),
|
||||||
}}
|
"duration-120 ease-in": !state.peeked || layout.sidebar.opened(),
|
||||||
style={{ left: `calc(4rem + ${Math.max(Math.max(layout.sidebar.width(), 244) - 64, 0)}px)` }}
|
}}
|
||||||
>
|
style={{ left: `calc(4rem + ${Math.max(Math.max(layout.sidebar.width(), 244) - 64, 0)}px)` }}
|
||||||
<div class="h-full w-px" style={{ "box-shadow": "var(--shadow-sidebar-overlay)" }} />
|
>
|
||||||
</div>
|
<div class="h-full w-px" style={{ "box-shadow": "var(--shadow-sidebar-overlay)" }} />
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{import.meta.env.DEV && <DebugBar />}
|
{import.meta.env.DEV && <DebugBar />}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue