Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Tip): Fixes hover gap and click issues with ToolTips and PreviewTips #3018

Merged
merged 15 commits into from
Jan 31, 2025
17 changes: 11 additions & 6 deletions packages/gamut/src/Popover/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useWindowScroll, useWindowSize } from 'react-use';
import { FocusTrap } from '../FocusTrap';
import {
Beak,
BeakBox,
PatternContainer,
PopoverContainer,
PopoverPortal,
Expand Down Expand Up @@ -172,12 +173,16 @@ export const Popover: React.FC<PopoverProps> = ({
widthRestricted={widthRestricted}
>
{beak && (
<Beak
outline={outline ? 'outline' : 'boxShadow'}
beak={`${position}-${beak}${variant === 'secondary' ? '-sml' : ''}`}
data-testid="popover-beak"
size={variant === 'secondary' ? 'sml' : 'lrg'}
/>
<BeakBox variant={position}>
<Beak
beak={`${position}-${beak}${
variant === 'secondary' ? '-sml' : ''
}`}
data-testid="popover-beak"
size={variant === 'secondary' ? 'sml' : 'lrg'}
hasBorder={outline || variant === 'secondary'}
/>
</BeakBox>
)}
{children}
</RaisedDiv>
Expand Down
13 changes: 9 additions & 4 deletions packages/gamut/src/Popover/elements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { AnimatePresence, motion } from 'framer-motion';
import * as React from 'react';

import { BodyPortal } from '../BodyPortal';
import { Box } from '../Box';
import { Box, FlexBox } from '../Box';
import { popoverToolTipBodyAlignments } from '../Tip/shared/styles';
import { WithChildrenProp } from '../utils';
import {
beakBorderStates,
beakBoxVariants,
beakSize,
beakVariants,
outlineVariants,
Expand Down Expand Up @@ -39,10 +41,13 @@ export const RaisedDiv = styled.div<

export const Beak = styled(Box)<
StyleProps<typeof popoverStates> &
StyleProps<typeof outlineVariants> &
StyleProps<typeof beakVariants> &
StyleProps<typeof beakSize>
>(beakVariants, beakSize);
StyleProps<typeof beakSize> &
StyleProps<typeof beakBorderStates>
>(beakBorderStates, beakVariants, beakSize);

export const BeakBox =
styled(FlexBox)<StyleProps<typeof beakBoxVariants>>(beakBoxVariants);

export const PatternContainer = styled.div(
variant({
Expand Down
30 changes: 27 additions & 3 deletions packages/gamut/src/Popover/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const raisedDivVariants = variant({
},
});

const borderStyles = { border: 1 } as const;
export const outlineVariants = variant({
defaultVariant: 'boxShadow',
prop: 'outline',
Expand All @@ -36,8 +37,7 @@ export const outlineVariants = variant({
boxShadow: '0 0 16px rgba(0, 0, 0, 0.1), 0 0 24px rgba(0, 0, 0, 0.15)',
},
outline: {
borderColor: 'secondary',
border: 1,
...borderStyles,
boxShadow: 'none',
},
},
Expand All @@ -50,6 +50,28 @@ export const widthStates = states({
},
});

export const beakBorderStates = states({
hasBorder: borderStyles,
});

export const beakBoxVariants = variant({
base: {
alignItems: 'flex-end',
height: '15px',
justifyContent: 'center',
left: 0,
position: 'absolute',
width: '100%',
},
variants: {
above: {
bottom: -15,
},
below: {
top: -15,
},
},
});
const beakVariantsArray = [
'below-left',
'below-right',
Expand All @@ -72,8 +94,10 @@ const beakVariantStyles = createVariantsFromAlignments(

export const beakVariants = variant({
base: {
position: 'absolute',
transform: 'rotate(45deg)',
background: 'transparent',
zIndex: 1,
position: 'fixed',
},
prop: 'beak',
variants: beakVariantStyles,
Expand Down
16 changes: 8 additions & 8 deletions packages/gamut/src/Popover/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { theme } from '@codecademy/gamut-styles';
import { tooltipBackgroundColor } from '../Tip/shared/styles';

const popoverAbove = {
borderRight: 'inherit',
borderBottom: 'inherit',
borderLeft: 'none',
borderTop: 'none',
top: 'calc(100% - 10px)',
} as const;

const popoverBelow = {
borderLeft: 'inherit',
borderTop: 'inherit',
borderRight: 'none',
borderBottom: 'none',
top: '-10px',
} as const;

Expand All @@ -27,14 +27,14 @@ const beakCenter = {
};

const popoverAboveSml = {
borderRight: 'inherit',
borderBottom: 'inherit',
borderLeft: 'none',
borderTop: 'none',
top: 'calc(100% - 8px)',
} as const;

const popoverBelowSml = {
borderLeft: 'inherit',
borderTop: 'inherit',
borderRight: 'none',
borderBottom: 'none',
top: '-8px',
} as const;

Expand Down
20 changes: 12 additions & 8 deletions packages/gamut/src/Tip/shared/FloatingTip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { useLayoutEffect, useRef, useState } from 'react';
import * as React from 'react';
import { useMeasure } from 'react-use';

import { Box, FlexBox } from '../../Box';
import { Box } from '../../Box';
import { PreviewTipContents } from '../PreviewTip/elements';
import { FloatingTipBody, TargetContainer } from './elements';
import { narrowWidth } from './styles';
import {
FloatingTipBody,
FloatingTipTextWrapper,
TargetContainer,
} from './elements';
import { TipWrapperProps } from './types';
import { getAlignmentWidths, getPopoverAlignment, runWithDelay } from './utils';

Expand Down Expand Up @@ -113,6 +116,7 @@ export const FloatingTip: React.FC<TipWrapperProps> = ({
onFocus={toolOnlyEventFunc}
onBlur={toolOnlyEventFunc}
onMouseEnter={toolOnlyEventFunc}
onMouseDown={(e) => e.preventDefault()}
onKeyDown={
escapeKeyPressHandler ? (e) => escapeKeyPressHandler(e) : undefined
}
Expand All @@ -133,14 +137,14 @@ export const FloatingTip: React.FC<TipWrapperProps> = ({
variant="secondary"
widthRestricted={false}
>
<FlexBox
alignItems={isHoverType ? undefined : 'flex-start'}
flexDirection="column"
<FloatingTipTextWrapper
ref={childRef}
width={narrow ? narrowWidth : undefined}
isHoverType={isHoverType}
narrow={narrow}
centered={alignment.includes('center')}
>
{contents}
</FlexBox>
</FloatingTipTextWrapper>
</FloatingTipBody>
</Box>
);
Expand Down
22 changes: 20 additions & 2 deletions packages/gamut/src/Tip/shared/elements.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import { css, timing } from '@codecademy/gamut-styles';
import { css, states, timing } from '@codecademy/gamut-styles';
import { StyleProps } from '@codecademy/variance';
import styled from '@emotion/styled';

import { Box } from '../../Box';
import { Box, FlexBox } from '../../Box';
import { Selectors } from '../../ButtonBase/ButtonBase';
import { Popover } from '../../Popover';
import {
centerWidths,
inlineToolTipBodyAlignments,
narrowWidth,
toolTipBodyCss,
toolTipWidthRestrictions,
} from './styles';

const tipWrapperStyles = {
position: 'relative',
display: 'inline-flex',
overflowWrap: 'break-word',
} as const;

const floatingTipTextStates = states({
isHoverType: { alignItems: 'flexStart' },
narrow: { width: narrowWidth },
centered: {
...centerWidths,
},
});

export const FloatingTipTextWrapper = styled(FlexBox)<
StyleProps<typeof floatingTipTextStates>
>(
css({ flexDirection: 'column', overflowWrap: 'break-word' }),
floatingTipTextStates
);

export const ToolTipWrapper = styled.div(
css({
'&:hover > div, &:focus-within > div': {
Expand Down
15 changes: 15 additions & 0 deletions packages/gamut/src/Tip/shared/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export const topStyles = {
pb: containerOffsetVertical,
} as const;

const beforeStyles = {
content: '""',
position: 'absolute',
width: '100%',
};

export const topStylesBefore = { ...beforeStyles, height: 16, bottom: '-4px' };

export const topStylesAfter = {
borderColor: 'currentColor',
borderWidth: '0 1px 1px 0',
Expand All @@ -42,6 +50,12 @@ export const bottomStyles = {
pt: containerOffsetVertical,
} as const;

export const bottomStylesBefore = {
...beforeStyles,
height: 24,
top: '-8px',
};

export const bottomStylesAfter = {
borderColor: 'currentColor',
borderWidth: '1px 0 0 1px',
Expand Down Expand Up @@ -104,6 +118,7 @@ export const toolTipAlignmentVariants = variant({
opacity: 0,
position: 'absolute',
visibility: 'hidden',

'&::after': {
content: '""',
display: 'block',
Expand Down
11 changes: 10 additions & 1 deletion packages/gamut/src/Tip/shared/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
bottomCenterStylesAfter,
bottomStyles,
bottomStylesAfter,
bottomStylesBefore,
centerStyles,
centerStylesAfter,
leftStyles,
Expand All @@ -14,6 +15,7 @@ import {
topCenterStylesAfter,
topStyles,
topStylesAfter,
topStylesBefore,
} from './styles';
import { TipPlacementComponentProps, TipWrapperProps } from './types';

Expand Down Expand Up @@ -62,13 +64,16 @@ export const getPopoverAlignment = ({
export const createToolTipVariantFromAlignment = (alignment: string) => {
let styleObject = {};
let styleObjectAfter = {};
let styleObjectBefore = {};

if (alignment.includes('top')) {
styleObject = { ...topStyles };
styleObjectAfter = { ...topStylesAfter };
styleObjectBefore = { ...topStylesBefore };
} else {
styleObject = { ...bottomStyles };
styleObjectAfter = { ...bottomStylesAfter };
styleObjectBefore = { ...bottomStylesBefore };
}

if (alignment.includes('center')) {
Expand All @@ -87,7 +92,11 @@ export const createToolTipVariantFromAlignment = (alignment: string) => {
styleObjectAfter = { ...styleObjectAfter, ...leftStylesAfter };
}

return { ...styleObject, '&::after': styleObjectAfter };
return {
...styleObject,
'&::after': styleObjectAfter,
'&::before': styleObjectBefore,
};
};

export const createVariantsFromAlignments = (
Expand Down
Loading