| import { createMemo, Show } from "solid-js" |
| import type { JSX } from "solid-js" |
| import { createSortable } from "@thisbeyond/solid-dnd" |
| import { FileIcon } from "@opencode-ai/ui/file-icon" |
| import { IconButton } from "@opencode-ai/ui/icon-button" |
| import { TooltipKeybind } from "@opencode-ai/ui/tooltip" |
| import { Tabs } from "@opencode-ai/ui/tabs" |
| import { getFilename } from "@opencode-ai/core/util/path" |
| import { useFile } from "@/context/file" |
| import { useLanguage } from "@/context/language" |
| import { useCommand } from "@/context/command" |
|
|
| export function FileVisual(props: { path: string; active?: boolean; temporary?: boolean }): JSX.Element { |
| return ( |
| <div class="flex items-center gap-x-1.5 min-w-0"> |
| <Show |
| when={!props.active} |
| fallback={<FileIcon node={{ path: props.path, type: "file" }} class="size-4 shrink-0" />} |
| > |
| <span class="relative inline-flex size-4 shrink-0"> |
| <FileIcon node={{ path: props.path, type: "file" }} class="absolute inset-0 size-4 tab-fileicon-color" /> |
| <FileIcon node={{ path: props.path, type: "file" }} mono class="absolute inset-0 size-4 tab-fileicon-mono" /> |
| </span> |
| </Show> |
| <span class="text-14-medium truncate" classList={{ italic: props.temporary }}> |
| {getFilename(props.path)} |
| </span> |
| </div> |
| ) |
| } |
|
|
| export function SortableTab(props: { |
| tab: string |
| temporary?: boolean |
| onTabClose: (tab: string) => void |
| onTabDoubleClick?: (tab: string) => void |
| }): JSX.Element { |
| const file = useFile() |
| const language = useLanguage() |
| const command = useCommand() |
| const sortable = createSortable(props.tab) |
| const path = createMemo(() => file.pathFromTab(props.tab)) |
| const content = createMemo(() => { |
| const value = path() |
| if (!value) return |
| return <FileVisual path={value} temporary={props.temporary} /> |
| }) |
| return ( |
| <div use:sortable class="h-full flex items-center" classList={{ "opacity-0": sortable.isActiveDraggable }}> |
| <div class="relative"> |
| <Tabs.Trigger |
| value={props.tab} |
| closeButton={ |
| <TooltipKeybind |
| title={language.t("common.closeTab")} |
| keybind={command.keybind("tab.close")} |
| placement="bottom" |
| gutter={10} |
| > |
| <IconButton |
| icon="close-small" |
| variant="ghost" |
| class="h-5 w-5" |
| onClick={() => props.onTabClose(props.tab)} |
| aria-label={language.t("common.closeTab")} |
| /> |
| </TooltipKeybind> |
| } |
| hideCloseButton |
| onMiddleClick={() => props.onTabClose(props.tab)} |
| onDblClick={() => props.onTabDoubleClick?.(props.tab)} |
| > |
| <Show when={content()}>{(value) => value()}</Show> |
| </Tabs.Trigger> |
| </div> |
| </div> |
| ) |
| } |
|
|