diff --git a/tradein-mvp/frontend/src/components/trade-in/VersionFooter.tsx b/tradein-mvp/frontend/src/components/trade-in/VersionFooter.tsx index 426e46df..2ae5cc80 100644 --- a/tradein-mvp/frontend/src/components/trade-in/VersionFooter.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/VersionFooter.tsx @@ -29,10 +29,12 @@ import { formatVersionLabel } from "@/lib/buildInfo"; const styles = ` .version-footer{opacity:.72;transition:opacity .15s;} .version-footer:hover{opacity:1;} -.version-footer a{color:${tokens.muted2};text-decoration:underline;text-underline-offset:2px;} +/* Плашка сквозная для указателя, ссылка внутри — нет. Даже когда она + что-то перекрывает, клик уходит вниз, а не пропадает в ней. */ +.version-footer a{color:${tokens.muted2};text-decoration:underline;text-underline-offset:2px;pointer-events:auto;} .version-footer a:hover{color:${tokens.ink};} @media (max-width: 480px){ - .version-footer{left:10px !important;bottom:10px !important;padding:3px 7px !important;font-size:9px !important;gap:6px !important;} + .version-footer{right:10px !important;bottom:72px !important;padding:3px 7px !important;font-size:9px !important;gap:6px !important;} } `; @@ -51,8 +53,22 @@ export function VersionFooter() { className="version-footer" style={{ position: "fixed", - left: 16, - bottom: 16, + // НЕ левый нижний угол. Там же стоит липкая кнопка «ОЦЕНИТЬ + // КВАРТИРУ» из панели параметров, и плашка ложилась ровно на её + // левую треть: надпись читалась разорванной, а клик по этой трети + // попадал в плашку, а не в кнопку — главное действие продукта + // частично не работало. Снято с прода 27.08. + // + // Правый край свободен: там только кнопка поддержки (z-index 25, + // высота 44 от низа), над ней и встаём. Ниже — пассивная панель + // «Сводка объекта» без органов управления, перекрыть её краем + // ничего не стоит. + right: 16, + bottom: 80, + // Указатель сквозь плашку проходит насквозь (ссылка внутри — + // исключение, см. стили выше): что бы под ней ни оказалось, + // клик достанется ему. + pointerEvents: "none", // Below SupportButton (25) and every v2 HUD overlay — hides under // modals/drawers instead of floating on top of them, mirrors the // z-index reasoning documented in SupportButton.tsx. diff --git a/tradein-mvp/frontend/src/components/trade-in/__tests__/VersionFooter.test.tsx b/tradein-mvp/frontend/src/components/trade-in/__tests__/VersionFooter.test.tsx new file mode 100644 index 00000000..2eab094e --- /dev/null +++ b/tradein-mvp/frontend/src/components/trade-in/__tests__/VersionFooter.test.tsx @@ -0,0 +1,50 @@ +/** + * Плашка версии не должна воровать клик у главной кнопки продукта. + * + * Замер на проде 27.08.2026 (`/trade-in/v2`, окно 1512×900): плашка стояла + * `position: fixed; left: 16; bottom: 16` и попадала ровно на левую треть + * липкой кнопки «ОЦЕНИТЬ КВАРТИРУ» (её прямоугольник — 59…484 по X, 859…904 + * по Y, плашки — 16…284 и 859…884). Надпись читалась разорванной, а + * `document.elementFromPoint` в центре кнопки возвращал плашку — то есть + * клик по этой трети в кнопку не попадал вовсе. + * + * Здесь закрепляются оба следствия разбора: плашка не якорится к левому + * нижнему углу (там живёт кнопка) и не перехватывает указатель, что бы под + * ней ни оказалось. Ссылка «История версий» — единственное исключение, + * иначе она стала бы недоступной. + */ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; + +import { VersionFooter } from "../VersionFooter"; + +function badge(): HTMLElement { + const el = document.querySelector(".version-footer"); + if (!(el instanceof HTMLElement)) throw new Error("плашка версии не отрисовалась"); + return el; +} + +describe("VersionFooter", () => { + it("не занимает левый нижний угол — там липкая кнопка «ОЦЕНИТЬ КВАРТИРУ»", () => { + render(); + const { left, right, bottom } = badge().style; + expect(left, "плашка снова прижата влево, к главной кнопке").toBe(""); + expect(right).not.toBe(""); + // Кнопка поддержки — 44px от низа; встаём НАД ней, а не на неё. + expect(Number.parseInt(bottom, 10)).toBeGreaterThan(60); + }); + + it("не перехватывает указатель, а ссылка внутри — остаётся живой", () => { + render(); + expect(badge().style.pointerEvents).toBe("none"); + // Возврат кликабельности ссылке живёт в