Skip to content
Merged
Show file tree
Hide file tree
Changes from 82 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
f854d27
feat: left/right tooltips
dreamwasp Apr 24, 2025
6dc46ae
Merge branch 'main' into cass-gm-1094
dreamwasp May 2, 2025
d136884
divide and conquer
dreamwasp May 2, 2025
281e809
getting closer to styles
dreamwasp May 2, 2025
f7af321
start with styles
dreamwasp May 2, 2025
7219b32
basic inline alignment
dreamwasp May 2, 2025
2795a2e
getting closer to popover solution
dreamwasp May 2, 2025
60d615d
tweak stories + removeuseEffects
dreamwasp May 5, 2025
b33f17f
starting to get things working with beak!
dreamwasp May 5, 2025
176282c
popover working and major progress on types
dreamwasp May 6, 2025
19778e0
somethings are broken but lets take a look
dreamwasp May 6, 2025
4723158
center popovers working again
dreamwasp May 6, 2025
fa0ec5e
progress progress progress
dreamwasp May 6, 2025
96b7e5a
center alignment added - need to tweak left beak
dreamwasp May 7, 2025
61ce097
tweaked
dreamwasp May 7, 2025
e97306a
clean up + to-dos
dreamwasp May 8, 2025
a604386
review changes
dreamwasp May 8, 2025
fec78e3
fix margin changes
dreamwasp May 8, 2025
712e9bd
widths sorted
dreamwasp May 9, 2025
1a1f69d
widths sorted - need to fix InfoTip positioning
dreamwasp May 9, 2025
0b51eee
more progress on inline - need to dedupe
dreamwasp May 9, 2025
8385469
tempermental commit - revisit
dreamwasp May 12, 2025
55c0a12
working styles - lots of restructure needed
dreamwasp May 12, 2025
a64b2b1
fixing more stuff
dreamwasp May 12, 2025
60cf683
put hover isOpen back
dreamwasp May 12, 2025
9d72f79
remove duplicated beak styles
dreamwasp May 12, 2025
180375c
fix preview + infotip alignment
dreamwasp May 12, 2025
f5772cf
Merge branch 'main' into cass-gm-1094
dreamwasp May 13, 2025
02ded10
turn on hover view + fix floating tooltip offset
dreamwasp May 13, 2025
bdf22ff
Merge branch 'cass-gm-1094' of ssh://github.com/Codecademy/gamut into…
dreamwasp May 13, 2025
3c4f709
better ifs
dreamwasp May 13, 2025
9e7c662
figure out whats up with inline center
dreamwasp May 13, 2025
4ad8dc6
tooltip center alignments fixed
dreamwasp May 13, 2025
a1e443f
tweak to pass build + start testing against mono + monolith
dreamwasp May 16, 2025
834b3b3
remove unneeded item in alignement arr
dreamwasp May 16, 2025
7640e39
merge in main
dreamwasp May 16, 2025
260d757
fix popover beak
dreamwasp May 16, 2025
02d097e
add tooltip storybook controls
dreamwasp May 21, 2025
9ebeec7
fix floatingToolTip offset + story
dreamwasp May 21, 2025
39f2813
merge in main
dreamwasp May 21, 2025
a34a888
remove hard-code;
dreamwasp May 21, 2025
ea2ce0c
finishing touches!
dreamwasp May 21, 2025
fc6a150
add better comments
dreamwasp May 22, 2025
f1a007e
Merge branch 'main' into cass-gm-1094
dreamwasp May 28, 2025
d5ff390
kenny feedback
dreamwasp May 29, 2025
1f69b68
add a beak
dreamwasp May 29, 2025
f4c7550
to a
dreamwasp May 29, 2025
ef2a570
rename to position
dreamwasp May 29, 2025
77d2398
Merge branch 'main' into cass-gm-1094
dreamwasp May 30, 2025
1b7e7ef
fix popover + more stories
dreamwasp May 30, 2025
4cb7302
merge in dev
dreamwasp May 30, 2025
840ee93
formatted
dreamwasp May 30, 2025
a19a79d
fix beak type
dreamwasp May 30, 2025
aebc3a5
split popover into more reasonable files
dreamwasp May 30, 2025
fe5bc3e
fix iconbutton test
dreamwasp Jun 2, 2025
59b09cd
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 2, 2025
6123cc5
fix popover stories
dreamwasp Jun 2, 2025
4b60e0b
fixed right center popover story"
dreamwasp Jun 2, 2025
791033a
fixed
dreamwasp Jun 2, 2025
f4891e7
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 3, 2025
85045f8
more reasonable naming conventions
dreamwasp Jun 3, 2025
76a7894
Merge branch 'cass-gm-1094' of github.com:Codecademy/gamut into cass-…
dreamwasp Jun 3, 2025
3e6e01c
sort imports
dreamwasp Jun 3, 2025
3b19e7c
facepalm
dreamwasp Jun 3, 2025
946a38c
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 3, 2025
390a806
fixed center-left
dreamwasp Jun 3, 2025
05ec7b6
Merge branch 'cass-gm-1094' of github.com:Codecademy/gamut into cass-…
dreamwasp Jun 3, 2025
cf44b38
remove console.log
dreamwasp Jun 3, 2025
446ef42
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 4, 2025
5515e68
fix offsets
dreamwasp Jun 4, 2025
6d043d1
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 5, 2025
f1462e4
fix tip color for darkmode
dreamwasp Jun 5, 2025
df50168
Merge branch 'cass-gm-1094' of github.com:Codecademy/gamut into cass-…
dreamwasp Jun 5, 2025
eece796
remove isOpen test
dreamwasp Jun 5, 2025
a98e1b8
make new function
dreamwasp Jun 5, 2025
ac2902c
use default offset func
dreamwasp Jun 5, 2025
383e5d2
removed after from shared style names
dreamwasp Jun 5, 2025
f8fc411
remove after
dreamwasp Jun 5, 2025
8ea380f
remove old story
dreamwasp Jun 5, 2025
799b38b
whoops
dreamwasp Jun 5, 2025
8308807
kenny nits
dreamwasp Jun 5, 2025
3ab9c9d
refactor to transform instead of changing bgcolor 💡
dreamwasp Jun 6, 2025
149e5e8
rename func
dreamwasp Jun 6, 2025
c650966
Merge branch 'main' into cass-gm-1094
dreamwasp Jun 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions packages/gamut/src/Coachmark/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import { useRef } from 'react';
import * as React from 'react';

import { DelayedRenderWrapper } from '../DelayedRenderWrapper';
import { Popover, PopoverBaseProps, PopoverProps } from '../Popover';
import {
Popover,
PopoverFocusProps,
PopoverProps,
PopoverYPositionType,
} from '../Popover';

export type CoachmarkProps = PopoverBaseProps & {
export type CoachmarkProps = PopoverFocusProps & {
/**
* Applied to the element to which the coachmark points.
*/
Expand All @@ -29,7 +34,9 @@ export type CoachmarkProps = PopoverBaseProps & {
/**
* Props to be passed into the popover component.
*/
popoverProps?: Partial<PopoverProps>;
popoverProps?: Partial<
Omit<PopoverProps, 'beak' | 'position'> & PopoverYPositionType
>;
};

export const Coachmark: React.FC<CoachmarkProps> = ({
Expand Down
95 changes: 55 additions & 40 deletions packages/gamut/src/Popover/Popover.tsx
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useCallback, useEffect, useState } from 'react';
import * as React from 'react';
import { useWindowScroll, useWindowSize } from 'react-use';

import { FocusTrap } from '../FocusTrap';
Expand All @@ -11,45 +10,20 @@ import {
PopoverPortal,
RaisedDiv,
} from './elements';
import { getBeakVariant } from './styles/beak';
import { PopoverProps } from './types';

const findScrollingParent = ({
parentElement,
}: HTMLElement): HTMLElement | null => {
if (parentElement) {
const { overflow, overflowY, overflowX } = getComputedStyle(parentElement);
if (
[overflow, overflowY, overflowX].some((val) =>
['scroll', 'auto'].includes(val)
)
) {
return parentElement;
}
return findScrollingParent(parentElement); // parent of this parent is used via prop destructure
}
return null;
};

const findResizingParent = ({
parentElement,
}: HTMLElement): HTMLElement | null => {
if (parentElement) {
const { overflow, overflowY, overflowX } = getComputedStyle(parentElement);
if ([overflow, overflowY, overflowX].some((val) => val === 'clip')) {
return parentElement;
}
return findResizingParent(parentElement); // parent of this parent is used via prop destructure
}
return null;
};
import {
findResizingParent,
findScrollingParent,
getDefaultOffset,
} from './utils';

export const Popover: React.FC<PopoverProps> = ({
animation,
align = 'left',
beak,
children,
className,
horizontalOffset = 0,
isOpen,
onRequestClose,
outline = false,
Expand All @@ -60,30 +34,72 @@ export const Popover: React.FC<PopoverProps> = ({
role,
variant,
targetRef,
verticalOffset = variant === 'secondary' ? 15 : 20,
horizontalOffset = getDefaultOffset({
axis: 'horizontal',
position,
variant,
}),
verticalOffset = getDefaultOffset({ axis: 'vertical', position, variant }),

widthRestricted,
}) => {
const [popoverHeight, setPopoverHeight] = useState<number>(0);
const [popoverWidth, setPopoverWidth] = useState<number>(0);
const [targetRect, setTargetRect] = useState<DOMRect>();
const [isInViewport, setIsInViewport] = useState(true);
const { width, height } = useWindowSize();
const { x, y } = useWindowScroll();

const getRaisedDivDimsRef = (popover: HTMLDivElement) => {
if (popover && popoverHeight === 0 && popoverWidth === 0) {
const { height, width } = popover.getBoundingClientRect();
setPopoverHeight(height);
setPopoverWidth(width);
}
};

const getPopoverPosition = useCallback(() => {
if (!targetRect) return {};

const isLRCentered = position === 'center';

const positions = {
above: Math.round(targetRect.top - verticalOffset),
below: Math.round(targetRect.top + targetRect.height + verticalOffset),
center: Math.round(
targetRect.top +
targetRect.height / 2 -
popoverHeight / 2 +
verticalOffset
),
};
const alignments = {
right: Math.round(window.scrollX + targetRect.right + horizontalOffset),
left: Math.round(window.scrollX + targetRect.left - horizontalOffset),
right: isLRCentered
? Math.round(targetRect.right + popoverWidth + horizontalOffset)
: Math.round(window.scrollX + targetRect.right + horizontalOffset),
left: isLRCentered
? Math.round(targetRect.left - popoverWidth - horizontalOffset)
: Math.round(window.scrollX + targetRect.left - horizontalOffset),
center: Math.round(
targetRect.left +
targetRect.width / 2 -
popoverWidth / 2 +
horizontalOffset
),
};
return {
top: positions[position],
left: alignments[align],
};
}, [targetRect, verticalOffset, horizontalOffset, align, position]);
}, [
align,
horizontalOffset,
popoverHeight,
popoverWidth,
position,
targetRect,
verticalOffset,
]);

useEffect(() => {
setTargetRect(targetRef?.current?.getBoundingClientRect());
Expand Down Expand Up @@ -149,12 +165,12 @@ export const Popover: React.FC<PopoverProps> = ({
},
[onRequestClose, targetRef]
);

if ((!isOpen || !targetRef) && !animation) return null;
const alignment =
(variant === 'primary' || beak) && beak !== 'center'
? 'aligned'
: 'centered';

const contents = (
<PopoverContainer
align={align}
Expand All @@ -169,15 +185,14 @@ export const Popover: React.FC<PopoverProps> = ({
<RaisedDiv
alignment={alignment}
outline={outline ? 'outline' : 'boxShadow'}
ref={getRaisedDivDimsRef}
variant={variant}
widthRestricted={widthRestricted}
>
{beak && (
<BeakBox variant={position}>
<Beak
beak={`${position}-${beak}${
variant === 'secondary' ? '-sml' : ''
}`}
beak={getBeakVariant({ align, position, beak, variant })}
data-testid="popover-beak"
hasBorder={outline || variant === 'secondary'}
size={variant === 'secondary' ? 'sml' : 'lrg'}
Expand Down
15 changes: 8 additions & 7 deletions packages/gamut/src/Popover/elements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@ import { timingValues, variant } from '@codecademy/gamut-styles';
import { StyleProps } from '@codecademy/variance';
import styled from '@emotion/styled';
import { AnimatePresence, motion } from 'framer-motion';
import * as React from 'react';

import { BodyPortal } from '../BodyPortal';
import { Box, FlexBox } from '../Box';
import { popoverToolTipBodyAlignments } from '../Tip/shared/styles';
import { popoverToolTipBodyAlignments } from '../Tip/shared/styles/styles';
import { WithChildrenProp } from '../utils';
import {
popoverStates,
raisedDivVariants,
transformValues,
} from './styles/base';
import { patternContainerBaseStyles } from './styles/pattern';
import {
beakBorderStates,
beakBoxVariants,
beakSize,
beakVariants,
outlineVariants,
patternContainerBaseStyles,
patternVariantStyles,
popoverStates,
raisedDivVariants,
transformValues,
widthStates,
} from './styles';
} from './styles/variants';
import { PopoverProps } from './types';

export type PopoverVariants = StyleProps<typeof raisedDivVariants> & {
Expand Down
44 changes: 44 additions & 0 deletions packages/gamut/src/Popover/styles/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { states, variant } from '@codecademy/gamut-styles';

import { toolTipBodyCss } from '../../Tip/shared/styles/styles';

export const borderStyles = { border: 1 } as const;
export const popoverPrimaryBgColor = `background`;

/**
* For the Popover + Tooltip style files:
*
* 'above' + 'below' map to position, 'top' + 'bottom' map to beak alignment
* variants for both follow this formula: `position`-`beakPosition`
* Popovers additionally will have `-sml` added to the end of this string if they are the `secondary` variant
*
*/

export const transformValues = {
right: 'translateX(-100%)',
left: 'translateX(0%)',
above: 'translateY(-100%)',
below: 'translateY(0%)',
center: '',
};

export const popoverStates = states({
widthRestricted: {
minWidth: '4rem',
maxWidth: '16rem',
},
});

export const raisedDivVariants = variant({
base: {
zIndex: 1,
},
defaultVariant: 'primary',
variants: {
primary: {
bg: popoverPrimaryBgColor,
borderRadius: 'sm',
},
secondary: { ...toolTipBodyCss },
},
});
Loading
Loading