fix(web): align queue panel with responsive composer

This commit is contained in:
kingwl
2026-07-30 12:25:48 +08:00
parent 1642b8f7d2
commit 751b970997
7 changed files with 61 additions and 14 deletions

View File

@@ -85,6 +85,26 @@ describe('web e2e: queue row actions', () => {
{ timeout: 10_000 }, { timeout: 10_000 },
).toBe(2) ).toBe(2)
await page.setViewportSize({ width: 640, height: 1000 })
const queueBox = await page.locator('[data-queue-dock]').boundingBox()
const composerBox = await page.locator('[data-composer-card]').boundingBox()
expect(queueBox).not.toBeNull()
expect(composerBox).not.toBeNull()
expect(queueBox!.x).toBeGreaterThanOrEqual(composerBox!.x)
expect(queueBox!.x + queueBox!.width)
.toBeLessThanOrEqual(composerBox!.x + composerBox!.width)
const queueLeftInset = queueBox!.x - composerBox!.x
const queueRightInset = composerBox!.x + composerBox!.width - queueBox!.x - queueBox!.width
const composerMetrics = await page.locator('[data-composer-card]').evaluate((element) => {
const style = getComputedStyle(element)
return {
dockInset: Number.parseFloat(style.getPropertyValue('--dsh-composer-dock-inset')),
}
})
expect(queueLeftInset).toBeCloseTo(composerMetrics.dockInset, 1)
expect(queueRightInset).toBeCloseTo(composerMetrics.dockInset, 1)
await page.setViewportSize({ width: 1680, height: 1000 })
const editRow = page.getByText(EDIT, { exact: true }).locator('..') const editRow = page.getByText(EDIT, { exact: true }).locator('..')
await editRow.getByRole('button', { name: '编辑排队消息' }).click() await editRow.getByRole('button', { name: '编辑排队消息' }).click()
const editor = page.getByRole('textbox', { name: '编辑排队消息' }) const editor = page.getByRole('textbox', { name: '编辑排队消息' })

View File

@@ -1,10 +1,21 @@
/* Figma .FileContainerText 1:791: 776px wrapper around the inset 752px panel. */ /* Figma .FileContainerText 1:791: the wrapper uses the shared dock inset
inside the composer card around the inset panel. */
.dock { .dock {
box-sizing: border-box; box-sizing: border-box;
flex: none; flex: none;
width: 100%; width: calc(
max-width: 776px; 100% -
var(--dsh-composer-side-clearance) -
var(--dsh-composer-side-clearance) -
var(--dsh-composer-dock-inset) -
var(--dsh-composer-dock-inset)
);
max-width: calc(
var(--dsh-composer-card-max-width) -
var(--dsh-composer-dock-inset) -
var(--dsh-composer-dock-inset)
);
/* Eat InputBar's 6px top padding and tuck the panel 2px under the card; /* Eat InputBar's 6px top padding and tuck the panel 2px under the card;
the later composer sibling paints its surface and shadow over this edge. */ the later composer sibling paints its surface and shadow over this edge. */
margin: 0 auto -10px; margin: 0 auto -10px;

View File

@@ -61,7 +61,7 @@ export function QueueDock({ useSession, updateQueue, notify }: QueueDockProps) {
} }
return ( return (
<div className={css.dock}> <div className={css.dock} data-queue-dock="">
<div className={css.panel}> <div className={css.panel}>
<ul className={css.list}> <ul className={css.list}>
{queue.map(row => ( {queue.map(row => (

View File

@@ -131,6 +131,11 @@
.composerStack { .composerStack {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
/* InputBar and dock registrants derive their horizontal geometry from the
same card width, outer clearance, and dock inset. */
--dsh-composer-card-max-width: 800px;
--dsh-composer-side-clearance: 32px;
--dsh-composer-dock-inset: 12px;
} }
/* Common seat for the composer chain (fallback + elected overlay siblings). */ /* Common seat for the composer chain (fallback + elected overlay siblings). */

View File

@@ -11,7 +11,7 @@
padding: 0 24px; padding: 0 24px;
} }
/* Cap matches InputBar card width (800). Glow may paint past the sides. */ /* Cap matches the InputBar card. Glow may paint past the sides. */
.stack { .stack {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -19,7 +19,7 @@
/* figma 75:8208: 12 between title block / workspace / card. */ /* figma 75:8208: 12 between title block / workspace / card. */
gap: 12px; gap: 12px;
width: 100%; width: 100%;
max-width: 800px; max-width: var(--dsh-composer-card-max-width);
overflow: visible; overflow: visible;
} }

View File

@@ -23,7 +23,7 @@
/* figma Input_Bottom: pad L32/R32/B12; the bottom gradient mask is owned by /* figma Input_Bottom: pad L32/R32/B12; the bottom gradient mask is owned by
the chat scroller. Top 6 is the gap under the dock todo strip (12px todo the chat scroller. Top 6 is the gap under the dock todo strip (12px todo
margin + 6px here); error/status strips still carry their own margin. */ margin + 6px here); error/status strips still carry their own margin. */
padding: 6px 32px 12px; padding: 6px var(--dsh-composer-side-clearance) 12px;
} }
.hero { .hero {
@@ -33,7 +33,7 @@
.error, .error,
.status { .status {
width: 100%; width: 100%;
max-width: 800px; max-width: var(--dsh-composer-card-max-width);
margin-bottom: 6px; margin-bottom: 6px;
padding: 4px 8px; padding: 4px 8px;
border-radius: 8px; border-radius: 8px;
@@ -48,7 +48,7 @@
.notice { .notice {
width: 100%; width: 100%;
max-width: 800px; max-width: var(--dsh-composer-card-max-width);
margin-bottom: 6px; margin-bottom: 6px;
padding: 4px 8px; padding: 4px 8px;
border-radius: 8px; border-radius: 8px;
@@ -69,6 +69,7 @@
} }
.card { .card {
box-sizing: border-box;
position: relative; /* overlay anchor positioning context */ position: relative; /* overlay anchor positioning context */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -76,7 +77,7 @@
top pad on the card before .InputText. */ top pad on the card before .InputText. */
gap: 12px; gap: 12px;
width: 100%; width: 100%;
max-width: 800px; max-width: var(--dsh-composer-card-max-width);
padding-top: 10px; padding-top: 10px;
/* Input stroke: black/0.10 light, white/0.06 dark (figma darkmode note says /* Input stroke: black/0.10 light, white/0.06 dark (figma darkmode note says
the input border is one notch weaker than buttons) — exactly the the input border is one notch weaker than buttons) — exactly the

View File

@@ -1,13 +1,23 @@
/* Todo strip above the composer (figma 772:51905 / 772:52972 / 772:53419): /* Todo strip above the composer (figma 772:51905 / 772:52972 / 772:53419):
tip surface, 14px radius, status icons + secondary item labels. Column is tip surface, 14px radius, status icons + secondary item labels. It shares
calc(100% - 88px) / max 776, centered; InputBar top pad supplies the gap. */ the composer card geometry and adds the dock inset on both sides. */
.root { .root {
flex: none; flex: none;
overflow: hidden; overflow: hidden;
margin: 0 auto; margin: 0 auto;
width: calc(100% - 88px); width: calc(
max-width: 776px; 100% -
var(--dsh-composer-side-clearance) -
var(--dsh-composer-side-clearance) -
var(--dsh-composer-dock-inset) -
var(--dsh-composer-dock-inset)
);
max-width: calc(
var(--dsh-composer-card-max-width) -
var(--dsh-composer-dock-inset) -
var(--dsh-composer-dock-inset)
);
border: 1px solid var(--dsw-alias-border-l1); border: 1px solid var(--dsw-alias-border-l1);
border-radius: 14px; border-radius: 14px;
background: var(--dsw-specific-tip); background: var(--dsw-specific-tip);