From 202bfef0f7d4ee6e8db58b25ed139ed4654fc75d Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Thu, 23 Jul 2026 14:01:14 +0100 Subject: [PATCH 1/5] Ensure step survey uses modern components and is accessible --- .../update-connection-js-package-ui-pt6 | 4 + .../disconnect-dialog/steps/step-survey.tsx | 9 +- .../components/disconnect-dialog/style.scss | 10 +- .../_jp-connect_disconnect-survey-card.scss | 56 +++++--- .../components/disconnect-survey/index.tsx | 125 +++++++++--------- .../disconnect-survey/survey-choice.tsx | 43 +++--- .../components/disconnect-survey/types.ts | 24 ++-- 7 files changed, 156 insertions(+), 115 deletions(-) create mode 100644 projects/js-packages/connection/changelog/update-connection-js-package-ui-pt6 diff --git a/projects/js-packages/connection/changelog/update-connection-js-package-ui-pt6 b/projects/js-packages/connection/changelog/update-connection-js-package-ui-pt6 new file mode 100644 index 000000000000..5717f0d8131e --- /dev/null +++ b/projects/js-packages/connection/changelog/update-connection-js-package-ui-pt6 @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Connection UI: Make the disconnect survey a real radio group so its options are announced and keyboard-operable as a single-choice control, and drop the decorative arrow the options no longer need. diff --git a/projects/js-packages/connection/components/disconnect-dialog/steps/step-survey.tsx b/projects/js-packages/connection/components/disconnect-dialog/steps/step-survey.tsx index ccbc3305a55d..817c035476d0 100644 --- a/projects/js-packages/connection/components/disconnect-dialog/steps/step-survey.tsx +++ b/projects/js-packages/connection/components/disconnect-dialog/steps/step-survey.tsx @@ -1,4 +1,5 @@ import { __ } from '@wordpress/i18n'; +import { Text } from '@wordpress/ui'; import '../../disconnect-survey/_jp-connect_disconnect-survey-card.scss'; import DisconnectSurvey from '../../disconnect-survey'; import type { MouseEvent } from 'react'; @@ -7,7 +8,7 @@ interface StepSurveyProps { /** Callback function used to close the modal and leave the disconnect flow. */ onExit?: ( e?: MouseEvent< HTMLElement > ) => void; /** Callback function to handle submission of survey response. */ - onFeedBackProvided?: ( answerId: string | undefined, answerText: string ) => void; + onFeedBackProvided?: ( answerId: string, answerText: string ) => void; /** If the survey feedback is currently being saved/submitted. */ isSubmittingFeedback?: boolean; } @@ -22,9 +23,9 @@ const StepSurvey = ( { onExit, onFeedBackProvided, isSubmittingFeedback }: StepS return (

{ __( 'Before you go, help us improve Jetpack', 'jetpack-connection-js' ) }

-

- { __( 'Let us know what didn‘t work for you', 'jetpack-connection-js' ) } -

+ + { __( "Let us know what didn't work for you", 'jetpack-connection-js' ) } + ` with a (visually hidden) `` naming the group. These + // rules strip the UA fieldset chrome, leaving the previous layout intact. &__survey { - margin-bottom: 1.5rem; + margin: 0 0 1.5rem; max-width: 100%; + border: 0; + padding: 0; + // A fieldset's default `min-width: min-content` would otherwise keep it + // from shrinking below its widest option on narrow screens. + min-width: 0; } // The thank-you step wraps its copy in a @wordpress/ui Stack, so let the diff --git a/projects/js-packages/connection/components/disconnect-survey/_jp-connect_disconnect-survey-card.scss b/projects/js-packages/connection/components/disconnect-survey/_jp-connect_disconnect-survey-card.scss index c33041a8bcf4..17e233e66963 100644 --- a/projects/js-packages/connection/components/disconnect-survey/_jp-connect_disconnect-survey-card.scss +++ b/projects/js-packages/connection/components/disconnect-survey/_jp-connect_disconnect-survey-card.scss @@ -11,42 +11,55 @@ padding: 1rem; position: relative; box-shadow: 0 0 15px var(--jp-gray-off); + display: flex; + align-items: center; + gap: 0.5rem; &--selected { border-color: var(--jp-black); background: var(--jp-gray-off); } - &::after { - content: ""; - display: block; - width: 5px; - height: 5px; - position: absolute; - top: 50%; - right: 1.5rem; - border-top: 2px solid var(--jp-black); - border-right: 2px solid var(--jp-black); - transform: translateY(-50%) rotate(45deg); - } - &:hover { cursor: pointer; } + // `:focus-within` rather than `:focus`: the focusable element is now the + // radio inside the card, not the card itself. &:hover, - &:focus { + &:focus-within { - &:not(.jp-disconnect-survey-card--selected) { + &:not(.jp-connect__disconnect-survey-card--selected) { border-color: var(--jp-black-80); } } + &__radio { + // Sits above the label's stretched hit area so the radio itself stays + // directly clickable, and so its focus ring is not painted over. + position: relative; + z-index: 1; + flex-shrink: 0; + margin: 0; + } + &__answer { + // Set explicitly rather than inherited: as a `

` the answer used to + // pick this up from the dialog's `p` rule, but a `

{ option.answerText }

- + name={ surveyGroupName } + label={ option.answerText } + checked={ selectedAnswer === option.id } + onSelect={ setSelectedAnswer } + /> ); } ); }; @@ -141,31 +128,37 @@ const DisconnectSurvey = ( props: DisconnectSurveyProps ) => { -

- { __( 'Other:', 'jetpack-connection-js' ) }{ ' ' } - -

+
); }; return ( -
+
+ }> + { __( 'Why are you disconnecting?', 'jetpack-connection-js' ) } + { renderOptions() } { renderCustomOption() } -
+