fix(web): align subagent catalog spacing
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
menu: 360px; padding 4px; gap 4px; radius 12px
|
||||||
|
row: 352×54px; padding 7px 8px 7px 4px; radius 8px
|
||||||
|
content: 340×40px; left inset 8px; right inset 12px
|
||||||
|
label: 14px/20px/400
|
||||||
|
summary: 12px/18px/400
|
||||||
@@ -21,6 +21,7 @@ const BASE_FIXTURE = fileURLToPath(new URL('./snapshots/live-interactions/sessio
|
|||||||
const AVAILABLE_CHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/ui.expected.md', import.meta.url))
|
const AVAILABLE_CHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/ui.expected.md', import.meta.url))
|
||||||
const TREE_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/tree.expected.md', import.meta.url))
|
const TREE_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/tree.expected.md', import.meta.url))
|
||||||
const BRANCHLESS_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/branchless.expected.md', import.meta.url))
|
const BRANCHLESS_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/branchless.expected.md', import.meta.url))
|
||||||
|
const BRANCHLESS_LAYOUT_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/branchless-layout.expected.md', import.meta.url))
|
||||||
const STALE_CATALOG_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/stale-catalog.expected.md', import.meta.url))
|
const STALE_CATALOG_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/stale-catalog.expected.md', import.meta.url))
|
||||||
const SIDEBAR_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/sidebar.expected.md', import.meta.url))
|
const SIDEBAR_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/sidebar.expected.md', import.meta.url))
|
||||||
const UNAVAILABLE_GRANDCHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/nested.expected.md', import.meta.url))
|
const UNAVAILABLE_GRANDCHILD_EXPECTED = fileURLToPath(new URL('./snapshots/subagent-conversation/nested.expected.md', import.meta.url))
|
||||||
@@ -400,6 +401,80 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
|
|||||||
const tree = page.getByRole('tree', { name: 'Subagent sessions' })
|
const tree = page.getByRole('tree', { name: 'Subagent sessions' })
|
||||||
const nestedRow = tree.getByRole('treeitem', { name: new RegExp(NESTED_LABEL) })
|
const nestedRow = tree.getByRole('treeitem', { name: new RegExp(NESTED_LABEL) })
|
||||||
expect(await nestedRow.locator(':scope > *').count()).toBe(1)
|
expect(await nestedRow.locator(':scope > *').count()).toBe(1)
|
||||||
|
const clickArea = nestedRow.locator(':scope > *')
|
||||||
|
const label = nestedRow.getByText(NESTED_LABEL, { exact: true })
|
||||||
|
const summary = nestedRow.getByText('continuable · not running', { exact: true })
|
||||||
|
const [treeBox, rowBox, clickAreaBox, treeStyle, rowStyle, labelStyle, summaryStyle] = await Promise.all([
|
||||||
|
tree.boundingBox(),
|
||||||
|
nestedRow.boundingBox(),
|
||||||
|
clickArea.boundingBox(),
|
||||||
|
tree.evaluate((element) => {
|
||||||
|
const style = getComputedStyle(element)
|
||||||
|
return { gap: style.gap, padding: style.padding, radius: style.borderRadius }
|
||||||
|
}),
|
||||||
|
nestedRow.evaluate((element) => {
|
||||||
|
const style = getComputedStyle(element)
|
||||||
|
return { padding: style.padding, radius: style.borderRadius }
|
||||||
|
}),
|
||||||
|
label.evaluate((element) => {
|
||||||
|
const style = getComputedStyle(element)
|
||||||
|
return { size: style.fontSize, lineHeight: style.lineHeight, weight: style.fontWeight }
|
||||||
|
}),
|
||||||
|
summary.evaluate((element) => {
|
||||||
|
const style = getComputedStyle(element)
|
||||||
|
return { size: style.fontSize, lineHeight: style.lineHeight, weight: style.fontWeight }
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
expect(treeBox).not.toBeNull()
|
||||||
|
expect(rowBox).not.toBeNull()
|
||||||
|
expect(clickAreaBox).not.toBeNull()
|
||||||
|
const leftInset = Math.round(clickAreaBox!.x - treeBox!.x)
|
||||||
|
const rightInset = Math.round(
|
||||||
|
treeBox!.x + treeBox!.width - clickAreaBox!.x - clickAreaBox!.width,
|
||||||
|
)
|
||||||
|
const layout = {
|
||||||
|
menuWidth: Math.round(treeBox!.width),
|
||||||
|
menuPadding: treeStyle.padding,
|
||||||
|
menuGap: treeStyle.gap,
|
||||||
|
menuRadius: treeStyle.radius,
|
||||||
|
rowWidth: Math.round(rowBox!.width),
|
||||||
|
rowHeight: Math.round(rowBox!.height),
|
||||||
|
rowPadding: rowStyle.padding,
|
||||||
|
rowRadius: rowStyle.radius,
|
||||||
|
contentWidth: Math.round(clickAreaBox!.width),
|
||||||
|
contentHeight: Math.round(clickAreaBox!.height),
|
||||||
|
leftInset,
|
||||||
|
rightInset,
|
||||||
|
label: labelStyle,
|
||||||
|
summary: summaryStyle,
|
||||||
|
}
|
||||||
|
expect(layout).toEqual({
|
||||||
|
menuWidth: 360,
|
||||||
|
menuPadding: '4px',
|
||||||
|
menuGap: '4px',
|
||||||
|
menuRadius: '12px',
|
||||||
|
rowWidth: 352,
|
||||||
|
rowHeight: 54,
|
||||||
|
rowPadding: '7px 8px 7px 4px',
|
||||||
|
rowRadius: '8px',
|
||||||
|
contentWidth: 340,
|
||||||
|
contentHeight: 40,
|
||||||
|
leftInset: 8,
|
||||||
|
rightInset: 12,
|
||||||
|
label: { size: '14px', lineHeight: '20px', weight: '400' },
|
||||||
|
summary: { size: '12px', lineHeight: '18px', weight: '400' },
|
||||||
|
})
|
||||||
|
await compareOrRefreshGolden(
|
||||||
|
BRANCHLESS_LAYOUT_EXPECTED,
|
||||||
|
[
|
||||||
|
`menu: ${layout.menuWidth}px; padding ${layout.menuPadding}; gap ${layout.menuGap}; radius ${layout.menuRadius}`,
|
||||||
|
`row: ${layout.rowWidth}×${layout.rowHeight}px; padding ${layout.rowPadding}; radius ${layout.rowRadius}`,
|
||||||
|
`content: ${layout.contentWidth}×${layout.contentHeight}px; left inset ${layout.leftInset}px; right inset ${layout.rightInset}px`,
|
||||||
|
`label: ${layout.label.size}/${layout.label.lineHeight}/${layout.label.weight}`,
|
||||||
|
`summary: ${layout.summary.size}/${layout.summary.lineHeight}/${layout.summary.weight}`,
|
||||||
|
].join('\n'),
|
||||||
|
MODE,
|
||||||
|
)
|
||||||
await compareOrRefreshGolden(
|
await compareOrRefreshGolden(
|
||||||
BRANCHLESS_EXPECTED,
|
BRANCHLESS_EXPECTED,
|
||||||
await captureStableAria(page, '[role="tree"][aria-label="Subagent sessions"]', scaffold.workspaceCwd),
|
await captureStableAria(page, '[role="tree"][aria-label="Subagent sessions"]', scaffold.workspaceCwd),
|
||||||
|
|||||||
@@ -49,42 +49,43 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 336px;
|
gap: 4px;
|
||||||
|
width: 360px;
|
||||||
max-width: min(400px, calc(100vw - 32px));
|
max-width: min(400px, calc(100vw - 32px));
|
||||||
max-height: min(560px, calc(100vh - 140px));
|
max-height: calc(100vh - 140px);
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border: 1px solid var(--dsw-alias-border-l2);
|
border: 0;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: var(--dsw-specific-menu);
|
background: var(--dsw-specific-menu);
|
||||||
--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
|
--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
|
||||||
--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
|
--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
|
||||||
box-shadow: var(--dsw-shadow-lv3);
|
box-shadow: inset 0 0 0 1px var(--dsw-alias-border-inverted), var(--dsw-shadow-lv3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.node {
|
.node {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.menu > .node {
|
|
||||||
margin-left: -8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 50px;
|
min-height: 54px;
|
||||||
padding: 7px 8px 7px 11px;
|
padding: 7px 8px 7px 4px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--dsw-alias-label-primary);
|
color: var(--dsw-alias-label-primary);
|
||||||
font-size: 13px;
|
font-size: 14px;
|
||||||
line-height: 18px;
|
line-height: 20px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -101,16 +102,26 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 6px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
margin: -7px -8px -7px;
|
border-radius: 12px;
|
||||||
padding: 7px 8px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.row > :global([data-state]),
|
|
||||||
.clickarea > :global([data-state]) {
|
.clickarea > :global([data-state]) {
|
||||||
margin-top: 4px;
|
margin: 5px 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:has(> .disclosure) > .clickarea,
|
||||||
|
.row:has(> .disclosureSpace) > .clickarea {
|
||||||
|
padding-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:has(> .disclosureSpace):not(:has(> .clickarea)) {
|
||||||
|
padding-left: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row > :global([data-state]) {
|
||||||
|
margin: 5px 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.disabled {
|
||||||
@@ -128,9 +139,16 @@
|
|||||||
|
|
||||||
.disclosure,
|
.disclosure,
|
||||||
.disclosureSpace {
|
.disclosureSpace {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
left: 4px;
|
||||||
flex: none;
|
flex: none;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 18px;
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclosureSpace {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disclosure {
|
.disclosure {
|
||||||
@@ -157,6 +175,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,19 +188,21 @@
|
|||||||
|
|
||||||
.label {
|
.label {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
font-size: 14px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary,
|
.summary,
|
||||||
.metrics {
|
.metrics {
|
||||||
color: var(--dsw-alias-label-tertiary);
|
color: var(--dsw-alias-label-tertiary);
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
line-height: 16px;
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metrics {
|
.metrics {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 18px 16px;
|
grid-template-rows: 20px 18px;
|
||||||
flex: none;
|
flex: none;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -190,7 +211,7 @@
|
|||||||
|
|
||||||
.metricToken {
|
.metricToken {
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
line-height: 18px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metricDuration {
|
.metricDuration {
|
||||||
@@ -199,6 +220,9 @@
|
|||||||
|
|
||||||
.children {
|
.children {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user