Skip to content

fix(direction): respect document-level dir attribute in useDirection when no DirectionProvider is present#3834

Open
ahmadaurwahaj wants to merge 1 commit intoradix-ui:mainfrom
ahmadaurwahaj:fix/direction-respect-document-dir
Open

fix(direction): respect document-level dir attribute in useDirection when no DirectionProvider is present#3834
ahmadaurwahaj wants to merge 1 commit intoradix-ui:mainfrom
ahmadaurwahaj:fix/direction-respect-document-dir

Conversation

@ahmadaurwahaj
Copy link
Copy Markdown

Fixes #3830

Description

useDirection() currently falls back to 'ltr' when no DirectionProvider exists in the React tree - completely ignoring <html dir="rtl"> set at the document level. This causes every Radix component (DropdownMenu, Dialog, Popover, ScrollArea, etc.) to render dir="ltr" on its DOM elements, overriding the document's RTL setting.

Teams building Arabic, Hebrew, Persian, or Urdu apps must manually wrap their entire application in <DirectionProvider dir="rtl"> just to get correct layout - boilerplate that should not be required.

Fix: Read document.documentElement.dir as a fallback before defaulting to 'ltr'. Added a getDocumentDirection() helper with an SSR guard.

Priority order (unchanged, additive only): localDir > DirectionProvider context > <html dir> > 'ltr'

Why this is safe:

  • No breaking changes - DirectionProvider and localDir still take full precedence. Existing apps are unaffected.
  • LTR apps unchanged - if <html dir> is not "rtl", result is 'ltr' as before.
  • SSR safe - typeof document === 'undefined' guard falls back to 'ltr' on the server.

Tests: Added the first unit tests for the direction package (6 tests) covering all priority levels - no provider + document rtl, provider overrides document, local dir overrides provider.

Storybook not required: This change is to an internal hook (useDirection) with no visual component of its own. There is no UI to demonstrate - the fix is a logic change in a single fallback value.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 19, 2026

🦋 Changeset detected

Latest commit: 8278551

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
@radix-ui/react-direction Patch
@radix-ui/react-accordion Patch
@radix-ui/react-menu Patch
@radix-ui/react-menubar Patch
@radix-ui/react-navigation-menu Patch
@radix-ui/react-one-time-password-field Patch
@radix-ui/react-radio-group Patch
radix-ui Patch
@radix-ui/react-roving-focus Patch
@radix-ui/react-scroll-area Patch
@radix-ui/react-select Patch
@radix-ui/react-slider Patch
@radix-ui/react-tabs Patch
@radix-ui/react-toggle-group Patch
@radix-ui/react-toolbar Patch
@radix-ui/react-context-menu Patch
@radix-ui/react-dropdown-menu Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR


function getDocumentDirection(): Direction {
if (typeof document === 'undefined') return 'ltr';
return document.documentElement.dir === 'rtl' ? 'rtl' : 'ltr';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can be simplified like this @ahmadaurwahaj.

Suggested change
return document.documentElement.dir === 'rtl' ? 'rtl' : 'ltr';
return document.documentElement.dir || 'ltr';

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.

feat(direction): auto-detect RTL from HTML document when no DirectionProvider is present

2 participants