website refactor
This commit is contained in:
64
apps/website/ui/InfoFlyout.tsx
Normal file
64
apps/website/ui/InfoFlyout.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React, { ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Box } from './primitives/Box';
|
||||
import { Surface } from './primitives/Surface';
|
||||
import { Text } from './Text';
|
||||
import { Icon } from './Icon';
|
||||
import { IconButton } from './IconButton';
|
||||
import { HelpCircle, X } from 'lucide-react';
|
||||
import { Heading } from './Heading';
|
||||
|
||||
export interface InfoFlyoutProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
title: string;
|
||||
children: ReactNode;
|
||||
anchorRef: React.RefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const InfoFlyout = ({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutProps) => {
|
||||
const [position, setPosition] = useState({ top: 0, left: 0 });
|
||||
const flyoutRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && anchorRef.current) {
|
||||
const rect = anchorRef.current.getBoundingClientRect();
|
||||
const flyoutWidth = 380;
|
||||
const padding = 16;
|
||||
|
||||
let left = rect.right + 12;
|
||||
let top = rect.top;
|
||||
|
||||
if (left + flyoutWidth > window.innerWidth - padding) {
|
||||
left = rect.left - flyoutWidth - 12;
|
||||
}
|
||||
|
||||
setPosition({ top, left });
|
||||
}
|
||||
}, [isOpen, anchorRef]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return createPortal(
|
||||
<Box
|
||||
ref={flyoutRef as any}
|
||||
position="fixed"
|
||||
zIndex={100}
|
||||
style={{ top: position.top, left: position.left, width: '24rem' }}
|
||||
>
|
||||
<Surface variant="muted" rounded="xl" shadow="xl" style={{ border: '1px solid var(--ui-color-border-default)', overflow: 'hidden' }}>
|
||||
<Box display="flex" alignItems="center" justifyContent="between" padding={4} bg="var(--ui-color-bg-surface-muted)" style={{ borderBottom: '1px solid var(--ui-color-border-default)' }}>
|
||||
<Box display="flex" alignItems="center" gap={2}>
|
||||
<Icon icon={HelpCircle} size={4} intent="primary" />
|
||||
<Heading level={6}>{title}</Heading>
|
||||
</Box>
|
||||
<IconButton icon={X} size="sm" variant="ghost" onClick={onClose} title="Close" />
|
||||
</Box>
|
||||
<Box padding={4} style={{ maxHeight: '20rem', overflowY: 'auto' }}>
|
||||
{children}
|
||||
</Box>
|
||||
</Surface>
|
||||
</Box>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user