-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ - feat: implemented the tooltip component
- Loading branch information
1 parent
a0c7f56
commit 2021471
Showing
5 changed files
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./tooltip"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
.mykn-tooltip { | ||
transition: opacity 0.5s; | ||
transform: scale(0.8); | ||
opacity: 0; | ||
border-radius: var(--border-radius-m); | ||
|
||
&--open { | ||
opacity: 1; | ||
background-color: var(--theme-color-primary-200); | ||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1); | ||
transform: scale(1); | ||
} | ||
|
||
&__arrow { | ||
fill: var(--theme-color-tertiary-400); | ||
} | ||
|
||
&__content { | ||
padding: var(--spacing-h-m) var(--spacing-v-m); | ||
box-sizing: border-box; | ||
overflow-wrap: break-word; | ||
|
||
&--sm { | ||
max-width: 200px; | ||
} | ||
|
||
&--md { | ||
max-width: 400px; | ||
} | ||
|
||
&--lg { | ||
max-width: 600px; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import React from "react"; | ||
|
||
import { Button } from "../button"; | ||
import { Outline } from "../icon"; | ||
import { Tooltip } from "./tooltip"; | ||
|
||
const meta = { | ||
title: "Controls/Tooltip", | ||
component: Tooltip, | ||
decorators: [ | ||
(Story) => ( | ||
<div style={{ padding: "2rem" }}> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
} satisfies Meta<typeof Tooltip>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof meta>; | ||
|
||
export const TooltipComponent: Story = { | ||
args: { | ||
children: ( | ||
<Button variant="transparent"> | ||
<Outline.InformationCircleIcon>Hover me</Outline.InformationCircleIcon> | ||
</Button> | ||
), | ||
content: | ||
"This tooltip works by hovering over any react element, and it can be placed in any direction.", | ||
}, | ||
}; | ||
|
||
export const TooltipTop: Story = { | ||
args: { | ||
...TooltipComponent.args, | ||
placement: "top", | ||
}, | ||
decorators: [ | ||
(Story) => ( | ||
<div style={{ paddingTop: "4rem" }}> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
}; | ||
|
||
export const TooltipRight: Story = { | ||
args: { | ||
...TooltipComponent.args, | ||
placement: "right", | ||
}, | ||
}; | ||
|
||
export const TooltipBottom: Story = { | ||
args: { | ||
...TooltipComponent.args, | ||
placement: "bottom", | ||
}, | ||
}; | ||
|
||
export const TooltipLeft: Story = { | ||
args: { | ||
...TooltipComponent.args, | ||
placement: "left", | ||
}, | ||
decorators: [ | ||
(Story) => ( | ||
<div style={{ display: "flex", justifyContent: "end" }}> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
}; | ||
|
||
export const TooltipBigText: Story = { | ||
args: { | ||
...TooltipComponent.args, | ||
content: ( | ||
<div> | ||
<p> | ||
This tooltip works by hovering over any react element, and it can be | ||
placed in any direction. | ||
</p> | ||
<p> | ||
This tooltip works by hovering over any react element, and it can be | ||
placed in any direction. | ||
</p> | ||
<p> | ||
This tooltip works by hovering over any react element, and it can be | ||
placed in any direction. | ||
</p> | ||
</div> | ||
), | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { | ||
FloatingArrow, | ||
Placement, | ||
arrow, | ||
autoUpdate, | ||
flip, | ||
offset, | ||
shift, | ||
useDismiss, | ||
useFloating, | ||
useFocus, | ||
useHover, | ||
useInteractions, | ||
useRole, | ||
useTransitionStyles, | ||
} from "@floating-ui/react"; | ||
import clsx from "clsx"; | ||
import React, { ReactNode, useRef, useState } from "react"; | ||
|
||
import { P } from "../typography"; | ||
import "./tooltip.scss"; | ||
|
||
type TooltipProps = React.PropsWithChildren<{ | ||
/* The content to display in the tooltip */ | ||
content?: ReactNode; | ||
|
||
/* The placement of the tooltip */ | ||
placement?: Placement; | ||
|
||
/* The size of the tooltip, defaults to md */ | ||
size?: "sm" | "md" | "lg"; | ||
}>; | ||
|
||
export const Tooltip = ({ | ||
content, | ||
children, | ||
placement, | ||
size = "md", | ||
}: TooltipProps) => { | ||
const [isOpen, setIsOpen] = useState(false); | ||
const arrowRef = useRef(null); | ||
|
||
const { | ||
refs: { setReference, setFloating }, | ||
floatingStyles, | ||
context, | ||
} = useFloating({ | ||
open: isOpen, | ||
onOpenChange: setIsOpen, | ||
placement, | ||
middleware: [ | ||
offset(12), | ||
flip(), | ||
shift(), | ||
arrow({ | ||
element: arrowRef, | ||
}), | ||
], | ||
whileElementsMounted: autoUpdate, | ||
}); | ||
|
||
const hover = useHover(context, { move: false }); | ||
const focus = useFocus(context); | ||
const dismiss = useDismiss(context); | ||
const role = useRole(context, { role: "tooltip" }); | ||
|
||
const { getReferenceProps, getFloatingProps } = useInteractions([ | ||
hover, | ||
focus, | ||
dismiss, | ||
role, | ||
]); | ||
|
||
const { styles: transitionStyles } = useTransitionStyles(context, { | ||
initial: { | ||
opacity: 0, | ||
transform: "scale(0.8)", | ||
}, | ||
}); | ||
|
||
return ( | ||
<> | ||
{React.cloneElement(children as React.ReactElement, { | ||
...getReferenceProps(), | ||
ref: setReference, | ||
})} | ||
<div | ||
ref={setFloating} | ||
style={{ ...floatingStyles, zIndex: 1 }} | ||
{...getFloatingProps({ | ||
className: clsx("mykn-tooltip", { | ||
"mykn-tooltip--open": isOpen, | ||
}), | ||
})} | ||
> | ||
<div | ||
style={transitionStyles} | ||
className={clsx("mykn-tooltip__content", { | ||
"mykn-tooltip__content--sm": size === "sm", | ||
"mykn-tooltip__content--md": size === "md", | ||
"mykn-tooltip__content--lg": size === "lg", | ||
})} | ||
> | ||
<FloatingArrow | ||
ref={arrowRef} | ||
context={context} | ||
className="mykn-tooltip__arrow" | ||
/> | ||
<P size="xs">{content}</P> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; |