Skip to content

[PLAN] Create a Next Task component #247

Open

Description

@goodbounties-nanoclaw-agent

[PLAN] Create a Next Task component

Type: Task
Parent: #246 ("[Feature] Create a Next Task component")

Plan v11. Replaces the earlier event-bus plan. #246 is unchanged. AI-executed PR: #248.

Scope

A reusable modal that opens after a successful action. First consumer: the claim flow in CitizenClaimWidget. Not in scope: analytics tooling, a content store or CMS, PR #191's native-redirect research. The component only exposes simple extension points: a content prop and onShown / onClicked / onDismissed callbacks.

Decisions (Laurence, Oct 21 to Nov 5)

  • Controlled component, no event bus. The host (or the widget) passes open, content and onClose. useNextTaskTrigger and the window event bus are removed.
  • CTA navigation: the host handles it, or we use Anchor.
    • resolveNavigation passed: the CTA is a Button and the host owns navigation (e.g. in-app GoodWallet routes). No external fallback.
    • Not passed: the CTA is Anchor with ctaTarget, after an http(s)-only check.
    • Handler throws or rejects, or the URL is rejected: show the error and keep the drawer open so the user can retry or dismiss (Laurence, Nov 5). No silent failure. PR Feature: Next Task component (NextTaskModal) #248 still closes the drawer after a failure; fixed in issue [GoodBounty] Finalize Next Task component PR (#248) #276.
  • resolveNavigation type: (ctaTarget: string) => void | Promise<void>.
  • No react-native import in NextTaskModal (Tamagui Image; Anchor handles native links).
  • Anchor mode must carry the primary CTA prominence shown in the design reference (Laurence, Nov 5, replacing the Nov 4 "link is fine" decision). PR Feature: Next Task component (NextTaskModal) #248 still renders a plain link; fixed in the contributor issue [GoodBounty] Finalize Next Task component PR (#248) #276.
  • Dismiss reason: the shared Drawer has one onClose, so the X button and an overlay press both report 'overlay'. Accepted as a known limitation (Oliseh, Nov 4).
  • Copy is integrator-configurable through the same content JSON (Laurence, Nov 5, replacing the earlier "fixed copy" draft default): optional headline, supportingCopy, recommendedLabel, skipLabel and statusLabel, falling back to the in-app defaults ("One good next step", etc.) when unset. PR Feature: Next Task component (NextTaskModal) #248 still hardcodes them; fixed in issue [GoodBounty] Finalize Next Task component PR (#248) #276. Drawer is used as elsewhere in the repo.
  • NextTaskModal and NextTaskCtaCard live in packages/ui. Tests live in tests/design-system/smoke.spec.ts.

Behavior

  • Single-chain claim: the modal opens after the success toast and onClaimSuccess, outside the claim try/catch, so a Next Task failure cannot report a successful claim as failed.
  • Multi-chain claimAll: opens once, only if at least one claim succeeded, even if refresh() throws.
  • No content: nothing renders. If content is removed while open, the modal closes without calling onDismissed.
  • Callbacks are wrapped so a throwing integrator callback cannot break the claim result or the modal.
  • Custom element (citizen-claim-widget): nextTaskContent and nextTaskResolveNavigation are properties; next-task-shown, next-task-clicked and next-task-dismissed are events.

Acceptance criteria

AI-executed PR #248 (checked = done and evidenced in the PR):

  • NextTaskModal / NextTaskCtaCard built once in packages/ui.
  • Controlled by open / content / onClose; event bus removed.
  • Nothing renders when content is missing.
  • Host handler mode (Button) and Anchor mode, with the http(s) check.
  • Handler throw, handler rejection and rejected URL each show an error toast.
  • Dismiss closes with no navigation and fires onDismissed.
  • onShown / onClicked / onDismissed exist and failures are contained.
  • Claim flow wired for single-chain and multi-chain, onClaimSuccess / onClaimError unchanged.
  • Custom element props and events added.
  • Playwright specs and baselines (desktop and mobile) in tests/design-system/.
  • No new tsc errors (9 pre-existing, same as main).

Left for the human contributor ([GoodBounty] issue #276):

  • Match the design reference closely (primary CTA prominent in both modes).
  • Responsive: usable on mobile, small screens, landscape and desktop, with realistic copy.
  • Navigation failure keeps the drawer open (error shown, retry or dismiss).
  • Integrator-configurable copy: headline, supporting line, badge, skip and status labels via content, with defaults.
  • Test the real CitizenClaimWidget flow (drawer opens after a successful claim, CTA works, dismiss works), plus focused responsive and failure regression tests.

Out of scope: special Shadow DOM handling, a shared portal/Drawer redesign.

Not part of this plan or its PR: native device/simulator verification. GoodWidget and Storybook have no real-native test setup today, so this is documented separately as a nice-to-have (a testing environment for real native devices) and left to the QA process.

Deferred to a separate testing workstream and NOT marked as passed by this PR: broader test-quality/coverage criteria (extra Playwright states beyond the navigation-mode and error-toast cases, overlay dismiss, and the 9 pre-existing tsc errors, which stay at main's baseline).

Human-reviewer checklist

  • The http(s)-only URL check is enough for Anchor mode, or a stricter rule (e.g. a domain allowlist) is wanted if content ever comes from a less-trusted source.
  • resolveNavigation (void | Promise<void>, errors become a toast) matches what host integrators expect.
  • "No UI when content is missing" is acceptable as is.
  • The optional copy fields in content (with defaults) are the right way for integrators to choose what to display.
  • Anchor no longer registers in the theme manifest (needed so onPress works on native); acceptable for a shared component.
  • Both modes show a primary CTA as in the design reference; dismiss reasons are limited as described above.
  • PR Citizen-claim-widget: contract-sourced how-it-works copy (invite rewards) #191's native-redirect overlap is still tracked for Laurence and is not resolved by this plan.
  • Storybook output matches the design reference in light and dark themes, at mobile width.
  • packages/ui is the right home vs. a dedicated package.
  • The claim wiring point in CitizenClaimWidget.tsx is correct and does not double-fire across single-chain and multi-chain.

Activity

  1. changed the title [-][DRAFT][PLAN] Create a Next Task component[/-] [+][PLAN] Create a Next Task component[/+] on Nov 4, 2026
  2. moved this from Prepare AI Task to In Progress in GoodBountieson Nov 9, 2026
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

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions