[site/components][f]: tooltip with clipped content

This commit is contained in:
olayway 2022-05-18 12:57:53 +02:00
parent 28c087e31d
commit 5589b2244d
6 changed files with 62 additions and 55 deletions

View File

@ -15,7 +15,7 @@ import {
useRole,
} from '@floating-ui/react-dom-interactions'
import getAbsolutePath from '../utils/absolutePath'
import siteConfig from '../config/siteConfig.js'
import documentExtract from '../utils/documentExtract'
import { Tooltip } from './Tooltip'
@ -52,7 +52,7 @@ export const Anchor = (props) => {
]
});
const { getReferenceProps, getFloatingProps } = useInteractions([
useHover(context, { delay: { open: 100, close: 0 } }),
useHover(context, { delay: 100 }),
useRole(context, { role: 'tooltip' }),
useDismiss(context, { ancestorScroll: true })
]);
@ -64,21 +64,17 @@ export const Anchor = (props) => {
}, [showTooltip])
const fetchPreview = async () => {
console.log("Fetching...")
setPreviewLoaded(false);
const basePath = "http://localhost:3000"; // TODO
const currentPath = router.asPath;
const relativePath = props.href.split(".")[0]; // TBD temp remove .md
const absolutePath = getAbsolutePath({ currentPath, basePath, relativePath });
const response = await fetch(absolutePath);
const path = new URL(props.href, document.baseURI).pathname;
const rawContentPath = [siteConfig.rawContentBaseUrl, path].join("")
const response = await fetch(rawContentPath);
if (response.status !== 200) {
// TODO
console.log(`Looks like there was a problem. Status Code: ${response.status}`)
return
}
const html = await response.text();
const extract = documentExtract(html);
const md = await response.text();
const extract = documentExtract(md);
setPreview(extract);
setPreviewLoaded(true);
@ -93,24 +89,25 @@ export const Anchor = (props) => {
return <Fragment>
<a {...props} {...getReferenceProps({ref: reference})} />
<FloatingPortal>
<Tooltip
{...getFloatingProps({
ref: floating,
theme: 'light',
arrowRef,
arrowX,
arrowY,
placement,
style: {
position: strategy,
visibility: showTooltip && previewLoaded ? 'visible' : 'hidden',
left: x ?? '',
top: y ?? '',
},
})}
>
{ preview }
</Tooltip>
{ showTooltip && previewLoaded &&
<Tooltip
{...getFloatingProps({
ref: floating,
theme: 'light',
arrowRef,
arrowX,
arrowY,
placement,
style: {
position: strategy,
left: x ?? '',
top: y ?? '',
},
})}
>
{ preview }
</Tooltip>
}
</FloatingPortal>
</Fragment>;
}

View File

@ -1,18 +1,24 @@
import React from 'react';
const tooltipStyles = (theme) => ({
const tooltipBoxStyle = (theme) => ({
height: 'auto',
maxWidth: '80vw',
padding: '1rem 2rem',
maxWidth: '60vw',
padding: '1rem',
background: theme === 'light' ? '#fff' : '#000',
color: theme === 'light' ? 'rgb(99, 98, 98)' : '#A8A8A8',
borderRadius: '4px',
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",
left: x != null ? `${x}px` : '',
top: y != null ? `${y}px` : '',
@ -36,11 +42,13 @@ export const Tooltip = React.forwardRef((props, ref) => {
}[placement.split('-')[0]];
return (
<div {...tooltipProps} ref={ref}>
<div style={ tooltipStyles(theme) }>
{ children }
<div className="tooltip" {...tooltipProps} ref={ref}>
<div className="tooltip-box" style={ tooltipBoxStyle(theme) }>
<div className="tooltip-body" style={ tooltipBodyStyle() }>
{ children }
</div>
</div>
<div ref={arrowRef} style={ tooltipArrowStyles({
<div className="tooltip-arrow" ref={arrowRef} style={ tooltipArrowStyle({
theme,
x: arrowX,
y: arrowY,

View File

@ -5,6 +5,7 @@ const siteConfig = {
url: "https://web3.lifeitself.us",
repoRoot: "https://github.com/life-itself/web3",
repoEditPath: "/edit/main/",
rawContentBaseUrl: "https://raw.githubusercontent.com/life-itself/web3/main",
tagline: "",
description:
"Introductions to key concepts and ideas in crypto and web3. Plus in-depth evaluation of its potential impact.",

View File

@ -27,3 +27,15 @@ body {
.extra-small {
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%);
}

View File

@ -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;

View File

@ -1,15 +1,13 @@
import { unified } from 'unified'
import rehypeParse from 'rehype-parse'
import remarkParse from 'remark-parse'
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
const documentExtract = (htmlString) => {
const hast = unified().use(rehypeParse).parse(htmlString);
const article = find(hast, (node) => node.tagName === "article");
const main = find(article, (node) => node.tagName === "main");
const paragraph = find(main, (node) => node.tagName === "p");
// get first paragraph
const documentExtract = (md) => {
const mdast = unified().use(remarkParse).parse(md);
let paragraph = find(mdast, (node) => node.type === "paragraph");
return toString(paragraph);
}