Skip to content

Commit

Permalink
Twoslash: Fix popups focus outline
Browse files Browse the repository at this point in the history
  • Loading branch information
fuma-nama committed Dec 9, 2024
1 parent 7f53da4 commit 9585561
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 27 deletions.
6 changes: 6 additions & 0 deletions .changeset/pretty-forks-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'fumadocs-twoslash': patch
'fumadocs-ui': patch
---

Fix Twoslash popups focus outline
55 changes: 29 additions & 26 deletions packages/twoslash/src/ui/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
useContext,
createContext,
useMemo,
type ReactNode,
type ComponentRef,
type ComponentPropsWithoutRef,
} from 'react';
import { Popover, PopoverContent, PopoverTrigger } from './popover';

Expand All @@ -23,41 +26,38 @@ function Popup({
children,
}: {
delay?: number;
children: React.ReactNode;
children: ReactNode;
}) {
const [open, setOpen] = useState(false);
const openTimeoutRef = useRef<number>(undefined);
const closeTimeoutRef = useRef<number>(undefined);

const handleOpen = (e: React.PointerEvent): void => {
if (e.pointerType === 'touch') return;
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);

openTimeoutRef.current = window.setTimeout(() => {
setOpen(true);
}, delay);
};

const handleClose = (e: React.PointerEvent): void => {
if (e.pointerType === 'touch') return;
if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current);

closeTimeoutRef.current = window.setTimeout(() => {
setOpen(false);
}, delay);
};

return (
<Popover open={open} onOpenChange={setOpen}>
<PopupContext.Provider
value={useMemo(
() => ({
open,
setOpen,
handleOpen,
handleClose,
handleOpen(e) {
if (e.pointerType === 'touch') return;
if (closeTimeoutRef.current)
clearTimeout(closeTimeoutRef.current);

openTimeoutRef.current = window.setTimeout(() => {
setOpen(true);
}, delay);
},
handleClose(e) {
if (e.pointerType === 'touch') return;
if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current);

closeTimeoutRef.current = window.setTimeout(() => {
setOpen(false);
}, delay);
},
}),
[handleClose, handleOpen, open],
[delay, open],
)}
>
{children}
Expand All @@ -67,8 +67,8 @@ function Popup({
}

const PopupTrigger = forwardRef<
React.ElementRef<typeof PopoverTrigger>,
React.ComponentPropsWithoutRef<typeof PopoverTrigger>
ComponentRef<typeof PopoverTrigger>,
ComponentPropsWithoutRef<typeof PopoverTrigger>
>((props, ref) => {
const ctx = useContext(PopupContext);
if (!ctx) throw new Error('Missing Popup Context');
Expand All @@ -86,8 +86,8 @@ const PopupTrigger = forwardRef<
PopupTrigger.displayName = 'PopupTrigger';

const PopupContent = forwardRef<
React.ComponentRef<typeof PopoverContent>,
React.ComponentPropsWithoutRef<typeof PopoverContent>
ComponentRef<typeof PopoverContent>,
ComponentPropsWithoutRef<typeof PopoverContent>
>((props, ref) => {
const ctx = useContext(PopupContext);
if (!ctx) throw new Error('Missing Popup Context');
Expand All @@ -97,6 +97,9 @@ const PopupContent = forwardRef<
ref={ref}
onPointerEnter={ctx.handleOpen}
onPointerLeave={ctx.handleClose}
onOpenAutoFocus={(e) => {
e.preventDefault();
}}
onCloseAutoFocus={(e) => {
e.preventDefault();
}}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/codeblock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const CodeBlock = forwardRef<HTMLElement, CodeBlockProps>(
<ScrollArea ref={areaRef} dir="ltr">
<ScrollViewport
{...viewportProps}
className={cn('max-h-[400px]', viewportProps?.className)}
className={cn('max-h-[600px]', viewportProps?.className)}
>
{props.children}
</ScrollViewport>
Expand Down

0 comments on commit 9585561

Please sign in to comment.