mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,260 @@
|
||||
# Issue #217 — внешняя рамка Text-маркера должна быть капсулой
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/217
|
||||
- **Связанные завершённые задачи:** #179, #211, #213
|
||||
- **Нормативный дизайн:** `demo/srv/reference/device-icons/Light/Text Default.svg`
|
||||
и `demo/srv/reference/device-icons/Dark/Text Default.svg` из пакета #179
|
||||
- **Тип:** bug / polish, обычный трек
|
||||
- **Приоритет:** P1
|
||||
- **Пользовательское изменение:** да
|
||||
|
||||
## 1. Сценарий и персона
|
||||
|
||||
**Персона:** домочадец или гость, который читает текстовое состояние устройства
|
||||
в View/kiosk, и администратор, который проверяет тот же маркер в редакторе.
|
||||
|
||||
**Сценарий:** пользователь видит Text-маркер с широким значением, например
|
||||
`498 ppm`, и ожидает, что внешний shell повторяет капсульную форму внутреннего
|
||||
белого core. После #213 core остаётся капсулой, но внешняя рамка стала эллипсом:
|
||||
вместо прямого среднего участка верхняя и нижняя границы изгибаются по всей
|
||||
ширине.
|
||||
|
||||
## 2. Что человек увидит до и после
|
||||
|
||||
До исправления широкий Text-маркер окружён овальной рамкой, которая визуально
|
||||
не совпадает ни с core, ни с дизайн-пакетом #179. После исправления внешняя
|
||||
рамка имеет форму stadium: торцы являются полуокружностями, а между ними идут
|
||||
прямые горизонтальные участки. Размер, положение и интерактивная область
|
||||
маркера не меняются.
|
||||
|
||||
## 3. Подтверждённая причина
|
||||
|
||||
`src/styles.ts` задаёт правильный общий fallback
|
||||
`border-radius: 9999px` для `.device-shell-frame`, но затем правило
|
||||
`.device-shell:not(.with-values) .device-shell-frame` заменяет его на `50%`.
|
||||
Text-маркер имеет класс `.text-shell`, но не `.with-values`, поэтому для широкой
|
||||
рамки `50%` вычисляется отдельно по ширине и высоте и даёт эллипс.
|
||||
|
||||
Регрессия появилась в реализации #213. Проверки её не поймали, потому что:
|
||||
|
||||
1. smoke `textCoreIsStadium` проверяет только внутренний core;
|
||||
2. capsule smoke проверяет hover/action, а не форму внешней рамки;
|
||||
3. существующий golden показывает Text-маркер слишком мелко, поэтому неверная
|
||||
кривизна не была заметна при визуальном review.
|
||||
|
||||
## 4. Нормативные источники и приоритет
|
||||
|
||||
При расхождении применяются:
|
||||
|
||||
1. решения владельца в #217;
|
||||
2. это ТЗ после зелёного SPEC-REVIEW;
|
||||
3. Light/Dark `Text Default.svg` из принятого пакета #179;
|
||||
4. контракты #213 для размеров, inset, соосности и полной hover/action-области;
|
||||
5. текущая реализация как compatibility baseline для поведения, которое это ТЗ
|
||||
явно не меняет.
|
||||
|
||||
Reference SVG задаёт stadium как для core, так и для внешней рамки Text.
|
||||
|
||||
## 5. Цели
|
||||
|
||||
1. Вернуть внешней рамке Text-маркера форму stadium во всех поверхностях.
|
||||
2. Не изменить размеры, inset, anchor, цвета и поведение маркера.
|
||||
3. Добавить автоматическую проверку именно внешней рамки, падающую при `50%`.
|
||||
4. Сделать дефект заметным в Light/Dark golden review.
|
||||
|
||||
## 6. Scope
|
||||
|
||||
В задачу входят:
|
||||
|
||||
- общий Text device face в full View, kiosk, Device editor/preview и
|
||||
`houseplan-space-card`;
|
||||
- Light/Dark и цветной фон плана;
|
||||
- короткие и длинные Text-значения на поддерживаемой матрице размеров;
|
||||
- CSS-правило формы внешнего `.device-shell-frame`;
|
||||
- source/unit contract, targeted browser smoke и крупный golden-сценарий;
|
||||
- оба changelog и testing-документация.
|
||||
|
||||
## 7. Не входит в задачу
|
||||
|
||||
- изменение ширины, высоты, inset, stroke, shadow, цвета или opacity;
|
||||
- изменение сохранённой координаты, `icon_size`, marker `size` или badge side;
|
||||
- изменение core, MDI-глифа, LQI, pulse, availability или virtual-state;
|
||||
- изменение Icon-only, Double/value/legacy capsule и opening Lock/Unlock;
|
||||
- изменение hover/action target, tooltip, z-index, keyboard или touch поведения;
|
||||
- новые настройки, строки, schema или миграция данных;
|
||||
- откат остальных изменений #213;
|
||||
- принятие golden baseline на Windows или выпуск без команды владельца.
|
||||
|
||||
## 8. Визуальный контракт
|
||||
|
||||
### 8.1. Text
|
||||
|
||||
Для `.device-shell.text-shell .device-shell-frame`:
|
||||
|
||||
- внешний shell имеет stadium-форму при любой ширине больше высоты;
|
||||
- радиус каждого внешнего угла визуально равен половине итоговой высоты рамки с
|
||||
допуском browser layout/raster quantum;
|
||||
- верхняя и нижняя границы между торцами имеют прямой горизонтальный участок;
|
||||
- рамка окружает core с существующим `--device-shell-inset`;
|
||||
- core и shell сохраняют текущие размеры, центр и относительное положение;
|
||||
- CSS `border-radius: 50%` не применяется к широкой Text-рамке.
|
||||
|
||||
Нормативный CSS-подход может использовать saturating radius (`9999px`) либо
|
||||
эквивалентное height-derived значение. Запрещены фиксированные pixel-компенсации
|
||||
по размеру, viewport или DPR.
|
||||
|
||||
### 8.2. Неизменяемые варианты
|
||||
|
||||
- Icon-only shell остаётся окружностью;
|
||||
- внутренний Text core остаётся stadium;
|
||||
- Double/value/legacy shell сохраняет существующую capsule geometry;
|
||||
- opening Lock/Unlock остаётся круглым;
|
||||
- внешний footprint и hit area всех вариантов не меняются.
|
||||
|
||||
### 8.3. Матрица
|
||||
|
||||
Контракт проверяется минимум на:
|
||||
|
||||
- длинном значении (`498 ppm` либо более длинной локализованной строке);
|
||||
- effective base 24, 32, 56, 96 и 112 CSS px;
|
||||
- DPR 1, 1.25, 1.5 и 2;
|
||||
- Light и Dark;
|
||||
- full, preview и static/space-card parity surfaces.
|
||||
|
||||
## 9. UX, accessibility и touch
|
||||
|
||||
Вся внешняя Text-капсула по-прежнему является одной hover- и action-областью,
|
||||
как принято в #213. Минимальная интерактивная область остаётся не меньше 44×44
|
||||
CSS px. Focus-visible, tooltip, accessible name, tab order, confirmation и
|
||||
действие не меняются. Touch/pen не получают новый hover; unavailable сохраняет
|
||||
текущее поведение.
|
||||
|
||||
## 10. Данные, migration и i18n
|
||||
|
||||
Config, layout, localStorage, backend schema и сериализация не меняются.
|
||||
Миграция не нужна; Open → Save не материализует новые поля. Новых
|
||||
пользовательских строк и i18n-ключей нет.
|
||||
|
||||
## 11. Архитектура и зоны изменений
|
||||
|
||||
Исправление должно оставаться в общем device face и применяться ко всем
|
||||
поверхностям без второго renderer:
|
||||
|
||||
```text
|
||||
device presentation
|
||||
→ shared renderDeviceFace classes
|
||||
→ common device styles
|
||||
→ Text-only stadium shell / Icon-only circle
|
||||
```
|
||||
|
||||
Ожидаемые зоны изменений:
|
||||
|
||||
- `src/styles.ts` — сузить circular override так, чтобы он не захватывал Text;
|
||||
- `test/device-marker-polish-contract.test.mjs` — source regression contract;
|
||||
- `demo/smoke_device_icon_design.mjs` — computed-style/geometry matrix внешней
|
||||
Text-рамки и неизменённой круглой Icon-рамки;
|
||||
- golden/reference matrix — крупный Text marker в Light/Dark;
|
||||
- `docs/TESTING.md`, `docs/CHANGELOG.md`, `docs/CHANGELOG.ru.md`.
|
||||
|
||||
## 12. Performance и security
|
||||
|
||||
Исправление является CSS-only geometry change. Нельзя добавлять per-frame JS,
|
||||
ResizeObserver, media listener, отдельный DOM-слой, backdrop-filter или новую
|
||||
анимацию. Число paint/compositor layers не увеличивается. Action и security
|
||||
paths не меняются.
|
||||
|
||||
## 13. Acceptance criteria
|
||||
|
||||
1. **AC1 — stadium shell.** Длинный Text-маркер имеет внешнюю stadium-рамку с
|
||||
прямым средним участком в Light/Dark. **Доказательство:** browser smoke и
|
||||
reviewed крупный golden.
|
||||
2. **AC2 — защита от `50%`.** Regression test проверяет внешнюю рамку и краснеет
|
||||
на documented mutant, возвращающем `border-radius: 50%` для Text.
|
||||
**Доказательство:** source/computed-style smoke + mutant result.
|
||||
3. **AC3 — матрица размеров.** Контракт Text shell выполняется на §8.3 без
|
||||
per-size/DPR исключений. **Доказательство:** browser matrix.
|
||||
4. **AC4 — геометрическая совместимость.** До/после совпадают outer rect, inset,
|
||||
core rect и anchor с допуском одного browser layout quantum; меняется только
|
||||
corner shape. **Доказательство:** browser rect assertions.
|
||||
5. **AC5 — соседние варианты.** Icon-only остаётся кругом, внутренний Text core
|
||||
и Double/value/legacy capsule не меняются. **Доказательство:** targeted smoke
|
||||
и existing device-face tests.
|
||||
6. **AC6 — interaction parity.** Hover и действие по всей Text-капсуле,
|
||||
44×44 minimum target, mouse/touch modality и unavailable остаются как в
|
||||
#213. **Доказательство:** existing capsule hover/action smoke.
|
||||
7. **AC7 — surface/theme parity.** Full View/kiosk, preview и static/space-card
|
||||
показывают одинаковую форму в Light/Dark. **Доказательство:** parity smoke и
|
||||
golden.
|
||||
8. **AC8 — data/i18n/security/performance.** Нет schema, storage, i18n, action,
|
||||
observer, animation или compositor changes. **Доказательство:** unit/source
|
||||
review и fast performance sanity.
|
||||
9. **AC9 — release artifacts.** Оба changelog, testing docs, smoke/golden
|
||||
fixtures и visual fingerprints актуальны. **Доказательство:** docs diff,
|
||||
`check-docs` и release review.
|
||||
|
||||
## 14. План автотестов
|
||||
|
||||
### 14.1. Цикл реализации
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm test
|
||||
npm run build
|
||||
node scripts/check-docs.mjs --external
|
||||
```
|
||||
|
||||
Source/unit guard должен явно различать Text и Icon-only selector contract.
|
||||
Browser smoke получает внешнюю рамку через `.device-shell-frame`, проверяет
|
||||
Text saturating radius и круглую Icon-рамку, сравнивает rect/inset до и после
|
||||
смены размеров и фиксирует documented mutant `50%` как failing case.
|
||||
|
||||
### 14.2. Targeted smoke перед S7
|
||||
|
||||
- `node demo/smoke_device_icon_design.mjs`;
|
||||
- `node demo/smoke_device_preview_parity.mjs`;
|
||||
- `node demo/smoke_static_icon.mjs`;
|
||||
- capsule hover/action smoke из #213;
|
||||
- Light/Dark reference/golden capture с крупным длинным Text-маркером.
|
||||
|
||||
Golden на Windows используется только диагностически. Канонический baseline
|
||||
принимается из reviewed Linux CI artifact перед beta.
|
||||
|
||||
## 15. Риски и меры
|
||||
|
||||
| Риск | Мера |
|
||||
| --- | --- |
|
||||
| Слишком широкое правило перестанет округлять Icon-only | Явная Icon-vs-Text source/browser проверка |
|
||||
| Исправление изменит footprint или anchor | До/после rect/inset assertions |
|
||||
| Double/value capsule получит новый радиус | Отдельный unchanged regression check |
|
||||
| Дефект снова потеряется на мелком golden | Выделенный крупный long-Text сценарий в Light/Dark |
|
||||
| Появится surface-specific CSS | Проверка shared face parity без второго renderer |
|
||||
|
||||
## 16. Откат
|
||||
|
||||
Откат одного implementation commit возвращает прежний selector и visual
|
||||
fixtures. Данных и миграций нет. Golden baseline возвращается только через
|
||||
нормативный Linux artifact, а не ручным принятием локального Windows capture.
|
||||
|
||||
## 17. Release-артефакты
|
||||
|
||||
В user-visible implementation commit одновременно обновляются:
|
||||
|
||||
- `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md` со ссылкой на #217;
|
||||
- `docs/TESTING.md` с новым Text-shell regression contract;
|
||||
- browser smoke и крупный Light/Dark golden/reference сценарий;
|
||||
- screenshot/golden fingerprints, если их источник изменён.
|
||||
|
||||
Release note: внешняя рамка текстовых маркеров снова соответствует капсульной
|
||||
форме дизайн-пакета вместо овала. Сначала beta; stable — только по отдельной
|
||||
команде владельца.
|
||||
|
||||
## 18. Принятые предположения
|
||||
|
||||
1. Дизайн-пакет #179 однозначно задаёт stadium для внешней рамки Text, поэтому
|
||||
дополнительного продуктового вопроса не требуется.
|
||||
2. Исправляется только форма внешней Text-рамки; её размеры, inset и цвета
|
||||
остаются текущими.
|
||||
3. Icon-only остаётся кругом, Double/value/legacy и opening lock не меняются.
|
||||
4. Новых настроек, строк и миграций нет.
|
||||
5. Для визуального review используется отдельный крупный длинный Text marker,
|
||||
а не только существующий общий мелкий golden.
|
||||
@@ -56,6 +56,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным
|
||||
| [#179](https://github.com/Matysh/houseplan-card/issues/179) Новый визуальный язык маркеров устройств | [179-device-icons-redesign.md](179-device-icons-redesign.md) |
|
||||
| [#210](https://github.com/Matysh/houseplan-card/issues/210) Фиксированное пространство экземпляра карточки | [210-fixed-floor-card.md](210-fixed-floor-card.md) |
|
||||
| [#211](https://github.com/Matysh/houseplan-card/issues/211) Визуальное соответствие маркеров дизайн-пакету #179 | [211-device-icons-visual-parity.md](211-device-icons-visual-parity.md) |
|
||||
| [#217](https://github.com/Matysh/houseplan-card/issues/217) Внешняя рамка Text-маркера должна быть капсулой | [217-text-shell-outline.md](217-text-shell-outline.md) |
|
||||
| [#205](https://github.com/Matysh/houseplan-card/issues/205) Продолжение следа после короткой остановки пылесоса | [205-vacuum-trail-resume-grace.md](205-vacuum-trail-resume-grace.md) |
|
||||
|
||||
## P2
|
||||
|
||||
Reference in New Issue
Block a user