diff --git a/vscode/package.json b/vscode/package.json index 6f606e9..62a0601 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -2,7 +2,7 @@ "publisher": "clurdra", "name": "superpowers-vscode-clurdra", "displayName": "Superpowers-clurdra", - "version": "0.2.97", + "version": "0.2.98", "packageManager": "pnpm@10.27.0", "description": "Superpowers specs and plans Kanban explorer", "author": "clurdra", diff --git a/vscode/webview-ui/src/components/ManagedSessionsPanel.tsx b/vscode/webview-ui/src/components/ManagedSessionsPanel.tsx index a246a7d..79ead17 100644 --- a/vscode/webview-ui/src/components/ManagedSessionsPanel.tsx +++ b/vscode/webview-ui/src/components/ManagedSessionsPanel.tsx @@ -145,15 +145,16 @@ export function ManagedSessionsPanel({
Profile - ({ value: p.path, label: p.name }))} - variant="input" - className="min-w-0 flex-1" - /> +
+ ({ value: p.path, label: p.name }))} + variant="input" + /> +
名字 diff --git a/vscode/webview-ui/src/components/ui/select-menu.tsx b/vscode/webview-ui/src/components/ui/select-menu.tsx index 128e6f8..8d981f3 100644 --- a/vscode/webview-ui/src/components/ui/select-menu.tsx +++ b/vscode/webview-ui/src/components/ui/select-menu.tsx @@ -22,6 +22,25 @@ export interface SelectMenuProps { } const MAX_MENU_HEIGHT = 240 +/** 勾选图标 + gap + 水平 padding + 竖滚动条槽。少算会把最后几个字挤成省略号。 */ +const MENU_CHROME_PX = 14 + 6 + 16 + 12 + +function measureOptionsWidth(options: SelectMenuOption[], font: string): number { + const probe = document.createElement('span') + probe.style.cssText = `position:absolute;left:-9999px;top:0;white-space:nowrap;font:${font}` + document.body.appendChild(probe) + let max = 0 + for (const o of options) { + probe.textContent = o.label + max = Math.max(max, probe.offsetWidth) + if (o.hint) { + probe.textContent = o.hint + max = Math.max(max, probe.offsetWidth) + } + } + probe.remove() + return max +} /** * 自定义下拉组件,替代原生 select。 @@ -57,12 +76,21 @@ export function SelectMenu({ const spaceBelow = window.innerHeight - rect.bottom const spaceAbove = rect.top const openUp = spaceBelow < menuHeight && spaceAbove > spaceBelow + // 跟触发器同宽会把长 profile 名截成省略号(ghost / 未撑满的 button 尤其明显)。 + // 按最长项测量,下限触发器宽、上限视口,溢出时左移,不超出 webview。 + const gutter = 8 + const contentW = measureOptionsWidth(options, getComputedStyle(el).font) + MENU_CHROME_PX + const maxWidth = window.innerWidth - gutter * 2 + const width = Math.min(maxWidth, Math.max(rect.width, contentW)) + let left = rect.left + if (left + width > window.innerWidth - gutter) + left = Math.max(gutter, window.innerWidth - gutter - width) setPos({ top: openUp ? Math.max(8, rect.top - menuHeight - 4) : rect.bottom + 4, - left: rect.left, - width: Math.max(rect.width, 120), + left, + width, }) - }, [options.length]) + }, [options]) const openMenu = useCallback((): void => { computePos() @@ -181,7 +209,7 @@ export function SelectMenu({ const triggerClasses = variant === 'input' - ? 'rounded border border-[var(--vscode-input-border,var(--vscode-panel-border))] bg-[var(--vscode-input-background)] px-2 py-1 text-xs text-[var(--vscode-input-foreground)] focus:ring-1 focus:ring-inset focus:ring-[var(--vscode-focusBorder)]' + ? 'w-full rounded border border-[var(--vscode-input-border,var(--vscode-panel-border))] bg-[var(--vscode-input-background)] px-2 py-1 text-xs text-[var(--vscode-input-foreground)] focus:ring-1 focus:ring-inset focus:ring-[var(--vscode-focusBorder)]' : 'rounded bg-transparent px-1 py-0 text-[10px] text-[var(--vscode-descriptionForeground)] hover:bg-[var(--vscode-toolbar-hoverBackground)]' return ( @@ -202,7 +230,7 @@ export function SelectMenu({ className, )} > - + {selected?.label ?? placeholder} @@ -244,8 +272,8 @@ export function SelectMenu({ - {opt.label} - {opt.hint && {opt.hint}} + {opt.label} + {opt.hint && {opt.hint}} ))}