Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/web/core/debates/matchmaking/matchmaking-claim-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ export function PositionRow({
disabled?: boolean;
/**
* The viewer's response is still confirming. The pills stay at full strength — the side is drawn
* as taken — but presses are dropped, and the buttons say so to assistive technology.
* as taken — but presses are dropped, and the buttons say so to assistive technology and, on the
* pointer, with a wait cursor.
*/
pending?: boolean;
titleFor?: (position: boolean) => string;
Expand Down Expand Up @@ -1221,6 +1222,10 @@ function PositionButton({
className={cx(
className,
'transition-colors disabled:opacity-60',
// The only sign the press was taken: the pill drops presses for the 10-50s a response
// spends confirming, and nothing else on the page says so. The copy that used to sit
// under the pills read as an unsettled side, so the cue stays on the pointer.
pending && 'cursor-progress',
!selected && !disabled && !pending && 'hover:border-text'
)}
>
Expand Down
36 changes: 36 additions & 0 deletions apps/web/core/debates/matchmaking/position-row.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,40 @@ describe('PositionRow', () => {
'bg-divider'
);
});

// A response confirms for 10-50s, and the pills drop presses for all of it. The wait cursor is
// the only thing left that says so on screen: the note that used to sit under the pills was
// taken out, because it read as a side not yet taken, and `aria-disabled` is heard rather than
// seen. Asserted so the next pass at quieting this row does not take the last cue with it.
describe('while a response is confirming', () => {
const pill = (label: string) => screen.getByText(label).closest('button') as HTMLElement;

it('puts a wait cursor on both pills', () => {
render(
<PositionRow positions={positions} responseKind="stance" viewerPosition={true} pending onRespond={() => {}} />
);

expect([...pill('Agree').classList]).toContain('cursor-progress');
expect([...pill('Disagree').classList]).toContain('cursor-progress');
});

it('leaves the pills looking taken, with no note under them', () => {
render(
<PositionRow positions={positions} responseKind="stance" viewerPosition={true} pending onRespond={() => {}} />
);

// The side still reads as held: full strength, and nothing announcing a wait. A pressable
// pill carries the fill on the button itself, not on an inner div as the read-only one does.
expect([...pill('Agree').classList]).toContain('bg-divider');
expect(screen.queryByText(/waiting for confirmation/i)).toBeNull();
// Dropped presses are still spoken, since a cursor is not.
expect(pill('Agree')).toHaveAttribute('aria-disabled', 'true');
});

it('drops the cursor once the response lands', () => {
render(<PositionRow positions={positions} responseKind="stance" viewerPosition={true} onRespond={() => {}} />);

expect([...pill('Agree').classList]).not.toContain('cursor-progress');
});
});
});
Loading