Skip to content

Commit

Permalink
Popover: fix arrow logic, use SVG to render triangle
Browse files Browse the repository at this point in the history
  • Loading branch information
ciampo committed Aug 1, 2022
1 parent 0e751ab commit 54505b5
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 26 deletions.
61 changes: 42 additions & 19 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from '@wordpress/compose';
import { close } from '@wordpress/icons';
import deprecated from '@wordpress/deprecated';
import { Path, SVG } from '@wordpress/primitives';

/**
* Internal dependencies
Expand All @@ -48,6 +49,30 @@ import { getAnimateClassName } from '../animate';
*/
const SLOT_NAME = 'Popover';

// An SVG displaying a triangle facing down, filled with a solid
// color and bordered in such a way to create an arrow-like effect.
// Keeping the SVG's viewbox squared simplify the arrow positioning
// calculations.
const ArrowTriangle = ( props ) => (
<SVG
{ ...props }
xmlns="http://www.w3.org/2000/svg"
viewBox={ `0 0 100 100` }
className="components-popover__triangle"
role="presentation"
>
<Path
className="components-popover__triangle-bg"
d="M 0 0 L 50 50 L 100 0"
/>
<Path
className="components-popover__triangle-border"
d="M 0 0 L 50 50 L 100 0"
vectorEffect="non-scaling-stroke"
/>
</SVG>
);

const slotNameContext = createContext();

const positionToPlacement = ( position ) => {
Expand Down Expand Up @@ -267,12 +292,7 @@ const Popover = (
placement: usedPlacement,
middleware: middlewares,
} );
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right',
}[ placementData.split( '-' )[ 0 ] ];

const mergedRefs = useMergeRefs( [ floating, dialogRef, ref ] );

// Updates references
Expand Down Expand Up @@ -408,22 +428,25 @@ const Popover = (
<div className="components-popover__content">{ children }</div>
{ hasArrow && (
<div
className="components-popover__arrow"
ref={ arrowRef }
className={ [
'components-popover__arrow',
`components-popover__arrow--${
placementData.split( '-' )[ 0 ]
}`,
].join( ' ' ) }
style={ {
left:
! arrowData?.x || Number.isNaN( arrowData?.x )
? 0
: arrowData.x,
top:
! arrowData?.y || Number.isNaN( arrowData?.y )
? 0
: arrowData.y,
right: undefined,
bottom: undefined,
[ staticSide ]: '-4px',
left: Number.isFinite( arrowData?.x )
? `${ arrowData.x }px`
: '',
top: Number.isFinite( arrowData?.y )
? `${ arrowData.y }px`
: '',
'--wp-popover-arrow-size': '14px',
} }
/>
>
<ArrowTriangle />
</div>
) }
</div>
);
Expand Down
63 changes: 56 additions & 7 deletions packages/components/src/popover/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,61 @@

.components-popover__arrow {
position: absolute;
background: $gray-400;
width: 8px;
height: 8px;
transform: rotate(45deg);
z-index: -1;
.is-alternate & {
background: $gray-900;
width: var(--wp-popover-arrow-size);
height: var(--wp-popover-arrow-size);
pointer-events: none;

// Thin line that helps to make sure that the underlying
// popover__content's outline is fully overlapped by the
// arrow
&::before {
content: "";
position: absolute;
top: -1px;
left: 0;
height: 2px;
width: 100%;
background-color: $white;
}

// Position and rotate the arrow depending on the popover's placement.
// The `!important' is necessary to override the inline styles.
&--top {
bottom: calc(-1 * var(--wp-popover-arrow-size)) !important;
transform: rotate(0);
}
&--right {
left: calc(-1 * var(--wp-popover-arrow-size)) !important;
transform: rotate(90deg);
}
&--bottom {
top: calc(-1 * var(--wp-popover-arrow-size)) !important;
transform: rotate(180deg);
}
&--left {
right: calc(-1 * var(--wp-popover-arrow-size)) !important;
transform: rotate(-90deg);
}
}

.components-popover__triangle {
fill: transparent;
position: absolute;
height: 100%;
width: 100%;
stroke-width: $border-width;

// Same as popover content
&-bg {
fill: $white;
stroke: $white;
}

&-border {
stroke: $gray-400;
}

.is-alternate &-border {
stroke: $gray-900;
}
}

0 comments on commit 54505b5

Please sign in to comment.