From cf9c3c33713ae670eedaa9ba80d3c8ffc679f1c7 Mon Sep 17 00:00:00 2001 From: Shayne Preston Date: Fri, 20 Sep 2024 17:25:11 -0400 Subject: [PATCH] reintroduce inline styles --- packages/react/popper/src/Popper.tsx | 43 +++++++++- packages/react/select/src/Select.tsx | 114 ++++++++++++++++++++++++--- 2 files changed, 146 insertions(+), 11 deletions(-) diff --git a/packages/react/popper/src/Popper.tsx b/packages/react/popper/src/Popper.tsx index b8b263723..f2276b6c4 100644 --- a/packages/react/popper/src/Popper.tsx +++ b/packages/react/popper/src/Popper.tsx @@ -123,6 +123,7 @@ interface PopperContentProps extends PrimitiveDivProps { hideWhenDetached?: boolean; updatePositionStrategy?: 'optimized' | 'always'; onPlaced?: () => void; + skipStyleInjection?: boolean; } const PopperContent = React.forwardRef( @@ -141,6 +142,7 @@ const PopperContent = React.forwardRef hideWhenDetached = false, updatePositionStrategy = 'optimized', onPlaced, + skipStyleInjection, ...contentProps } = props; @@ -224,10 +226,15 @@ const PopperContent = React.forwardRef const arrowY = middlewareData.arrow?.y; const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0; + const [contentZIndex, setContentZIndex] = React.useState(); const updateStyleVariables = React.useCallback(() => { if (refs.floating.current) { if (content) { - refs.floating.current.style.zIndex = window.getComputedStyle(content).zIndex; + if (skipStyleInjection) { + refs.floating.current.style.zIndex = window.getComputedStyle(content).zIndex; + } else { + setContentZIndex(window.getComputedStyle(content).zIndex); + } } /* if the PopperContent hasn't been placed yet (not all measurements done) @@ -262,7 +269,7 @@ const PopperContent = React.forwardRef refs.floating.current.style.left = floatingStyles.left as string; refs.floating.current.style.top = floatingStyles.top as string; } - }, [content, floatingStyles, isPositioned, middlewareData, refs.floating]); + }, [content, floatingStyles, isPositioned, middlewareData, refs.floating, skipStyleInjection]); useLayoutEffect(() => { updateStyleVariables(); @@ -274,6 +281,28 @@ const PopperContent = React.forwardRef diff --git a/packages/react/select/src/Select.tsx b/packages/react/select/src/Select.tsx index 66374a96b..78c42437c 100644 --- a/packages/react/select/src/Select.tsx +++ b/packages/react/select/src/Select.tsx @@ -322,12 +322,21 @@ type SelectValueElement = React.ElementRef; type PrimitiveSpanProps = React.ComponentPropsWithoutRef; interface SelectValueProps extends Omit { placeholder?: React.ReactNode; + skipStyleInjection?: boolean; } const SelectValue = React.forwardRef( (props: ScopedProps, forwardedRef) => { // We ignore `className` and `style` as this part shouldn't be styled. - const { __scopeSelect, className, style, children, placeholder = '', ...valueProps } = props; + const { + __scopeSelect, + className, + style, + children, + placeholder = '', + skipStyleInjection, + ...valueProps + } = props; const context = useSelectContext(VALUE_NAME, __scopeSelect); const { onValueNodeHasChildrenChange } = context; const hasChildren = children !== undefined; @@ -338,7 +347,12 @@ const SelectValue = React.forwardRef( }, [onValueNodeHasChildrenChange, hasChildren]); return ( - + {shouldShowPlaceholder(context.value) ? <>{placeholder} : children} ); @@ -485,6 +499,7 @@ interface SelectContentImplProps onPointerDownOutside?: DismissableLayerProps['onPointerDownOutside']; position?: 'item-aligned' | 'popper'; + skipStyleInjection?: boolean; } const SelectContentImpl = React.forwardRef( @@ -507,6 +522,7 @@ const SelectContentImpl = React.forwardRef setIsPositioned(true)} ref={composedRefs} + style={ + skipStyleInjection + ? undefined + : { + // flex layout so we can place the scroll buttons properly + display: 'flex', + flexDirection: 'column', + // reset the outline by default as the content MAY get focused + outline: 'none', + ...contentProps.style, + } + } onKeyDown={composeEventHandlers(contentProps.onKeyDown, (event) => { const isModifierKey = event.ctrlKey || event.altKey || event.metaKey; @@ -768,13 +796,15 @@ SelectContentImpl.displayName = CONTENT_IMPL_NAME; const ITEM_ALIGNED_POSITION_NAME = 'SelectItemAlignedPosition'; type SelectItemAlignedPositionElement = React.ElementRef; -interface SelectItemAlignedPositionProps extends PrimitiveDivProps, SelectPopperPrivateProps {} +interface SelectItemAlignedPositionProps extends PrimitiveDivProps, SelectPopperPrivateProps { + skipStyleInjection?: boolean; +} const SelectItemAlignedPosition = React.forwardRef< SelectItemAlignedPositionElement, SelectItemAlignedPositionProps >((props: ScopedProps, forwardedRef) => { - const { __scopeSelect, onPlaced, ...popperProps } = props; + const { __scopeSelect, onPlaced, skipStyleInjection, ...popperProps } = props; const context = useSelectContext(CONTENT_NAME, __scopeSelect); const contentContext = useSelectContentContext(CONTENT_NAME, __scopeSelect); const [contentWrapper, setContentWrapper] = React.useState(null); @@ -914,11 +944,17 @@ const SelectItemAlignedPosition = React.forwardRef< useLayoutEffect(() => position(), [position]); + // copy z-index from content to wrapper + const [contentZIndex, setContentZIndex] = React.useState(); useLayoutEffect(() => { if (content && contentWrapper) { - contentWrapper.style.zIndex = window.getComputedStyle(content).zIndex; + if (skipStyleInjection) { + contentWrapper.style.zIndex = window.getComputedStyle(content).zIndex; + } else { + setContentZIndex(window.getComputedStyle(content).zIndex); + } } - }, [content, contentWrapper]); + }, [content, contentWrapper, skipStyleInjection]); // When the viewport becomes scrollable at the top, the scroll up button will mount. // Because it is part of the normal flow, it will push down the viewport, thus throwing our @@ -942,11 +978,36 @@ const SelectItemAlignedPosition = React.forwardRef< shouldExpandOnScrollRef={shouldExpandOnScrollRef} onScrollButtonChange={handleScrollButtonChange} > -
+
@@ -963,7 +1024,9 @@ const POPPER_POSITION_NAME = 'SelectPopperPosition'; type SelectPopperPositionElement = React.ElementRef; type PopperContentProps = React.ComponentPropsWithoutRef; -interface SelectPopperPositionProps extends PopperContentProps, SelectPopperPrivateProps {} +interface SelectPopperPositionProps extends PopperContentProps, SelectPopperPrivateProps { + skipStyleInjection?: boolean; +} const SelectPopperPosition = React.forwardRef< SelectPopperPositionElement, @@ -973,6 +1036,7 @@ const SelectPopperPosition = React.forwardRef< __scopeSelect, align = 'start', collisionPadding = CONTENT_MARGIN, + skipStyleInjection, ...popperProps } = props; const popperScope = usePopperScope(__scopeSelect); @@ -985,6 +1049,23 @@ const SelectPopperPosition = React.forwardRef< ref={forwardedRef} align={align} collisionPadding={collisionPadding} + style={ + skipStyleInjection + ? undefined + : { + // Ensure border-box for floating-ui calculations + boxSizing: 'border-box', + ...popperProps.style, + // re-namespace exposed content custom properties + ...{ + '--radix-select-content-transform-origin': 'var(--radix-popper-transform-origin)', + '--radix-select-content-available-width': 'var(--radix-popper-available-width)', + '--radix-select-content-available-height': 'var(--radix-popper-available-height)', + '--radix-select-trigger-width': 'var(--radix-popper-anchor-width)', + '--radix-select-trigger-height': 'var(--radix-popper-anchor-height)', + }, + } + } /> ); }); @@ -1037,6 +1118,19 @@ const SelectViewport = React.forwardRef { const viewport = event.currentTarget; const { contentWrapper, shouldExpandOnScrollRef } = viewportContext; @@ -1429,13 +1523,14 @@ SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME; type SelectScrollButtonImplElement = React.ElementRef; interface SelectScrollButtonImplProps extends PrimitiveDivProps { onAutoScroll(): void; + skipStyleInjection?: boolean; } const SelectScrollButtonImpl = React.forwardRef< SelectScrollButtonImplElement, SelectScrollButtonImplProps >((props: ScopedProps, forwardedRef) => { - const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props; + const { __scopeSelect, onAutoScroll, skipStyleInjection, ...scrollIndicatorProps } = props; const contentContext = useSelectContentContext('SelectScrollButton', __scopeSelect); const autoScrollTimerRef = React.useRef(null); const getItems = useCollection(__scopeSelect); @@ -1466,6 +1561,7 @@ const SelectScrollButtonImpl = React.forwardRef< data-radix-select-scroll-button-impl="" {...scrollIndicatorProps} ref={forwardedRef} + style={skipStyleInjection ? undefined : { flexShrink: 0, ...scrollIndicatorProps.style }} onPointerDown={composeEventHandlers(scrollIndicatorProps.onPointerDown, () => { if (autoScrollTimerRef.current === null) { autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);