Files
Bill Ballou 7940050196 Add mobile floating banners for specialization status and course selection progress
On mobile, the single-column layout makes it easy to lose context when
scrolling between the specializations and course selection panels. This adds
two floating banners that appear via IntersectionObserver:

- Top banner: summarizes specialization statuses (achieved/achievable/missing/unreachable)
- Bottom banner: shows course selection progress (N/12 selected)

Both slide in/out with CSS transitions and scroll to their respective
sections on tap. Only rendered on mobile viewports (max-width: 639px).
2026-02-28 22:27:07 -05:00

4.1 KiB

ADDED Requirements

Requirement: Banner appears when specializations scroll out of view

The system SHALL display a floating summary banner fixed to the top of the viewport on mobile when the specializations section is no longer visible in the viewport.

Scenario: User scrolls past specializations on mobile

  • WHEN the user is on a mobile viewport (max-width: 639px) and scrolls down until the specializations section leaves the viewport
  • THEN a fixed banner SHALL slide in from the top of the screen displaying specialization status counts

Scenario: User scrolls back up to specializations on mobile

  • WHEN the banner is visible and the user scrolls up until the specializations section re-enters the viewport
  • THEN the banner SHALL slide out of view (upward)

Scenario: User is on tablet or desktop

  • WHEN the viewport width is greater than 639px
  • THEN the banner SHALL NOT render at all

Requirement: Banner displays status counts with color-coded badges

The banner SHALL show the count of specializations in each status category using the same color scheme as the specialization list: achieved (green), achievable (blue), missing required (amber), and unreachable (gray).

Scenario: Multiple statuses present

  • WHEN the banner is visible and statuses are: 2 achieved, 5 achievable, 1 missing required, 6 unreachable
  • THEN the banner SHALL display four badges: "2 Achieved" in green, "5 Achievable" in blue, "1 Missing Req." in amber, "6 Unreachable" in gray

Scenario: Zero count for a status category

  • WHEN a status category has zero specializations (e.g., 0 missing required)
  • THEN that category's badge SHALL still be displayed with a count of 0

Scenario: Statuses update after course selection change

  • WHEN the user selects or deselects a course while the banner is visible
  • THEN the banner status counts SHALL update to reflect the new optimization result

Requirement: Banner animates in and out

The banner SHALL animate its appearance and disappearance using a vertical slide transition.

Scenario: Banner slides in

  • WHEN the specializations section scrolls out of the viewport on mobile
  • THEN the banner SHALL transition from translateY(-100%) to translateY(0) over 200ms with ease-out timing

Scenario: Banner slides out

  • WHEN the specializations section scrolls back into the viewport on mobile
  • THEN the banner SHALL transition from translateY(0) to translateY(-100%) over 200ms with ease-out timing

Requirement: Tapping banner scrolls to specializations

The banner SHALL be tappable. Tapping it SHALL smoothly scroll the page so the specializations section is visible at the top of the viewport.

Scenario: User taps the banner

  • WHEN the banner is visible and the user taps anywhere on it
  • THEN the page SHALL smooth-scroll to bring the specializations section to the top of the viewport

Scenario: Banner hides after scroll completes

  • WHEN the user taps the banner and the page scrolls to the specializations section
  • THEN the banner SHALL slide out as the specializations section becomes visible (via the standard intersection trigger)

Requirement: Banner renders above all other content

The banner SHALL use position: fixed with z-index: 1000 to ensure it layers above all other page content.

Scenario: Banner overlaps page content

  • WHEN the banner is visible
  • THEN it SHALL be rendered at position: fixed; top: 0 spanning the full viewport width, above all other elements

Requirement: Banner uses consistent styling

The banner SHALL use inline React.CSSProperties consistent with the existing codebase convention, and SHALL reuse the exported STATUS_STYLES color definitions from the specialization ranking component.

Scenario: Status colors match specialization list

  • WHEN the banner displays status badges
  • THEN the badge colors SHALL exactly match the STATUS_STYLES used in the specialization ranking rows (achieved: #16a34a, achievable: #2563eb, missing_required: #d97706, unreachable: #9ca3af)