Files
limitless-ui/src/components/Tooltip.tsx
Claude 8b9e577694 refactor(AppShell): pure renderer, drop browser fetch
The browser-fetching variant ran into the cross-origin / cert-trust
wall that came up the moment a real user loaded the page. Move the
network call out of the library: <AppShell> now takes a pre-resolved
ShellConfig as a required prop. Apps fetch from gsc-shell-api in
their RSC layout (server-to-server, no CORS, no cert dance) and pass
the result down.

Public surface:
  AppShell, useShell, ShellConfig + sub-types

Removed:
  ShellProvider (network logic gone), all fetcher props
  (apiUrl, getToken, appKey, initialConfig, revalidateMs).

useShell() now returns ShellConfig directly (was ShellContextValue
with loading/error/refresh — no longer relevant).

Apps drive revalidation by re-rendering; chrome stays request-fresh
without any client-side polling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:18:07 +02:00

70 lines
1.9 KiB
TypeScript

import React, { useState } from 'react';
import { useFloating, offset, shift, flip, arrow, Placement, Middleware } from '@floating-ui/react';
export type TooltipProps = {
content: React.ReactNode;
placement?: Placement;
children: React.ReactElement<any>;
className?: string;
};
/**
* Minimal tooltip using floating-ui.
*/
export function Tooltip({ content, placement = 'top', children, className = '' }: TooltipProps) {
const [open, setOpen] = useState(false);
const [arrowEl, setArrowEl] = useState<HTMLElement | null>(null);
const middleware: Middleware[] = [offset(8), flip(), shift()];
if (arrowEl) middleware.push(arrow({ element: arrowEl }));
const { x, y, refs, strategy, middlewareData, placement: finalPlacement } = useFloating({
open,
onOpenChange: setOpen,
placement,
middleware
});
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
}[finalPlacement.split('-')[0]] as string;
return (
<>
{React.cloneElement(children, {
ref: refs.setReference,
onMouseEnter: () => setOpen(true),
onMouseLeave: () => setOpen(false),
onFocus: () => setOpen(true),
onBlur: () => setOpen(false)
})}
{open ? (
<div
ref={refs.setFloating}
className={['tooltip bs-tooltip-auto show', className].filter(Boolean).join(' ')}
role="tooltip"
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0
}}
>
<div className="tooltip-inner">{content}</div>
<div
ref={setArrowEl as any}
className="tooltip-arrow"
style={{
left: middlewareData.arrow?.x,
top: middlewareData.arrow?.y,
[staticSide]: '-4px'
}}
/>
</div>
) : null}
</>
);
}