summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components/prompt-input/context-items.tsx
blob: a843e109d820511ff72047ce68e6a4a1d27e3c77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { Component, For, Show } from "solid-js"
import { FileIcon } from "@opencode-ai/ui/file-icon"
import { IconButton } from "@opencode-ai/ui/icon-button"
import { Tooltip } from "@opencode-ai/ui/tooltip"
import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/util/path"
import type { ContextItem } from "@/context/prompt"

type PromptContextItem = ContextItem & { key: string }

type ContextItemsProps = {
  items: PromptContextItem[]
  active: (item: PromptContextItem) => boolean
  openComment: (item: PromptContextItem) => void
  remove: (item: PromptContextItem) => void
  t: (key: string) => string
}

export const PromptContextItems: Component<ContextItemsProps> = (props) => {
  return (
    <Show when={props.items.length > 0}>
      <div class="flex flex-nowrap items-start gap-2 p-2 overflow-x-auto no-scrollbar">
        <For each={props.items}>
          {(item) => (
            <Tooltip
              value={
                <span class="flex max-w-[300px]">
                  <span class="text-text-invert-base truncate-start [unicode-bidi:plaintext] min-w-0">
                    {getDirectory(item.path)}
                  </span>
                  <span class="shrink-0">{getFilename(item.path)}</span>
                </span>
              }
              placement="top"
              openDelay={2000}
            >
              <div
                classList={{
                  "group shrink-0 flex flex-col rounded-[6px] pl-2 pr-1 py-1 max-w-[200px] h-12 transition-all transition-transform shadow-xs-border hover:shadow-xs-border-hover": true,
                  "cursor-pointer hover:bg-surface-interactive-weak": !!item.commentID && !props.active(item),
                  "cursor-pointer bg-surface-interactive-hover hover:bg-surface-interactive-hover shadow-xs-border-hover":
                    props.active(item),
                  "bg-background-stronger": !props.active(item),
                }}
                onClick={() => props.openComment(item)}
              >
                <div class="flex items-center gap-1.5">
                  <FileIcon node={{ path: item.path, type: "file" }} class="shrink-0 size-3.5" />
                  <div class="flex items-center text-11-regular min-w-0 font-medium">
                    <span class="text-text-strong whitespace-nowrap">{getFilenameTruncated(item.path, 14)}</span>
                    <Show when={item.selection}>
                      {(sel) => (
                        <span class="text-text-weak whitespace-nowrap shrink-0">
                          {sel().startLine === sel().endLine
                            ? `:${sel().startLine}`
                            : `:${sel().startLine}-${sel().endLine}`}
                        </span>
                      )}
                    </Show>
                  </div>
                  <IconButton
                    type="button"
                    icon="close-small"
                    variant="ghost"
                    class="ml-auto size-3.5 text-text-weak hover:text-text-strong transition-all"
                    onClick={(e) => {
                      e.stopPropagation()
                      props.remove(item)
                    }}
                    aria-label={props.t("prompt.context.removeFile")}
                  />
                </div>
                <Show when={item.comment}>
                  {(comment) => <div class="text-12-regular text-text-strong ml-5 pr-1 truncate">{comment()}</div>}
                </Show>
              </div>
            </Tooltip>
          )}
        </For>
      </div>
    </Show>
  )
}