Skip to content

Commit

Permalink
fixed embed link toolbars overlapping each other in sibling blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
iskaktoltay committed Nov 29, 2024
1 parent 3c52dde commit 11e27b7
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 77 deletions.
136 changes: 82 additions & 54 deletions frontend/apps/desktop/src/editor/embed-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ import {
Separator,
SizableText,
toast,
Tooltip,
usePopoverState,
XStack,
YGroup,
YStack,
} from '@shm/ui'
import {ChevronRight} from '@tamagui/lucide-icons'
import {Fragment} from '@tiptap/pm/model'
import {useCallback, useEffect, useState} from 'react'
import {ErrorBoundary} from 'react-error-boundary'
import {GestureResponderEvent} from 'react-native'
import {Block, BlockNoteEditor, HMBlockSchema} from '.'
import {createReactBlockSpec} from './blocknote/react'
import {useEmbedToolbarContext} from './embed-toolbar-context'
import {HypermediaLinkSwitchToolbar} from './hm-link-switch-toolbar'
import {LauncherItem, SwitcherItem} from './launcher-item'
import {MediaContainer} from './media-container'
Expand Down Expand Up @@ -188,6 +190,7 @@ const display = ({
}: DisplayComponentProps) => {
const unpackedId = unpackHmId(block.props.url)
const [showControl, setShowControl] = useState(false)
const {activeId, setActiveId} = useEmbedToolbarContext()

return (
<MediaContainer
Expand All @@ -197,15 +200,30 @@ const display = ({
selected={selected}
setSelected={setSelected}
assign={assign}
onHoverIn={() => setShowControl(true)}
onHoverOut={() => setShowControl(false)}
styleProps={{
pointerEvents: activeId && activeId !== block.id ? 'none' : '',
}}
onHoverIn={() => {
if (!activeId) {
setShowControl(true)
setActiveId(block.id)
}
}}
onHoverOut={() => {
setShowControl(false)
if (activeId && activeId === block.id) {
setActiveId(null)
}
}}
>
<EmbedControl
editor={editor}
block={block}
unpackedId={unpackedId}
assign={assign}
showControl={showControl}
activeId={activeId}
setActiveId={setActiveId}
/>
{block.props.url && (
<ErrorBoundary FallbackComponent={EmbedError}>
Expand Down Expand Up @@ -242,12 +260,16 @@ function EmbedControl({
unpackedId,
assign,
showControl,
activeId,
setActiveId,
}: {
editor: BlockNoteEditor<HMBlockSchema>
block: Block<HMBlockSchema>
unpackedId: UnpackedHypermediaId | null
assign: any
showControl: boolean
activeId: string | null
setActiveId: (id: string | null) => void
}) {
const [url, setUrl] = useState<string>(block.props.url || '')
const openUrl = useOpenUrl()
Expand All @@ -262,6 +284,13 @@ function EmbedControl({
const hasBlockRef = unpackedId?.blockRef
const isLatestVersion = isEmbedUrlLatest(block.props.url)

const setHover = (hovered: boolean) => {
if (hovered && !activeId) setActiveId(block.id)
else if (!hovered && activeId === block.id) {
setActiveId(null)
}
}

function isEmbedUrlLatest(url: string): boolean {
const queryParams = parseCustomURL(url)

Expand Down Expand Up @@ -317,52 +346,6 @@ function EmbedControl({
function EmbedLinkComponents() {
return (
<YStack gap="$0.25">
{/* {hasBlockRef ? (
<Tooltip
content={
isBlockExpanded
? `Embed only the block's content`
: `Embed the block and its children`
}
>
<Button
{...expandButtonHover}
size="$2"
icon={
isBlockExpanded
? expandButtonHover.hover
? ChevronRight
: ChevronDown
: expandButtonHover.hover
? ChevronDown
: ChevronRight
}
backgroundColor="$backgroundStrong"
onPress={(e: GestureResponderEvent) => {
e.stopPropagation()
let url = packHmId({
...unpackedId,
blockRange: {expanded: !isBlockExpanded},
})
assign({
props: {
url,
},
})
}}
>
{isBlockExpanded
? expandButtonHover.hover
? 'Collapse'
: 'Expand'
: expandButtonHover.hover
? 'Expand'
: 'Collapse'}
</Button>
</Tooltip>
) : null} */}

{allowViewSwitcher && (
<Popover
{...popoverViewState}
Expand Down Expand Up @@ -520,19 +503,18 @@ function EmbedControl({
}

return (
<XStack
<YStack
position="absolute"
x={0}
y={0}
zIndex="$zIndex.4"
width="100%"
height="100%"
ai="flex-start"
ai="flex-end"
jc="flex-end"
opacity={showControl ? 1 : 0}
// opacity={popoverState.open ? 1 : 0}
padding="$2"
gap="$2"
gap="$0.5"
>
<HypermediaLinkSwitchToolbar
url={url}
Expand Down Expand Up @@ -560,8 +542,54 @@ function EmbedControl({
formComponents={EmbedLinkComponents}
type="embed"
id={block.id}
setHovered={setHover}
/>
</XStack>
{hasBlockRef ? (
<Tooltip
content={
isBlockExpanded
? `Embed only the block's content`
: `Embed the block and its children`
}
>
<Button
{...expandButtonHover}
size="$2"
icon={
isBlockExpanded
? expandButtonHover.hover
? ChevronRight
: ChevronDown
: expandButtonHover.hover
? ChevronDown
: ChevronRight
}
backgroundColor="$backgroundStrong"
onPress={(e: GestureResponderEvent) => {
e.stopPropagation()
let url = packHmId({
...unpackedId,
blockRange: {expanded: !isBlockExpanded},
})

assign({
props: {
url,
},
})
}}
>
{isBlockExpanded
? expandButtonHover.hover
? 'Collapse'
: 'Expand'
: expandButtonHover.hover
? 'Expand'
: 'Collapse'}
</Button>
</Tooltip>
) : null}
</YStack>
)
}

Expand Down
27 changes: 27 additions & 0 deletions frontend/apps/desktop/src/editor/embed-toolbar-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, {createContext, useContext, useState} from 'react'

// Context to keep track of which embed link toolbar is showing
const EmbedToolbarContext = createContext<{
activeId: string | null
setActiveId: (id: string | null) => void
} | null>(null)

export const EmbedToolbarProvider: React.FC<{children: React.ReactNode}> = ({
children,
}) => {
const [activeId, setActiveId] = useState<string | null>(null)

return (
<EmbedToolbarContext.Provider value={{activeId, setActiveId}}>
{children}
</EmbedToolbarContext.Provider>
)
}

export const useEmbedToolbarContext = () => {
const context = useContext(EmbedToolbarContext)
if (!context) {
throw new Error('useToolbarContext must be used within a ToolbarProvider')
}
return context
}
15 changes: 1 addition & 14 deletions frontend/apps/desktop/src/editor/hm-link-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ export type HypermediaLinkFormProps = {
editLink: (url: string, text: string) => void
openUrl: (url?: string | undefined, newWindow?: boolean | undefined) => void
isSeedDocument?: boolean
isFocused: boolean
setIsFocused: (focused: boolean) => void
hasName?: boolean
hasSearch?: boolean
}
Expand All @@ -45,18 +43,7 @@ export function HypermediaLinkForm(props: HypermediaLinkFormProps) {
}

return (
<YStack
gap="$1.5"
zIndex="$zIndex.5"
onMouseEnter={(e) => {
e.stopPropagation()
if (!props.isFocused) props.setIsFocused(true)
}}
onMouseLeave={(e) => {
e.stopPropagation()
props.setIsFocused(false)
}}
>
<YStack gap="$1.5" zIndex="$zIndex.5">
{props.hasName && (
<XStack
paddingHorizontal="$2"
Expand Down
23 changes: 14 additions & 9 deletions frontend/apps/desktop/src/editor/hm-link-switch-toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,30 @@ export function HypermediaLinkSwitchToolbar(
stopEditing: boolean
formComponents: () => React.JSX.Element
type: string
setHovered?: (hovered: boolean) => void
},
) {
const [isEditing, setIsEditing] = useState(false)
const [isFocused, setIsFocused] = useState(isEditing)
const unpackedRef = useMemo(() => unpackHmId(props.url), [props.url])

useEffect(() => {
if (props.stopEditing && isEditing) {
if (props.type === 'embed') {
if (!isFocused) setIsEditing(false)
} else setIsEditing(false)
setIsEditing(false)
}
}, [props.stopEditing, isEditing, isFocused])
}, [props.stopEditing, isEditing])

return (
<XStack zIndex="$zIndex.4">
<XStack
zIndex="$zIndex.4"
{...(props.setHovered && {
onMouseEnter: () => {
props.setHovered?.(true)
},
onMouseLeave: () => {
props.setHovered?.(false)
},
})}
>
{isEditing ? (
// Render the form when in editing mode
<YStack
Expand Down Expand Up @@ -75,8 +83,6 @@ export function HypermediaLinkSwitchToolbar(
hasName={props.type !== 'embed'}
hasSearch={props.type !== 'link'}
isSeedDocument={unpackedRef ? true : false}
isFocused={isFocused}
setIsFocused={setIsFocused}
/>
</YStack>
) : (
Expand All @@ -98,7 +104,6 @@ export function HypermediaLinkSwitchToolbar(
tooltipText={`Edit ${props.type}`}
icon={Pencil}
onPress={() => {
setIsFocused(true)
setIsEditing(true)
}}
active={false}
Expand Down

0 comments on commit 11e27b7

Please sign in to comment.