fix: tour init on All tab + 11" Latex card; fix modal title truncation
- Tour now switches to the All tab and clears search on start, ensuring the 11" Latex product is always visible and the exit overlay works - data-tour="first-card" now targets the 11" Latex item by name instead of whichever card happens to be first in the filtered list - Modal header title now truncates with ellipsis so the X close button is never pushed off screen by a long product name Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6fea1f2be1
commit
c6d5a0265f
@ -151,9 +151,9 @@ export default function ColorPicker({ product, maxColors, onClose, editingEntry
|
|||||||
<div className="modal is-active" onClick={onClose}>
|
<div className="modal is-active" onClick={onClose}>
|
||||||
<div className="modal-card" style={{ maxWidth: '780px', width: '95vw' }} onClick={(e) => e.stopPropagation()}>
|
<div className="modal-card" style={{ maxWidth: '780px', width: '95vw' }} onClick={(e) => e.stopPropagation()}>
|
||||||
|
|
||||||
<header className="modal-card-head" style={{ background: '#11b3be' }}>
|
<header className="modal-card-head" style={{ background: '#11b3be', gap: '0.75rem' }}>
|
||||||
<p className="modal-card-title has-text-white">{product.name}</p>
|
<p className="modal-card-title has-text-white" style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{product.name}</p>
|
||||||
<button className="delete" aria-label="close" onClick={onClose} />
|
<button className="delete" aria-label="close" onClick={onClose} style={{ flexShrink: 0 }} />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section className="modal-card-body" style={{ maxHeight: '70vh', overflowY: 'auto', padding: '1.25rem 1.5rem' }}>
|
<section className="modal-card-body" style={{ maxHeight: '70vh', overflowY: 'auto', padding: '1.25rem 1.5rem' }}>
|
||||||
|
|||||||
@ -48,6 +48,12 @@ export default function FeaturedProducts() {
|
|||||||
setShowTour(true)
|
setShowTour(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tourInit = () => {
|
||||||
|
setCategory('all')
|
||||||
|
setSearch('')
|
||||||
|
setSearchOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
const endTour = () => {
|
const endTour = () => {
|
||||||
setShowTour(false)
|
setShowTour(false)
|
||||||
// Close any customization modal that may have been opened during the tour
|
// Close any customization modal that may have been opened during the tour
|
||||||
@ -224,7 +230,7 @@ export default function FeaturedProducts() {
|
|||||||
|
|
||||||
{/* Welcome modal + guided tour */}
|
{/* Welcome modal + guided tour */}
|
||||||
{showWelcome && <WelcomeModal onTour={startTour} onDismiss={dismissWelcome} />}
|
{showWelcome && <WelcomeModal onTour={startTour} onDismiss={dismissWelcome} />}
|
||||||
{showTour && <GuidedTour onDone={endTour} />}
|
{showTour && <GuidedTour onDone={endTour} onStart={tourInit} />}
|
||||||
|
|
||||||
{/* Product grid */}
|
{/* Product grid */}
|
||||||
{loading ? (
|
{loading ? (
|
||||||
@ -244,11 +250,11 @@ export default function FeaturedProducts() {
|
|||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="columns is-multiline is-centered">
|
<div className="columns is-multiline is-centered">
|
||||||
{filtered.map((item, index) => (
|
{filtered.map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="column is-3-desktop is-6-tablet is-12-mobile"
|
className="column is-3-desktop is-6-tablet is-12-mobile"
|
||||||
{...(index === 0 ? { 'data-tour': 'first-card' } : {})}
|
{...(/\b11["''″]|\b11[- ]?inch/i.test(item.name) && /latex/i.test(item.name) ? { 'data-tour': 'first-card' } : {})}
|
||||||
>
|
>
|
||||||
<ProductCard item={item} />
|
<ProductCard item={item} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -57,10 +57,11 @@ const PAD = 10 // px padding around spotlight
|
|||||||
const TIP_WIDTH = 300 // tooltip width in px
|
const TIP_WIDTH = 300 // tooltip width in px
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onDone: () => void
|
onDone: () => void
|
||||||
|
onStart?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function GuidedTour({ onDone }: Props) {
|
export default function GuidedTour({ onDone, onStart }: Props) {
|
||||||
const [step, setStep] = useState(0)
|
const [step, setStep] = useState(0)
|
||||||
const [targetRect, setTargetRect] = useState<DOMRect | null>(null)
|
const [targetRect, setTargetRect] = useState<DOMRect | null>(null)
|
||||||
|
|
||||||
@ -72,6 +73,12 @@ export default function GuidedTour({ onDone }: Props) {
|
|||||||
if (el) setTargetRect(el.getBoundingClientRect())
|
if (el) setTargetRect(el.getBoundingClientRect())
|
||||||
}, [current.target])
|
}, [current.target])
|
||||||
|
|
||||||
|
// Switch to All tab and pick the 11" Latex card as the tour example on mount
|
||||||
|
useEffect(() => {
|
||||||
|
onStart?.()
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [])
|
||||||
|
|
||||||
// On step change: fire onEnter, poll until target appears, then scroll + measure.
|
// On step change: fire onEnter, poll until target appears, then scroll + measure.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTargetRect(null) // clear stale rect immediately
|
setTargetRect(null) // clear stale rect immediately
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user