Skip to content

Commit 2a2fc42

Browse files
committed
Add support for tooltips
1 parent 1a5465d commit 2a2fc42

File tree

5 files changed

+201
-1
lines changed

5 files changed

+201
-1
lines changed

.eslintrc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ rules:
4444
array-bracket-spacing:
4545
- warn
4646
- always
47+
"@typescript-eslint/no-unused-vars":
48+
- warn
49+
- argsIgnorePattern: '^_'
50+
varsIgnorePattern: '^_'
4751
# Remove errors for not having newlines between operands of ternary expressions https://eslint.org/docs/rules/multiline-ternary
4852
multiline-ternary: 0
4953
"react-hooks/rules-of-hooks":

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "pterodactyl-panel",
33
"dependencies": {
4+
"@floating-ui/react-dom-interactions": "^0.6.3",
45
"@fortawesome/fontawesome-svg-core": "^1.2.32",
56
"@fortawesome/free-solid-svg-icons": "^5.15.1",
67
"@fortawesome/react-fontawesome": "^0.1.11",
@@ -18,6 +19,7 @@
1819
"easy-peasy": "^4.0.1",
1920
"events": "^3.0.0",
2021
"formik": "^2.2.6",
22+
"framer-motion": "^6.3.10",
2123
"i18next": "^19.0.0",
2224
"i18next-chained-backend": "^2.0.0",
2325
"i18next-localstorage-backend": "^3.0.0",
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import React, { cloneElement, useRef, useState } from 'react';
2+
import {
3+
arrow,
4+
autoUpdate,
5+
flip,
6+
offset,
7+
Placement,
8+
shift,
9+
Side,
10+
Strategy,
11+
useDismiss,
12+
useFloating,
13+
useFocus,
14+
useHover,
15+
useInteractions,
16+
useRole,
17+
} from '@floating-ui/react-dom-interactions';
18+
import { AnimatePresence, motion } from 'framer-motion';
19+
20+
interface Props {
21+
content: string | React.ReactChild;
22+
arrow?: boolean;
23+
placement?: Placement;
24+
strategy?: Strategy;
25+
className?: string;
26+
children: React.ReactElement;
27+
}
28+
29+
const arrowSides: Record<Side, Side> = {
30+
top: 'bottom',
31+
bottom: 'top',
32+
left: 'right',
33+
right: 'left',
34+
};
35+
36+
export default ({ content, children, ...props }: Props) => {
37+
const arrowEl = useRef<HTMLSpanElement>(null);
38+
const [ open, setOpen ] = useState(false);
39+
40+
const { x, y, reference, floating, middlewareData, strategy, context } = useFloating({
41+
open,
42+
placement: props.placement || 'top',
43+
strategy: props.strategy || 'absolute',
44+
middleware: [ offset(6), flip(), shift({ padding: 6 }), arrow({ element: arrowEl, padding: 6 }) ],
45+
onOpenChange: setOpen,
46+
whileElementsMounted: autoUpdate,
47+
});
48+
49+
const { getReferenceProps, getFloatingProps } = useInteractions([
50+
useFocus(context),
51+
useHover(context, { restMs: 30 }),
52+
useRole(context, { role: 'tooltip' }),
53+
useDismiss(context),
54+
]);
55+
56+
const side = arrowSides[(props.placement || 'top').split('-')[0] as Side];
57+
const { x: ax, y: ay } = middlewareData.arrow || {};
58+
59+
return (
60+
<>
61+
{cloneElement(children, getReferenceProps({ ref: reference, ...children.props }))}
62+
<AnimatePresence>
63+
{open &&
64+
<motion.span
65+
initial={{ opacity: 0, scale: 0.85 }}
66+
animate={{ opacity: 1, scale: 1 }}
67+
exit={{ opacity: 0 }}
68+
transition={{ type: 'easeIn', damping: 20, stiffness: 300, duration: 0.1 }}
69+
{...getFloatingProps({
70+
ref: floating,
71+
className: 'absolute top-0 left-0 bg-gray-900 text-sm text-gray-200 px-3 py-2 rounded pointer-events-none',
72+
style: {
73+
position: strategy,
74+
top: `${y || 0}px`,
75+
left: `${x || 0}px`,
76+
},
77+
})}
78+
>
79+
{content}
80+
{props.arrow &&
81+
<span
82+
ref={arrowEl}
83+
style={{
84+
transform: `translate(${Math.round(ax || 0)}px, ${Math.round(ay || 0)}px)`,
85+
[side]: '-6px',
86+
}}
87+
className={'absolute top-0 left-0 bg-gray-900 w-3 h-3 rotate-45'}
88+
/>
89+
}
90+
</motion.span>
91+
}
92+
</AnimatePresence>
93+
</>
94+
);
95+
};

webpack.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ module.exports = {
2929
exclude: /node_modules|\.spec\.tsx?$/,
3030
loader: 'babel-loader',
3131
},
32+
{
33+
test: /\.mjs$/,
34+
include: /node_modules/,
35+
type: 'javascript/auto',
36+
},
3237
{
3338
test: /\.css$/,
3439
use: [

yarn.lock

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@
12041204
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.0.tgz#65b12f12db55188422070e34687bf3af09870922"
12051205
integrity sha512-rZ6vufeY/UjAgtyiJ4WvfF6XP6HizIyOfbZOg0RnecIwjrvH8Am3nN1BpKnnPZunYAkUcPPXDhwbxOtGop8cfQ==
12061206

1207-
"@emotion/is-prop-valid@^0.8.8":
1207+
"@emotion/is-prop-valid@^0.8.2", "@emotion/is-prop-valid@^0.8.8":
12081208
version "0.8.8"
12091209
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
12101210
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
@@ -1241,6 +1241,35 @@
12411241
minimatch "^3.0.4"
12421242
strip-json-comments "^3.1.1"
12431243

1244+
"@floating-ui/core@^0.7.2":
1245+
version "0.7.2"
1246+
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.2.tgz#f7af9613d080dc29360e77c970965b79b524d45a"
1247+
integrity sha512-FRVAkSNU/vGXLIsgbggcs70GkXKEOXgBBbNpYPNHSaKsCAMMd00NrjbtKTesxkdv9xm9N3+XiDlcFGY6WnatBg==
1248+
1249+
"@floating-ui/dom@^0.5.1":
1250+
version "0.5.2"
1251+
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.2.tgz#908f3febbfc0d6696d70921616ec194fe07af183"
1252+
integrity sha512-z1DnEa7F3d8Fm/eXSbii8UEGpcjZGkQaYYUI0WpEVgD3vBfebDW8j/3ysusxonuMexoigA+A3b/fYH7sEqiwyg==
1253+
dependencies:
1254+
"@floating-ui/core" "^0.7.2"
1255+
1256+
"@floating-ui/react-dom-interactions@^0.6.3":
1257+
version "0.6.3"
1258+
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.6.3.tgz#895c52cb06bf5ea73c00f1074c75b0535e0046bc"
1259+
integrity sha512-xvbGEtBtA7JaEngnHQjROArv2onRp3oJIpb4+bEN5EGJf0hBYDY0vD8vFGPz/5TQwN++hb6icOB1QwdOnffMzw==
1260+
dependencies:
1261+
"@floating-ui/react-dom" "^0.7.1"
1262+
aria-hidden "^1.1.3"
1263+
use-isomorphic-layout-effect "^1.1.1"
1264+
1265+
"@floating-ui/react-dom@^0.7.1":
1266+
version "0.7.1"
1267+
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.1.tgz#e0eb57cb05c7762d4c904bfbae73148684578d66"
1268+
integrity sha512-Dd7e8AupUjzcjeGf1g3EItf/QRtEWKF5GGyEs5WA5n3zlHvEgZ4XrZM6ANhUnzgE3pUQAaXkcXLnibgFp1YBRw==
1269+
dependencies:
1270+
"@floating-ui/dom" "^0.5.1"
1271+
use-isomorphic-layout-effect "^1.1.1"
1272+
12441273
"@fortawesome/fontawesome-common-types@^0.2.32":
12451274
version "0.2.32"
12461275
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.32.tgz#3436795d5684f22742989bfa08f46f50f516f259"
@@ -2027,6 +2056,13 @@ argparse@^1.0.7:
20272056
dependencies:
20282057
sprintf-js "~1.0.2"
20292058

2059+
aria-hidden@^1.1.3:
2060+
version "1.1.3"
2061+
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
2062+
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
2063+
dependencies:
2064+
tslib "^1.0.0"
2065+
20302066
arr-diff@^4.0.0:
20312067
version "4.0.0"
20322068
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@@ -4120,6 +4156,26 @@ fragment-cache@^0.2.1:
41204156
dependencies:
41214157
map-cache "^0.2.2"
41224158

4159+
framer-motion@^6.3.10:
4160+
version "6.3.10"
4161+
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.3.10.tgz#e71f8c4ee09612de8328725c4fb1a1c204ae451f"
4162+
integrity sha512-modFplFb1Fznsm0MrmRAJUC32UDA5jbGU9rDvkGzhAHksru2tnoKbU/Pa3orzdsJI0CJviG4NGBrmwGveU98Cg==
4163+
dependencies:
4164+
framesync "6.0.1"
4165+
hey-listen "^1.0.8"
4166+
popmotion "11.0.3"
4167+
style-value-types "5.0.0"
4168+
tslib "^2.1.0"
4169+
optionalDependencies:
4170+
"@emotion/is-prop-valid" "^0.8.2"
4171+
4172+
framesync@6.0.1:
4173+
version "6.0.1"
4174+
resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20"
4175+
integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==
4176+
dependencies:
4177+
tslib "^2.1.0"
4178+
41234179
fresh@0.5.2:
41244180
version "0.5.2"
41254181
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -4499,6 +4555,11 @@ hex-color-regex@^1.1.0:
44994555
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
45004556
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
45014557

4558+
hey-listen@^1.0.8:
4559+
version "1.0.8"
4560+
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
4561+
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
4562+
45024563
history@^4.9.0:
45034564
version "4.9.0"
45044565
resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca"
@@ -6334,6 +6395,16 @@ pkg-up@^2.0.0:
63346395
dependencies:
63356396
find-up "^2.1.0"
63366397

6398+
popmotion@11.0.3:
6399+
version "11.0.3"
6400+
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9"
6401+
integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==
6402+
dependencies:
6403+
framesync "6.0.1"
6404+
hey-listen "^1.0.8"
6405+
style-value-types "5.0.0"
6406+
tslib "^2.1.0"
6407+
63376408
portfinder@^1.0.26:
63386409
version "1.0.26"
63396410
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70"
@@ -7993,6 +8064,14 @@ style-loader@^2.0.0:
79938064
loader-utils "^2.0.0"
79948065
schema-utils "^3.0.0"
79958066

8067+
style-value-types@5.0.0:
8068+
version "5.0.0"
8069+
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad"
8070+
integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==
8071+
dependencies:
8072+
hey-listen "^1.0.8"
8073+
tslib "^2.1.0"
8074+
79968075
styled-components-breakpoint@^3.0.0-preview.20:
79978076
version "3.0.0-preview.20"
79988077
resolved "https://registry.yarnpkg.com/styled-components-breakpoint/-/styled-components-breakpoint-3.0.0-preview.20.tgz#877e88a00c0cf66976f610a1d347839a1a0b6d70"
@@ -8340,6 +8419,11 @@ tsconfig-paths@^3.9.0:
83408419
minimist "^1.2.0"
83418420
strip-bom "^3.0.0"
83428421

8422+
tslib@^1.0.0:
8423+
version "1.14.1"
8424+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
8425+
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
8426+
83438427
tslib@^1.10.0:
83448428
version "1.11.1"
83458429
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
@@ -8349,6 +8433,11 @@ tslib@^1.8.1, tslib@^1.9.0:
83498433
version "1.10.0"
83508434
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
83518435

8436+
tslib@^2.1.0:
8437+
version "2.4.0"
8438+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
8439+
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
8440+
83528441
tsutils@^3.17.1:
83538442
version "3.17.1"
83548443
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
@@ -8517,6 +8606,11 @@ url@^0.11.0:
85178606
punycode "1.3.2"
85188607
querystring "0.2.0"
85198608

8609+
use-isomorphic-layout-effect@^1.1.1:
8610+
version "1.1.2"
8611+
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
8612+
integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==
8613+
85208614
use-memo-one@^1.1.1:
85218615
version "1.1.1"
85228616
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c"

0 commit comments

Comments
 (0)