diff --git a/.changeset/gentle-grapes-remain.md b/.changeset/gentle-grapes-remain.md new file mode 100644 index 000000000..0616bf555 --- /dev/null +++ b/.changeset/gentle-grapes-remain.md @@ -0,0 +1,8 @@ +--- +'@westpac/ui': minor +'protoform': patch +'site': patch +'@westpac/eslint-config': patch +--- + +bottom sheet fix diff --git a/packages/ui/.storybook/preview.tsx b/packages/ui/.storybook/preview.tsx index afe14d42d..3746e9bce 100644 --- a/packages/ui/.storybook/preview.tsx +++ b/packages/ui/.storybook/preview.tsx @@ -2,12 +2,19 @@ import type { Preview } from '@storybook/react'; import './global.css'; import * as React from 'react'; import { clsx } from 'clsx'; +import { useEffect } from 'react'; const withThemeProvider = (Story, context) => { const theme = context.globals?.theme || 'WBC'; + // workaround for modal + useEffect(() => { + if (typeof window !== 'undefined') { + document.querySelector('html')?.setAttribute('data-theme', theme.toLowerCase()); + } + }, [theme]); // Note: Not using padding for grid demos as it affects the proper grid visuals i.e. breakpoints, paddings, margins etc. return ( -
+
); diff --git a/packages/ui/src/components/autocomplete/components/autocomplete-popover/autocomplete-popover.component.tsx b/packages/ui/src/components/autocomplete/components/autocomplete-popover/autocomplete-popover.component.tsx index 27b9465c8..553f59eb5 100644 --- a/packages/ui/src/components/autocomplete/components/autocomplete-popover/autocomplete-popover.component.tsx +++ b/packages/ui/src/components/autocomplete/components/autocomplete-popover/autocomplete-popover.component.tsx @@ -1,5 +1,7 @@ +'use client'; + import { clsx } from 'clsx'; -import * as React from 'react'; +import React, { useMemo, useRef } from 'react'; import { DismissButton, Overlay, usePopover } from 'react-aria'; import { AutocompletePopoverProps } from './autocomplete-popover.types.js'; @@ -7,7 +9,7 @@ import { AutocompletePopoverProps } from './autocomplete-popover.types.js'; * @private */ export function AutocompletePopover(props: AutocompletePopoverProps) { - const ref = React.useRef(null); + const ref = useRef(null); const { popoverRef = ref, state, children, className, isNonModal, portalContainer } = props; const { popoverProps, underlayProps } = usePopover( { @@ -18,11 +20,17 @@ export function AutocompletePopover(props: AutocompletePopoverProps) { ); // This is required so branding applies correctly by default due to portal location, can be overridden with portalContainer prop - const brandContainer = document.querySelector('[data-theme]') || document.querySelector('[className="data-theme"]'); + const brandContainer = useMemo(() => { + if (typeof window !== 'undefined') { + return ( + document.querySelector('[data-theme]') || document.querySelector('[className="data-theme"]') || document.body + ); + } + }, []); const width = props.triggerRef.current?.getBoundingClientRect().width; return ( - + {!isNonModal &&
}
{ + if (isBrowser) { + return ( + document.querySelector('[data-theme]') || document.querySelector('[className="data-theme"]') || document.body + ); + } + }, []); useEffect(() => { function handleResize() { @@ -68,7 +74,7 @@ export function BottomSheetModal({ state, height, width, children, portalContain } return ( - +
{ + if (typeof window !== 'undefined') { + return ( + document.querySelector('[data-theme]') || document.querySelector('[className="data-theme"]') || document.body + ); + } + }, []); + // Don't render anything if the modal is not open and we're not animating out. if (!state.isOpen) { return null; } - // This is required so branding applies correctly by default due to portal location, can be overridden with portalContainer prop - const brandContainer = document.querySelector('[data-theme]') || document.querySelector('[className="data-theme"]'); - return ( - +
{children} diff --git a/packages/ui/src/components/popover/components/panel/panel.component.tsx b/packages/ui/src/components/popover/components/panel/panel.component.tsx index aa8c35e72..81b83444d 100644 --- a/packages/ui/src/components/popover/components/panel/panel.component.tsx +++ b/packages/ui/src/components/popover/components/panel/panel.component.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; +import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { FocusScope } from 'react-aria'; import { Button } from '../../../button/index.js'; @@ -14,7 +14,12 @@ import { type PanelProps, Position } from './panel.types.js'; export function Panel({ state, heading, headingTag: Tag = 'h1', content, placement, id, triggerRef }: PanelProps) { const popoverRef = useRef(null); const arrowRef = useRef(null); - const remSize = parseInt(window.getComputedStyle(document.getElementsByTagName('html')[0]).fontSize); + const remSize = useMemo(() => { + if (typeof window !== 'undefined') { + return parseInt(window.getComputedStyle(document.getElementsByTagName('html')[0]).fontSize); + } + return 1; + }, []); const [position, setPosition] = useState({ placement: 'top', diff --git a/packages/ui/src/components/popover/popover.hooks.tsx b/packages/ui/src/components/popover/popover.hooks.tsx index e3dab01aa..22745416b 100644 --- a/packages/ui/src/components/popover/popover.hooks.tsx +++ b/packages/ui/src/components/popover/popover.hooks.tsx @@ -1,4 +1,4 @@ -import { RefObject } from 'react'; +import { RefObject, useMemo } from 'react'; import { Position } from './components/panel/panel.types.js'; @@ -16,7 +16,10 @@ export const usePopoverPosition = ( const trigger = triggerRef.current.getBoundingClientRect(); const popover = popoverRef.current.getBoundingClientRect(); const arrow = arrowRef.current.getBoundingClientRect(); - const remSize = parseInt(window.getComputedStyle(document.getElementsByTagName('html')[0]).fontSize); + const remSize = + typeof window !== 'undefined' + ? parseInt(window.getComputedStyle(document.getElementsByTagName('html')[0]).fontSize) + : 1; const position: Position = { placement: placement ? placement : 'top',