Open links in new tab
This commit is contained in:
54
packages/web/components/patterns/LinkHoverBar.tsx
Normal file
54
packages/web/components/patterns/LinkHoverBar.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { isAndroid } from '../../lib/deviceType'
|
||||||
|
import { styled, theme } from '../tokens/stitches.config'
|
||||||
|
import { Button } from '../elements/Button'
|
||||||
|
import { HStack, Box } from '../elements/LayoutPrimitives'
|
||||||
|
import { Circle, CheckCircle } from 'phosphor-react'
|
||||||
|
import { LabelIcon } from '../elements/icons/LabelIcon'
|
||||||
|
import { NotebookIcon } from '../elements/icons/NotebookIcon'
|
||||||
|
import { highlightColor, highlightColors } from '../../lib/themeUpdater'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { CopyIcon } from '../elements/icons/CopyIcon'
|
||||||
|
|
||||||
|
type PageCoordinates = {
|
||||||
|
pageX: number
|
||||||
|
pageY: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinkHoverBarProps = {
|
||||||
|
anchorCoordinates: PageCoordinates
|
||||||
|
handleButtonClick: (action: HighlightAction, param?: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LinkHoverBar(props: LinkHoverBarProps): JSX.Element {
|
||||||
|
console.log('settingh link hover, ', props)
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
css={{
|
||||||
|
// width: '295px',
|
||||||
|
// height: '50px',
|
||||||
|
position: 'absolute',
|
||||||
|
background: '$thBackground2',
|
||||||
|
borderRadius: '5px',
|
||||||
|
border: '1px solid $thHighlightBar',
|
||||||
|
boxShadow: `0px 4px 4px 0px rgba(0, 0, 0, 0.15)`,
|
||||||
|
padding: '10px',
|
||||||
|
|
||||||
|
// ...(props.displayAtBottom && {
|
||||||
|
// bottom: 'calc(38px + env(safe-area-inset-bottom, 40px))',
|
||||||
|
// }),
|
||||||
|
// ...(props.displayAtBottom && {
|
||||||
|
// '@smDown': {
|
||||||
|
// maxWidth: '90vw',
|
||||||
|
// bottom: `calc(28px + ${
|
||||||
|
// isAndroid() ? 30 : 0
|
||||||
|
// }px + env(safe-area-inset-bottom, 40px))`,
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
left: props.anchorCoordinates.pageX,
|
||||||
|
top: props.anchorCoordinates.pageY,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box>Save to Omnivore</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -7,7 +7,14 @@ import {
|
|||||||
ScrollOffsetChangeset,
|
ScrollOffsetChangeset,
|
||||||
useScrollWatcher,
|
useScrollWatcher,
|
||||||
} from '../../../lib/hooks/useScrollWatcher'
|
} from '../../../lib/hooks/useScrollWatcher'
|
||||||
import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react'
|
import {
|
||||||
|
MutableRefObject,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
import { isDarkTheme } from '../../../lib/themeUpdater'
|
import { isDarkTheme } from '../../../lib/themeUpdater'
|
||||||
import { ArticleMutations } from '../../../lib/articleActions'
|
import { ArticleMutations } from '../../../lib/articleActions'
|
||||||
import { Lightbox, SlideImage } from 'yet-another-react-lightbox'
|
import { Lightbox, SlideImage } from 'yet-another-react-lightbox'
|
||||||
@ -18,6 +25,7 @@ import Zoom from 'yet-another-react-lightbox/plugins/zoom'
|
|||||||
import Counter from 'yet-another-react-lightbox/plugins/counter'
|
import Counter from 'yet-another-react-lightbox/plugins/counter'
|
||||||
|
|
||||||
import loadjs from 'loadjs'
|
import loadjs from 'loadjs'
|
||||||
|
import { LinkHoverBar } from '../../patterns/LinkHoverBar'
|
||||||
|
|
||||||
export type ArticleProps = {
|
export type ArticleProps = {
|
||||||
articleId: string
|
articleId: string
|
||||||
@ -30,6 +38,16 @@ export type ArticleProps = {
|
|||||||
isAppleAppEmbed: boolean
|
isAppleAppEmbed: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PageCoordinates = {
|
||||||
|
pageX: number
|
||||||
|
pageY: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinkHoverData = {
|
||||||
|
href: string
|
||||||
|
pageCoordinate: PageCoordinates
|
||||||
|
}
|
||||||
|
|
||||||
export function Article(props: ArticleProps): JSX.Element {
|
export function Article(props: ArticleProps): JSX.Element {
|
||||||
const highlightTheme = isDarkTheme() ? 'dark' : 'default'
|
const highlightTheme = isDarkTheme() ? 'dark' : 'default'
|
||||||
|
|
||||||
@ -49,6 +67,9 @@ export function Article(props: ArticleProps): JSX.Element {
|
|||||||
const [lightboxOpen, setLightboxOpen] = useState(false)
|
const [lightboxOpen, setLightboxOpen] = useState(false)
|
||||||
const [imageSrcs, setImageSrcs] = useState<SlideImage[]>([])
|
const [imageSrcs, setImageSrcs] = useState<SlideImage[]>([])
|
||||||
const [lightboxIndex, setlightBoxIndex] = useState(0)
|
const [lightboxIndex, setlightBoxIndex] = useState(0)
|
||||||
|
const [linkHoverData, setlinkHoverData] = useState<
|
||||||
|
LinkHoverData | undefined
|
||||||
|
>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
@ -267,6 +288,41 @@ export function Article(props: ArticleProps): JSX.Element {
|
|||||||
}
|
}
|
||||||
}, [props])
|
}, [props])
|
||||||
|
|
||||||
|
// const linkMouseOver = useCallback(
|
||||||
|
// (event: Event) => {
|
||||||
|
// const element = event.target as HTMLLinkElement
|
||||||
|
|
||||||
|
// setlinkHoverData({
|
||||||
|
// href: element.href,
|
||||||
|
// pageCoordinate: {
|
||||||
|
// pageX: element.offsetLeft,
|
||||||
|
// pageY: element.offsetTop - 45,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// [props]
|
||||||
|
// )
|
||||||
|
|
||||||
|
// const linkMouseOut = useCallback(
|
||||||
|
// (event: Event) => {
|
||||||
|
// console.log('mouse out link', event.target)
|
||||||
|
// setlinkHoverData(undefined)
|
||||||
|
// },
|
||||||
|
// [props]
|
||||||
|
// )
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const embeddedLinks = Array.from(
|
||||||
|
document.querySelectorAll('a[data-omnivore-anchor-idx]')
|
||||||
|
)
|
||||||
|
|
||||||
|
embeddedLinks.forEach((link: Element) => {
|
||||||
|
link.setAttribute('target', '_blank')
|
||||||
|
// link.addEventListener('mouseover', linkMouseOver)
|
||||||
|
// link.addEventListener('mouseout', linkMouseOut)
|
||||||
|
})
|
||||||
|
}, [props.content])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!props.isAppleAppEmbed && (
|
{!props.isAppleAppEmbed && (
|
||||||
@ -306,6 +362,16 @@ export function Article(props: ArticleProps): JSX.Element {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SpanBox>
|
</SpanBox>
|
||||||
|
{linkHoverData && (
|
||||||
|
<>
|
||||||
|
<LinkHoverBar
|
||||||
|
anchorCoordinates={linkHoverData.pageCoordinate}
|
||||||
|
handleButtonClick={() => {
|
||||||
|
console.log('saved link hover: ', linkHoverData)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user