Skip to content

The floating top bar fades under its hairline, and Term of the Day and the mini-game intro seal at 8 (10 Sep drop) #583

Description

@maximsan

Found reconciling the 10 September 2026 prototype drop (e914cf40: settings.jsx FloatTopbar/StickyHeaderChrome, dictionary-extras.jsx, screens.jsx GameIntroScreen, customize.jsx, index.html) against the app's floating top bar, scroll flag scope, Term of the Day, the mini-game intro and the paywall.

Rewritten 11 September 2026 at triage: of the four findings, two are already in the app and one is in an open PR. What is left is the fade on the floating bar and two thresholds.

What the design draws now

  1. A fade under the scrolled bar. Both the floating top bar and the sticky header chrome draw, below their hairline, a 22-high band from color-mix(in oklab, bg 88%, transparent) to transparent, opacity 1 when scrolled and 0 at rest, over 260 ms, so content never scrolls through a bare edge.
  2. Term of the Day and the mini-game intro seal at 8, not 40. Both moved onto FloatTopbar with useScrollFlag(8, …): their scroller is full-bleed to y=0, so a long page ran under the close control, the bookmark and the status bar before the default threshold.
  3. The paywall's scroll starts clear of the bar. FLOAT_PAD = 96 (was 64) at the top, 32 at the bottom; Roasty is 96 (was 112); the pitch list sits 14 below the title (was 18); the note under Maybe later opens at 26 (was 14).
  4. The bar caps the status-bar inset. lesson-topbar::before fills the 54 above the bar with the bar's own background and blur, so content scrolled past renders behind the bar, not the clock.

Where the app stands

  • 1 is half built. HeaderChrome — the tab header and every pushed page's back bar — already paints the band (fadeHeight 22, MoodColors.headerFade at 0.88, scaled by the scrolled progress over scrolledFade, reduced motion collapsing it to a cut; landed with Pages opened from a tab wear a stock Material bar, not the design's #513). FloatTopbar paints its own band and hairline instead of composing that chrome, so the five flows it fronts — Term of the Day, the mini-game intro, the paywall, lesson completion, module complete — still scroll through a bare edge.
  • 2 is not built. Both screens call ScrollFlagScope without a threshold and take the default scrollFlagThreshold of 40. The scope takes a threshold already.
  • 3 is in PR #592, open. It touches none of the files this ticket needs.
  • 4 is built on both bars. FloatTopbar's band and HeaderChrome's painted half are each sized bar-plus-inset and filled, so what scrolls past renders behind the bar. Nothing to do.

Agent Brief

This was generated by AI during triage.

Category: enhancement
Summary: The floating top bar draws the design's fade band by composing the shared header chrome, and Term of the Day and the mini-game intro seal at 8.

Current behavior:
FloatTopbar paints its own fill and hairline in a private band widget and draws no fade below the hairline. HeaderChrome draws the fade. The two bars fade their fill on the same ScrolledProgress but are two implementations. Term of the Day and the mini-game intro take the scroll flag's default threshold of 40, so a long page runs under the close control and the status bar before the bar takes chrome.

Desired behavior:

  • The floating top bar draws the 22-high fade below its hairline, at the same opacity curve as its fill: 0 at rest, 1 scrolled, over 260 ms, a cut under reduced motion. The design ties the fade's opacity to the same scrolled that switches the fill on, so the fade rides the fill: the sealed variant (the mini-game player, the flashcards — an app-side construct the design has no counterpart for) is filled from the first frame and draws the fade at full opacity from the first frame.
  • It gets there by composing HeaderChrome's painted half rather than adding a second gradient, so the two bars cannot drift again. The band still reaches under the status-bar inset, and the bar's 32px 1fr 32px control row and the pointer pass-through are unchanged.
  • Term of the Day and the mini-game intro pass a threshold of 8 to the scroll flag scope, quoted from the design as an OffToken. Every other scope keeps 40.

Key interfaces:

  • FloatTopbar — its private band widget goes; the painted half comes from HeaderChrome, with the fade riding the progress ScrolledProgress already supplies.
  • HeaderChrome — may need to expose the painted band and fade for a caller that lays its own controls over them; height stays the caller's.
  • ScrollFlagScope — no change; the two screens pass threshold.

Acceptance criteria:

  • The floating bar draws the fade band, scrolled only, and a widget test on one floating-bar screen pins its height, its opacity at rest and scrolled, and that it is a cut under reduced motion
  • Term of the Day and the mini-game intro seal at 8 (widget test on each), and no other scope's threshold changes
  • The paywall's top and bottom clearance, its Roasty size and its two gaps match the drop — PR #592: FLOAT_PAD 96 at the top, 32 at the foot, Roasty 96, the pitch 14 below the title and the note 26 below Maybe later; driven on an iPhone 16 Pro simulator
  • dart format, flutter analyze, the metrics gate and the suite pass, with a changelog bullet, and Term of the Day and the mini-game intro are each shown scrolled in a screenshot

Out of scope:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    design-parityCloses a finding in the app-vs-prototype divergence registerenhancementNew feature or requestfeature-buildA screen or mechanic the app does not have yetready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions