summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/components/message-nav.tsx
blob: 8475c320643bd85f2a45173b8a34284389e275c5 (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
import { UserMessage } from "@opencode-ai/sdk"
import { ComponentProps, createMemo, For, Match, Show, splitProps, Switch } from "solid-js"
import { DiffChanges } from "./diff-changes"
import { Spinner } from "./spinner"

export function MessageNav(
  props: ComponentProps<"ul"> & {
    messages: UserMessage[]
    current?: UserMessage
    size: "normal" | "compact"
    working?: boolean
    onMessageSelect: (message: UserMessage) => void
  },
) {
  const [local, others] = splitProps(props, ["messages", "current", "size", "working", "onMessageSelect"])
  const lastUserMessage = createMemo(() => {
    return local.messages?.at(0)
  })

  return (
    <ul role="list" data-component="message-nav" data-size={local.size} {...others}>
      <For each={local.messages}>
        {(message) => {
          const messageWorking = createMemo(() => message.id === lastUserMessage()?.id && local.working)
          const handleClick = () => local.onMessageSelect(message)

          return (
            <li data-slot="message-nav-item">
              <Switch>
                <Match when={local.size === "compact"}>
                  <button
                    data-slot="message-nav-tick-button"
                    data-active={message.id === local.current?.id || undefined}
                    onClick={handleClick}
                  >
                    <div data-slot="message-nav-tick-line" />
                  </button>
                </Match>
                <Match when={local.size === "normal"}>
                  <button data-slot="message-nav-message-button" onClick={handleClick}>
                    <Switch>
                      <Match when={messageWorking()}>
                        <Spinner />
                      </Match>
                      <Match when={true}>
                        <DiffChanges changes={message.summary?.diffs ?? []} variant="bars" />
                      </Match>
                    </Switch>
                    <div
                      data-slot="message-nav-title-preview"
                      data-active={message.id === local.current?.id || undefined}
                    >
                      <Show when={message.summary?.title} fallback="New message">
                        {message.summary?.title}
                      </Show>
                    </div>
                  </button>
                </Match>
              </Switch>
            </li>
          )
        }}
      </For>
    </ul>
  )
}