Skip to content

Commit

Permalink
Merge a824d25 into e7ac1f2
Browse files Browse the repository at this point in the history
  • Loading branch information
jonambas committed Mar 27, 2020
2 parents e7ac1f2 + a824d25 commit 14d3dab
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 31 deletions.
9 changes: 8 additions & 1 deletion packages/matchbox/src/components/Tooltip/Tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function Tooltip(props) {

function renderTooltip({ preferredDirection }) {
const {
as,
content,
dark, // TODO deprecate in favor of system props
top,
Expand Down Expand Up @@ -91,7 +92,7 @@ function Tooltip(props) {
function renderActivator({ activatorRef }) {
return (
<Box
display="inline-block"
display={props.as === 'span' ? 'inline-block' : null}
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
ref={activatorRef}
Expand All @@ -103,6 +104,7 @@ function Tooltip(props) {

return (
<TooltipOverlay
as={props.as}
id={props.id}
hideTooltip={handleMouseOut}
renderTooltip={renderTooltip}
Expand All @@ -114,6 +116,10 @@ function Tooltip(props) {

Tooltip.displayName = 'Tooltip';
Tooltip.propTypes = {
/**
* Configures the html element that wraps the tooltip, defaults to 'span'
*/
as: PropTypes.string,
id: PropTypes.string,
content: PropTypes.node,
/**
Expand Down Expand Up @@ -152,6 +158,7 @@ Tooltip.propTypes = {
};

Tooltip.defaultProps = {
as: 'span',
right: true,
bottom: true,
horizontalOffset: '0px',
Expand Down
37 changes: 19 additions & 18 deletions packages/matchbox/src/components/Tooltip/TooltipOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ function TooltipOverlay(props) {
const [preferredDirection, setPreferredDirection] = React.useState(defaultDirection);
const activatorRef = React.useRef(null);

const { id, renderTooltip, renderActivator, hideTooltip, visible } = props;
const { as, id, renderTooltip, renderActivator, hideTooltip, visible } = props;

function handleMeasurement() {
if (activatorRef.current && visible) {
setPosition(getPositionFor(activatorRef.current, { fixed: true }));
setPosition(getPositionFor(activatorRef.current));
setPreferredDirection(getPreferredDirectionFor(activatorRef.current));
}
}
Expand All @@ -48,22 +48,23 @@ function TooltipOverlay(props) {
return (
<>
<WindowEvent event="scroll" handler={handleScroll} />
{renderActivator({ activatorRef })}
<Box
{...(!visible ? { 'aria-hidden': true } : {})}
as="span"
id={id}
// Fixes this wrapper to the top and left of viewport
// Handles any potential 'position: relative' on a parent
position="fixed"
top={0}
left={0}
style={{
pointerEvents: 'none',
}}
zIndex={tokens.zIndex_overlay} // TODO add zindices to styled system theme
>
<Box as="span" position="absolute" {...position}>
<Box as={as} display={as === 'span' ? 'inline-block' : null} position="relative">
{renderActivator({ activatorRef })}
<Box
as="span"
display="inline-block"
position="absolute"
{...(!visible ? { 'aria-hidden': true } : {})}
id={id}
top="0"
left="0"
width={position.width}
height={position.height}
zIndex={tokens.zIndex_overlay} // TODO add zindices to styled system theme
style={{
pointerEvents: 'none',
}}
>
{renderTooltip({ preferredDirection })}
</Box>
</Box>
Expand Down
14 changes: 10 additions & 4 deletions packages/matchbox/src/components/Tooltip/tests/Tooltip.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,17 @@ describe('Tooltip', () => {

it('should render overlay', () => {
const wrapper = subject();
expect(wrapper.find('span').at(0)).toHaveStyleRule('z-index', '1000');
expect(wrapper.find('span').at(0)).toHaveAttributeValue('id', 'test-id');
expect(wrapper.find('span').at(0)).toHaveStyleRule('display', 'inline-block');
expect(wrapper.find('span').at(1)).toHaveStyleRule('z-index', '1000');
expect(wrapper.find('span').at(1)).toHaveAttributeValue('id', 'test-id');
// These values are 0 but shows the positioning is working
expect(wrapper.find('span').at(0)).toHaveStyleRule('top', '0');
expect(wrapper.find('span').at(0)).toHaveStyleRule('left', '0');
expect(wrapper.find('span').at(1)).toHaveStyleRule('top', '0');
expect(wrapper.find('span').at(1)).toHaveStyleRule('left', '0');
expect(wrapper.find('span').at(1)).toHaveStyleRule('height', '0');
});

it('should render with a block wrapper', () => {
const wrapper = subject({ as: 'div' });
expect(wrapper.find('div').at(0)).not.toHaveStyleRule('display');
});
});
42 changes: 34 additions & 8 deletions stories/overlays/Tooltip.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { action } from '@storybook/addon-actions';

import { ThemeProvider, Tooltip, Button, Box } from '@sparkpost/matchbox';
import { ThemeProvider, Tooltip, Button, Box, TextField } from '@sparkpost/matchbox';

addDecorator(storyFn => <ThemeProvider>{storyFn()}</ThemeProvider>);

Expand All @@ -12,7 +12,6 @@ export default {
};

export const DefaultStyle = withInfo({ propTables: [Tooltip] })(() => (
// Adding a Box here to test relative positioning
<Box position="relative">
<Button.Group>
<Tooltip content="Hellow I am a Tooltip">
Expand Down Expand Up @@ -46,15 +45,17 @@ export const Positioning = withInfo({ propTables: [Tooltip] })(() => (
<small>Scroll down and hover</small>
</p>
<div style={{ height: '400px' }} />
<Tooltip content="Tooltips are positioned automatically based on the components position.">
<Button>Hover me</Button>
</Tooltip>

<Box textAlign="right">
<Button.Group>
<Tooltip content="Tooltips are positioned automatically based on the components position.">
<Button>Hover me</Button>
</Tooltip>
</Box>

<Box textAlign="right">
<Tooltip content="Tooltips are positioned automatically based on the components position.">
<Button>Hover me</Button>
</Tooltip>
</Box>
</Button.Group>
</div>
));

Expand Down Expand Up @@ -84,3 +85,28 @@ export const StyledWithSystemProps = withInfo({ propTables: [Tooltip] })(() => (
</Tooltip>
</div>
));

export const WithinAbsoluteContainer = withInfo({ propTables: [Tooltip] })(() => (
<Box>
<p>This story is meant to test positioning functionality</p>
<Box height="20rem"></Box>
<Box position="fixed" top="0" left="0" zIndex="10000">
<Box position="absolute" top="300px" left="200px">
<Tooltip content="Tooltips are positioned automatically based on the components position.">
<Button>Hover me</Button>
</Tooltip>
</Box>
</Box>
</Box>
));

export const AroundABlockElement = withInfo({ propTables: [Tooltip] })(() => (
<Box>
<Tooltip
as="div"
content="Tooltips are positioned automatically based on the components position."
>
<TextField label="A block level element" />
</Tooltip>
</Box>
));
2 changes: 2 additions & 0 deletions unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@
- #358 - ActionList actions now accept a new `is` prop, and accept either `link` `button` or
`checkbox`
- #361 – Tabs now specify `type="button"` and support long text content
- #365 – Adds a Tooltip `as` prop, defaults to `span`
- #365 – Fixes tooltip positioning within relative contexts

0 comments on commit 14d3dab

Please sign in to comment.