diff --git a/.changeset/warm-groups-reply.md b/.changeset/warm-groups-reply.md new file mode 100644 index 000000000..37dc7086f --- /dev/null +++ b/.changeset/warm-groups-reply.md @@ -0,0 +1,5 @@ +--- +'@qwik-ui/headless': patch +--- + +Support rtl for elements using floating ui diff --git a/apps/website/src/routes/docs/headless/popover/index.mdx b/apps/website/src/routes/docs/headless/popover/index.mdx index 91af0d9d9..8242279bb 100644 --- a/apps/website/src/routes/docs/headless/popover/index.mdx +++ b/apps/website/src/routes/docs/headless/popover/index.mdx @@ -5,12 +5,31 @@ title: Qwik UI | Popover import { statusByComponent } from '~/_state/component-statuses'; import Styles from './examples/styles'; -import { ShowcaseHero, ShowcaseBasic, ShowcaseInspect, ShowcaseAuto, ShowcaseManual, ShowcaseProgrammatic, ShowcaseToggleEvent, ShowcaseFloating, ShowcasePlacement, ShowcaseCorners, ShowcaseFlip, ShowcaseGutter, ShowcaseStyling, ShowcaseAnimation, ShowcaseTransition } from './showcase-components'; -import { CodeSnippetFloatingCss, CodeSnippetPopoverCss, CodeSnippetBuildingBlocks } from './code-snippets'; +import { + ShowcaseHero, + ShowcaseBasic, + ShowcaseInspect, + ShowcaseAuto, + ShowcaseManual, + ShowcaseProgrammatic, + ShowcaseToggleEvent, + ShowcaseFloating, + ShowcasePlacement, + ShowcaseCorners, + ShowcaseFlip, + ShowcaseGutter, + ShowcaseStyling, + ShowcaseAnimation, + ShowcaseTransition, +} from './showcase-components'; +import { + CodeSnippetFloatingCss, + CodeSnippetPopoverCss, + CodeSnippetBuildingBlocks, +} from './code-snippets'; - # Popover A popup that goes above other content on the page. You can still interact with the rest of the page while the popover is open. @@ -24,6 +43,7 @@ A popup that goes above other content on the page. You can still interact with t 'Polyfill for unsupported browsers', 'Executes code on interaction', 'Float and position the popover', + 'Supports RTL', ]} /> diff --git a/apps/website/src/routes/docs/headless/tooltip/index.mdx b/apps/website/src/routes/docs/headless/tooltip/index.mdx index 98fe4b7b4..7ed2bc27a 100644 --- a/apps/website/src/routes/docs/headless/tooltip/index.mdx +++ b/apps/website/src/routes/docs/headless/tooltip/index.mdx @@ -4,7 +4,19 @@ title: Qwik UI | Tooltip import { statusByComponent } from '~/_state/component-statuses'; -import { ShowcaseHero, ShowcaseFloating, ShowcasePlacement, ShowcaseFlip, ShowcaseGutter, ShowcaseStyling, ShowcaseAnimation, ShowcaseTransition, ShowcaseOnChange, ShowcaseBasic, ShowcaseComplex } from './showcase-components'; +import { + ShowcaseHero, + ShowcaseFloating, + ShowcasePlacement, + ShowcaseFlip, + ShowcaseGutter, + ShowcaseStyling, + ShowcaseAnimation, + ShowcaseTransition, + ShowcaseOnChange, + ShowcaseBasic, + ShowcaseComplex, +} from './showcase-components'; @@ -25,6 +37,7 @@ A text label that appears when a user hovers, focuses, or touches an element. 'Accessibility with ARIA roles and keyboard interactions', 'Flipping to avoid overflow', 'Automatic placement adjustment', + 'Supports RTL', ]} /> @@ -42,9 +55,7 @@ export default component$(() => { - - Tooltip content here - + Tooltip content here ); }); diff --git a/packages/kit-headless/src/components/dropdown/dropdown-popover.tsx b/packages/kit-headless/src/components/dropdown/dropdown-popover.tsx index f5017712b..72dfdb7d8 100644 --- a/packages/kit-headless/src/components/dropdown/dropdown-popover.tsx +++ b/packages/kit-headless/src/components/dropdown/dropdown-popover.tsx @@ -23,7 +23,7 @@ export const HDropdownPopover = component$>((props) const { showPopover, hidePopover } = usePopover(context.localId); const initialLoadSig = useSignal(true); - const { floating, flip, hover, gutter, ...rest } = props; + const { floating, flip, hover, gutter, shift, ...rest } = props; useTask$(async ({ track }) => { track(() => context.isOpenSig.value); @@ -103,6 +103,7 @@ export const HDropdownPopover = component$>((props) manual id={context.localId} style={{ display: 'contents' }} + shift={shift} > ) => { }).then(async (resolvedData) => { const { x, y } = resolvedData; - Object.assign(popover.style, { - left: `${x}px`, - top: `${y}px`, - transform: context.transform, - }); + const isRTL = document.documentElement.dir === 'rtl'; + + if (isRTL) { + const documentWidth = document.body.getBoundingClientRect().width; + const popoverWidth = popover.getBoundingClientRect().width; + const boundaryX = Math.max(x, 0); + + Object.assign(popover.style, { + right: `${documentWidth - boundaryX - popoverWidth}px`, + top: `${y}px`, + transform: context.transform, + }); + } else { + Object.assign(popover.style, { + left: `${x}px`, + top: `${y}px`, + transform: context.transform, + }); + } if (resolvedData.middlewareData.arrow && context.arrowRef?.value) { const { x, y } = resolvedData.middlewareData.arrow;