mirror of
https://github.com/pterodactyl/panel.git
synced 2024-11-22 09:02:28 +01:00
Add support for tooltips
This commit is contained in:
parent
1a5465dc34
commit
2a2fc42e37
@ -44,6 +44,10 @@ rules:
|
||||
array-bracket-spacing:
|
||||
- warn
|
||||
- always
|
||||
"@typescript-eslint/no-unused-vars":
|
||||
- warn
|
||||
- argsIgnorePattern: '^_'
|
||||
varsIgnorePattern: '^_'
|
||||
# Remove errors for not having newlines between operands of ternary expressions https://eslint.org/docs/rules/multiline-ternary
|
||||
multiline-ternary: 0
|
||||
"react-hooks/rules-of-hooks":
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "pterodactyl-panel",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom-interactions": "^0.6.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.11",
|
||||
@ -18,6 +19,7 @@
|
||||
"easy-peasy": "^4.0.1",
|
||||
"events": "^3.0.0",
|
||||
"formik": "^2.2.6",
|
||||
"framer-motion": "^6.3.10",
|
||||
"i18next": "^19.0.0",
|
||||
"i18next-chained-backend": "^2.0.0",
|
||||
"i18next-localstorage-backend": "^3.0.0",
|
||||
|
95
resources/scripts/components/elements/tooltip/Tooltip.tsx
Normal file
95
resources/scripts/components/elements/tooltip/Tooltip.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import React, { cloneElement, useRef, useState } from 'react';
|
||||
import {
|
||||
arrow,
|
||||
autoUpdate,
|
||||
flip,
|
||||
offset,
|
||||
Placement,
|
||||
shift,
|
||||
Side,
|
||||
Strategy,
|
||||
useDismiss,
|
||||
useFloating,
|
||||
useFocus,
|
||||
useHover,
|
||||
useInteractions,
|
||||
useRole,
|
||||
} from '@floating-ui/react-dom-interactions';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
||||
interface Props {
|
||||
content: string | React.ReactChild;
|
||||
arrow?: boolean;
|
||||
placement?: Placement;
|
||||
strategy?: Strategy;
|
||||
className?: string;
|
||||
children: React.ReactElement;
|
||||
}
|
||||
|
||||
const arrowSides: Record<Side, Side> = {
|
||||
top: 'bottom',
|
||||
bottom: 'top',
|
||||
left: 'right',
|
||||
right: 'left',
|
||||
};
|
||||
|
||||
export default ({ content, children, ...props }: Props) => {
|
||||
const arrowEl = useRef<HTMLSpanElement>(null);
|
||||
const [ open, setOpen ] = useState(false);
|
||||
|
||||
const { x, y, reference, floating, middlewareData, strategy, context } = useFloating({
|
||||
open,
|
||||
placement: props.placement || 'top',
|
||||
strategy: props.strategy || 'absolute',
|
||||
middleware: [ offset(6), flip(), shift({ padding: 6 }), arrow({ element: arrowEl, padding: 6 }) ],
|
||||
onOpenChange: setOpen,
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||
useFocus(context),
|
||||
useHover(context, { restMs: 30 }),
|
||||
useRole(context, { role: 'tooltip' }),
|
||||
useDismiss(context),
|
||||
]);
|
||||
|
||||
const side = arrowSides[(props.placement || 'top').split('-')[0] as Side];
|
||||
const { x: ax, y: ay } = middlewareData.arrow || {};
|
||||
|
||||
return (
|
||||
<>
|
||||
{cloneElement(children, getReferenceProps({ ref: reference, ...children.props }))}
|
||||
<AnimatePresence>
|
||||
{open &&
|
||||
<motion.span
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ type: 'easeIn', damping: 20, stiffness: 300, duration: 0.1 }}
|
||||
{...getFloatingProps({
|
||||
ref: floating,
|
||||
className: 'absolute top-0 left-0 bg-gray-900 text-sm text-gray-200 px-3 py-2 rounded pointer-events-none',
|
||||
style: {
|
||||
position: strategy,
|
||||
top: `${y || 0}px`,
|
||||
left: `${x || 0}px`,
|
||||
},
|
||||
})}
|
||||
>
|
||||
{content}
|
||||
{props.arrow &&
|
||||
<span
|
||||
ref={arrowEl}
|
||||
style={{
|
||||
transform: `translate(${Math.round(ax || 0)}px, ${Math.round(ay || 0)}px)`,
|
||||
[side]: '-6px',
|
||||
}}
|
||||
className={'absolute top-0 left-0 bg-gray-900 w-3 h-3 rotate-45'}
|
||||
/>
|
||||
}
|
||||
</motion.span>
|
||||
}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
};
|
@ -29,6 +29,11 @@ module.exports = {
|
||||
exclude: /node_modules|\.spec\.tsx?$/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: 'javascript/auto',
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
|
96
yarn.lock
96
yarn.lock
@ -1204,7 +1204,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.0.tgz#65b12f12db55188422070e34687bf3af09870922"
|
||||
integrity sha512-rZ6vufeY/UjAgtyiJ4WvfF6XP6HizIyOfbZOg0RnecIwjrvH8Am3nN1BpKnnPZunYAkUcPPXDhwbxOtGop8cfQ==
|
||||
|
||||
"@emotion/is-prop-valid@^0.8.8":
|
||||
"@emotion/is-prop-valid@^0.8.2", "@emotion/is-prop-valid@^0.8.8":
|
||||
version "0.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
||||
@ -1241,6 +1241,35 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@floating-ui/core@^0.7.2":
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.2.tgz#f7af9613d080dc29360e77c970965b79b524d45a"
|
||||
integrity sha512-FRVAkSNU/vGXLIsgbggcs70GkXKEOXgBBbNpYPNHSaKsCAMMd00NrjbtKTesxkdv9xm9N3+XiDlcFGY6WnatBg==
|
||||
|
||||
"@floating-ui/dom@^0.5.1":
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.2.tgz#908f3febbfc0d6696d70921616ec194fe07af183"
|
||||
integrity sha512-z1DnEa7F3d8Fm/eXSbii8UEGpcjZGkQaYYUI0WpEVgD3vBfebDW8j/3ysusxonuMexoigA+A3b/fYH7sEqiwyg==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^0.7.2"
|
||||
|
||||
"@floating-ui/react-dom-interactions@^0.6.3":
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.6.3.tgz#895c52cb06bf5ea73c00f1074c75b0535e0046bc"
|
||||
integrity sha512-xvbGEtBtA7JaEngnHQjROArv2onRp3oJIpb4+bEN5EGJf0hBYDY0vD8vFGPz/5TQwN++hb6icOB1QwdOnffMzw==
|
||||
dependencies:
|
||||
"@floating-ui/react-dom" "^0.7.1"
|
||||
aria-hidden "^1.1.3"
|
||||
use-isomorphic-layout-effect "^1.1.1"
|
||||
|
||||
"@floating-ui/react-dom@^0.7.1":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.1.tgz#e0eb57cb05c7762d4c904bfbae73148684578d66"
|
||||
integrity sha512-Dd7e8AupUjzcjeGf1g3EItf/QRtEWKF5GGyEs5WA5n3zlHvEgZ4XrZM6ANhUnzgE3pUQAaXkcXLnibgFp1YBRw==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "^0.5.1"
|
||||
use-isomorphic-layout-effect "^1.1.1"
|
||||
|
||||
"@fortawesome/fontawesome-common-types@^0.2.32":
|
||||
version "0.2.32"
|
||||
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:
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
aria-hidden@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
|
||||
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
|
||||
dependencies:
|
||||
tslib "^1.0.0"
|
||||
|
||||
arr-diff@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
||||
@ -4120,6 +4156,26 @@ fragment-cache@^0.2.1:
|
||||
dependencies:
|
||||
map-cache "^0.2.2"
|
||||
|
||||
framer-motion@^6.3.10:
|
||||
version "6.3.10"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.3.10.tgz#e71f8c4ee09612de8328725c4fb1a1c204ae451f"
|
||||
integrity sha512-modFplFb1Fznsm0MrmRAJUC32UDA5jbGU9rDvkGzhAHksru2tnoKbU/Pa3orzdsJI0CJviG4NGBrmwGveU98Cg==
|
||||
dependencies:
|
||||
framesync "6.0.1"
|
||||
hey-listen "^1.0.8"
|
||||
popmotion "11.0.3"
|
||||
style-value-types "5.0.0"
|
||||
tslib "^2.1.0"
|
||||
optionalDependencies:
|
||||
"@emotion/is-prop-valid" "^0.8.2"
|
||||
|
||||
framesync@6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20"
|
||||
integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
@ -4499,6 +4555,11 @@ hex-color-regex@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
|
||||
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
|
||||
|
||||
hey-listen@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
|
||||
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
|
||||
|
||||
history@^4.9.0:
|
||||
version "4.9.0"
|
||||
resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca"
|
||||
@ -6334,6 +6395,16 @@ pkg-up@^2.0.0:
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
popmotion@11.0.3:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9"
|
||||
integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==
|
||||
dependencies:
|
||||
framesync "6.0.1"
|
||||
hey-listen "^1.0.8"
|
||||
style-value-types "5.0.0"
|
||||
tslib "^2.1.0"
|
||||
|
||||
portfinder@^1.0.26:
|
||||
version "1.0.26"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70"
|
||||
@ -7993,6 +8064,14 @@ style-loader@^2.0.0:
|
||||
loader-utils "^2.0.0"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
style-value-types@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad"
|
||||
integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==
|
||||
dependencies:
|
||||
hey-listen "^1.0.8"
|
||||
tslib "^2.1.0"
|
||||
|
||||
styled-components-breakpoint@^3.0.0-preview.20:
|
||||
version "3.0.0-preview.20"
|
||||
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:
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.0.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^1.10.0:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
|
||||
@ -8349,6 +8433,11 @@ tslib@^1.8.1, tslib@^1.9.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
|
||||
tslib@^2.1.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||
|
||||
tsutils@^3.17.1:
|
||||
version "3.17.1"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
||||
@ -8517,6 +8606,11 @@ url@^0.11.0:
|
||||
punycode "1.3.2"
|
||||
querystring "0.2.0"
|
||||
|
||||
use-isomorphic-layout-effect@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
|
||||
integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==
|
||||
|
||||
use-memo-one@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c"
|
||||
|
Loading…
Reference in New Issue
Block a user