feat: small transitions, spacing, polishing
This commit is contained in:
@@ -1557,7 +1557,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
</Show>
|
||||
</div>
|
||||
<div class="relative p-3 flex items-center justify-between">
|
||||
<div class="flex items-center justify-start gap-0.5">
|
||||
<div class="flex items-center justify-start gap-1">
|
||||
<Switch>
|
||||
<Match when={store.mode === "shell"}>
|
||||
<div class="flex items-center gap-2 px-2 h-6">
|
||||
@@ -1608,13 +1608,60 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
title="Thinking effort"
|
||||
keybind={command.keybind("model.variant.cycle")}
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="text-text-base _hidden group-hover/prompt-input:inline-block capitalize text-12-regular"
|
||||
onClick={() => local.model.variant.cycle()}
|
||||
>
|
||||
{local.model.variant.current() ?? "Default"}
|
||||
</Button>
|
||||
{(() => {
|
||||
const [text, setText] = createSignal(local.model.variant.current() ?? "Default")
|
||||
const [animating, setAnimating] = createSignal(false)
|
||||
let locked = false
|
||||
|
||||
const handleClick = async () => {
|
||||
if (locked) return
|
||||
|
||||
local.model.variant.cycle()
|
||||
const newText = local.model.variant.current() ?? "Default"
|
||||
|
||||
if (newText === text()) return
|
||||
|
||||
locked = true
|
||||
setAnimating(true)
|
||||
|
||||
// Wait for exit animation
|
||||
const charCount = text().length
|
||||
await new Promise((r) => setTimeout(r, charCount * 40 + 400))
|
||||
|
||||
// Reset animating before setting new text so @starting-style works
|
||||
setAnimating(false)
|
||||
setText(newText)
|
||||
|
||||
// Wait for enter animation
|
||||
const newCharCount = newText.length
|
||||
await new Promise((r) => setTimeout(r, newCharCount * 40 + 400))
|
||||
|
||||
locked = false
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="text-text-base _hidden text-12-regular"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span data-slot="cycle-text" data-animating={animating()}>
|
||||
<For each={text().split("")}>
|
||||
{(char, i) =>
|
||||
char === " " ? (
|
||||
<span data-slot="space" />
|
||||
) : (
|
||||
<span data-slot="char" style={{ "--i": i() }}>
|
||||
{i() === 0 ? char.toUpperCase() : char}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</For>
|
||||
</span>
|
||||
<Icon name="chevron-down" size="small" />
|
||||
</Button>
|
||||
)
|
||||
})()}
|
||||
</TooltipKeybind>
|
||||
</Show>
|
||||
<Show when={permission.permissionsEnabled() && params.id}>
|
||||
|
||||
@@ -34,7 +34,7 @@ import { DiffChanges } from "@opencode-ai/ui/diff-changes"
|
||||
import { Spinner } from "@opencode-ai/ui/spinner"
|
||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||
import { getFilename } from "@opencode-ai/util/path"
|
||||
import { Session, type Message, type TextPart } from "@opencode-ai/sdk/v2/client"
|
||||
import { Session, type Message, type TextPart, UserMessage } from "@opencode-ai/sdk/v2/client"
|
||||
import { usePlatform } from "@/context/platform"
|
||||
import { createStore, produce, reconcile } from "solid-js/store"
|
||||
import {
|
||||
@@ -1352,7 +1352,7 @@ export default function Layout(props: ParentProps) {
|
||||
})
|
||||
|
||||
const hoverMessages = createMemo(() =>
|
||||
sessionStore.message[props.session.id]?.filter((message) => message.role === "user"),
|
||||
sessionStore.message[props.session.id]?.filter((message) => message.role === "user") as UserMessage[],
|
||||
)
|
||||
const hoverReady = createMemo(() => sessionStore.message[props.session.id] !== undefined)
|
||||
const hoverAllowed = createMemo(() => !props.mobile && layout.sidebar.opened())
|
||||
@@ -1425,8 +1425,8 @@ export default function Layout(props: ParentProps) {
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<HoverCard openDelay={150} closeDelay={100} placement="right" gutter={12} trigger={item}>
|
||||
<Show when={hoverReady()} fallback={<div class="text-12-regular text-text-weak">Loading messages…</div>}>
|
||||
<HoverCard openDelay={150} closeDelay={100} placement="right" gutter={28} trigger={item}>
|
||||
<Show when={hoverReady()} fallback={<div>Loading messages…</div>}>
|
||||
<MessageNav
|
||||
messages={hoverMessages() ?? []}
|
||||
current={undefined}
|
||||
@@ -1822,7 +1822,7 @@ export default function Layout(props: ParentProps) {
|
||||
class="size-full flex flex-col py-2 overflow-y-auto no-scrollbar"
|
||||
style={{ "overflow-anchor": "none" }}
|
||||
>
|
||||
<nav class="flex flex-col gap-1 px-2">
|
||||
<nav class="flex flex-col gap-2 px-2">
|
||||
<Show when={loading()}>
|
||||
<SessionSkeleton />
|
||||
</Show>
|
||||
|
||||
@@ -1180,7 +1180,7 @@ export default function Page() {
|
||||
if (isDesktop()) scheduleScrollSpy(e.currentTarget)
|
||||
}}
|
||||
onClick={autoScroll.handleInteraction}
|
||||
class="relative min-w-0 w-full h-full overflow-y-auto no-scrollbar snap-y snap-mandatory"
|
||||
class="relative min-w-0 w-full h-full overflow-y-auto no-scrollbar snap-both snap-mandatory"
|
||||
style={{ "--session-title-height": info()?.title ? "40px" : "0px" }}
|
||||
>
|
||||
<Show when={info()?.title}>
|
||||
@@ -1252,7 +1252,7 @@ export default function Page() {
|
||||
id={anchor(message.id)}
|
||||
data-message-id={message.id}
|
||||
classList={{
|
||||
"min-w-0 w-full max-w-full snap-start": true,
|
||||
"min-w-0 w-full max-w-full snap-both": true,
|
||||
"md:max-w-200": !showTabs(),
|
||||
"last:min-h-[calc(100vh-5.5rem-var(--prompt-height,8rem)-64px)] md:last:min-h-[calc(100vh-4.5rem-var(--prompt-height,10rem)-64px)]":
|
||||
platform.platform !== "desktop",
|
||||
|
||||
Reference in New Issue
Block a user