Skip to content

Commit

Permalink
feat: added tooltips
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraghazra committed Jun 19, 2020
1 parent 060764e commit f5c2f5c
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 12 deletions.
195 changes: 195 additions & 0 deletions client/src/@convoy-ui/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import React, { useRef, useEffect, useState } from "react";
import styled, { css, CSSProp } from "styled-components";

type PLACEMENTS =
| "top"
| "left"
| "bottom"
| "right"
| "bottom-left"
| "top-left";

const caret = css`
position: absolute;
content: "";
width: 0;
height: 0;
`;
const centerV = css`
top: 50%;
transform: translateY(-50%);
`;
const centerH = css`
left: 50%;
transform: translateX(-50%);
`;

const fourCarets: Record<
Extract<PLACEMENTS, "top" | "left" | "bottom" | "right">,
CSSProp
> = {
top: css`
${caret};
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid ${p => p.theme.colors.gray};
top: 100%;
`,
bottom: css`
${caret};
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid ${p => p.theme.colors.gray};
bottom: 100%;
`,
left: css`
${caret};
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid ${p => p.theme.colors.gray};
left: 100%;
`,
right: css`
${caret};
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-right: 5px solid ${p => p.theme.colors.gray};
right: 100%;
`,
};

const carets: Record<PLACEMENTS, CSSProp> = {
...fourCarets,
"bottom-left": css`
${caret};
${fourCarets.bottom};
`,
"top-left": css`
${caret};
${fourCarets.top};
`,
};

const placements = {
top: css`
bottom: 100%;
margin-bottom: 5px;
${centerH};
&:before {
${carets.top};
${centerH};
}
`,
bottom: css`
top: 100%;
margin-top: 5px;
${centerH};
&:before {
${carets.bottom};
${centerH};
}
`,
left: css`
top: 50%;
right: 100%;
transform: translateY(-50%);
margin-right: 5px;
${centerV};
&:before {
${carets.left};
${centerV};
}
`,
right: css`
left: 100%;
margin-left: 5px;
${centerV};
&:before {
${carets.right};
${centerV};
}
`,
"bottom-left": css`
top: 100%;
margin-top: 5px;
right: 0;
&:before {
${carets.bottom};
right: 10px;
}
`,
"top-left": css`
bottom: 100%;
margin-bottom: 5px;
right: 0;
&:before {
${carets.top};
right: 10px;
}
`,
};

const TooltipStyles = styled.div<{ placement: PLACEMENTS }>`
position: relative;
width: fit-content;
.tooltip__trigger:hover + .tooltip__message {
opacity: 1;
transition-delay: 0.3s;
}
.tooltip__message {
position: absolute;
width: fit-content;
padding: 5px 10px;
font-size: 12px;
white-space: pre;
background-color: ${p => p.theme.colors.dark2};
border: 1px solid ${p => p.theme.colors.gray};
border-radius: ${p => p.theme.radius.small}px;
opacity: 0;
transition: 0.2s;
pointer-events: none;
z-index: 1;
${p => (placements as any)[p.placement as any]};
}
`;

interface ITooltip {
message: React.ReactNode;
placement?: PLACEMENTS;
}

export const Tooltip: React.FC<ITooltip> = ({
children,
message,
placement = "top",
}) => {
const [position, setPosition] = useState<PLACEMENTS>(placement);
const contentRef = useRef<HTMLDivElement>();
const calculateBounds = () => {
if (contentRef.current) {
const bounds = contentRef.current.getBoundingClientRect();
if (bounds.left < 5) setPosition("right");
if (bounds.top < 5) setPosition("bottom");
if (bounds.right > window.innerWidth) setPosition("left");
if (bounds.bottom > window.innerHeight) setPosition("top");
}
};

useEffect(() => {
calculateBounds();
}, []);

return (
<TooltipStyles placement={position}>
<div className="tooltip__trigger">{children}</div>
<div className="tooltip__message" ref={contentRef}>
{message}
</div>
</TooltipStyles>
);
};

export default Tooltip;
1 change: 1 addition & 0 deletions client/src/@convoy-ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from "./Input";
export * from "./Loading";
export * from "./Spacer";
export * from "./Toast";
export * from "./Tooltip";
21 changes: 16 additions & 5 deletions client/src/components/Member/Member.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from "react";
import styled from "styled-components";
import { Avatar, Flex, IconButton } from "@convoy-ui";
import { Avatar, Flex, IconButton, Tooltip } from "@convoy-ui";
import { RoomMemberFragment } from "graphql/generated/graphql";
import { FiUserMinus } from "react-icons/fi";
import { useAuthContext } from "contexts/AuthContext";

const StyledMember = styled.section`
padding: 15px;
Expand All @@ -26,6 +27,9 @@ interface MemberProps {
onActionClick?: (useId?: RoomMemberFragment) => void;
}
const Member: React.FC<MemberProps> = ({ user, onActionClick }) => {
const { user: currentUser } = useAuthContext();
const isCurrentUser = currentUser.id === user.id;

return (
<StyledMember>
<Flex gap="medium" align="center" justify="space-between" nowrap>
Expand All @@ -39,10 +43,17 @@ const Member: React.FC<MemberProps> = ({ user, onActionClick }) => {
</Flex>
</Flex>

<IconButton
onClick={() => onActionClick(user)}
icon={<FiUserMinus />}
/>
{!isCurrentUser && (
<Tooltip
placement="top-left"
message={<span>Remove member from group</span>}
>
<IconButton
icon={<FiUserMinus />}
onClick={() => onActionClick(user)}
/>
</Tooltip>
)}
</Flex>
</StyledMember>
);
Expand Down
12 changes: 7 additions & 5 deletions client/src/components/RoomsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MdAdd } from "react-icons/md";
import { useHistory } from "react-router-dom";
import { useListCurrentUserRoomsQuery } from "graphql/generated/graphql";

import { Flex, Spacer, Loading, IconButton } from "@convoy-ui";
import { Flex, Spacer, Loading, IconButton, Tooltip } from "@convoy-ui";
import { useModalContext } from "contexts/ModalContext";

import RoomLink from "components/RoomLink";
Expand Down Expand Up @@ -32,10 +32,12 @@ const RoomsList: React.FC = () => {

<Flex align="center" justify="space-between">
<h3>Your Rooms</h3>
<IconButton
onClick={() => dispatch({ type: "OPEN", modal: "CreateRoom" })}
icon={<MdAdd />}
/>
<Tooltip placement="top" message={<span>Create new room</span>}>
<IconButton
onClick={() => dispatch({ type: "OPEN", modal: "CreateRoom" })}
icon={<MdAdd />}
/>
</Tooltip>
</Flex>
<Spacer gap="large" />

Expand Down
9 changes: 7 additions & 2 deletions client/src/components/UserInfoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import styled, { css } from "styled-components";

import { AiFillSetting } from "react-icons/ai";
import { Flex, Avatar } from "@convoy-ui";
import { Flex, Avatar, Tooltip, IconButton } from "@convoy-ui";

const StyledUserInfoCard = styled.section<{ isMember?: boolean }>`
padding: 10px 0;
Expand Down Expand Up @@ -48,7 +48,12 @@ const UserInfoCard: React.FC<IUserInfoCard> = ({
{username?.slice(0, 15)}...
</small>
</Flex>
{!isMember && <AiFillSetting size={20} />}

{!isMember && (
<Tooltip placement="right" message={<span>Settings</span>}>
<IconButton icon={<AiFillSetting size={20} />} />
</Tooltip>
)}
</Flex>
</StyledUserInfoCard>
);
Expand Down

0 comments on commit f5c2f5c

Please sign in to comment.