Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-07
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# add-homeds-upsell-bubble

Анимированный бабл апсейла на карточке устройства (вертикаль homeds)

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Why

Продукту нужна механика апсейла на главном экране «Мой дом»: анимированный бабл-подсказка на карточке устройства, который разворачивается в предложение и ведёт на экран апсейла. Разработчики вертикали попросили сделать это через дизайн-систему — не кастомить с нуля и ускорить разработку. Готового компонента с такой анимацией (иконка-триггер, разворачивающийся бабл с автосворачиванием) в ДС нет; ближайший прецедент по механике — `Tooltip`/`Popover` в `sdds-core/uikit-compose` — не подходит по архитектуре (см. `design.md`), а сам компонент по природе специфичен для одного продукта и не должен попадать в общий `uikit-compose`.

## What Changes

- Новый компонент **`UpsellBubble`** добавляется в `tokens/plasma.homeds.compose` — по аналогии с `NumberPanel`: компонент вертикали, не часть `sdds-core/uikit-compose`.
- Публичный API — двухчастный: `UpsellBubbleTrigger` (иконка-значок, кладётся внутрь карточки устройства) + `UpsellBubbleHost` (монтируется один раз вокруг сетки устройств, владеет позиционированием и рендерит развёрнутый бабл).
- Позиционирование — собственный overlay в общем `Box`-родителе с сеткой (без системного `Popup`/окна). Трекинг позиции триггера идёт штатным layout-проходом Compose, без выделенной подсистемы отслеживания положения на экране.
- Форма бабла (тело + шейка + круг иконки) рисуется как единая анимируемая геометрия (`Path.op(..., PathOperation.Union)`, по мотивам приёма из `BasePopover.kt`, но без зависимости от кода `Popover`).
- Иконка-триггер анимированно переключается между звёздочкой и крестиком (кроссфейд/скейл); используются существующие иконки ДС (`ic_star_four_outline_16`, `ic_close_24`), новых иконок не требуется.
- Стейт-машина показа: Скрыт → Свёрнут → (клик) → Развёрнут (5 сек) → по таймауту → Свёрнут; из Развёрнутого по клику на крестик → Скрыт насовсем. Это два разных исхода закрытия, не единый `onDismissRequest`, как в `Tooltip`.
- Содержимое развёрнутого бабла — пользовательский `content`-слот (произвольный composable от вызывающей стороны), а не фиксированный набор текст/шеврон/индикатор. Компонент предоставляет слоту только цвет текста из стиля.
- Стилевой контракт компонента (`UpsellBubbleStyle`, `UpsellBubbleMotionStyle`) заводится по паттерну `NumberPanelStyle`/`NumberPanelMotionStyle` — вручную, без themebuilder/CMP-генератора (для vertical-only компонентов пайплайн генератора не применяется — `NumberPanel` тоже не генерируется).
- На первом этапе — **одна-единственная стилевая вариация `Default`**, без набора size/view-вариаций (полноценного макета с вариациями пока нет; при появлении дизайн-спеки размеры/варианты добавляются отдельным изменением).
- В песочницу `tokens/plasma.homeds.compose/app` добавляется `UpsellBubbleStory`.
- Компонент не содержит бизнес-логики: приоритет между статус-бейджами устройства и баблом апсейла, признак «есть новое предложение», персист «просмотрено» и переход на экран апсейла по клику — ответственность вызывающего приложения (передаются как параметры/колбэки).
- Компонент сознательно не защищается от перекрытия системными диалогами/шторками — это принятый риск, т.к. фолбэк на системный `Popup`/окно не предусмотрен (см. `design.md`, Non-Goals).

## Capabilities

### New Capabilities
- `homeds-upsell-bubble-component`: компонент `UpsellBubble` (Trigger + Host) — публичный API, стейт-машина показа/сворачивания/закрытия, анимация геометрии и иконки-триггера, позиционирование overlay без системного `Popup`, единственная стилевая вариация `Default`.

### Modified Capabilities
*(нет — в `openspec/specs/` не существует ранее задокументированной capability для компонентов `tokens/plasma.homeds.compose`, требования переносить неоткуда)*

## Impact

- **Модуль**: `tokens` (included build) → `tokens/plasma.homeds.compose` — новый компонент, стиль, motion-контракт, ручные style-bindings (аналог `NumberPanelStyles.kt`).
- **Публичный API**: новый публичный API вертикали `plasma.homeds.compose` (`UpsellBubbleTrigger`, `UpsellBubbleHost`, `UpsellBubbleStyle`) — additive, не затрагивает `sdds-core/uikit-compose` и другие бренд-токены.
- **Кодогенерация**: не затрагивается — компонент вне periметра themebuilder/CMP-генератора, как и `NumberPanel`.
- **Иконки**: новых ассетов не требуется, переиспользуются существующие `sdds-core/icons`.
- **Сэндбокс/демо**: `tokens/plasma.homeds.compose/app` — новая `UpsellBubbleStory`; `tokens/plasma.homeds.compose/integration` — screenshot-фикстура по аналогии с `PlasmaHomedsNumberPanelVariationsCompose.kt`.
- **Вне скоупа этого репозитория**: экран «Мой дом», сетка устройств, приоритет статус-бейджей, переход на экран апсейла, персист «нового предложения» — это код отдельного consumer-приложения, которое зависит от `tokens/plasma.homeds.compose` и в этом монорепо отсутствует. Изменение поставляет только сам компонент и его публичный контракт.
- **Валидация**: `./gradlew tokens:plasma.homeds.compose:test`, `tokens:plasma.homeds.compose:detekt`, `tokens:plasma.homeds.compose:spotlessApply`; сборка песочницы — `tokens:plasma.homeds.compose:app:assembleDebug`.
Loading
Loading