diff --git a/artifacts/badge-preview.config.mts b/artifacts/badge-preview.config.mts new file mode 100644 index 0000000..4fbcec1 --- /dev/null +++ b/artifacts/badge-preview.config.mts @@ -0,0 +1,3 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +export default defineConfig({ plugins: [react()], base: '/__visual-badge/', build: { outDir: 'dist/__visual-badge', rollupOptions: { input: 'artifacts/badge-preview.html' } } }); diff --git a/artifacts/badge-preview.html b/artifacts/badge-preview.html new file mode 100644 index 0000000..eb838ea --- /dev/null +++ b/artifacts/badge-preview.html @@ -0,0 +1 @@ +RideBus — смена номеров
diff --git a/artifacts/badge-preview.tsx b/artifacts/badge-preview.tsx new file mode 100644 index 0000000..c524845 --- /dev/null +++ b/artifacts/badge-preview.tsx @@ -0,0 +1,18 @@ +// Regression fixture: reuse each badge while changing from long to short numbers. +import { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import type { CSSProperties } from 'react'; +import '@fontsource-variable/manrope'; +import '../src/styles.css'; +import { RouteBadge } from '../src/RouteBadge'; +function Preview() { + const [short, setShort] = useState(false); + const numbers = short ? ['2', '6', '11'] : ['21тк', '16тк', '11']; + return
+

Смена номеров

+

Маршруты остановки

+
{numbers.map((number, index) =>

{['Калинина — Автовокзал', 'Гвардеец — Автовокзал', 'Тросницкая — Автовокзал'][index]}

Автобус
)}
+
+
; +} +createRoot(document.getElementById('root')!).render(); diff --git a/artifacts/board-badge-size-fixed.jpg b/artifacts/board-badge-size-fixed.jpg new file mode 100644 index 0000000..2c0c3db Binary files /dev/null and b/artifacts/board-badge-size-fixed.jpg differ diff --git a/artifacts/verification-badge-sizing.md b/artifacts/verification-badge-sizing.md new file mode 100644 index 0000000..0d3f185 --- /dev/null +++ b/artifacts/verification-badge-sizing.md @@ -0,0 +1,11 @@ +# Размер номера после анимации — 9 октября 2026 + +Браузерный сценарий воспроизведён на настоящих `RouteBadge` и `NumericText`, с сохранением компонентов при смене номера. Проверены переходы `21тк → 2`, `16тк → 6` и обратные переходы, повторный цикл, неизменный номер `11`. + +- До исправления после завершения анимации метки `2` и `6` имели ширину 22 px, но сохраняли масштаб `0.54023`, рассчитанный во время исчезновения предыдущих символов. `11` имел масштаб 1. +- `ResizeObserver` теперь наблюдает также за меткой номера: сжатие исчезающих разрядов и изменение шрифта повторно запускают вписывание. CSS-transform самой метки не меняет наблюдаемый размер, поэтому расчёт не образует обратную связь. +- После исправления короткие `2`, `6`, `11` используют масштаб 1 при базовом шрифте 35 px. Длинные `21тк`, `16тк` корректно уменьшаются до масштаба `0.5875` в этом контейнере. Повторные смены возвращают ожидаемый масштаб. +- Во время смены сохранены анимации `digit-down-in` и прокрутка разрядов. Смещение центра метки <0,01 px. Браузерных ошибок и предупреждений нет. +- Проверены широкий браузерный вид и узкий 487×664. Production build и TypeScript проходят. + +Снимок `board-badge-size-fixed.jpg` содержит тестовые карточки после перехода на короткие номера. Сценарий воспроизводится через `npm exec vite build -- --config artifacts/badge-preview.config.mts` и `/__visual-badge/artifacts/badge-preview.html`. Кнопка переключает длинные и короткие номера; позиции компонентов сохраняются. Обычный production build не включает этот сценарий. diff --git a/src/RouteBadge.tsx b/src/RouteBadge.tsx index b81804a..d1a4453 100644 --- a/src/RouteBadge.tsx +++ b/src/RouteBadge.tsx @@ -17,6 +17,9 @@ export function RouteBadge({ number, large = false, filled = false }: { number: }; const observer = new ResizeObserver(fit); observer.observe(element); + // Outgoing digits collapse after the prop change; refit as their width shrinks. + // Observing the untransformed label avoids retaining the previous number's scale. + observer.observe(content); fit(); void document.fonts.ready.then(fit); return () => { mounted = false; observer.disconnect(); }; }, [number]);