|
|
@@ -104,7 +104,7 @@ const SessionRow = (props: {
|
|
|
}): JSX.Element => (
|
|
|
<A
|
|
|
href={`/${props.slug}/session/${props.session.id}`}
|
|
|
- class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${props.mobile ? "pr-7" : ""} group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${props.dense ? "py-0.5" : "py-1"}`}
|
|
|
+ class={`flex items-center gap-1 min-w-0 w-full text-left focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`}
|
|
|
onPointerDown={props.warmPress}
|
|
|
onPointerEnter={props.warmHover}
|
|
|
onPointerLeave={props.cancelHoverPrefetch}
|
|
|
@@ -115,30 +115,26 @@ const SessionRow = (props: {
|
|
|
props.clearHoverProjectSoon()
|
|
|
}}
|
|
|
>
|
|
|
- <div class="flex items-center gap-1 w-full">
|
|
|
- <div
|
|
|
- class="shrink-0 size-6 flex items-center justify-center"
|
|
|
- style={{ color: props.tint() ?? "var(--icon-interactive-base)" }}
|
|
|
- >
|
|
|
- <Switch fallback={<Icon name="dash" size="small" class="text-icon-weak" />}>
|
|
|
- <Match when={props.isWorking()}>
|
|
|
- <Spinner class="size-[15px]" />
|
|
|
- </Match>
|
|
|
- <Match when={props.hasPermissions()}>
|
|
|
- <div class="size-1.5 rounded-full bg-surface-warning-strong" />
|
|
|
- </Match>
|
|
|
- <Match when={props.hasError()}>
|
|
|
- <div class="size-1.5 rounded-full bg-text-diff-delete-base" />
|
|
|
- </Match>
|
|
|
- <Match when={props.unseenCount() > 0}>
|
|
|
- <div class="size-1.5 rounded-full bg-text-interactive-base" />
|
|
|
- </Match>
|
|
|
- </Switch>
|
|
|
- </div>
|
|
|
- <span class="text-14-regular text-text-strong grow-1 min-w-0 overflow-hidden text-ellipsis truncate">
|
|
|
- {props.session.title}
|
|
|
- </span>
|
|
|
+ <div
|
|
|
+ class="shrink-0 size-6 flex items-center justify-center"
|
|
|
+ style={{ color: props.tint() ?? "var(--icon-interactive-base)" }}
|
|
|
+ >
|
|
|
+ <Switch fallback={<Icon name="dash" size="small" class="text-icon-weak" />}>
|
|
|
+ <Match when={props.isWorking()}>
|
|
|
+ <Spinner class="size-[15px]" />
|
|
|
+ </Match>
|
|
|
+ <Match when={props.hasPermissions()}>
|
|
|
+ <div class="size-1.5 rounded-full bg-surface-warning-strong" />
|
|
|
+ </Match>
|
|
|
+ <Match when={props.hasError()}>
|
|
|
+ <div class="size-1.5 rounded-full bg-text-diff-delete-base" />
|
|
|
+ </Match>
|
|
|
+ <Match when={props.unseenCount() > 0}>
|
|
|
+ <div class="size-1.5 rounded-full bg-text-interactive-base" />
|
|
|
+ </Match>
|
|
|
+ </Switch>
|
|
|
</div>
|
|
|
+ <span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{props.session.title}</span>
|
|
|
</A>
|
|
|
)
|
|
|
|
|
|
@@ -167,7 +163,11 @@ const SessionHoverPreview = (props: {
|
|
|
placement="right-start"
|
|
|
gutter={16}
|
|
|
shift={-2}
|
|
|
- trigger={<div ref={ref}>{props.trigger}</div>}
|
|
|
+ trigger={
|
|
|
+ <div ref={ref} class="min-w-0 w-full">
|
|
|
+ {props.trigger}
|
|
|
+ </div>
|
|
|
+ }
|
|
|
open={props.hoverSession() === props.session.id}
|
|
|
onOpenChange={(open) => {
|
|
|
if (!open) {
|
|
|
@@ -309,62 +309,71 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
|
|
|
return (
|
|
|
<div
|
|
|
data-session-id={props.session.id}
|
|
|
- class="group/session relative w-full rounded-md cursor-default pl-2 pr-3 transition-colors
|
|
|
+ class="group/session relative w-full min-w-0 rounded-md cursor-default pl-2 pr-3 transition-colors
|
|
|
hover:bg-surface-raised-base-hover [&:has(:focus-visible)]:bg-surface-raised-base-hover has-[[data-expanded]]:bg-surface-raised-base-hover has-[.active]:bg-surface-base-active"
|
|
|
>
|
|
|
- <Show
|
|
|
- when={hoverEnabled()}
|
|
|
- fallback={
|
|
|
- <Tooltip placement={props.mobile ? "bottom" : "right"} value={props.session.title} gutter={10}>
|
|
|
- {item}
|
|
|
- </Tooltip>
|
|
|
- }
|
|
|
- >
|
|
|
- <SessionHoverPreview
|
|
|
- mobile={props.mobile}
|
|
|
- nav={props.nav}
|
|
|
- hoverSession={props.hoverSession}
|
|
|
- session={props.session}
|
|
|
- sidebarHovering={props.sidebarHovering}
|
|
|
- hoverReady={hoverReady}
|
|
|
- hoverMessages={hoverMessages}
|
|
|
- language={language}
|
|
|
- isActive={isActive}
|
|
|
- slug={props.slug}
|
|
|
- setHoverSession={props.setHoverSession}
|
|
|
- messageLabel={messageLabel}
|
|
|
- onMessageSelect={(message) => {
|
|
|
- if (!isActive())
|
|
|
- layout.pendingMessage.set(`${base64Encode(props.session.directory)}/${props.session.id}`, message.id)
|
|
|
+ <div class="flex min-w-0 items-center gap-1">
|
|
|
+ <div class="min-w-0 flex-1">
|
|
|
+ <Show
|
|
|
+ when={hoverEnabled()}
|
|
|
+ fallback={
|
|
|
+ <Tooltip
|
|
|
+ placement={props.mobile ? "bottom" : "right"}
|
|
|
+ value={props.session.title}
|
|
|
+ gutter={10}
|
|
|
+ class="min-w-0 w-full"
|
|
|
+ >
|
|
|
+ {item}
|
|
|
+ </Tooltip>
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <SessionHoverPreview
|
|
|
+ mobile={props.mobile}
|
|
|
+ nav={props.nav}
|
|
|
+ hoverSession={props.hoverSession}
|
|
|
+ session={props.session}
|
|
|
+ sidebarHovering={props.sidebarHovering}
|
|
|
+ hoverReady={hoverReady}
|
|
|
+ hoverMessages={hoverMessages}
|
|
|
+ language={language}
|
|
|
+ isActive={isActive}
|
|
|
+ slug={props.slug}
|
|
|
+ setHoverSession={props.setHoverSession}
|
|
|
+ messageLabel={messageLabel}
|
|
|
+ onMessageSelect={(message) => {
|
|
|
+ if (!isActive())
|
|
|
+ layout.pendingMessage.set(`${base64Encode(props.session.directory)}/${props.session.id}`, message.id)
|
|
|
|
|
|
- navigate(`${props.slug}/session/${props.session.id}#message-${message.id}`)
|
|
|
- }}
|
|
|
- trigger={item}
|
|
|
- />
|
|
|
- </Show>
|
|
|
+ navigate(`${props.slug}/session/${props.session.id}#message-${message.id}`)
|
|
|
+ }}
|
|
|
+ trigger={item}
|
|
|
+ />
|
|
|
+ </Show>
|
|
|
+ </div>
|
|
|
|
|
|
- <div
|
|
|
- class={`absolute ${props.dense ? "top-0.5 right-0.5" : "top-1 right-1"} flex items-center gap-0.5 transition-opacity`}
|
|
|
- classList={{
|
|
|
- "opacity-100 pointer-events-auto": !!props.mobile,
|
|
|
- "opacity-0 pointer-events-none": !props.mobile,
|
|
|
- "group-hover/session:opacity-100 group-hover/session:pointer-events-auto": true,
|
|
|
- "group-focus-within/session:opacity-100 group-focus-within/session:pointer-events-auto": true,
|
|
|
- }}
|
|
|
- >
|
|
|
- <Tooltip value={language.t("common.archive")} placement="top">
|
|
|
- <IconButton
|
|
|
- icon="archive"
|
|
|
- variant="ghost"
|
|
|
- class="size-6 rounded-md"
|
|
|
- aria-label={language.t("common.archive")}
|
|
|
- onClick={(event) => {
|
|
|
- event.preventDefault()
|
|
|
- event.stopPropagation()
|
|
|
- void props.archiveSession(props.session)
|
|
|
- }}
|
|
|
- />
|
|
|
- </Tooltip>
|
|
|
+ <div
|
|
|
+ class="shrink-0 overflow-hidden transition-[width,opacity]"
|
|
|
+ classList={{
|
|
|
+ "w-6 opacity-100 pointer-events-auto": !!props.mobile,
|
|
|
+ "w-0 opacity-0 pointer-events-none": !props.mobile,
|
|
|
+ "group-hover/session:w-6 group-hover/session:opacity-100 group-hover/session:pointer-events-auto": true,
|
|
|
+ "group-focus-within/session:w-6 group-focus-within/session:opacity-100 group-focus-within/session:pointer-events-auto": true,
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Tooltip value={language.t("common.archive")} placement="top">
|
|
|
+ <IconButton
|
|
|
+ icon="archive"
|
|
|
+ variant="ghost"
|
|
|
+ class="size-6 rounded-md"
|
|
|
+ aria-label={language.t("common.archive")}
|
|
|
+ onClick={(event) => {
|
|
|
+ event.preventDefault()
|
|
|
+ event.stopPropagation()
|
|
|
+ void props.archiveSession(props.session)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </Tooltip>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
)
|
|
|
@@ -386,30 +395,26 @@ export const NewSessionItem = (props: {
|
|
|
<A
|
|
|
href={`/${props.slug}/session`}
|
|
|
end
|
|
|
- class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`}
|
|
|
+ class={`flex items-center gap-1 min-w-0 w-full text-left focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`}
|
|
|
onClick={() => {
|
|
|
props.setHoverSession(undefined)
|
|
|
if (layout.sidebar.opened()) return
|
|
|
props.clearHoverProjectSoon()
|
|
|
}}
|
|
|
>
|
|
|
- <div class="flex items-center gap-1 w-full">
|
|
|
- <div class="shrink-0 size-6 flex items-center justify-center">
|
|
|
- <Icon name="new-session" size="small" class="text-icon-weak" />
|
|
|
- </div>
|
|
|
- <span class="text-14-regular text-text-strong grow-1 min-w-0 overflow-hidden text-ellipsis truncate">
|
|
|
- {label}
|
|
|
- </span>
|
|
|
+ <div class="shrink-0 size-6 flex items-center justify-center">
|
|
|
+ <Icon name="new-session" size="small" class="text-icon-weak" />
|
|
|
</div>
|
|
|
+ <span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{label}</span>
|
|
|
</A>
|
|
|
)
|
|
|
|
|
|
return (
|
|
|
- <div class="group/session relative w-full rounded-md cursor-default transition-colors pl-2 pr-3 hover:bg-surface-raised-base-hover [&:has(:focus-visible)]:bg-surface-raised-base-hover has-[.active]:bg-surface-base-active">
|
|
|
+ <div class="group/session relative w-full min-w-0 rounded-md cursor-default transition-colors pl-2 pr-3 hover:bg-surface-raised-base-hover [&:has(:focus-visible)]:bg-surface-raised-base-hover has-[.active]:bg-surface-base-active">
|
|
|
<Show
|
|
|
when={!tooltip()}
|
|
|
fallback={
|
|
|
- <Tooltip placement={props.mobile ? "bottom" : "right"} value={label} gutter={10}>
|
|
|
+ <Tooltip placement={props.mobile ? "bottom" : "right"} value={label} gutter={10} class="min-w-0 w-full">
|
|
|
{item}
|
|
|
</Tooltip>
|
|
|
}
|