Skip to content

Float the Questionnaire Action and Add an Eraser to the Annotation Editor - #89

Merged
lukaskollmer merged 1 commit into
account-on-the-page-scaffoldfrom
questionnaire-on-the-page-scaffold
Sep 21, 2026
Merged

lukaskollmer merged 1 commit into
account-on-the-page-scaffoldfrom
questionnaire-on-the-page-scaffold

Conversation

@PSchmiedmayer

@PSchmiedmayer PSchmiedmayer commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

♻️ Current situation & Problem

The questionnaire's action was the last row of the form, so a long page hid it below the fold and the navigator had to scroll for it before every check. The large navigation title cut long names and did not match the other pages. In the image annotation the only way to correct a stroke was to remove all of them.

⚙️ Release Notes

Heart check-inMissing answerScoreText and choiceNumbersImage annotation
Heart check-inMissing answerScoreText and choiceNumbersImage annotation
  • The action floats over the foot of every page, follow-up sheets and the completion page included.
  • A missing answer tints its card and says so with the shared BlockingMessage, the way the rest of Grove does since Share One Page Scaffold and Blocking Feedback Across the Views #87.
  • Each page opens with PageHeader in its compact spacing, aligned with the cards, and the name rises into the bar as the page scrolls. Group and section captions sit under it as before.
  • The annotation editor gets an eraser as a tool at the bottom trailing edge; the region chips scroll past it and fade out. Undo and redo cover erasing; the trash button and its dialog are gone.
  • QuestionnaireSheetNavigator reads a page's name with pageTitle, isTitled(_:) and waitUntilTitled(_:timeout:); waitUntilNavigationBarShows and scrollToPrimaryAction are gone. Follow-up questions are tapped only once they are reachable below the bar, which fixes the follow-up tests.
  • The test app gains a heart check-in instrument for the documentation.
  • A top-level group's SDC enableWhenExpression gates the items it holds, the way an item's own does; the FHIR conversion dropped it before.

📚 Documentation

The questionnaire page opens on the heart check-in and shows one page per family of question kinds.

✅ Testing

The questionnaire UI suite and unit legs on iOS and the macOS unit leg.

Code of Conduct & Contributing Guidelines

By creating and submitting this pull request, you agree to follow our Code of Conduct and Contributing Guidelines:

Copilot AI lite review requested due to automatic review settings September 7, 2026 17:53
@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 83bf6479-1c67-4787-ac96-05bd55d0f9a3


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

It introduces downstream-breaking removals in a public UI-test helper API and appears to remove/add doc screenshot resources without the repo’s usual .license sidecars.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates GroveQuestionnaire’s questionnaire page UX to match the app-wide “shared header + floating bottom action” pattern, improves the image annotation editor with an eraser workflow, and refreshes the UI-test and documentation scaffolding to reflect the new behavior.

Changes:

  • Move the questionnaire primary action from an in-form last row to a floating bottom action (including the completion page) and introduce a rising in-content page title (PageHeader).
  • Add an eraser tool to image annotation (replace “Remove all” flow), update PencilKit tooling to support non-inking tools, and adjust UI tests accordingly.
  • Update UI-test navigation/title assertions and add a scripted screenshot-capture UI test plus new documentation screenshots/markdown.
File summaries
File Description
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/TestAppUITests.swift Updates questionnaire “presented + titled” wait helper to new title API.
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/QuestionKindTests.swift Updates annotate-image UI test to exercise eraser + undo workflow.
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/PrimaryActionTests.swift Adjusts expectations for floating primary action and renames a test to match behavior.
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/PageLayoutTests.swift Switches from nav-bar-only title checks to isTitled and tightens title repetition assertions.
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/DocumentationScreenshots.swift Adds gated UI test to drive scripted documentation screenshot capture.
Tests/GroveQuestionnaireTests/UITests/TestAppUITests/BasicTests.swift Removes now-unnecessary scrolling to reach primary action.
Tests/GroveQuestionnaireTests/UITests/TestApp/Routes/SwiftDSLRoute.swift Adds Heart Check-In instrument to Swift DSL examples (for docs entry state).
Tests/GroveQuestionnaireTests/UITests/TestApp/Questionnaires/QuestionKinds.swift Makes date/time demo questions optional for documentation walkthrough flow.
Tests/GroveQuestionnaireTests/UITests/TestApp/Questionnaires/HeartCheckIn.swift Introduces Heart Check-In demo instrument used for docs/testing.
Sources/XCTGroveQuestionnaire/QuestionnaireSheetNavigator+Scanning.swift Adds reachability helper to avoid taps landing under the nav bar.
Sources/XCTGroveQuestionnaire/QuestionnaireSheetNavigator+Question.swift Uses reachability scan for taps; updates follow-up waits to use waitUntilTitled.
Sources/XCTGroveQuestionnaire/QuestionnaireSheetNavigator.swift Adds page-title reading/waiting API; removes primary-action scrolling assumptions for floating action.
Sources/GroveQuestionnaire/UI/View+FormActionRow.swift Removes obsolete “action as last form row” helper.
Sources/GroveQuestionnaire/UI/Tasks/TaskView+Choice.swift Removes follow-up navigation title/header chrome to align with new page title pattern.
Sources/GroveQuestionnaire/UI/TaskRun.swift Adjusts group heading suppression to compare against page title.
Sources/GroveQuestionnaire/UI/SwiftUI+Title.swift Removes custom navigation title/subtitle helper in favor of PageHeader/rising title.
Sources/GroveQuestionnaire/UI/QuestionnaireSheet.swift Updates module docs to reflect floating action and rising title behavior.
Sources/GroveQuestionnaire/UI/QuestionnaireSectionView.swift Adds PageHeader title section + floating primary action; refactors card rendering; updates missing-answer messaging.
Sources/GroveQuestionnaire/UI/CompletionPage.swift Moves Done button into floating actions inset.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/ZoomableImageAnnotationView.swift Generalizes tool type to support eraser (any PKTool).
Sources/GroveQuestionnaire/Tasks/AnnotateImage/ImageAnnotationView.swift Updates CanvasView integration for any PKTool and disables tool picker.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationRegionPicker.swift Adds eraser button, trailing fade, and selection behavior for erasing vs region selection.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationPreviewImage.swift Updates preview tool initialization to match new tool typing.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationHistoryController.swift Removes “remove all actions” support (trash workflow removed).
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationEraserButton.swift Adds eraser button component with accessibility identifier/selection traits.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationEditorCanvas.swift Refactors editor canvas inputs to receive tool + drawing-enabled state.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotationDrawingStyle.swift Adds eraser tool generation sized relative to stroke width.
Sources/GroveQuestionnaire/Tasks/AnnotateImage/AnnotateImageSheet.swift Replaces trash/reset flow with eraser + undo/redo; wires tool selection state.
Sources/GroveQuestionnaire/Resources/Localizable.xcstrings Removes reset-related strings; adds “Eraser”.
Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview~dark.png.license Removes license sidecar for screenshot resource.
Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview.png.license Removes license sidecar for screenshot resource.
Sources/GroveQuestionnaire/GroveQuestionnaire.docc/QuestionKinds.md Adds documentation screenshots for question kinds and annotate-image/custom kinds.
Sources/GroveQuestionnaire/GroveQuestionnaire.docc/GroveQuestionnaire.md Expands overview with multiple screenshots and updated narrative.
Sources/GroveQuestionnaire/GroveQuestionnaire.docc/AuthoringQuestionnaires.md Adds screenshot callout for score/conditional behavior section.
Review details
  • Files reviewed: 34/50 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Sources/XCTGroveQuestionnaire/QuestionnaireSheetNavigator.swift
Comment thread Sources/XCTGroveQuestionnaire/QuestionnaireSheetNavigator.swift
Comment thread Sources/GroveQuestionnaire/UI/QuestionnaireSectionView.swift Outdated
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 5f67a8b to 5e9278a Compare September 7, 2026 18:07
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 5e9278a to ef69da1 Compare September 7, 2026 18:55
@PSchmiedmayer PSchmiedmayer changed the title Put the Questionnaire Pages on the Shared Header and Floating Action Float the Questionnaire Action and Add an Eraser to the Annotation Editor Sep 7, 2026
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from ef69da1 to ec23e36 Compare September 7, 2026 21:00
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from ec23e36 to 9cdea62 Compare September 8, 2026 06:35
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 9cdea62 to 8fc1e52 Compare September 8, 2026 13:58
@github-project-automation github-project-automation Bot moved this to Todo in Grove Sep 8, 2026
@PSchmiedmayer PSchmiedmayer added documentation Improvements or additions to documentation enhancement New feature or request labels Sep 8, 2026
@PSchmiedmayer PSchmiedmayer self-assigned this Sep 8, 2026
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 8fc1e52 to e1618db Compare September 9, 2026 02:50
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from e1618db to 1bdd83a Compare September 9, 2026 04:06
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 1bdd83a to 1f38003 Compare September 9, 2026 04:36
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 1f38003 to 0d73409 Compare September 9, 2026 04:42
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from 0d73409 to fe14a9b Compare September 9, 2026 04:46
@PSchmiedmayer PSchmiedmayer added this to the 0.3.0 milestone Sep 9, 2026
@PSchmiedmayer
PSchmiedmayer force-pushed the questionnaire-on-the-page-scaffold branch from fe14a9b to 191c1a0 Compare September 10, 2026 02:39
@PSchmiedmayer
PSchmiedmayer removed this pull request from stack #92 September 11, 2026 16:15
@PSchmiedmayer
PSchmiedmayer added this pull request to stack #98 September 11, 2026 16:15
@PSchmiedmayer PSchmiedmayer moved this from Todo to In Progress in Grove Sep 13, 2026

@lukaskollmer lukaskollmer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@lukaskollmer
lukaskollmer merged commit 78c685c into main Sep 21, 2026
30 of 37 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Grove Sep 21, 2026
@lukaskollmer
lukaskollmer deleted the questionnaire-on-the-page-scaffold branch September 21, 2026 14:48
lukaskollmer pushed a commit that referenced this pull request Sep 21, 2026
### ♻️ Current situation & Problem

Onboarding, account setup, consent and the questionnaire each built
their own page: their own title, their own footer, their own idea of
what a missing answer looks like. Validation drew a red box inside the
grey card it sat on, the questionnaire and consent tinted their cards
each in their own way, and a page that had to be read to the end looked
nothing like a page with a button. The documentation showed screenshots
from different eras, and the walks that regenerate them ran inside the
CI suites.

### ⚙️ Release Notes

<table><tr><td align="center"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Welcome~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Welcome.png"
width="200" alt="Page with floating actions"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/ImageHeader~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/ImageHeader.png"
width="200" alt="Header with a symbol"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveOnboarding/GroveOnboarding.docc/Resources/ScrolledTitle~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveOnboarding/GroveOnboarding.docc/Resources/ScrolledTitle.png"
width="200" alt="Title risen into the bar"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Validation~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Validation.png"
width="200" alt="Blocking feedback"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveLLMOpenAI/GroveLLMOpenAI.docc/Resources/APITokenStep~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveLLMOpenAI/GroveLLMOpenAI.docc/Resources/APITokenStep.png"
width="200" alt="LLM setup step"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Tiles~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/page-scaffold/Sources/GroveViews/GroveViews.docc/Resources/Tiles.png"
width="200" alt="Tiles"></picture></td></tr><tr><td
align="center"><sub>Page with floating actions</sub></td><td
align="center"><sub>Header with a symbol</sub></td><td
align="center"><sub>Title risen into the bar</sub></td><td
align="center"><sub>Blocking feedback</sub></td><td
align="center"><sub>LLM setup step</sub></td><td
align="center"><sub>Tiles</sub></td></tr></table>

- GroveViews gets the page scaffold every full-page step uses:
`PageView` with a header, scrolling content and a footer that floats
over it, `PageHeader` with an optional symbol and a `spacing` option for
a header under a navigation bar, and `PageActions` with
`ActionButtonRole` and `actionButtonStyle(_:)`. The pieces are modifiers
too: `floatingActions`, `fadesIntoBottomEdge`, `risesIntoNavigationBar`
with `acceptsRisingTitle` (measured in global coordinates, so it also
works on a form that recycles its rows), and `softScrollEdge` for lists
under a bar. GroveOnboarding keeps `OnboardingInformationView` and
`SequentialOnboardingView`; `OnboardingView` is an alias of `PageView`
with the areas initialiser. The LLM setup steps move over here; account,
consent and the questionnaire follow in #88, #90 and #89.
- One language for something that still needs the participant:
`BlockingMessage`, and `reportsBlocking` on the control with
`highlightsBlockingContent` on its row or card, so the red is painted in
the container's own shape. `VerifiableTextField` uses it here; the
questionnaire and consent cards adopt it in #89 and #90.
- `Scripts/documentation-screenshots.sh` captures through RocketSim and
a `snapshot` directive installs a snapshot-test reference for views only
a snapshot renders. The walks skip themselves unless the script runs
them. Every catalogue except chat, LLM, account, consent and the
questionnaire is regenerated here, with inline images on the public
views.
- Textual 0.6.4, `ProgressiveBlur` moves from the chat to GroveViews,
and lists under a bar get the soft edge.
- The questionnaire navigator taps a row only once it is reachable below
the bar, and the consent test helper drags a picker back out from under
it: with a floating footer both used to tap the bar instead.
- `ListHeader` stays until #88 removes its last users, the consent view
only picks up the new names, the chat keeps its own blur until #91, and
three images the README still shows leave with #90.

### 📚 Documentation

GroveViews' page gets a Pages and a Blocking Feedback topic,
GroveOnboarding describes onboarding on top of the scaffold, and the
Documentation Guide covers the script's directives.

### ✅ Testing

UI suites for Views, Onboarding, Chat, LLM, Scheduler, Contact, License,
AccessGuard, Devices and HealthKit on an iPhone 17 Pro with iOS 26.5,
the iOS and macOS unit legs, the floor build and the documentation
build. The chat, LLM, account, consent and questionnaire suites were run
on the full stack.

### Code of Conduct & Contributing Guidelines

By creating and submitting this pull request, you agree to follow our
[Code of
Conduct](https://github.com/SchmiedmayerLab/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/SchmiedmayerLab/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/SchmiedmayerLab/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/SchmiedmayerLab/.github/blob/main/CONTRIBUTING.md).
lukaskollmer pushed a commit that referenced this pull request Sep 21, 2026
…estionnaire (#97)

### ♻️ Current situation & Problem

A questionnaire gave no sense of how far along it was, its choice marks
looked the same for one answer and for several, a missing answer was
pointed out by a line that pushed the question around as it came and
went, and a drop-down, date or file answer took two taps to open. The
keyboard stayed up when a participant tapped beside a field.

### ⚙️ Release Notes

<table><tr><td></td><td align="center"><sub>Progress bar</sub></td><td
align="center"><sub>Blocking line</sub></td><td align="center"><sub>Day
options and score</sub></td></tr><tr><td
align="center"><sub>#89</sub></td><td align="center"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview.png"
width="200" alt="Progress bar before"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Validation~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Validation.png"
width="200" alt="Blocking line before"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Score~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Score.png"
width="200" alt="Day options and score
before"></picture></td></tr><tr><td
align="center"><sub>#97</sub></td><td align="center"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Overview.png"
width="200" alt="Progress bar"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Validation~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Validation.png"
width="200" alt="Blocking line"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Score~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Score.png"
width="200" alt="Day options and
score"></picture></td></tr><tr><td></td><td align="center"><sub>Date and
time pills</sub></td><td align="center"><sub>Numbers</sub></td><td
align="center"><sub>Annotation editor</sub></td></tr><tr><td
align="center"><sub>#89</sub></td><td align="center"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/DatesAndTimes~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/DatesAndTimes.png"
width="200" alt="Date and time pills before"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Numbers~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Numbers.png"
width="200" alt="Numbers before"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/AnnotateImage~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-on-the-page-scaffold/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/AnnotateImage.png"
width="200" alt="Annotation editor before"></picture></td></tr><tr><td
align="center"><sub>#97</sub></td><td align="center"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/DatesAndTimes~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/DatesAndTimes.png"
width="200" alt="Date and time pills"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Numbers~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/Numbers.png"
width="200" alt="Numbers"></picture></td><td
align="center"><picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/AnnotateImage~dark.png"><img
src="https://raw.githubusercontent.com/SchmiedmayerLab/Grove/questionnaire-progress/Sources/GroveQuestionnaire/GroveQuestionnaire.docc/Resources/AnnotateImage.png"
width="200" alt="Annotation editor"></picture></td></tr></table>

- A hairline progress bar hangs off the navigation bar and fills as
answers and page turns come in; it never moves back while a condition
still might ask a question. It is on unless asked otherwise, `progress:`
takes `.bar`, `.questionNumbers` or both, and `progressRange:` lets a
questionnaire that is one step of a longer flow fill only its part.
`QuestionProgressConfig` is deprecated in favour of it.
- With the bar, the page's name sits in the navigation bar with the
instrument's name under it, and both rise as the page scrolls;
`PageHeader(subtitleRises:)` in GroveViews is what carries the subtitle
along.
- Single and multiple choice questions show distinct marks; "Select all
that apply" and other hints are off unless `hints:` asks for them.
- A question that keeps the page from continuing is tinted and gets its
line under the answers: the card grows down over 0.4 s and the line
fades in once there is room; on an answer the line and the tint fade
together at the pace the answer is confirmed and the room closes over
0.2 s. The question above never moves.
- Drop-down, date and file answers open from a pill in one tap; a
drop-down answer scrolls on to the next question like a choice does; an
attachment can be removed, and a photo taken for one is cleaned up once
it is copied.
- `ResponseValidationResult` gains `.incomplete` for an answer on its
way, such as "Other" with nothing typed: the page holds it back only
once the participant tries to move on. An exhaustive `switch` over the
result needs the new case.
- A tap beside the fields lets the keyboard go, as on a form; the
annotation editor's buttons are back to their earlier look.
- A number field keeps its fraction: its formatter kept none, so a typed
3.5 settled as 4.
- `progressRange` bounds outside `0...1` are clamped, as documented; a
range reaching below the bar drew its halfway mark too low.
- The floating action and the completion page's Done button take the
`PageActions` style and size, so they match the actions on the other
pages; they stood a few points taller.
- A card scrolled to the top stops halfway into the gap it shares with
the card before, not against the navigation bar; the progress line keeps
its place.

### 📚 Documentation

The questionnaire article covers `progress`, `progressRange` and
`hints`; `QuestionnaireProgress` and `QuestionnaireHints` are documented
in place. The questionnaire screenshots are retaken with the bar, the
marks and the pills, and with every kind answered: dates and times
chosen, numbers typed, a mark drawn on the body map, the stopwatch
running. The screenshot script starts RocketSim itself, since RocketSim
quits whenever a simulator it shows is shut down and its CLI reports
success either way, and stops on a failed build rather than shooting a
stale app.

### ✅ Testing

Unit tests cover the progress counting and the clamped range: answers,
page turns, questions a condition hides, an answer the page rejects, a
page outside the run, and a questionnaire that asks nothing. UI tests
cover the bar, the page naming, the pills, the keyboard, and the
blocking line. The test helper opens a date pill at the row's trailing
end, where the pill is. The gate jobs of Tests, Deployment Floor and
release validation run under `!cancelled()` rather than `always()`, so a
run superseded by a newer push ends as cancelled instead of failed, and
Repository Standards has a concurrency group like the other workflows.
Run locally: the questionnaire's unit legs on iOS and macOS and its UI
suite, the GroveViews unit legs on iOS, macOS and watchOS and its UI
suite, SwiftLint, Periphery, the documentation build, the UI-test
project and documentation-target checks, REUSE, and the five
deployment-floor builds. The documentation walk closes every date picker
popover before it continues, so the dates page is taken with none open.

### Code of Conduct & Contributing Guidelines

By creating and submitting this pull request, you agree to follow our
[Code of
Conduct](https://github.com/SchmiedmayerLab/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/SchmiedmayerLab/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/SchmiedmayerLab/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/SchmiedmayerLab/.github/blob/main/CONTRIBUTING.md).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants