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

[FE] 툴팁 위치가 계속해서 변경되는 문제 해결 #446

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ export const Playground: Story = {
const s_td = css`
position: relative;

overflow: hidden;

width: 10rem;
max-width: 10rem;
height: 4rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { css } from '@emotion/react';

import theme from '@styles/theme';

export const s_tooltipTrigger = css`
width: 100%;
height: 100%;
`;

export const s_attendeeTooltipContainer = css`
display: flex;
flex-direction: column;
Expand Down
13 changes: 9 additions & 4 deletions frontend/src/components/AttendeeTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { css } from '@emotion/react';
import type { PropsWithChildren } from 'react';
import type { TooltipPosition } from 'types/tooltip';

import Tooltip from '@components/_common/Tooltip';
Expand All @@ -8,15 +9,18 @@ import {
s_attendeeTooltipContainer,
s_attendeesContainer,
s_tooltipTitle,
s_tooltipTrigger,
} from './AttendeeTooltip.styles';

interface AttendeeTooltipProps {
attendeeNames: string[];
position: TooltipPosition;
}

export default function AttendeeTooltip({ attendeeNames, position }: AttendeeTooltipProps) {
export default function AttendeeTooltip({
attendeeNames,
position,
children,
}: PropsWithChildren<AttendeeTooltipProps>) {
return (
<Tooltip
position={position}
Expand All @@ -33,10 +37,11 @@ export default function AttendeeTooltip({ attendeeNames, position }: AttendeeToo
</div>
}
visibleStyles={css`
border: 0.3rem dashed #71717a;
outline: 3px dashed #71717a;
outline-offset: -3px;
`}
>
<div css={s_tooltipTrigger} />
{children}
</Tooltip>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,39 @@ export default function SingleDateViewer({
if (selectAttendee !== '' && availableAttendees) return <Check width={12} height={12} />;
};

const renderTooltip = () =>
selectAttendee === '' &&
availableAttendees && <AttendeeTooltip attendeeNames={availableAttendees} position="top" />;
const hasAttendeeTooltip = selectAttendee === '' && availableAttendees;

return status === 'current' ? (
if (status !== 'current') return <div css={s_dateContainer}></div>;

return hasAttendeeTooltip ? (
<AttendeeTooltip attendeeNames={availableAttendees} position="top">
<div
css={[
s_dateContainer,
s_baseDateButton,
s_viewer,
s_dateText({
isDisabledDate: !isAvailable || isPrevDate,
isSelectedDate: false,
isToday,
isHoliday,
isSunday,
isSaturday,
}),
]}
role="text"
aria-hidden={!isAvailable}
aria-label={
isAvailable
? formatAriaFullDate(targetFullDate, targetDayOfWeekKR, availableAttendees)
: ''
}
>
<span css={s_baseDateText}>{date}</span>
<span css={s_additionalText}>{additionalText()}</span>
</div>
</AttendeeTooltip>
) : (
<div
css={[
s_dateContainer,
Expand All @@ -76,9 +104,6 @@ export default function SingleDateViewer({
>
<span css={s_baseDateText}>{date}</span>
<span css={s_additionalText}>{additionalText()}</span>
{renderTooltip()}
</div>
) : (
<div css={s_dateContainer}></div>
);
}
18 changes: 11 additions & 7 deletions frontend/src/components/Schedules/SchedulePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useState } from 'react';
import { useContext, useMemo, useState } from 'react';
import type { MeetingDateTime } from 'types/meeting';
import type { MeetingSingleSchedule, Mode } from 'types/schedule';

Expand Down Expand Up @@ -56,12 +56,16 @@ export default function SchedulePicker({

const { handleToggleIsTimePickerUpdate } = useContext(TimePickerUpdateStateContext);

const schedules = generateSingleScheduleTable({
firstTime,
lastTime,
availableDates,
meetingSingleSchedule,
});
const schedules = useMemo(
() =>
generateSingleScheduleTable({
firstTime,
lastTime,
availableDates,
meetingSingleSchedule,
}),
[availableDates, firstTime, lastTime, meetingSingleSchedule],
);

const {
tableRef,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import type { MeetingDateTime } from 'types/meeting';
import type { MeetingAllSchedules } from 'types/schedule';

Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Schedules/Schedules.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const s_baseTimeCell = (isHalfHour: boolean, isLastRow: boolean) => css`

export const s_bottomFixedButtonContainer = css`
position: sticky; /* 절대 위치로 부모 컨테이너 내에서 배치 */
z-index: 1; /* 툴팁이 푸터보다 위에 위치하는 문제를 해결하기 위해서 z-index 추가(@해리) */
bottom: 0;
left: 0;

Expand Down
33 changes: 28 additions & 5 deletions frontend/src/components/_common/Tooltip/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { css } from '@emotion/react';
import type { Meta, StoryObj } from '@storybook/react';
import { Fragment } from 'react';

import Tooltip from '.';

Expand Down Expand Up @@ -51,15 +53,36 @@ type Story = StoryObj<typeof Tooltip>;

export const Playground: Story = {
args: {
content: <div>안녕하세요 툴팁입니다</div>,
children: <button>마우스를 올려보세요</button>,
content: (
<div
css={css`
display: flex;
justify-content: center;
width: 20rem;
`}
>
안녕하세요 툴팁입니다
</div>
),
children: (
<button
css={css`
width: 20rem;
height: 10rem;
`}
>
마우스를 올려보세요
</button>
),
position: 'top',
},
render: (args) => {
return (
<Tooltip content={args.content} position={args.position}>
{args.children}
</Tooltip>
<Fragment>
<Tooltip content={args.content} position={args.position}>
{args.children}
</Tooltip>
</Fragment>
);
},
};
141 changes: 101 additions & 40 deletions frontend/src/components/_common/Tooltip/Tooltip.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,89 +3,150 @@ import { css } from '@emotion/react';
import type { TooltipPosition } from 'types/tooltip';

export const tooltipContainer = css`
position: absolute;
position: relative;
width: 100%;
height: 100%;
`;

export const tooltipContent = css`
position: absolute;
z-index: 1;
`;

export const getTooltipPosition = (position: TooltipPosition, targetRect: DOMRect | undefined) => {
if (!targetRect) return '';

export const getTooltipPosition = (position: TooltipPosition) => {
const positions = {
top: css`
top: ${targetRect.top + window.scrollY}px;
left: ${targetRect.left + targetRect.width / 2 + window.scrollX}px;
transform: translate(-50%, -100%);
bottom: 100%;
left: 50%;
transform: translateX(-50%);
`,
bottom: css`
top: ${targetRect.bottom + window.scrollY}px;
left: ${targetRect.left + targetRect.width / 2 + window.scrollX}px;
transform: translate(-50%, 0);
top: 100%;
left: 50%;
transform: translateX(-50%);
`,
right: css`
top: ${targetRect.top + targetRect.height / 2 + window.scrollY}px;
left: ${targetRect.right + window.scrollX}px;
transform: translate(0, -50%);
top: 50%;
left: 100%;
transform: translateY(-50%);
`,
left: css`
top: ${targetRect.top + targetRect.height / 2 + window.scrollY}px;
left: ${targetRect.left + window.scrollX}px;
transform: translate(-100%, -50%);
top: 50%;
right: 100%;
transform: translateY(-50%);
`,
topLeft: css`
top: ${targetRect.top + window.scrollY}px;
left: ${targetRect.left + window.scrollX}px;
transform: translate(0, -100%);
bottom: 100%;
left: 0;
`,
topRight: css`
top: ${targetRect.top + window.scrollY}px;
left: ${targetRect.right + window.scrollX}px;
transform: translate(-100%, -100%);
right: 0;
bottom: 100%;
`,
bottomLeft: css`
top: ${targetRect.bottom + window.scrollY}px;
left: ${targetRect.left + window.scrollX}px;
transform: translate(0, 0);
top: 100%;
left: 0;
`,
bottomRight: css`
top: ${targetRect.bottom + window.scrollY}px;
left: ${targetRect.right + window.scrollX}px;
transform: translateX(0) translateY(0);
top: 100%;
right: 0;
`,
leftTop: css`
top: ${targetRect.top + window.scrollY}px;
left: ${targetRect.left + window.scrollX}px;
transform: translate(-100%, 0);
top: 0;
right: 100%;
`,
leftBottom: css`
top: ${targetRect.bottom + window.scrollY}px;
left: ${targetRect.left + window.scrollX}px;
transform: translate(-100%, -100%);
right: 100%;
bottom: 0;
`,
rightTop: css`
top: ${targetRect.top + window.scrollY}px;
left: ${targetRect.right + window.scrollX}px;
transform: translate(0, 0);
top: 0;
left: 100%;
`,
rightBottom: css`
top: ${targetRect.bottom + window.scrollY}px;
left: ${targetRect.right + window.scrollX}px;
transform: translate(0, -100%);
bottom: 0;
left: 100%;
`,
};

return positions[position] || positions.top;
};

// export const getTooltipPosition = (position: TooltipPosition, targetRect: DOMRect | undefined) => {
// if (!targetRect) return '';

// const positions = {
// top: css`
// top: ${targetRect.top + window.scrollY}px;
// left: ${targetRect.left + targetRect.width / 2 + window.scrollX}px;
// transform: translate(-50%, -100%);
// `,
// bottom: css`
// top: ${targetRect.bottom + window.scrollY}px;
// left: ${targetRect.left + targetRect.width / 2 + window.scrollX}px;
// transform: translate(-50%, 0);
// `,
// right: css`
// top: ${targetRect.top + targetRect.height / 2 + window.scrollY}px;
// left: ${targetRect.right + window.scrollX}px;
// transform: translate(0, -50%);
// `,
// left: css`
// top: ${targetRect.top + targetRect.height / 2 + window.scrollY}px;
// left: ${targetRect.left + window.scrollX}px;
// transform: translate(-100%, -50%);
// `,
// topLeft: css`
// top: ${targetRect.top + window.scrollY}px;
// left: ${targetRect.left + window.scrollX}px;
// transform: translate(0, -100%);
// `,
// topRight: css`
// top: ${targetRect.top + window.scrollY}px;
// left: ${targetRect.right + window.scrollX}px;
// transform: translate(-100%, -100%);
// `,
// bottomLeft: css`
// top: ${targetRect.bottom + window.scrollY}px;
// left: ${targetRect.left + window.scrollX}px;
// transform: translate(0, 0);
// `,
// bottomRight: css`
// top: ${targetRect.bottom + window.scrollY}px;
// left: ${targetRect.right + window.scrollX}px;
// transform: translateX(0) translateY(0);
// `,
// leftTop: css`
// top: ${targetRect.top + window.scrollY}px;
// left: ${targetRect.left + window.scrollX}px;
// transform: translate(-100%, 0);
// `,
// leftBottom: css`
// top: ${targetRect.bottom + window.scrollY}px;
// left: ${targetRect.left + window.scrollX}px;
// transform: translate(-100%, -100%);
// `,
// rightTop: css`
// top: ${targetRect.top + window.scrollY}px;
// left: ${targetRect.right + window.scrollX}px;
// transform: translate(0, 0);
// `,
// rightBottom: css`
// top: ${targetRect.bottom + window.scrollY}px;
// left: ${targetRect.right + window.scrollX}px;
// transform: translate(0, -100%);
// `,
// };

// return positions[position] || positions.top;
// };

export const s_tooltipTrigger = (
isVisible: boolean,
visibleStyles: SerializedStyles | undefined,
) => css`
cursor: pointer;
width: 100%;
height: 100%;
${isVisible && visibleStyles}
`;
Loading
Loading