You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
feat(web): ask the experience survey after a delivered artifact, and add an "other" answer (#7117) (#7127)
* feat(web): add an "other" answer with a free-text field to the survey
The eight choices cover what users already tell us most often, but they cannot
cover what we have not heard yet — and the people whose problem is not on the
list are exactly the ones worth hearing from. Picking "Something else" opens a
text field instead of finishing the survey.
The cost is paid only by the people who need it: everyone whose answer is on
the list still finishes in one tap. This is the open-ended question we cut
earlier, put back behind a door rather than in everyone way.
Wire shape follows PostHog open-choice convention — the response recorded is
the text they typed. Picking "Something else" and typing nothing still reports
the choice itself, because "none of these fit" is an answer and dropping it
would turn those people into non-responders.
Skip disappears once the choice is made; it would only have been a second way
to submit.
* style(web): use a neutral focus border on the survey text field
The green ring competed with the brand fill on the selected chip directly
above it — two green things one under the other, neither reading as primary.
A neutral border marks focus without joining that fight, and the inset fill
still separates the field from the card.
* fix(web): keep the survey submit button on the footer right edge
Submit replaces Skip in the footer, but only Skip carried the margin-left:auto
that pushes it right — so the moment the text field opened, the primary action
collapsed back against the step counter and jumped from the right edge to the
left. Measured from the card edge, both now sit at the same 17px gap.
* feat(web): ask the experience survey after a delivered artifact, not an export
The post-export survey could only reach people who exported. Over 30 days
~13k users exported while ~37k produced an artifact, so roughly two thirds
of the people who got real work out of the product were never asked — and
the ones who tried it, got something, and left without exporting are the
ones worth hearing from most.
The card is now armed by a delivered design run (resolveDesignDeliveryOutcome
=== 'delivered'), from the second such delivery on. The first delivery
measures a first impression rather than an experience, and lands at the one
moment the user most wants to look at what they just got; waiting for the
second costs almost no reach because deliveries repeat (~13 per user per 30
days).
Because a delivery is usually mid-session rather than end-of-session, the
3s delay now bails out if the user starts writing their next prompt.
'beforeinput' rather than 'keydown' so IME composition counts as typing.
A dropped chance is taken by the next delivery, so the card lands after the
turn the user actually stopped on.
Export no longer arms anything; the three FileViewer call sites are gone.
Every survey event carries trigger: 'post_generation' so the two regimes
stay distinguishable in the events table.
* feat(web): arm the experience survey on the first delivered artifact
Drops the two-delivery threshold to one. Waiting for a second run bought a
more considered opinion at the cost of everyone who produces one artifact
and leaves — the users we understand least, and the ones this survey was
widened to reach in the first place.
Asking on the first delivery is affordable because the card is not an
interruption: the component still waits out the delay and still drops the
chance entirely if the user starts typing, so an early ask that lands badly
costs a dropped chance rather than a derailed session.
The delivery counter stays. It is the seam the policy is made of, and it is
what makes an unwritable store read as "not yet qualified" — a store that
cannot write cannot record a dismissal either, so without it the card would
come back after every run with no way to stop it.
* fix(web): retire the experience survey when it is shown, not when it is answered
One ask per user was the intent, but `retireSurvey()` only ran from `finish`
and `close`. Ignoring the card — the most common way to decline a prompt —
left the flag unset, so the card returned after the user's next artifact, and
the one after that. `exposedRef` did not cover this: it is a ref, so it resets
on the next page load.
Retiring on exposure makes the rule what it claims to be: a user sees this
card at most once, whatever they do with it. A chance dropped by the typing
bail-out is still retried, because a card the user never saw did not spend
their one ask.
* refactor(web): drop the typing bail-out from the experience survey
The card no longer cancels itself when the user starts typing during the
three-second delay. With one ask per user, a dropped chance is the whole ask
for anyone whose habit is to type straight into the next prompt — and that
habit belongs to the engaged users this survey most wants to hear from.
Removes the `beforeinput` listener and the IME reasoning that went with it.
The delay stays: it keeps the card from animating in on top of the artifact,
which was always its other job.
* fix(web): give the survey's free-text field an accessible name
Review finding from #7074, folded in with that branch. The textarea is
auto-focused the instant "Something else" is picked, so its accessible name
is the only thing telling a screen-reader user what the field is for — and it
had none. A placeholder is not a label and disappears on the first keystroke.
Reuses the placeholder string rather than adding a twentieth translation of
the same sentence, so the visible and announced names cannot drift.
* chore: ensure PR CI
---------
(cherry picked from commit 713caf0)
Co-authored-by: open-design-crew[bot] <299007234+open-design-crew[bot]@users.noreply.github.com>
Co-authored-by: elifive555555 <296440099+elifive555555@users.noreply.github.com>
Co-authored-by: Eli <qiongyu1999@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: open-design-crew[bot] <4197780+open-design-crew[bot]@users.noreply.github.com>
0 commit comments