Skip to content

fix(ActionRow): align DOM and visual order in stacked mode#4271

Open
e0d wants to merge 2 commits intorelease-23.xfrom
e0d/fix-actionrow-stacked-focus-order
Open

fix(ActionRow): align DOM and visual order in stacked mode#4271
e0d wants to merge 2 commits intorelease-23.xfrom
e0d/fix-actionrow-stacked-focus-order

Conversation

@e0d
Copy link
Copy Markdown

@e0d e0d commented May 2, 2026

In isStacked mode, flex-direction: column-reverse placed the primary action (last DOM child) at the visual top but keyboard focus still reached it last, violating WCAG 1.3.2 Meaningful Sequence and 2.4.3 Focus Order.

Fix (Option A): reverse children in DOM order when isStacked is true and change the SCSS to flex-direction: column. The primary action is now first in both DOM and visual order — a sighted keyboard user tabs to it first, matching what they see.

Consumers continue passing the primary action as the last child (consistent with horizontal mode); the component handles reversal internally.

Description

Include a description of your changes here, along with a link to any relevant Jira tickets and/or Github issues.

Deploy Preview

Include a direct link to your changes in this PR's deploy preview here (e.g., a specific component page).

Merge Checklist

  • If your update includes visual changes, have they been reviewed by a designer? Send them a link to the Netlify deploy preview, if applicable.
  • Does your change adhere to the documented style conventions?
  • Do any prop types have missing descriptions in the Props API tables in the documentation site (check deploy preview)?
  • Were your changes tested using all available themes (see theme switcher in the header of the deploy preview, under the "Settings" icon)?
  • Were your changes tested in the example app?
  • Is there adequate test coverage for your changes?
  • Consider whether this change needs to reviewed/QA'ed for accessibility (a11y). If so, please request an a11y review for the PR in the #wg-paragon Open edX Slack channel.

Post-merge Checklist

  • Verify your changes were released to NPM at the expected version.
  • If you'd like, share your contribution in #show-and-tell.
  • 🎉 🙌 Celebrate! Thanks for your contribution.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 2, 2026

Deploy Preview for paragon-openedx-v23 ready!

Name Link
🔨 Latest commit 4e3c7bd
🔍 Latest deploy log https://app.netlify.com/projects/paragon-openedx-v23/deploys/69fca637ea54460008558516
😎 Deploy Preview https://deploy-preview-4271--paragon-openedx-v23.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79c695fcb3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/ActionRow/_index.scss
flex-grow: 1;
align-items: center;
flex-direction: column-reverse;
flex-direction: column;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fix stacked item spacing after switching to column flow

Changing pgn__action-row-stacked to flex-direction: column without updating the sibling spacing rule causes the vertical gap to be applied below later items (margin-bottom) instead of between adjacent actions. In stacked mode this makes controls visually bunch together (no inter-button gap) while adding extra trailing space at the bottom, so the layout regresses for any multi-action stack.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

@e0d e0d May 2, 2026

Choose a reason for hiding this comment

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

@codex Does the change at line 28 of this file resolve this issue satisfactorily?

In isStacked mode, flex-direction: column-reverse placed the primary
action (last DOM child) at the visual top but keyboard focus still
reached it last, violating WCAG 1.3.2 Meaningful Sequence and 2.4.3
Focus Order.

Fix (Option A): reverse children in DOM order when isStacked is true
and change the SCSS to flex-direction: column. The primary action is
now first in both DOM and visual order — a sighted keyboard user tabs
to it first, matching what they see.

Consumers continue passing the primary action as the last child
(consistent with horizontal mode); the component handles reversal
internally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@e0d e0d force-pushed the e0d/fix-actionrow-stacked-focus-order branch from 79c695f to 5c2a355 Compare May 2, 2026 21:48
@e0d
Copy link
Copy Markdown
Author

e0d commented May 2, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@codecov
Copy link
Copy Markdown

codecov Bot commented May 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.41%. Comparing base (51702d5) to head (4e3c7bd).
⚠️ Report is 1 commits behind head on release-23.x.

Additional details and impacted files
@@              Coverage Diff              @@
##           release-23.x    #4271   +/-   ##
=============================================
  Coverage         94.40%   94.41%           
=============================================
  Files               242      242           
  Lines              4309     4312    +3     
  Branches           1020      984   -36     
=============================================
+ Hits               4068     4071    +3     
  Misses              237      237           
  Partials              4        4           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@brian-smith-tcril
Copy link
Copy Markdown
Contributor

@kblemel in the WG meeting you mentioned finding documentation/discussions about flex-direction: column-reverse and flex-direction: row-reverse for interactive elements. Would you be able to link those here?

Copy link
Copy Markdown
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

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

Overall I think this makes sense.

I did notice one edge case when using the following example code to simulate an application that switches between stacked and non-stacked (I'm thinking this would likely be done for responsive design with useMediaQuery)

Code used on docs site to test
() => {
  const [stackIt, setStackIt] = React.useState(false);
  
  React.useEffect(() => {
    const interval = setInterval(() => {
      setStackIt(prev => !prev);
    }, 2000); // toggles every 2 seconds
    
    return () => clearInterval(interval);
  }, []);
  
  return (
    <ActionRow isStacked={stackIt}>
      <p className="x-small">
        Bespoke leggings yuccie, portland umami readymade craft beer vaporware sriracha.
      </p>
      <Button variant="tertiary">
        Go back
      </Button>
      <Button variant="primary">
        Continue
      </Button>
    </ActionRow>
  );
}

Behavior before PR

The element selected by the keyboard stays selected when the component switches between stacked and non-stacked.

Screencast.From.2026-05-07.10-24-52.mp4

Behavior after PR

The element selected by the keyboard is no longer selected when the component switches between stacked and non-stacked

Screencast.From.2026-05-07.10-26-59.mp4

@kblemel - any thoughts on that change? Also it'd be great to know if any of the conversations/documentation you found mentioned something like that (I assume the plugin you mentioned does something similar to what this PR is doing and would result in similar behavior)

Comment thread CLAUDE.md Outdated
@@ -0,0 +1,98 @@
# CLAUDE.md
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I know we've discussed adding CLAUDE.md and AGENTS.md files to repos in the org before, but that should definitely happen as a separate PR.

Comment thread ACCESSIBILITY_AUDIT.md Outdated
@@ -0,0 +1,394 @@
# WCAG 2.2 AA Accessibility Audit — Paragon Component Library
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Very cool to see this file for context, but it shouldn't be part of this PR

Comment thread .gitignore

# Local Netlify folder
.netlify
.claude/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure about "claude" as the section comment here but I figure making it clear this isn't part of the "Local Netlify folder" would be good

Suggested change
.claude/
# claude
.claude/

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

What's your recommendation? I don't have a strong commitment to this change.

Comment thread docs/a11y-audit-ActionRow.md Outdated
@@ -0,0 +1,154 @@
# WCAG 2.2 AA Accessibility Audit — ActionRow
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Very cool to see this file for context, but it shouldn't be part of this PR

Adds WCAG 2.2 AA audit documentation for ActionRow, top-level
ACCESSIBILITY_AUDIT.md overview, ActionRow component PDF reference,
and CLAUDE.md project instructions. Excludes .claude/ from tracking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@e0d e0d force-pushed the e0d/fix-actionrow-stacked-focus-order branch from d8d8fd7 to 4e3c7bd Compare May 7, 2026 14:48
@wittjeff
Copy link
Copy Markdown

wittjeff commented May 7, 2026

I have vague memory of this being a design choice with external input -- someone wanted Next to be earlier than Back because Back is much less likely to be needed, so it's a usability improvement. This is the kind of thing I don't have a strong opinion on, so defer to whatever Design wants.
I have seen something similar somewhere with Desktop nav collapsing into a hamburger menu (somewhere, not necessarily with Paragon), where the focus order was not as expected. I have the same neutral opinion there. I think "may be confusing" is possible and technically correct but perhaps too strong in practical terms.

@e0d
Copy link
Copy Markdown
Author

e0d commented May 8, 2026

I have vague memory of this being a design choice with external input -- someone wanted Next to be earlier than Back because Back is much less likely to be needed, so it's a usability improvement. This is the kind of thing I don't have a strong opinion on, so defer to whatever Design wants. I have seen something similar somewhere with Desktop nav collapsing into a hamburger menu (somewhere, not necessarily with Paragon), where the focus order was not as expected. I have the same neutral opinion there. I think "may be confusing" is possible and technically correct but perhaps too strong in practical terms.

Maybe that's true, but I'd argue the visual order and tab order should still be the same in that case. Do you disagree?

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.

3 participants