fix(web): keep pet composer menu expanded (#3336)

- apps/web/src/components/ChatComposer.tsx
- apps/web/tests/components/ChatComposer.context-pickers.test.tsx

Clear stale absolute anchors when the pet composer menu is positioned fixed so the popover wraps its content instead of collapsing over the composer textarea.
This commit is contained in:
Ramiro 2026-05-30 06:19:02 +02:00 committed by GitHub
parent c33641e592
commit ed5e8c147b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 1 deletions

View file

@ -373,7 +373,13 @@ export const ChatComposer = forwardRef<ChatComposerHandle, Props>(
// Right-align by default (menu right edge ≈ button right edge). // Right-align by default (menu right edge ≈ button right edge).
// Shift left when the menu would spill past the viewport left edge. // Shift left when the menu would spill past the viewport left edge.
const left = Math.max(8, Math.min(viewW - menuW - 8, rect.right - menuW)); const left = Math.max(8, Math.min(viewW - menuW - 8, rect.right - menuW));
setPetMenuStyle({ position: 'fixed', top, left }); setPetMenuStyle({
position: 'fixed',
top,
left,
bottom: 'auto',
right: 'auto',
});
}, [petMenuOpen]); }, [petMenuOpen]);
// Lazy-fetch the user's external MCP servers list once on mount so the // Lazy-fetch the user's external MCP servers list once on mount so the

View file

@ -344,4 +344,34 @@ describe('ChatComposer context pickers', () => {
}); });
expect(screen.getByText('Private export workflow')).toBeTruthy(); expect(screen.getByText('Private export workflow')).toBeTruthy();
}); });
it('clears absolute anchors when the pet popover switches to fixed positioning', async () => {
renderComposer({
petConfig: {
adopted: false,
enabled: false,
petId: 'custom',
custom: {
name: 'Buddy',
glyph: '🐾',
accent: '#7c3aed',
greeting: 'hi',
},
},
onAdoptPet: vi.fn(),
onTogglePet: vi.fn(),
onOpenPetSettings: vi.fn(),
});
fireEvent.click(screen.getByRole('button', { name: 'Pets — wake, tuck, or pick one' }));
const menu = screen.getByText('Show pet').closest('.composer-pet-menu') as HTMLElement | null;
expect(menu).not.toBeNull();
await waitFor(() => {
expect(menu?.style.position).toBe('fixed');
expect(menu?.style.bottom).toBe('auto');
expect(menu?.style.right).toBe('auto');
});
});
}); });