Skip to content

User instructions modal (issue #2885 item 3)#2891

Draft
lifeart wants to merge 2 commits intomasterfrom
feat/user-instructions-modal-2885
Draft

User instructions modal (issue #2885 item 3)#2891
lifeart wants to merge 2 commits intomasterfrom
feat/user-instructions-modal-2885

Conversation

@lifeart
Copy link
Copy Markdown
Collaborator

@lifeart lifeart commented Apr 21, 2026

Summary

Adds the "how to use the site" feature from issue #2885 item 3:

  • A 4-step overview modal triggered from the global header on every authenticated route.
  • A contextual mini-help modal inside the fullscreen exercise overlay that only explains the three playback buttons (user is already past the "pick a topic" stage there).
  • Updated tooltips on the exercise-list squares (available vs locked) — also requested in the same issue.

Components

File Purpose
app/components/ui/instructions-dialog/index.gts Shared shell built on the native <dialog> element (modeled on ui/confirm-dialog). Focus trap, ESC-to-close, backdrop-click-to-close come for free.
app/components/instructions-modal/index.gts 4-step overview content. Mounted in <Header> between <GlobalTimer> and <XpBadge>.
app/components/exercise-playback-help/index.gts Playback-only content. Mounted in templates/group/series/subgroup/exercise.gts next to the close-X.
app/components/ui/exercise-button/index.gts Tooltip now uses the two new keys (exercise_button.tooltip_available / tooltip_locked) based on @isAvailable.

Copy accuracy

A domain reviewer walked the author's original Russian spec against the current code:

  • Dropped the "75%" threshold claim: app/schemas/exercise.ts isCompleted is binary. Wording softened to "когда правильных ответов наберётся достаточно" / "when you finish a task successfully".
  • Dropped the "green check with exclamation" state: it does not exist in the current UI.
  • Listen→Interact auto-advance and Interact→Solve manual transition match the behaviour introduced in PR Exercise UX fixes (issue #2885 items 4, audio freeze, page update) #2889.

Accessibility

  • Native <dialog> element (inherent role="dialog", ESC closes).
  • aria-modal, aria-labelledby<h2> inside.
  • Trigger has aria-haspopup="dialog", aria-expanded, aria-controls, aria-label.
  • Focus returns to the trigger when the dialog closes.
  • All interactive elements meet a 44×44 touch-target minimum.
  • Icon + label at every breakpoint (no icon-only variant — audience includes seniors and 7-year-olds per UX review).

Out of scope (follow-ups)

  • Auto-open on first visit (needs a server-persisted hasSeenInstructions flag; shared-device rehab contexts mean localStorage is wrong).
  • Drawer/bottom-sheet mobile variant.
  • Per-step icons and screenshots.
  • Red-exclamation icon for <75% completion — backend flag doesn't exist.
  • Analytics event for "instructions opened".

Notes

  • frontend/patches/ exists locally with pnpm-format patch files left over from an earlier exploration. Not touched in this PR. Either keep or revert in a follow-up — current master has patch-package as its postinstall, so the untracked files do not affect CI.
  • Local pnpm test:ember currently fails on pristine master with Could not find module 'calculate-cache-key-for-tree' — reproducible on master without this PR's changes. CI will show whether this is a local-only issue.

Test plan

  • Click the new "Как заниматься" button in the header → 4-step dialog opens with the full walkthrough.
  • Press ESC → dialog closes, focus returns to the trigger.
  • Open a task → click the help-icon next to the close-X → short playback-steps dialog opens.
  • Hover a locked exercise square → new locked tooltip ("Это задание пока недоступно…"). Hover an available one → new available tooltip.
  • Switch locale to en-us → dialog renders English copy.

🤖 Generated with Claude Code

Addresses item 3 of issue #2885: a "how to use the site" overview for
first-time users and an exercise-screen contextual help that explains
the three playback steps.

## What this adds

- `<InstructionsModal>` — a four-step overview ("pick a topic →
  open a task → run Listen/Interact/Solve → see the results") triggered
  from the global header on every authenticated route. Icon + label
  ("Как заниматься" / "How to practise") visible at every breakpoint
  (no icon-only mobile variant — users include seniors and 7-year-olds).
- `<ExercisePlaybackHelp>` — a contextual mini-help in the fullscreen
  exercise overlay that only covers the three playback buttons, since
  the user is already past the "pick a topic" stage. Placed next to the
  existing close-X, mirror-positioned.
- `<UiInstructionsDialog>` — shared shell built on the native <dialog>
  element (modeled on `ui/confirm-dialog`), which gives focus trap,
  ESC-to-close, and backdrop-click-to-close for free. Both modals
  above are thin content wrappers around this shell.
- `UiExerciseButton` tooltip: replaced the old "Exercise 3" level-only
  title with the two new strings (`exercise_button.tooltip_available`
  for unlocked tasks, `exercise_button.tooltip_locked` for locked
  tasks) — also requested in the same issue.

## Copy decisions (domain review)

- Dropped the author's "75%" threshold claim. `app/schemas/exercise.ts`
  `isCompleted` is binary (all tasks or nothing). Wording softened to
  "когда правильных ответов наберётся достаточно" so the copy survives
  any future backend threshold changes.
- Dropped the "green check with exclamation mark" state — it does not
  exist in the current UI.
- Confirmed Listen→Interact auto-advances and Interact→Solve is
  manual (matches PR #2889 behavior).

## Accessibility

- `<dialog>` native element → inherent `role="dialog"`, ESC closes,
  backdrop visible.
- `aria-modal="true"`, `aria-labelledby` pointing at an <h2> inside.
- Trigger carries `aria-haspopup="dialog"`, `aria-expanded`,
  `aria-controls`, `aria-label`.
- Focus is restored to the trigger when the dialog closes.
- All interactive elements meet 44×44 touch-target minimum.

## Out of scope

- Auto-open on first visit — needs a server-persisted
  `hasSeenInstructions` flag. Devices are shared at rehab centres, so
  localStorage would be wrong.
- Drawer/bottom-sheet mobile variant — centered modal for v1, visual
  follow-up possible.
- Per-step icons and screenshots (asset work).
- Red-exclamation icon for <75% completion (backend flag doesn't exist).
- Analytics for "instructions opened".

## Tests

- `instructions-modal/component-test.gjs` — trigger renders, dialog
  opens with the four steps, ESC/X/OK close, aria metadata correct,
  Russian locale renders Russian title.
- `exercise-playback-help/component-test.gjs` — trigger renders,
  dialog opens with the playback-specific title, close dismisses it.
- `ui/exercise-button-test.gjs` — tooltip switches between
  `exercise_button.tooltip_available` and `tooltip_locked` based on
  `@isAvailable`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

Gradle Unit and Integration Test Results

523 tests  ±0   521 ✔️ ±0   39s ⏱️ -1s
116 suites ±0       2 💤 ±0 
116 files   ±0       0 ±0 

Results for commit 2ee509b. ± Comparison against base commit 92b150e.

♻️ This comment has been updated with latest results.

`setupIntl` in the rendering-test env returns the `t:<key>` placeholder
instead of loading real translations (same pattern documented on
`doctor-feedback/component-test.gjs` and used across the existing
suite). Asserting full English strings fails in CI.

Switch all tooltip and title assertions to the `t:KEY` placeholder
form. Drop the redundant ru-ru locale module — placeholders do not
change with locale, so the test was duplicative of the en-us case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Frontend test coverage: 72.56% (+0.16% compared to 72.4% on base)

@sonarqubecloud
Copy link
Copy Markdown

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