[site/components][f]: tooltip with clipped content
This commit is contained in:
parent
28c087e31d
commit
5589b2244d
|
|
@ -15,7 +15,7 @@ import {
|
||||||
useRole,
|
useRole,
|
||||||
} from '@floating-ui/react-dom-interactions'
|
} from '@floating-ui/react-dom-interactions'
|
||||||
|
|
||||||
import getAbsolutePath from '../utils/absolutePath'
|
import siteConfig from '../config/siteConfig.js'
|
||||||
import documentExtract from '../utils/documentExtract'
|
import documentExtract from '../utils/documentExtract'
|
||||||
import { Tooltip } from './Tooltip'
|
import { Tooltip } from './Tooltip'
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ export const Anchor = (props) => {
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||||
useHover(context, { delay: { open: 100, close: 0 } }),
|
useHover(context, { delay: 100 }),
|
||||||
useRole(context, { role: 'tooltip' }),
|
useRole(context, { role: 'tooltip' }),
|
||||||
useDismiss(context, { ancestorScroll: true })
|
useDismiss(context, { ancestorScroll: true })
|
||||||
]);
|
]);
|
||||||
|
|
@ -64,21 +64,17 @@ export const Anchor = (props) => {
|
||||||
}, [showTooltip])
|
}, [showTooltip])
|
||||||
|
|
||||||
const fetchPreview = async () => {
|
const fetchPreview = async () => {
|
||||||
console.log("Fetching...")
|
|
||||||
setPreviewLoaded(false);
|
setPreviewLoaded(false);
|
||||||
const basePath = "http://localhost:3000"; // TODO
|
const path = new URL(props.href, document.baseURI).pathname;
|
||||||
const currentPath = router.asPath;
|
const rawContentPath = [siteConfig.rawContentBaseUrl, path].join("")
|
||||||
const relativePath = props.href.split(".")[0]; // TBD temp remove .md
|
const response = await fetch(rawContentPath);
|
||||||
const absolutePath = getAbsolutePath({ currentPath, basePath, relativePath });
|
|
||||||
|
|
||||||
const response = await fetch(absolutePath);
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
// TODO
|
// TODO
|
||||||
console.log(`Looks like there was a problem. Status Code: ${response.status}`)
|
console.log(`Looks like there was a problem. Status Code: ${response.status}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const html = await response.text();
|
const md = await response.text();
|
||||||
const extract = documentExtract(html);
|
const extract = documentExtract(md);
|
||||||
|
|
||||||
setPreview(extract);
|
setPreview(extract);
|
||||||
setPreviewLoaded(true);
|
setPreviewLoaded(true);
|
||||||
|
|
@ -93,24 +89,25 @@ export const Anchor = (props) => {
|
||||||
return <Fragment>
|
return <Fragment>
|
||||||
<a {...props} {...getReferenceProps({ref: reference})} />
|
<a {...props} {...getReferenceProps({ref: reference})} />
|
||||||
<FloatingPortal>
|
<FloatingPortal>
|
||||||
<Tooltip
|
{ showTooltip && previewLoaded &&
|
||||||
{...getFloatingProps({
|
<Tooltip
|
||||||
ref: floating,
|
{...getFloatingProps({
|
||||||
theme: 'light',
|
ref: floating,
|
||||||
arrowRef,
|
theme: 'light',
|
||||||
arrowX,
|
arrowRef,
|
||||||
arrowY,
|
arrowX,
|
||||||
placement,
|
arrowY,
|
||||||
style: {
|
placement,
|
||||||
position: strategy,
|
style: {
|
||||||
visibility: showTooltip && previewLoaded ? 'visible' : 'hidden',
|
position: strategy,
|
||||||
left: x ?? '',
|
left: x ?? '',
|
||||||
top: y ?? '',
|
top: y ?? '',
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{ preview }
|
{ preview }
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
}
|
||||||
</FloatingPortal>
|
</FloatingPortal>
|
||||||
</Fragment>;
|
</Fragment>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,24 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
|
||||||
const tooltipStyles = (theme) => ({
|
const tooltipBoxStyle = (theme) => ({
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
maxWidth: '80vw',
|
maxWidth: '60vw',
|
||||||
padding: '1rem 2rem',
|
padding: '1rem',
|
||||||
background: theme === 'light' ? '#fff' : '#000',
|
background: theme === 'light' ? '#fff' : '#000',
|
||||||
color: theme === 'light' ? 'rgb(99, 98, 98)' : '#A8A8A8',
|
color: theme === 'light' ? 'rgb(99, 98, 98)' : '#A8A8A8',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
boxShadow: 'rgba(0, 0, 0, 0.55) 0px 0px 16px -3px',
|
boxShadow: 'rgba(0, 0, 0, 0.55) 0px 0px 16px -3px',
|
||||||
fontSize: '0.9em'
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const tooltipArrowStyles = ({ theme, x, y, side }) => ({
|
const tooltipBodyStyle = () => ({
|
||||||
|
maxHeight: '3.6rem',
|
||||||
|
position: 'relative',
|
||||||
|
lineHeight: '1.2rem',
|
||||||
|
overflow: 'hidden',
|
||||||
|
})
|
||||||
|
|
||||||
|
const tooltipArrowStyle = ({ theme, x, y, side }) => ({
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: x != null ? `${x}px` : '',
|
left: x != null ? `${x}px` : '',
|
||||||
top: y != null ? `${y}px` : '',
|
top: y != null ? `${y}px` : '',
|
||||||
|
|
@ -36,11 +42,13 @@ export const Tooltip = React.forwardRef((props, ref) => {
|
||||||
}[placement.split('-')[0]];
|
}[placement.split('-')[0]];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...tooltipProps} ref={ref}>
|
<div className="tooltip" {...tooltipProps} ref={ref}>
|
||||||
<div style={ tooltipStyles(theme) }>
|
<div className="tooltip-box" style={ tooltipBoxStyle(theme) }>
|
||||||
{ children }
|
<div className="tooltip-body" style={ tooltipBodyStyle() }>
|
||||||
|
{ children }
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref={arrowRef} style={ tooltipArrowStyles({
|
<div className="tooltip-arrow" ref={arrowRef} style={ tooltipArrowStyle({
|
||||||
theme,
|
theme,
|
||||||
x: arrowX,
|
x: arrowX,
|
||||||
y: arrowY,
|
y: arrowY,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ const siteConfig = {
|
||||||
url: "https://web3.lifeitself.us",
|
url: "https://web3.lifeitself.us",
|
||||||
repoRoot: "https://github.com/life-itself/web3",
|
repoRoot: "https://github.com/life-itself/web3",
|
||||||
repoEditPath: "/edit/main/",
|
repoEditPath: "/edit/main/",
|
||||||
|
rawContentBaseUrl: "https://raw.githubusercontent.com/life-itself/web3/main",
|
||||||
tagline: "",
|
tagline: "",
|
||||||
description:
|
description:
|
||||||
"Introductions to key concepts and ideas in crypto and web3. Plus in-depth evaluation of its potential impact.",
|
"Introductions to key concepts and ideas in crypto and web3. Plus in-depth evaluation of its potential impact.",
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,15 @@ body {
|
||||||
.extra-small {
|
.extra-small {
|
||||||
font-size: 0.50rem;
|
font-size: 0.50rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tooltip fade-out clip */
|
||||||
|
.tooltip-body::after {
|
||||||
|
content: "";
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 10%;
|
||||||
|
height: 1.2em;
|
||||||
|
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
const absolutePath = ({ currentPath, basePath, relativePath }) => {
|
|
||||||
const absolutePath = currentPath.slice(1).split("/")
|
|
||||||
absolutePath.pop(); // remove current page name
|
|
||||||
absolutePath.unshift(basePath);
|
|
||||||
absolutePath.push(relativePath);
|
|
||||||
return absolutePath.join("/");
|
|
||||||
};
|
|
||||||
|
|
||||||
export default absolutePath;
|
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
import { unified } from 'unified'
|
import { unified } from 'unified'
|
||||||
import rehypeParse from 'rehype-parse'
|
import remarkParse from 'remark-parse'
|
||||||
import find from 'unist-util-find'
|
import find from 'unist-util-find'
|
||||||
import { toString } from 'hast-util-to-string'
|
import { toString } from 'mdast-util-to-string'
|
||||||
|
|
||||||
|
|
||||||
// get first paragraph inside article's main tag
|
// get first paragraph
|
||||||
const documentExtract = (htmlString) => {
|
const documentExtract = (md) => {
|
||||||
const hast = unified().use(rehypeParse).parse(htmlString);
|
const mdast = unified().use(remarkParse).parse(md);
|
||||||
const article = find(hast, (node) => node.tagName === "article");
|
let paragraph = find(mdast, (node) => node.type === "paragraph");
|
||||||
const main = find(article, (node) => node.tagName === "main");
|
|
||||||
const paragraph = find(main, (node) => node.tagName === "p");
|
|
||||||
return toString(paragraph);
|
return toString(paragraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue