fix(web): крупные стрелки устройств и панели, не уезжающие за экран

- стрелки настроек микрофона, камеры и наушников стали прямоугольниками во всю
  высоту основной кнопки (32 px) и шириной около трети кнопки: по ним легко
  попасть, группы не наслаиваются и не выходят за панель (сайдбар расширен до
  256 px, у групп фиксированная ширина 36 px);
- поповеры и меню теперь позиционируются от рабочей области: новая
  `useAnchoredPosition` прижимает панель к краям окна, выбирает сторону с
  большим запасом места и ограничивает высоту, а содержимое прокручивается —
  подписи устройств и слайдер громкости больше не обрезаются;
- тесты: геометрия группы стрелки, открытие меню и ограничение положения
  панели в пределах окна (289 тестов Vitest).
This commit is contained in:
2026-09-20 14:35:08 +03:00
parent a126f50468
commit 494589ffca
6 changed files with 189 additions and 17 deletions
+38
View File
@@ -227,3 +227,41 @@ describe('панель пользователя: профиль', () => {
expect(fresh.useVoiceStore.getState().headphonesEnabled).toBe(true);
});
});
describe('панель: кнопки устройств', () => {
it('стрелки — прямоугольники во всю высоту кнопки и открывают меню', async () => {
const panelRoot = await bootPanel();
const visitor = userEvent.setup();
// Стрелка микрофона доступна по подписи и лежит в одной группе с кнопкой.
const arrow = within(panelRoot).getByRole('button', { name: 'Настройки микрофона' });
const group = arrow.parentElement;
expect(group).not.toBeNull();
expect(group?.className).toContain('h-8');
expect(group?.className).toContain('w-9');
// Кнопка-переключатель — сосед стрелки в той же группе.
expect(group?.querySelectorAll('button')).toHaveLength(2);
await visitor.click(arrow);
const panel = await screen.findByTestId('popover-panel');
// Панель прижата к рабочей области: фиксированное позиционирование и
// ограничение высоты, чтобы содержимое не уезжало за экран.
expect(panel.style.position).toBe('fixed');
expect(panel.style.maxHeight).not.toBe('');
expect(panel.getAttribute('role')).toBe('dialog');
});
it('попап настроек звука не выходит за пределы окна', async () => {
const panelRoot = await bootPanel();
const visitor = userEvent.setup();
await visitor.click(within(panelRoot).getByRole('button', { name: 'Настройки звука' }));
const panel = await screen.findByTestId('popover-panel');
const left = Number.parseInt(panel.style.left, 10);
const top = Number.parseInt(panel.style.top, 10);
expect(left).toBeGreaterThanOrEqual(0);
expect(top).toBeGreaterThanOrEqual(0);
expect(left).toBeLessThan(window.innerWidth);
expect(top).toBeLessThan(window.innerHeight);
});
});