Add customer and business user-product flows across dashboards.

Ship my-products / customer-products UI with gallery uploads, status controls, module gating, and related shared UI polish.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-10 00:23:03 +03:30
co-authored by Cursor
parent c5bdaad16b
commit 1271d96539
96 changed files with 10532 additions and 345 deletions
+64 -5
View File
@@ -1,4 +1,5 @@
import type { ReactElement } from 'react'
import { useEffect, useRef, useState, type ReactElement } from 'react'
import { createPortal } from 'react-dom'
import styles from './Tooltip.module.css'
interface TooltipProps {
@@ -7,12 +8,70 @@ interface TooltipProps {
}
export function Tooltip({ label, children }: TooltipProps) {
const wrapRef = useRef<HTMLSpanElement>(null)
const [visible, setVisible] = useState(false)
const [coords, setCoords] = useState({ top: 0, left: 0 })
function updatePosition() {
const el = wrapRef.current
if (!el) return
const rect = el.getBoundingClientRect()
setCoords({
top: rect.top - 8,
left: rect.left + rect.width / 2,
})
}
function show() {
updatePosition()
setVisible(true)
}
function hide() {
setVisible(false)
}
useEffect(() => {
if (!visible) return
function onReposition() {
updatePosition()
}
window.addEventListener('scroll', onReposition, true)
window.addEventListener('resize', onReposition)
return () => {
window.removeEventListener('scroll', onReposition, true)
window.removeEventListener('resize', onReposition)
}
}, [visible])
return (
<span className={styles.wrap}>
<span
ref={wrapRef}
className={styles.wrap}
onMouseEnter={show}
onMouseLeave={hide}
onFocusCapture={show}
onBlurCapture={(e) => {
if (!wrapRef.current?.contains(e.relatedTarget as Node | null)) {
hide()
}
}}
>
{children}
<span className={styles.tip} role="tooltip">
{label}
</span>
{visible
? createPortal(
<span
className={`${styles.tip} ${styles.tipVisible}`}
role="tooltip"
style={{ top: coords.top, left: coords.left }}
>
{label}
</span>,
document.body,
)
: null}
</span>
)
}