Skip to content

Commit

Permalink
use Radix HoverCard instead of react-popper and popper.js (#874)
Browse files Browse the repository at this point in the history
  • Loading branch information
Simek authored Aug 30, 2022
1 parent 03094f3 commit aa4e692
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 162 deletions.
146 changes: 65 additions & 81 deletions components/Library/Thumbnail.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { memo, useCallback, useContext, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { ActivityIndicator } from 'react-native';
import { usePopper } from 'react-popper';
import * as HoverCard from '@radix-ui/react-hover-card';
import React, { useContext, memo, useState } from 'react';
import { ActivityIndicator, useWindowDimensions } from 'react-native';

import { colors, darkColors } from '../../common/styleguide';
import CustomAppearanceContext from '../../context/CustomAppearanceContext';
Expand All @@ -11,51 +10,20 @@ type Props = {
url: string;
};

const customOffset = {
name: 'offset',
options: {
offset: ({ placement, popper }) => {
if (placement === 'right-start') {
return [32, -30];
} else {
return [32, -popper.height + 80];
}
},
},
};
const GITHUB_PREVIEW_MIN_WIDTH = 640;

const Thumbnail = ({ url }: Props) => {
const { isDark } = useContext(CustomAppearanceContext);
const [showPreview, setShowPreview] = useState(false);
const [isLoaded, setLoaded] = useState(false);
const iconRef = useRef();
const previewRef = useRef();
const { width, height } = useWindowDimensions();

const maxPreviewWidth = width < GITHUB_PREVIEW_MIN_WIDTH ? width : GITHUB_PREVIEW_MIN_WIDTH;
const maxPreviewImageWidth = maxPreviewWidth - 20;
const maxPreviewHeight = height / 2;
const maxImgPreviewHeight = maxPreviewHeight - 20;

const { styles, attributes } = usePopper(iconRef.current, previewRef.current, {
placement: 'right-start',
strategy: 'fixed',
modifiers: [
{
name: 'preventOverflow',
enabled: true,
options: {
rootBoundary: 'document',
},
},
customOffset,
{
name: 'flip',
enabled: true,
options: {
rootBoundary: 'document',
fallbackPlacements: ['top-start'],
allowedAutoPlacements: ['right-start', 'top-start'],
},
},
],
});
const [isLoaded, setLoaded] = useState(false);
const [showPreview, setShowPreview] = useState(false);

const handleMouseEvent = useCallback(show => setShowPreview(show), [showPreview]);
const iconFill = isDark
? showPreview
? colors.primary
Expand All @@ -65,45 +33,61 @@ const Thumbnail = ({ url }: Props) => {
: undefined;

return (
<>
<div
ref={iconRef}
onMouseEnter={() => handleMouseEvent(true)}
onMouseLeave={() => handleMouseEvent(false)}
style={{
marginRight: 10,
marginTop: 4,
marginBottom: 4,
padding: 6,
paddingBottom: 0,
minHeight: 30,
boxSizing: 'border-box',
overflow: 'hidden',
textAlign: 'center',
borderWidth: 1,
borderRadius: 3,
borderColor: isDark ? darkColors.border : colors.gray2,
borderStyle: 'solid',
}}>
{showPreview && !isLoaded ? (
<div style={{ width: 14, marginLeft: 1, marginRight: 1, marginTop: -2 }}>
<ActivityIndicator size="small" color={iconFill} />
</div>
) : (
<ThumbnailIcon fill={iconFill} />
)}
</div>
{createPortal(
<div ref={previewRef} style={styles.popper} {...attributes.popper}>
{showPreview && (
<div className={'preview' + (isLoaded ? ' loaded' : '')}>
<img src={url} onLoad={() => setLoaded(true)} alt="" />
<HoverCard.Root openDelay={0} closeDelay={0} onOpenChange={open => setShowPreview(open)}>
<HoverCard.Trigger asChild>
<div
style={{
marginRight: 10,
marginTop: 4,
marginBottom: 4,
padding: 6,
paddingBottom: 0,
minHeight: 30,
boxSizing: 'border-box',
overflow: 'hidden',
textAlign: 'center',
borderWidth: 1,
borderRadius: 3,
borderColor: isDark ? darkColors.border : colors.gray2,
borderStyle: 'solid',
}}>
{showPreview && !isLoaded ? (
<div style={{ width: 14, marginLeft: 1, marginRight: 1, marginTop: -2 }}>
<ActivityIndicator size="small" color={iconFill} />
</div>
) : (
<ThumbnailIcon fill={iconFill} />
)}
</div>,
document.querySelector('#__next')
)}
</>
</div>
</HoverCard.Trigger>
<HoverCard.Portal>
<HoverCard.Content sideOffset={6} sticky="always">
<div
style={{
backgroundColor: isDark ? darkColors.black : colors.white,
opacity: 1,
padding: 10,
boxSizing: 'border-box',
maxWidth: maxPreviewWidth,
maxHeight: maxPreviewHeight,
borderRadius: 4,
display: showPreview && isLoaded ? 'block' : 'none',
boxShadow: `0 4px 6px 0 ${isDark ? '#2a2e3633' : '#00000025'}`,
}}>
<img
src={url}
onLoad={() => setLoaded(true)}
alt=""
style={{
maxWidth: maxPreviewImageWidth,
maxHeight: maxImgPreviewHeight,
borderRadius: 2,
}}
/>
</div>
</HoverCard.Content>
</HoverCard.Portal>
</HoverCard.Root>
);
};

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@expo/html-elements": "^0.2.0",
"@expo/match-media": "^0.3.0",
"@jlengstorf/get-share-image": "^0.8.0",
"@popperjs/core": "^2.11.6",
"@radix-ui/react-hover-card": "^1.0.0",
"@react-native-async-storage/async-storage": "^1.17.9",
"@react-native-picker/picker": "^2.4.4",
"@sentry/react": "^6.19.7",
Expand All @@ -42,7 +42,6 @@
"react-native-svg": "^12.3.0",
"react-native-web": "^0.18.7",
"react-native-web-hooks": "^3.0.2",
"react-popper": "^2.3.0",
"use-debounce": "^8.0.1"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import CustomAppearanceContext from '../context/CustomAppearanceContext';
import CustomAppearanceProvider from '../context/CustomAppearanceProvider';

import '../styles/styles.css';
import PreviewStyles from '../styles/PreviewStyles';
import ThemedBody from '../styles/ThemedBody';

Sentry.init({
dsn: 'https://d91de4406c74494dbfcadfd007774ba6@o574947.ingest.sentry.io/5727369',
Expand Down Expand Up @@ -41,7 +41,7 @@ const App = ({ pageProps, Component }) => (
<Header />
<Component {...pageProps} />
<Footer />
<PreviewStyles />
<ThemedBody />
</SafeAreaProvider>
)}
</CustomAppearanceContext.Consumer>
Expand Down
52 changes: 0 additions & 52 deletions styles/PreviewStyles.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions styles/ThemedBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, { useContext } from 'react';

import { colors, darkColors } from '../common/styleguide';
import CustomAppearanceContext from '../context/CustomAppearanceContext';

const ThemedBody = () => {
const { isDark } = useContext(CustomAppearanceContext);
return (
<style>{`
html,
body {
background-color: ${isDark ? darkColors.background : colors.white};
}
`}</style>
);
};

export default ThemedBody;
Loading

0 comments on commit aa4e692

Please sign in to comment.