Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
c39e2fe
feat(app): add Preview tab and Panel Menu to side panel (#162)
jeonghun-jj-lee Aug 11, 2026
4a23c67
feat: add /file/write endpoint, remove SESSION_OPEN_FILE_TAB inline b…
jeonghun-jj-lee Aug 11, 2026
1e5a4bd
fix: always show Preview in panel menu, fix nested button issue
jeonghun-jj-lee Aug 11, 2026
5a03a91
fix: render math/tables in Preview, make toggle a segmented control
jeonghun-jj-lee Aug 11, 2026
f43d0de
feat: add right-click context menu to copy filename/path in Preview tab
jeonghun-jj-lee Aug 11, 2026
165c25f
fix: math overflow, save status indicator, icon-only segmented toggle
jeonghun-jj-lee Aug 11, 2026
916ca39
fix: segmented control width, panel menu tab overlap, save indicator
jeonghun-jj-lee Aug 11, 2026
01407d5
fix: push + button right with pl-3, add zoom control, green save indi…
jeonghun-jj-lee Aug 11, 2026
dd062f9
fix: wire zoom to content scaling (preview + raw editor)
jeonghun-jj-lee Aug 11, 2026
31c4c32
fix: zoom layout [100% | - +], match session font size (text-12)
jeonghun-jj-lee Aug 11, 2026
8ad7e1e
fix: copy full path resolves ~, reorder filename above full path
jeonghun-jj-lee Aug 11, 2026
6487db1
fix: clipboard copy via bridge, zoom % wider, -/+ tighter
jeonghun-jj-lee Aug 11, 2026
a3be6dc
fix: preserve native undo/redo/select-all in raw editor
jeonghun-jj-lee Aug 11, 2026
3c37b36
fix: move + button outside Tabs.List, stop propagation for Cmd+A/Z, m…
jeonghun-jj-lee Aug 11, 2026
7718be8
fix: native keydown listener for Cmd+A, push + button further right
jeonghun-jj-lee Aug 11, 2026
1f2b46e
fix: reduce right padding on + button, add selection styling to textarea
jeonghun-jj-lee Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/app/src/components/session/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export { SessionHeader } from "./session-header"
export { SessionContextTab } from "./session-context-tab"
export { SessionPreviewTab } from "./session-preview-tab"
export { PanelMenu } from "./panel-menu"
export { SortableTab, FileVisual } from "./session-sortable-tab"
export { SortableTabV2 } from "./session-sortable-tab-v2"
export { SortableTerminalTab } from "./session-sortable-terminal-tab"
Expand Down
55 changes: 55 additions & 0 deletions packages/app/src/components/session/panel-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { For, Show } from "solid-js"
import { Icon } from "@opencode-ai/ui/icon"
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"

// ─── Types ──────────────────────────────────────────────────────────────────

export interface PanelMenuItem {
id: string
label: string
icon: string
available: () => boolean
active?: () => boolean
}

// ─── Component ──────────────────────────────────────────────────────────────

export function PanelMenu(props: {
items: PanelMenuItem[]
onSelect: (id: string) => void
v2?: boolean
}) {
return (
<DropdownMenu gutter={4} placement="bottom-end">
<DropdownMenu.Trigger
class="flex items-center justify-center w-7 h-7 rounded-md text-text-weak hover:text-text-base hover:bg-background-stronger transition-colors cursor-pointer"
aria-label="Open panel"
>
<Icon name="plus-small" />
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
class="z-50 min-w-[160px] overflow-hidden rounded-lg border border-border-base bg-background-base p-1 shadow-md"
>
<For each={props.items.filter((item) => item.available())}>
{(item) => (
<DropdownMenu.Item
class="flex items-center gap-2 px-2.5 py-1.5 rounded-md text-12-regular text-text-base cursor-pointer outline-none hover:bg-background-stronger focus:bg-background-stronger transition-colors"
classList={{
"opacity-60": item.active?.() ?? false,
}}
onSelect={() => props.onSelect(item.id)}
>
<Icon name={item.icon as any} size="small" class="text-text-weak" />
<span>{item.label}</span>
<Show when={item.active?.()}>
<Icon name="check-small" size="small" class="ml-auto text-text-weak" />
</Show>
</DropdownMenu.Item>
)}
</For>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu>
)
}
Loading
Loading