diff options
| author | Adam <[email protected]> | 2026-03-24 13:03:55 -0500 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-03-24 13:04:32 -0500 |
| commit | 42a773481e4d50a59784d514d81257330de38ca9 (patch) | |
| tree | 3faa9617e0f7ff979833ec56427623eb6ac8d944 | |
| parent | 539b01f20fc3677155b3bdbb428c69423a805578 (diff) | |
| download | opencode-42a773481e4d50a59784d514d81257330de38ca9.tar.gz opencode-42a773481e4d50a59784d514d81257330de38ca9.zip | |
fix(app): sidebar truncation
| -rw-r--r-- | packages/app/src/pages/layout/sidebar-items.tsx | 179 |
1 files changed, 92 insertions, 87 deletions
diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index a9627c5db..75dada05f 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -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> } |
