Start organizational migration

This commit is contained in:
adilallo
2026-02-05 18:21:56 -07:00
parent 69074b23f3
commit db3c0274f6
161 changed files with 145 additions and 145 deletions
@@ -0,0 +1,52 @@
"use client";
import { memo, useState } from "react";
import { TooltipView } from "./Tooltip.view";
import type { TooltipProps } from "./Tooltip.types";
import { normalizeTooltipPosition } from "../../../../lib/propNormalization";
const TooltipContainer = memo<TooltipProps>(
({ children, text, position: positionProp = "top", className = "", disabled = false }) => {
// Normalize props to handle both PascalCase (Figma) and lowercase (codebase)
const position = normalizeTooltipPosition(positionProp);
const [isVisible, setIsVisible] = useState(false);
if (disabled) {
return <>{children}</>;
}
const tooltipClasses = `absolute z-50 bg-[var(--color-surface-default-primary)] px-[var(--space-300)] py-[var(--space-200)] rounded-[var(--radius-300,12px)] shadow-[0px_0px_48px_0px_rgba(0,0,0,0.1)] flex items-center whitespace-nowrap ${
position === "top" ? "bottom-full mb-[7px]" : "top-full mt-[7px]"
} left-1/2 -translate-x-1/2 ${isVisible ? "opacity-100 visible" : "opacity-0 invisible pointer-events-none"} transition-all duration-200`;
// Pointer positioning: 10px tall, 7px sticks out, 3px inside tooltip
// For bottom tooltip: pointer at top, pointing up, 7px above tooltip
// For top tooltip: pointer at bottom, pointing down, 7px below tooltip
const pointerClasses = `absolute ${
position === "top" ? "bottom-[-7px]" : "top-[-7px]"
} left-1/2 -translate-x-1/2`;
return (
<div
className={`relative inline-block ${className}`}
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
onFocus={() => setIsVisible(true)}
onBlur={() => setIsVisible(false)}
>
{children}
<TooltipView
text={text}
position={position}
className=""
tooltipClasses={tooltipClasses}
pointerClasses={pointerClasses}
/>
</div>
);
},
);
TooltipContainer.displayName = "Tooltip";
export default TooltipContainer;
@@ -0,0 +1,21 @@
export type TooltipPositionValue = "top" | "bottom" | "Top" | "Bottom";
export interface TooltipProps {
children: React.ReactNode;
text: string;
/**
* Tooltip position. Accepts both lowercase and PascalCase (case-insensitive).
* Figma uses PascalCase, codebase uses lowercase - both are supported.
*/
position?: TooltipPositionValue;
className?: string;
disabled?: boolean;
}
export interface TooltipViewProps {
text: string;
position: "top" | "bottom";
className: string;
tooltipClasses: string;
pointerClasses: string;
}
@@ -0,0 +1,45 @@
import type { TooltipViewProps } from "./Tooltip.types";
export function TooltipView({
text,
position,
className: _className,
tooltipClasses,
pointerClasses,
}: TooltipViewProps) {
// Pointer is 10px tall with 7px sticking out
// Icon_Pointer.svg is 14x8, scale to 10px height = 17.5px width
const pointerWidth = 17.5;
const pointerHeight = 10;
const pointerRotation = position === "top" ? "rotate-180" : "rotate-0";
return (
<div
className={tooltipClasses}
role="tooltip"
aria-live="polite"
id={`tooltip-${text.replace(/\s+/g, "-").toLowerCase()}`}
>
<p className="font-inter text-[var(--sizing-350,14px)] leading-[16px] font-medium tracking-[0%] text-[var(--color-content-default-primary)] relative shrink-0">
{text}
</p>
<div
className={pointerClasses}
style={{ width: `${pointerWidth}px`, height: `${pointerHeight}px` }}
>
<svg
className={`${pointerRotation} w-full h-full`}
viewBox="0 0 14 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
d="M6.92822 0L13.8564 7.5H1.95503e-05L6.92822 0Z"
fill="var(--color-surface-default-primary)"
/>
</svg>
</div>
</div>
);
}
+2
View File
@@ -0,0 +1,2 @@
export { default } from "./Tooltip.container";
export type { TooltipProps } from "./Tooltip.types";