67 lines
4.5 KiB
Markdown
67 lines
4.5 KiB
Markdown
# 2026-09-19 — Мобильный UI-кит переведён на iOS (Cupertino)
|
||
|
||
## Запрос
|
||
Widgetbook запустился, но Material-компоненты визуально не устроили. Задача — сделать
|
||
компоненты «из iOS kit».
|
||
|
||
## Что сделано
|
||
|
||
### Токены и тема (`mobile/lib/theme/`)
|
||
- `tokens.dart` переписан под Apple HIG: семантические цвета (`label`, `secondaryLabel`,
|
||
`separator`, `opaqueSeparator`, `groupedBackground`, `groupedSurface`, `barBackground`)
|
||
и системная палитра (`systemRed/Orange/Green/Gray/Gray3/Gray5/Gray6`) объявлены как
|
||
`CupertinoDynamicColor.withBrightness` — light/dark резолвится самим фреймворком через
|
||
`AppColors.of(context, color)`.
|
||
- Бренд-тинт остался зелёным (`accent` = #12885A / #3CD68C в тёмной) и подменяет systemBlue.
|
||
- Типографика — шкала SF Pro: largeTitle 34 … caption2 11 с нативными letterSpacing.
|
||
- Размеры контролов: 50 / 44 / 34 pt, hairline 0.5, радиусы 6/10/12/16/capsule.
|
||
- `app_theme.dart` теперь возвращает `CupertinoThemeData` (`buildLightTheme` /
|
||
`buildDarkTheme`), шрифт — Inter через google_fonts как кросс-платформенная замена SF Pro
|
||
(на Windows/web SF недоступен).
|
||
|
||
### Компоненты (`mobile/lib/ui/`)
|
||
Material-версии удалены, вместо них Cupertino:
|
||
- atoms: `AppButton` (filled/tinted/gray/plain/destructive × large/medium/small),
|
||
`AppTextField` (CupertinoTextField + error/prefix/clear), `AppText` (именованные
|
||
конструкторы по шкале iOS) + `AppSectionHeader`, `AppIcon` + `AppIconBadge`
|
||
(Settings-style скруглённый квадрат).
|
||
- molecules: `AppListSection` (inset-grouped, header/footer, hairline с indent),
|
||
`AppListTile` (leading/value/chevron, press-highlight, destructive), `AppSwitchRow`
|
||
(CupertinoSwitch), `AppCard`, `AppChip` (капсула), `AppAvatar`.
|
||
- navigation: `AppNavBar` (реализует `ObstructingPreferredSizeWidget`, есть subtitle),
|
||
`AppLargeNavBar` (`CupertinoSliverNavigationBar`), `AppTabBar` (наследник
|
||
`CupertinoTabBar`, чтобы отдавать в `CupertinoTabScaffold`), `AppSegmentedControl`
|
||
(`CupertinoSlidingSegmentedControl`), `AppAlert` + `showAppAlert` + `showAppActionSheet`.
|
||
- feedback: `AppSpinner` (`CupertinoActivityIndicator`), `AppProgressBar` (4pt капсула),
|
||
`AppSkeleton` / `AppSkeletonRow`, `AppToast` + `showAppToast` (blur-капсула через
|
||
OverlayEntry — в iOS нет SnackBar).
|
||
- screens: Feed (large title + сегменты + группы + empty/loading), Detail (hero-сумма,
|
||
прогресс, группа параметров, кнопки), Profile (Settings-подобный экран со свитчами).
|
||
- `main.dart` переведён на `CupertinoApp` + `CupertinoTabScaffold`.
|
||
|
||
### Widgetbook (`mobile/widgetbook/`)
|
||
- `Widgetbook.cupertino` + `CupertinoThemeAddon` вместо material-варианта.
|
||
- Новый `lib/support/preview.dart` — `IosPreview` кладёт use-case на grouped-фон,
|
||
чтобы карточки и разделители читались как в приложении.
|
||
- Каталог: Atoms (Button/TextField/Typography/Icons), Molecules (Card/ListTile/SwitchRow/
|
||
Chip/Avatar), Navigation (NavBar/TabBar/SegmentedControl/Alert), Feedback (Progress/
|
||
Skeleton/Toast), Screens (Feed/Detail/Profile) — 42 use-case.
|
||
- Knobs: добавлены `knobEnum` и `knobTint` (дропдаун по системным тинтам), убран
|
||
deprecated `knobs.list`.
|
||
|
||
### Тесты
|
||
`widgetbook/test/catalog_smoke_test.dart` больше не проверяет только структуру: каждый
|
||
use-case пампится в light и dark внутри `WidgetbookScope` (knobs читают `WidgetbookState`
|
||
из контекста, иначе падает «No Widgetbook found in the context»). В тестах отключён
|
||
`GoogleFonts.config.allowRuntimeFetching` и вызван `TestWidgetsFlutterBinding.ensureInitialized()`.
|
||
|
||
## Результат
|
||
- `flutter analyze` (mobile + widgetbook) — 0 issues.
|
||
- `flutter test` — 84 теста в widgetbook + 1 в приложении, всё зелёное.
|
||
|
||
## Запуск
|
||
```powershell
|
||
cd mobile\widgetbook
|
||
.\run.ps1 -Device windows
|
||
```
|