Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/app/e2e/sidebar/sidebar-leading-slot.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { expect, test } from "../fixtures"
import { openSidebar, withSession } from "../actions"
import { pawworkSidebarSelector } from "../selectors"

test("pawwork sidebar merges pin into the status slot with a stable title baseline", async ({
page,
sdk,
gotoSession,
}) => {
const stamp = Date.now()
await withSession(sdk, `i150 regression ${stamp}`, async (session) => {
await gotoSession(session.id)
await openSidebar(page)

const sidebar = page.locator(pawworkSidebarSelector).first()
const row = sidebar.locator(`[data-session-id="${session.id}"]`).first()
const title = row.locator("span", { hasText: `i150 regression ${stamp}` }).first()

const leftOf = async (locator: typeof title) => {
const rect = await locator.evaluate((el) => el.getBoundingClientRect())
return Math.round(rect.left)
}

// Baseline: unpinned, no hover.
await page.mouse.move(0, 0)
await expect(row).toBeVisible()
const baseline = await leftOf(title)

// Hover must not shift the title horizontally (action slot grows on the right).
await row.hover()
expect(await leftOf(title)).toBe(baseline)

// Pin via row menu; the row rerenders in the pinned section.
await row.locator('[data-action="session-row-menu"]').click()
await page.getByRole("menuitem", { name: /pin session/i }).click()
const pinnedRow = sidebar
.locator(`[data-component="pawwork-sidebar-pinned"] [data-session-id="${session.id}"]`)
.first()
await expect(pinnedRow).toBeVisible()

const pinnedTitle = pinnedRow.locator("span", { hasText: `i150 regression ${stamp}` }).first()
await page.mouse.move(0, 0)
expect(await leftOf(pinnedTitle)).toBe(baseline)
await pinnedRow.hover()
expect(await leftOf(pinnedTitle)).toBe(baseline)

// Pin button should occupy the row's leading slot, not a separate column.
const pinButton = pinnedRow.locator('[data-action="pawwork-session-pin"][data-pinned="true"]').first()
await expect(pinButton).toBeVisible()
const pinRect = await pinButton.evaluate((el) => el.getBoundingClientRect())
const rowRect = await pinnedRow.evaluate((el) => el.getBoundingClientRect())
expect(Math.round(pinRect.left - rowRect.left)).toBe(8)
expect(Math.round(pinRect.width)).toBe(24)
})
})
Comment thread
Astro-Han marked this conversation as resolved.
7 changes: 3 additions & 4 deletions packages/app/src/pages/layout/sidebar-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,15 @@ const SessionRow = (props: {
warmPress: () => void
warmFocus: () => void
titleContent?: JSX.Element
leadingSlot?: JSX.Element
}): JSX.Element => {
const title = () => sessionTitle(props.session.title)
const indicator = () => {
if (props.isWorking()) return <Spinner class="size-[15px]" />
if (props.hasPermissions()) return <div class="size-1.5 rounded-full bg-surface-warning-strong" />
if (props.hasError()) return <div class="size-1.5 rounded-full bg-text-diff-delete-base" />
if (props.unseenCount() > 0) return <div class="size-1.5 rounded-full bg-text-interactive-base" />
return null
return props.leadingSlot ?? null
Comment thread
Astro-Han marked this conversation as resolved.
}

return (
Expand Down Expand Up @@ -195,6 +196,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
warmPress={() => warm(2, "high")}
warmFocus={() => warm(2, "high")}
titleContent={props.titleContent?.({ session: props.session, title: () => sessionTitle(props.session.title) ?? "" })}
leadingSlot={!props.level && props.leadingSlot ? props.leadingSlot(props.session) : undefined}
/>
)

Expand All @@ -206,9 +208,6 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
style={{ "padding-left": `${8 + (props.level ?? 0) * 16}px` }}
>
<div class="flex min-w-0 items-center gap-1">
<Show when={props.leadingSlot && !props.level}>
<div class="shrink-0">{props.leadingSlot?.(props.session)}</div>
</Show>
<div class="min-w-0 flex-1">
<Show
when={!tooltip()}
Expand Down
Loading