Skip to content
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.

Commit

Permalink
fix: Fix broken secondary placement for Arrow
Browse files Browse the repository at this point in the history
  • Loading branch information
diondiondion committed Aug 6, 2019
1 parent c34698b commit afaa051
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
51 changes: 30 additions & 21 deletions src/PopOver/Arrow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {forwardRef, useMemo} from 'react';

import getArrowPosition, {getPlacements} from './getArrowPosition';

Expand All @@ -9,33 +9,42 @@ const transformMap = {
left: 'translateX(-50%) rotate(45deg)',
};

const getArrowStyles = (primaryPlacement, arrowSize) => {
return {
position: 'absolute',
function useArrowStyles(primaryPlacement, arrowSize) {
const arrowStyles = useMemo(
() => ({
position: 'absolute',

display: 'inline-block',
width: arrowSize + 'px',
height: arrowSize + 'px',
display: 'inline-block',
width: arrowSize + 'px',
height: arrowSize + 'px',

backgroundColor: 'inherit',
border: 'inherit',
borderLeftColor: 'transparent',
borderBottomColor: 'transparent',
backgroundColor: 'inherit',
border: 'inherit',
borderLeftColor: 'transparent',
borderBottomColor: 'transparent',

transform: transformMap[primaryPlacement],
transformOrigin: '50%',
clipPath: 'polygon(0 0, 100% 0, 100% 100%)',
};
};
transform: transformMap[primaryPlacement],
transformOrigin: '50%',
clipPath: 'polygon(0 0, 100% 0, 100% 100%)',
}),
[arrowSize, primaryPlacement]
);

return arrowStyles;
}

const Arrow = React.forwardRef((props, ref) => {
const Arrow = forwardRef((props, ref) => {
const {placement, size, style} = props;

const [primaryPlacement] = getPlacements(placement);
const baseArrowStyles = getArrowStyles(primaryPlacement, size);
const defaultArrowPosition = getArrowPosition(placement, {
centerOffset: `-${size / 2}px`,
});
const baseArrowStyles = useArrowStyles(primaryPlacement, size);
const defaultArrowPosition = useMemo(
() =>
getArrowPosition(placement, {
centerOffset: `-${size / 2}px`,
}),
[placement, size]
);
// Don't let an empty primary position attribute reset the default
if (style && style[primaryPlacement] === '') {
delete style[primaryPlacement];
Expand Down
9 changes: 5 additions & 4 deletions src/PopOver/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@ It's a wrapper around `react-popper`.

<Props of={PopOver} />

# Using the Arrow Components
## Using just the Arrow component

The Arrow component is a tooltip "arrow" that can be dropped into any container element and will inherit its styling.
The Arrow component is a tooltip "arrow" that can be dropped into any container element. It will then inherit the container's styling and can be positioned using a normal popper.js placement string (e.g. `left`, `top-start`, `right-end`).

It accepts a placement string formatted in the style of popper.js (i.e. `left`, `top-start`, `right-end`) and will position itself on the opposing side of its parent element. For this to work, the parent element needs to have a position other than 'static', e.g. 'relative', 'absolute', or 'fixed'.
For the positioning to work, the parent element needs to have a position other than `static`, e.g. `relative`, `absolute`, or `fixed`.

Use the `size` prop to adjust the arrow's size (in pixels).

<Playground>
<div
style={{
position: 'relative',
width: 250,
padding: 8,
backgroundColor: 'grey',
color: 'white',
Expand All @@ -49,6 +50,6 @@ Use the `size` prop to adjust the arrow's size (in pixels).
}}
>
Hello, I'm a box with a pointy arrow.
<Arrow placement="bottom-start" size={12} />
<Arrow placement="top-end" size={10} />
</div>
</Playground>
8 changes: 6 additions & 2 deletions src/PopOver/getArrowPosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* returns a CSS style object containing sensible default
* styles for the placement string.
*
* The values can be customised, but default to:
* The (customisable) defaults are:
* - 100% for the primary direction
* - 8 pixels for the secondary direction
*
Expand Down Expand Up @@ -40,10 +40,14 @@ function getArrowPosition(
{defaultPrimaryValue = '100%', defaultSecondaryValue = 8, centerOffset}
) {
const [primaryPlacement, secondaryPlacement] = getPlacements(placement);
const secondaryDirection = getSecondaryDirection(
primaryPlacement,
secondaryPlacement
);

return {
[primaryPlacement]: defaultPrimaryValue,
[getSecondaryDirection(secondaryPlacement)]: secondaryPlacement
[secondaryDirection]: secondaryPlacement
? defaultSecondaryValue
: centerOffset
? `calc(50% + ${centerOffset})`
Expand Down

0 comments on commit afaa051

Please sign in to comment.