Skip to content

refactor(polish): match mockup spec for the bottom navigation bar#20

Merged
netqo merged 1 commit into
devfrom
polish/bottom-nav
May 27, 2026
Merged

refactor(polish): match mockup spec for the bottom navigation bar#20
netqo merged 1 commit into
devfrom
polish/bottom-nav

Conversation

@netqo
Copy link
Copy Markdown
Owner

@netqo netqo commented May 27, 2026

Summary

Replaces the Material 3 NavigationBar (own surface, indicator pill, icon tinting defaults) with a custom Row that mirrors the mockup bottomNav exactly (mockup/js/components.js):

  • nav: h-16, border-t border-line, bg-[#0B0B12], grid 5 cols
  • button: stacked icon + 9px tracked label, violet when active, muted otherwise
  • icon: 18dp, stroked (no fill), stroke-width 2

Each tab uses a custom vector drawable ported verbatim from the mockup SVG path data:

  • ic_tab_lobby - house
  • ic_tab_wallet - rect + clasp
  • ic_tab_history - clock
  • ic_tab_news - document with text lines
  • ic_tab_profile - head + shoulders

Drawables live in res/drawable/ and are tinted by Icon so the active/inactive color swap stays in Compose.

Self-review tweaks before pushing

  • Top border was drawn at y=0; drawLine centers strokes on the given coordinate so half of the 1dp line was clipped above the canvas. Offset by strokePx/2 to keep the full border visible.
  • The icon contentDescription was tab.label; the visible label below already announces the tab, so TalkBack was reading it twice. Set the icon to contentDescription = null.

No behavior change; the same callback fires on tab clicks and the visibility rule (PrimaryTab.routePaths) is untouched.

Test plan

  • ./gradlew :app:assembleDebug green
  • ./gradlew :app:testDebugUnitTest green (34/34, no regressions)
  • ./gradlew ktlintCheck detekt green
  • On-device: bottom bar matches the mockup screenshot 1:1
  • CI mirrors the local result

Replaces the Material 3 NavigationBar (which carried its own surface,
indicator pill and icon tinting defaults) with a custom Row that
mirrors the mockup bottomNav exactly (mockup/js/components.js):

  nav:    h-16, border-t border-line, bg-[#0B0B12], grid 5 cols
  button: stacked icon + 9px tracked label, violet when active,
          muted otherwise
  icon:   18dp, stroked (no fill), stroke-width 2

Each tab uses a custom vector drawable ported verbatim from the
mockup SVG path data: ic_tab_lobby (house), ic_tab_wallet (rect +
clasp), ic_tab_history (clock), ic_tab_news (document with text
lines), ic_tab_profile (head + shoulders). Drawables live in
res/drawable so the Icon composable can tint them by route activity
without per-tab Compose code.

Cleanups noted in self-review:
* Top border was drawn at y=0, which (because drawLine centers strokes
  on the given coordinate) left half of the 1dp line clipped. Offset
  by strokePx/2 so the entire border is visible.
* The icon contentDescription was set to the tab label, duplicating
  the visible label below for TalkBack users. Null it out so the
  tab is announced once via the Text content.

No behavior change; the same callback fires on tab clicks and the
visibility rule (PrimaryTab.routePaths) is untouched.
@netqo netqo merged commit e749b37 into dev May 27, 2026
3 checks passed
@netqo netqo deleted the polish/bottom-nav branch May 27, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant